summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2022-01-10 20:28:00 -0600
committerMatt A. Tobin <email@mattatobin.com>2022-01-10 20:28:00 -0600
commit9ff8e15c6effab231e3fe4e9d94e6d0f5bbeecd5 (patch)
tree77f2d9bd2a77feed6f133ef68d3eacc632e95c3d /editor
parentedcfffe3dbf41ae18451fb0d47c5e41d2e67fede (diff)
downloadaura-central-9ff8e15c6effab231e3fe4e9d94e6d0f5bbeecd5.tar.gz
Issue %3005 - Move editor to system/
Diffstat (limited to 'editor')
-rw-r--r--editor/AsyncSpellCheckTestHelper.jsm86
-rw-r--r--editor/composer/crashtests/351236-1.html37
-rw-r--r--editor/composer/crashtests/407062-1.html20
-rw-r--r--editor/composer/crashtests/419563-1.xhtml20
-rw-r--r--editor/composer/crashtests/428844-1-inner.xhtml4
-rw-r--r--editor/composer/crashtests/428844-1.html17
-rw-r--r--editor/composer/crashtests/461049-1.html25
-rw-r--r--editor/composer/crashtests/crashtests.list6
-rw-r--r--editor/composer/crashtests/removing-editable-xslt-inner.xhtml4
-rw-r--r--editor/composer/crashtests/removing-editable-xslt.html17
-rw-r--r--editor/composer/moz.build52
-rw-r--r--editor/composer/nsComposeTxtSrvFilter.cpp62
-rw-r--r--editor/composer/nsComposeTxtSrvFilter.h55
-rw-r--r--editor/composer/nsComposerCommands.cpp1525
-rw-r--r--editor/composer/nsComposerCommands.h281
-rw-r--r--editor/composer/nsComposerCommandsUpdater.cpp381
-rw-r--r--editor/composer/nsComposerCommandsUpdater.h102
-rw-r--r--editor/composer/nsComposerController.cpp140
-rw-r--r--editor/composer/nsComposerController.h34
-rw-r--r--editor/composer/nsComposerDocumentCommands.cpp480
-rw-r--r--editor/composer/nsComposerRegistration.cpp226
-rw-r--r--editor/composer/nsEditingSession.cpp1391
-rw-r--r--editor/composer/nsEditingSession.h148
-rw-r--r--editor/composer/nsEditorSpellCheck.cpp934
-rw-r--r--editor/composer/nsEditorSpellCheck.h85
-rw-r--r--editor/composer/nsIEditingSession.idl104
-rw-r--r--editor/composer/res/EditorOverride.css323
-rw-r--r--editor/composer/res/grabber.gifbin858 -> 0 bytes
-rw-r--r--editor/composer/res/table-add-column-after-active.gifbin58 -> 0 bytes
-rw-r--r--editor/composer/res/table-add-column-after-hover.gifbin826 -> 0 bytes
-rw-r--r--editor/composer/res/table-add-column-after.gifbin826 -> 0 bytes
-rw-r--r--editor/composer/res/table-add-column-before-active.gifbin57 -> 0 bytes
-rw-r--r--editor/composer/res/table-add-column-before-hover.gifbin825 -> 0 bytes
-rw-r--r--editor/composer/res/table-add-column-before.gifbin825 -> 0 bytes
-rw-r--r--editor/composer/res/table-add-row-after-active.gifbin57 -> 0 bytes
-rw-r--r--editor/composer/res/table-add-row-after-hover.gifbin826 -> 0 bytes
-rw-r--r--editor/composer/res/table-add-row-after.gifbin826 -> 0 bytes
-rw-r--r--editor/composer/res/table-add-row-before-active.gifbin57 -> 0 bytes
-rw-r--r--editor/composer/res/table-add-row-before-hover.gifbin825 -> 0 bytes
-rw-r--r--editor/composer/res/table-add-row-before.gifbin825 -> 0 bytes
-rw-r--r--editor/composer/res/table-remove-column-active.gifbin835 -> 0 bytes
-rw-r--r--editor/composer/res/table-remove-column-hover.gifbin841 -> 0 bytes
-rw-r--r--editor/composer/res/table-remove-column.gifbin841 -> 0 bytes
-rw-r--r--editor/composer/res/table-remove-row-active.gifbin835 -> 0 bytes
-rw-r--r--editor/composer/res/table-remove-row-hover.gifbin841 -> 0 bytes
-rw-r--r--editor/composer/res/table-remove-row.gifbin841 -> 0 bytes
-rw-r--r--editor/composer/test/bug1200533_subframe.html14
-rw-r--r--editor/composer/test/bug1204147_subframe.html11
-rw-r--r--editor/composer/test/bug1204147_subframe2.html9
-rw-r--r--editor/composer/test/bug678842_subframe.html8
-rw-r--r--editor/composer/test/bug717433_subframe.html8
-rw-r--r--editor/composer/test/chrome.ini5
-rw-r--r--editor/composer/test/de-DE/de_DE.aff2
-rw-r--r--editor/composer/test/de-DE/de_DE.dic6
-rw-r--r--editor/composer/test/en-AU/en_AU.aff2
-rw-r--r--editor/composer/test/en-AU/en_AU.dic4
-rw-r--r--editor/composer/test/en-GB/en_GB.aff2
-rw-r--r--editor/composer/test/en-GB/en_GB.dic4
-rw-r--r--editor/composer/test/mochitest.ini40
-rw-r--r--editor/composer/test/test_async_UpdateCurrentDictionary.html75
-rw-r--r--editor/composer/test/test_bug1200533.html139
-rw-r--r--editor/composer/test/test_bug1204147.html112
-rw-r--r--editor/composer/test/test_bug1205983.html137
-rw-r--r--editor/composer/test/test_bug1209414.html150
-rw-r--r--editor/composer/test/test_bug1219928.html76
-rw-r--r--editor/composer/test/test_bug1266815.html82
-rw-r--r--editor/composer/test/test_bug338427.html61
-rw-r--r--editor/composer/test/test_bug348497.html36
-rw-r--r--editor/composer/test/test_bug384147.html204
-rw-r--r--editor/composer/test/test_bug389350.html33
-rw-r--r--editor/composer/test/test_bug434998.xul109
-rw-r--r--editor/composer/test/test_bug519928.html123
-rw-r--r--editor/composer/test/test_bug678842.html105
-rw-r--r--editor/composer/test/test_bug697981.html133
-rw-r--r--editor/composer/test/test_bug717433.html107
-rw-r--r--editor/composer/test/test_bug738440.html37
-rw-r--r--editor/libeditor/CSSEditUtils.cpp1441
-rw-r--r--editor/libeditor/CSSEditUtils.h480
-rw-r--r--editor/libeditor/ChangeAttributeTransaction.cpp98
-rw-r--r--editor/libeditor/ChangeAttributeTransaction.h72
-rw-r--r--editor/libeditor/ChangeStyleTransaction.cpp287
-rw-r--r--editor/libeditor/ChangeStyleTransaction.h123
-rw-r--r--editor/libeditor/CompositionTransaction.cpp344
-rw-r--r--editor/libeditor/CompositionTransaction.h104
-rw-r--r--editor/libeditor/CreateElementTransaction.cpp154
-rw-r--r--editor/libeditor/CreateElementTransaction.h80
-rw-r--r--editor/libeditor/DeleteNodeTransaction.cpp124
-rw-r--r--editor/libeditor/DeleteNodeTransaction.h66
-rw-r--r--editor/libeditor/DeleteRangeTransaction.cpp256
-rw-r--r--editor/libeditor/DeleteRangeTransaction.h78
-rw-r--r--editor/libeditor/DeleteTextTransaction.cpp106
-rw-r--r--editor/libeditor/DeleteTextTransaction.h76
-rw-r--r--editor/libeditor/EditActionListener.h17
-rw-r--r--editor/libeditor/EditAggregateTransaction.cpp145
-rw-r--r--editor/libeditor/EditAggregateTransaction.h58
-rw-r--r--editor/libeditor/EditTransactionBase.cpp55
-rw-r--r--editor/libeditor/EditTransactionBase.h44
-rw-r--r--editor/libeditor/EditorBase.cpp5359
-rw-r--r--editor/libeditor/EditorBase.h1126
-rw-r--r--editor/libeditor/EditorCommands.cpp1169
-rw-r--r--editor/libeditor/EditorCommands.h106
-rw-r--r--editor/libeditor/EditorController.cpp146
-rw-r--r--editor/libeditor/EditorController.h37
-rw-r--r--editor/libeditor/EditorEventListener.cpp1279
-rw-r--r--editor/libeditor/EditorEventListener.h116
-rw-r--r--editor/libeditor/EditorUtils.cpp227
-rw-r--r--editor/libeditor/EditorUtils.h428
-rw-r--r--editor/libeditor/EditorUtils.js34
-rw-r--r--editor/libeditor/EditorUtils.manifest2
-rw-r--r--editor/libeditor/HTMLAbsPositionEditor.cpp682
-rw-r--r--editor/libeditor/HTMLAnonymousNodeEditor.cpp551
-rw-r--r--editor/libeditor/HTMLEditRules.cpp8909
-rw-r--r--editor/libeditor/HTMLEditRules.h427
-rw-r--r--editor/libeditor/HTMLEditUtils.cpp838
-rw-r--r--editor/libeditor/HTMLEditUtils.h73
-rw-r--r--editor/libeditor/HTMLEditor.cpp5255
-rw-r--r--editor/libeditor/HTMLEditor.h1111
-rw-r--r--editor/libeditor/HTMLEditorDataTransfer.cpp2414
-rw-r--r--editor/libeditor/HTMLEditorEventListener.cpp235
-rw-r--r--editor/libeditor/HTMLEditorEventListener.h43
-rw-r--r--editor/libeditor/HTMLEditorObjectResizer.cpp1054
-rw-r--r--editor/libeditor/HTMLEditorObjectResizerUtils.h82
-rw-r--r--editor/libeditor/HTMLInlineTableEditor.cpp283
-rw-r--r--editor/libeditor/HTMLStyleEditor.cpp1756
-rw-r--r--editor/libeditor/HTMLTableEditor.cpp3452
-rw-r--r--editor/libeditor/HTMLURIRefObject.cpp262
-rw-r--r--editor/libeditor/HTMLURIRefObject.h48
-rw-r--r--editor/libeditor/InsertNodeTransaction.cpp101
-rw-r--r--editor/libeditor/InsertNodeTransaction.h58
-rw-r--r--editor/libeditor/InsertTextTransaction.cpp130
-rw-r--r--editor/libeditor/InsertTextTransaction.h88
-rw-r--r--editor/libeditor/InternetCiter.cpp366
-rw-r--r--editor/libeditor/InternetCiter.h40
-rw-r--r--editor/libeditor/JoinNodeTransaction.cpp121
-rw-r--r--editor/libeditor/JoinNodeTransaction.h68
-rw-r--r--editor/libeditor/PlaceholderTransaction.cpp276
-rw-r--r--editor/libeditor/PlaceholderTransaction.h99
-rw-r--r--editor/libeditor/SelectionState.cpp696
-rw-r--r--editor/libeditor/SelectionState.h357
-rw-r--r--editor/libeditor/SetDocumentTitleTransaction.cpp229
-rw-r--r--editor/libeditor/SetDocumentTitleTransaction.h60
-rw-r--r--editor/libeditor/SplitNodeTransaction.cpp140
-rw-r--r--editor/libeditor/SplitNodeTransaction.h71
-rw-r--r--editor/libeditor/StyleSheetTransactions.cpp159
-rw-r--r--editor/libeditor/StyleSheetTransactions.h73
-rw-r--r--editor/libeditor/TextEditRules.cpp1485
-rw-r--r--editor/libeditor/TextEditRules.h357
-rw-r--r--editor/libeditor/TextEditRulesBidi.cpp100
-rw-r--r--editor/libeditor/TextEditUtils.cpp113
-rw-r--r--editor/libeditor/TextEditUtils.h47
-rw-r--r--editor/libeditor/TextEditor.cpp1641
-rw-r--r--editor/libeditor/TextEditor.h250
-rw-r--r--editor/libeditor/TextEditorDataTransfer.cpp479
-rw-r--r--editor/libeditor/TextEditorTest.cpp259
-rw-r--r--editor/libeditor/TextEditorTest.h42
-rw-r--r--editor/libeditor/TypeInState.cpp397
-rw-r--r--editor/libeditor/TypeInState.h112
-rw-r--r--editor/libeditor/WSRunObject.cpp1926
-rw-r--r--editor/libeditor/WSRunObject.h411
-rw-r--r--editor/libeditor/crashtests/1057677.html9
-rw-r--r--editor/libeditor/crashtests/1128787.html17
-rw-r--r--editor/libeditor/crashtests/1134545.html22
-rw-r--r--editor/libeditor/crashtests/1158452.html10
-rw-r--r--editor/libeditor/crashtests/1158651.html18
-rw-r--r--editor/libeditor/crashtests/1244894.xhtml21
-rw-r--r--editor/libeditor/crashtests/1272490.html20
-rw-r--r--editor/libeditor/crashtests/1317704.html36
-rw-r--r--editor/libeditor/crashtests/1348851.html19
-rw-r--r--editor/libeditor/crashtests/336081-1.xhtml52
-rw-r--r--editor/libeditor/crashtests/336104.html37
-rw-r--r--editor/libeditor/crashtests/382527-1.html58
-rw-r--r--editor/libeditor/crashtests/382778-1.html53
-rw-r--r--editor/libeditor/crashtests/402172-1.html23
-rw-r--r--editor/libeditor/crashtests/403965-1.xhtml7
-rw-r--r--editor/libeditor/crashtests/407074-1.html7
-rw-r--r--editor/libeditor/crashtests/407079-1.html15
-rw-r--r--editor/libeditor/crashtests/407256-1.html23
-rw-r--r--editor/libeditor/crashtests/407277-1.html7
-rw-r--r--editor/libeditor/crashtests/414178-1.html22
-rw-r--r--editor/libeditor/crashtests/418923-1.html19
-rw-r--r--editor/libeditor/crashtests/420439.html30
-rw-r--r--editor/libeditor/crashtests/428489-1.html8
-rw-r--r--editor/libeditor/crashtests/429586-1.html8
-rw-r--r--editor/libeditor/crashtests/430624-1.html14
-rw-r--r--editor/libeditor/crashtests/431086-1.xhtml22
-rw-r--r--editor/libeditor/crashtests/448329-1.html72
-rw-r--r--editor/libeditor/crashtests/448329-2.html21
-rw-r--r--editor/libeditor/crashtests/448329-3.html112
-rw-r--r--editor/libeditor/crashtests/456727-1.html8
-rw-r--r--editor/libeditor/crashtests/456727-2.html8
-rw-r--r--editor/libeditor/crashtests/459613-iframe.html1
-rw-r--r--editor/libeditor/crashtests/459613.html17
-rw-r--r--editor/libeditor/crashtests/467647-1.html19
-rw-r--r--editor/libeditor/crashtests/475132-1.xhtml20
-rw-r--r--editor/libeditor/crashtests/499844-1.html15
-rw-r--r--editor/libeditor/crashtests/503709-1.xhtml11
-rw-r--r--editor/libeditor/crashtests/513375-1.xhtml19
-rw-r--r--editor/libeditor/crashtests/535632-1.xhtml1
-rw-r--r--editor/libeditor/crashtests/574558-1.xhtml15
-rw-r--r--editor/libeditor/crashtests/580151-1.xhtml26
-rw-r--r--editor/libeditor/crashtests/582138-1.xhtml10
-rw-r--r--editor/libeditor/crashtests/612565-1.html17
-rw-r--r--editor/libeditor/crashtests/615015-1.html17
-rw-r--r--editor/libeditor/crashtests/615450-1.html17
-rw-r--r--editor/libeditor/crashtests/633709.xhtml36
-rw-r--r--editor/libeditor/crashtests/636074-1.html18
-rw-r--r--editor/libeditor/crashtests/639736-1.xhtml14
-rw-r--r--editor/libeditor/crashtests/643786-1.html18
-rw-r--r--editor/libeditor/crashtests/650572-1.html18
-rw-r--r--editor/libeditor/crashtests/667321-1.html15
-rw-r--r--editor/libeditor/crashtests/682650-1.html30
-rw-r--r--editor/libeditor/crashtests/713427-1.html9
-rw-r--r--editor/libeditor/crashtests/713427-2.xhtml28
-rw-r--r--editor/libeditor/crashtests/716456-1.html29
-rw-r--r--editor/libeditor/crashtests/759748.html58
-rw-r--r--editor/libeditor/crashtests/761861.html15
-rw-r--r--editor/libeditor/crashtests/762183.html6
-rw-r--r--editor/libeditor/crashtests/766305.html21
-rw-r--r--editor/libeditor/crashtests/766360.html18
-rw-r--r--editor/libeditor/crashtests/766387.html20
-rw-r--r--editor/libeditor/crashtests/766413.html42
-rw-r--r--editor/libeditor/crashtests/766795.html21
-rw-r--r--editor/libeditor/crashtests/766845.xhtml27
-rw-r--r--editor/libeditor/crashtests/767169.html23
-rw-r--r--editor/libeditor/crashtests/768748.html16
-rw-r--r--editor/libeditor/crashtests/768765.html36
-rw-r--r--editor/libeditor/crashtests/769008-1.html23
-rw-r--r--editor/libeditor/crashtests/769967.xhtml16
-rw-r--r--editor/libeditor/crashtests/771749.html21
-rw-r--r--editor/libeditor/crashtests/772282.html27
-rw-r--r--editor/libeditor/crashtests/776323.html18
-rw-r--r--editor/libeditor/crashtests/793866.html21
-rw-r--r--editor/libeditor/crashtests/crashtests.list72
-rw-r--r--editor/libeditor/moz.build99
-rw-r--r--editor/libeditor/nsIAbsorbingTransaction.h58
-rw-r--r--editor/libeditor/nsIEditRules.h68
-rw-r--r--editor/libeditor/tests/browser.ini8
-rw-r--r--editor/libeditor/tests/browser_bug527935.js63
-rw-r--r--editor/libeditor/tests/browser_bug629172.js106
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext/LICENSE202
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext/README58
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext/README.Mozilla17
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext/currentStatus.js46
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext/current_revision1
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext/richtext/editable.html11
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext/richtext/js/range.js1069
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext/richtext/richtext.html1081
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext/update_from_upstream16
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/LICENSE202
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/README58
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/README.Mozilla23
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/currentStatus.js1850
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/current_revision1
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/__init__.py0
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/common.py25
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/handlers.py107
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/common.css116
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-body.html11
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-dM.html17
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-div.html11
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable.css66
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/canonicalize.js436
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/compare.js489
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/output.js456
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/pad.js269
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/range-bootstrap.js5
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/range.js6184
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/run.js383
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/units.js416
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/variables.js227
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/templates/output.html138
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/templates/richtext2.html107
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/__init__.py17
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/apply.py364
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/applyCSS.py244
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/change.py273
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/changeCSS.py210
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/delete.py330
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/forwarddelete.py315
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/insert.py285
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryEnabled.py215
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryIndeterm.py214
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryState.py575
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/querySupported.py226
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryValue.py429
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/selection.py772
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/unapply.py462
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/unapplyCSS.py226
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/richtext2/unittestexample.html103
-rw-r--r--editor/libeditor/tests/browserscope/lib/richtext2/update_from_upstream19
-rw-r--r--editor/libeditor/tests/browserscope/mochitest.ini59
-rw-r--r--editor/libeditor/tests/browserscope/test_richtext.html48
-rw-r--r--editor/libeditor/tests/browserscope/test_richtext2.html233
-rw-r--r--editor/libeditor/tests/bug527935.html11
-rw-r--r--editor/libeditor/tests/bug527935_2.html1
-rw-r--r--editor/libeditor/tests/bug629172.html15
-rw-r--r--editor/libeditor/tests/chrome.ini15
-rw-r--r--editor/libeditor/tests/data/cfhtml-chromium.txtbin856 -> 0 bytes
-rw-r--r--editor/libeditor/tests/data/cfhtml-firefox.txtbin266 -> 0 bytes
-rw-r--r--editor/libeditor/tests/data/cfhtml-ie.txtbin1080 -> 0 bytes
-rw-r--r--editor/libeditor/tests/data/cfhtml-nocontext.txt18
-rw-r--r--editor/libeditor/tests/data/cfhtml-ooo.txtbin649 -> 0 bytes
-rw-r--r--editor/libeditor/tests/file_bug549262.html8
-rw-r--r--editor/libeditor/tests/file_bug586662.html7
-rw-r--r--editor/libeditor/tests/file_bug635636_2.html1
-rw-r--r--editor/libeditor/tests/file_bug674770-1.html5
-rw-r--r--editor/libeditor/tests/file_bug915962.html13
-rw-r--r--editor/libeditor/tests/file_bug966155.html1
-rw-r--r--editor/libeditor/tests/file_bug966552.html1
-rw-r--r--editor/libeditor/tests/file_select_all_without_body.html41
-rw-r--r--editor/libeditor/tests/green.pngbin334 -> 0 bytes
-rw-r--r--editor/libeditor/tests/mochitest.ini251
-rw-r--r--editor/libeditor/tests/spellcheck.js20
-rw-r--r--editor/libeditor/tests/test_CF_HTML_clipboard.html159
-rw-r--r--editor/libeditor/tests/test_backspace_vs.html130
-rw-r--r--editor/libeditor/tests/test_bug1026397.html103
-rw-r--r--editor/libeditor/tests/test_bug1053048.html73
-rw-r--r--editor/libeditor/tests/test_bug1067255.html57
-rw-r--r--editor/libeditor/tests/test_bug1068979.html72
-rw-r--r--editor/libeditor/tests/test_bug1094000.html104
-rw-r--r--editor/libeditor/tests/test_bug1100966.html65
-rw-r--r--editor/libeditor/tests/test_bug1101392.html78
-rw-r--r--editor/libeditor/tests/test_bug1102906.html51
-rw-r--r--editor/libeditor/tests/test_bug1109465.html69
-rw-r--r--editor/libeditor/tests/test_bug1140105.html71
-rw-r--r--editor/libeditor/tests/test_bug1140617.html37
-rw-r--r--editor/libeditor/tests/test_bug1153237.html49
-rw-r--r--editor/libeditor/tests/test_bug1154791.html67
-rw-r--r--editor/libeditor/tests/test_bug1162952.html43
-rw-r--r--editor/libeditor/tests/test_bug1181130-1.html50
-rw-r--r--editor/libeditor/tests/test_bug1181130-2.html44
-rw-r--r--editor/libeditor/tests/test_bug1186799.html81
-rw-r--r--editor/libeditor/tests/test_bug1230473.html124
-rw-r--r--editor/libeditor/tests/test_bug1247483.html61
-rw-r--r--editor/libeditor/tests/test_bug1248128.html52
-rw-r--r--editor/libeditor/tests/test_bug1248185.html57
-rw-r--r--editor/libeditor/tests/test_bug1250010.html93
-rw-r--r--editor/libeditor/tests/test_bug1257363.html182
-rw-r--r--editor/libeditor/tests/test_bug1258085.html66
-rw-r--r--editor/libeditor/tests/test_bug1268736.html64
-rw-r--r--editor/libeditor/tests/test_bug1270235.html46
-rw-r--r--editor/libeditor/tests/test_bug1306532.html64
-rw-r--r--editor/libeditor/tests/test_bug1310912.html93
-rw-r--r--editor/libeditor/tests/test_bug1314790.html65
-rw-r--r--editor/libeditor/tests/test_bug1315065.html145
-rw-r--r--editor/libeditor/tests/test_bug1328023.html64
-rw-r--r--editor/libeditor/tests/test_bug1330796.html101
-rw-r--r--editor/libeditor/tests/test_bug1332876.html49
-rw-r--r--editor/libeditor/tests/test_bug1352799.html98
-rw-r--r--editor/libeditor/tests/test_bug200416.html15
-rw-r--r--editor/libeditor/tests/test_bug289384.html49
-rw-r--r--editor/libeditor/tests/test_bug290026.html52
-rw-r--r--editor/libeditor/tests/test_bug291780.html50
-rw-r--r--editor/libeditor/tests/test_bug309731.html58
-rw-r--r--editor/libeditor/tests/test_bug316447.html16
-rw-r--r--editor/libeditor/tests/test_bug318065.html82
-rw-r--r--editor/libeditor/tests/test_bug332636.html75
-rw-r--r--editor/libeditor/tests/test_bug332636.html^headers^1
-rw-r--r--editor/libeditor/tests/test_bug366682.html67
-rw-r--r--editor/libeditor/tests/test_bug372345.html59
-rw-r--r--editor/libeditor/tests/test_bug404320.html91
-rw-r--r--editor/libeditor/tests/test_bug408231.html250
-rw-r--r--editor/libeditor/tests/test_bug410986.html80
-rw-r--r--editor/libeditor/tests/test_bug414526.html247
-rw-r--r--editor/libeditor/tests/test_bug417418.html78
-rw-r--r--editor/libeditor/tests/test_bug432225.html71
-rw-r--r--editor/libeditor/tests/test_bug439808.html37
-rw-r--r--editor/libeditor/tests/test_bug442186.html103
-rw-r--r--editor/libeditor/tests/test_bug449243.html136
-rw-r--r--editor/libeditor/tests/test_bug455992.html97
-rw-r--r--editor/libeditor/tests/test_bug456244.html70
-rw-r--r--editor/libeditor/tests/test_bug460740.html124
-rw-r--r--editor/libeditor/tests/test_bug46555.html47
-rw-r--r--editor/libeditor/tests/test_bug468353.html117
-rw-r--r--editor/libeditor/tests/test_bug471319.html80
-rw-r--r--editor/libeditor/tests/test_bug471722.html81
-rw-r--r--editor/libeditor/tests/test_bug478725.html131
-rw-r--r--editor/libeditor/tests/test_bug480647.html110
-rw-r--r--editor/libeditor/tests/test_bug480972.html98
-rw-r--r--editor/libeditor/tests/test_bug483651.html53
-rw-r--r--editor/libeditor/tests/test_bug484181.html78
-rw-r--r--editor/libeditor/tests/test_bug487524.html65
-rw-r--r--editor/libeditor/tests/test_bug489202.xul81
-rw-r--r--editor/libeditor/tests/test_bug490879.html45
-rw-r--r--editor/libeditor/tests/test_bug502673.html108
-rw-r--r--editor/libeditor/tests/test_bug514156.html50
-rw-r--r--editor/libeditor/tests/test_bug520189.html621
-rw-r--r--editor/libeditor/tests/test_bug525389.html198
-rw-r--r--editor/libeditor/tests/test_bug537046.html51
-rw-r--r--editor/libeditor/tests/test_bug549262.html132
-rw-r--r--editor/libeditor/tests/test_bug550434.html42
-rw-r--r--editor/libeditor/tests/test_bug551704.html125
-rw-r--r--editor/libeditor/tests/test_bug552782.html47
-rw-r--r--editor/libeditor/tests/test_bug567213.html58
-rw-r--r--editor/libeditor/tests/test_bug569988.html99
-rw-r--r--editor/libeditor/tests/test_bug570144.html123
-rw-r--r--editor/libeditor/tests/test_bug578771.html63
-rw-r--r--editor/libeditor/tests/test_bug586662.html60
-rw-r--r--editor/libeditor/tests/test_bug587461.html16
-rw-r--r--editor/libeditor/tests/test_bug590554.html36
-rw-r--r--editor/libeditor/tests/test_bug592592.html72
-rw-r--r--editor/libeditor/tests/test_bug596001.html55
-rw-r--r--editor/libeditor/tests/test_bug596333.html124
-rw-r--r--editor/libeditor/tests/test_bug596506.html60
-rw-r--r--editor/libeditor/tests/test_bug597331.html72
-rw-r--r--editor/libeditor/tests/test_bug597784.html37
-rw-r--r--editor/libeditor/tests/test_bug599322.html58
-rw-r--r--editor/libeditor/tests/test_bug599983.html16
-rw-r--r--editor/libeditor/tests/test_bug599983.xul70
-rw-r--r--editor/libeditor/tests/test_bug600570.html80
-rw-r--r--editor/libeditor/tests/test_bug602130.html45
-rw-r--r--editor/libeditor/tests/test_bug603556.html48
-rw-r--r--editor/libeditor/tests/test_bug604532.html42
-rw-r--r--editor/libeditor/tests/test_bug607584.html41
-rw-r--r--editor/libeditor/tests/test_bug607584.xul115
-rw-r--r--editor/libeditor/tests/test_bug611182.html239
-rw-r--r--editor/libeditor/tests/test_bug612128.html42
-rw-r--r--editor/libeditor/tests/test_bug612447.html74
-rw-r--r--editor/libeditor/tests/test_bug616590.xul105
-rw-r--r--editor/libeditor/tests/test_bug620906.html50
-rw-r--r--editor/libeditor/tests/test_bug622371.html40
-rw-r--r--editor/libeditor/tests/test_bug625452.html66
-rw-r--r--editor/libeditor/tests/test_bug629845.html60
-rw-r--r--editor/libeditor/tests/test_bug635636.html65
-rw-r--r--editor/libeditor/tests/test_bug636465.html54
-rw-r--r--editor/libeditor/tests/test_bug638596.html37
-rw-r--r--editor/libeditor/tests/test_bug640321.html190
-rw-r--r--editor/libeditor/tests/test_bug641466.html46
-rw-r--r--editor/libeditor/tests/test_bug645914.html63
-rw-r--r--editor/libeditor/tests/test_bug646194.html38
-rw-r--r--editor/libeditor/tests/test_bug668599.html73
-rw-r--r--editor/libeditor/tests/test_bug674770-1.html86
-rw-r--r--editor/libeditor/tests/test_bug674770-2.html395
-rw-r--r--editor/libeditor/tests/test_bug674861.html185
-rw-r--r--editor/libeditor/tests/test_bug676401.html119
-rw-r--r--editor/libeditor/tests/test_bug677752.html107
-rw-r--r--editor/libeditor/tests/test_bug681229.html51
-rw-r--r--editor/libeditor/tests/test_bug686203.html50
-rw-r--r--editor/libeditor/tests/test_bug692520.html42
-rw-r--r--editor/libeditor/tests/test_bug697842.html117
-rw-r--r--editor/libeditor/tests/test_bug725069.html35
-rw-r--r--editor/libeditor/tests/test_bug735059.html22
-rw-r--r--editor/libeditor/tests/test_bug738366.html24
-rw-r--r--editor/libeditor/tests/test_bug740784.html48
-rw-r--r--editor/libeditor/tests/test_bug742261.html14
-rw-r--r--editor/libeditor/tests/test_bug757371.html26
-rw-r--r--editor/libeditor/tests/test_bug757771.html31
-rw-r--r--editor/libeditor/tests/test_bug767684.html15
-rw-r--r--editor/libeditor/tests/test_bug772796.html223
-rw-r--r--editor/libeditor/tests/test_bug773262.html63
-rw-r--r--editor/libeditor/tests/test_bug780035.html22
-rw-r--r--editor/libeditor/tests/test_bug780908.xul113
-rw-r--r--editor/libeditor/tests/test_bug787432.html17
-rw-r--r--editor/libeditor/tests/test_bug790475.html95
-rw-r--r--editor/libeditor/tests/test_bug795418-2.html88
-rw-r--r--editor/libeditor/tests/test_bug795418-3.html88
-rw-r--r--editor/libeditor/tests/test_bug795418-4.html67
-rw-r--r--editor/libeditor/tests/test_bug795418-5.html67
-rw-r--r--editor/libeditor/tests/test_bug795418-6.html67
-rw-r--r--editor/libeditor/tests/test_bug795418.html67
-rw-r--r--editor/libeditor/tests/test_bug795785.html168
-rw-r--r--editor/libeditor/tests/test_bug796839.html17
-rw-r--r--editor/libeditor/tests/test_bug830600.html100
-rw-r--r--editor/libeditor/tests/test_bug832025.html42
-rw-r--r--editor/libeditor/tests/test_bug850043.html65
-rw-r--r--editor/libeditor/tests/test_bug857487.html72
-rw-r--r--editor/libeditor/tests/test_bug858918.html16
-rw-r--r--editor/libeditor/tests/test_bug915962.html100
-rw-r--r--editor/libeditor/tests/test_bug966155.html54
-rw-r--r--editor/libeditor/tests/test_bug966552.html42
-rw-r--r--editor/libeditor/tests/test_bug974309.html78
-rw-r--r--editor/libeditor/tests/test_bug998188.html52
-rw-r--r--editor/libeditor/tests/test_composition_event_created_in_chrome.html82
-rw-r--r--editor/libeditor/tests/test_contenteditable_focus.html209
-rw-r--r--editor/libeditor/tests/test_contenteditable_text_input_handling.html329
-rw-r--r--editor/libeditor/tests/test_css_chrome_load_access.html67
-rw-r--r--editor/libeditor/tests/test_dom_input_event_on_htmleditor.html172
-rw-r--r--editor/libeditor/tests/test_dom_input_event_on_texteditor.html130
-rw-r--r--editor/libeditor/tests/test_dragdrop.html178
-rw-r--r--editor/libeditor/tests/test_htmleditor_keyevent_handling.html664
-rw-r--r--editor/libeditor/tests/test_keypress_untrusted_event.html99
-rw-r--r--editor/libeditor/tests/test_pasteImgTextarea.html20
-rw-r--r--editor/libeditor/tests/test_pasteImgTextarea.xul27
-rw-r--r--editor/libeditor/tests/test_root_element_replacement.html148
-rw-r--r--editor/libeditor/tests/test_select_all_without_body.html27
-rw-r--r--editor/libeditor/tests/test_selection_move_commands.html219
-rw-r--r--editor/libeditor/tests/test_set_document_title_transaction.html79
-rw-r--r--editor/libeditor/tests/test_spellcheck_pref.html23
-rw-r--r--editor/libeditor/tests/test_texteditor_keyevent_handling.html386
-rw-r--r--editor/moz.build40
-rw-r--r--editor/nsEditorCID.h25
-rw-r--r--editor/nsIContentFilter.idl85
-rw-r--r--editor/nsIDocumentStateListener.idl16
-rw-r--r--editor/nsIEditActionListener.idl199
-rw-r--r--editor/nsIEditor.idl567
-rw-r--r--editor/nsIEditorIMESupport.idl40
-rw-r--r--editor/nsIEditorMailSupport.idl81
-rw-r--r--editor/nsIEditorObserver.idl36
-rw-r--r--editor/nsIEditorSpellCheck.idl166
-rw-r--r--editor/nsIEditorStyleSheets.idl71
-rw-r--r--editor/nsIEditorUtils.idl32
-rw-r--r--editor/nsIHTMLAbsPosEditor.idl132
-rw-r--r--editor/nsIHTMLEditor.idl559
-rw-r--r--editor/nsIHTMLInlineTableEditor.idl44
-rw-r--r--editor/nsIHTMLObjectResizeListener.idl33
-rw-r--r--editor/nsIHTMLObjectResizer.idl93
-rw-r--r--editor/nsIPlaintextEditor.idl112
-rw-r--r--editor/nsITableEditor.idl337
-rw-r--r--editor/nsIURIRefObject.idl43
-rw-r--r--editor/nsPIEditorTransaction.idl20
-rw-r--r--editor/reftests/1088158-ref.html2
-rw-r--r--editor/reftests/1088158.html8
-rw-r--r--editor/reftests/338427-1-ref.html7
-rw-r--r--editor/reftests/338427-1.html7
-rw-r--r--editor/reftests/338427-2-ref.html19
-rw-r--r--editor/reftests/338427-2.html18
-rw-r--r--editor/reftests/338427-3-ref.html19
-rw-r--r--editor/reftests/338427-3.html19
-rw-r--r--editor/reftests/388980-1-ref.html25
-rw-r--r--editor/reftests/388980-1.html43
-rw-r--r--editor/reftests/462758-grabbers-resizers-ref.html34
-rw-r--r--editor/reftests/462758-grabbers-resizers.html33
-rw-r--r--editor/reftests/642800-iframe.html29
-rw-r--r--editor/reftests/642800-ref.html7
-rw-r--r--editor/reftests/642800.html18
-rw-r--r--editor/reftests/672709-ref.html22
-rw-r--r--editor/reftests/672709.html12
-rw-r--r--editor/reftests/674212-spellcheck-ref.html20
-rw-r--r--editor/reftests/674212-spellcheck.html20
-rw-r--r--editor/reftests/694880-1.html10
-rw-r--r--editor/reftests/694880-2.html11
-rw-r--r--editor/reftests/694880-3.html10
-rw-r--r--editor/reftests/694880-ref.html9
-rw-r--r--editor/reftests/824080-1-ref.html17
-rw-r--r--editor/reftests/824080-1.html19
-rw-r--r--editor/reftests/824080-2-ref.html22
-rw-r--r--editor/reftests/824080-2.html22
-rw-r--r--editor/reftests/824080-3-ref.html21
-rw-r--r--editor/reftests/824080-3.html21
-rw-r--r--editor/reftests/824080-4-ref.html21
-rw-r--r--editor/reftests/824080-4.html26
-rw-r--r--editor/reftests/824080-5-ref.html22
-rw-r--r--editor/reftests/824080-5.html25
-rw-r--r--editor/reftests/824080-6-ref.html18
-rw-r--r--editor/reftests/824080-6.html20
-rw-r--r--editor/reftests/824080-7-ref.html19
-rw-r--r--editor/reftests/824080-7.html22
-rw-r--r--editor/reftests/911201-ref.html2
-rw-r--r--editor/reftests/911201.html2
-rw-r--r--editor/reftests/969773-ref.html24
-rw-r--r--editor/reftests/969773.html29
-rw-r--r--editor/reftests/997805-ref.html2
-rw-r--r--editor/reftests/997805.html16
-rw-r--r--editor/reftests/caret_after_reframe-ref.html6
-rw-r--r--editor/reftests/caret_after_reframe.html14
-rw-r--r--editor/reftests/caret_on_focus-ref.html11
-rw-r--r--editor/reftests/caret_on_focus.html11
-rw-r--r--editor/reftests/caret_on_positioned-ref.html8
-rw-r--r--editor/reftests/caret_on_positioned.html8
-rw-r--r--editor/reftests/caret_on_presshell_reinit-2.html27
-rw-r--r--editor/reftests/caret_on_presshell_reinit-ref.html19
-rw-r--r--editor/reftests/caret_on_presshell_reinit.html22
-rw-r--r--editor/reftests/caret_on_textarea_lastline-ref.html13
-rw-r--r--editor/reftests/caret_on_textarea_lastline.html14
-rw-r--r--editor/reftests/dynamic-1.html9
-rw-r--r--editor/reftests/dynamic-overflow-change-ref.html13
-rw-r--r--editor/reftests/dynamic-overflow-change.html13
-rw-r--r--editor/reftests/dynamic-ref.html6
-rw-r--r--editor/reftests/dynamic-type-1.html11
-rw-r--r--editor/reftests/dynamic-type-2.html11
-rw-r--r--editor/reftests/dynamic-type-3.html11
-rw-r--r--editor/reftests/dynamic-type-4.html11
-rw-r--r--editor/reftests/emptypasswd-1.html6
-rw-r--r--editor/reftests/emptypasswd-2.html9
-rw-r--r--editor/reftests/emptypasswd-ref.html6
-rw-r--r--editor/reftests/input-text-notheme-onfocus-reframe-ref.html28
-rw-r--r--editor/reftests/input-text-notheme-onfocus-reframe.html32
-rw-r--r--editor/reftests/input-text-onfocus-reframe-ref.html25
-rw-r--r--editor/reftests/input-text-onfocus-reframe.html29
-rw-r--r--editor/reftests/newline-1.html6
-rw-r--r--editor/reftests/newline-2.html6
-rw-r--r--editor/reftests/newline-3.html6
-rw-r--r--editor/reftests/newline-4.html6
-rw-r--r--editor/reftests/newline-ref.html6
-rw-r--r--editor/reftests/nobogusnode-1.html6
-rw-r--r--editor/reftests/nobogusnode-2.html5
-rw-r--r--editor/reftests/nobogusnode-ref.html6
-rw-r--r--editor/reftests/passwd-1.html6
-rw-r--r--editor/reftests/passwd-2.html6
-rw-r--r--editor/reftests/passwd-3.html9
-rw-r--r--editor/reftests/passwd-4.html19
-rw-r--r--editor/reftests/passwd-ref.html6
-rw-r--r--editor/reftests/readonly-editable-ref.html13
-rw-r--r--editor/reftests/readonly-editable.html24
-rw-r--r--editor/reftests/readonly-non-editable-ref.html21
-rw-r--r--editor/reftests/readonly-non-editable.html24
-rw-r--r--editor/reftests/readwrite-editable-ref.html13
-rw-r--r--editor/reftests/readwrite-editable.html24
-rw-r--r--editor/reftests/readwrite-non-editable-ref.html21
-rw-r--r--editor/reftests/readwrite-non-editable.html24
-rw-r--r--editor/reftests/reftest-stylo.list177
-rw-r--r--editor/reftests/reftest.list137
-rw-r--r--editor/reftests/selection_visibility_after_reframe-2.html11
-rw-r--r--editor/reftests/selection_visibility_after_reframe-3.html14
-rw-r--r--editor/reftests/selection_visibility_after_reframe-ref.html6
-rw-r--r--editor/reftests/selection_visibility_after_reframe.html15
-rw-r--r--editor/reftests/spellcheck-comma-valid-ref.html6
-rw-r--r--editor/reftests/spellcheck-comma-valid.html6
-rw-r--r--editor/reftests/spellcheck-contenteditable-attr-dynamic-inherit.html11
-rw-r--r--editor/reftests/spellcheck-contenteditable-attr-dynamic-override-inherit.html11
-rw-r--r--editor/reftests/spellcheck-contenteditable-attr-dynamic-override.html11
-rw-r--r--editor/reftests/spellcheck-contenteditable-attr-dynamic.html11
-rw-r--r--editor/reftests/spellcheck-contenteditable-attr-inherit.html6
-rw-r--r--editor/reftests/spellcheck-contenteditable-attr.html6
-rw-r--r--editor/reftests/spellcheck-contenteditable-disabled-partial-ref.html12
-rw-r--r--editor/reftests/spellcheck-contenteditable-disabled-partial.html11
-rw-r--r--editor/reftests/spellcheck-contenteditable-disabled-ref.html6
-rw-r--r--editor/reftests/spellcheck-contenteditable-disabled.html11
-rw-r--r--editor/reftests/spellcheck-contenteditable-focused-reframe.html18
-rw-r--r--editor/reftests/spellcheck-contenteditable-focused.html13
-rw-r--r--editor/reftests/spellcheck-contenteditable-nofocus-ref.html6
-rw-r--r--editor/reftests/spellcheck-contenteditable-nofocus.html6
-rw-r--r--editor/reftests/spellcheck-contenteditable-property-dynamic-inherit.html11
-rw-r--r--editor/reftests/spellcheck-contenteditable-property-dynamic-override-inherit.html11
-rw-r--r--editor/reftests/spellcheck-contenteditable-property-dynamic-override.html11
-rw-r--r--editor/reftests/spellcheck-contenteditable-property-dynamic.html11
-rw-r--r--editor/reftests/spellcheck-contenteditable-ref.html11
-rw-r--r--editor/reftests/spellcheck-dotafterquote-valid-ref.html6
-rw-r--r--editor/reftests/spellcheck-dotafterquote-valid.html6
-rw-r--r--editor/reftests/spellcheck-hyphen-invalid-ref.html6
-rw-r--r--editor/reftests/spellcheck-hyphen-invalid.html6
-rw-r--r--editor/reftests/spellcheck-hyphen-multiple-invalid-ref.html6
-rw-r--r--editor/reftests/spellcheck-hyphen-multiple-invalid.html6
-rw-r--r--editor/reftests/spellcheck-hyphen-multiple-valid-ref.html6
-rw-r--r--editor/reftests/spellcheck-hyphen-multiple-valid.html6
-rw-r--r--editor/reftests/spellcheck-hyphen-valid-ref.html6
-rw-r--r--editor/reftests/spellcheck-hyphen-valid.html6
-rw-r--r--editor/reftests/spellcheck-input-attr-after.html6
-rw-r--r--editor/reftests/spellcheck-input-attr-before.html6
-rw-r--r--editor/reftests/spellcheck-input-attr-dynamic-inherit.html11
-rw-r--r--editor/reftests/spellcheck-input-attr-dynamic-override-inherit.html11
-rw-r--r--editor/reftests/spellcheck-input-attr-dynamic-override.html11
-rw-r--r--editor/reftests/spellcheck-input-attr-dynamic.html11
-rw-r--r--editor/reftests/spellcheck-input-attr-inherit.html6
-rw-r--r--editor/reftests/spellcheck-input-disabled.html6
-rw-r--r--editor/reftests/spellcheck-input-nofocus-ref.html6
-rw-r--r--editor/reftests/spellcheck-input-property-dynamic-inherit.html11
-rw-r--r--editor/reftests/spellcheck-input-property-dynamic-override-inherit.html11
-rw-r--r--editor/reftests/spellcheck-input-property-dynamic-override.html11
-rw-r--r--editor/reftests/spellcheck-input-property-dynamic.html11
-rw-r--r--editor/reftests/spellcheck-input-ref.html11
-rw-r--r--editor/reftests/spellcheck-non-latin-arabic-ref.html9
-rw-r--r--editor/reftests/spellcheck-non-latin-arabic.html9
-rw-r--r--editor/reftests/spellcheck-non-latin-chinese-simplified-ref.html9
-rw-r--r--editor/reftests/spellcheck-non-latin-chinese-simplified.html9
-rw-r--r--editor/reftests/spellcheck-non-latin-chinese-traditional-ref.html9
-rw-r--r--editor/reftests/spellcheck-non-latin-chinese-traditional.html9
-rw-r--r--editor/reftests/spellcheck-non-latin-hebrew-ref.html9
-rw-r--r--editor/reftests/spellcheck-non-latin-hebrew.html9
-rw-r--r--editor/reftests/spellcheck-non-latin-japanese-ref.html9
-rw-r--r--editor/reftests/spellcheck-non-latin-japanese.html9
-rw-r--r--editor/reftests/spellcheck-non-latin-korean-ref.html9
-rw-r--r--editor/reftests/spellcheck-non-latin-korean.html9
-rw-r--r--editor/reftests/spellcheck-period-valid-ref.html6
-rw-r--r--editor/reftests/spellcheck-period-valid.html6
-rw-r--r--editor/reftests/spellcheck-slash-valid-ref.html6
-rw-r--r--editor/reftests/spellcheck-slash-valid.html6
-rw-r--r--editor/reftests/spellcheck-space-valid-ref.html6
-rw-r--r--editor/reftests/spellcheck-space-valid.html6
-rw-r--r--editor/reftests/spellcheck-superscript-1-ref.html3
-rw-r--r--editor/reftests/spellcheck-superscript-1.html3
-rw-r--r--editor/reftests/spellcheck-superscript-2-ref.html3
-rw-r--r--editor/reftests/spellcheck-superscript-2.html3
-rw-r--r--editor/reftests/spellcheck-textarea-attr-dynamic-inherit.html11
-rw-r--r--editor/reftests/spellcheck-textarea-attr-dynamic-override-inherit.html11
-rw-r--r--editor/reftests/spellcheck-textarea-attr-dynamic-override.html11
-rw-r--r--editor/reftests/spellcheck-textarea-attr-dynamic.html11
-rw-r--r--editor/reftests/spellcheck-textarea-attr-inherit.html6
-rw-r--r--editor/reftests/spellcheck-textarea-attr.html6
-rw-r--r--editor/reftests/spellcheck-textarea-disabled.html6
-rw-r--r--editor/reftests/spellcheck-textarea-focused-notreadonly.html19
-rw-r--r--editor/reftests/spellcheck-textarea-focused-reframe.html18
-rw-r--r--editor/reftests/spellcheck-textarea-focused.html13
-rw-r--r--editor/reftests/spellcheck-textarea-nofocus-ref.html6
-rw-r--r--editor/reftests/spellcheck-textarea-nofocus.html6
-rw-r--r--editor/reftests/spellcheck-textarea-property-dynamic-inherit.html11
-rw-r--r--editor/reftests/spellcheck-textarea-property-dynamic-override-inherit.html11
-rw-r--r--editor/reftests/spellcheck-textarea-property-dynamic-override.html11
-rw-r--r--editor/reftests/spellcheck-textarea-property-dynamic.html11
-rw-r--r--editor/reftests/spellcheck-textarea-ref.html11
-rw-r--r--editor/reftests/spellcheck-textarea-ref2.html11
-rw-r--r--editor/reftests/spellcheck-url-valid-ref.html14
-rw-r--r--editor/reftests/spellcheck-url-valid.html14
-rw-r--r--editor/reftests/unneeded_scroll-ref.html16
-rw-r--r--editor/reftests/unneeded_scroll.html24
-rw-r--r--editor/reftests/xul/autocomplete-1.xul14
-rw-r--r--editor/reftests/xul/autocomplete-ref.xul13
-rw-r--r--editor/reftests/xul/empty-1.xul13
-rw-r--r--editor/reftests/xul/empty-2.xul12
-rw-r--r--editor/reftests/xul/empty-ref.xul13
-rw-r--r--editor/reftests/xul/emptyautocomplete-1.xul12
-rw-r--r--editor/reftests/xul/emptyautocomplete-ref.xul13
-rw-r--r--editor/reftests/xul/emptymultiline-1.xul13
-rw-r--r--editor/reftests/xul/emptymultiline-2.xul13
-rw-r--r--editor/reftests/xul/emptymultiline-ref.xul13
-rw-r--r--editor/reftests/xul/emptytextbox-1.xul12
-rw-r--r--editor/reftests/xul/emptytextbox-2.xul12
-rw-r--r--editor/reftests/xul/emptytextbox-3.xul12
-rw-r--r--editor/reftests/xul/emptytextbox-4.xul12
-rw-r--r--editor/reftests/xul/emptytextbox-5.xul12
-rw-r--r--editor/reftests/xul/emptytextbox-ref.xul13
-rw-r--r--editor/reftests/xul/input.css70
-rw-r--r--editor/reftests/xul/number-1.xul12
-rw-r--r--editor/reftests/xul/number-2.xul12
-rw-r--r--editor/reftests/xul/number-3.xul12
-rw-r--r--editor/reftests/xul/number-4.xul12
-rw-r--r--editor/reftests/xul/number-5.xul12
-rw-r--r--editor/reftests/xul/number-ref.xul13
-rw-r--r--editor/reftests/xul/numberwithvalue-1.xul12
-rw-r--r--editor/reftests/xul/numberwithvalue-ref.xul13
-rw-r--r--editor/reftests/xul/passwd-1.xul12
-rw-r--r--editor/reftests/xul/passwd-2.xul12
-rw-r--r--editor/reftests/xul/passwd-3.xul12
-rw-r--r--editor/reftests/xul/passwd-ref.xul13
-rw-r--r--editor/reftests/xul/placeholder-reset.css8
-rw-r--r--editor/reftests/xul/plain-1.xul12
-rw-r--r--editor/reftests/xul/plain-ref.xul13
-rw-r--r--editor/reftests/xul/platform.js28
-rw-r--r--editor/reftests/xul/reftest-stylo.list67
-rw-r--r--editor/reftests/xul/reftest.list29
-rw-r--r--editor/reftests/xul/textbox-1.xul12
-rw-r--r--editor/reftests/xul/textbox-disabled.xul12
-rw-r--r--editor/reftests/xul/textbox-readonly.xul12
-rw-r--r--editor/reftests/xul/textbox-ref.xul13
-rw-r--r--editor/txmgr/moz.build29
-rw-r--r--editor/txmgr/nsITransaction.idl63
-rw-r--r--editor/txmgr/nsITransactionList.idl70
-rw-r--r--editor/txmgr/nsITransactionListener.idl170
-rw-r--r--editor/txmgr/nsITransactionManager.idl168
-rw-r--r--editor/txmgr/nsTransactionItem.cpp349
-rw-r--r--editor/txmgr/nsTransactionItem.h68
-rw-r--r--editor/txmgr/nsTransactionList.cpp174
-rw-r--r--editor/txmgr/nsTransactionList.h46
-rw-r--r--editor/txmgr/nsTransactionManager.cpp752
-rw-r--r--editor/txmgr/nsTransactionManager.h83
-rw-r--r--editor/txmgr/nsTransactionManagerCID.h14
-rw-r--r--editor/txmgr/nsTransactionManagerFactory.cpp38
-rw-r--r--editor/txmgr/nsTransactionStack.cpp108
-rw-r--r--editor/txmgr/nsTransactionStack.h39
-rw-r--r--editor/txmgr/tests/TestTXMgr.cpp4478
-rw-r--r--editor/txmgr/tests/crashtests/407072-1.html22
-rw-r--r--editor/txmgr/tests/crashtests/449006-1.html28
-rw-r--r--editor/txmgr/tests/crashtests/crashtests.list2
-rw-r--r--editor/txmgr/tests/moz.build8
-rw-r--r--editor/txtsvc/moz.build25
-rw-r--r--editor/txtsvc/nsFilteredContentIterator.cpp424
-rw-r--r--editor/txtsvc/nsFilteredContentIterator.h75
-rw-r--r--editor/txtsvc/nsIInlineSpellChecker.idl50
-rw-r--r--editor/txtsvc/nsISpellChecker.h122
-rw-r--r--editor/txtsvc/nsITextService.h42
-rw-r--r--editor/txtsvc/nsITextServicesDocument.h185
-rw-r--r--editor/txtsvc/nsITextServicesFilter.idl21
-rw-r--r--editor/txtsvc/nsTSAtomList.h51
-rw-r--r--editor/txtsvc/nsTextServicesCID.h19
-rw-r--r--editor/txtsvc/nsTextServicesDocument.cpp3514
-rw-r--r--editor/txtsvc/nsTextServicesDocument.h236
-rw-r--r--editor/txtsvc/nsTextServicesFactory.cpp31
-rw-r--r--editor/ui/composer/content/ComposerCommands.js3900
-rw-r--r--editor/ui/composer/content/EditorContent.css62
-rw-r--r--editor/ui/composer/content/editor.js3226
-rw-r--r--editor/ui/composer/content/editorApplicationOverlay.js161
-rw-r--r--editor/ui/composer/content/editorMailOverlay.xul27
-rw-r--r--editor/ui/composer/content/editorNavigatorOverlay.xul27
-rw-r--r--editor/ui/composer/content/editorSmileyOverlay.xul108
-rw-r--r--editor/ui/composer/content/editorTasksOverlay.xul32
-rw-r--r--editor/ui/composer/content/editorUtilities.js987
-rw-r--r--editor/ui/composer/content/images/tag-anchor.gifbin127 -> 0 bytes
-rw-r--r--editor/ui/dialogs/content/EdAEAttributes.js1811
-rw-r--r--editor/ui/dialogs/content/EdAECSSAttributes.js144
-rw-r--r--editor/ui/dialogs/content/EdAEHTMLAttributes.js366
-rw-r--r--editor/ui/dialogs/content/EdAEJSEAttributes.js192
-rw-r--r--editor/ui/dialogs/content/EdAdvancedEdit.js333
-rw-r--r--editor/ui/dialogs/content/EdAdvancedEdit.xul183
-rw-r--r--editor/ui/dialogs/content/EdButtonProps.js146
-rw-r--r--editor/ui/dialogs/content/EdButtonProps.xul84
-rw-r--r--editor/ui/dialogs/content/EdColorPicker.js306
-rw-r--r--editor/ui/dialogs/content/EdColorPicker.xul67
-rw-r--r--editor/ui/dialogs/content/EdColorProps.js428
-rw-r--r--editor/ui/dialogs/content/EdColorProps.xul118
-rw-r--r--editor/ui/dialogs/content/EdConvertToTable.js330
-rw-r--r--editor/ui/dialogs/content/EdConvertToTable.xul47
-rw-r--r--editor/ui/dialogs/content/EdDialogCommon.js1001
-rw-r--r--editor/ui/dialogs/content/EdDialogOverlay.xul76
-rw-r--r--editor/ui/dialogs/content/EdDialogTemplate.js44
-rw-r--r--editor/ui/dialogs/content/EdDialogTemplate.xul26
-rw-r--r--editor/ui/dialogs/content/EdDictionary.js183
-rw-r--r--editor/ui/dialogs/content/EdDictionary.xul58
-rw-r--r--editor/ui/dialogs/content/EdFieldSetProps.js182
-rw-r--r--editor/ui/dialogs/content/EdFieldSetProps.xul59
-rw-r--r--editor/ui/dialogs/content/EdFormProps.js128
-rw-r--r--editor/ui/dialogs/content/EdFormProps.xul88
-rw-r--r--editor/ui/dialogs/content/EdHLineProps.js195
-rw-r--r--editor/ui/dialogs/content/EdHLineProps.xul69
-rw-r--r--editor/ui/dialogs/content/EdImageOverlay.js598
-rw-r--r--editor/ui/dialogs/content/EdImageOverlay.xul267
-rw-r--r--editor/ui/dialogs/content/EdImageProps.js316
-rw-r--r--editor/ui/dialogs/content/EdImageProps.xul70
-rw-r--r--editor/ui/dialogs/content/EdInputImage.js179
-rw-r--r--editor/ui/dialogs/content/EdInputImage.xul71
-rw-r--r--editor/ui/dialogs/content/EdInputProps.js327
-rw-r--r--editor/ui/dialogs/content/EdInputProps.xul124
-rw-r--r--editor/ui/dialogs/content/EdInsSrc.js142
-rw-r--r--editor/ui/dialogs/content/EdInsSrc.xul44
-rw-r--r--editor/ui/dialogs/content/EdInsertChars.js409
-rw-r--r--editor/ui/dialogs/content/EdInsertChars.xul57
-rw-r--r--editor/ui/dialogs/content/EdInsertMath.js314
-rw-r--r--editor/ui/dialogs/content/EdInsertMath.xul63
-rw-r--r--editor/ui/dialogs/content/EdInsertTOC.js378
-rw-r--r--editor/ui/dialogs/content/EdInsertTOC.xul227
-rw-r--r--editor/ui/dialogs/content/EdInsertTable.js220
-rw-r--r--editor/ui/dialogs/content/EdInsertTable.xul72
-rw-r--r--editor/ui/dialogs/content/EdLabelProps.js108
-rw-r--r--editor/ui/dialogs/content/EdLabelProps.xul58
-rw-r--r--editor/ui/dialogs/content/EdLinkProps.js340
-rw-r--r--editor/ui/dialogs/content/EdLinkProps.xul42
-rw-r--r--editor/ui/dialogs/content/EdListProps.js441
-rw-r--r--editor/ui/dialogs/content/EdListProps.xul59
-rw-r--r--editor/ui/dialogs/content/EdNamedAnchorProps.js164
-rw-r--r--editor/ui/dialogs/content/EdNamedAnchorProps.xul35
-rw-r--r--editor/ui/dialogs/content/EdPageProps.js166
-rw-r--r--editor/ui/dialogs/content/EdPageProps.xul57
-rw-r--r--editor/ui/dialogs/content/EdReplace.js380
-rw-r--r--editor/ui/dialogs/content/EdReplace.xul66
-rw-r--r--editor/ui/dialogs/content/EdSelectProps.js752
-rw-r--r--editor/ui/dialogs/content/EdSelectProps.xul129
-rw-r--r--editor/ui/dialogs/content/EdSpellCheck.js522
-rw-r--r--editor/ui/dialogs/content/EdSpellCheck.xul115
-rw-r--r--editor/ui/dialogs/content/EdTableProps.js1273
-rw-r--r--editor/ui/dialogs/content/EdTableProps.xul266
-rw-r--r--editor/ui/dialogs/content/EdTextAreaProps.js168
-rw-r--r--editor/ui/dialogs/content/EdTextAreaProps.xul103
-rw-r--r--editor/ui/editorUtilities.jsm13
-rw-r--r--editor/ui/jar.mn81
-rw-r--r--editor/ui/locales/en-US/chrome/composer/editor.properties208
-rw-r--r--editor/ui/locales/en-US/chrome/composer/editorOverlay.dtd346
-rw-r--r--editor/ui/locales/en-US/chrome/composer/editorSmileyOverlay.dtd58
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EdAdvancedEdit.dtd18
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EdColorPicker.dtd22
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EdConvertToTable.dtd15
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EdDialogOverlay.dtd18
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EdNamedAnchorProperties.dtd10
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorButtonProperties.dtd27
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorColorProperties.dtd28
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorFieldSetProperties.dtd20
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorFormProperties.dtd21
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorHLineProperties.dtd27
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorImageProperties.dtd79
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorInputProperties.dtd50
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorInsertChars.dtd19
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorInsertMath.dtd21
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorInsertSource.dtd15
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorInsertTOC.dtd16
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorInsertTable.dtd18
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorLabelProperties.dtd18
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorLinkProperties.dtd6
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorListProperties.dtd20
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorPersonalDictionary.dtd20
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorReplace.dtd26
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorSelectProperties.dtd48
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorSpellCheck.dtd38
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorTableProperties.dtd75
-rw-r--r--editor/ui/locales/en-US/chrome/dialogs/EditorTextAreaProperties.dtd33
-rw-r--r--editor/ui/locales/jar.mn38
-rw-r--r--editor/ui/locales/moz.build6
-rw-r--r--editor/ui/moz.build8
-rw-r--r--editor/ui/texzilla/content/TeXZilla.js815
876 files changed, 0 insertions, 142866 deletions
diff --git a/editor/AsyncSpellCheckTestHelper.jsm b/editor/AsyncSpellCheckTestHelper.jsm
deleted file mode 100644
index 99aa14bd3..000000000
--- a/editor/AsyncSpellCheckTestHelper.jsm
+++ /dev/null
@@ -1,86 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-this.EXPORTED_SYMBOLS = [
- "onSpellCheck",
-];
-
-const SPELL_CHECK_ENDED_TOPIC = "inlineSpellChecker-spellCheck-ended";
-const SPELL_CHECK_STARTED_TOPIC = "inlineSpellChecker-spellCheck-started";
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-/**
- * Waits until spell checking has stopped on the given element.
- *
- * When a spell check is pending, this waits indefinitely until the spell check
- * ends. When a spell check is not pending, it waits a small number of turns of
- * the event loop: if a spell check begins, it resumes waiting indefinitely for
- * the end, and otherwise it stops waiting and calls the callback.
- *
- * This this can therefore trap spell checks that have not started at the time
- * of calling, spell checks that have already started, multiple consecutive
- * spell checks, and the absence of spell checks altogether.
- *
- * @param editableElement The element being spell checked.
- * @param callback Called when spell check has completed or enough turns
- * of the event loop have passed to determine it has not
- * started.
- */
-function onSpellCheck(editableElement, callback) {
- let editor = editableElement.editor;
- if (!editor) {
- let win = editableElement.ownerDocument.defaultView;
- editor = win.QueryInterface(Ci.nsIInterfaceRequestor).
- getInterface(Ci.nsIWebNavigation).
- QueryInterface(Ci.nsIInterfaceRequestor).
- getInterface(Ci.nsIEditingSession).
- getEditorForWindow(win);
- }
- if (!editor)
- throw new Error("Unable to find editor for element " + editableElement);
-
- try {
- // False is important here. Pass false so that the inline spell checker
- // isn't created if it doesn't already exist.
- var isc = editor.getInlineSpellChecker(false);
- }
- catch (err) {
- // getInlineSpellChecker throws if spell checking is not enabled instead of
- // just returning null, which seems kind of lame. (Spell checking is not
- // enabled on Android.) The point here is only to determine whether spell
- // check is pending, and if getInlineSpellChecker throws, then it's not
- // pending.
- }
- let waitingForEnded = isc && isc.spellCheckPending;
- let count = 0;
-
- function observe(subj, topic, data) {
- if (subj != editor)
- return;
- count = 0;
- let expectedTopic = waitingForEnded ? SPELL_CHECK_ENDED_TOPIC :
- SPELL_CHECK_STARTED_TOPIC;
- if (topic != expectedTopic)
- Cu.reportError("Expected " + expectedTopic + " but got " + topic + "!");
- waitingForEnded = !waitingForEnded;
- }
-
- let os = Cc["@mozilla.org/observer-service;1"].
- getService(Ci.nsIObserverService);
- os.addObserver(observe, SPELL_CHECK_STARTED_TOPIC, false);
- os.addObserver(observe, SPELL_CHECK_ENDED_TOPIC, false);
-
- let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- timer.init(function tick() {
- // Wait an arbitrarily large number -- 50 -- turns of the event loop before
- // declaring that no spell checks will start.
- if (waitingForEnded || ++count < 50)
- return;
- timer.cancel();
- os.removeObserver(observe, SPELL_CHECK_STARTED_TOPIC);
- os.removeObserver(observe, SPELL_CHECK_ENDED_TOPIC);
- callback();
- }, 0, Ci.nsITimer.TYPE_REPEATING_SLACK);
-};
diff --git a/editor/composer/crashtests/351236-1.html b/editor/composer/crashtests/351236-1.html
deleted file mode 100644
index 22133a215..000000000
--- a/editor/composer/crashtests/351236-1.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<html><head>
-<title>Testcase bug 351236 - Crash [@ nsGetInterface::operator()] with designMode iframes, removing styles, removing iframes, reloading, etc</title>
-<script>
-function designmodes(i){
-try {
-window.frames[0].document.designMode='on';
-window.frames[0].focus();
-window.frames[0].getSelection().collapse(window.frames[0].document.body.childNodes[0],window.frames[0].document.body.childNodes[0].length-2)
-window.frames[0].document.execCommand('inserthtml', false, 'tesxt ');
-} catch(e) {}
-
-setTimeout(designmodes,50);
-}
-
-function removestyles(){
-document.getElementsByTagName('iframe')[0].removeAttribute('style');
-document.getElementsByTagName('q')[0].removeAttribute('style');
-}
-
-function doe() {
-setTimeout(designmodes,200);
-setTimeout(removestyles,500);
-setTimeout(function() {document.removeChild(document.documentElement);}, 1000);
-setTimeout(function() {window.location.reload();}, 1500);
-}
-window.onload=doe;
-</script>
-
-</head>
-<body>
-This page should not crash Mozilla within 2 seconds<br>
-<q style="display: table-row;">
-<iframe style="display: table-row;"></iframe>
-<iframe></iframe>
-</q>
-</body>
-</html> \ No newline at end of file
diff --git a/editor/composer/crashtests/407062-1.html b/editor/composer/crashtests/407062-1.html
deleted file mode 100644
index 81083c235..000000000
--- a/editor/composer/crashtests/407062-1.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<html contentEditable="true">
-<head>
-
-<script type="text/javascript">
-
-function boom()
-{
- var r = document.documentElement;
- while(r.firstChild)
- r.removeChild(r.firstChild);
-
- document.execCommand("contentReadOnly", false, "");
- document.documentElement.focus();
-}
-
-</script>
-</head>
-
-<body onload="boom();"></body>
-</html>
diff --git a/editor/composer/crashtests/419563-1.xhtml b/editor/composer/crashtests/419563-1.xhtml
deleted file mode 100644
index 417530c13..000000000
--- a/editor/composer/crashtests/419563-1.xhtml
+++ /dev/null
@@ -1,20 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
-<head>
-<script type="text/javascript">
-
-function boom()
-{
- document.documentElement.appendChild(document.body);
- document.getElementById("s").contentEditable = "true";
- document.getElementById("v").focus();
- document.body.focus();
- document.execCommand("delete", false, null);
- document.documentElement.removeAttribute("class");
-}
-
-</script>
-</head>
-
-<span id="s">thesewords arenot realwords</span><body contenteditable="true" onload="setTimeout(boom, 0);"><span contenteditable="false"><div id="v" contenteditable="true"></div>Five</span></body>
-
-</html>
diff --git a/editor/composer/crashtests/428844-1-inner.xhtml b/editor/composer/crashtests/428844-1-inner.xhtml
deleted file mode 100644
index 1cc72d085..000000000
--- a/editor/composer/crashtests/428844-1-inner.xhtml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml-stylesheet type="text/xsl" href="#a"?>
-<html xmlns="http://www.w3.org/1999/xhtml" onload="dump('Inner onload\n'); window.location.reload()" contenteditable="true">
-<xsl:stylesheet version="1.0" id="a" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/>
-</html>
diff --git a/editor/composer/crashtests/428844-1.html b/editor/composer/crashtests/428844-1.html
deleted file mode 100644
index 8bebdbf4b..000000000
--- a/editor/composer/crashtests/428844-1.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<html class="reftest-wait">
-<head>
-<script>
-function boom() {
- var iframe = document.getElementById('inner');
- iframe.addEventListener("load", function() {
- document.documentElement.removeAttribute("class");
- }, false);
- iframe.src = "data:text/html,";
- dump("Outer onload\n");
-}
-</script>
-</head>
-<body onload="boom()">
-<iframe src="428844-1-inner.xhtml" id="inner"></iframe>
-</body>
-</html>
diff --git a/editor/composer/crashtests/461049-1.html b/editor/composer/crashtests/461049-1.html
deleted file mode 100644
index c25ed991f..000000000
--- a/editor/composer/crashtests/461049-1.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script type="text/javascript">
-
-function uu()
-{
- document.removeEventListener("DOMSubtreeModified", uu, false);
- document.execCommand("undo", false, null);
-}
-
-function boom()
-{
- document.execCommand("selectAll", false, null);
- document.execCommand("strikethrough", false, null);
- document.addEventListener("DOMSubtreeModified", uu, false);
- document.execCommand("undo", false, null);
-}
-
-</script>
-</head>
-
-<body contenteditable="true" onload="boom();"><div></div></body>
-
-</html>
diff --git a/editor/composer/crashtests/crashtests.list b/editor/composer/crashtests/crashtests.list
deleted file mode 100644
index db84e0e5b..000000000
--- a/editor/composer/crashtests/crashtests.list
+++ /dev/null
@@ -1,6 +0,0 @@
-load 351236-1.html
-load 407062-1.html
-load 419563-1.xhtml
-load 428844-1.html
-load 461049-1.html
-load removing-editable-xslt.html
diff --git a/editor/composer/crashtests/removing-editable-xslt-inner.xhtml b/editor/composer/crashtests/removing-editable-xslt-inner.xhtml
deleted file mode 100644
index cbf206d7e..000000000
--- a/editor/composer/crashtests/removing-editable-xslt-inner.xhtml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml-stylesheet type="text/xsl" href="#a"?>
-<html xmlns="http://www.w3.org/1999/xhtml" contenteditable="true">
-<xsl:stylesheet version="1.0" id="a" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/>
-</html>
diff --git a/editor/composer/crashtests/removing-editable-xslt.html b/editor/composer/crashtests/removing-editable-xslt.html
deleted file mode 100644
index cbf104ac9..000000000
--- a/editor/composer/crashtests/removing-editable-xslt.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<html class="reftest-wait">
-<head>
-<script>
-function boom()
-{
- document.getElementById("i").src = "removing-editable-xslt-inner.xhtml";
- setTimeout(function() {
- document.body.removeChild(document.getElementById("i"));
- document.documentElement.removeAttribute("class");
- }, 0);
-}
-</script>
-</head>
-<body onload="boom();">
-<iframe id="i"></iframe>
-</body>
-</html>
diff --git a/editor/composer/moz.build b/editor/composer/moz.build
deleted file mode 100644
index 8da0e1f32..000000000
--- a/editor/composer/moz.build
+++ /dev/null
@@ -1,52 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-MOCHITEST_MANIFESTS += ['test/mochitest.ini']
-
-MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
-
-XPIDL_SOURCES += [
- 'nsIEditingSession.idl',
-]
-
-XPIDL_MODULE = 'composer'
-
-SOURCES += [
- 'nsComposerCommands.cpp',
- 'nsComposerCommandsUpdater.cpp',
- 'nsComposerController.cpp',
- 'nsComposerDocumentCommands.cpp',
- 'nsComposerRegistration.cpp',
- 'nsComposeTxtSrvFilter.cpp',
- 'nsEditingSession.cpp',
- 'nsEditorSpellCheck.cpp',
-]
-
-FINAL_LIBRARY = 'xul'
-RESOURCE_FILES += [
- 'res/EditorOverride.css',
- 'res/grabber.gif',
- 'res/table-add-column-after-active.gif',
- 'res/table-add-column-after-hover.gif',
- 'res/table-add-column-after.gif',
- 'res/table-add-column-before-active.gif',
- 'res/table-add-column-before-hover.gif',
- 'res/table-add-column-before.gif',
- 'res/table-add-row-after-active.gif',
- 'res/table-add-row-after-hover.gif',
- 'res/table-add-row-after.gif',
- 'res/table-add-row-before-active.gif',
- 'res/table-add-row-before-hover.gif',
- 'res/table-add-row-before.gif',
- 'res/table-remove-column-active.gif',
- 'res/table-remove-column-hover.gif',
- 'res/table-remove-column.gif',
- 'res/table-remove-row-active.gif',
- 'res/table-remove-row-hover.gif',
- 'res/table-remove-row.gif',
-]
-
-if CONFIG['GNU_CXX']:
- CXXFLAGS += ['-Wno-error=shadow']
diff --git a/editor/composer/nsComposeTxtSrvFilter.cpp b/editor/composer/nsComposeTxtSrvFilter.cpp
deleted file mode 100644
index ba66bca95..000000000
--- a/editor/composer/nsComposeTxtSrvFilter.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsComposeTxtSrvFilter.h"
-#include "nsError.h" // for NS_OK
-#include "nsIContent.h" // for nsIContent
-#include "nsIDOMNode.h" // for nsIDOMNode
-#include "nsNameSpaceManager.h" // for kNameSpaceID_None
-#include "nsLiteralString.h" // for NS_LITERAL_STRING
-#include "nscore.h" // for NS_IMETHODIMP
-
-nsComposeTxtSrvFilter::nsComposeTxtSrvFilter() :
- mIsForMail(false)
-{
-}
-
-NS_IMPL_ISUPPORTS(nsComposeTxtSrvFilter, nsITextServicesFilter)
-
-NS_IMETHODIMP
-nsComposeTxtSrvFilter::Skip(nsIDOMNode* aNode, bool *_retval)
-{
- *_retval = false;
-
- // Check to see if we can skip this node
- // For nodes that are blockquotes, we must make sure
- // their type is "cite"
- nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
- if (content) {
- if (content->IsHTMLElement(nsGkAtoms::blockquote)) {
- if (mIsForMail) {
- *_retval = content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
- nsGkAtoms::cite, eIgnoreCase);
- }
- } else if (content->IsHTMLElement(nsGkAtoms::span)) {
- if (mIsForMail) {
- *_retval = content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mozquote,
- nsGkAtoms::_true, eIgnoreCase);
- if (!*_retval) {
- *_retval = content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::_class,
- nsGkAtoms::mozsignature, eCaseMatters);
- }
- }
- } else if (content->IsAnyOfHTMLElements(nsGkAtoms::script,
- nsGkAtoms::textarea,
- nsGkAtoms::select,
- nsGkAtoms::style,
- nsGkAtoms::map)) {
- *_retval = true;
- } else if (content->IsHTMLElement(nsGkAtoms::table)) {
- if (mIsForMail) {
- *_retval =
- content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::_class,
- NS_LITERAL_STRING("moz-email-headers-table"),
- eCaseMatters);
- }
- }
- }
-
- return NS_OK;
-}
diff --git a/editor/composer/nsComposeTxtSrvFilter.h b/editor/composer/nsComposeTxtSrvFilter.h
deleted file mode 100644
index 0e5bba433..000000000
--- a/editor/composer/nsComposeTxtSrvFilter.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsComposeTxtSrvFilter_h__
-#define nsComposeTxtSrvFilter_h__
-
-#include "nsISupportsImpl.h" // for NS_DECL_ISUPPORTS
-#include "nsITextServicesFilter.h"
-
-/**
- * This class implements a filter interface, that enables
- * those using it to skip over certain nodes when traversing content
- *
- * This filter is used to skip over various form control nodes and
- * mail's cite nodes
- */
-class nsComposeTxtSrvFilter final : public nsITextServicesFilter
-{
-public:
- nsComposeTxtSrvFilter();
-
- // nsISupports interface...
- NS_DECL_ISUPPORTS
-
- // nsITextServicesFilter
- NS_DECL_NSITEXTSERVICESFILTER
-
- // Helper - Intializer
- void Init(bool aIsForMail) { mIsForMail = aIsForMail; }
-
-private:
- ~nsComposeTxtSrvFilter() {}
-
- bool mIsForMail;
-};
-
-#define NS_COMPOSERTXTSRVFILTER_CID \
-{/* {171E72DB-0F8A-412a-8461-E4C927A3A2AC}*/ \
-0x171e72db, 0xf8a, 0x412a, \
-{ 0x84, 0x61, 0xe4, 0xc9, 0x27, 0xa3, 0xa2, 0xac} }
-
-#define NS_COMPOSERTXTSRVFILTERMAIL_CID \
-{/* {7FBD2146-5FF4-4674-B069-A7BBCE66E773}*/ \
-0x7fbd2146, 0x5ff4, 0x4674, \
-{ 0xb0, 0x69, 0xa7, 0xbb, 0xce, 0x66, 0xe7, 0x73} }
-
-// Generic for the editor
-#define COMPOSER_TXTSRVFILTER_CONTRACTID "@mozilla.org/editor/txtsrvfilter;1"
-
-// This is the same but includes "cite" typed blocked quotes
-#define COMPOSER_TXTSRVFILTERMAIL_CONTRACTID "@mozilla.org/editor/txtsrvfiltermail;1"
-
-#endif
diff --git a/editor/composer/nsComposerCommands.cpp b/editor/composer/nsComposerCommands.cpp
deleted file mode 100644
index 3853604e4..000000000
--- a/editor/composer/nsComposerCommands.cpp
+++ /dev/null
@@ -1,1525 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-#include <stdio.h> // for printf
-
-#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
-#include "nsAString.h"
-#include "nsCOMPtr.h" // for nsCOMPtr, do_QueryInterface, etc
-#include "nsComponentManagerUtils.h" // for do_CreateInstance
-#include "nsComposerCommands.h"
-#include "nsDebug.h" // for NS_ENSURE_TRUE, etc
-#include "nsError.h" // for NS_OK, NS_ERROR_FAILURE, etc
-#include "nsGkAtoms.h" // for nsGkAtoms, nsGkAtoms::font, etc
-#include "nsIAtom.h" // for nsIAtom, etc
-#include "nsIClipboard.h" // for nsIClipboard, etc
-#include "nsICommandParams.h" // for nsICommandParams, etc
-#include "nsID.h"
-#include "nsIDOMElement.h" // for nsIDOMElement
-#include "nsIEditor.h" // for nsIEditor
-#include "nsIHTMLAbsPosEditor.h" // for nsIHTMLAbsPosEditor
-#include "nsIHTMLEditor.h" // for nsIHTMLEditor, etc
-#include "nsLiteralString.h" // for NS_LITERAL_STRING
-#include "nsReadableUtils.h" // for EmptyString
-#include "nsString.h" // for nsAutoString, nsString, etc
-#include "nsStringFwd.h" // for nsAFlatString
-
-class nsISupports;
-
-//prototype
-nsresult GetListState(nsIHTMLEditor* aEditor, bool* aMixed,
- nsAString& aLocalName);
-nsresult RemoveOneProperty(nsIHTMLEditor* aEditor, const nsAString& aProp);
-nsresult RemoveTextProperty(nsIHTMLEditor* aEditor, const nsAString& aProp);
-nsresult SetTextProperty(nsIHTMLEditor *aEditor, const nsAString& aProp);
-
-
-//defines
-#define STATE_ENABLED "state_enabled"
-#define STATE_ALL "state_all"
-#define STATE_ANY "state_any"
-#define STATE_MIXED "state_mixed"
-#define STATE_BEGIN "state_begin"
-#define STATE_END "state_end"
-#define STATE_ATTRIBUTE "state_attribute"
-#define STATE_DATA "state_data"
-
-
-nsBaseComposerCommand::nsBaseComposerCommand()
-{
-}
-
-NS_IMPL_ISUPPORTS(nsBaseComposerCommand, nsIControllerCommand)
-
-
-nsBaseStateUpdatingCommand::nsBaseStateUpdatingCommand(nsIAtom* aTagName)
-: nsBaseComposerCommand()
-, mTagName(aTagName)
-{
- MOZ_ASSERT(mTagName);
-}
-
-nsBaseStateUpdatingCommand::~nsBaseStateUpdatingCommand()
-{
-}
-
-NS_IMPL_ISUPPORTS_INHERITED0(nsBaseStateUpdatingCommand, nsBaseComposerCommand)
-
-NS_IMETHODIMP
-nsBaseStateUpdatingCommand::IsCommandEnabled(const char *aCommandName,
- nsISupports *refCon,
- bool *outCmdEnabled)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- if (editor)
- return editor->GetIsSelectionEditable(outCmdEnabled);
-
- *outCmdEnabled = false;
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsBaseStateUpdatingCommand::DoCommand(const char *aCommandName,
- nsISupports *refCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(editor, NS_ERROR_NOT_INITIALIZED);
-
- return ToggleState(editor);
-}
-
-NS_IMETHODIMP
-nsBaseStateUpdatingCommand::DoCommandParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- return DoCommand(aCommandName, refCon);
-}
-
-NS_IMETHODIMP
-nsBaseStateUpdatingCommand::GetCommandStateParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- if (editor)
- return GetCurrentState(editor, aParams);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsPasteNoFormattingCommand::IsCommandEnabled(const char * aCommandName,
- nsISupports *refCon,
- bool *outCmdEnabled)
-{
- NS_ENSURE_ARG_POINTER(outCmdEnabled);
- *outCmdEnabled = false;
-
- // This command is only implemented by nsIHTMLEditor, since
- // pasting in a plaintext editor automatically only supplies
- // "unformatted" text
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NOT_IMPLEMENTED);
-
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(htmlEditor);
- NS_ENSURE_TRUE(editor, NS_ERROR_INVALID_ARG);
-
- return editor->CanPaste(nsIClipboard::kGlobalClipboard, outCmdEnabled);
-}
-
-
-NS_IMETHODIMP
-nsPasteNoFormattingCommand::DoCommand(const char *aCommandName,
- nsISupports *refCon)
-{
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NOT_IMPLEMENTED);
-
- return htmlEditor->PasteNoFormatting(nsIClipboard::kGlobalClipboard);
-}
-
-NS_IMETHODIMP
-nsPasteNoFormattingCommand::DoCommandParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- return DoCommand(aCommandName, refCon);
-}
-
-NS_IMETHODIMP
-nsPasteNoFormattingCommand::GetCommandStateParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- NS_ENSURE_ARG_POINTER(aParams);
-
- bool enabled = false;
- nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return aParams->SetBooleanValue(STATE_ENABLED, enabled);
-}
-
-nsStyleUpdatingCommand::nsStyleUpdatingCommand(nsIAtom* aTagName)
-: nsBaseStateUpdatingCommand(aTagName)
-{
-}
-
-nsresult
-nsStyleUpdatingCommand::GetCurrentState(nsIEditor *aEditor,
- nsICommandParams *aParams)
-{
- NS_ASSERTION(aEditor, "Need editor here");
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NOT_INITIALIZED);
-
- bool firstOfSelectionHasProp = false;
- bool anyOfSelectionHasProp = false;
- bool allOfSelectionHasProp = false;
-
- nsresult rv = htmlEditor->GetInlineProperty(mTagName, EmptyString(),
- EmptyString(),
- &firstOfSelectionHasProp,
- &anyOfSelectionHasProp,
- &allOfSelectionHasProp);
-
- aParams->SetBooleanValue(STATE_ENABLED, NS_SUCCEEDED(rv));
- aParams->SetBooleanValue(STATE_ALL, allOfSelectionHasProp);
- aParams->SetBooleanValue(STATE_ANY, anyOfSelectionHasProp);
- aParams->SetBooleanValue(STATE_MIXED, anyOfSelectionHasProp
- && !allOfSelectionHasProp);
- aParams->SetBooleanValue(STATE_BEGIN, firstOfSelectionHasProp);
- aParams->SetBooleanValue(STATE_END, allOfSelectionHasProp);//not completely accurate
- return NS_OK;
-}
-
-nsresult
-nsStyleUpdatingCommand::ToggleState(nsIEditor *aEditor)
-{
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NO_INTERFACE);
-
- //create some params now...
- nsresult rv;
- nsCOMPtr<nsICommandParams> params =
- do_CreateInstance(NS_COMMAND_PARAMS_CONTRACTID,&rv);
- if (NS_FAILED(rv) || !params)
- return rv;
-
- // tags "href" and "name" are special cases in the core editor
- // they are used to remove named anchor/link and shouldn't be used for insertion
- bool doTagRemoval;
- if (mTagName == nsGkAtoms::href || mTagName == nsGkAtoms::name) {
- doTagRemoval = true;
- } else {
- // check current selection; set doTagRemoval if formatting should be removed
- rv = GetCurrentState(aEditor, params);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = params->GetBooleanValue(STATE_ALL, &doTagRemoval);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- if (doTagRemoval) {
- // Also remove equivalent properties (bug 317093)
- if (mTagName == nsGkAtoms::b) {
- rv = RemoveTextProperty(htmlEditor, NS_LITERAL_STRING("strong"));
- NS_ENSURE_SUCCESS(rv, rv);
- } else if (mTagName == nsGkAtoms::i) {
- rv = RemoveTextProperty(htmlEditor, NS_LITERAL_STRING("em"));
- NS_ENSURE_SUCCESS(rv, rv);
- } else if (mTagName == nsGkAtoms::strike) {
- rv = RemoveTextProperty(htmlEditor, NS_LITERAL_STRING("s"));
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- rv = RemoveTextProperty(htmlEditor, nsDependentAtomString(mTagName));
- } else {
- // Superscript and Subscript styles are mutually exclusive
- aEditor->BeginTransaction();
-
- nsDependentAtomString tagName(mTagName);
- if (mTagName == nsGkAtoms::sub || mTagName == nsGkAtoms::sup) {
- rv = RemoveTextProperty(htmlEditor, tagName);
- }
- if (NS_SUCCEEDED(rv))
- rv = SetTextProperty(htmlEditor, tagName);
-
- aEditor->EndTransaction();
- }
-
- return rv;
-}
-
-nsListCommand::nsListCommand(nsIAtom* aTagName)
-: nsBaseStateUpdatingCommand(aTagName)
-{
-}
-
-nsresult
-nsListCommand::GetCurrentState(nsIEditor* aEditor, nsICommandParams* aParams)
-{
- NS_ASSERTION(aEditor, "Need editor here");
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NO_INTERFACE);
-
- bool bMixed;
- nsAutoString localName;
- nsresult rv = GetListState(htmlEditor, &bMixed, localName);
- NS_ENSURE_SUCCESS(rv, rv);
-
- bool inList = mTagName->Equals(localName);
- aParams->SetBooleanValue(STATE_ALL, !bMixed && inList);
- aParams->SetBooleanValue(STATE_MIXED, bMixed);
- aParams->SetBooleanValue(STATE_ENABLED, true);
- return NS_OK;
-}
-
-nsresult
-nsListCommand::ToggleState(nsIEditor *aEditor)
-{
- nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(editor, NS_NOINTERFACE);
-
- nsresult rv;
- nsCOMPtr<nsICommandParams> params =
- do_CreateInstance(NS_COMMAND_PARAMS_CONTRACTID,&rv);
- if (NS_FAILED(rv) || !params)
- return rv;
-
- rv = GetCurrentState(aEditor, params);
- NS_ENSURE_SUCCESS(rv, rv);
-
- bool inList;
- rv = params->GetBooleanValue(STATE_ALL,&inList);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsDependentAtomString listType(mTagName);
- if (inList) {
- rv = editor->RemoveList(listType);
- } else {
- rv = editor->MakeOrChangeList(listType, false, EmptyString());
- }
-
- return rv;
-}
-
-nsListItemCommand::nsListItemCommand(nsIAtom* aTagName)
-: nsBaseStateUpdatingCommand(aTagName)
-{
-}
-
-nsresult
-nsListItemCommand::GetCurrentState(nsIEditor* aEditor,
- nsICommandParams *aParams)
-{
- NS_ASSERTION(aEditor, "Need editor here");
- // 39584
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_NOINTERFACE);
-
- bool bMixed, bLI, bDT, bDD;
- nsresult rv = htmlEditor->GetListItemState(&bMixed, &bLI, &bDT, &bDD);
- NS_ENSURE_SUCCESS(rv, rv);
-
- bool inList = false;
- if (!bMixed) {
- if (bLI) {
- inList = mTagName == nsGkAtoms::li;
- } else if (bDT) {
- inList = mTagName == nsGkAtoms::dt;
- } else if (bDD) {
- inList = mTagName == nsGkAtoms::dd;
- }
- }
-
- aParams->SetBooleanValue(STATE_ALL, !bMixed && inList);
- aParams->SetBooleanValue(STATE_MIXED, bMixed);
-
- return NS_OK;
-}
-
-nsresult
-nsListItemCommand::ToggleState(nsIEditor *aEditor)
-{
- NS_ASSERTION(aEditor, "Need editor here");
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NOT_INITIALIZED);
-
- bool inList;
- // Need to use mTagName????
- nsresult rv;
- nsCOMPtr<nsICommandParams> params =
- do_CreateInstance(NS_COMMAND_PARAMS_CONTRACTID,&rv);
- if (NS_FAILED(rv) || !params)
- return rv;
- rv = GetCurrentState(aEditor, params);
- rv = params->GetBooleanValue(STATE_ALL,&inList);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (inList) {
- // To remove a list, first get what kind of list we're in
- bool bMixed;
- nsAutoString localName;
- rv = GetListState(htmlEditor, &bMixed, localName);
- NS_ENSURE_SUCCESS(rv, rv);
- if (localName.IsEmpty() || bMixed) {
- return rv;
- }
- return htmlEditor->RemoveList(localName);
- }
-
- // Set to the requested paragraph type
- //XXX Note: This actually doesn't work for "LI",
- // but we currently don't use this for non DL lists anyway.
- // Problem: won't this replace any current block paragraph style?
- return htmlEditor->SetParagraphFormat(nsDependentAtomString(mTagName));
-}
-
-NS_IMETHODIMP
-nsRemoveListCommand::IsCommandEnabled(const char * aCommandName,
- nsISupports *refCon,
- bool *outCmdEnabled)
-{
- *outCmdEnabled = false;
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(editor, NS_OK);
-
- bool isEditable = false;
- nsresult rv = editor->GetIsSelectionEditable(&isEditable);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!isEditable) {
- return NS_OK;
- }
-
- // It is enabled if we are in any list type
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NO_INTERFACE);
-
- bool bMixed;
- nsAutoString localName;
- rv = GetListState(htmlEditor, &bMixed, localName);
- NS_ENSURE_SUCCESS(rv, rv);
-
- *outCmdEnabled = bMixed || !localName.IsEmpty();
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsRemoveListCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
-{
- nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
-
- nsresult rv = NS_OK;
- if (editor) {
- // This removes any list type
- rv = editor->RemoveList(EmptyString());
- }
-
- return rv;
-}
-
-NS_IMETHODIMP
-nsRemoveListCommand::DoCommandParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- return DoCommand(aCommandName, refCon);
-}
-
-NS_IMETHODIMP
-nsRemoveListCommand::GetCommandStateParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- bool outCmdEnabled = false;
- IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
- return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled);
-}
-
-NS_IMETHODIMP
-nsIndentCommand::IsCommandEnabled(const char * aCommandName,
- nsISupports *refCon, bool *outCmdEnabled)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- if (editor)
- return editor->GetIsSelectionEditable(outCmdEnabled);
-
- *outCmdEnabled = false;
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsIndentCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
-{
- nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
-
- nsresult rv = NS_OK;
- if (editor) {
- rv = editor->Indent(NS_LITERAL_STRING("indent"));
- }
-
- return rv;
-}
-
-NS_IMETHODIMP
-nsIndentCommand::DoCommandParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- return DoCommand(aCommandName, refCon);
-}
-
-NS_IMETHODIMP
-nsIndentCommand::GetCommandStateParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- bool outCmdEnabled = false;
- IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
- return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled);
-}
-
-
-//OUTDENT
-
-NS_IMETHODIMP
-nsOutdentCommand::IsCommandEnabled(const char * aCommandName,
- nsISupports *refCon,
- bool *outCmdEnabled)
-{
- *outCmdEnabled = false;
-
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- if (editor) {
- nsresult rv = editor->GetIsSelectionEditable(outCmdEnabled);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsOutdentCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
-{
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(refCon);
- if (htmlEditor)
- return htmlEditor->Indent(NS_LITERAL_STRING("outdent"));
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsOutdentCommand::DoCommandParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- return DoCommand(aCommandName, refCon);
-}
-
-NS_IMETHODIMP
-nsOutdentCommand::GetCommandStateParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- bool outCmdEnabled = false;
- IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
- return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled);
-}
-
-nsMultiStateCommand::nsMultiStateCommand()
-: nsBaseComposerCommand()
-{
-}
-
-nsMultiStateCommand::~nsMultiStateCommand()
-{
-}
-
-NS_IMPL_ISUPPORTS_INHERITED0(nsMultiStateCommand, nsBaseComposerCommand)
-
-NS_IMETHODIMP
-nsMultiStateCommand::IsCommandEnabled(const char * aCommandName,
- nsISupports *refCon,
- bool *outCmdEnabled)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- // should be disabled sometimes, like if the current selection is an image
- if (editor)
- return editor->GetIsSelectionEditable(outCmdEnabled);
-
- *outCmdEnabled = false;
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsMultiStateCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
-{
-#ifdef DEBUG
- printf("who is calling nsMultiStateCommand::DoCommand \
- (no implementation)? %s\n", aCommandName);
-#endif
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsMultiStateCommand::DoCommandParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-
- nsresult rv = NS_OK;
- if (editor) {
- nsAutoString tString;
-
- if (aParams) {
- nsXPIDLCString s;
- rv = aParams->GetCStringValue(STATE_ATTRIBUTE, getter_Copies(s));
- if (NS_SUCCEEDED(rv))
- tString.AssignWithConversion(s);
- else
- rv = aParams->GetStringValue(STATE_ATTRIBUTE, tString);
- }
-
- rv = SetState(editor, tString);
- }
-
- return rv;
-}
-
-NS_IMETHODIMP
-nsMultiStateCommand::GetCommandStateParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- nsresult rv = NS_OK;
- if (editor) {
- rv = GetCurrentState(editor, aParams);
- }
- return rv;
-}
-
-nsParagraphStateCommand::nsParagraphStateCommand()
-: nsMultiStateCommand()
-{
-}
-
-nsresult
-nsParagraphStateCommand::GetCurrentState(nsIEditor *aEditor,
- nsICommandParams *aParams)
-{
- NS_ASSERTION(aEditor, "Need an editor here");
-
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
-
- bool outMixed;
- nsAutoString outStateString;
- nsresult rv = htmlEditor->GetParagraphState(&outMixed, outStateString);
- if (NS_SUCCEEDED(rv)) {
- nsAutoCString tOutStateString;
- tOutStateString.AssignWithConversion(outStateString);
- aParams->SetBooleanValue(STATE_MIXED,outMixed);
- aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
- }
- return rv;
-}
-
-
-nsresult
-nsParagraphStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
-{
- NS_ASSERTION(aEditor, "Need an editor here");
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
-
- return htmlEditor->SetParagraphFormat(newState);
-}
-
-nsFontFaceStateCommand::nsFontFaceStateCommand()
-: nsMultiStateCommand()
-{
-}
-
-nsresult
-nsFontFaceStateCommand::GetCurrentState(nsIEditor *aEditor,
- nsICommandParams *aParams)
-{
- NS_ASSERTION(aEditor, "Need an editor here");
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
-
- nsAutoString outStateString;
- bool outMixed;
- nsresult rv = htmlEditor->GetFontFaceState(&outMixed, outStateString);
- if (NS_SUCCEEDED(rv)) {
- aParams->SetBooleanValue(STATE_MIXED,outMixed);
- aParams->SetCStringValue(STATE_ATTRIBUTE, NS_ConvertUTF16toUTF8(outStateString).get());
- }
- return rv;
-}
-
-
-nsresult
-nsFontFaceStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
-{
- NS_ASSERTION(aEditor, "Need an editor here");
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
-
- if (newState.EqualsLiteral("tt")) {
- // The old "teletype" attribute
- nsresult rv = htmlEditor->SetInlineProperty(nsGkAtoms::tt, EmptyString(),
- EmptyString());
- NS_ENSURE_SUCCESS(rv, rv);
- // Clear existing font face
- return htmlEditor->RemoveInlineProperty(nsGkAtoms::font,
- NS_LITERAL_STRING("face"));
- }
-
- // Remove any existing TT nodes
- nsresult rv = htmlEditor->RemoveInlineProperty(nsGkAtoms::tt, EmptyString());
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (newState.IsEmpty() || newState.EqualsLiteral("normal")) {
- return htmlEditor->RemoveInlineProperty(nsGkAtoms::font,
- NS_LITERAL_STRING("face"));
- }
-
- return htmlEditor->SetInlineProperty(nsGkAtoms::font,
- NS_LITERAL_STRING("face"), newState);
-}
-
-nsFontSizeStateCommand::nsFontSizeStateCommand()
- : nsMultiStateCommand()
-{
-}
-
-// nsAutoCString tOutStateString;
-// tOutStateString.AssignWithConversion(outStateString);
-nsresult
-nsFontSizeStateCommand::GetCurrentState(nsIEditor *aEditor,
- nsICommandParams *aParams)
-{
- NS_ASSERTION(aEditor, "Need an editor here");
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_INVALID_ARG);
-
- nsAutoString outStateString;
- nsCOMPtr<nsIAtom> fontAtom = NS_Atomize("font");
- bool firstHas, anyHas, allHas;
- nsresult rv = htmlEditor->GetInlinePropertyWithAttrValue(fontAtom,
- NS_LITERAL_STRING("size"),
- EmptyString(),
- &firstHas, &anyHas, &allHas,
- outStateString);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsAutoCString tOutStateString;
- tOutStateString.AssignWithConversion(outStateString);
- aParams->SetBooleanValue(STATE_MIXED, anyHas && !allHas);
- aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
- aParams->SetBooleanValue(STATE_ENABLED, true);
-
- return rv;
-}
-
-
-// acceptable values for "newState" are:
-// -2
-// -1
-// 0
-// +1
-// +2
-// +3
-// medium
-// normal
-nsresult
-nsFontSizeStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
-{
- NS_ASSERTION(aEditor, "Need an editor here");
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_INVALID_ARG);
-
- if (!newState.IsEmpty() &&
- !newState.EqualsLiteral("normal") &&
- !newState.EqualsLiteral("medium")) {
- return htmlEditor->SetInlineProperty(nsGkAtoms::font,
- NS_LITERAL_STRING("size"), newState);
- }
-
- // remove any existing font size, big or small
- nsresult rv = htmlEditor->RemoveInlineProperty(nsGkAtoms::font,
- NS_LITERAL_STRING("size"));
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = htmlEditor->RemoveInlineProperty(nsGkAtoms::big, EmptyString());
- NS_ENSURE_SUCCESS(rv, rv);
-
- return htmlEditor->RemoveInlineProperty(nsGkAtoms::small, EmptyString());
-}
-
-nsFontColorStateCommand::nsFontColorStateCommand()
-: nsMultiStateCommand()
-{
-}
-
-nsresult
-nsFontColorStateCommand::GetCurrentState(nsIEditor *aEditor,
- nsICommandParams *aParams)
-{
- NS_ASSERTION(aEditor, "Need an editor here");
-
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
-
- bool outMixed;
- nsAutoString outStateString;
- nsresult rv = htmlEditor->GetFontColorState(&outMixed, outStateString);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsAutoCString tOutStateString;
- tOutStateString.AssignWithConversion(outStateString);
- aParams->SetBooleanValue(STATE_MIXED, outMixed);
- aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
- return NS_OK;
-}
-
-nsresult
-nsFontColorStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
-{
- NS_ASSERTION(aEditor, "Need an editor here");
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
-
- if (newState.IsEmpty() || newState.EqualsLiteral("normal")) {
- return htmlEditor->RemoveInlineProperty(nsGkAtoms::font,
- NS_LITERAL_STRING("color"));
- }
-
- return htmlEditor->SetInlineProperty(nsGkAtoms::font,
- NS_LITERAL_STRING("color"), newState);
-}
-
-nsHighlightColorStateCommand::nsHighlightColorStateCommand()
-: nsMultiStateCommand()
-{
-}
-
-nsresult
-nsHighlightColorStateCommand::GetCurrentState(nsIEditor *aEditor,
- nsICommandParams *aParams)
-{
- NS_ASSERTION(aEditor, "Need an editor here");
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
-
- bool outMixed;
- nsAutoString outStateString;
- nsresult rv = htmlEditor->GetHighlightColorState(&outMixed, outStateString);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsAutoCString tOutStateString;
- tOutStateString.AssignWithConversion(outStateString);
- aParams->SetBooleanValue(STATE_MIXED, outMixed);
- aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
- return NS_OK;
-}
-
-nsresult
-nsHighlightColorStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
-{
- NS_ASSERTION(aEditor, "Need an editor here");
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
-
- if (newState.IsEmpty() || newState.EqualsLiteral("normal")) {
- return htmlEditor->RemoveInlineProperty(nsGkAtoms::font,
- NS_LITERAL_STRING("bgcolor"));
- }
-
- return htmlEditor->SetInlineProperty(nsGkAtoms::font,
- NS_LITERAL_STRING("bgcolor"),
- newState);
-}
-
-NS_IMETHODIMP
-nsHighlightColorStateCommand::IsCommandEnabled(const char * aCommandName,
- nsISupports *refCon,
- bool *outCmdEnabled)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- if (editor)
- return editor->GetIsSelectionEditable(outCmdEnabled);
-
- *outCmdEnabled = false;
- return NS_OK;
-}
-
-
-nsBackgroundColorStateCommand::nsBackgroundColorStateCommand()
-: nsMultiStateCommand()
-{
-}
-
-nsresult
-nsBackgroundColorStateCommand::GetCurrentState(nsIEditor *aEditor,
- nsICommandParams *aParams)
-{
- NS_ASSERTION(aEditor, "Need an editor here");
-
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
-
- bool outMixed;
- nsAutoString outStateString;
- nsresult rv = htmlEditor->GetBackgroundColorState(&outMixed, outStateString);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsAutoCString tOutStateString;
- tOutStateString.AssignWithConversion(outStateString);
- aParams->SetBooleanValue(STATE_MIXED, outMixed);
- aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
- return NS_OK;
-}
-
-nsresult
-nsBackgroundColorStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
-{
- NS_ASSERTION(aEditor, "Need an editor here");
-
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
-
- return htmlEditor->SetBackgroundColor(newState);
-}
-
-nsAlignCommand::nsAlignCommand()
-: nsMultiStateCommand()
-{
-}
-
-nsresult
-nsAlignCommand::GetCurrentState(nsIEditor *aEditor, nsICommandParams *aParams)
-{
- NS_ASSERTION(aEditor, "Need an editor here");
-
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
-
- nsIHTMLEditor::EAlignment firstAlign;
- bool outMixed;
- nsresult rv = htmlEditor->GetAlignment(&outMixed, &firstAlign);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsAutoString outStateString;
- switch (firstAlign) {
- default:
- case nsIHTMLEditor::eLeft:
- outStateString.AssignLiteral("left");
- break;
-
- case nsIHTMLEditor::eCenter:
- outStateString.AssignLiteral("center");
- break;
-
- case nsIHTMLEditor::eRight:
- outStateString.AssignLiteral("right");
- break;
-
- case nsIHTMLEditor::eJustify:
- outStateString.AssignLiteral("justify");
- break;
- }
- nsAutoCString tOutStateString;
- tOutStateString.AssignWithConversion(outStateString);
- aParams->SetBooleanValue(STATE_MIXED,outMixed);
- aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
- return NS_OK;
-}
-
-nsresult
-nsAlignCommand::SetState(nsIEditor *aEditor, nsString& newState)
-{
- NS_ASSERTION(aEditor, "Need an editor here");
-
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
-
- return htmlEditor->Align(newState);
-}
-
-nsAbsolutePositioningCommand::nsAbsolutePositioningCommand()
-: nsBaseStateUpdatingCommand(nsGkAtoms::_empty)
-{
-}
-
-NS_IMETHODIMP
-nsAbsolutePositioningCommand::IsCommandEnabled(const char * aCommandName,
- nsISupports *aCommandRefCon,
- bool *outCmdEnabled)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(aCommandRefCon);
- if (htmlEditor) {
- bool isEditable = false;
- nsresult rv = editor->GetIsSelectionEditable(&isEditable);
- NS_ENSURE_SUCCESS(rv, rv);
- if (isEditable)
- return htmlEditor->GetAbsolutePositioningEnabled(outCmdEnabled);
- }
-
- *outCmdEnabled = false;
- return NS_OK;
-}
-
-nsresult
-nsAbsolutePositioningCommand::GetCurrentState(nsIEditor *aEditor, nsICommandParams *aParams)
-{
- NS_ASSERTION(aEditor, "Need an editor here");
-
- nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
-
- bool isEnabled;
- htmlEditor->GetAbsolutePositioningEnabled(&isEnabled);
- if (!isEnabled) {
- aParams->SetBooleanValue(STATE_MIXED,false);
- aParams->SetCStringValue(STATE_ATTRIBUTE, "");
- return NS_OK;
- }
-
- nsCOMPtr<nsIDOMElement> elt;
- nsresult rv = htmlEditor->GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(elt));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsAutoString outStateString;
- if (elt)
- outStateString.AssignLiteral("absolute");
-
- aParams->SetBooleanValue(STATE_MIXED,false);
- aParams->SetCStringValue(STATE_ATTRIBUTE, NS_ConvertUTF16toUTF8(outStateString).get());
- return NS_OK;
-}
-
-nsresult
-nsAbsolutePositioningCommand::ToggleState(nsIEditor *aEditor)
-{
- NS_ASSERTION(aEditor, "Need an editor here");
-
- nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(aEditor);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIDOMElement> elt;
- nsresult rv = htmlEditor->GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(elt));
- NS_ENSURE_SUCCESS(rv, rv);
-
- return htmlEditor->AbsolutePositionSelection(!elt);
-}
-
-
-NS_IMETHODIMP
-nsDecreaseZIndexCommand::IsCommandEnabled(const char * aCommandName,
- nsISupports *refCon,
- bool *outCmdEnabled)
-{
- nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
-
- htmlEditor->GetAbsolutePositioningEnabled(outCmdEnabled);
- if (!(*outCmdEnabled))
- return NS_OK;
-
- nsCOMPtr<nsIDOMElement> positionedElement;
- htmlEditor->GetPositionedElement(getter_AddRefs(positionedElement));
- *outCmdEnabled = false;
- if (positionedElement) {
- int32_t z;
- nsresult rv = htmlEditor->GetElementZIndex(positionedElement, &z);
- NS_ENSURE_SUCCESS(rv, rv);
- *outCmdEnabled = (z > 0);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDecreaseZIndexCommand::DoCommand(const char *aCommandName,
- nsISupports *refCon)
-{
- nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NOT_IMPLEMENTED);
-
- return htmlEditor->RelativeChangeZIndex(-1);
-}
-
-NS_IMETHODIMP
-nsDecreaseZIndexCommand::DoCommandParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- return DoCommand(aCommandName, refCon);
-}
-
-NS_IMETHODIMP
-nsDecreaseZIndexCommand::GetCommandStateParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- NS_ENSURE_ARG_POINTER(aParams);
-
- bool enabled = false;
- nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return aParams->SetBooleanValue(STATE_ENABLED, enabled);
-}
-
-NS_IMETHODIMP
-nsIncreaseZIndexCommand::IsCommandEnabled(const char * aCommandName,
- nsISupports *refCon,
- bool *outCmdEnabled)
-{
- nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
-
- htmlEditor->GetAbsolutePositioningEnabled(outCmdEnabled);
- if (!(*outCmdEnabled))
- return NS_OK;
-
- nsCOMPtr<nsIDOMElement> positionedElement;
- htmlEditor->GetPositionedElement(getter_AddRefs(positionedElement));
- *outCmdEnabled = (nullptr != positionedElement);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsIncreaseZIndexCommand::DoCommand(const char *aCommandName,
- nsISupports *refCon)
-{
- nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NOT_IMPLEMENTED);
-
- return htmlEditor->RelativeChangeZIndex(1);
-}
-
-NS_IMETHODIMP
-nsIncreaseZIndexCommand::DoCommandParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- return DoCommand(aCommandName, refCon);
-}
-
-NS_IMETHODIMP
-nsIncreaseZIndexCommand::GetCommandStateParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- NS_ENSURE_ARG_POINTER(aParams);
-
- bool enabled = false;
- nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return aParams->SetBooleanValue(STATE_ENABLED, enabled);
-}
-
-
-NS_IMETHODIMP
-nsRemoveStylesCommand::IsCommandEnabled(const char * aCommandName,
- nsISupports *refCon,
- bool *outCmdEnabled)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- // test if we have any styles?
- if (editor)
- return editor->GetIsSelectionEditable(outCmdEnabled);
-
- *outCmdEnabled = false;
- return NS_OK;
-}
-
-
-
-NS_IMETHODIMP
-nsRemoveStylesCommand::DoCommand(const char *aCommandName,
- nsISupports *refCon)
-{
- nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
-
- nsresult rv = NS_OK;
- if (editor) {
- rv = editor->RemoveAllInlineProperties();
- }
-
- return rv;
-}
-
-NS_IMETHODIMP
-nsRemoveStylesCommand::DoCommandParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- return DoCommand(aCommandName, refCon);
-}
-
-NS_IMETHODIMP
-nsRemoveStylesCommand::GetCommandStateParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- bool outCmdEnabled = false;
- IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
- return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled);
-}
-
-NS_IMETHODIMP
-nsIncreaseFontSizeCommand::IsCommandEnabled(const char * aCommandName,
- nsISupports *refCon,
- bool *outCmdEnabled)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- // test if we are at max size?
- if (editor)
- return editor->GetIsSelectionEditable(outCmdEnabled);
-
- *outCmdEnabled = false;
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsIncreaseFontSizeCommand::DoCommand(const char *aCommandName,
- nsISupports *refCon)
-{
- nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
-
- nsresult rv = NS_OK;
- if (editor) {
- rv = editor->IncreaseFontSize();
- }
-
- return rv;
-}
-
-NS_IMETHODIMP
-nsIncreaseFontSizeCommand::DoCommandParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- return DoCommand(aCommandName, refCon);
-}
-
-NS_IMETHODIMP
-nsIncreaseFontSizeCommand::GetCommandStateParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- bool outCmdEnabled = false;
- IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
- return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled);
-}
-
-NS_IMETHODIMP
-nsDecreaseFontSizeCommand::IsCommandEnabled(const char * aCommandName,
- nsISupports *refCon,
- bool *outCmdEnabled)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- // test if we are at min size?
- if (editor)
- return editor->GetIsSelectionEditable(outCmdEnabled);
-
- *outCmdEnabled = false;
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsDecreaseFontSizeCommand::DoCommand(const char *aCommandName,
- nsISupports *refCon)
-{
- nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
-
- nsresult rv = NS_OK;
- if (editor) {
- rv = editor->DecreaseFontSize();
- }
-
- return rv;
-}
-
-NS_IMETHODIMP
-nsDecreaseFontSizeCommand::DoCommandParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- return DoCommand(aCommandName, refCon);
-}
-
-NS_IMETHODIMP
-nsDecreaseFontSizeCommand::GetCommandStateParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- bool outCmdEnabled = false;
- IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
- return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled);
-}
-
-NS_IMETHODIMP
-nsInsertHTMLCommand::IsCommandEnabled(const char * aCommandName,
- nsISupports *refCon,
- bool *outCmdEnabled)
-{
- NS_ENSURE_ARG_POINTER(outCmdEnabled);
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- if (editor)
- return editor->GetIsSelectionEditable(outCmdEnabled);
-
- *outCmdEnabled = false;
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsInsertHTMLCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
-{
- // If nsInsertHTMLCommand is called with no parameters, it was probably called with
- // an empty string parameter ''. In this case, it should act the same as the delete command
- NS_ENSURE_ARG_POINTER(refCon);
-
- nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(editor, NS_ERROR_NOT_IMPLEMENTED);
-
- nsString html = EmptyString();
- return editor->InsertHTML(html);
-}
-
-NS_IMETHODIMP
-nsInsertHTMLCommand::DoCommandParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- NS_ENSURE_ARG_POINTER(aParams);
- NS_ENSURE_ARG_POINTER(refCon);
-
- nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(editor, NS_ERROR_NOT_IMPLEMENTED);
-
- // Get HTML source string to insert from command params
- nsAutoString html;
- nsresult rv = aParams->GetStringValue(STATE_DATA, html);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return editor->InsertHTML(html);
-}
-
-NS_IMETHODIMP
-nsInsertHTMLCommand::GetCommandStateParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- NS_ENSURE_ARG_POINTER(aParams);
- NS_ENSURE_ARG_POINTER(refCon);
-
- bool outCmdEnabled = false;
- IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
- return aParams->SetBooleanValue(STATE_ENABLED, outCmdEnabled);
-}
-
-NS_IMPL_ISUPPORTS_INHERITED0(nsInsertTagCommand, nsBaseComposerCommand)
-
-nsInsertTagCommand::nsInsertTagCommand(nsIAtom* aTagName)
-: nsBaseComposerCommand()
-, mTagName(aTagName)
-{
- MOZ_ASSERT(mTagName);
-}
-
-nsInsertTagCommand::~nsInsertTagCommand()
-{
-}
-
-NS_IMETHODIMP
-nsInsertTagCommand::IsCommandEnabled(const char * aCommandName,
- nsISupports *refCon,
- bool *outCmdEnabled)
-{
- NS_ENSURE_ARG_POINTER(outCmdEnabled);
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- if (editor)
- return editor->GetIsSelectionEditable(outCmdEnabled);
-
- *outCmdEnabled = false;
- return NS_OK;
-}
-
-
-// corresponding STATE_ATTRIBUTE is: src (img) and href (a)
-NS_IMETHODIMP
-nsInsertTagCommand::DoCommand(const char *aCmdName, nsISupports *refCon)
-{
- NS_ENSURE_TRUE(mTagName == nsGkAtoms::hr, NS_ERROR_NOT_IMPLEMENTED);
-
- nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(editor, NS_ERROR_NOT_IMPLEMENTED);
-
- nsCOMPtr<nsIDOMElement> domElem;
- nsresult rv = editor->CreateElementWithDefaults(
- nsDependentAtomString(mTagName), getter_AddRefs(domElem));
- NS_ENSURE_SUCCESS(rv, rv);
-
- return editor->InsertElementAtSelection(domElem, true);
-}
-
-NS_IMETHODIMP
-nsInsertTagCommand::DoCommandParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- NS_ENSURE_ARG_POINTER(refCon);
-
- // inserting an hr shouldn't have an parameters, just call DoCommand for that
- if (mTagName == nsGkAtoms::hr) {
- return DoCommand(aCommandName, refCon);
- }
-
- NS_ENSURE_ARG_POINTER(aParams);
-
- nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(editor, NS_ERROR_NOT_IMPLEMENTED);
-
- // do we have an href to use for creating link?
- nsXPIDLCString s;
- nsresult rv = aParams->GetCStringValue(STATE_ATTRIBUTE, getter_Copies(s));
- NS_ENSURE_SUCCESS(rv, rv);
- nsAutoString attrib; attrib.AssignWithConversion(s);
-
- if (attrib.IsEmpty())
- return NS_ERROR_INVALID_ARG;
-
- // filter out tags we don't know how to insert
- nsAutoString attributeType;
- if (mTagName == nsGkAtoms::a) {
- attributeType.AssignLiteral("href");
- } else if (mTagName == nsGkAtoms::img) {
- attributeType.AssignLiteral("src");
- } else {
- return NS_ERROR_NOT_IMPLEMENTED;
- }
-
- nsCOMPtr<nsIDOMElement> domElem;
- rv = editor->CreateElementWithDefaults(nsDependentAtomString(mTagName),
- getter_AddRefs(domElem));
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = domElem->SetAttribute(attributeType, attrib);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // do actual insertion
- if (mTagName == nsGkAtoms::a)
- return editor->InsertLinkAroundSelection(domElem);
-
- return editor->InsertElementAtSelection(domElem, true);
-}
-
-NS_IMETHODIMP
-nsInsertTagCommand::GetCommandStateParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- NS_ENSURE_ARG_POINTER(aParams);
- NS_ENSURE_ARG_POINTER(refCon);
-
- bool outCmdEnabled = false;
- IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
- return aParams->SetBooleanValue(STATE_ENABLED, outCmdEnabled);
-}
-
-
-/****************************/
-//HELPER METHODS
-/****************************/
-
-nsresult
-GetListState(nsIHTMLEditor* aEditor, bool* aMixed, nsAString& aLocalName)
-{
- MOZ_ASSERT(aEditor);
- MOZ_ASSERT(aMixed);
-
- *aMixed = false;
- aLocalName.Truncate();
-
- bool bOL, bUL, bDL;
- nsresult rv = aEditor->GetListState(aMixed, &bOL, &bUL, &bDL);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (*aMixed) {
- return NS_OK;
- }
-
- if (bOL) {
- aLocalName.AssignLiteral("ol");
- } else if (bUL) {
- aLocalName.AssignLiteral("ul");
- } else if (bDL) {
- aLocalName.AssignLiteral("dl");
- }
- return NS_OK;
-}
-
-nsresult
-RemoveOneProperty(nsIHTMLEditor* aEditor, const nsAString& aProp)
-{
- MOZ_ASSERT(aEditor);
-
- /// XXX Hack alert! Look in nsIEditProperty.h for this
- nsCOMPtr<nsIAtom> styleAtom = NS_Atomize(aProp);
- NS_ENSURE_TRUE(styleAtom, NS_ERROR_OUT_OF_MEMORY);
-
- return aEditor->RemoveInlineProperty(styleAtom, EmptyString());
-}
-
-
-// the name of the attribute here should be the contents of the appropriate
-// tag, e.g. 'b' for bold, 'i' for italics.
-nsresult
-RemoveTextProperty(nsIHTMLEditor* aEditor, const nsAString& aProp)
-{
- MOZ_ASSERT(aEditor);
-
- if (aProp.LowerCaseEqualsLiteral("all")) {
- return aEditor->RemoveAllInlineProperties();
- }
-
- return RemoveOneProperty(aEditor, aProp);
-}
-
-// the name of the attribute here should be the contents of the appropriate
-// tag, e.g. 'b' for bold, 'i' for italics.
-nsresult
-SetTextProperty(nsIHTMLEditor* aEditor, const nsAString& aProp)
-{
- MOZ_ASSERT(aEditor);
-
- /// XXX Hack alert! Look in nsIEditProperty.h for this
- nsCOMPtr<nsIAtom> styleAtom = NS_Atomize(aProp);
- NS_ENSURE_TRUE(styleAtom, NS_ERROR_OUT_OF_MEMORY);
-
- return aEditor->SetInlineProperty(styleAtom, EmptyString(), EmptyString());
-}
diff --git a/editor/composer/nsComposerCommands.h b/editor/composer/nsComposerCommands.h
deleted file mode 100644
index 3d3855d40..000000000
--- a/editor/composer/nsComposerCommands.h
+++ /dev/null
@@ -1,281 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsComposerCommands_h_
-#define nsComposerCommands_h_
-
-#include "nsIControllerCommand.h"
-#include "nsISupportsImpl.h" // for NS_DECL_ISUPPORTS_INHERITED, etc
-#include "nscore.h" // for nsresult, NS_IMETHOD
-
-class nsIAtom;
-class nsICommandParams;
-class nsIEditor;
-class nsISupports;
-class nsString;
-
-// This is a virtual base class for commands registered with the composer controller.
-// Note that such commands are instantiated once per composer, so can store state.
-// Also note that IsCommandEnabled can be called with an editor that may not
-// have an editor yet (because the document is loading). Most commands will want
-// to return false in this case.
-// Don't hold on to any references to the editor or document from
-// your command. This will cause leaks. Also, be aware that the document the
-// editor is editing can change under you (if the user Reverts the file, for
-// instance).
-class nsBaseComposerCommand : public nsIControllerCommand
-{
-protected:
- virtual ~nsBaseComposerCommand() {}
-
-public:
-
- nsBaseComposerCommand();
-
- // nsISupports
- NS_DECL_ISUPPORTS
-
- // nsIControllerCommand. Declared longhand so we can make them pure virtual
- NS_IMETHOD IsCommandEnabled(const char * aCommandName, nsISupports *aCommandRefCon, bool *_retval) override = 0;
- NS_IMETHOD DoCommand(const char * aCommandName, nsISupports *aCommandRefCon) override = 0;
-
-};
-
-
-#define NS_DECL_COMPOSER_COMMAND(_cmd) \
-class _cmd : public nsBaseComposerCommand \
-{ \
-public: \
- NS_DECL_NSICONTROLLERCOMMAND \
-};
-
-// virtual base class for commands that need to save and update Boolean state (like styles etc)
-class nsBaseStateUpdatingCommand : public nsBaseComposerCommand
-{
-public:
- explicit nsBaseStateUpdatingCommand(nsIAtom* aTagName);
-
- NS_DECL_ISUPPORTS_INHERITED
-
- NS_DECL_NSICONTROLLERCOMMAND
-
-protected:
- virtual ~nsBaseStateUpdatingCommand();
-
- // get the current state (on or off) for this style or block format
- virtual nsresult GetCurrentState(nsIEditor* aEditor, nsICommandParams* aParams) = 0;
-
- // add/remove the style
- virtual nsresult ToggleState(nsIEditor* aEditor) = 0;
-
-protected:
- nsIAtom* mTagName;
-};
-
-
-// Shared class for the various style updating commands like bold, italics etc.
-// Suitable for commands whose state is either 'on' or 'off'.
-class nsStyleUpdatingCommand : public nsBaseStateUpdatingCommand
-{
-public:
- explicit nsStyleUpdatingCommand(nsIAtom* aTagName);
-
-protected:
-
- // get the current state (on or off) for this style or block format
- virtual nsresult GetCurrentState(nsIEditor* aEditor, nsICommandParams* aParams);
-
- // add/remove the style
- virtual nsresult ToggleState(nsIEditor* aEditor);
-};
-
-
-class nsInsertTagCommand : public nsBaseComposerCommand
-{
-public:
- explicit nsInsertTagCommand(nsIAtom* aTagName);
-
- NS_DECL_ISUPPORTS_INHERITED
-
- NS_DECL_NSICONTROLLERCOMMAND
-
-protected:
- virtual ~nsInsertTagCommand();
-
- nsIAtom* mTagName;
-};
-
-
-class nsListCommand : public nsBaseStateUpdatingCommand
-{
-public:
- explicit nsListCommand(nsIAtom* aTagName);
-
-protected:
-
- // get the current state (on or off) for this style or block format
- virtual nsresult GetCurrentState(nsIEditor* aEditor, nsICommandParams* aParams);
-
- // add/remove the style
- virtual nsresult ToggleState(nsIEditor* aEditor);
-};
-
-class nsListItemCommand : public nsBaseStateUpdatingCommand
-{
-public:
- explicit nsListItemCommand(nsIAtom* aTagName);
-
-protected:
-
- // get the current state (on or off) for this style or block format
- virtual nsresult GetCurrentState(nsIEditor* aEditor, nsICommandParams* aParams);
-
- // add/remove the style
- virtual nsresult ToggleState(nsIEditor* aEditor);
-};
-
-// Base class for commands whose state consists of a string (e.g. para format)
-class nsMultiStateCommand : public nsBaseComposerCommand
-{
-public:
-
- nsMultiStateCommand();
-
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_NSICONTROLLERCOMMAND
-
-protected:
- virtual ~nsMultiStateCommand();
-
- virtual nsresult GetCurrentState(nsIEditor *aEditor, nsICommandParams* aParams) =0;
- virtual nsresult SetState(nsIEditor *aEditor, nsString& newState) = 0;
-
-};
-
-
-class nsParagraphStateCommand : public nsMultiStateCommand
-{
-public:
- nsParagraphStateCommand();
-
-protected:
-
- virtual nsresult GetCurrentState(nsIEditor *aEditor, nsICommandParams* aParams);
- virtual nsresult SetState(nsIEditor *aEditor, nsString& newState);
-};
-
-class nsFontFaceStateCommand : public nsMultiStateCommand
-{
-public:
- nsFontFaceStateCommand();
-
-protected:
-
- virtual nsresult GetCurrentState(nsIEditor *aEditor, nsICommandParams* aParams);
- virtual nsresult SetState(nsIEditor *aEditor, nsString& newState);
-};
-
-class nsFontSizeStateCommand : public nsMultiStateCommand
-{
-public:
- nsFontSizeStateCommand();
-
-protected:
-
- virtual nsresult GetCurrentState(nsIEditor *aEditor,
- nsICommandParams* aParams);
- virtual nsresult SetState(nsIEditor *aEditor, nsString& newState);
-};
-
-class nsHighlightColorStateCommand : public nsMultiStateCommand
-{
-public:
- nsHighlightColorStateCommand();
-
-protected:
-
- NS_IMETHOD IsCommandEnabled(const char *aCommandName, nsISupports *aCommandRefCon, bool *_retval);
- virtual nsresult GetCurrentState(nsIEditor *aEditor, nsICommandParams* aParams);
- virtual nsresult SetState(nsIEditor *aEditor, nsString& newState);
-
-};
-
-class nsFontColorStateCommand : public nsMultiStateCommand
-{
-public:
- nsFontColorStateCommand();
-
-protected:
-
- virtual nsresult GetCurrentState(nsIEditor *aEditor, nsICommandParams* aParams);
- virtual nsresult SetState(nsIEditor *aEditor, nsString& newState);
-};
-
-class nsAlignCommand : public nsMultiStateCommand
-{
-public:
- nsAlignCommand();
-
-protected:
-
- virtual nsresult GetCurrentState(nsIEditor *aEditor, nsICommandParams* aParams);
- virtual nsresult SetState(nsIEditor *aEditor, nsString& newState);
-};
-
-class nsBackgroundColorStateCommand : public nsMultiStateCommand
-{
-public:
- nsBackgroundColorStateCommand();
-
-protected:
-
- virtual nsresult GetCurrentState(nsIEditor *aEditor, nsICommandParams* aParams);
- virtual nsresult SetState(nsIEditor *aEditor, nsString& newState);
-};
-
-class nsAbsolutePositioningCommand : public nsBaseStateUpdatingCommand
-{
-public:
- nsAbsolutePositioningCommand();
-
-protected:
-
- NS_IMETHOD IsCommandEnabled(const char *aCommandName, nsISupports *aCommandRefCon, bool *_retval);
- virtual nsresult GetCurrentState(nsIEditor* aEditor, nsICommandParams* aParams);
- virtual nsresult ToggleState(nsIEditor* aEditor);
-};
-
-// composer commands
-
-NS_DECL_COMPOSER_COMMAND(nsCloseCommand)
-NS_DECL_COMPOSER_COMMAND(nsDocumentStateCommand)
-NS_DECL_COMPOSER_COMMAND(nsSetDocumentStateCommand)
-NS_DECL_COMPOSER_COMMAND(nsSetDocumentOptionsCommand)
-//NS_DECL_COMPOSER_COMMAND(nsPrintingCommands)
-
-NS_DECL_COMPOSER_COMMAND(nsDecreaseZIndexCommand)
-NS_DECL_COMPOSER_COMMAND(nsIncreaseZIndexCommand)
-
-// Generic commands
-
-// File menu
-NS_DECL_COMPOSER_COMMAND(nsNewCommands) // handles 'new' anything
-
-// Edit menu
-NS_DECL_COMPOSER_COMMAND(nsPasteNoFormattingCommand)
-
-// Block transformations
-NS_DECL_COMPOSER_COMMAND(nsIndentCommand)
-NS_DECL_COMPOSER_COMMAND(nsOutdentCommand)
-
-NS_DECL_COMPOSER_COMMAND(nsRemoveListCommand)
-NS_DECL_COMPOSER_COMMAND(nsRemoveStylesCommand)
-NS_DECL_COMPOSER_COMMAND(nsIncreaseFontSizeCommand)
-NS_DECL_COMPOSER_COMMAND(nsDecreaseFontSizeCommand)
-
-// Insert content commands
-NS_DECL_COMPOSER_COMMAND(nsInsertHTMLCommand)
-
-#endif // nsComposerCommands_h_
diff --git a/editor/composer/nsComposerCommandsUpdater.cpp b/editor/composer/nsComposerCommandsUpdater.cpp
deleted file mode 100644
index 4999f7b92..000000000
--- a/editor/composer/nsComposerCommandsUpdater.cpp
+++ /dev/null
@@ -1,381 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/mozalloc.h" // for operator new
-#include "nsAString.h"
-#include "nsComponentManagerUtils.h" // for do_CreateInstance
-#include "nsComposerCommandsUpdater.h"
-#include "nsDebug.h" // for NS_ENSURE_TRUE, etc
-#include "nsError.h" // for NS_OK, NS_ERROR_FAILURE, etc
-#include "nsICommandManager.h" // for nsICommandManager
-#include "nsID.h" // for NS_GET_IID, etc
-#include "nsIDOMWindow.h" // for nsIDOMWindow
-#include "nsIDocShell.h" // for nsIDocShell
-#include "nsIInterfaceRequestorUtils.h" // for do_GetInterface
-#include "nsISelection.h" // for nsISelection
-#include "nsITransactionManager.h" // for nsITransactionManager
-#include "nsLiteralString.h" // for NS_LITERAL_STRING
-#include "nsPICommandUpdater.h" // for nsPICommandUpdater
-#include "nsPIDOMWindow.h" // for nsPIDOMWindow
-
-class nsIDOMDocument;
-class nsITransaction;
-
-nsComposerCommandsUpdater::nsComposerCommandsUpdater()
-: mDirtyState(eStateUninitialized)
-, mSelectionCollapsed(eStateUninitialized)
-, mFirstDoOfFirstUndo(true)
-{
-}
-
-nsComposerCommandsUpdater::~nsComposerCommandsUpdater()
-{
- // cancel any outstanding update timer
- if (mUpdateTimer) {
- mUpdateTimer->Cancel();
- }
-}
-
-NS_IMPL_ISUPPORTS(nsComposerCommandsUpdater, nsISelectionListener,
- nsIDocumentStateListener, nsITransactionListener, nsITimerCallback)
-
-#if 0
-#pragma mark -
-#endif
-
-NS_IMETHODIMP
-nsComposerCommandsUpdater::NotifyDocumentCreated()
-{
- // Trigger an nsIObserve notification that the document has been created
- UpdateOneCommand("obs_documentCreated");
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsComposerCommandsUpdater::NotifyDocumentWillBeDestroyed()
-{
- // cancel any outstanding update timer
- if (mUpdateTimer) {
- mUpdateTimer->Cancel();
- mUpdateTimer = nullptr;
- }
-
- // We can't call this right now; it is too late in some cases and the window
- // is already partially destructed (e.g. JS objects may be gone).
-#if 0
- // Trigger an nsIObserve notification that the document will be destroyed
- UpdateOneCommand("obs_documentWillBeDestroyed");
-#endif
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsComposerCommandsUpdater::NotifyDocumentStateChanged(bool aNowDirty)
-{
- // update document modified. We should have some other notifications for this too.
- return UpdateDirtyState(aNowDirty);
-}
-
-NS_IMETHODIMP
-nsComposerCommandsUpdater::NotifySelectionChanged(nsIDOMDocument *,
- nsISelection *, int16_t)
-{
- return PrimeUpdateTimer();
-}
-
-#if 0
-#pragma mark -
-#endif
-
-NS_IMETHODIMP
-nsComposerCommandsUpdater::WillDo(nsITransactionManager *aManager,
- nsITransaction *aTransaction, bool *aInterrupt)
-{
- *aInterrupt = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsComposerCommandsUpdater::DidDo(nsITransactionManager *aManager,
- nsITransaction *aTransaction, nsresult aDoResult)
-{
- // only need to update if the status of the Undo menu item changes.
- int32_t undoCount;
- aManager->GetNumberOfUndoItems(&undoCount);
- if (undoCount == 1) {
- if (mFirstDoOfFirstUndo) {
- UpdateCommandGroup(NS_LITERAL_STRING("undo"));
- }
- mFirstDoOfFirstUndo = false;
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsComposerCommandsUpdater::WillUndo(nsITransactionManager *aManager,
- nsITransaction *aTransaction,
- bool *aInterrupt)
-{
- *aInterrupt = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsComposerCommandsUpdater::DidUndo(nsITransactionManager *aManager,
- nsITransaction *aTransaction,
- nsresult aUndoResult)
-{
- int32_t undoCount;
- aManager->GetNumberOfUndoItems(&undoCount);
- if (undoCount == 0)
- mFirstDoOfFirstUndo = true; // reset the state for the next do
-
- UpdateCommandGroup(NS_LITERAL_STRING("undo"));
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsComposerCommandsUpdater::WillRedo(nsITransactionManager *aManager,
- nsITransaction *aTransaction,
- bool *aInterrupt)
-{
- *aInterrupt = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsComposerCommandsUpdater::DidRedo(nsITransactionManager *aManager,
- nsITransaction *aTransaction,
- nsresult aRedoResult)
-{
- UpdateCommandGroup(NS_LITERAL_STRING("undo"));
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsComposerCommandsUpdater::WillBeginBatch(nsITransactionManager *aManager,
- bool *aInterrupt)
-{
- *aInterrupt = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsComposerCommandsUpdater::DidBeginBatch(nsITransactionManager *aManager,
- nsresult aResult)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsComposerCommandsUpdater::WillEndBatch(nsITransactionManager *aManager,
- bool *aInterrupt)
-{
- *aInterrupt = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsComposerCommandsUpdater::DidEndBatch(nsITransactionManager *aManager,
- nsresult aResult)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsComposerCommandsUpdater::WillMerge(nsITransactionManager *aManager,
- nsITransaction *aTopTransaction,
- nsITransaction *aTransactionToMerge,
- bool *aInterrupt)
-{
- *aInterrupt = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsComposerCommandsUpdater::DidMerge(nsITransactionManager *aManager,
- nsITransaction *aTopTransaction,
- nsITransaction *aTransactionToMerge,
- bool aDidMerge, nsresult aMergeResult)
-{
- return NS_OK;
-}
-
-#if 0
-#pragma mark -
-#endif
-
-nsresult
-nsComposerCommandsUpdater::Init(nsPIDOMWindowOuter* aDOMWindow)
-{
- NS_ENSURE_ARG(aDOMWindow);
- mDOMWindow = do_GetWeakReference(aDOMWindow);
- mDocShell = do_GetWeakReference(aDOMWindow->GetDocShell());
- return NS_OK;
-}
-
-nsresult
-nsComposerCommandsUpdater::PrimeUpdateTimer()
-{
- if (!mUpdateTimer) {
- nsresult rv = NS_OK;
- mUpdateTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- const uint32_t kUpdateTimerDelay = 150;
- return mUpdateTimer->InitWithCallback(static_cast<nsITimerCallback*>(this),
- kUpdateTimerDelay,
- nsITimer::TYPE_ONE_SHOT);
-}
-
-
-void nsComposerCommandsUpdater::TimerCallback()
-{
- // if the selection state has changed, update stuff
- bool isCollapsed = SelectionIsCollapsed();
- if (static_cast<int8_t>(isCollapsed) != mSelectionCollapsed) {
- UpdateCommandGroup(NS_LITERAL_STRING("select"));
- mSelectionCollapsed = isCollapsed;
- }
-
- // isn't this redundant with the UpdateCommandGroup above?
- // can we just nuke the above call? or create a meta command group?
- UpdateCommandGroup(NS_LITERAL_STRING("style"));
-}
-
-nsresult
-nsComposerCommandsUpdater::UpdateDirtyState(bool aNowDirty)
-{
- if (mDirtyState != static_cast<int8_t>(aNowDirty)) {
- UpdateCommandGroup(NS_LITERAL_STRING("save"));
- UpdateCommandGroup(NS_LITERAL_STRING("undo"));
- mDirtyState = aNowDirty;
- }
-
- return NS_OK;
-}
-
-nsresult
-nsComposerCommandsUpdater::UpdateCommandGroup(const nsAString& aCommandGroup)
-{
- nsCOMPtr<nsPICommandUpdater> commandUpdater = GetCommandUpdater();
- NS_ENSURE_TRUE(commandUpdater, NS_ERROR_FAILURE);
-
-
- // This hardcoded list of commands is temporary.
- // This code should use nsIControllerCommandGroup.
- if (aCommandGroup.EqualsLiteral("undo")) {
- commandUpdater->CommandStatusChanged("cmd_undo");
- commandUpdater->CommandStatusChanged("cmd_redo");
- return NS_OK;
- }
-
- if (aCommandGroup.EqualsLiteral("select") ||
- aCommandGroup.EqualsLiteral("style")) {
- commandUpdater->CommandStatusChanged("cmd_bold");
- commandUpdater->CommandStatusChanged("cmd_italic");
- commandUpdater->CommandStatusChanged("cmd_underline");
- commandUpdater->CommandStatusChanged("cmd_tt");
-
- commandUpdater->CommandStatusChanged("cmd_strikethrough");
- commandUpdater->CommandStatusChanged("cmd_superscript");
- commandUpdater->CommandStatusChanged("cmd_subscript");
- commandUpdater->CommandStatusChanged("cmd_nobreak");
-
- commandUpdater->CommandStatusChanged("cmd_em");
- commandUpdater->CommandStatusChanged("cmd_strong");
- commandUpdater->CommandStatusChanged("cmd_cite");
- commandUpdater->CommandStatusChanged("cmd_abbr");
- commandUpdater->CommandStatusChanged("cmd_acronym");
- commandUpdater->CommandStatusChanged("cmd_code");
- commandUpdater->CommandStatusChanged("cmd_samp");
- commandUpdater->CommandStatusChanged("cmd_var");
-
- commandUpdater->CommandStatusChanged("cmd_increaseFont");
- commandUpdater->CommandStatusChanged("cmd_decreaseFont");
-
- commandUpdater->CommandStatusChanged("cmd_paragraphState");
- commandUpdater->CommandStatusChanged("cmd_fontFace");
- commandUpdater->CommandStatusChanged("cmd_fontColor");
- commandUpdater->CommandStatusChanged("cmd_backgroundColor");
- commandUpdater->CommandStatusChanged("cmd_highlight");
- return NS_OK;
- }
-
- if (aCommandGroup.EqualsLiteral("save")) {
- // save commands (most are not in C++)
- commandUpdater->CommandStatusChanged("cmd_setDocumentModified");
- commandUpdater->CommandStatusChanged("cmd_save");
- return NS_OK;
- }
-
- return NS_OK;
-}
-
-nsresult
-nsComposerCommandsUpdater::UpdateOneCommand(const char *aCommand)
-{
- nsCOMPtr<nsPICommandUpdater> commandUpdater = GetCommandUpdater();
- NS_ENSURE_TRUE(commandUpdater, NS_ERROR_FAILURE);
-
- commandUpdater->CommandStatusChanged(aCommand);
-
- return NS_OK;
-}
-
-bool
-nsComposerCommandsUpdater::SelectionIsCollapsed()
-{
- nsCOMPtr<nsPIDOMWindowOuter> domWindow = do_QueryReferent(mDOMWindow);
- NS_ENSURE_TRUE(domWindow, true);
-
- nsCOMPtr<nsISelection> domSelection = domWindow->GetSelection();
- if (NS_WARN_IF(!domSelection)) {
- return false;
- }
-
- bool selectionCollapsed = false;
- domSelection->GetIsCollapsed(&selectionCollapsed);
- return selectionCollapsed;
-}
-
-already_AddRefed<nsPICommandUpdater>
-nsComposerCommandsUpdater::GetCommandUpdater()
-{
- nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocShell);
- NS_ENSURE_TRUE(docShell, nullptr);
- nsCOMPtr<nsICommandManager> manager = docShell->GetCommandManager();
- nsCOMPtr<nsPICommandUpdater> updater = do_QueryInterface(manager);
- return updater.forget();
-}
-
-#if 0
-#pragma mark -
-#endif
-
-nsresult
-nsComposerCommandsUpdater::Notify(nsITimer *timer)
-{
- NS_ASSERTION(timer == mUpdateTimer.get(), "Hey, this ain't my timer!");
- TimerCallback();
- return NS_OK;
-}
-
-#if 0
-#pragma mark -
-#endif
-
-
-nsresult
-NS_NewComposerCommandsUpdater(nsISelectionListener** aInstancePtrResult)
-{
- RefPtr<nsComposerCommandsUpdater> newThang = new nsComposerCommandsUpdater;
- newThang.forget(aInstancePtrResult);
- return NS_OK;
-}
diff --git a/editor/composer/nsComposerCommandsUpdater.h b/editor/composer/nsComposerCommandsUpdater.h
deleted file mode 100644
index 3b853edeb..000000000
--- a/editor/composer/nsComposerCommandsUpdater.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-
-
-#ifndef nsComposerCommandsUpdater_h__
-#define nsComposerCommandsUpdater_h__
-
-#include "nsCOMPtr.h" // for already_AddRefed, nsCOMPtr
-#include "nsIDocumentStateListener.h"
-#include "nsISelectionListener.h"
-#include "nsISupportsImpl.h" // for NS_DECL_ISUPPORTS
-#include "nsITimer.h" // for NS_DECL_NSITIMERCALLBACK, etc
-#include "nsITransactionListener.h" // for nsITransactionListener
-#include "nsIWeakReferenceUtils.h" // for nsWeakPtr
-#include "nscore.h" // for NS_IMETHOD, nsresult, etc
-
-class nsPIDOMWindowOuter;
-class nsITransaction;
-class nsITransactionManager;
-class nsPICommandUpdater;
-
-class nsComposerCommandsUpdater : public nsISelectionListener,
- public nsIDocumentStateListener,
- public nsITransactionListener,
- public nsITimerCallback
-{
-public:
-
- nsComposerCommandsUpdater();
-
- // nsISupports
- NS_DECL_ISUPPORTS
-
- // nsISelectionListener
- NS_DECL_NSISELECTIONLISTENER
-
- // nsIDocumentStateListener
- NS_DECL_NSIDOCUMENTSTATELISTENER
-
- // nsITimerCallback interfaces
- NS_DECL_NSITIMERCALLBACK
-
- /** nsITransactionListener interfaces
- */
- NS_IMETHOD WillDo(nsITransactionManager *aManager, nsITransaction *aTransaction, bool *aInterrupt) override;
- NS_IMETHOD DidDo(nsITransactionManager *aManager, nsITransaction *aTransaction, nsresult aDoResult) override;
- NS_IMETHOD WillUndo(nsITransactionManager *aManager, nsITransaction *aTransaction, bool *aInterrupt) override;
- NS_IMETHOD DidUndo(nsITransactionManager *aManager, nsITransaction *aTransaction, nsresult aUndoResult) override;
- NS_IMETHOD WillRedo(nsITransactionManager *aManager, nsITransaction *aTransaction, bool *aInterrupt) override;
- NS_IMETHOD DidRedo(nsITransactionManager *aManager, nsITransaction *aTransaction, nsresult aRedoResult) override;
- NS_IMETHOD WillBeginBatch(nsITransactionManager *aManager, bool *aInterrupt) override;
- NS_IMETHOD DidBeginBatch(nsITransactionManager *aManager, nsresult aResult) override;
- NS_IMETHOD WillEndBatch(nsITransactionManager *aManager, bool *aInterrupt) override;
- NS_IMETHOD DidEndBatch(nsITransactionManager *aManager, nsresult aResult) override;
- NS_IMETHOD WillMerge(nsITransactionManager *aManager, nsITransaction *aTopTransaction,
- nsITransaction *aTransactionToMerge, bool *aInterrupt) override;
- NS_IMETHOD DidMerge(nsITransactionManager *aManager, nsITransaction *aTopTransaction,
- nsITransaction *aTransactionToMerge,
- bool aDidMerge, nsresult aMergeResult) override;
-
-
- nsresult Init(nsPIDOMWindowOuter* aDOMWindow);
-
-protected:
-
- virtual ~nsComposerCommandsUpdater();
-
- enum {
- eStateUninitialized = -1,
- eStateOff = false,
- eStateOn = true
- };
-
- bool SelectionIsCollapsed();
- nsresult UpdateDirtyState(bool aNowDirty);
- nsresult UpdateOneCommand(const char* aCommand);
- nsresult UpdateCommandGroup(const nsAString& aCommandGroup);
-
- already_AddRefed<nsPICommandUpdater> GetCommandUpdater();
-
- nsresult PrimeUpdateTimer();
- void TimerCallback();
- nsCOMPtr<nsITimer> mUpdateTimer;
-
- nsWeakPtr mDOMWindow;
- nsWeakPtr mDocShell;
- int8_t mDirtyState;
- int8_t mSelectionCollapsed;
- bool mFirstDoOfFirstUndo;
-
-
-};
-
-extern "C" nsresult NS_NewComposerCommandsUpdater(nsISelectionListener** aInstancePtrResult);
-
-
-#endif // nsComposerCommandsUpdater_h__
diff --git a/editor/composer/nsComposerController.cpp b/editor/composer/nsComposerController.cpp
deleted file mode 100644
index 5d90fbff0..000000000
--- a/editor/composer/nsComposerController.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/mozalloc.h" // for operator new
-#include "nsComposerCommands.h" // for nsStyleUpdatingCommand, etc
-#include "nsComposerController.h"
-#include "nsError.h" // for NS_OK
-#include "nsGkAtoms.h" // for nsGkAtoms, nsGkAtoms::a, etc
-#include "nsIControllerCommandTable.h" // for nsIControllerCommandTable
-
-class nsIControllerCommand;
-
-#define NS_REGISTER_ONE_COMMAND(_cmdClass, _cmdName) \
- { \
- _cmdClass* theCmd = new _cmdClass(); \
- inCommandTable->RegisterCommand(_cmdName, \
- static_cast<nsIControllerCommand *>(theCmd)); \
- }
-
-#define NS_REGISTER_FIRST_COMMAND(_cmdClass, _cmdName) \
- { \
- _cmdClass* theCmd = new _cmdClass(); \
- inCommandTable->RegisterCommand(_cmdName, \
- static_cast<nsIControllerCommand *>(theCmd));
-
-#define NS_REGISTER_NEXT_COMMAND(_cmdClass, _cmdName) \
- inCommandTable->RegisterCommand(_cmdName, \
- static_cast<nsIControllerCommand *>(theCmd));
-
-#define NS_REGISTER_LAST_COMMAND(_cmdClass, _cmdName) \
- inCommandTable->RegisterCommand(_cmdName, \
- static_cast<nsIControllerCommand *>(theCmd)); \
- }
-
-#define NS_REGISTER_STYLE_COMMAND(_cmdClass, _cmdName, _styleTag) \
- { \
- _cmdClass* theCmd = new _cmdClass(_styleTag); \
- inCommandTable->RegisterCommand(_cmdName, \
- static_cast<nsIControllerCommand *>(theCmd)); \
- }
-
-#define NS_REGISTER_TAG_COMMAND(_cmdClass, _cmdName, _tagName) \
- { \
- _cmdClass* theCmd = new _cmdClass(_tagName); \
- inCommandTable->RegisterCommand(_cmdName, \
- static_cast<nsIControllerCommand *>(theCmd)); \
- }
-
-
-// static
-nsresult
-nsComposerController::RegisterEditorDocStateCommands(
- nsIControllerCommandTable *inCommandTable)
-{
- // observer commands for document state
- NS_REGISTER_FIRST_COMMAND(nsDocumentStateCommand, "obs_documentCreated")
- NS_REGISTER_NEXT_COMMAND(nsDocumentStateCommand, "obs_documentWillBeDestroyed")
- NS_REGISTER_LAST_COMMAND(nsDocumentStateCommand, "obs_documentLocationChanged")
-
- // commands that may get or change state
- NS_REGISTER_FIRST_COMMAND(nsSetDocumentStateCommand, "cmd_setDocumentModified")
- NS_REGISTER_NEXT_COMMAND(nsSetDocumentStateCommand, "cmd_setDocumentUseCSS")
- NS_REGISTER_NEXT_COMMAND(nsSetDocumentStateCommand, "cmd_setDocumentReadOnly")
- NS_REGISTER_NEXT_COMMAND(nsSetDocumentStateCommand, "cmd_insertBrOnReturn")
- NS_REGISTER_NEXT_COMMAND(nsSetDocumentStateCommand, "cmd_enableObjectResizing")
- NS_REGISTER_LAST_COMMAND(nsSetDocumentStateCommand, "cmd_enableInlineTableEditing")
-
- NS_REGISTER_ONE_COMMAND(nsSetDocumentOptionsCommand, "cmd_setDocumentOptions")
-
- return NS_OK;
-}
-
-// static
-nsresult
-nsComposerController::RegisterHTMLEditorCommands(
- nsIControllerCommandTable *inCommandTable)
-{
- // Edit menu
- NS_REGISTER_ONE_COMMAND(nsPasteNoFormattingCommand, "cmd_pasteNoFormatting");
-
- // indent/outdent
- NS_REGISTER_ONE_COMMAND(nsIndentCommand, "cmd_indent");
- NS_REGISTER_ONE_COMMAND(nsOutdentCommand, "cmd_outdent");
-
- // Styles
- NS_REGISTER_STYLE_COMMAND(nsStyleUpdatingCommand, "cmd_bold", nsGkAtoms::b);
- NS_REGISTER_STYLE_COMMAND(nsStyleUpdatingCommand, "cmd_italic", nsGkAtoms::i);
- NS_REGISTER_STYLE_COMMAND(nsStyleUpdatingCommand, "cmd_underline", nsGkAtoms::u);
- NS_REGISTER_STYLE_COMMAND(nsStyleUpdatingCommand, "cmd_tt", nsGkAtoms::tt);
-
- NS_REGISTER_STYLE_COMMAND(nsStyleUpdatingCommand, "cmd_strikethrough", nsGkAtoms::strike);
- NS_REGISTER_STYLE_COMMAND(nsStyleUpdatingCommand, "cmd_superscript", nsGkAtoms::sup);
- NS_REGISTER_STYLE_COMMAND(nsStyleUpdatingCommand, "cmd_subscript", nsGkAtoms::sub);
- NS_REGISTER_STYLE_COMMAND(nsStyleUpdatingCommand, "cmd_nobreak", nsGkAtoms::nobr);
-
- NS_REGISTER_STYLE_COMMAND(nsStyleUpdatingCommand, "cmd_em", nsGkAtoms::em);
- NS_REGISTER_STYLE_COMMAND(nsStyleUpdatingCommand, "cmd_strong", nsGkAtoms::strong);
- NS_REGISTER_STYLE_COMMAND(nsStyleUpdatingCommand, "cmd_cite", nsGkAtoms::cite);
- NS_REGISTER_STYLE_COMMAND(nsStyleUpdatingCommand, "cmd_abbr", nsGkAtoms::abbr);
- NS_REGISTER_STYLE_COMMAND(nsStyleUpdatingCommand, "cmd_acronym", nsGkAtoms::acronym);
- NS_REGISTER_STYLE_COMMAND(nsStyleUpdatingCommand, "cmd_code", nsGkAtoms::code);
- NS_REGISTER_STYLE_COMMAND(nsStyleUpdatingCommand, "cmd_samp", nsGkAtoms::samp);
- NS_REGISTER_STYLE_COMMAND(nsStyleUpdatingCommand, "cmd_var", nsGkAtoms::var);
- NS_REGISTER_STYLE_COMMAND(nsStyleUpdatingCommand, "cmd_removeLinks", nsGkAtoms::href);
-
- // lists
- NS_REGISTER_STYLE_COMMAND(nsListCommand, "cmd_ol", nsGkAtoms::ol);
- NS_REGISTER_STYLE_COMMAND(nsListCommand, "cmd_ul", nsGkAtoms::ul);
- NS_REGISTER_STYLE_COMMAND(nsListItemCommand, "cmd_dt", nsGkAtoms::dt);
- NS_REGISTER_STYLE_COMMAND(nsListItemCommand, "cmd_dd", nsGkAtoms::dd);
- NS_REGISTER_ONE_COMMAND(nsRemoveListCommand, "cmd_removeList");
-
- // format stuff
- NS_REGISTER_ONE_COMMAND(nsParagraphStateCommand, "cmd_paragraphState");
- NS_REGISTER_ONE_COMMAND(nsFontFaceStateCommand, "cmd_fontFace");
- NS_REGISTER_ONE_COMMAND(nsFontSizeStateCommand, "cmd_fontSize");
- NS_REGISTER_ONE_COMMAND(nsFontColorStateCommand, "cmd_fontColor");
- NS_REGISTER_ONE_COMMAND(nsBackgroundColorStateCommand, "cmd_backgroundColor");
- NS_REGISTER_ONE_COMMAND(nsHighlightColorStateCommand, "cmd_highlight");
-
- NS_REGISTER_ONE_COMMAND(nsAlignCommand, "cmd_align");
- NS_REGISTER_ONE_COMMAND(nsRemoveStylesCommand, "cmd_removeStyles");
-
- NS_REGISTER_ONE_COMMAND(nsIncreaseFontSizeCommand, "cmd_increaseFont");
- NS_REGISTER_ONE_COMMAND(nsDecreaseFontSizeCommand, "cmd_decreaseFont");
-
- // Insert content
- NS_REGISTER_ONE_COMMAND(nsInsertHTMLCommand, "cmd_insertHTML");
- NS_REGISTER_TAG_COMMAND(nsInsertTagCommand, "cmd_insertLinkNoUI", nsGkAtoms::a);
- NS_REGISTER_TAG_COMMAND(nsInsertTagCommand, "cmd_insertImageNoUI", nsGkAtoms::img);
- NS_REGISTER_TAG_COMMAND(nsInsertTagCommand, "cmd_insertHR", nsGkAtoms::hr);
-
- NS_REGISTER_ONE_COMMAND(nsAbsolutePositioningCommand, "cmd_absPos");
- NS_REGISTER_ONE_COMMAND(nsDecreaseZIndexCommand, "cmd_decreaseZIndex");
- NS_REGISTER_ONE_COMMAND(nsIncreaseZIndexCommand, "cmd_increaseZIndex");
-
- return NS_OK;
-}
diff --git a/editor/composer/nsComposerController.h b/editor/composer/nsComposerController.h
deleted file mode 100644
index 768c67b80..000000000
--- a/editor/composer/nsComposerController.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsComposerController_h__
-#define nsComposerController_h__
-
-
-#include "nscore.h" // for nsresult
-
-class nsIControllerCommandTable;
-
-
-// The plaintext editor controller is used for basic text editing and html editing
-// commands in composer
-// The refCon that gets passed to its commands is initially nsIEditingSession,
-// and after successfule editor creation it is changed to nsIEditor.
-#define NS_EDITORDOCSTATECONTROLLER_CID \
- { 0x50e95301, 0x17a8, 0x11d4, { 0x9f, 0x7e, 0xdd, 0x53, 0x0d, 0x5f, 0x05, 0x7c } }
-
-// The HTMLEditor controller is used only for HTML editors and takes nsIEditor as refCon
-#define NS_HTMLEDITORCONTROLLER_CID \
- { 0x62db0002, 0xdbb6, 0x43f4, { 0x8f, 0xb7, 0x9d, 0x25, 0x38, 0xbc, 0x57, 0x47 } }
-
-
-class nsComposerController
-{
-public:
- static nsresult RegisterEditorDocStateCommands(nsIControllerCommandTable* inCommandTable);
- static nsresult RegisterHTMLEditorCommands(nsIControllerCommandTable* inCommandTable);
-};
-
-#endif /* nsComposerController_h__ */
diff --git a/editor/composer/nsComposerDocumentCommands.cpp b/editor/composer/nsComposerDocumentCommands.cpp
deleted file mode 100644
index d44e940f6..000000000
--- a/editor/composer/nsComposerDocumentCommands.cpp
+++ /dev/null
@@ -1,480 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-#include "nsCOMPtr.h" // for nsCOMPtr, do_QueryInterface, etc
-#include "nsCRT.h" // for nsCRT
-#include "nsComposerCommands.h" // for nsSetDocumentOptionsCommand, etc
-#include "nsDebug.h" // for NS_ENSURE_ARG_POINTER, etc
-#include "nsError.h" // for NS_ERROR_INVALID_ARG, etc
-#include "nsICommandParams.h" // for nsICommandParams
-#include "nsIDOMDocument.h" // for nsIDOMDocument
-#include "nsIDocShell.h" // for nsIDocShell
-#include "nsIDocument.h" // for nsIDocument
-#include "nsIEditingSession.h" // for nsIEditingSession, etc
-#include "nsIEditor.h" // for nsIEditor
-#include "nsIHTMLEditor.h" // for nsIHTMLEditor
-#include "nsIHTMLInlineTableEditor.h" // for nsIHTMLInlineTableEditor
-#include "nsIHTMLObjectResizer.h" // for nsIHTMLObjectResizer
-#include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc
-#include "nsIPresShell.h" // for nsIPresShell
-#include "nsISelectionController.h" // for nsISelectionController
-#include "nsISupportsImpl.h" // for nsPresContext::Release
-#include "nsISupportsUtils.h" // for NS_IF_ADDREF
-#include "nsIURI.h" // for nsIURI
-#include "nsPresContext.h" // for nsPresContext
-#include "nscore.h" // for NS_IMETHODIMP, nsresult, etc
-
-class nsISupports;
-
-//defines
-#define STATE_ENABLED "state_enabled"
-#define STATE_ALL "state_all"
-#define STATE_ATTRIBUTE "state_attribute"
-#define STATE_DATA "state_data"
-
-static
-nsresult
-GetPresContextFromEditor(nsIEditor *aEditor, nsPresContext **aResult)
-{
- NS_ENSURE_ARG_POINTER(aResult);
- *aResult = nullptr;
- NS_ENSURE_ARG_POINTER(aEditor);
-
- nsCOMPtr<nsISelectionController> selCon;
- nsresult rv = aEditor->GetSelectionController(getter_AddRefs(selCon));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIPresShell> presShell = do_QueryInterface(selCon);
- NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
-
- NS_IF_ADDREF(*aResult = presShell->GetPresContext());
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSetDocumentOptionsCommand::IsCommandEnabled(const char * aCommandName,
- nsISupports *refCon,
- bool *outCmdEnabled)
-{
- NS_ENSURE_ARG_POINTER(outCmdEnabled);
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- if (editor) {
- return editor->GetIsSelectionEditable(outCmdEnabled);
- }
-
- *outCmdEnabled = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSetDocumentOptionsCommand::DoCommand(const char *aCommandName,
- nsISupports *refCon)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsSetDocumentOptionsCommand::DoCommandParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- NS_ENSURE_ARG_POINTER(aParams);
-
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(editor, NS_ERROR_INVALID_ARG);
-
- RefPtr<nsPresContext> presContext;
- nsresult rv = GetPresContextFromEditor(editor, getter_AddRefs(presContext));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
-
- int32_t animationMode;
- rv = aParams->GetLongValue("imageAnimation", &animationMode);
- if (NS_SUCCEEDED(rv)) {
- // for possible values of animation mode, see:
- // http://lxr.mozilla.org/seamonkey/source/image/public/imgIContainer.idl
- presContext->SetImageAnimationMode(animationMode);
- }
-
- bool allowPlugins;
- rv = aParams->GetBooleanValue("plugins", &allowPlugins);
- if (NS_SUCCEEDED(rv)) {
- nsCOMPtr<nsIDocShell> docShell(presContext->GetDocShell());
- NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
-
- rv = docShell->SetAllowPlugins(allowPlugins);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSetDocumentOptionsCommand::GetCommandStateParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- NS_ENSURE_ARG_POINTER(aParams);
- NS_ENSURE_ARG_POINTER(refCon);
-
- // The base editor owns most state info
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(editor, NS_ERROR_INVALID_ARG);
-
- // Always get the enabled state
- bool outCmdEnabled = false;
- IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
- nsresult rv = aParams->SetBooleanValue(STATE_ENABLED, outCmdEnabled);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // get pres context
- RefPtr<nsPresContext> presContext;
- rv = GetPresContextFromEditor(editor, getter_AddRefs(presContext));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
-
- int32_t animationMode;
- rv = aParams->GetLongValue("imageAnimation", &animationMode);
- if (NS_SUCCEEDED(rv)) {
- // for possible values of animation mode, see
- // http://lxr.mozilla.org/seamonkey/source/image/public/imgIContainer.idl
- rv = aParams->SetLongValue("imageAnimation",
- presContext->ImageAnimationMode());
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- bool allowPlugins = false;
- rv = aParams->GetBooleanValue("plugins", &allowPlugins);
- if (NS_SUCCEEDED(rv)) {
- nsCOMPtr<nsIDocShell> docShell(presContext->GetDocShell());
- NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
-
- allowPlugins = docShell->PluginsAllowedInCurrentDoc();
-
- rv = aParams->SetBooleanValue("plugins", allowPlugins);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-
-/**
- * Commands for document state that may be changed via doCommandParams
- * As of 11/11/02, this is just "cmd_setDocumentModified"
- * Note that you can use the same command class, nsSetDocumentStateCommand,
- * for more than one of this type of command
- * We check the input command param for different behavior
- */
-
-NS_IMETHODIMP
-nsSetDocumentStateCommand::IsCommandEnabled(const char * aCommandName,
- nsISupports *refCon,
- bool *outCmdEnabled)
-{
- // These commands are always enabled
- NS_ENSURE_ARG_POINTER(outCmdEnabled);
- *outCmdEnabled = true;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSetDocumentStateCommand::DoCommand(const char *aCommandName,
- nsISupports *refCon)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsSetDocumentStateCommand::DoCommandParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(editor, NS_ERROR_INVALID_ARG);
-
- if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentModified")) {
- NS_ENSURE_ARG_POINTER(aParams);
-
- bool modified;
- nsresult rv = aParams->GetBooleanValue(STATE_ATTRIBUTE, &modified);
-
- // Should we fail if this param wasn't set?
- // I'm not sure we should be that strict
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (modified) {
- return editor->IncrementModificationCount(1);
- }
-
- return editor->ResetModificationCount();
- }
-
- if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentReadOnly")) {
- NS_ENSURE_ARG_POINTER(aParams);
- bool isReadOnly;
- nsresult rvRO = aParams->GetBooleanValue(STATE_ATTRIBUTE, &isReadOnly);
- NS_ENSURE_SUCCESS(rvRO, rvRO);
-
- uint32_t flags;
- editor->GetFlags(&flags);
- if (isReadOnly) {
- flags |= nsIPlaintextEditor::eEditorReadonlyMask;
- } else {
- flags &= ~(nsIPlaintextEditor::eEditorReadonlyMask);
- }
-
- return editor->SetFlags(flags);
- }
-
- if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentUseCSS")) {
- NS_ENSURE_ARG_POINTER(aParams);
- nsCOMPtr<nsIHTMLEditor> htmleditor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(htmleditor, NS_ERROR_INVALID_ARG);
-
- bool desireCSS;
- nsresult rvCSS = aParams->GetBooleanValue(STATE_ATTRIBUTE, &desireCSS);
- NS_ENSURE_SUCCESS(rvCSS, rvCSS);
-
- return htmleditor->SetIsCSSEnabled(desireCSS);
- }
-
- if (!nsCRT::strcmp(aCommandName, "cmd_insertBrOnReturn")) {
- NS_ENSURE_ARG_POINTER(aParams);
- nsCOMPtr<nsIHTMLEditor> htmleditor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(htmleditor, NS_ERROR_INVALID_ARG);
-
- bool insertBrOnReturn;
- nsresult rvBR = aParams->GetBooleanValue(STATE_ATTRIBUTE,
- &insertBrOnReturn);
- NS_ENSURE_SUCCESS(rvBR, rvBR);
-
- return htmleditor->SetReturnInParagraphCreatesNewParagraph(!insertBrOnReturn);
- }
-
- if (!nsCRT::strcmp(aCommandName, "cmd_enableObjectResizing")) {
- NS_ENSURE_ARG_POINTER(aParams);
- nsCOMPtr<nsIHTMLObjectResizer> resizer = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(resizer, NS_ERROR_INVALID_ARG);
-
- bool enabled;
- nsresult rvOR = aParams->GetBooleanValue(STATE_ATTRIBUTE, &enabled);
- NS_ENSURE_SUCCESS(rvOR, rvOR);
-
- return resizer->SetObjectResizingEnabled(enabled);
- }
-
- if (!nsCRT::strcmp(aCommandName, "cmd_enableInlineTableEditing")) {
- NS_ENSURE_ARG_POINTER(aParams);
- nsCOMPtr<nsIHTMLInlineTableEditor> editor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(editor, NS_ERROR_INVALID_ARG);
-
- bool enabled;
- nsresult rvOR = aParams->GetBooleanValue(STATE_ATTRIBUTE, &enabled);
- NS_ENSURE_SUCCESS(rvOR, rvOR);
-
- return editor->SetInlineTableEditingEnabled(enabled);
- }
-
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsSetDocumentStateCommand::GetCommandStateParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- NS_ENSURE_ARG_POINTER(aParams);
- NS_ENSURE_ARG_POINTER(refCon);
-
- // The base editor owns most state info
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(editor, NS_ERROR_INVALID_ARG);
-
- // Always get the enabled state
- bool outCmdEnabled = false;
- IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
- nsresult rv = aParams->SetBooleanValue(STATE_ENABLED, outCmdEnabled);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentModified")) {
- bool modified;
- rv = editor->GetDocumentModified(&modified);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return aParams->SetBooleanValue(STATE_ATTRIBUTE, modified);
- }
-
- if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentReadOnly")) {
- NS_ENSURE_ARG_POINTER(aParams);
-
- uint32_t flags;
- editor->GetFlags(&flags);
- bool isReadOnly = flags & nsIPlaintextEditor::eEditorReadonlyMask;
- return aParams->SetBooleanValue(STATE_ATTRIBUTE, isReadOnly);
- }
-
- if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentUseCSS")) {
- NS_ENSURE_ARG_POINTER(aParams);
- nsCOMPtr<nsIHTMLEditor> htmleditor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(htmleditor, NS_ERROR_INVALID_ARG);
-
- bool isCSS;
- htmleditor->GetIsCSSEnabled(&isCSS);
- return aParams->SetBooleanValue(STATE_ALL, isCSS);
- }
-
- if (!nsCRT::strcmp(aCommandName, "cmd_insertBrOnReturn")) {
- NS_ENSURE_ARG_POINTER(aParams);
- nsCOMPtr<nsIHTMLEditor> htmleditor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(htmleditor, NS_ERROR_INVALID_ARG);
-
- bool createPOnReturn;
- htmleditor->GetReturnInParagraphCreatesNewParagraph(&createPOnReturn);
- return aParams->SetBooleanValue(STATE_ATTRIBUTE, !createPOnReturn);
- }
-
- if (!nsCRT::strcmp(aCommandName, "cmd_enableObjectResizing")) {
- NS_ENSURE_ARG_POINTER(aParams);
- nsCOMPtr<nsIHTMLObjectResizer> resizer = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(resizer, NS_ERROR_INVALID_ARG);
-
- bool enabled;
- resizer->GetObjectResizingEnabled(&enabled);
- return aParams->SetBooleanValue(STATE_ATTRIBUTE, enabled);
- }
-
- if (!nsCRT::strcmp(aCommandName, "cmd_enableInlineTableEditing")) {
- NS_ENSURE_ARG_POINTER(aParams);
- nsCOMPtr<nsIHTMLInlineTableEditor> editor = do_QueryInterface(refCon);
- NS_ENSURE_TRUE(editor, NS_ERROR_INVALID_ARG);
-
- bool enabled;
- editor->GetInlineTableEditingEnabled(&enabled);
- return aParams->SetBooleanValue(STATE_ATTRIBUTE, enabled);
- }
-
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/**
- * Commands just for state notification
- * As of 11/21/02, possible commands are:
- * "obs_documentCreated"
- * "obs_documentWillBeDestroyed"
- * "obs_documentLocationChanged"
- * Note that you can use the same command class, nsDocumentStateCommand
- * for these or future observer commands.
- * We check the input command param for different behavior
- *
- * How to use:
- * 1. Get the nsICommandManager for the current editor
- * 2. Implement an nsIObserve object, e.g:
- *
- * void Observe(
- * in nsISupports aSubject, // The nsICommandManager calling this Observer
- * in string aTopic, // command name, e.g.:"obs_documentCreated"
- * // or "obs_documentWillBeDestroyed"
- in wstring aData ); // ignored (set to "command_status_changed")
- *
- * 3. Add the observer by:
- * commandManager.addObserver(observeobject, obs_documentCreated);
- * 4. In the appropriate location in editorSession, editor, or commands code,
- * trigger the notification of this observer by something like:
- *
- * nsCOMPtr<nsICommandManager> commandManager = mDocShell->GetCommandManager();
- * nsCOMPtr<nsPICommandUpdater> commandUpdater = do_QueryInterface(commandManager);
- * NS_ENSURE_TRUE(commandUpdater, NS_ERROR_FAILURE);
- * commandUpdater->CommandStatusChanged(obs_documentCreated);
- *
- * 5. Use GetCommandStateParams() to obtain state information
- * e.g., any creation state codes when creating an editor are
- * supplied for "obs_documentCreated" command in the
- * "state_data" param's value
- *
- */
-
-NS_IMETHODIMP
-nsDocumentStateCommand::IsCommandEnabled(const char* aCommandName,
- nsISupports *refCon,
- bool *outCmdEnabled)
-{
- NS_ENSURE_ARG_POINTER(outCmdEnabled);
- // Always return false to discourage callers from using DoCommand()
- *outCmdEnabled = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDocumentStateCommand::DoCommand(const char *aCommandName,
- nsISupports *refCon)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsDocumentStateCommand::DoCommandParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsDocumentStateCommand::GetCommandStateParams(const char *aCommandName,
- nsICommandParams *aParams,
- nsISupports *refCon)
-{
- NS_ENSURE_ARG_POINTER(aParams);
- NS_ENSURE_ARG_POINTER(aCommandName);
- nsresult rv;
-
- if (!nsCRT::strcmp(aCommandName, "obs_documentCreated")) {
- uint32_t editorStatus = nsIEditingSession::eEditorErrorUnknown;
-
- nsCOMPtr<nsIEditingSession> editingSession = do_QueryInterface(refCon);
- if (editingSession) {
- // refCon is initially set to nsIEditingSession until editor
- // is successfully created and source doc is loaded
- // Embedder gets error status if this fails
- // If called before startup is finished,
- // status = eEditorCreationInProgress
- rv = editingSession->GetEditorStatus(&editorStatus);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // If refCon is an editor, then everything started up OK!
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- if (editor) {
- editorStatus = nsIEditingSession::eEditorOK;
- }
- }
-
- // Note that if refCon is not-null, but is neither
- // an nsIEditingSession or nsIEditor, we return "eEditorErrorUnknown"
- aParams->SetLongValue(STATE_DATA, editorStatus);
- return NS_OK;
- }
-
- if (!nsCRT::strcmp(aCommandName, "obs_documentLocationChanged")) {
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
- if (!editor) {
- return NS_OK;
- }
-
- nsCOMPtr<nsIDOMDocument> domDoc;
- editor->GetDocument(getter_AddRefs(domDoc));
- nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
- NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
-
- nsIURI *uri = doc->GetDocumentURI();
- NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
-
- return aParams->SetISupportsValue(STATE_DATA, (nsISupports*)uri);
- }
-
- return NS_ERROR_NOT_IMPLEMENTED;
-}
diff --git a/editor/composer/nsComposerRegistration.cpp b/editor/composer/nsComposerRegistration.cpp
deleted file mode 100644
index 7a0b3a440..000000000
--- a/editor/composer/nsComposerRegistration.cpp
+++ /dev/null
@@ -1,226 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <stddef.h> // for nullptr
-
-#include "mozilla/Module.h" // for Module, Module::CIDEntry, etc
-#include "mozilla/ModuleUtils.h"
-#include "mozilla/mozalloc.h" // for operator new
-#include "nsCOMPtr.h" // for nsCOMPtr, getter_AddRefs, etc
-#include "nsComponentManagerUtils.h" // for do_CreateInstance
-#include "nsComposeTxtSrvFilter.h" // for nsComposeTxtSrvFilter, etc
-#include "nsComposerController.h" // for nsComposerController, etc
-#include "nsDebug.h" // for NS_ENSURE_SUCCESS
-#include "nsEditingSession.h" // for NS_EDITINGSESSION_CID, etc
-#include "nsEditorSpellCheck.h" // for NS_EDITORSPELLCHECK_CID, etc
-#include "nsError.h" // for NS_ERROR_NO_AGGREGATION, etc
-#include "nsIController.h" // for nsIController
-#include "nsIControllerCommandTable.h" // for nsIControllerCommandTable, etc
-#include "nsIControllerContext.h" // for nsIControllerContext
-#include "nsID.h" // for NS_DEFINE_NAMED_CID, etc
-#include "nsISupportsImpl.h"
-#include "nsISupportsUtils.h" // for NS_ADDREF, NS_RELEASE
-#include "nsServiceManagerUtils.h" // for do_GetService
-#include "nscore.h" // for nsresult
-
-class nsISupports;
-
-#define NS_HTMLEDITOR_COMMANDTABLE_CID \
-{ 0x13e50d8d, 0x9cee, 0x4ad1, { 0xa3, 0xa2, 0x4a, 0x44, 0x2f, 0xdf, 0x7d, 0xfa } }
-
-#define NS_HTMLEDITOR_DOCSTATE_COMMANDTABLE_CID \
-{ 0xa33982d3, 0x1adf, 0x4162, { 0x99, 0x41, 0xf7, 0x34, 0xbc, 0x45, 0xe4, 0xed } }
-
-
-static NS_DEFINE_CID(kHTMLEditorCommandTableCID, NS_HTMLEDITOR_COMMANDTABLE_CID);
-static NS_DEFINE_CID(kHTMLEditorDocStateCommandTableCID, NS_HTMLEDITOR_DOCSTATE_COMMANDTABLE_CID);
-
-
-////////////////////////////////////////////////////////////////////////
-// Define the contructor function for the objects
-//
-// NOTE: This creates an instance of objects by using the default constructor
-//
-
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsEditingSession)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsEditorSpellCheck)
-
-// There are no macros that enable us to have 2 constructors
-// for the same object
-//
-// Here we are creating the same object with two different contract IDs
-// and then initializing it different.
-// Basically, we need to tell the filter whether it is doing mail or not
-static nsresult
-nsComposeTxtSrvFilterConstructor(nsISupports *aOuter, REFNSIID aIID,
- void **aResult, bool aIsForMail)
-{
- *aResult = nullptr;
- if (aOuter) {
- return NS_ERROR_NO_AGGREGATION;
- }
- nsComposeTxtSrvFilter * inst = new nsComposeTxtSrvFilter();
- if (!inst) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- NS_ADDREF(inst);
- inst->Init(aIsForMail);
- nsresult rv = inst->QueryInterface(aIID, aResult);
- NS_RELEASE(inst);
- return rv;
-}
-
-static nsresult
-nsComposeTxtSrvFilterConstructorForComposer(nsISupports *aOuter,
- REFNSIID aIID,
- void **aResult)
-{
- return nsComposeTxtSrvFilterConstructor(aOuter, aIID, aResult, false);
-}
-
-static nsresult
-nsComposeTxtSrvFilterConstructorForMail(nsISupports *aOuter,
- REFNSIID aIID,
- void **aResult)
-{
- return nsComposeTxtSrvFilterConstructor(aOuter, aIID, aResult, true);
-}
-
-
-// Constructor for a controller set up with a command table specified
-// by the CID passed in. This function uses do_GetService to get the
-// command table, so that every controller shares a single command
-// table, for space-efficiency.
-//
-// The only reason to go via the service manager for the command table
-// is that it holds onto the singleton for us, avoiding static variables here.
-static nsresult
-CreateControllerWithSingletonCommandTable(const nsCID& inCommandTableCID, nsIController **aResult)
-{
- nsresult rv;
- nsCOMPtr<nsIController> controller = do_CreateInstance("@mozilla.org/embedcomp/base-command-controller;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIControllerCommandTable> composerCommandTable = do_GetService(inCommandTableCID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // this guy is a singleton, so make it immutable
- composerCommandTable->MakeImmutable();
-
- nsCOMPtr<nsIControllerContext> controllerContext = do_QueryInterface(controller, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = controllerContext->Init(composerCommandTable);
- NS_ENSURE_SUCCESS(rv, rv);
-
- *aResult = controller;
- NS_ADDREF(*aResult);
- return NS_OK;
-}
-
-
-// Here we make an instance of the controller that holds doc state commands.
-// We set it up with a singleton command table.
-static nsresult
-nsHTMLEditorDocStateControllerConstructor(nsISupports *aOuter, REFNSIID aIID,
- void **aResult)
-{
- nsCOMPtr<nsIController> controller;
- nsresult rv = CreateControllerWithSingletonCommandTable(kHTMLEditorDocStateCommandTableCID, getter_AddRefs(controller));
- NS_ENSURE_SUCCESS(rv, rv);
-
- return controller->QueryInterface(aIID, aResult);
-}
-
-// Tere we make an instance of the controller that holds composer commands.
-// We set it up with a singleton command table.
-static nsresult
-nsHTMLEditorControllerConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult)
-{
- nsCOMPtr<nsIController> controller;
- nsresult rv = CreateControllerWithSingletonCommandTable(kHTMLEditorCommandTableCID, getter_AddRefs(controller));
- NS_ENSURE_SUCCESS(rv, rv);
-
- return controller->QueryInterface(aIID, aResult);
-}
-
-// Constructor for a command table that is pref-filled with HTML editor commands
-static nsresult
-nsHTMLEditorCommandTableConstructor(nsISupports *aOuter, REFNSIID aIID,
- void **aResult)
-{
- nsresult rv;
- nsCOMPtr<nsIControllerCommandTable> commandTable =
- do_CreateInstance(NS_CONTROLLERCOMMANDTABLE_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = nsComposerController::RegisterHTMLEditorCommands(commandTable);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // we don't know here whether we're being created as an instance,
- // or a service, so we can't become immutable
-
- return commandTable->QueryInterface(aIID, aResult);
-}
-
-
-// Constructor for a command table that is pref-filled with HTML editor doc state commands
-static nsresult
-nsHTMLEditorDocStateCommandTableConstructor(nsISupports *aOuter, REFNSIID aIID,
- void **aResult)
-{
- nsresult rv;
- nsCOMPtr<nsIControllerCommandTable> commandTable =
- do_CreateInstance(NS_CONTROLLERCOMMANDTABLE_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = nsComposerController::RegisterEditorDocStateCommands(commandTable);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // we don't know here whether we're being created as an instance,
- // or a service, so we can't become immutable
-
- return commandTable->QueryInterface(aIID, aResult);
-}
-
-NS_DEFINE_NAMED_CID(NS_HTMLEDITORCONTROLLER_CID);
-NS_DEFINE_NAMED_CID(NS_EDITORDOCSTATECONTROLLER_CID);
-NS_DEFINE_NAMED_CID(NS_HTMLEDITOR_COMMANDTABLE_CID);
-NS_DEFINE_NAMED_CID(NS_HTMLEDITOR_DOCSTATE_COMMANDTABLE_CID);
-NS_DEFINE_NAMED_CID(NS_EDITINGSESSION_CID);
-NS_DEFINE_NAMED_CID(NS_EDITORSPELLCHECK_CID);
-NS_DEFINE_NAMED_CID(NS_COMPOSERTXTSRVFILTER_CID);
-NS_DEFINE_NAMED_CID(NS_COMPOSERTXTSRVFILTERMAIL_CID);
-
-
-static const mozilla::Module::CIDEntry kComposerCIDs[] = {
- { &kNS_HTMLEDITORCONTROLLER_CID, false, nullptr, nsHTMLEditorControllerConstructor },
- { &kNS_EDITORDOCSTATECONTROLLER_CID, false, nullptr, nsHTMLEditorDocStateControllerConstructor },
- { &kNS_HTMLEDITOR_COMMANDTABLE_CID, false, nullptr, nsHTMLEditorCommandTableConstructor },
- { &kNS_HTMLEDITOR_DOCSTATE_COMMANDTABLE_CID, false, nullptr, nsHTMLEditorDocStateCommandTableConstructor },
- { &kNS_EDITINGSESSION_CID, false, nullptr, nsEditingSessionConstructor },
- { &kNS_EDITORSPELLCHECK_CID, false, nullptr, nsEditorSpellCheckConstructor },
- { &kNS_COMPOSERTXTSRVFILTER_CID, false, nullptr, nsComposeTxtSrvFilterConstructorForComposer },
- { &kNS_COMPOSERTXTSRVFILTERMAIL_CID, false, nullptr, nsComposeTxtSrvFilterConstructorForMail },
- { nullptr }
-};
-
-static const mozilla::Module::ContractIDEntry kComposerContracts[] = {
- { "@mozilla.org/editor/htmleditorcontroller;1", &kNS_HTMLEDITORCONTROLLER_CID },
- { "@mozilla.org/editor/editordocstatecontroller;1", &kNS_EDITORDOCSTATECONTROLLER_CID },
- { "@mozilla.org/editor/editingsession;1", &kNS_EDITINGSESSION_CID },
- { "@mozilla.org/editor/editorspellchecker;1", &kNS_EDITORSPELLCHECK_CID },
- { COMPOSER_TXTSRVFILTER_CONTRACTID, &kNS_COMPOSERTXTSRVFILTER_CID },
- { COMPOSER_TXTSRVFILTERMAIL_CONTRACTID, &kNS_COMPOSERTXTSRVFILTERMAIL_CID },
- { nullptr }
-};
-
-static const mozilla::Module kComposerModule = {
- mozilla::Module::kVersion,
- kComposerCIDs,
- kComposerContracts
-};
-
-NSMODULE_DEFN(nsComposerModule) = &kComposerModule;
diff --git a/editor/composer/nsEditingSession.cpp b/editor/composer/nsEditingSession.cpp
deleted file mode 100644
index f376d2bad..000000000
--- a/editor/composer/nsEditingSession.cpp
+++ /dev/null
@@ -1,1391 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <string.h> // for nullptr, strcmp
-
-#include "imgIContainer.h" // for imgIContainer, etc
-#include "mozFlushType.h" // for mozFlushType::Flush_Frames
-#include "mozilla/mozalloc.h" // for operator new
-#include "nsAString.h"
-#include "nsComponentManagerUtils.h" // for do_CreateInstance
-#include "nsComposerCommandsUpdater.h" // for nsComposerCommandsUpdater
-#include "nsDebug.h" // for NS_ENSURE_SUCCESS, etc
-#include "nsEditingSession.h"
-#include "nsError.h" // for NS_ERROR_FAILURE, NS_OK, etc
-#include "nsIChannel.h" // for nsIChannel
-#include "nsICommandManager.h" // for nsICommandManager
-#include "nsIContentViewer.h" // for nsIContentViewer
-#include "nsIController.h" // for nsIController
-#include "nsIControllerContext.h" // for nsIControllerContext
-#include "nsIControllers.h" // for nsIControllers
-#include "nsID.h" // for NS_GET_IID, etc
-#include "nsIDOMDocument.h" // for nsIDOMDocument
-#include "nsIDOMHTMLDocument.h" // for nsIDOMHTMLDocument
-#include "nsIDOMWindow.h" // for nsIDOMWindow
-#include "nsIDocShell.h" // for nsIDocShell
-#include "nsIDocument.h" // for nsIDocument
-#include "nsIDocumentStateListener.h"
-#include "nsIEditor.h" // for nsIEditor
-#include "nsIHTMLDocument.h" // for nsIHTMLDocument, etc
-#include "nsIInterfaceRequestorUtils.h" // for do_GetInterface
-#include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc
-#include "nsIPresShell.h" // for nsIPresShell
-#include "nsIRefreshURI.h" // for nsIRefreshURI
-#include "nsIRequest.h" // for nsIRequest
-#include "nsISelection.h" // for nsISelection
-#include "nsISelectionPrivate.h" // for nsISelectionPrivate
-#include "nsITimer.h" // for nsITimer, etc
-#include "nsITransactionManager.h" // for nsITransactionManager
-#include "nsIWeakReference.h" // for nsISupportsWeakReference, etc
-#include "nsIWebNavigation.h" // for nsIWebNavigation
-#include "nsIWebProgress.h" // for nsIWebProgress, etc
-#include "nsLiteralString.h" // for NS_LITERAL_STRING
-#include "nsPICommandUpdater.h" // for nsPICommandUpdater
-#include "nsPIDOMWindow.h" // for nsPIDOMWindow
-#include "nsPresContext.h" // for nsPresContext
-#include "nsReadableUtils.h" // for AppendUTF16toUTF8
-#include "nsStringFwd.h" // for nsAFlatString
-#include "mozilla/dom/Selection.h" // for AutoHideSelectionChanges
-#include "nsFrameSelection.h" // for nsFrameSelection
-
-class nsISupports;
-class nsIURI;
-
-/*---------------------------------------------------------------------------
-
- nsEditingSession
-
-----------------------------------------------------------------------------*/
-nsEditingSession::nsEditingSession()
-: mDoneSetup(false)
-, mCanCreateEditor(false)
-, mInteractive(false)
-, mMakeWholeDocumentEditable(true)
-, mDisabledJSAndPlugins(false)
-, mScriptsEnabled(true)
-, mPluginsEnabled(true)
-, mProgressListenerRegistered(false)
-, mImageAnimationMode(0)
-, mEditorFlags(0)
-, mEditorStatus(eEditorOK)
-, mBaseCommandControllerId(0)
-, mDocStateControllerId(0)
-, mHTMLCommandControllerId(0)
-{
-}
-
-/*---------------------------------------------------------------------------
-
- ~nsEditingSession
-
-----------------------------------------------------------------------------*/
-nsEditingSession::~nsEditingSession()
-{
- // Must cancel previous timer?
- if (mLoadBlankDocTimer)
- mLoadBlankDocTimer->Cancel();
-}
-
-NS_IMPL_ISUPPORTS(nsEditingSession, nsIEditingSession, nsIWebProgressListener,
- nsISupportsWeakReference)
-
-/*---------------------------------------------------------------------------
-
- MakeWindowEditable
-
- aEditorType string, "html" "htmlsimple" "text" "textsimple"
- void makeWindowEditable(in nsIDOMWindow aWindow, in string aEditorType,
- in boolean aDoAfterUriLoad,
- in boolean aMakeWholeDocumentEditable,
- in boolean aInteractive);
-----------------------------------------------------------------------------*/
-#define DEFAULT_EDITOR_TYPE "html"
-
-NS_IMETHODIMP
-nsEditingSession::MakeWindowEditable(mozIDOMWindowProxy* aWindow,
- const char *aEditorType,
- bool aDoAfterUriLoad,
- bool aMakeWholeDocumentEditable,
- bool aInteractive)
-{
- mEditorType.Truncate();
- mEditorFlags = 0;
-
- NS_ENSURE_TRUE(aWindow, NS_ERROR_FAILURE);
- auto* window = nsPIDOMWindowOuter::From(aWindow);
-
- // disable plugins
- nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
- NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
-
- mDocShell = do_GetWeakReference(docShell);
- mInteractive = aInteractive;
- mMakeWholeDocumentEditable = aMakeWholeDocumentEditable;
-
- nsresult rv;
- if (!mInteractive) {
- rv = DisableJSAndPlugins(aWindow);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // Always remove existing editor
- TearDownEditorOnWindow(aWindow);
-
- // Tells embedder that startup is in progress
- mEditorStatus = eEditorCreationInProgress;
-
- //temporary to set editor type here. we will need different classes soon.
- if (!aEditorType)
- aEditorType = DEFAULT_EDITOR_TYPE;
- mEditorType = aEditorType;
-
- // if all this does is setup listeners and I don't need listeners,
- // can't this step be ignored?? (based on aDoAfterURILoad)
- rv = PrepareForEditing(window);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // set the flag on the docShell to say that it's editable
- rv = docShell->MakeEditable(aDoAfterUriLoad);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Setup commands common to plaintext and html editors,
- // including the document creation observers
- // the first is an editing controller
- rv = SetupEditorCommandController("@mozilla.org/editor/editingcontroller;1",
- aWindow,
- static_cast<nsIEditingSession*>(this),
- &mBaseCommandControllerId);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // The second is a controller to monitor doc state,
- // such as creation and "dirty flag"
- rv = SetupEditorCommandController("@mozilla.org/editor/editordocstatecontroller;1",
- aWindow,
- static_cast<nsIEditingSession*>(this),
- &mDocStateControllerId);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // aDoAfterUriLoad can be false only when making an existing window editable
- if (!aDoAfterUriLoad) {
- rv = SetupEditorOnWindow(aWindow);
-
- // mEditorStatus is set to the error reason
- // Since this is used only when editing an existing page,
- // it IS ok to destroy current editor
- if (NS_FAILED(rv)) {
- TearDownEditorOnWindow(aWindow);
- }
- }
- return rv;
-}
-
-NS_IMETHODIMP
-nsEditingSession::DisableJSAndPlugins(mozIDOMWindowProxy* aWindow)
-{
- NS_ENSURE_TRUE(aWindow, NS_ERROR_FAILURE);
- nsIDocShell *docShell = nsPIDOMWindowOuter::From(aWindow)->GetDocShell();
- NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
-
- bool tmp;
- nsresult rv = docShell->GetAllowJavascript(&tmp);
- NS_ENSURE_SUCCESS(rv, rv);
-
- mScriptsEnabled = tmp;
-
- rv = docShell->SetAllowJavascript(false);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Disable plugins in this document:
- mPluginsEnabled = docShell->PluginsAllowedInCurrentDoc();
-
- rv = docShell->SetAllowPlugins(false);
- NS_ENSURE_SUCCESS(rv, rv);
-
- mDisabledJSAndPlugins = true;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsEditingSession::RestoreJSAndPlugins(mozIDOMWindowProxy* aWindow)
-{
- if (!mDisabledJSAndPlugins) {
- return NS_OK;
- }
-
- mDisabledJSAndPlugins = false;
-
- NS_ENSURE_TRUE(aWindow, NS_ERROR_FAILURE);
- nsIDocShell *docShell = nsPIDOMWindowOuter::From(aWindow)->GetDocShell();
- NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
-
- nsresult rv = docShell->SetAllowJavascript(mScriptsEnabled);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Disable plugins in this document:
- return docShell->SetAllowPlugins(mPluginsEnabled);
-}
-
-NS_IMETHODIMP
-nsEditingSession::GetJsAndPluginsDisabled(bool *aResult)
-{
- NS_ENSURE_ARG_POINTER(aResult);
- *aResult = mDisabledJSAndPlugins;
- return NS_OK;
-}
-
-/*---------------------------------------------------------------------------
-
- WindowIsEditable
-
- boolean windowIsEditable (in nsIDOMWindow aWindow);
-----------------------------------------------------------------------------*/
-NS_IMETHODIMP
-nsEditingSession::WindowIsEditable(mozIDOMWindowProxy* aWindow,
- bool *outIsEditable)
-{
- NS_ENSURE_STATE(aWindow);
- nsCOMPtr<nsIDocShell> docShell = nsPIDOMWindowOuter::From(aWindow)->GetDocShell();
- NS_ENSURE_STATE(docShell);
-
- return docShell->GetEditable(outIsEditable);
-}
-
-
-// These are MIME types that are automatically parsed as "text/plain"
-// and thus we can edit them as plaintext
-// Note: in older versions, we attempted to convert the mimetype of
-// the network channel for these and "text/xml" to "text/plain",
-// but further investigation reveals that strategy doesn't work
-const char* const gSupportedTextTypes[] = {
- "text/plain",
- "text/css",
- "text/rdf",
- "text/xsl",
- "text/javascript", // obsolete type
- "text/ecmascript", // obsolete type
- "application/javascript",
- "application/ecmascript",
- "application/x-javascript", // obsolete type
- "text/xul", // obsolete type
- "application/vnd.mozilla.xul+xml",
- nullptr // IMPORTANT! Null must be at end
-};
-
-bool
-IsSupportedTextType(const char* aMIMEType)
-{
- NS_ENSURE_TRUE(aMIMEType, false);
-
- for (size_t i = 0; gSupportedTextTypes[i]; ++i) {
- if (!strcmp(gSupportedTextTypes[i], aMIMEType)) {
- return true;
- }
- }
-
- return false;
-}
-
-/*---------------------------------------------------------------------------
-
- SetupEditorOnWindow
-
- nsIEditor setupEditorOnWindow (in nsIDOMWindow aWindow);
-----------------------------------------------------------------------------*/
-NS_IMETHODIMP
-nsEditingSession::SetupEditorOnWindow(mozIDOMWindowProxy* aWindow)
-{
- mDoneSetup = true;
-
- NS_ENSURE_TRUE(aWindow, NS_ERROR_FAILURE);
- auto* window = nsPIDOMWindowOuter::From(aWindow);
-
- nsresult rv;
-
- //MIME CHECKING
- //must get the content type
- // Note: the doc gets this from the network channel during StartPageLoad,
- // so we don't have to get it from there ourselves
- nsAutoCString mimeCType;
-
- //then lets check the mime type
- if (nsCOMPtr<nsIDocument> doc = window->GetDoc()) {
- nsAutoString mimeType;
- if (NS_SUCCEEDED(doc->GetContentType(mimeType)))
- AppendUTF16toUTF8(mimeType, mimeCType);
-
- if (IsSupportedTextType(mimeCType.get())) {
- mEditorType.AssignLiteral("text");
- mimeCType = "text/plain";
- } else if (!mimeCType.EqualsLiteral("text/html") &&
- !mimeCType.EqualsLiteral("application/xhtml+xml")) {
- // Neither an acceptable text or html type.
- mEditorStatus = eEditorErrorCantEditMimeType;
-
- // Turn editor into HTML -- we will load blank page later
- mEditorType.AssignLiteral("html");
- mimeCType.AssignLiteral("text/html");
- }
-
- // Flush out frame construction to make sure that the subframe's
- // presshell is set up if it needs to be.
- nsCOMPtr<nsIDocument> document = do_QueryInterface(doc);
- if (document) {
- document->FlushPendingNotifications(Flush_Frames);
- if (mMakeWholeDocumentEditable) {
- document->SetEditableFlag(true);
- nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(document);
- if (htmlDocument) {
- // Enable usage of the execCommand API
- htmlDocument->SetEditingState(nsIHTMLDocument::eDesignMode);
- }
- }
- }
- }
- bool needHTMLController = false;
-
- const char *classString = "@mozilla.org/editor/htmleditor;1";
- if (mEditorType.EqualsLiteral("textmail")) {
- mEditorFlags = nsIPlaintextEditor::eEditorPlaintextMask |
- nsIPlaintextEditor::eEditorEnableWrapHackMask |
- nsIPlaintextEditor::eEditorMailMask;
- } else if (mEditorType.EqualsLiteral("text")) {
- mEditorFlags = nsIPlaintextEditor::eEditorPlaintextMask |
- nsIPlaintextEditor::eEditorEnableWrapHackMask;
- } else if (mEditorType.EqualsLiteral("htmlmail")) {
- if (mimeCType.EqualsLiteral("text/html")) {
- needHTMLController = true;
- mEditorFlags = nsIPlaintextEditor::eEditorMailMask;
- } else {
- // Set the flags back to textplain.
- mEditorFlags = nsIPlaintextEditor::eEditorPlaintextMask |
- nsIPlaintextEditor::eEditorEnableWrapHackMask;
- }
- } else {
- // Defaulted to html
- needHTMLController = true;
- }
-
- if (mInteractive) {
- mEditorFlags |= nsIPlaintextEditor::eEditorAllowInteraction;
- }
-
- // make the UI state maintainer
- mStateMaintainer = new nsComposerCommandsUpdater();
-
- // now init the state maintainer
- // This allows notification of error state
- // even if we don't create an editor
- rv = mStateMaintainer->Init(window);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (mEditorStatus != eEditorCreationInProgress) {
- mStateMaintainer->NotifyDocumentCreated();
- return NS_ERROR_FAILURE;
- }
-
- // Create editor and do other things
- // only if we haven't found some error above,
- nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
- NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
- nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
- NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
-
- if (!mInteractive) {
- // Disable animation of images in this document:
- nsPresContext* presContext = presShell->GetPresContext();
- NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
-
- mImageAnimationMode = presContext->ImageAnimationMode();
- presContext->SetImageAnimationMode(imgIContainer::kDontAnimMode);
- }
-
- // Hide selection changes during initialization, in order to hide this
- // from web pages.
- RefPtr<nsFrameSelection> fs = presShell->FrameSelection();
- NS_ENSURE_TRUE(fs, NS_ERROR_FAILURE);
- mozilla::dom::AutoHideSelectionChanges hideSelectionChanges(fs);
-
- // create and set editor
- // Try to reuse an existing editor
- nsCOMPtr<nsIEditor> editor = do_QueryReferent(mExistingEditor);
- if (editor) {
- editor->PreDestroy(false);
- } else {
- editor = do_CreateInstance(classString, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- mExistingEditor = do_GetWeakReference(editor);
- }
- // set the editor on the docShell. The docShell now owns it.
- rv = docShell->SetEditor(editor);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // setup the HTML editor command controller
- if (needHTMLController) {
- // The third controller takes an nsIEditor as the context
- rv = SetupEditorCommandController("@mozilla.org/editor/htmleditorcontroller;1",
- aWindow, editor,
- &mHTMLCommandControllerId);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // Set mimetype on editor
- rv = editor->SetContentsMIMEType(mimeCType.get());
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIContentViewer> contentViewer;
- rv = docShell->GetContentViewer(getter_AddRefs(contentViewer));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(contentViewer, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIDOMDocument> domDoc;
- rv = contentViewer->GetDOMDocument(getter_AddRefs(domDoc));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
-
- // Set up as a doc state listener
- // Important! We must have this to broadcast the "obs_documentCreated" message
- rv = editor->AddDocumentStateListener(mStateMaintainer);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = editor->Init(domDoc, nullptr /* root content */,
- nullptr, mEditorFlags, EmptyString());
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsISelection> selection;
- editor->GetSelection(getter_AddRefs(selection));
- nsCOMPtr<nsISelectionPrivate> selPriv = do_QueryInterface(selection);
- NS_ENSURE_TRUE(selPriv, NS_ERROR_FAILURE);
-
- rv = selPriv->AddSelectionListener(mStateMaintainer);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // and as a transaction listener
- nsCOMPtr<nsITransactionManager> txnMgr;
- editor->GetTransactionManager(getter_AddRefs(txnMgr));
- if (txnMgr) {
- txnMgr->AddListener(mStateMaintainer);
- }
-
- // Set context on all controllers to be the editor
- rv = SetEditorOnControllers(aWindow, editor);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Everything went fine!
- mEditorStatus = eEditorOK;
-
- // This will trigger documentCreation notification
- return editor->PostCreate();
-}
-
-// Removes all listeners and controllers from aWindow and aEditor.
-void
-nsEditingSession::RemoveListenersAndControllers(nsPIDOMWindowOuter* aWindow,
- nsIEditor *aEditor)
-{
- if (!mStateMaintainer || !aEditor) {
- return;
- }
-
- // Remove all the listeners
- nsCOMPtr<nsISelection> selection;
- aEditor->GetSelection(getter_AddRefs(selection));
- nsCOMPtr<nsISelectionPrivate> selPriv = do_QueryInterface(selection);
- if (selPriv)
- selPriv->RemoveSelectionListener(mStateMaintainer);
-
- aEditor->RemoveDocumentStateListener(mStateMaintainer);
-
- nsCOMPtr<nsITransactionManager> txnMgr;
- aEditor->GetTransactionManager(getter_AddRefs(txnMgr));
- if (txnMgr) {
- txnMgr->RemoveListener(mStateMaintainer);
- }
-
- // Remove editor controllers from the window now that we're not
- // editing in that window any more.
- RemoveEditorControllers(aWindow);
-}
-
-/*---------------------------------------------------------------------------
-
- TearDownEditorOnWindow
-
- void tearDownEditorOnWindow (in nsIDOMWindow aWindow);
-----------------------------------------------------------------------------*/
-NS_IMETHODIMP
-nsEditingSession::TearDownEditorOnWindow(mozIDOMWindowProxy *aWindow)
-{
- if (!mDoneSetup) {
- return NS_OK;
- }
-
- NS_ENSURE_TRUE(aWindow, NS_ERROR_NULL_POINTER);
-
- nsresult rv;
-
- // Kill any existing reload timer
- if (mLoadBlankDocTimer) {
- mLoadBlankDocTimer->Cancel();
- mLoadBlankDocTimer = nullptr;
- }
-
- mDoneSetup = false;
-
- // Check if we're turning off editing (from contentEditable or designMode).
- auto* window = nsPIDOMWindowOuter::From(aWindow);
-
- nsCOMPtr<nsIDocument> doc = window->GetDoc();
- nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(doc);
- bool stopEditing = htmlDoc && htmlDoc->IsEditingOn();
- if (stopEditing) {
- RemoveWebProgressListener(window);
- }
-
- nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
- NS_ENSURE_STATE(docShell);
-
- nsCOMPtr<nsIEditor> editor;
- rv = docShell->GetEditor(getter_AddRefs(editor));
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (stopEditing) {
- htmlDoc->TearingDownEditor(editor);
- }
-
- if (mStateMaintainer && editor) {
- // Null out the editor on the controllers first to prevent their weak
- // references from pointing to a destroyed editor.
- SetEditorOnControllers(aWindow, nullptr);
- }
-
- // Null out the editor on the docShell to trigger PreDestroy which
- // needs to happen before document state listeners are removed below.
- docShell->SetEditor(nullptr);
-
- RemoveListenersAndControllers(window, editor);
-
- if (stopEditing) {
- // Make things the way they were before we started editing.
- RestoreJSAndPlugins(aWindow);
- RestoreAnimationMode(window);
-
- if (mMakeWholeDocumentEditable) {
- doc->SetEditableFlag(false);
- nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(doc);
- if (htmlDocument) {
- htmlDocument->SetEditingState(nsIHTMLDocument::eOff);
- }
- }
- }
-
- return rv;
-}
-
-/*---------------------------------------------------------------------------
-
- GetEditorForFrame
-
- nsIEditor getEditorForFrame (in nsIDOMWindow aWindow);
-----------------------------------------------------------------------------*/
-NS_IMETHODIMP
-nsEditingSession::GetEditorForWindow(mozIDOMWindowProxy* aWindow,
- nsIEditor **outEditor)
-{
- NS_ENSURE_STATE(aWindow);
- nsCOMPtr<nsIDocShell> docShell = nsPIDOMWindowOuter::From(aWindow)->GetDocShell();
- NS_ENSURE_STATE(docShell);
-
- return docShell->GetEditor(outEditor);
-}
-
-/*---------------------------------------------------------------------------
-
- OnStateChange
-
-----------------------------------------------------------------------------*/
-NS_IMETHODIMP
-nsEditingSession::OnStateChange(nsIWebProgress *aWebProgress,
- nsIRequest *aRequest,
- uint32_t aStateFlags, nsresult aStatus)
-{
-
-#ifdef NOISY_DOC_LOADING
- nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
- if (channel) {
- nsAutoCString contentType;
- channel->GetContentType(contentType);
- if (!contentType.IsEmpty()) {
- printf(" ++++++ MIMETYPE = %s\n", contentType.get());
- }
- }
-#endif
-
- //
- // A Request has started...
- //
- if (aStateFlags & nsIWebProgressListener::STATE_START) {
-#ifdef NOISY_DOC_LOADING
- {
- nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
- if (channel) {
- nsCOMPtr<nsIURI> uri;
- channel->GetURI(getter_AddRefs(uri));
- if (uri) {
- nsXPIDLCString spec;
- uri->GetSpec(spec);
- printf(" **** STATE_START: CHANNEL URI=%s, flags=%x\n",
- spec.get(), aStateFlags);
- }
- } else {
- printf(" STATE_START: NO CHANNEL flags=%x\n", aStateFlags);
- }
- }
-#endif
- // Page level notification...
- if (aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK) {
- nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
- StartPageLoad(channel);
-#ifdef NOISY_DOC_LOADING
- printf("STATE_START & STATE_IS_NETWORK flags=%x\n", aStateFlags);
-#endif
- }
-
- // Document level notification...
- if (aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT &&
- !(aStateFlags & nsIWebProgressListener::STATE_RESTORING)) {
-#ifdef NOISY_DOC_LOADING
- printf("STATE_START & STATE_IS_DOCUMENT flags=%x\n", aStateFlags);
-#endif
-
- bool progressIsForTargetDocument =
- IsProgressForTargetDocument(aWebProgress);
-
- if (progressIsForTargetDocument) {
- nsCOMPtr<mozIDOMWindowProxy> window;
- aWebProgress->GetDOMWindow(getter_AddRefs(window));
-
- auto* piWindow = nsPIDOMWindowOuter::From(window);
- nsCOMPtr<nsIDocument> doc = piWindow->GetDoc();
-
- nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(doc));
-
- if (htmlDoc && htmlDoc->IsWriting()) {
- nsCOMPtr<nsIDOMHTMLDocument> htmlDomDoc = do_QueryInterface(doc);
- nsAutoString designMode;
- htmlDomDoc->GetDesignMode(designMode);
-
- if (designMode.EqualsLiteral("on")) {
- // This notification is for data coming in through
- // document.open/write/close(), ignore it.
-
- return NS_OK;
- }
- }
-
- mCanCreateEditor = true;
- StartDocumentLoad(aWebProgress, progressIsForTargetDocument);
- }
- }
- }
- //
- // A Request is being processed
- //
- else if (aStateFlags & nsIWebProgressListener::STATE_TRANSFERRING) {
- if (aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT) {
- // document transfer started
- }
- }
- //
- // Got a redirection
- //
- else if (aStateFlags & nsIWebProgressListener::STATE_REDIRECTING) {
- if (aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT) {
- // got a redirect
- }
- }
- //
- // A network or document Request has finished...
- //
- else if (aStateFlags & nsIWebProgressListener::STATE_STOP) {
-#ifdef NOISY_DOC_LOADING
- {
- nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
- if (channel) {
- nsCOMPtr<nsIURI> uri;
- channel->GetURI(getter_AddRefs(uri));
- if (uri) {
- nsXPIDLCString spec;
- uri->GetSpec(spec);
- printf(" **** STATE_STOP: CHANNEL URI=%s, flags=%x\n",
- spec.get(), aStateFlags);
- }
- } else {
- printf(" STATE_STOP: NO CHANNEL flags=%x\n", aStateFlags);
- }
- }
-#endif
-
- // Document level notification...
- if (aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT) {
- nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
- EndDocumentLoad(aWebProgress, channel, aStatus,
- IsProgressForTargetDocument(aWebProgress));
-#ifdef NOISY_DOC_LOADING
- printf("STATE_STOP & STATE_IS_DOCUMENT flags=%x\n", aStateFlags);
-#endif
- }
-
- // Page level notification...
- if (aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK) {
- nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
- (void)EndPageLoad(aWebProgress, channel, aStatus);
-#ifdef NOISY_DOC_LOADING
- printf("STATE_STOP & STATE_IS_NETWORK flags=%x\n", aStateFlags);
-#endif
- }
- }
-
- return NS_OK;
-}
-
-/*---------------------------------------------------------------------------
-
- OnProgressChange
-
-----------------------------------------------------------------------------*/
-NS_IMETHODIMP
-nsEditingSession::OnProgressChange(nsIWebProgress *aWebProgress,
- nsIRequest *aRequest,
- int32_t aCurSelfProgress,
- int32_t aMaxSelfProgress,
- int32_t aCurTotalProgress,
- int32_t aMaxTotalProgress)
-{
- NS_NOTREACHED("notification excluded in AddProgressListener(...)");
- return NS_OK;
-}
-
-/*---------------------------------------------------------------------------
-
- OnLocationChange
-
-----------------------------------------------------------------------------*/
-NS_IMETHODIMP
-nsEditingSession::OnLocationChange(nsIWebProgress *aWebProgress,
- nsIRequest *aRequest, nsIURI *aURI,
- uint32_t aFlags)
-{
- nsCOMPtr<mozIDOMWindowProxy> domWindow;
- nsresult rv = aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
- NS_ENSURE_SUCCESS(rv, rv);
-
- auto* piWindow = nsPIDOMWindowOuter::From(domWindow);
-
- nsCOMPtr<nsIDocument> doc = piWindow->GetDoc();
- NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
-
- doc->SetDocumentURI(aURI);
-
- // Notify the location-changed observer that
- // the document URL has changed
- nsIDocShell *docShell = piWindow->GetDocShell();
- NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsICommandManager> commandManager = docShell->GetCommandManager();
- nsCOMPtr<nsPICommandUpdater> commandUpdater =
- do_QueryInterface(commandManager);
- NS_ENSURE_TRUE(commandUpdater, NS_ERROR_FAILURE);
-
- return commandUpdater->CommandStatusChanged("obs_documentLocationChanged");
-}
-
-/*---------------------------------------------------------------------------
-
- OnStatusChange
-
-----------------------------------------------------------------------------*/
-NS_IMETHODIMP
-nsEditingSession::OnStatusChange(nsIWebProgress *aWebProgress,
- nsIRequest *aRequest,
- nsresult aStatus,
- const char16_t *aMessage)
-{
- NS_NOTREACHED("notification excluded in AddProgressListener(...)");
- return NS_OK;
-}
-
-/*---------------------------------------------------------------------------
-
- OnSecurityChange
-
-----------------------------------------------------------------------------*/
-NS_IMETHODIMP
-nsEditingSession::OnSecurityChange(nsIWebProgress *aWebProgress,
- nsIRequest *aRequest, uint32_t state)
-{
- NS_NOTREACHED("notification excluded in AddProgressListener(...)");
- return NS_OK;
-}
-
-
-/*---------------------------------------------------------------------------
-
- IsProgressForTargetDocument
-
- Check that this notification is for our document.
-----------------------------------------------------------------------------*/
-
-bool
-nsEditingSession::IsProgressForTargetDocument(nsIWebProgress *aWebProgress)
-{
- nsCOMPtr<nsIWebProgress> editedWebProgress = do_QueryReferent(mDocShell);
- return editedWebProgress == aWebProgress;
-}
-
-
-/*---------------------------------------------------------------------------
-
- GetEditorStatus
-
- Called during GetCommandStateParams("obs_documentCreated"...)
- to determine if editor was created and document
- was loaded successfully
-----------------------------------------------------------------------------*/
-NS_IMETHODIMP
-nsEditingSession::GetEditorStatus(uint32_t *aStatus)
-{
- NS_ENSURE_ARG_POINTER(aStatus);
- *aStatus = mEditorStatus;
- return NS_OK;
-}
-
-/*---------------------------------------------------------------------------
-
- StartDocumentLoad
-
- Called on start of load in a single frame
-----------------------------------------------------------------------------*/
-nsresult
-nsEditingSession::StartDocumentLoad(nsIWebProgress *aWebProgress,
- bool aIsToBeMadeEditable)
-{
-#ifdef NOISY_DOC_LOADING
- printf("======= StartDocumentLoad ========\n");
-#endif
-
- NS_ENSURE_ARG_POINTER(aWebProgress);
-
- if (aIsToBeMadeEditable) {
- mEditorStatus = eEditorCreationInProgress;
- }
-
- return NS_OK;
-}
-
-/*---------------------------------------------------------------------------
-
- EndDocumentLoad
-
- Called on end of load in a single frame
-----------------------------------------------------------------------------*/
-nsresult
-nsEditingSession::EndDocumentLoad(nsIWebProgress *aWebProgress,
- nsIChannel* aChannel, nsresult aStatus,
- bool aIsToBeMadeEditable)
-{
- NS_ENSURE_ARG_POINTER(aWebProgress);
-
-#ifdef NOISY_DOC_LOADING
- printf("======= EndDocumentLoad ========\n");
- printf("with status %d, ", aStatus);
- nsCOMPtr<nsIURI> uri;
- nsXPIDLCString spec;
- if (NS_SUCCEEDED(aChannel->GetURI(getter_AddRefs(uri)))) {
- uri->GetSpec(spec);
- printf(" uri %s\n", spec.get());
- }
-#endif
-
- // We want to call the base class EndDocumentLoad,
- // but avoid some of the stuff
- // that nsDocShell does (need to refactor).
-
- // OK, time to make an editor on this document
- nsCOMPtr<mozIDOMWindowProxy> domWindow;
- aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
- NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
-
- // Set the error state -- we will create an editor
- // anyway and load empty doc later
- if (aIsToBeMadeEditable && aStatus == NS_ERROR_FILE_NOT_FOUND) {
- mEditorStatus = eEditorErrorFileNotFound;
- }
-
- nsIDocShell *docShell = nsPIDOMWindowOuter::From(domWindow)->GetDocShell();
- NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); // better error handling?
-
- // cancel refresh from meta tags
- // we need to make sure that all pages in editor (whether editable or not)
- // can't refresh contents being edited
- nsCOMPtr<nsIRefreshURI> refreshURI = do_QueryInterface(docShell);
- if (refreshURI) {
- refreshURI->CancelRefreshURITimers();
- }
-
- nsresult rv = NS_OK;
-
- // did someone set the flag to make this shell editable?
- if (aIsToBeMadeEditable && mCanCreateEditor) {
- bool makeEditable;
- docShell->GetEditable(&makeEditable);
-
- if (makeEditable) {
- // To keep pre Gecko 1.9 behavior, setup editor always when
- // mMakeWholeDocumentEditable.
- bool needsSetup = false;
- if (mMakeWholeDocumentEditable) {
- needsSetup = true;
- } else {
- // do we already have an editor here?
- nsCOMPtr<nsIEditor> editor;
- rv = docShell->GetEditor(getter_AddRefs(editor));
- NS_ENSURE_SUCCESS(rv, rv);
-
- needsSetup = !editor;
- }
-
- if (needsSetup) {
- mCanCreateEditor = false;
- rv = SetupEditorOnWindow(domWindow);
- if (NS_FAILED(rv)) {
- // If we had an error, setup timer to load a blank page later
- if (mLoadBlankDocTimer) {
- // Must cancel previous timer?
- mLoadBlankDocTimer->Cancel();
- mLoadBlankDocTimer = nullptr;
- }
-
- mLoadBlankDocTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- mEditorStatus = eEditorCreationInProgress;
- mLoadBlankDocTimer->InitWithFuncCallback(
- nsEditingSession::TimerCallback,
- static_cast<void*> (mDocShell.get()),
- 10, nsITimer::TYPE_ONE_SHOT);
- }
- }
- }
- }
- return rv;
-}
-
-
-void
-nsEditingSession::TimerCallback(nsITimer* aTimer, void* aClosure)
-{
- nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(static_cast<nsIWeakReference*> (aClosure));
- if (docShell) {
- nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell));
- if (webNav) {
- webNav->LoadURI(u"about:blank", 0, nullptr, nullptr, nullptr);
- }
- }
-}
-
-/*---------------------------------------------------------------------------
-
- StartPageLoad
-
- Called on start load of the entire page (incl. subframes)
-----------------------------------------------------------------------------*/
-nsresult
-nsEditingSession::StartPageLoad(nsIChannel *aChannel)
-{
-#ifdef NOISY_DOC_LOADING
- printf("======= StartPageLoad ========\n");
-#endif
- return NS_OK;
-}
-
-/*---------------------------------------------------------------------------
-
- EndPageLoad
-
- Called on end load of the entire page (incl. subframes)
-----------------------------------------------------------------------------*/
-nsresult
-nsEditingSession::EndPageLoad(nsIWebProgress *aWebProgress,
- nsIChannel* aChannel, nsresult aStatus)
-{
-#ifdef NOISY_DOC_LOADING
- printf("======= EndPageLoad ========\n");
- printf(" with status %d, ", aStatus);
- nsCOMPtr<nsIURI> uri;
- nsXPIDLCString spec;
- if (NS_SUCCEEDED(aChannel->GetURI(getter_AddRefs(uri)))) {
- uri->GetSpec(spec);
- printf("uri %s\n", spec.get());
- }
-
- nsAutoCString contentType;
- aChannel->GetContentType(contentType);
- if (!contentType.IsEmpty()) {
- printf(" flags = %d, status = %d, MIMETYPE = %s\n",
- mEditorFlags, mEditorStatus, contentType.get());
- }
-#endif
-
- // Set the error state -- we will create an editor anyway
- // and load empty doc later
- if (aStatus == NS_ERROR_FILE_NOT_FOUND) {
- mEditorStatus = eEditorErrorFileNotFound;
- }
-
- nsCOMPtr<mozIDOMWindowProxy> domWindow;
- aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
-
- nsIDocShell *docShell =
- domWindow ? nsPIDOMWindowOuter::From(domWindow)->GetDocShell() : nullptr;
- NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
-
- // cancel refresh from meta tags
- // we need to make sure that all pages in editor (whether editable or not)
- // can't refresh contents being edited
- nsCOMPtr<nsIRefreshURI> refreshURI = do_QueryInterface(docShell);
- if (refreshURI) {
- refreshURI->CancelRefreshURITimers();
- }
-
-#if 0
- // Shouldn't we do this when we want to edit sub-frames?
- return MakeWindowEditable(domWindow, "html", false, mInteractive);
-#else
- return NS_OK;
-#endif
-}
-
-/*---------------------------------------------------------------------------
-
- PrepareForEditing
-
- Set up this editing session for one or more editors
-----------------------------------------------------------------------------*/
-nsresult
-nsEditingSession::PrepareForEditing(nsPIDOMWindowOuter* aWindow)
-{
- if (mProgressListenerRegistered) {
- return NS_OK;
- }
-
- nsIDocShell *docShell = aWindow ? aWindow->GetDocShell() : nullptr;
-
- // register callback
- nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
- NS_ENSURE_TRUE(webProgress, NS_ERROR_FAILURE);
-
- nsresult rv =
- webProgress->AddProgressListener(this,
- (nsIWebProgress::NOTIFY_STATE_NETWORK |
- nsIWebProgress::NOTIFY_STATE_DOCUMENT |
- nsIWebProgress::NOTIFY_LOCATION));
-
- mProgressListenerRegistered = NS_SUCCEEDED(rv);
-
- return rv;
-}
-
-/*---------------------------------------------------------------------------
-
- SetupEditorCommandController
-
- Create a command controller, append to controllers,
- get and return the controller ID, and set the context
-----------------------------------------------------------------------------*/
-nsresult
-nsEditingSession::SetupEditorCommandController(
- const char *aControllerClassName,
- mozIDOMWindowProxy *aWindow,
- nsISupports *aContext,
- uint32_t *aControllerId)
-{
- NS_ENSURE_ARG_POINTER(aControllerClassName);
- NS_ENSURE_ARG_POINTER(aWindow);
- NS_ENSURE_ARG_POINTER(aContext);
- NS_ENSURE_ARG_POINTER(aControllerId);
-
- auto* piWindow = nsPIDOMWindowOuter::From(aWindow);
- MOZ_ASSERT(piWindow);
-
- nsCOMPtr<nsIControllers> controllers;
- nsresult rv = piWindow->GetControllers(getter_AddRefs(controllers));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // We only have to create each singleton controller once
- // We know this has happened once we have a controllerId value
- if (!*aControllerId) {
- nsCOMPtr<nsIController> controller;
- controller = do_CreateInstance(aControllerClassName, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // We must insert at head of the list to be sure our
- // controller is found before other implementations
- // (e.g., not-implemented versions by browser)
- rv = controllers->InsertControllerAt(0, controller);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Remember the ID for the controller
- rv = controllers->GetControllerId(controller, aControllerId);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // Set the context
- return SetContextOnControllerById(controllers, aContext, *aControllerId);
-}
-
-/*---------------------------------------------------------------------------
-
- SetEditorOnControllers
-
- Set the editor on the controller(s) for this window
-----------------------------------------------------------------------------*/
-NS_IMETHODIMP
-nsEditingSession::SetEditorOnControllers(mozIDOMWindowProxy* aWindow,
- nsIEditor* aEditor)
-{
- NS_ENSURE_TRUE(aWindow, NS_ERROR_NULL_POINTER);
-
- auto* piWindow = nsPIDOMWindowOuter::From(aWindow);
-
- nsCOMPtr<nsIControllers> controllers;
- nsresult rv = piWindow->GetControllers(getter_AddRefs(controllers));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsISupports> editorAsISupports = do_QueryInterface(aEditor);
- if (mBaseCommandControllerId) {
- rv = SetContextOnControllerById(controllers, editorAsISupports,
- mBaseCommandControllerId);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- if (mDocStateControllerId) {
- rv = SetContextOnControllerById(controllers, editorAsISupports,
- mDocStateControllerId);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- if (mHTMLCommandControllerId) {
- rv = SetContextOnControllerById(controllers, editorAsISupports,
- mHTMLCommandControllerId);
- }
-
- return rv;
-}
-
-nsresult
-nsEditingSession::SetContextOnControllerById(nsIControllers* aControllers,
- nsISupports* aContext,
- uint32_t aID)
-{
- NS_ENSURE_ARG_POINTER(aControllers);
-
- // aContext can be null (when destroying editor)
- nsCOMPtr<nsIController> controller;
- aControllers->GetControllerById(aID, getter_AddRefs(controller));
-
- // ok with nil controller
- nsCOMPtr<nsIControllerContext> editorController =
- do_QueryInterface(controller);
- NS_ENSURE_TRUE(editorController, NS_ERROR_FAILURE);
-
- return editorController->SetCommandContext(aContext);
-}
-
-void
-nsEditingSession::RemoveEditorControllers(nsPIDOMWindowOuter* aWindow)
-{
- // Remove editor controllers from the aWindow, call when we're
- // tearing down/detaching editor.
-
- nsCOMPtr<nsIControllers> controllers;
- if (aWindow) {
- aWindow->GetControllers(getter_AddRefs(controllers));
- }
-
- if (controllers) {
- nsCOMPtr<nsIController> controller;
- if (mBaseCommandControllerId) {
- controllers->GetControllerById(mBaseCommandControllerId,
- getter_AddRefs(controller));
- if (controller) {
- controllers->RemoveController(controller);
- }
- }
-
- if (mDocStateControllerId) {
- controllers->GetControllerById(mDocStateControllerId,
- getter_AddRefs(controller));
- if (controller) {
- controllers->RemoveController(controller);
- }
- }
-
- if (mHTMLCommandControllerId) {
- controllers->GetControllerById(mHTMLCommandControllerId,
- getter_AddRefs(controller));
- if (controller) {
- controllers->RemoveController(controller);
- }
- }
- }
-
- // Clear IDs to trigger creation of new controllers.
- mBaseCommandControllerId = 0;
- mDocStateControllerId = 0;
- mHTMLCommandControllerId = 0;
-}
-
-void
-nsEditingSession::RemoveWebProgressListener(nsPIDOMWindowOuter* aWindow)
-{
- nsIDocShell *docShell = aWindow ? aWindow->GetDocShell() : nullptr;
- nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
- if (webProgress) {
- webProgress->RemoveProgressListener(this);
- mProgressListenerRegistered = false;
- }
-}
-
-void
-nsEditingSession::RestoreAnimationMode(nsPIDOMWindowOuter* aWindow)
-{
- if (mInteractive) {
- return;
- }
-
- nsCOMPtr<nsIDocShell> docShell = aWindow ? aWindow->GetDocShell() : nullptr;
- NS_ENSURE_TRUE_VOID(docShell);
- nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
- NS_ENSURE_TRUE_VOID(presShell);
- nsPresContext* presContext = presShell->GetPresContext();
- NS_ENSURE_TRUE_VOID(presContext);
-
- presContext->SetImageAnimationMode(mImageAnimationMode);
-}
-
-nsresult
-nsEditingSession::DetachFromWindow(mozIDOMWindowProxy* aWindow)
-{
- NS_ENSURE_TRUE(mDoneSetup, NS_OK);
-
- NS_ASSERTION(mStateMaintainer, "mStateMaintainer should exist.");
-
- // Kill any existing reload timer
- if (mLoadBlankDocTimer) {
- mLoadBlankDocTimer->Cancel();
- mLoadBlankDocTimer = nullptr;
- }
-
- auto* window = nsPIDOMWindowOuter::From(aWindow);
-
- // Remove controllers, webprogress listener, and otherwise
- // make things the way they were before we started editing.
- RemoveEditorControllers(window);
- RemoveWebProgressListener(window);
- RestoreJSAndPlugins(aWindow);
- RestoreAnimationMode(window);
-
- // Kill our weak reference to our original window, in case
- // it changes on restore, or otherwise dies.
- mDocShell = nullptr;
-
- return NS_OK;
-}
-
-nsresult
-nsEditingSession::ReattachToWindow(mozIDOMWindowProxy* aWindow)
-{
- NS_ENSURE_TRUE(mDoneSetup, NS_OK);
- NS_ENSURE_TRUE(aWindow, NS_ERROR_FAILURE);
-
- NS_ASSERTION(mStateMaintainer, "mStateMaintainer should exist.");
-
- // Imitate nsEditorDocShell::MakeEditable() to reattach the
- // old editor ot the window.
- nsresult rv;
-
- auto* window = nsPIDOMWindowOuter::From(aWindow);
- nsIDocShell *docShell = window->GetDocShell();
- NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
- mDocShell = do_GetWeakReference(docShell);
-
- // Disable plugins.
- if (!mInteractive) {
- rv = DisableJSAndPlugins(aWindow);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // Tells embedder that startup is in progress.
- mEditorStatus = eEditorCreationInProgress;
-
- // Adds back web progress listener.
- rv = PrepareForEditing(window);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Setup the command controllers again.
- rv = SetupEditorCommandController("@mozilla.org/editor/editingcontroller;1",
- aWindow,
- static_cast<nsIEditingSession*>(this),
- &mBaseCommandControllerId);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = SetupEditorCommandController("@mozilla.org/editor/editordocstatecontroller;1",
- aWindow,
- static_cast<nsIEditingSession*>(this),
- &mDocStateControllerId);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (mStateMaintainer) {
- mStateMaintainer->Init(window);
- }
-
- // Get editor
- nsCOMPtr<nsIEditor> editor;
- rv = GetEditorForWindow(aWindow, getter_AddRefs(editor));
- NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE);
-
- if (!mInteractive) {
- // Disable animation of images in this document:
- nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
- NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
- nsPresContext* presContext = presShell->GetPresContext();
- NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
-
- mImageAnimationMode = presContext->ImageAnimationMode();
- presContext->SetImageAnimationMode(imgIContainer::kDontAnimMode);
- }
-
- // The third controller takes an nsIEditor as the context
- rv = SetupEditorCommandController("@mozilla.org/editor/htmleditorcontroller;1",
- aWindow, editor,
- &mHTMLCommandControllerId);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Set context on all controllers to be the editor
- rv = SetEditorOnControllers(aWindow, editor);
- NS_ENSURE_SUCCESS(rv, rv);
-
-#ifdef DEBUG
- {
- bool isEditable;
- rv = WindowIsEditable(aWindow, &isEditable);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ASSERTION(isEditable, "Window is not editable after reattaching editor.");
- }
-#endif // DEBUG
-
- return NS_OK;
-}
diff --git a/editor/composer/nsEditingSession.h b/editor/composer/nsEditingSession.h
deleted file mode 100644
index a40f45e2d..000000000
--- a/editor/composer/nsEditingSession.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsEditingSession_h__
-#define nsEditingSession_h__
-
-
-#ifndef nsWeakReference_h__
-#include "nsWeakReference.h" // for nsSupportsWeakReference, etc
-#endif
-
-#include "nsCOMPtr.h" // for nsCOMPtr
-#include "nsISupportsImpl.h" // for NS_DECL_ISUPPORTS
-#include "nsIWeakReferenceUtils.h" // for nsWeakPtr
-#include "nsWeakReference.h" // for nsSupportsWeakReference, etc
-#include "nscore.h" // for nsresult
-
-#ifndef __gen_nsIWebProgressListener_h__
-#include "nsIWebProgressListener.h"
-#endif
-
-#ifndef __gen_nsIEditingSession_h__
-#include "nsIEditingSession.h" // for NS_DECL_NSIEDITINGSESSION, etc
-#endif
-
-#include "nsString.h" // for nsCString
-
-class nsPIDOMWindowOuter;
-class mozIDOMWindowProxy;
-class nsIDOMWindow;
-class nsISupports;
-class nsITimer;
-
-#define NS_EDITINGSESSION_CID \
-{ 0xbc26ff01, 0xf2bd, 0x11d4, { 0xa7, 0x3c, 0xe5, 0xa4, 0xb5, 0xa8, 0xbd, 0xfc } }
-
-
-class nsComposerCommandsUpdater;
-class nsIChannel;
-class nsIControllers;
-class nsIDocShell;
-class nsIEditor;
-class nsIWebProgress;
-
-class nsEditingSession final : public nsIEditingSession,
- public nsIWebProgressListener,
- public nsSupportsWeakReference
-{
-public:
-
- nsEditingSession();
-
- // nsISupports
- NS_DECL_ISUPPORTS
-
- // nsIWebProgressListener
- NS_DECL_NSIWEBPROGRESSLISTENER
-
- // nsIEditingSession
- NS_DECL_NSIEDITINGSESSION
-
-protected:
- virtual ~nsEditingSession();
-
- nsresult SetupEditorCommandController(const char *aControllerClassName,
- mozIDOMWindowProxy* aWindow,
- nsISupports *aContext,
- uint32_t *aControllerId);
-
- nsresult SetContextOnControllerById(nsIControllers* aControllers,
- nsISupports* aContext,
- uint32_t aID);
-
- nsresult PrepareForEditing(nsPIDOMWindowOuter* aWindow);
-
- static void TimerCallback(nsITimer *aTimer, void *aClosure);
- nsCOMPtr<nsITimer> mLoadBlankDocTimer;
-
- // progress load stuff
- nsresult StartDocumentLoad(nsIWebProgress *aWebProgress,
- bool isToBeMadeEditable);
- nsresult EndDocumentLoad(nsIWebProgress *aWebProgress,
- nsIChannel* aChannel, nsresult aStatus,
- bool isToBeMadeEditable);
- nsresult StartPageLoad(nsIChannel *aChannel);
- nsresult EndPageLoad(nsIWebProgress *aWebProgress,
- nsIChannel* aChannel, nsresult aStatus);
-
- bool IsProgressForTargetDocument(nsIWebProgress *aWebProgress);
-
- void RemoveEditorControllers(nsPIDOMWindowOuter* aWindow);
- void RemoveWebProgressListener(nsPIDOMWindowOuter* aWindow);
- void RestoreAnimationMode(nsPIDOMWindowOuter* aWindow);
- void RemoveListenersAndControllers(nsPIDOMWindowOuter* aWindow,
- nsIEditor *aEditor);
-
-protected:
-
- bool mDoneSetup; // have we prepared for editing yet?
-
- // Used to prevent double creation of editor because nsIWebProgressListener
- // receives a STATE_STOP notification before the STATE_START
- // for our document, so we wait for the STATE_START, then STATE_STOP
- // before creating an editor
- bool mCanCreateEditor;
-
- bool mInteractive;
- bool mMakeWholeDocumentEditable;
-
- bool mDisabledJSAndPlugins;
-
- // True if scripts were enabled before the editor turned scripts
- // off, otherwise false.
- bool mScriptsEnabled;
-
- // True if plugins were enabled before the editor turned plugins
- // off, otherwise false.
- bool mPluginsEnabled;
-
- bool mProgressListenerRegistered;
-
- // The image animation mode before it was turned off.
- uint16_t mImageAnimationMode;
-
- // THE REMAINING MEMBER VARIABLES WILL BECOME A SET WHEN WE EDIT
- // MORE THAN ONE EDITOR PER EDITING SESSION
- RefPtr<nsComposerCommandsUpdater> mStateMaintainer;
-
- // Save the editor type so we can create the editor after loading uri
- nsCString mEditorType;
- uint32_t mEditorFlags;
- uint32_t mEditorStatus;
- uint32_t mBaseCommandControllerId;
- uint32_t mDocStateControllerId;
- uint32_t mHTMLCommandControllerId;
-
- // Make sure the docshell we use is safe
- nsWeakPtr mDocShell;
-
- // See if we can reuse an existing editor
- nsWeakPtr mExistingEditor;
-};
-
-
-
-#endif // nsEditingSession_h__
diff --git a/editor/composer/nsEditorSpellCheck.cpp b/editor/composer/nsEditorSpellCheck.cpp
deleted file mode 100644
index 1413653ac..000000000
--- a/editor/composer/nsEditorSpellCheck.cpp
+++ /dev/null
@@ -1,934 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <stdlib.h> // for getenv
-
-#include "mozilla/Attributes.h" // for final
-#include "mozilla/Preferences.h" // for Preferences
-#include "mozilla/Services.h" // for GetXULChromeRegistryService
-#include "mozilla/dom/Element.h" // for Element
-#include "mozilla/dom/Selection.h"
-#include "mozilla/mozalloc.h" // for operator delete, etc
-#include "nsAString.h" // for nsAString_internal::IsEmpty, etc
-#include "nsComponentManagerUtils.h" // for do_CreateInstance
-#include "nsDebug.h" // for NS_ENSURE_TRUE, etc
-#include "nsDependentSubstring.h" // for Substring
-#include "nsEditorSpellCheck.h"
-#include "nsError.h" // for NS_ERROR_NOT_INITIALIZED, etc
-#include "nsIChromeRegistry.h" // for nsIXULChromeRegistry
-#include "nsIContent.h" // for nsIContent
-#include "nsIContentPrefService.h" // for nsIContentPrefService, etc
-#include "nsIContentPrefService2.h" // for nsIContentPrefService2, etc
-#include "nsIDOMDocument.h" // for nsIDOMDocument
-#include "nsIDOMElement.h" // for nsIDOMElement
-#include "nsIDocument.h" // for nsIDocument
-#include "nsIEditor.h" // for nsIEditor
-#include "nsIHTMLEditor.h" // for nsIHTMLEditor
-#include "nsILoadContext.h"
-#include "nsISelection.h" // for nsISelection
-#include "nsISpellChecker.h" // for nsISpellChecker, etc
-#include "nsISupportsBase.h" // for nsISupports
-#include "nsISupportsUtils.h" // for NS_ADDREF
-#include "nsITextServicesDocument.h" // for nsITextServicesDocument
-#include "nsITextServicesFilter.h" // for nsITextServicesFilter
-#include "nsIURI.h" // for nsIURI
-#include "nsVariant.h" // for nsIWritableVariant, etc
-#include "nsLiteralString.h" // for NS_LITERAL_STRING, etc
-#include "nsMemory.h" // for nsMemory
-#include "nsRange.h"
-#include "nsReadableUtils.h" // for ToNewUnicode, EmptyString, etc
-#include "nsServiceManagerUtils.h" // for do_GetService
-#include "nsString.h" // for nsAutoString, nsString, etc
-#include "nsStringFwd.h" // for nsAFlatString
-#include "nsStyleUtil.h" // for nsStyleUtil
-#include "nsXULAppAPI.h" // for XRE_GetProcessType
-#include "nsIPlaintextEditor.h" // for editor flags
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-class UpdateDictionaryHolder {
- private:
- nsEditorSpellCheck* mSpellCheck;
- public:
- explicit UpdateDictionaryHolder(nsEditorSpellCheck* esc): mSpellCheck(esc) {
- if (mSpellCheck) {
- mSpellCheck->BeginUpdateDictionary();
- }
- }
- ~UpdateDictionaryHolder() {
- if (mSpellCheck) {
- mSpellCheck->EndUpdateDictionary();
- }
- }
-};
-
-#define CPS_PREF_NAME NS_LITERAL_STRING("spellcheck.lang")
-
-/**
- * Gets the URI of aEditor's document.
- */
-static nsresult
-GetDocumentURI(nsIEditor* aEditor, nsIURI * *aURI)
-{
- NS_ENSURE_ARG_POINTER(aEditor);
- NS_ENSURE_ARG_POINTER(aURI);
-
- nsCOMPtr<nsIDOMDocument> domDoc;
- aEditor->GetDocument(getter_AddRefs(domDoc));
- NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
- NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIURI> docUri = doc->GetDocumentURI();
- NS_ENSURE_TRUE(docUri, NS_ERROR_FAILURE);
-
- *aURI = docUri;
- NS_ADDREF(*aURI);
- return NS_OK;
-}
-
-static already_AddRefed<nsILoadContext>
-GetLoadContext(nsIEditor* aEditor)
-{
- nsCOMPtr<nsIDOMDocument> domDoc;
- aEditor->GetDocument(getter_AddRefs(domDoc));
- NS_ENSURE_TRUE(domDoc, nullptr);
-
- nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
- NS_ENSURE_TRUE(doc, nullptr);
-
- nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
- return loadContext.forget();
-}
-
-/**
- * Fetches the dictionary stored in content prefs and maintains state during the
- * fetch, which is asynchronous.
- */
-class DictionaryFetcher final : public nsIContentPrefCallback2
-{
-public:
- NS_DECL_ISUPPORTS
-
- DictionaryFetcher(nsEditorSpellCheck* aSpellCheck,
- nsIEditorSpellCheckCallback* aCallback,
- uint32_t aGroup)
- : mCallback(aCallback), mGroup(aGroup), mSpellCheck(aSpellCheck) {}
-
- NS_IMETHOD Fetch(nsIEditor* aEditor);
-
- NS_IMETHOD HandleResult(nsIContentPref* aPref) override
- {
- nsCOMPtr<nsIVariant> value;
- nsresult rv = aPref->GetValue(getter_AddRefs(value));
- NS_ENSURE_SUCCESS(rv, rv);
- value->GetAsAString(mDictionary);
- return NS_OK;
- }
-
- NS_IMETHOD HandleCompletion(uint16_t reason) override
- {
- mSpellCheck->DictionaryFetched(this);
- return NS_OK;
- }
-
- NS_IMETHOD HandleError(nsresult error) override
- {
- return NS_OK;
- }
-
- nsCOMPtr<nsIEditorSpellCheckCallback> mCallback;
- uint32_t mGroup;
- nsString mRootContentLang;
- nsString mRootDocContentLang;
- nsString mDictionary;
-
-private:
- ~DictionaryFetcher() {}
-
- RefPtr<nsEditorSpellCheck> mSpellCheck;
-};
-NS_IMPL_ISUPPORTS(DictionaryFetcher, nsIContentPrefCallback2)
-
-NS_IMETHODIMP
-DictionaryFetcher::Fetch(nsIEditor* aEditor)
-{
- NS_ENSURE_ARG_POINTER(aEditor);
-
- nsresult rv;
-
- nsCOMPtr<nsIURI> docUri;
- rv = GetDocumentURI(aEditor, getter_AddRefs(docUri));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsAutoCString docUriSpec;
- rv = docUri->GetSpec(docUriSpec);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIContentPrefService2> contentPrefService =
- do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
- NS_ENSURE_TRUE(contentPrefService, NS_ERROR_NOT_AVAILABLE);
-
- nsCOMPtr<nsILoadContext> loadContext = GetLoadContext(aEditor);
- rv = contentPrefService->GetByDomainAndName(NS_ConvertUTF8toUTF16(docUriSpec),
- CPS_PREF_NAME, loadContext,
- this);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-/**
- * Stores the current dictionary for aEditor's document URL.
- */
-static nsresult
-StoreCurrentDictionary(nsIEditor* aEditor, const nsAString& aDictionary)
-{
- NS_ENSURE_ARG_POINTER(aEditor);
-
- nsresult rv;
-
- nsCOMPtr<nsIURI> docUri;
- rv = GetDocumentURI(aEditor, getter_AddRefs(docUri));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsAutoCString docUriSpec;
- rv = docUri->GetSpec(docUriSpec);
- NS_ENSURE_SUCCESS(rv, rv);
-
- RefPtr<nsVariant> prefValue = new nsVariant();
- prefValue->SetAsAString(aDictionary);
-
- nsCOMPtr<nsIContentPrefService2> contentPrefService =
- do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
- NS_ENSURE_TRUE(contentPrefService, NS_ERROR_NOT_INITIALIZED);
-
- nsCOMPtr<nsILoadContext> loadContext = GetLoadContext(aEditor);
- return contentPrefService->Set(NS_ConvertUTF8toUTF16(docUriSpec),
- CPS_PREF_NAME, prefValue, loadContext,
- nullptr);
-}
-
-/**
- * Forgets the current dictionary stored for aEditor's document URL.
- */
-static nsresult
-ClearCurrentDictionary(nsIEditor* aEditor)
-{
- NS_ENSURE_ARG_POINTER(aEditor);
-
- nsresult rv;
-
- nsCOMPtr<nsIURI> docUri;
- rv = GetDocumentURI(aEditor, getter_AddRefs(docUri));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsAutoCString docUriSpec;
- rv = docUri->GetSpec(docUriSpec);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIContentPrefService2> contentPrefService =
- do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
- NS_ENSURE_TRUE(contentPrefService, NS_ERROR_NOT_INITIALIZED);
-
- nsCOMPtr<nsILoadContext> loadContext = GetLoadContext(aEditor);
- return contentPrefService->RemoveByDomainAndName(
- NS_ConvertUTF8toUTF16(docUriSpec), CPS_PREF_NAME, loadContext, nullptr);
-}
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsEditorSpellCheck)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsEditorSpellCheck)
-
-NS_INTERFACE_MAP_BEGIN(nsEditorSpellCheck)
- NS_INTERFACE_MAP_ENTRY(nsIEditorSpellCheck)
- NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIEditorSpellCheck)
- NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsEditorSpellCheck)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTION(nsEditorSpellCheck,
- mEditor,
- mSpellChecker,
- mTxtSrvFilter)
-
-nsEditorSpellCheck::nsEditorSpellCheck()
- : mSuggestedWordIndex(0)
- , mDictionaryIndex(0)
- , mEditor(nullptr)
- , mDictionaryFetcherGroup(0)
- , mUpdateDictionaryRunning(false)
-{
-}
-
-nsEditorSpellCheck::~nsEditorSpellCheck()
-{
- // Make sure we blow the spellchecker away, just in
- // case it hasn't been destroyed already.
- mSpellChecker = nullptr;
-}
-
-// The problem is that if the spell checker does not exist, we can not tell
-// which dictionaries are installed. This function works around the problem,
-// allowing callers to ask if we can spell check without actually doing so (and
-// enabling or disabling UI as necessary). This just creates a spellcheck
-// object if needed and asks it for the dictionary list.
-NS_IMETHODIMP
-nsEditorSpellCheck::CanSpellCheck(bool* _retval)
-{
- nsresult rv;
- nsCOMPtr<nsISpellChecker> spellChecker;
- if (! mSpellChecker) {
- spellChecker = do_CreateInstance(NS_SPELLCHECKER_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- spellChecker = mSpellChecker;
- }
- nsTArray<nsString> dictList;
- rv = spellChecker->GetDictionaryList(&dictList);
- NS_ENSURE_SUCCESS(rv, rv);
-
- *_retval = (dictList.Length() > 0);
- return NS_OK;
-}
-
-// Instances of this class can be used as either runnables or RAII helpers.
-class CallbackCaller final : public Runnable
-{
-public:
- explicit CallbackCaller(nsIEditorSpellCheckCallback* aCallback)
- : mCallback(aCallback) {}
-
- ~CallbackCaller()
- {
- Run();
- }
-
- NS_IMETHOD Run() override
- {
- if (mCallback) {
- mCallback->EditorSpellCheckDone();
- mCallback = nullptr;
- }
- return NS_OK;
- }
-
-private:
- nsCOMPtr<nsIEditorSpellCheckCallback> mCallback;
-};
-
-NS_IMETHODIMP
-nsEditorSpellCheck::InitSpellChecker(nsIEditor* aEditor, bool aEnableSelectionChecking, nsIEditorSpellCheckCallback* aCallback)
-{
- NS_ENSURE_TRUE(aEditor, NS_ERROR_NULL_POINTER);
- mEditor = aEditor;
-
- nsresult rv;
-
- // We can spell check with any editor type
- nsCOMPtr<nsITextServicesDocument>tsDoc =
- do_CreateInstance("@mozilla.org/textservices/textservicesdocument;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- NS_ENSURE_TRUE(tsDoc, NS_ERROR_NULL_POINTER);
-
- tsDoc->SetFilter(mTxtSrvFilter);
-
- // Pass the editor to the text services document
- rv = tsDoc->InitWithEditor(aEditor);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (aEnableSelectionChecking) {
- // Find out if the section is collapsed or not.
- // If it isn't, we want to spellcheck just the selection.
-
- nsCOMPtr<nsISelection> domSelection;
- aEditor->GetSelection(getter_AddRefs(domSelection));
- if (NS_WARN_IF(!domSelection)) {
- return NS_ERROR_FAILURE;
- }
- RefPtr<Selection> selection = domSelection->AsSelection();
-
- int32_t count = 0;
-
- rv = selection->GetRangeCount(&count);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (count > 0) {
- RefPtr<nsRange> range = selection->GetRangeAt(0);
- NS_ENSURE_STATE(range);
-
- bool collapsed = false;
- rv = range->GetCollapsed(&collapsed);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!collapsed) {
- // We don't want to touch the range in the selection,
- // so create a new copy of it.
-
- RefPtr<nsRange> rangeBounds = range->CloneRange();
-
- // Make sure the new range spans complete words.
-
- rv = tsDoc->ExpandRangeToWordBoundaries(rangeBounds);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Now tell the text services that you only want
- // to iterate over the text in this range.
-
- rv = tsDoc->SetExtent(rangeBounds);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- }
-
- mSpellChecker = do_CreateInstance(NS_SPELLCHECKER_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NULL_POINTER);
-
- rv = mSpellChecker->SetDocument(tsDoc, true);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // do not fail if UpdateCurrentDictionary fails because this method may
- // succeed later.
- rv = UpdateCurrentDictionary(aCallback);
- if (NS_FAILED(rv) && aCallback) {
- // However, if it does fail, we still need to call the callback since we
- // discard the failure. Do it asynchronously so that the caller is always
- // guaranteed async behavior.
- RefPtr<CallbackCaller> caller = new CallbackCaller(aCallback);
- NS_ENSURE_STATE(caller);
- rv = NS_DispatchToMainThread(caller);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsEditorSpellCheck::GetNextMisspelledWord(char16_t **aNextMisspelledWord)
-{
- NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NOT_INITIALIZED);
-
- nsAutoString nextMisspelledWord;
-
- DeleteSuggestedWordList();
- // Beware! This may flush notifications via synchronous
- // ScrollSelectionIntoView.
- nsresult rv = mSpellChecker->NextMisspelledWord(nextMisspelledWord,
- &mSuggestedWordList);
-
- *aNextMisspelledWord = ToNewUnicode(nextMisspelledWord);
- return rv;
-}
-
-NS_IMETHODIMP
-nsEditorSpellCheck::GetSuggestedWord(char16_t **aSuggestedWord)
-{
- nsAutoString word;
- // XXX This is buggy if mSuggestedWordList.Length() is over INT32_MAX.
- if (mSuggestedWordIndex < static_cast<int32_t>(mSuggestedWordList.Length())) {
- *aSuggestedWord = ToNewUnicode(mSuggestedWordList[mSuggestedWordIndex]);
- mSuggestedWordIndex++;
- } else {
- // A blank string signals that there are no more strings
- *aSuggestedWord = ToNewUnicode(EmptyString());
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsEditorSpellCheck::CheckCurrentWord(const char16_t *aSuggestedWord,
- bool *aIsMisspelled)
-{
- NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NOT_INITIALIZED);
-
- DeleteSuggestedWordList();
- return mSpellChecker->CheckWord(nsDependentString(aSuggestedWord),
- aIsMisspelled, &mSuggestedWordList);
-}
-
-NS_IMETHODIMP
-nsEditorSpellCheck::CheckCurrentWordNoSuggest(const char16_t *aSuggestedWord,
- bool *aIsMisspelled)
-{
- NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NOT_INITIALIZED);
-
- return mSpellChecker->CheckWord(nsDependentString(aSuggestedWord),
- aIsMisspelled, nullptr);
-}
-
-NS_IMETHODIMP
-nsEditorSpellCheck::ReplaceWord(const char16_t *aMisspelledWord,
- const char16_t *aReplaceWord,
- bool allOccurrences)
-{
- NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NOT_INITIALIZED);
-
- return mSpellChecker->Replace(nsDependentString(aMisspelledWord),
- nsDependentString(aReplaceWord), allOccurrences);
-}
-
-NS_IMETHODIMP
-nsEditorSpellCheck::IgnoreWordAllOccurrences(const char16_t *aWord)
-{
- NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NOT_INITIALIZED);
-
- return mSpellChecker->IgnoreAll(nsDependentString(aWord));
-}
-
-NS_IMETHODIMP
-nsEditorSpellCheck::GetPersonalDictionary()
-{
- NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NOT_INITIALIZED);
-
- // We can spell check with any editor type
- mDictionaryList.Clear();
- mDictionaryIndex = 0;
- return mSpellChecker->GetPersonalDictionary(&mDictionaryList);
-}
-
-NS_IMETHODIMP
-nsEditorSpellCheck::GetPersonalDictionaryWord(char16_t **aDictionaryWord)
-{
- // XXX This is buggy if mDictionaryList.Length() is over INT32_MAX.
- if (mDictionaryIndex < static_cast<int32_t>(mDictionaryList.Length())) {
- *aDictionaryWord = ToNewUnicode(mDictionaryList[mDictionaryIndex]);
- mDictionaryIndex++;
- } else {
- // A blank string signals that there are no more strings
- *aDictionaryWord = ToNewUnicode(EmptyString());
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsEditorSpellCheck::AddWordToDictionary(const char16_t *aWord)
-{
- NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NOT_INITIALIZED);
-
- return mSpellChecker->AddWordToPersonalDictionary(nsDependentString(aWord));
-}
-
-NS_IMETHODIMP
-nsEditorSpellCheck::RemoveWordFromDictionary(const char16_t *aWord)
-{
- NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NOT_INITIALIZED);
-
- return mSpellChecker->RemoveWordFromPersonalDictionary(nsDependentString(aWord));
-}
-
-NS_IMETHODIMP
-nsEditorSpellCheck::GetDictionaryList(char16_t ***aDictionaryList, uint32_t *aCount)
-{
- NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NOT_INITIALIZED);
-
- NS_ENSURE_TRUE(aDictionaryList && aCount, NS_ERROR_NULL_POINTER);
-
- *aDictionaryList = 0;
- *aCount = 0;
-
- nsTArray<nsString> dictList;
-
- nsresult rv = mSpellChecker->GetDictionaryList(&dictList);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- char16_t **tmpPtr = 0;
-
- if (dictList.IsEmpty()) {
- // If there are no dictionaries, return an array containing
- // one element and a count of one.
-
- tmpPtr = (char16_t **)moz_xmalloc(sizeof(char16_t *));
-
- NS_ENSURE_TRUE(tmpPtr, NS_ERROR_OUT_OF_MEMORY);
-
- *tmpPtr = 0;
- *aDictionaryList = tmpPtr;
- *aCount = 0;
-
- return NS_OK;
- }
-
- tmpPtr = (char16_t **)moz_xmalloc(sizeof(char16_t *) * dictList.Length());
-
- NS_ENSURE_TRUE(tmpPtr, NS_ERROR_OUT_OF_MEMORY);
-
- *aDictionaryList = tmpPtr;
- *aCount = dictList.Length();
-
- for (uint32_t i = 0; i < *aCount; i++) {
- tmpPtr[i] = ToNewUnicode(dictList[i]);
- }
-
- return rv;
-}
-
-NS_IMETHODIMP
-nsEditorSpellCheck::GetCurrentDictionary(nsAString& aDictionary)
-{
- NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NOT_INITIALIZED);
-
- return mSpellChecker->GetCurrentDictionary(aDictionary);
-}
-
-NS_IMETHODIMP
-nsEditorSpellCheck::SetCurrentDictionary(const nsAString& aDictionary)
-{
- NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NOT_INITIALIZED);
-
- RefPtr<nsEditorSpellCheck> kungFuDeathGrip = this;
-
- // The purpose of mUpdateDictionaryRunning is to avoid doing all of this if
- // UpdateCurrentDictionary's helper method DictionaryFetched, which calls us,
- // is on the stack. In other words: Only do this, if the user manually selected a
- // dictionary to use.
- if (!mUpdateDictionaryRunning) {
-
- // Ignore pending dictionary fetchers by increasing this number.
- mDictionaryFetcherGroup++;
-
- if (mPreferredLang.IsEmpty() ||
- !mPreferredLang.Equals(aDictionary, nsCaseInsensitiveStringComparator())) {
- // When user sets dictionary manually, we store this value associated
- // with editor url, if it doesn't match the document language exactly.
- // For example on "en" sites, we need to store "en-GB", otherwise
- // the language might jump back to en-US although the user explicitly
- // chose otherwise.
- StoreCurrentDictionary(mEditor, aDictionary);
- } else {
- // If user sets a dictionary matching the language defined by
- // document, we consider content pref has been canceled, and we clear it.
- ClearCurrentDictionary(mEditor);
- }
- }
- return mSpellChecker->SetCurrentDictionary(aDictionary);
-}
-
-
-NS_IMETHODIMP
-nsEditorSpellCheck::UninitSpellChecker()
-{
- NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NOT_INITIALIZED);
-
- // Cleanup - kill the spell checker
- DeleteSuggestedWordList();
- mDictionaryList.Clear();
- mDictionaryIndex = 0;
- mSpellChecker = nullptr;
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsEditorSpellCheck::SetFilter(nsITextServicesFilter *filter)
-{
- mTxtSrvFilter = filter;
- return NS_OK;
-}
-
-nsresult
-nsEditorSpellCheck::DeleteSuggestedWordList()
-{
- mSuggestedWordList.Clear();
- mSuggestedWordIndex = 0;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsEditorSpellCheck::UpdateCurrentDictionary(nsIEditorSpellCheckCallback* aCallback)
-{
- if (NS_WARN_IF(!mSpellChecker)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- nsresult rv;
-
- RefPtr<nsEditorSpellCheck> kungFuDeathGrip = this;
-
- // Get language with html5 algorithm
- nsCOMPtr<nsIContent> rootContent;
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(mEditor);
- if (htmlEditor) {
- rootContent = htmlEditor->GetActiveEditingHost();
- } else {
- nsCOMPtr<nsIDOMElement> rootElement;
- rv = mEditor->GetRootElement(getter_AddRefs(rootElement));
- NS_ENSURE_SUCCESS(rv, rv);
- rootContent = do_QueryInterface(rootElement);
- }
-
- // Try to get topmost document's document element for embedded mail editor.
- uint32_t flags = 0;
- mEditor->GetFlags(&flags);
- if (flags & nsIPlaintextEditor::eEditorMailMask) {
- nsCOMPtr<nsIDocument> ownerDoc = rootContent->OwnerDoc();
- NS_ENSURE_TRUE(ownerDoc, NS_ERROR_FAILURE);
- nsIDocument* parentDoc = ownerDoc->GetParentDocument();
- if (parentDoc) {
- rootContent = do_QueryInterface(parentDoc->GetDocumentElement());
- }
- }
-
- if (!rootContent) {
- return NS_ERROR_FAILURE;
- }
-
- RefPtr<DictionaryFetcher> fetcher =
- new DictionaryFetcher(this, aCallback, mDictionaryFetcherGroup);
- rootContent->GetLang(fetcher->mRootContentLang);
- nsCOMPtr<nsIDocument> doc = rootContent->GetUncomposedDoc();
- NS_ENSURE_STATE(doc);
- doc->GetContentLanguage(fetcher->mRootDocContentLang);
-
- rv = fetcher->Fetch(mEditor);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-// Helper function that iterates over the list of dictionaries and sets the one
-// that matches based on a given comparison type.
-nsresult
-nsEditorSpellCheck::TryDictionary(const nsAString& aDictName,
- nsTArray<nsString>& aDictList,
- enum dictCompare aCompareType)
-{
- nsresult rv = NS_ERROR_NOT_AVAILABLE;
-
- for (uint32_t i = 0; i < aDictList.Length(); i++) {
- nsAutoString dictStr(aDictList.ElementAt(i));
- bool equals = false;
- switch (aCompareType) {
- case DICT_NORMAL_COMPARE:
- equals = aDictName.Equals(dictStr);
- break;
- case DICT_COMPARE_CASE_INSENSITIVE:
- equals = aDictName.Equals(dictStr, nsCaseInsensitiveStringComparator());
- break;
- case DICT_COMPARE_DASHMATCH:
- equals = nsStyleUtil::DashMatchCompare(dictStr, aDictName, nsCaseInsensitiveStringComparator());
- break;
- }
- if (equals) {
- rv = mSpellChecker->SetCurrentDictionary(dictStr);
-#ifdef DEBUG_DICT
- if (NS_SUCCEEDED(rv))
- printf("***** Set |%s|.\n", NS_ConvertUTF16toUTF8(dictStr).get());
-#endif
- // We always break here. We tried to set the dictionary to an existing
- // dictionary from the list. This must work, if it doesn't, there is
- // no point trying another one.
- break;
- }
- }
- return rv;
-}
-
-nsresult
-nsEditorSpellCheck::DictionaryFetched(DictionaryFetcher* aFetcher)
-{
- MOZ_ASSERT(aFetcher);
- RefPtr<nsEditorSpellCheck> kungFuDeathGrip = this;
-
- // Important: declare the holder after the callback caller so that the former
- // is destructed first so that it's not active when the callback is called.
- CallbackCaller callbackCaller(aFetcher->mCallback);
- UpdateDictionaryHolder holder(this);
-
- if (aFetcher->mGroup < mDictionaryFetcherGroup) {
- // SetCurrentDictionary was called after the fetch started. Don't overwrite
- // that dictionary with the fetched one.
- return NS_OK;
- }
-
- /*
- * We try to derive the dictionary to use based on the following priorities:
- * 1) Content preference: the language the user set for the site before.
- * 2) The value of "spellchecker.dictionary.override" which reflects a
- * global choice of language explicitly set by the user.
- * 3) Language set by the website, or any other dictionary that partly matches that.
- * Eg. if the website is "en-GB", a user who only has "en-US" will get that.
- * If the website is generic "en", the user will get one of the "en-*" installed,
- * pretty much at random.
- * 4) The user's locale
- * 5) Leave the current dictionary set.
- * 6) The content of the "LANG" environment variable (if set)
- * 7) The first spell check dictionary installed.
- */
-
- // Get the language from the element or its closest parent according to:
- // https://html.spec.whatwg.org/#attr-lang
- // This is used in SetCurrentDictionary.
- mPreferredLang.Assign(aFetcher->mRootContentLang);
-
- // If no luck, try the "Content-Language" header.
- if (mPreferredLang.IsEmpty()) {
- mPreferredLang.Assign(aFetcher->mRootDocContentLang);
- }
-
- // Priority 1:
- // Get language from content prefs, if set.
- // If we successfully fetched a dictionary from content prefs, do not go
- // further. Use this exact dictionary.
- nsAutoString dictName;
- dictName.Assign(aFetcher->mDictionary);
- if (!dictName.IsEmpty()) {
- if (NS_SUCCEEDED(SetCurrentDictionary(dictName))) {
- // We take an early exit here, so clear the suggested word list.
- DeleteSuggestedWordList();
- return NS_OK;
- }
- // Maybe the dictionary was uninstalled ?
- // Clear the content preference and continue.
- ClearCurrentDictionary(mEditor);
- }
-
- // Priority 2:
- // Get global preferred language from preferences, if set.
- nsAutoString preferredDict;
- preferredDict = Preferences::GetLocalizedString("spellchecker.dictionary.override");
- if (!preferredDict.IsEmpty()) {
- dictName.Assign(preferredDict);
- }
-
- // Priority 3:
- // Get language from element/doc, if set.
- if (dictName.IsEmpty() && !mPreferredLang.IsEmpty()) {
- dictName.Assign(mPreferredLang);
- }
-
- // Auxiliary status value
- nsresult rv2;
-
- // Obtain a list of available dictionaries to check against.
- nsTArray<nsString> dictList;
- rv2 = mSpellChecker->GetDictionaryList(&dictList);
- NS_ENSURE_SUCCESS(rv2, rv2);
- int32_t i, dictCount = dictList.Length();
-
- // The following will be driven by this status. Once we are able to set a
- // dictionary successfully, we're done. So we start with a "failed" status.
- nsresult rv = NS_ERROR_FAILURE;
-
- if (!dictName.IsEmpty()) {
- for (i = 0; i < dictCount; i++) {
- nsAutoString dictStr(dictList.ElementAt(i));
- if (dictName.Equals(dictStr, nsCaseInsensitiveStringComparator())) {
- // First let's correct any problems due to non-matching case.
- // This applies to both a user-set override and document language.
- // RFC 5646 explicitly states that matches should be case-insensitive.
- dictName.Assign(dictStr);
- // Try to set it. Doing this inside this loop avoids trying to set a
- // dictionary that isn't available.
- rv = SetCurrentDictionary(dictName);
- break;
- }
- }
-
- if (NS_FAILED(rv)) {
- // Required dictionary was not available. Try to get a dictionary
- // matching at least the language part of dictName:
- nsAutoString langCode;
- int32_t dashIdx = dictName.FindChar('-');
- if (dashIdx != -1) {
- langCode.Assign(Substring(dictName, 0, dashIdx));
- } else {
- langCode.Assign(dictName);
- }
-
- nsDefaultStringComparator comparator;
-
- // Loop over available dictionaries; if we find one with the required
- // language, use it.
- for (i = 0; i < dictCount; i++) {
- nsAutoString dictStr(dictList.ElementAt(i));
- if (nsStyleUtil::DashMatchCompare(dictStr, langCode, comparator) &&
- NS_SUCCEEDED(rv = SetCurrentDictionary(dictStr))) {
- break;
- }
- }
- }
- }
-
- // Priority 4:
- // Content prefs, override and document didn't give us a valid dictionary
- // name, so we just get the current locale and try to use that.
- if (NS_FAILED (rv)) {
- nsCOMPtr<nsIXULChromeRegistry> packageRegistry =
- mozilla::services::GetXULChromeRegistryService();
-
- if (packageRegistry) {
- nsAutoCString utf8DictName;
- rv2 = packageRegistry->GetSelectedLocale(NS_LITERAL_CSTRING("global"),
- false, utf8DictName);
- dictName.Assign(EmptyString());
- AppendUTF8toUTF16(utf8DictName, dictName);
- // Try to set it, if it's in the list.
- for (i = 0; i < dictCount; i++) {
- nsAutoString dictStr(dictList.ElementAt(i));
- if (dictStr.Equals(dictName)) {
- rv = SetCurrentDictionary(dictName);
- break;
- }
- }
- }
- }
-
- if (NS_FAILED(rv)) {
- // Still no success. Further fallback attempts required.
-
- // Priority 5:
- // If we have a current dictionary, don't try anything else.
- nsAutoString currentDictionary;
- rv2 = GetCurrentDictionary(currentDictionary);
-
- if (NS_FAILED(rv2) || currentDictionary.IsEmpty()) {
- // We don't have a current dictionary.
- // Priority 6:
- // Try to get current dictionary from environment variable LANG.
- // LANG = language[_territory][.codeset]
- char* env_lang = getenv("LANG");
- if (env_lang != nullptr) {
- nsString lang = NS_ConvertUTF8toUTF16(env_lang);
-
- // Strip trailing charset, if there is any.
- int32_t dot_pos = lang.FindChar('.');
- if (dot_pos != -1) {
- lang = Substring(lang, 0, dot_pos);
- }
-
- // Convert underscore to dash.
- int32_t underScore = lang.FindChar('_');
- if (underScore != -1) {
- lang.Replace(underScore, 1, '-');
- // Only attempt to set if a _territory is present.
- rv = SetCurrentDictionary(lang);
- }
- }
-
- // Priority 7:
- // If LANG does not work either, pick the first one.
- if (NS_FAILED(rv)) {
- if (dictList.Length() > 0) {
- rv = SetCurrentDictionary(dictList[0]);
- }
- }
- }
- }
-
- // If an error was thrown while setting the dictionary, just
- // fail silently so that the spellchecker dialog is allowed to come
- // up. The user can manually reset the language to their choice on
- // the dialog if it is wrong.
-
- // Dictionary has changed, so delete the suggested word list.
- DeleteSuggestedWordList();
-
- return NS_OK;
-}
diff --git a/editor/composer/nsEditorSpellCheck.h b/editor/composer/nsEditorSpellCheck.h
deleted file mode 100644
index e39a2c891..000000000
--- a/editor/composer/nsEditorSpellCheck.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsEditorSpellCheck_h___
-#define nsEditorSpellCheck_h___
-
-
-#include "nsCOMPtr.h" // for nsCOMPtr
-#include "nsCycleCollectionParticipant.h"
-#include "nsIEditorSpellCheck.h" // for NS_DECL_NSIEDITORSPELLCHECK, etc
-#include "nsISupportsImpl.h"
-#include "nsString.h" // for nsString
-#include "nsTArray.h" // for nsTArray
-#include "nscore.h" // for nsresult
-
-class nsIEditor;
-class nsISpellChecker;
-class nsITextServicesFilter;
-
-#define NS_EDITORSPELLCHECK_CID \
-{ /* {75656ad9-bd13-4c5d-939a-ec6351eea0cc} */ \
- 0x75656ad9, 0xbd13, 0x4c5d, \
- { 0x93, 0x9a, 0xec, 0x63, 0x51, 0xee, 0xa0, 0xcc }\
-}
-
-class DictionaryFetcher;
-
-enum dictCompare {
- DICT_NORMAL_COMPARE,
- DICT_COMPARE_CASE_INSENSITIVE,
- DICT_COMPARE_DASHMATCH
-};
-
-class nsEditorSpellCheck final : public nsIEditorSpellCheck
-{
- friend class DictionaryFetcher;
-
-public:
- nsEditorSpellCheck();
-
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS(nsEditorSpellCheck)
-
- /* Declare all methods in the nsIEditorSpellCheck interface */
- NS_DECL_NSIEDITORSPELLCHECK
-
-protected:
- virtual ~nsEditorSpellCheck();
-
- nsCOMPtr<nsISpellChecker> mSpellChecker;
-
- nsTArray<nsString> mSuggestedWordList;
- int32_t mSuggestedWordIndex;
-
- // these are the words in the current personal dictionary,
- // GetPersonalDictionary must be called to load them.
- nsTArray<nsString> mDictionaryList;
- int32_t mDictionaryIndex;
-
- nsresult DeleteSuggestedWordList();
-
- nsCOMPtr<nsITextServicesFilter> mTxtSrvFilter;
- nsCOMPtr<nsIEditor> mEditor;
-
- nsString mPreferredLang;
-
- uint32_t mDictionaryFetcherGroup;
-
- bool mUpdateDictionaryRunning;
-
- nsresult TryDictionary(const nsAString& aDictName, nsTArray<nsString>& aDictList,
- enum dictCompare aCompareType);
-
- nsresult DictionaryFetched(DictionaryFetcher* aFetchState);
-
-public:
- void BeginUpdateDictionary() { mUpdateDictionaryRunning = true ;}
- void EndUpdateDictionary() { mUpdateDictionaryRunning = false ;}
-};
-
-#endif // nsEditorSpellCheck_h___
-
-
diff --git a/editor/composer/nsIEditingSession.idl b/editor/composer/nsIEditingSession.idl
deleted file mode 100644
index 6cbf00481..000000000
--- a/editor/composer/nsIEditingSession.idl
+++ /dev/null
@@ -1,104 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "domstubs.idl"
-
-interface mozIDOMWindowProxy;
-interface nsIEditor;
-
-[scriptable, uuid(24f963d1-e6fc-43ea-a206-99ac5fcc5265)]
-
-interface nsIEditingSession : nsISupports
-{
- /**
- * Error codes when we fail to create an editor
- * is placed in attribute editorStatus
- */
- const long eEditorOK = 0;
- const long eEditorCreationInProgress = 1;
- const long eEditorErrorCantEditMimeType = 2;
- const long eEditorErrorFileNotFound = 3;
- const long eEditorErrorCantEditFramesets = 8;
- const long eEditorErrorUnknown = 9;
-
- /**
- * Status after editor creation and document loading
- * Value is one of the above error codes
- */
- readonly attribute unsigned long editorStatus;
-
- /**
- * Make this window editable
- * @param aWindow nsIDOMWindow, the window the embedder needs to make editable
- * @param aEditorType string, "html" "htmlsimple" "text" "textsimple"
- * @param aMakeWholeDocumentEditable if PR_TRUE make the whole document in
- * aWindow editable, otherwise it's the
- * embedder who should make the document
- * (or part of it) editable.
- * @param aInteractive if PR_FALSE turn off scripting and plugins
- */
- void makeWindowEditable(in mozIDOMWindowProxy window,
- in string aEditorType,
- in boolean doAfterUriLoad,
- in boolean aMakeWholeDocumentEditable,
- in boolean aInteractive);
-
- /**
- * Test whether a specific window has had its editable flag set; it may have an editor
- * now, or will get one after the uri load.
- *
- * Use this, passing the content root window, to test if we've set up editing
- * for this content.
- */
- boolean windowIsEditable(in mozIDOMWindowProxy window);
-
- /**
- * Get the editor for this window. May return null
- */
- nsIEditor getEditorForWindow(in mozIDOMWindowProxy window);
-
- /**
- * Setup editor and related support objects
- */
- void setupEditorOnWindow(in mozIDOMWindowProxy window);
-
- /**
- * Destroy editor and related support objects
- */
- void tearDownEditorOnWindow(in mozIDOMWindowProxy window);
-
- void setEditorOnControllers(in mozIDOMWindowProxy aWindow,
- in nsIEditor aEditor);
-
- /**
- * Disable scripts and plugins in aWindow.
- */
- void disableJSAndPlugins(in mozIDOMWindowProxy aWindow);
-
- /**
- * Restore JS and plugins (enable/disable them) according to the state they
- * were before the last call to disableJSAndPlugins.
- */
- void restoreJSAndPlugins(in mozIDOMWindowProxy aWindow);
-
- /**
- * Removes all the editor's controllers/listeners etc and makes the window
- * uneditable.
- */
- void detachFromWindow(in mozIDOMWindowProxy aWindow);
-
- /**
- * Undos detachFromWindow(), reattaches this editing session/editor
- * to the window.
- */
- void reattachToWindow(in mozIDOMWindowProxy aWindow);
-
- /**
- * Whether this session has disabled JS and plugins.
- */
- readonly attribute boolean jsAndPluginsDisabled;
-};
-
diff --git a/editor/composer/res/EditorOverride.css b/editor/composer/res/EditorOverride.css
deleted file mode 100644
index 4940fbb30..000000000
--- a/editor/composer/res/EditorOverride.css
+++ /dev/null
@@ -1,323 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-*|* {
- -moz-user-modify: read-write;
-}
-
-/* Styles to alter look of things in the Editor content window
- * that should NOT be removed when we display in completely WYSIWYG
- * "Browser Preview" mode.
- * Anything that should change, like appearance of table borders
- * and Named Anchors, should be placed in EditorContent.css instead of here.
-*/
-
-/* Primary cursor is text I-beam */
-
-::-moz-canvas, a:link {
- cursor: text;
-}
-
-/* Use default arrow over objects with size that
- are selected when clicked on.
- Override the browser's pointer cursor over links
-*/
-
-img, img[usemap], area,
-object, object[usemap],
-applet, hr, button, input, textarea, select,
-a:link img, a:visited img, a:active img,
-a[name]:-moz-only-whitespace {
- cursor: default;
-}
-
-a:visited, a:active {
- cursor: text;
-}
-
-/* Prevent clicking on links from going to link */
-a:link img, a:visited img {
- -moz-user-input: none;
-}
-
-/* We suppress user/author's prefs for link underline,
- so we must set explicitly. This isn't good!
-*/
-a:link {
- text-decoration: underline -moz-anchor-decoration;
- color: -moz-hyperlinktext;
-}
-
-/* Allow double-clicks on these widgets to open properties dialogs
- XXX except when the widget has disabled attribute */
-input, button, textarea {
- -moz-user-select: all !important;
- -moz-user-input: auto !important;
- -moz-user-focus: none !important;
-}
-
-/* XXX Still need a better way of blocking other events to these widgets */
-select, input[disabled], input[type="checkbox"], input[type="radio"], input[type="file"] {
- -moz-user-select: all !important;
- -moz-user-input: none !important;
- -moz-user-focus: none !important;
-}
-
-input[type="hidden"] {
- border: 1px solid black !important;
- visibility: visible !important;
-}
-
-label {
- -moz-user-select: all !important;
-}
-
-::-moz-display-comboboxcontrol-frame {
- -moz-user-select: text !important;
-}
-
-option {
- -moz-user-select: text !important;
-}
-
-#mozToc.readonly {
- -moz-user-select: all !important;
- -moz-user-input: none !important;
-}
-
-/* the following rules are for Image Resizing */
-
-span[\_moz_anonclass="mozResizer"] {
- width: 5px;
- height: 5px;
- position: absolute;
- border: 1px black solid;
- background-color: white;
- -moz-user-select: none;
- z-index: 2147483646; /* max value -1 for this property */
-}
-
-/* we can't use :active below */
-span[\_moz_anonclass="mozResizer"][\_moz_activated],
-span[\_moz_anonclass="mozResizer"]:hover {
- background-color: black;
-}
-
-span[\_moz_anonclass="mozResizer"].hidden,
-span[\_moz_anonclass="mozResizingShadow"].hidden,
-img[\_moz_anonclass="mozResizingShadow"].hidden,
-span[\_moz_anonclass="mozGrabber"].hidden,
-span[\_moz_anonclass="mozResizingInfo"].hidden,
-a[\_moz_anonclass="mozTableRemoveRow"].hidden,
-a[\_moz_anonclass="mozTableRemoveColumn"].hidden {
- display: none !important;
-}
-
-span[\_moz_anonclass="mozResizer"][anonlocation="nw"] {
- cursor: nw-resize;
-}
-span[\_moz_anonclass="mozResizer"][anonlocation="n"] {
- cursor: n-resize;
-}
-span[\_moz_anonclass="mozResizer"][anonlocation="ne"] {
- cursor: ne-resize;
-}
-span[\_moz_anonclass="mozResizer"][anonlocation="w"] {
- cursor: w-resize;
-}
-span[\_moz_anonclass="mozResizer"][anonlocation="e"] {
- cursor: e-resize;
-}
-span[\_moz_anonclass="mozResizer"][anonlocation="sw"] {
- cursor: sw-resize;
-}
-span[\_moz_anonclass="mozResizer"][anonlocation="s"] {
- cursor: s-resize;
-}
-span[\_moz_anonclass="mozResizer"][anonlocation="se"] {
- cursor: se-resize;
-}
-
-span[\_moz_anonclass="mozResizingShadow"],
-img[\_moz_anonclass="mozResizingShadow"] {
- outline: thin dashed black;
- -moz-user-select: none;
- opacity: 0.5;
- position: absolute;
- z-index: 2147483647; /* max value for this property */
-}
-
-span[\_moz_anonclass="mozResizingInfo"] {
- font-family: sans-serif;
- font-size: x-small;
- color: black;
- background-color: #d0d0d0;
- border: ridge 2px #d0d0d0;
- padding: 2px;
- position: absolute;
- z-index: 2147483647; /* max value for this property */
-}
-
-img[\_moz_resizing] {
- outline: thin solid black;
-}
-
-*[\_moz_abspos] {
- outline: silver ridge 2px;
- z-index: 2147483645 !important; /* max value -2 for this property */
-}
-*[\_moz_abspos="white"] {
- background-color: white !important;
-}
-*[\_moz_abspos="black"] {
- background-color: black !important;
-}
-
-span[\_moz_anonclass="mozGrabber"] {
- outline: ridge 2px silver;
- padding: 2px;
- position: absolute;
- width: 12px;
- height: 12px;
- background-image: url("resource://gre/res/grabber.gif");
- background-repeat: no-repeat;
- background-position: center center;
- -moz-user-select: none;
- cursor: move;
- z-index: 2147483647; /* max value for this property */
-}
-
-/* INLINE TABLE EDITING */
-
-a[\_moz_anonclass="mozTableAddColumnBefore"] {
- position: absolute;
- z-index: 2147483647; /* max value for this property */
- text-decoration: none !important;
- border: none 0px !important;
- width: 4px;
- height: 8px;
- background-image: url("resource://gre/res/table-add-column-before.gif");
- background-repeat: no-repeat;
- background-position: center center;
- -moz-user-select: none !important;
- -moz-user-focus: none !important;
-}
-
-a[\_moz_anonclass="mozTableAddColumnBefore"]:hover {
- background-image: url("resource://gre/res/table-add-column-before-hover.gif");
-}
-
-a[\_moz_anonclass="mozTableAddColumnBefore"]:active {
- background-image: url("resource://gre/res/table-add-column-before-active.gif");
-}
-
-a[\_moz_anonclass="mozTableAddColumnAfter"] {
- position: absolute;
- z-index: 2147483647; /* max value for this property */
- text-decoration: none !important;
- border: none 0px !important;
- width: 4px;
- height: 8px;
- background-image: url("resource://gre/res/table-add-column-after.gif");
- background-repeat: no-repeat;
- background-position: center center;
- -moz-user-select: none !important;
- -moz-user-focus: none !important;
-}
-
-a[\_moz_anonclass="mozTableAddColumnAfter"]:hover {
- background-image: url("resource://gre/res/table-add-column-after-hover.gif");
-}
-
-a[\_moz_anonclass="mozTableAddColumnAfter"]:active {
- background-image: url("resource://gre/res/table-add-column-after-active.gif");
-}
-
-a[\_moz_anonclass="mozTableRemoveColumn"] {
- position: absolute;
- z-index: 2147483647; /* max value for this property */
- text-decoration: none !important;
- border: none 0px !important;
- width: 8px;
- height: 8px;
- background-image: url("resource://gre/res/table-remove-column.gif");
- background-repeat: no-repeat;
- background-position: center center;
- -moz-user-select: none !important;
- -moz-user-focus: none !important;
-}
-
-a[\_moz_anonclass="mozTableRemoveColumn"]:hover {
- background-image: url("resource://gre/res/table-remove-column-hover.gif");
-}
-
-a[\_moz_anonclass="mozTableRemoveColumn"]:active {
- background-image: url("resource://gre/res/table-remove-column-active.gif");
-}
-
-a[\_moz_anonclass="mozTableAddRowBefore"] {
- position: absolute;
- z-index: 2147483647; /* max value for this property */
- text-decoration: none !important;
- border: none 0px !important;
- width: 8px;
- height: 4px;
- background-image: url("resource://gre/res/table-add-row-before.gif");
- background-repeat: no-repeat;
- background-position: center center;
- -moz-user-select: none !important;
- -moz-user-focus: none !important;
-}
-
-a[\_moz_anonclass="mozTableAddRowBefore"]:hover {
- background-image: url("resource://gre/res/table-add-row-before-hover.gif");
-}
-
-a[\_moz_anonclass="mozTableAddRowBefore"]:active {
- background-image: url("resource://gre/res/table-add-row-before-active.gif");
-}
-
-a[\_moz_anonclass="mozTableAddRowAfter"] {
- position: absolute;
- z-index: 2147483647; /* max value for this property */
- text-decoration: none !important;
- border: none 0px !important;
- width: 8px;
- height: 4px;
- background-image: url("resource://gre/res/table-add-row-after.gif");
- background-repeat: no-repeat;
- background-position: center center;
- -moz-user-select: none !important;
- -moz-user-focus: none !important;
-}
-
-a[\_moz_anonclass="mozTableAddRowAfter"]:hover {
- background-image: url("resource://gre/res/table-add-row-after-hover.gif");
-}
-
-a[\_moz_anonclass="mozTableAddRowAfter"]:active {
- background-image: url("resource://gre/res/table-add-row-after-active.gif");
-}
-
-a[\_moz_anonclass="mozTableRemoveRow"] {
- position: absolute;
- z-index: 2147483647; /* max value for this property */
- text-decoration: none !important;
- border: none 0px !important;
- width: 8px;
- height: 8px;
- background-image: url("resource://gre/res/table-remove-row.gif");
- background-repeat: no-repeat;
- background-position: center center;
- -moz-user-select: none !important;
- -moz-user-focus: none !important;
-}
-
-a[\_moz_anonclass="mozTableRemoveRow"]:hover {
- background-image: url("resource://gre/res/table-remove-row-hover.gif");
-}
-
-a[\_moz_anonclass="mozTableRemoveRow"]:active {
- background-image: url("resource://gre/res/table-remove-row-active.gif");
-}
diff --git a/editor/composer/res/grabber.gif b/editor/composer/res/grabber.gif
deleted file mode 100644
index 06749a64f..000000000
--- a/editor/composer/res/grabber.gif
+++ /dev/null
Binary files differ
diff --git a/editor/composer/res/table-add-column-after-active.gif b/editor/composer/res/table-add-column-after-active.gif
deleted file mode 100644
index 3ec50b82e..000000000
--- a/editor/composer/res/table-add-column-after-active.gif
+++ /dev/null
Binary files differ
diff --git a/editor/composer/res/table-add-column-after-hover.gif b/editor/composer/res/table-add-column-after-hover.gif
deleted file mode 100644
index 29679f981..000000000
--- a/editor/composer/res/table-add-column-after-hover.gif
+++ /dev/null
Binary files differ
diff --git a/editor/composer/res/table-add-column-after.gif b/editor/composer/res/table-add-column-after.gif
deleted file mode 100644
index 8891be969..000000000
--- a/editor/composer/res/table-add-column-after.gif
+++ /dev/null
Binary files differ
diff --git a/editor/composer/res/table-add-column-before-active.gif b/editor/composer/res/table-add-column-before-active.gif
deleted file mode 100644
index 1e205291e..000000000
--- a/editor/composer/res/table-add-column-before-active.gif
+++ /dev/null
Binary files differ
diff --git a/editor/composer/res/table-add-column-before-hover.gif b/editor/composer/res/table-add-column-before-hover.gif
deleted file mode 100644
index 7b54537e4..000000000
--- a/editor/composer/res/table-add-column-before-hover.gif
+++ /dev/null
Binary files differ
diff --git a/editor/composer/res/table-add-column-before.gif b/editor/composer/res/table-add-column-before.gif
deleted file mode 100644
index d4a3ffe5e..000000000
--- a/editor/composer/res/table-add-column-before.gif
+++ /dev/null
Binary files differ
diff --git a/editor/composer/res/table-add-row-after-active.gif b/editor/composer/res/table-add-row-after-active.gif
deleted file mode 100644
index cc01da2c9..000000000
--- a/editor/composer/res/table-add-row-after-active.gif
+++ /dev/null
Binary files differ
diff --git a/editor/composer/res/table-add-row-after-hover.gif b/editor/composer/res/table-add-row-after-hover.gif
deleted file mode 100644
index a829351b6..000000000
--- a/editor/composer/res/table-add-row-after-hover.gif
+++ /dev/null
Binary files differ
diff --git a/editor/composer/res/table-add-row-after.gif b/editor/composer/res/table-add-row-after.gif
deleted file mode 100644
index 3f1a39d98..000000000
--- a/editor/composer/res/table-add-row-after.gif
+++ /dev/null
Binary files differ
diff --git a/editor/composer/res/table-add-row-before-active.gif b/editor/composer/res/table-add-row-before-active.gif
deleted file mode 100644
index 34f1e0ade..000000000
--- a/editor/composer/res/table-add-row-before-active.gif
+++ /dev/null
Binary files differ
diff --git a/editor/composer/res/table-add-row-before-hover.gif b/editor/composer/res/table-add-row-before-hover.gif
deleted file mode 100644
index e8f1d10b0..000000000
--- a/editor/composer/res/table-add-row-before-hover.gif
+++ /dev/null
Binary files differ
diff --git a/editor/composer/res/table-add-row-before.gif b/editor/composer/res/table-add-row-before.gif
deleted file mode 100644
index 1682170cb..000000000
--- a/editor/composer/res/table-add-row-before.gif
+++ /dev/null
Binary files differ
diff --git a/editor/composer/res/table-remove-column-active.gif b/editor/composer/res/table-remove-column-active.gif
deleted file mode 100644
index 4dfbde4ce..000000000
--- a/editor/composer/res/table-remove-column-active.gif
+++ /dev/null
Binary files differ
diff --git a/editor/composer/res/table-remove-column-hover.gif b/editor/composer/res/table-remove-column-hover.gif
deleted file mode 100644
index fd11bb52c..000000000
--- a/editor/composer/res/table-remove-column-hover.gif
+++ /dev/null
Binary files differ
diff --git a/editor/composer/res/table-remove-column.gif b/editor/composer/res/table-remove-column.gif
deleted file mode 100644
index d8071da0a..000000000
--- a/editor/composer/res/table-remove-column.gif
+++ /dev/null
Binary files differ
diff --git a/editor/composer/res/table-remove-row-active.gif b/editor/composer/res/table-remove-row-active.gif
deleted file mode 100644
index 4dfbde4ce..000000000
--- a/editor/composer/res/table-remove-row-active.gif
+++ /dev/null
Binary files differ
diff --git a/editor/composer/res/table-remove-row-hover.gif b/editor/composer/res/table-remove-row-hover.gif
deleted file mode 100644
index fd11bb52c..000000000
--- a/editor/composer/res/table-remove-row-hover.gif
+++ /dev/null
Binary files differ
diff --git a/editor/composer/res/table-remove-row.gif b/editor/composer/res/table-remove-row.gif
deleted file mode 100644
index d8071da0a..000000000
--- a/editor/composer/res/table-remove-row.gif
+++ /dev/null
Binary files differ
diff --git a/editor/composer/test/bug1200533_subframe.html b/editor/composer/test/bug1200533_subframe.html
deleted file mode 100644
index 6eaefc266..000000000
--- a/editor/composer/test/bug1200533_subframe.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta http-equiv="Content-Language" content="en-US">
-</head>
-<body>
-<textarea id="none">root en-US</textarea>
-<textarea id="en-GB" lang="en-GB">root en-US, but element en-GB</textarea>
-<textarea id="en-gb" lang="en-gb">root en-US, but element en-gb (lower case)</textarea>
-<textarea id="en-ZA-not-avail" lang="en-ZA">root en-US, but element en-ZA (which is not installed)</textarea>
-<textarea id="en-generic" lang="en">root en-US, but element en</textarea>
-<textarea id="ko-not-avail" lang="ko">root en-US, but element ko (which is not installed)</textarea>
-</body>
-</html>
diff --git a/editor/composer/test/bug1204147_subframe.html b/editor/composer/test/bug1204147_subframe.html
deleted file mode 100644
index a9b1225cd..000000000
--- a/editor/composer/test/bug1204147_subframe.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-</head>
-<body>
-<textarea id="en-GB" lang="en-GB">element en-GB</textarea>
-<textarea id="en-US" lang="testing-XX">element should default to en-US</textarea>
-
-<div id="trouble-maker" contenteditable>the presence of this div triggers the faulty code path</div>
-</body>
-</html>
diff --git a/editor/composer/test/bug1204147_subframe2.html b/editor/composer/test/bug1204147_subframe2.html
deleted file mode 100644
index 935777bd9..000000000
--- a/editor/composer/test/bug1204147_subframe2.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-</head>
-<body>
-<textarea id="en-GB" lang="en-GB">element en-GB</textarea>
-<textarea id="en-US" lang="testing-XX">element should default to en-US</textarea>
-</body>
-</html>
diff --git a/editor/composer/test/bug678842_subframe.html b/editor/composer/test/bug678842_subframe.html
deleted file mode 100644
index 39d578ee4..000000000
--- a/editor/composer/test/bug678842_subframe.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-</head>
-<body>
-<textarea id="textarea" lang="testing-XXX"></textarea>
-</body>
-</html>
diff --git a/editor/composer/test/bug717433_subframe.html b/editor/composer/test/bug717433_subframe.html
deleted file mode 100644
index 3c2927e88..000000000
--- a/editor/composer/test/bug717433_subframe.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-</head>
-<body>
-<textarea id="textarea" lang="en"></textarea>
-</body>
-</html>
diff --git a/editor/composer/test/chrome.ini b/editor/composer/test/chrome.ini
deleted file mode 100644
index 015cad3d5..000000000
--- a/editor/composer/test/chrome.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[DEFAULT]
-skip-if = os == 'android'
-
-[test_bug434998.xul]
-[test_bug1266815.html]
diff --git a/editor/composer/test/de-DE/de_DE.aff b/editor/composer/test/de-DE/de_DE.aff
deleted file mode 100644
index 5dc6896b6..000000000
--- a/editor/composer/test/de-DE/de_DE.aff
+++ /dev/null
@@ -1,2 +0,0 @@
-# Affix file for German English dictionary
-# Fake file, nothing here.
diff --git a/editor/composer/test/de-DE/de_DE.dic b/editor/composer/test/de-DE/de_DE.dic
deleted file mode 100644
index 415c21686..000000000
--- a/editor/composer/test/de-DE/de_DE.dic
+++ /dev/null
@@ -1,6 +0,0 @@
-5
-ein
-guter
-heute
-ist
-Tag
diff --git a/editor/composer/test/en-AU/en_AU.aff b/editor/composer/test/en-AU/en_AU.aff
deleted file mode 100644
index e0c467248..000000000
--- a/editor/composer/test/en-AU/en_AU.aff
+++ /dev/null
@@ -1,2 +0,0 @@
-# Affix file for British English dictionary
-# Fake file, nothing here.
diff --git a/editor/composer/test/en-AU/en_AU.dic b/editor/composer/test/en-AU/en_AU.dic
deleted file mode 100644
index 0a1be725d..000000000
--- a/editor/composer/test/en-AU/en_AU.dic
+++ /dev/null
@@ -1,4 +0,0 @@
-3
-Mary
-Paul
-Peter
diff --git a/editor/composer/test/en-GB/en_GB.aff b/editor/composer/test/en-GB/en_GB.aff
deleted file mode 100644
index e0c467248..000000000
--- a/editor/composer/test/en-GB/en_GB.aff
+++ /dev/null
@@ -1,2 +0,0 @@
-# Affix file for British English dictionary
-# Fake file, nothing here.
diff --git a/editor/composer/test/en-GB/en_GB.dic b/editor/composer/test/en-GB/en_GB.dic
deleted file mode 100644
index 0a1be725d..000000000
--- a/editor/composer/test/en-GB/en_GB.dic
+++ /dev/null
@@ -1,4 +0,0 @@
-3
-Mary
-Paul
-Peter
diff --git a/editor/composer/test/mochitest.ini b/editor/composer/test/mochitest.ini
deleted file mode 100644
index 832137d60..000000000
--- a/editor/composer/test/mochitest.ini
+++ /dev/null
@@ -1,40 +0,0 @@
-[DEFAULT]
-support-files =
- bug678842_subframe.html
- bug717433_subframe.html
- bug1200533_subframe.html
- bug1204147_subframe.html
- bug1204147_subframe2.html
- en-GB/en_GB.dic
- en-GB/en_GB.aff
- en-AU/en_AU.dic
- en-AU/en_AU.aff
- de-DE/de_DE.dic
- de-DE/de_DE.aff
-
-[test_async_UpdateCurrentDictionary.html]
-skip-if = os == 'android'
-[test_bug338427.html]
-skip-if = os == 'android'
-[test_bug348497.html]
-[test_bug384147.html]
-[test_bug389350.html]
-skip-if = toolkit == 'android'
-[test_bug519928.html]
-[test_bug678842.html]
-skip-if = os == 'android'
-[test_bug697981.html]
-skip-if = os == 'android'
-[test_bug717433.html]
-skip-if = os == 'android'
-[test_bug738440.html]
-[test_bug1200533.html]
-skip-if = os == 'android'
-[test_bug1204147.html]
-skip-if = os == 'android'
-[test_bug1205983.html]
-skip-if = os == 'android'
-[test_bug1209414.html]
-skip-if = os == 'android'
-[test_bug1219928.html]
-skip-if = e10s || os == 'android'
diff --git a/editor/composer/test/test_async_UpdateCurrentDictionary.html b/editor/composer/test/test_async_UpdateCurrentDictionary.html
deleted file mode 100644
index 53d9ff307..000000000
--- a/editor/composer/test/test_async_UpdateCurrentDictionary.html
+++ /dev/null
@@ -1,75 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=856270
--->
-<head>
- <title>Test for Bug 856270 - Async UpdateCurrentDictionary</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=856270">Mozilla Bug 856270</a>
-<p id="display"></p>
-<div id="content">
-<textarea id="editor" spellcheck="true"></textarea>
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript;version=1.8">
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(start);
-
-function start() {
- var textarea = document.getElementById("editor");
- textarea.focus();
-
- SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm")
- .onSpellCheck(textarea, function () {
- var isc = SpecialPowers.wrap(textarea).editor.getInlineSpellChecker(false);
- ok(isc, "Inline spell checker should exist after focus and spell check");
- var sc = isc.spellChecker;
- isnot(sc.GetCurrentDictionary(), lang,
- "Current dictionary should not be set yet.");
-
- // First, set the lang attribute on the textarea, call Update, and make
- // sure the spell checker's language was updated appropriately.
- var lang = "en-US";
- textarea.setAttribute("lang", lang);
- sc.UpdateCurrentDictionary(function () {
- is(sc.GetCurrentDictionary(), lang,
- "UpdateCurrentDictionary should set the current dictionary.");
-
- // Second, make some Update calls, but then do a Set. The Set should
- // effectively cancel the Updates, but the Updates' callbacks should be
- // called nonetheless.
- var numCalls = 3;
- for (var i = 0; i < numCalls; i++) {
- sc.UpdateCurrentDictionary(function () {
- is(sc.GetCurrentDictionary(), "",
- "No dictionary should be active after Update.");
- if (--numCalls == 0) {
- // This will clear the content preferences and reset "spellchecker.dictionary".
- sc.SetCurrentDictionary("");
- SimpleTest.finish();
- }
- });
- }
- try {
- sc.SetCurrentDictionary("testing-XX");
- }
- catch (err) {
- // Set throws NS_ERROR_NOT_AVAILABLE because "testing-XX" isn't really
- // an available dictionary.
- }
- is(sc.GetCurrentDictionary(), "",
- "No dictionary should be active after Set.");
- });
- });
-}
-
-</script>
-</pre>
-</body>
-</html>
-
diff --git a/editor/composer/test/test_bug1200533.html b/editor/composer/test/test_bug1200533.html
deleted file mode 100644
index 310b8d7cf..000000000
--- a/editor/composer/test/test_bug1200533.html
+++ /dev/null
@@ -1,139 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1200533
--->
-<head>
- <title>Test for Bug 1200533</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1200533">Mozilla Bug 1200533</a>
-<p id="display"></p>
-<iframe id="content"></iframe>
-
-</div>
-<pre id="test">
-<script class="testbody" ttype="application/javascript">
-
-/** Test for Bug 1200533 **/
-/** Visit the elements defined above and check the dictionary we got **/
-SimpleTest.waitForExplicitFinish();
-var content = document.getElementById('content');
-
-var tests = [
- // text area, value of spellchecker.dictionary, result.
- // Result: Document language.
- [ "none", "", "en-US" ],
- // Result: Element language.
- [ "en-GB", "", "en-GB" ],
- [ "en-gb", "", "en-GB" ],
- // Result: Random en-*.
- [ "en-ZA-not-avail", "", "*" ],
- [ "en-generic", "", "*" ],
- // Result: Locale.
- [ "ko-not-avail", "", "en-US" ],
-
- // Result: Preference value in all cases.
- [ "en-ZA-not-avail", "en-AU", "en-AU" ],
- [ "en-generic", "en-AU", "en-AU" ],
- [ "ko-not-avail", "en-AU", "en-AU" ],
-
- // Result: Random en-*.
- [ "en-ZA-not-avail", "de-DE", "*" ],
- [ "en-generic", "de-DE", "*" ],
- // Result: Preference value.
- [ "ko-not-avail", "de-DE", "de-DE" ],
- ];
-
-var loadCount = 0;
-var script;
-
-var loadListener = function(evt) {
- if (loadCount == 0) {
- script = SpecialPowers.loadChromeScript(function() {
- var dir = Components.classes["@mozilla.org/file/directory_service;1"]
- .getService(Components.interfaces.nsIProperties)
- .get("CurWorkD", Components.interfaces.nsIFile);
- dir.append("tests");
- dir.append("editor");
- dir.append("composer");
- dir.append("test");
-
- var hunspell = Components.classes["@mozilla.org/spellchecker/engine;1"]
- .getService(Components.interfaces.mozISpellCheckingEngine);
-
- // Install en-GB, en-AU and de-DE dictionaries.
- var en_GB = dir.clone();
- var en_AU = dir.clone();
- var de_DE = dir.clone();
- en_GB.append("en-GB");
- en_AU.append("en-AU");
- de_DE.append("de-DE");
- hunspell.addDirectory(en_GB);
- hunspell.addDirectory(en_AU);
- hunspell.addDirectory(de_DE);
-
- addMessageListener("check-existence",
- () => [en_GB.exists(), en_AU.exists(),
- de_DE.exists()]);
- addMessageListener("destroy", () => {
- hunspell.removeDirectory(en_GB);
- hunspell.removeDirectory(en_AU);
- hunspell.removeDirectory(de_DE);
- });
- });
- var existenceChecks = script.sendSyncMessage("check-existence")[0][0];
- is(existenceChecks[0], true, "true expected (en-GB directory should exist)");
- is(existenceChecks[1], true, "true expected (en-AU directory should exist)");
- is(existenceChecks[2], true, "true expected (de-DE directory should exist)");
- }
-
- SpecialPowers.pushPrefEnv({set: [["spellchecker.dictionary", tests[loadCount][1]]]},
- function() { continueTest(evt) });
-}
-
-function continueTest(evt) {
- var doc = evt.target.contentDocument;
- var elem = doc.getElementById(tests[loadCount][0]);
- var editor = SpecialPowers.wrap(elem).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
- editor.setSpellcheckUserOverride(true);
- var inlineSpellChecker = editor.getInlineSpellChecker(true);
-
- SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm")
- .onSpellCheck(elem, function () {
- var spellchecker = inlineSpellChecker.spellChecker;
- try {
- var dict = spellchecker.GetCurrentDictionary();
- } catch(e) {}
-
- if (tests[loadCount][2] != "*") {
- is (dict, tests[loadCount][2], "expected " + tests[loadCount][2]);
- } else {
- var gotEn = (dict == "en-GB" || dict == "en-AU" || dict == "en-US");
- is (gotEn, true, "expected en-AU or en-GB or en-US");
- }
-
- loadCount++;
- if (loadCount < tests.length) {
- // Load the iframe again.
- content.src = 'http://mochi.test:8888/tests/editor/composer/test/bug1200533_subframe.html?firstload=false';
- } else {
- // Remove the fake dictionaries again, since it's otherwise picked up by later tests.
- script.sendSyncMessage("destroy");
-
- SimpleTest.finish();
- }
- });
-
-}
-
-content.addEventListener('load', loadListener, false);
-
-content.src = 'http://mochi.test:8888/tests/editor/composer/test/bug1200533_subframe.html?firstload=true';
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/composer/test/test_bug1204147.html b/editor/composer/test/test_bug1204147.html
deleted file mode 100644
index d7dd90474..000000000
--- a/editor/composer/test/test_bug1204147.html
+++ /dev/null
@@ -1,112 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1204147
--->
-<head>
- <title>Test for Bug 1204147</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1204147">Mozilla Bug 1204147</a>
-<p id="display"></p>
-<iframe id="content"></iframe>
-</div>
-
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-/** Test for Bug 1204147 **/
-SimpleTest.waitForExplicitFinish();
-var content = document.getElementById('content');
-// Load a subframe containing an editor with using "en-GB". At first
-// load, it will set the dictionary to "en-GB". The bug was that a content preference
-// was also created. At second load, we check the dictionary for another element,
-// one that should use "en-US". With the bug corrected, we get "en-US", before
-// we got "en-GB" from the content preference.
-
-var firstLoad = true;
-var script;
-
-var loadListener = function(evt) {
- if (firstLoad) {
- script = SpecialPowers.loadChromeScript(function() {
- var dir = Components.classes["@mozilla.org/file/directory_service;1"]
- .getService(Components.interfaces.nsIProperties)
- .get("CurWorkD", Components.interfaces.nsIFile);
- dir.append("tests");
- dir.append("editor");
- dir.append("composer");
- dir.append("test");
-
- var hunspell = Components.classes["@mozilla.org/spellchecker/engine;1"]
- .getService(Components.interfaces.mozISpellCheckingEngine);
-
- // Install en-GB dictionary.
- en_GB = dir.clone();
- en_GB.append("en-GB");
- hunspell.addDirectory(en_GB);
-
- addMessageListener("en_GB-exists", () => en_GB.exists());
- addMessageListener("destroy", () => hunspell.removeDirectory(en_GB));
- });
- is(script.sendSyncMessage("en_GB-exists")[0][0], true,
- "true expected (en-GB directory should exist)");
- }
-
- var doc = evt.target.contentDocument;
- var elem;
- if (firstLoad) {
- elem = doc.getElementById('en-GB');
- } else {
- elem = doc.getElementById('en-US');
- }
-
- var editor = SpecialPowers.wrap(elem).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
- editor.setSpellcheckUserOverride(true);
- var inlineSpellChecker = editor.getInlineSpellChecker(true);
-
- SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm")
- .onSpellCheck(elem, function () {
- var spellchecker = inlineSpellChecker.spellChecker;
- try {
- var currentDictonary = spellchecker.GetCurrentDictionary();
- } catch(e) {}
-
- if (firstLoad) {
- firstLoad = false;
-
- // First time around, the element's language should be used.
- is (currentDictonary, "en-GB", "unexpected lang " + currentDictonary + " instead of en-GB");
-
- // Note that on second load, we load a different page, which does NOT have the trouble-causing
- // contenteditable in it. Sadly, loading the same page with the trouble-maker in it
- // doesn't allow the retrieval of the spell check dictionary used for the element,
- // because the trouble-maker causes the 'global' spell check dictionary to be set to "en-GB"
- // (since it picks the first one from the list) before we have the chance to retrieve
- // the dictionary for the element (which happens asynchonously after the spell check has completed).
- content.src = 'http://mochi.test:8888/tests/editor/composer/test/bug1204147_subframe2.html?firstload=false';
- } else {
- // Second time around, the element should default to en-US.
- // Without the fix, the first run sets the content preference to en-GB for the whole site.
- is (currentDictonary, "en-US", "unexpected lang " + currentDictonary + " instead of en-US");
- content.removeEventListener('load', loadListener, false);
-
- // Remove the fake en-GB dictionary again, since it's otherwise picked up by later tests.
- script.sendSyncMessage("destroy");
-
- // Reset the preference, so the last value we set doesn't collide with the next test.
- SimpleTest.finish();
- }
- });
-}
-
-content.addEventListener('load', loadListener, false);
-
-content.src = 'http://mochi.test:8888/tests/editor/composer/test/bug1204147_subframe.html?firstload=true';
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/composer/test/test_bug1205983.html b/editor/composer/test/test_bug1205983.html
deleted file mode 100644
index 139f6fc3c..000000000
--- a/editor/composer/test/test_bug1205983.html
+++ /dev/null
@@ -1,137 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1205983
--->
-<head>
- <title>Test for Bug 1205983</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1205983">Mozilla Bug 1205983</a>
-<p id="display"></p>
-</div>
-
-<div contenteditable id="de-DE" lang="de-DE" onfocus="deFocus()">German heute ist ein guter Tag</div>
-<textarea id="en-US" lang="en-US" onfocus="enFocus()">Nogoodword today is a nice day</textarea>
-
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-function getMisspelledWords(editor) {
- return editor.selectionController.getSelection(SpecialPowers.Ci.nsISelectionController.SELECTION_SPELLCHECK).toString();
-}
-
-var elem_de;
-var editor_de;
-var selcon_de;
-var script;
-
-var onSpellCheck =
- SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm")
- .onSpellCheck;
-
-/** Test for Bug 1205983 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- script = SpecialPowers.loadChromeScript(function() {
- var dir = Components.classes["@mozilla.org/file/directory_service;1"]
- .getService(Components.interfaces.nsIProperties)
- .get("CurWorkD", Components.interfaces.nsIFile);
- dir.append("tests");
- dir.append("editor");
- dir.append("composer");
- dir.append("test");
-
- var hunspell = Components.classes["@mozilla.org/spellchecker/engine;1"]
- .getService(Components.interfaces.mozISpellCheckingEngine);
-
- // Install de-DE dictionary.
- var de_DE = dir.clone();
- de_DE.append("de-DE");
- hunspell.addDirectory(de_DE);
-
- addMessageListener("de_DE-exists", () => de_DE.exists());
- addMessageListener("destroy", () => hunspell.removeDirectory(de_DE));
- });
- is(script.sendSyncMessage("de_DE-exists")[0][0], true,
- "true expected (de_DE directory should exist)");
-
- document.getElementById('de-DE').focus();
-});
-
-function deFocus() {
- elem_de = document.getElementById('de-DE');
-
- onSpellCheck(elem_de, function () {
- var Ci = SpecialPowers.Ci;
- var editingSession = SpecialPowers.wrap(window)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIEditingSession);
- editor_de = editingSession.getEditorForWindow(window);
- selcon_de = editor_de.selectionController;
- var sel = selcon_de.getSelection(selcon_de.SELECTION_SPELLCHECK);
-
- // Check that we spelled in German, so there is only one misspelled word.
- is(sel.toString(), "German", "one misspelled word expected: German");
-
- // Now focus the textarea, which requires English spelling.
- document.getElementById('en-US').focus();
- });
-}
-
-function enFocus() {
- var elem_en = document.getElementById('en-US');
- var editor_en =
- SpecialPowers.wrap(elem_en)
- .QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement)
- .editor;
- editor_en.setSpellcheckUserOverride(true);
- var inlineSpellChecker = editor_en.getInlineSpellChecker(true);
-
- onSpellCheck(elem_en, function () {
- var spellchecker = inlineSpellChecker.spellChecker;
- try {
- currentDictonary = spellchecker.GetCurrentDictionary();
- } catch(e) {}
-
- // Check that the English dictionary is loaded and that the spell check has worked.
- is(currentDictonary, "en-US", "expected en-US");
- is(getMisspelledWords(editor_en), "Nogoodword", "one misspelled word expected: Nogoodword");
-
- // So far all was boring. The important thing is whether the spell check result
- // in the de-DE editor is still the same. After losing focus, no spell check
- // updates should take place there.
- var sel = selcon_de.getSelection(selcon_de.SELECTION_SPELLCHECK);
- is(sel.toString(), "German", "one misspelled word expected: German");
-
- // Remove the fake de_DE dictionary again.
- script.sendSyncMessage("destroy");
-
- // Focus again, so the spelling gets updated, but before we need to kill the focus handler.
- elem_de.onfocus = null;
- elem_de.blur();
- elem_de.focus();
-
- // After removal, the de_DE editor should refresh the spelling with en-US.
- onSpellCheck(elem_de, function () {
- var sel = selcon_de.getSelection(selcon_de.SELECTION_SPELLCHECK);
- is(sel.toString(), "heute" + "ist" + "ein" + "guter",
- "some misspelled words expected: heute ist ein guter");
-
- // If we don't reset this, we cause massive leaks.
- selcon_de = null;
- editor_de = null;
-
- SimpleTest.finish();
- });
- });
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/composer/test/test_bug1209414.html b/editor/composer/test/test_bug1209414.html
deleted file mode 100644
index bce1bb313..000000000
--- a/editor/composer/test/test_bug1209414.html
+++ /dev/null
@@ -1,150 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1209414
--->
-<head>
- <title>Test for Bug 1209414</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <script src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1209414">Mozilla Bug 1209414</a>
-<p id="display"></p>
-</div>
-
-<textarea id="de-DE" lang="de-DE">heute ist ein guter Tag - today is a good day</textarea>
-
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-const Ci = SpecialPowers.Ci;
-
-function getMisspelledWords(editor) {
- return editor.selectionController.getSelection(Ci.nsISelectionController.SELECTION_SPELLCHECK).toString();
-}
-
-var elem_de;
-var editor_de;
-var script;
-
-/** Test for Bug 1209414 **/
-/*
- * All we want to do in this test is change the spelling using a right-click and selection from the menu.
- * This is necessary since all the other tests use SetCurrentDictionary() which doesn't reflect
- * user behaviour.
- */
-
-var onSpellCheck =
- SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm")
- .onSpellCheck;
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- script = SpecialPowers.loadChromeScript(function() {
- const Ci = Components.interfaces;
- var chromeWin = browserElement.ownerDocument.defaultView
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShellTreeItem)
- .rootTreeItem
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindow)
- .QueryInterface(Ci.nsIDOMChromeWindow);
- var contextMenu = chromeWin.document.getElementById("contentAreaContextMenu");
- contextMenu.addEventListener("popupshown",
- () => sendAsyncMessage("popupshown"), false);
-
- var dir = Components.classes["@mozilla.org/file/directory_service;1"]
- .getService(Ci.nsIProperties)
- .get("CurWorkD", Ci.nsIFile);
- dir.append("tests");
- dir.append("editor");
- dir.append("composer");
- dir.append("test");
-
- var hunspell = Components.classes["@mozilla.org/spellchecker/engine;1"]
- .getService(Ci.mozISpellCheckingEngine);
-
- // Install de-DE dictionary.
- de_DE = dir.clone();
- de_DE.append("de-DE");
- hunspell.addDirectory(de_DE);
-
- addMessageListener("hidepopup", function() {
- var state = contextMenu.state;
-
- // Select Language from the menu. Take a look at
- // toolkit/modules/InlineSpellChecker.jsm to see how the menu works.
-
- contextMenu.ownerDocument.getElementById("spell-check-dictionary-en-US")
- .doCommand();
- contextMenu.hidePopup();
-
- return state;
- });
- addMessageListener("destroy", () => hunspell.removeDirectory(de_DE));
- addMessageListener("contextMenu-not-null", () => contextMenu != null);
- addMessageListener("de_DE-exists", () => de_DE.exists());
- });
- is(script.sendSyncMessage("contextMenu-not-null")[0][0], true,
- "Got context menu XUL");
- is(script.sendSyncMessage("de_DE-exists")[0][0], true,
- "true expected (de_DE directory should exist)");
- script.addMessageListener("popupshown", handlePopup);
-
- elem_de = document.getElementById('de-DE');
- editor_de = SpecialPowers.wrap(elem_de)
- .QueryInterface(Ci.nsIDOMNSEditableElement).editor;
- editor_de.setSpellcheckUserOverride(true);
-
- onSpellCheck(elem_de, function () {
- var inlineSpellChecker = editor_de.getInlineSpellChecker(true);
- var spellchecker = inlineSpellChecker.spellChecker;
- try {
- var currentDictonary = spellchecker.GetCurrentDictionary();
- } catch(e) {}
-
- // Check that the German dictionary is loaded and that the spell check has worked.
- is(currentDictonary, "de-DE", "expected de-DE");
- is(getMisspelledWords(editor_de), "today" + "is" + "a" + "good" + "day", "some misspelled words expected: today is a good day");
-
- // Focus again, just to be sure that the context-click won't trigger another spell check.
- elem_de.focus();
-
- // Make sure all spell checking action is done before right-click to select the en-US dictionary.
- onSpellCheck(elem_de, function () {
- synthesizeMouse(elem_de, 2, 2, { type : "contextmenu", button : 2 }, window);
- });
- });
-});
-
-function handlePopup() {
- var state = script.sendSyncMessage("hidepopup")[0][0];
- is(state, "open", "checking if popup is open");
-
- onSpellCheck(elem_de, function () {
- var inlineSpellChecker = editor_de.getInlineSpellChecker(true);
- var spellchecker = inlineSpellChecker.spellChecker;
- try {
- currentDictonary = spellchecker.GetCurrentDictionary();
- } catch(e) {}
-
- // Check that the English dictionary is loaded and that the spell check has worked.
- is(currentDictonary, "en-US", "expected en-US");
- is(getMisspelledWords(editor_de), "heute" + "ist" + "ein" + "guter", "some misspelled words expected: heute ist ein guter");
-
- // Remove the fake de_DE dictionary again.
- script.sendSyncMessage("destroy");
-
- // This will clear the content preferences and reset "spellchecker.dictionary".
- spellchecker.SetCurrentDictionary("");
- SimpleTest.finish();
- });
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/composer/test/test_bug1219928.html b/editor/composer/test/test_bug1219928.html
deleted file mode 100644
index 2f646f00f..000000000
--- a/editor/composer/test/test_bug1219928.html
+++ /dev/null
@@ -1,76 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1219928
--->
-<head>
- <title>Test for Bug 1219928</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1219928">Mozilla Bug 1219928</a>
-<p id="display"></p>
-
-<div contenteditable id="en-US" lang="en-US">
-<p>And here a missspelled word</p>
-<style>
-<!-- and here another onnee in a style comment -->
-</style>
-</div>
-
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-/** Test for Bug 1219928 **/
-/* Very simple test to check that <style> blocks are skipped in the spell check */
-
-var spellchecker;
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm",
- window);
-
- var elem = document.getElementById('en-US');
- elem.focus();
-
- onSpellCheck(elem, function () {
- var Ci = SpecialPowers.Ci;
- var editingSession = SpecialPowers.wrap(window)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIEditingSession);
- var editor = editingSession.getEditorForWindow(window);
- var selcon = editor.selectionController;
- var sel = selcon.getSelection(selcon.SELECTION_SPELLCHECK);
-
- is(sel.toString(), "missspelled", "one misspelled word expected: missspelled");
-
- spellchecker = SpecialPowers.Cc['@mozilla.org/editor/editorspellchecker;1']
- .createInstance(Ci.nsIEditorSpellCheck);
- var filterContractId = "@mozilla.org/editor/txtsrvfilter;1";
- spellchecker.setFilter(SpecialPowers.Cc[filterContractId]
- .createInstance(Ci.nsITextServicesFilter));
- spellchecker.InitSpellChecker(editor, false, spellCheckStarted);
- });
-});
-
-function spellCheckStarted() {
- var misspelledWord = spellchecker.GetNextMisspelledWord();
- is(misspelledWord, "missspelled", "first misspelled word expected: missspelled");
-
- // Without the fix, the next misspelled word was 'onnee', so we check that we don't get it.
- misspelledWord = spellchecker.GetNextMisspelledWord();
- isnot(misspelledWord, "onnee", "second misspelled word should not be: onnee");
-
- spellchecker = "";
-
- SimpleTest.finish();
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/composer/test/test_bug1266815.html b/editor/composer/test/test_bug1266815.html
deleted file mode 100644
index a2ab0b048..000000000
--- a/editor/composer/test/test_bug1266815.html
+++ /dev/null
@@ -1,82 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
- <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-</head>
-<body>
-<p id="display"></p>
-<script type="text/javascript">
-const Cc = SpecialPowers.Cc;
-const Ci = SpecialPowers.Ci;
-const Cu = SpecialPowers.Cu;
-
-const {XPCOMUtils} = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
-
-const HELPERAPP_DIALOG_CID =
- SpecialPowers.wrap(SpecialPowers.Components)
- .ID(Cc["@mozilla.org/helperapplauncherdialog;1"].number);
-const HELPERAPP_DIALOG_CONTRACT_ID = "@mozilla.org/helperapplauncherdialog;1";
-const MOCK_HELPERAPP_DIALOG_CID =
- SpecialPowers.wrap(SpecialPowers.Components)
- .ID("{391832c8-5232-4676-b838-cc8ad373f3d8}");
-
-var registrar = SpecialPowers.wrap(Components).manager
- .QueryInterface(Ci.nsIComponentRegistrar);
-
-var helperAppDlgPromise = new Promise(function(resolve) {
- var mockHelperAppService;
-
- function HelperAppLauncherDialog() {
- }
-
- HelperAppLauncherDialog.prototype = {
- show: function(aLauncher, aWindowContext, aReason) {
- ok(true, "Whether showing Dialog");
- resolve();
- registrar.unregisterFactory(MOCK_HELPERAPP_DIALOG_CID,
- mockHelperAppService);
- },
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIHelperAppLauncherDialog])
- };
-
- mockHelperAppService = XPCOMUtils._getFactory(HelperAppLauncherDialog);
- registrar.registerFactory(MOCK_HELPERAPP_DIALOG_CID, "",
- HELPERAPP_DIALOG_CONTRACT_ID,
- mockHelperAppService);
-});
-
-add_task(function*() {
- let promise = new Promise(function(resolve) {
- let iframe = document.createElement("iframe");
- iframe.onload = function() {
- is(iframe.contentDocument.getElementById("edit").innerText, "abc",
- "load iframe source");
- resolve();
- };
- iframe.id = "testframe";
- iframe.src = "data:text/html,<div id=edit contenteditable=true>abc</div>";
- document.body.appendChild(iframe);
- });
-
- yield promise;
-
- let iframe = document.getElementById("testframe");
- let docShell = SpecialPowers.wrap(iframe.contentWindow)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShell);
-
- ok(docShell.hasEditingSession, "Should have editing session");
-
- document.getElementById("testframe").src =
- "data:application/octet-stream,TESTCONTENT";
-
- yield helperAppDlgPromise;
-
- ok(docShell.hasEditingSession, "Should have editing session");
-});
-</script>
-</body>
-</html>
diff --git a/editor/composer/test/test_bug338427.html b/editor/composer/test/test_bug338427.html
deleted file mode 100644
index f16194b3d..000000000
--- a/editor/composer/test/test_bug338427.html
+++ /dev/null
@@ -1,61 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=338427
--->
-<head>
- <title>Test for Bug 338427</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=338427">Mozilla Bug 338427</a>
-<p id="display"></p>
-<div id="content">
-<textarea id="editor" lang="testing-XX" spellcheck="true"></textarea>
-
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-/** Test for Bug 338427 **/
-function init() {
- var onSpellCheck =
- SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm")
- .onSpellCheck;
- var textarea = document.getElementById("editor");
- var editor = SpecialPowers.wrap(textarea).editor;
- var spellchecker = editor.getInlineSpellChecker(true);
- spellchecker.enableRealTimeSpell = true;
- textarea.focus();
-
- onSpellCheck(textarea, function () {
- var list = {}, count = {};
- spellchecker.spellChecker.GetDictionaryList(list, count);
- ok(count.value > 0, "At least one dictionary should be present");
-
- var lang = list.value[0];
- spellchecker.spellChecker.SetCurrentDictionary(lang);
-
- onSpellCheck(textarea, function () {
- try {
- var dictionary =
- spellchecker.spellChecker.GetCurrentDictionary();
- } catch(e) {}
- is(dictionary, lang, "Unexpected spell check dictionary");
-
- // This will clear the content preferences and reset "spellchecker.dictionary".
- spellchecker.spellChecker.SetCurrentDictionary("");
- SimpleTest.finish();
- });
- });
-}
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(init);
-
-</script>
-</pre>
-</body>
-</html>
-
diff --git a/editor/composer/test/test_bug348497.html b/editor/composer/test/test_bug348497.html
deleted file mode 100644
index 9483b727a..000000000
--- a/editor/composer/test/test_bug348497.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=348497
--->
-<head>
- <title>Test for Bug 348497</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=348497">Mozilla Bug 348497</a>
-<p id="display"></p>
-<div id="content">
- This page should not crash Mozilla<br>
- <iframe id="testIframe"></iframe>
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-/** Test for Bug 348497 **/
-function doe() {
- document.getElementById('testIframe').style.display = 'block';
- document.getElementById('testIframe').contentDocument.designMode = 'on';
-}
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(doe);
-addLoadEvent(function() { ok(true, "enabling designmode on an iframe onload does not crash Mozilla")});
-addLoadEvent(SimpleTest.finish);
-
-</script>
-</pre>
-</body>
-</html>
-
diff --git a/editor/composer/test/test_bug384147.html b/editor/composer/test/test_bug384147.html
deleted file mode 100644
index 35f0e533e..000000000
--- a/editor/composer/test/test_bug384147.html
+++ /dev/null
@@ -1,204 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=384147
--->
-<head>
- <title>Test for Bug 384147</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=384147">Mozilla Bug 384147</a>
-<p id="display"></p>
-<div id="content" style="display: block">
-<div contentEditable id="editor"></div>
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript;version=1.7">
-
-/** Test for Bug 384147 **/
-
-SimpleTest.waitForExplicitFinish();
-
-var editor = document.getElementById("editor");
-
-editor.innerHTML = "<ol><li>Item 1</li><li>Item 2</li><ol><li>Item 3</li></ol></ol><ul><li>Item 4</li><li>Item 5</li></ul>";
-editor.focus();
-
-// If executed directly, a race condition exists that will cause execCommand
-// to fail occasionally (but often). Defer test execution to page load.
-addLoadEvent(function() {
-
- var sel = window.getSelection();
-
- // Test the effect that the tab key has on list items. Each test is
- // documented with the initial state of the list on the left, and the
- // expected state of the list on the right. {\t} indicates the list item
- // that will be indented. {\st} indicates that a shift-tab will be simulated
- // on that list item, outdenting it.
- //
- // Note: any test failing will likely result in all following tests failing
- // as well, since each test depends on the document being in a given state.
- // Unfortunately, due to the problems getting document focus and key events
- // to fire consistently, it's difficult to reset state between tests.
- // If there are test failures here, only debug the first test failure.
-
- // *** test 1 ***
- // 1. Item 1 1. Item 1
- // 2. {\t}Item 2 1. Item 2
- // 1. Item 3 2. Item 3
- // * Item 4 * Item 4
- // * Item 5 * Item 5
- sel.removeAllRanges();
- sel.selectAllChildren(editor.getElementsByTagName("li")[1]);
- document.execCommand("indent", false, null);
- ok(editor.innerHTML == "<ol><li>Item 1</li><ol><li>Item 2</li><li>Item 3</li></ol></ol><ul><li>Item 4</li><li>Item 5</li></ul>",
- "html output doesn't match expected value in test 1");
-
- // *** test 2 ***
- // 1. Item 1 1. Item 1
- // 1. Item 2 1. Item 2
- // 2. {\t}Item 3 1. Item 3
- // * Item 4 * Item 4
- // * Item 5 * Item 5
- sel.removeAllRanges();
- sel.selectAllChildren(editor.getElementsByTagName("li")[2]);
- document.execCommand("indent", false, null);
- ok(editor.innerHTML == "<ol><li>Item 1</li><ol><li>Item 2</li><ol><li>Item 3</li></ol></ol></ol><ul><li>Item 4</li><li>Item 5</li></ul>",
- "html output doesn't match expected value in test 2");
-
- // *** test 3 ***
- // 1. Item 1 1. Item 1
- // 1. Item 2 1. Item 2
- // 1. {\st}Item 3 2. Item 3
- // * Item 4 * Item 4
- // * Item 5 * Item 5
- document.execCommand("outdent", false, null);
- ok(editor.innerHTML == "<ol><li>Item 1</li><ol><li>Item 2</li><li>Item 3</li></ol></ol><ul><li>Item 4</li><li>Item 5</li></ul>",
- "html output doesn't match expected value in test 3");
-
- // *** test 4 ***
- // 1. Item 1 1. Item 1
- // 1. Item 2 1. Item 2
- // 2. {\st}Item 3 2. Item 3
- // * Item 4 * Item 4
- // * Item 5 * Item 5
- document.execCommand("outdent", false, null);
- ok(editor.innerHTML == "<ol><li>Item 1</li><ol><li>Item 2</li></ol><li>Item 3</li></ol><ul><li>Item 4</li><li>Item 5</li></ul>",
- "html output doesn't match expected value in test 4");
-
- // *** test 5 ***
- // 1. Item 1 1. Item 1
- // 1. {\st}Item 2 2. Item 2
- // 2. Item 3 3. Item 3
- // * Item 4 * Item 4
- // * Item 5 * Item 5
- sel.removeAllRanges();
- sel.selectAllChildren(editor.getElementsByTagName("li")[1]);
- document.execCommand("outdent", false, null);
- ok(editor.innerHTML == "<ol><li>Item 1</li><li>Item 2</li><li>Item 3</li></ol><ul><li>Item 4</li><li>Item 5</li></ul>",
- "html output doesn't match expected value in test 5");
-
- // *** test 6 ***
- // 1. Item 1 1. Item 1
- // 2. {\t}Item 2 1. Item 2
- // 3. Item 3 2. Item 3
- // * Item 4 * Item 4
- // * Item 5 * Item 5
- document.execCommand("indent", false, null);
- ok(editor.innerHTML == "<ol><li>Item 1</li><ol><li>Item 2</li></ol><li>Item 3</li></ol><ul><li>Item 4</li><li>Item 5</li></ul>",
- "html output doesn't match expected value in test 6");
-
- // *** test 7 ***
- // 1. Item 1 1. Item 1
- // 1. Item 2 1. Item 2
- // 2. {\t}Item 3 2. Item 3
- // * Item 4 * Item 4
- // * Item 5 * Item 5
- sel.removeAllRanges();
- sel.selectAllChildren(editor.getElementsByTagName("li")[2]);
- document.execCommand("indent", false, null);
- ok(editor.innerHTML == "<ol><li>Item 1</li><ol><li>Item 2</li><li>Item 3</li></ol></ol><ul><li>Item 4</li><li>Item 5</li></ul>",
- "html output doesn't match expected value in test 7");
-
- // That covers the basics of merging lists on indent and outdent.
- // We also want to check that ul / ol lists won't be merged together,
- // since they're different types of lists.
- // *** test 8 ***
- // 1. Item 1 1. Item 1
- // 1. Item 2 1. Item 2
- // 2. Item 3 2. Item 3
- // * {\t}Item 4 * Item 4
- // * Item 5 * Item 5
- sel.removeAllRanges();
- sel.selectAllChildren(editor.getElementsByTagName("li")[3]);
- document.execCommand("indent", false, null);
- ok(editor.innerHTML == "<ol><li>Item 1</li><ol><li>Item 2</li><li>Item 3</li></ol></ol><ul><ul><li>Item 4</li></ul><li>Item 5</li></ul>",
- "html output doesn't match expected value in test 8");
-
- // Better test merging with <ul> rather than <ol> too.
- // *** test 9 ***
- // 1. Item 1 1. Item 1
- // 1. Item 2 1. Item 2
- // 2. Item 3 2. Item 3
- // * Item 4 * Item 4
- // * {\t}Item 5 * Item 5
- sel.removeAllRanges();
- sel.selectAllChildren(editor.getElementsByTagName("li")[4]);
- document.execCommand("indent", false, null);
- ok(editor.innerHTML == "<ol><li>Item 1</li><ol><li>Item 2</li><li>Item 3</li></ol></ol><ul><ul><li>Item 4</li><li>Item 5</li></ul></ul>",
- "html output doesn't match expected value in test 9");
-
- // Same test as test 8, but with outdent rather than indent.
- // *** test 10 ***
- // 1. Item 1 1. Item 1
- // 1. Item 2 1. Item 2
- // 2. Item 3 2. Item 3
- // * {\st}Item 4 * Item 4
- // * Item 5 * Item 5
- sel.removeAllRanges();
- sel.selectAllChildren(editor.getElementsByTagName("li")[3]);
- document.execCommand("outdent", false, null);
- ok(editor.innerHTML == "<ol><li>Item 1</li><ol><li>Item 2</li><li>Item 3</li></ol></ol><ul><li>Item 4</li><ul><li>Item 5</li></ul></ul>",
- "html output doesn't match expected value in test 10");
-
- // Test indenting multiple items at once. Hold down "shift" and select
- // upwards to get all the <ol> items and the first <ul> item.
- // *** test 11 ***
- // 1. Item 1 1. Item 1
- // 1. {\t}Item 2 1. Item 2
- // 2. {\t}Item 3 2. Item 3
- // * {\t}Item 4 * Item 4
- // * Item 5 * Item 5
- sel.removeAllRanges();
- var range = document.createRange();
- range.setStart(editor.getElementsByTagName("li")[1], 0);
- range.setEnd(editor.getElementsByTagName("li")[3], editor.getElementsByTagName("li")[3].childNodes.length);
- sel.addRange(range);
- document.execCommand("indent", false, null);
- ok(editor.innerHTML == "<ol><li>Item 1</li><ol><ol><li>Item 2</li><li>Item 3</li></ol></ol></ol><ul><ul><li>Item 4</li><li>Item 5</li></ul></ul>",
- "html output doesn't match expected value in test 11");
-
- // Test outdenting multiple items at once. Selection is already ready...
- // *** test 12 ***
- // 1. Item 1 1. Item 1
- // 1. {\st}Item 2 1. Item 2
- // 2. {\st}Item 3 2. Item 3
- // * {\st}Item 4 * Item 4
- // * Item 5 * Item 5
- document.execCommand("outdent", false, null);
- ok(editor.innerHTML == "<ol><li>Item 1</li><ol><li>Item 2</li><li>Item 3</li></ol></ol><ul><li>Item 4</li><ul><li>Item 5</li></ul></ul>",
- "html output doesn't match expected value in test 12");
-
- SimpleTest.finish();
-});
-
-
-
-</script>
-</pre>
-</body>
-</html>
-
diff --git a/editor/composer/test/test_bug389350.html b/editor/composer/test/test_bug389350.html
deleted file mode 100644
index bf1d514ad..000000000
--- a/editor/composer/test/test_bug389350.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=389350
--->
-<head>
-<title>Test for Bug 389350</title>
-<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-
-<script type="text/javascript">
-
-function runTest() {
- var e = document.getElementById("edit");
- e.contentDocument.designMode='on';
- e.style.display='block';
- e.focus();
- sendString('abc');
- var expected = "<head></head><body>abc</body>";
- var result = e.contentDocument.documentElement.innerHTML;
- is(result, expected, "iframe with designmode on had incorrect content");
- SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(runTest);
-</script>
-
-</head>
-<body id="body">
-<iframe id="edit" width="200" height="100" style="display: none;" src="">
-</body>
-</html>
diff --git a/editor/composer/test/test_bug434998.xul b/editor/composer/test/test_bug434998.xul
deleted file mode 100644
index 4a384ac1c..000000000
--- a/editor/composer/test/test_bug434998.xul
+++ /dev/null
@@ -1,109 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin"
- type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
- type="text/css"?>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=434998
--->
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- title="Mozilla Bug 434998" onload="runTest();">
- <script type="application/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
- <script type="application/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
-
- <body xmlns="http://www.w3.org/1999/xhtml">
- <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=434998"
- target="_blank">Mozilla Bug 434998</a>
- <p/>
- <editor xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- id="editor"
- type="content-primary"
- editortype="html"
- style="width: 400px; height: 100px; border: thin solid black"/>
- <p/>
- <pre id="test">
- </pre>
- </body>
- <script class="testbody" type="application/javascript">
- <![CDATA[
-
- SimpleTest.waitForExplicitFinish();
-
- function EditorContentListener(aEditor)
- {
- this.init(aEditor);
- }
-
- EditorContentListener.prototype = {
- init : function(aEditor)
- {
- this.mEditor = aEditor;
- },
-
- QueryInterface : function(aIID)
- {
- if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
- aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
- aIID.equals(Components.interfaces.nsISupports))
- return this;
- throw Components.results.NS_NOINTERFACE;
- },
-
- onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus)
- {
- if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP)
- {
- var editor = this.mEditor.getEditor(this.mEditor.contentWindow);
- if (editor) {
- // Should not throw
- var threw = false;
- try {
- this.mEditor.contentDocument.execCommand("bold", false, null);
- } catch (e) {
- threw = true;
- }
- ok(!threw, "The execCommand API should work on <xul:editor>");
- progress.removeProgressListener(progressListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
- SimpleTest.finish();
- }
- }
- },
-
-
- onProgressChange : function(aWebProgress, aRequest,
- aCurSelfProgress, aMaxSelfProgress,
- aCurTotalProgress, aMaxTotalProgress)
- {
- },
-
- onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags)
- {
- },
-
- onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
- {
- },
-
- onSecurityChange : function(aWebProgress, aRequest, aState)
- {
- },
-
- mEditor: null
- };
-
- var progress, progressListener;
-
- function runTest() {
- var newEditorElement = document.getElementById("editor");
- newEditorElement.makeEditable("html", true);
- var docShell = newEditorElement.boxObject.docShell;
- progress = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebProgress);
- progressListener = new EditorContentListener(newEditorElement);
- progress.addProgressListener(progressListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
- newEditorElement.setAttribute("src", "data:text/html,");
- }
-]]>
-</script>
-</window>
diff --git a/editor/composer/test/test_bug519928.html b/editor/composer/test/test_bug519928.html
deleted file mode 100644
index 3b1a9ba17..000000000
--- a/editor/composer/test/test_bug519928.html
+++ /dev/null
@@ -1,123 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=519928
--->
-<head>
- <title>Test for Bug 519928</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=519928">Mozilla Bug 519928</a>
-<p id="display"></p>
-<div id="content">
-<iframe id="load-frame"></iframe>
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-var iframe = document.getElementById("load-frame");
-
-function enableJS() { allowJS(true, iframe); }
-function disableJS() { allowJS(false, iframe); }
-function allowJS(allow, frame) {
- SpecialPowers.wrap(frame.contentWindow)
- .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
- .getInterface(SpecialPowers.Ci.nsIWebNavigation)
- .QueryInterface(SpecialPowers.Ci.nsIDocShell)
- .allowJavascript = allow;
-}
-
-function expectJSAllowed(allowed, testCondition, callback) {
- window.ICanRunMyJS = false;
- var self_ = window;
- testCondition();
-
- var doc = iframe.contentDocument;
- doc.body.innerHTML = "<iframe></iframe>";
- var innerFrame = doc.querySelector("iframe");
- innerFrame.addEventListener("load", function() {
- innerFrame.removeEventListener("load", arguments.callee, false);
-
- var msg = "The inner iframe should" + (allowed ? "" : " not") + " be able to run Javascript";
- is(self_.ICanRunMyJS, allowed, msg);
- callback();
- }, false);
- var iframeSrc = "data:text/html,<script>parent.parent.ICanRunMyJS = true;</scr" + "ipt>";
- innerFrame.src = iframeSrc;
-}
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(function() {
- var enterDesignMode = function() { document.designMode = "on"; };
- var leaveDesignMode = function() { document.designMode = "off"; };
- expectJSAllowed(false, disableJS, function() {
- expectJSAllowed(true, enableJS, function() {
- expectJSAllowed(true, enterDesignMode, function() {
- expectJSAllowed(true, leaveDesignMode, function() {
- expectJSAllowed(false, disableJS, function() {
- expectJSAllowed(false, enterDesignMode, function() {
- expectJSAllowed(false, leaveDesignMode, function() {
- expectJSAllowed(true, enableJS, function() {
- enterDesignMode = function() { iframe.contentDocument.designMode = "on"; };
- leaveDesignMode = function() { iframe.contentDocument.designMode = "off"; };
- expectJSAllowed(false, disableJS, function() {
- expectJSAllowed(true, enableJS, function() {
- expectJSAllowed(true, enterDesignMode, function() {
- expectJSAllowed(true, leaveDesignMode, function() {
- expectJSAllowed(false, disableJS, function() {
- expectJSAllowed(false, enterDesignMode, function() {
- expectJSAllowed(false, leaveDesignMode, function() {
- expectJSAllowed(true, enableJS, function() {
- testDocumentDisabledJS();
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
-});
-
-function testDocumentDisabledJS() {
- window.ICanRunMyJS = false;
- var self_ = window;
- // Ensure design modes are disabled
- document.designMode = "off";
- iframe.contentDocument.designMode = "off";
-
- // Javascript enabled on the main iframe
- enableJS();
-
- var doc = iframe.contentDocument;
- doc.body.innerHTML = "<iframe></iframe>";
- var innerFrame = doc.querySelector("iframe");
-
- // Javascript disabled on the innerFrame.
- allowJS(false, innerFrame);
-
- innerFrame.addEventListener("load", function() {
- innerFrame.removeEventListener("load", arguments.callee, false);
-
- var msg = "The inner iframe should not be able to run Javascript";
- is(self_.ICanRunMyJS, false, msg);
- SimpleTest.finish();
- }, false);
- var iframeSrc = "data:text/html,<script>parent.parent.ICanRunMyJS = true;</scr" + "ipt>";
- innerFrame.src = iframeSrc;
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/composer/test/test_bug678842.html b/editor/composer/test/test_bug678842.html
deleted file mode 100644
index 226b25ee2..000000000
--- a/editor/composer/test/test_bug678842.html
+++ /dev/null
@@ -1,105 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=678842
--->
-<head>
- <title>Test for Bug 678842</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=678842">Mozilla Bug 678842</a>
-<p id="display"></p>
-<iframe id="content"></iframe>
-
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-/** Test for Bug 678842 **/
-SimpleTest.waitForExplicitFinish();
-var content = document.getElementById('content');
-// load a subframe containing an editor with a defined unknown lang. At first
-// load, it will set dictionary to en-US. At second load, it will return current
-// dictionary. So, we can check, dictionary is correctly remembered between
-// loads.
-
-var firstLoad = true;
-var script;
-
-var loadListener = function(evt) {
- if (firstLoad) {
- script = SpecialPowers.loadChromeScript(function() {
- var dir = Components.classes["@mozilla.org/file/directory_service;1"]
- .getService(Components.interfaces.nsIProperties)
- .get("CurWorkD", Components.interfaces.nsIFile);
- dir.append("tests");
- dir.append("editor");
- dir.append("composer");
- dir.append("test");
-
- var hunspell = Components.classes["@mozilla.org/spellchecker/engine;1"]
- .getService(Components.interfaces.mozISpellCheckingEngine);
-
- // Install en-GB dictionary.
- en_GB = dir.clone();
- en_GB.append("en-GB");
- hunspell.addDirectory(en_GB);
-
- addMessageListener("en_GB-exists", () => en_GB.exists());
- addMessageListener("destroy", () => hunspell.removeDirectory(en_GB));
- });
- is(script.sendSyncMessage("en_GB-exists")[0][0], true,
- "true expected (en-GB directory should exist)");
- }
-
- var doc = evt.target.contentDocument;
- var elem = doc.getElementById('textarea');
- var editor = SpecialPowers.wrap(elem).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
- editor.setSpellcheckUserOverride(true);
- var inlineSpellChecker = editor.getInlineSpellChecker(true);
-
- SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm")
- .onSpellCheck(elem, function () {
- var spellchecker = inlineSpellChecker.spellChecker;
- try {
- var currentDictonary = spellchecker.GetCurrentDictionary();
- } catch(e) {}
-
- if (!currentDictonary) {
- spellchecker.SetCurrentDictionary('en-US');
- }
-
- if (firstLoad) {
- firstLoad = false;
-
- // First time around, the dictionary defaults to the locale.
- is (currentDictonary, "en-US", "unexpected lang " + currentDictonary + " instead of en-US");
-
- // Select en-GB.
- spellchecker.SetCurrentDictionary("en-GB");
-
- content.src = 'http://mochi.test:8888/tests/editor/composer/test/bug678842_subframe.html?firstload=false';
- } else {
- is (currentDictonary, "en-GB", "unexpected lang " + currentDictonary + " instead of en-GB");
- content.removeEventListener('load', loadListener, false);
-
- // Remove the fake en-GB dictionary again, since it's otherwise picked up by later tests.
- script.sendSyncMessage("destroy");
-
- // This will clear the content preferences and reset "spellchecker.dictionary".
- spellchecker.SetCurrentDictionary("");
- SimpleTest.finish();
- }
- });
-}
-
-content.addEventListener('load', loadListener, false);
-
-content.src = 'http://mochi.test:8888/tests/editor/composer/test/bug678842_subframe.html?firstload=true';
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/composer/test/test_bug697981.html b/editor/composer/test/test_bug697981.html
deleted file mode 100644
index f9417acb0..000000000
--- a/editor/composer/test/test_bug697981.html
+++ /dev/null
@@ -1,133 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=697981
--->
-<head>
- <title>Test for Bug 697981</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=697981">Mozilla Bug 697981</a>
-<p id="display"></p>
-</div>
-
-<textarea id="de-DE" lang="de-DE" onfocus="deFocus()">German heute ist ein guter Tag</textarea>
-<textarea id="en-US" lang="en-US" onfocus="enFocus()">Nogoodword today is a nice day</textarea>
-
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-function getMisspelledWords(editor) {
- return editor.selectionController.getSelection(SpecialPowers.Ci.nsISelectionController.SELECTION_SPELLCHECK).toString();
-}
-
-var elem_de;
-var editor_de;
-var script;
-
-var onSpellCheck =
- SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm")
- .onSpellCheck;
-
-/** Test for Bug 697981 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- script = SpecialPowers.loadChromeScript(function() {
- var dir = Components.classes["@mozilla.org/file/directory_service;1"]
- .getService(Components.interfaces.nsIProperties)
- .get("CurWorkD", Components.interfaces.nsIFile);
- dir.append("tests");
- dir.append("editor");
- dir.append("composer");
- dir.append("test");
-
- var hunspell = Components.classes["@mozilla.org/spellchecker/engine;1"]
- .getService(Components.interfaces.mozISpellCheckingEngine);
-
- // Install de-DE dictionary.
- var de_DE = dir.clone();
- de_DE.append("de-DE");
- hunspell.addDirectory(de_DE);
-
- addMessageListener("de_DE-exists", () => de_DE.exists());
- addMessageListener("destroy", () => hunspell.removeDirectory(de_DE));
- });
- is(script.sendSyncMessage("de_DE-exists")[0][0], true,
- "true expected (de_DE directory should exist)");
-
- document.getElementById('de-DE').focus();
-});
-
-function deFocus() {
- elem_de = document.getElementById('de-DE');
- editor_de = SpecialPowers.wrap(elem_de).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
- editor_de.setSpellcheckUserOverride(true);
- var inlineSpellChecker = editor_de.getInlineSpellChecker(true);
-
- onSpellCheck(elem_de, function () {
- var spellchecker = inlineSpellChecker.spellChecker;
- try {
- var currentDictonary = spellchecker.GetCurrentDictionary();
- } catch(e) {}
-
- // Check that the German dictionary is loaded and that the spell check has worked.
- is(currentDictonary, "de-DE", "expected de-DE");
- is(getMisspelledWords(editor_de), "German", "one misspelled word expected: German");
-
- // Now focus the other textarea, which requires English spelling.
- document.getElementById('en-US').focus();
- });
-}
-
-function enFocus() {
- var elem_en = document.getElementById('en-US');
- var editor_en = SpecialPowers.wrap(elem_en).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
- editor_en.setSpellcheckUserOverride(true);
- var inlineSpellChecker = editor_en.getInlineSpellChecker(true);
-
- onSpellCheck(elem_en, function () {
- var spellchecker = inlineSpellChecker.spellChecker;
- try {
- currentDictonary = spellchecker.GetCurrentDictionary();
- } catch(e) {}
-
- // Check that the English dictionary is loaded and that the spell check has worked.
- is(currentDictonary, "en-US", "expected en-US");
- is(getMisspelledWords(editor_en), "Nogoodword", "one misspelled word expected: Nogoodword");
-
- // So far all was boring. The important thing is whether the spell check result
- // in the de-DE editor is still the same. After losing focus, no spell check
- // updates should take place there.
- is(getMisspelledWords(editor_de), "German", "one misspelled word expected: German");
-
- // Remove the fake de_DE dictionary again.
- script.sendSyncMessage("destroy");
-
- // Focus again, so the spelling gets updated, but before we need to kill the focus handler.
- elem_de.onfocus = null;
- elem_de.blur();
- elem_de.focus();
-
- // After removal, the de_DE editor should refresh the spelling with en-US.
- onSpellCheck(elem_de, function () {
- spellchecker = inlineSpellChecker.spellChecker;
- try {
- currentDictonary = spellchecker.GetCurrentDictionary();
- } catch(e) {}
-
- // Check that the default English dictionary is loaded and that the spell check has worked.
- is(currentDictonary, "en-US", "expected en-US");
- is(getMisspelledWords(editor_de), "heute" + "ist" + "ein" + "guter",
- "some misspelled words expected: heute ist ein guter");
-
- SimpleTest.finish();
- });
- });
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/composer/test/test_bug717433.html b/editor/composer/test/test_bug717433.html
deleted file mode 100644
index 59ad9b247..000000000
--- a/editor/composer/test/test_bug717433.html
+++ /dev/null
@@ -1,107 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=717433
--->
-<head>
- <title>Test for Bug 717433</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717433">Mozilla Bug 717433</a>
-<p id="display"></p>
-<iframe id="content"></iframe>
-
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-/** Test for Bug 717433 **/
-SimpleTest.waitForExplicitFinish();
-var content = document.getElementById('content');
-// Load a subframe containing an editor with language "en". At first
-// load, it will set the dictionary to en-GB or en-US. We set the other one.
-// At second load, it will return the current dictionary. We can check that the
-// dictionary is correctly remembered between loads.
-
-var firstLoad = true;
-var expected = "";
-var script;
-
-var loadListener = function(evt) {
-
- if (firstLoad) {
- script = SpecialPowers.loadChromeScript(function() {
- var dir = Components.classes["@mozilla.org/file/directory_service;1"]
- .getService(Components.interfaces.nsIProperties)
- .get("CurWorkD", Components.interfaces.nsIFile);
- dir.append("tests");
- dir.append("editor");
- dir.append("composer");
- dir.append("test");
-
- var hunspell = Components.classes["@mozilla.org/spellchecker/engine;1"]
- .getService(Components.interfaces.mozISpellCheckingEngine);
-
- // Install en-GB dictionary.
- var en_GB = dir.clone();
- en_GB.append("en-GB");
- hunspell.addDirectory(en_GB);
-
- addMessageListener("en_GB-exists", () => en_GB.exists());
- addMessageListener("destroy", () => hunspell.removeDirectory(en_GB));
- });
- is(script.sendSyncMessage("en_GB-exists")[0][0], true,
- "true expected (en-GB directory should exist)");
- }
-
- var doc = evt.target.contentDocument;
- var elem = doc.getElementById('textarea');
- var editor = SpecialPowers.wrap(elem).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement).editor;
- editor.setSpellcheckUserOverride(true);
- var inlineSpellChecker = editor.getInlineSpellChecker(true);
-
- SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm")
- .onSpellCheck(elem, function () {
- var spellchecker = inlineSpellChecker.spellChecker;
- try {
- var currentDictonary = spellchecker.GetCurrentDictionary();
- } catch(e) {}
-
- if (firstLoad) {
- firstLoad = false;
-
- // First time around, we get a random dictionary based on the language "en".
- if (currentDictonary == "en-GB") {
- spellchecker.SetCurrentDictionary("en-US");
- expected = "en-US";
- } else if (currentDictonary == "en-US") {
- spellchecker.SetCurrentDictionary("en-GB");
- expected = "en-GB";
- } else {
- is(true, false, "Neither en-US nor en-GB are current");
- }
- content.src = 'http://mochi.test:8888/tests/editor/composer/test/bug717433_subframe.html?firstload=false';
- } else {
- is(currentDictonary, expected, expected + " expected");
- content.removeEventListener('load', loadListener, false);
-
- // Remove the fake en-GB dictionary again, since it's otherwise picked up by later tests.
- script.sendSyncMessage("destroy");
-
- // This will clear the content preferences and reset "spellchecker.dictionary".
- spellchecker.SetCurrentDictionary("");
- SimpleTest.finish();
- }
- });
-}
-
-content.addEventListener('load', loadListener, false);
-
-content.src = 'http://mochi.test:8888/tests/editor/composer/test/bug717433_subframe.html?firstload=true';
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/composer/test/test_bug738440.html b/editor/composer/test/test_bug738440.html
deleted file mode 100644
index a021906cf..000000000
--- a/editor/composer/test/test_bug738440.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!doctype html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=738440
--->
-<title>Test for Bug 738440</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css" />
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=738440">Mozilla Bug 738440</a>
-<div contenteditable></div>
-<script>
-
-/** Test for Bug 738440 **/
-document.execCommand("stylewithcss", false, "true");
-is(document.queryCommandState("stylewithcss"), true,
- "setting stylewithcss to true should cause its state to be true");
-is(document.queryCommandState("usecss"), false,
- "usecss state should always be false");
-
-document.execCommand("stylewithcss", false, "false");
-is(document.queryCommandState("stylewithcss"), false,
- "setting stylewithcss to false should cause its state to be false");
-is(document.queryCommandState("usecss"), false,
- "usecss state should always be false");
-
-document.execCommand("usecss", false, "true");
-is(document.queryCommandState("stylewithcss"), false,
- "setting usecss to true should cause stylewithcss state to be false");
-is(document.queryCommandState("usecss"), false,
- "usecss state should always be false");
-
-document.execCommand("usecss", false, "false");
-is(document.queryCommandState("stylewithcss"), true,
- "setting usecss to false should cause stylewithcss state to be true");
-is(document.queryCommandState("usecss"), false,
- "usecss state should always be false");
-
-</script>
diff --git a/editor/libeditor/CSSEditUtils.cpp b/editor/libeditor/CSSEditUtils.cpp
deleted file mode 100644
index e15bc278f..000000000
--- a/editor/libeditor/CSSEditUtils.cpp
+++ /dev/null
@@ -1,1441 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/CSSEditUtils.h"
-
-#include "mozilla/Assertions.h"
-#include "mozilla/ChangeStyleTransaction.h"
-#include "mozilla/HTMLEditor.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/DeclarationBlockInlines.h"
-#include "mozilla/css/StyleRule.h"
-#include "mozilla/dom/Element.h"
-#include "mozilla/mozalloc.h"
-#include "nsAString.h"
-#include "nsCOMPtr.h"
-#include "nsColor.h"
-#include "nsComputedDOMStyle.h"
-#ifdef DEBUG
-#include "nsDocument.h"
-#endif
-#include "nsDebug.h"
-#include "nsDependentSubstring.h"
-#include "nsError.h"
-#include "nsGkAtoms.h"
-#include "nsIAtom.h"
-#include "nsIContent.h"
-#include "nsIDOMCSSStyleDeclaration.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMNode.h"
-#include "nsIDOMWindow.h"
-#include "nsIDocument.h"
-#include "nsIEditor.h"
-#include "nsINode.h"
-#include "nsISupportsImpl.h"
-#include "nsISupportsUtils.h"
-#include "nsLiteralString.h"
-#include "nsPIDOMWindow.h"
-#include "nsReadableUtils.h"
-#include "nsString.h"
-#include "nsStringFwd.h"
-#include "nsStringIterator.h"
-#include "nsStyledElement.h"
-#include "nsSubstringTuple.h"
-#include "nsUnicharUtils.h"
-
-namespace mozilla {
-
-using namespace dom;
-
-static
-void ProcessBValue(const nsAString* aInputString,
- nsAString& aOutputString,
- const char* aDefaultValueString,
- const char* aPrependString,
- const char* aAppendString)
-{
- if (aInputString && aInputString->EqualsLiteral("-moz-editor-invert-value")) {
- aOutputString.AssignLiteral("normal");
- }
- else {
- aOutputString.AssignLiteral("bold");
- }
-}
-
-static
-void ProcessDefaultValue(const nsAString* aInputString,
- nsAString& aOutputString,
- const char* aDefaultValueString,
- const char* aPrependString,
- const char* aAppendString)
-{
- CopyASCIItoUTF16(aDefaultValueString, aOutputString);
-}
-
-static
-void ProcessSameValue(const nsAString* aInputString,
- nsAString & aOutputString,
- const char* aDefaultValueString,
- const char* aPrependString,
- const char* aAppendString)
-{
- if (aInputString) {
- aOutputString.Assign(*aInputString);
- }
- else
- aOutputString.Truncate();
-}
-
-static
-void ProcessExtendedValue(const nsAString* aInputString,
- nsAString& aOutputString,
- const char* aDefaultValueString,
- const char* aPrependString,
- const char* aAppendString)
-{
- aOutputString.Truncate();
- if (aInputString) {
- if (aPrependString) {
- AppendASCIItoUTF16(aPrependString, aOutputString);
- }
- aOutputString.Append(*aInputString);
- if (aAppendString) {
- AppendASCIItoUTF16(aAppendString, aOutputString);
- }
- }
-}
-
-static
-void ProcessLengthValue(const nsAString* aInputString,
- nsAString& aOutputString,
- const char* aDefaultValueString,
- const char* aPrependString,
- const char* aAppendString)
-{
- aOutputString.Truncate();
- if (aInputString) {
- aOutputString.Append(*aInputString);
- if (-1 == aOutputString.FindChar(char16_t('%'))) {
- aOutputString.AppendLiteral("px");
- }
- }
-}
-
-static
-void ProcessListStyleTypeValue(const nsAString* aInputString,
- nsAString& aOutputString,
- const char* aDefaultValueString,
- const char* aPrependString,
- const char* aAppendString)
-{
- aOutputString.Truncate();
- if (aInputString) {
- if (aInputString->EqualsLiteral("1")) {
- aOutputString.AppendLiteral("decimal");
- }
- else if (aInputString->EqualsLiteral("a")) {
- aOutputString.AppendLiteral("lower-alpha");
- }
- else if (aInputString->EqualsLiteral("A")) {
- aOutputString.AppendLiteral("upper-alpha");
- }
- else if (aInputString->EqualsLiteral("i")) {
- aOutputString.AppendLiteral("lower-roman");
- }
- else if (aInputString->EqualsLiteral("I")) {
- aOutputString.AppendLiteral("upper-roman");
- }
- else if (aInputString->EqualsLiteral("square")
- || aInputString->EqualsLiteral("circle")
- || aInputString->EqualsLiteral("disc")) {
- aOutputString.Append(*aInputString);
- }
- }
-}
-
-static
-void ProcessMarginLeftValue(const nsAString* aInputString,
- nsAString& aOutputString,
- const char* aDefaultValueString,
- const char* aPrependString,
- const char* aAppendString)
-{
- aOutputString.Truncate();
- if (aInputString) {
- if (aInputString->EqualsLiteral("center") ||
- aInputString->EqualsLiteral("-moz-center")) {
- aOutputString.AppendLiteral("auto");
- }
- else if (aInputString->EqualsLiteral("right") ||
- aInputString->EqualsLiteral("-moz-right")) {
- aOutputString.AppendLiteral("auto");
- }
- else {
- aOutputString.AppendLiteral("0px");
- }
- }
-}
-
-static
-void ProcessMarginRightValue(const nsAString* aInputString,
- nsAString& aOutputString,
- const char* aDefaultValueString,
- const char* aPrependString,
- const char* aAppendString)
-{
- aOutputString.Truncate();
- if (aInputString) {
- if (aInputString->EqualsLiteral("center") ||
- aInputString->EqualsLiteral("-moz-center")) {
- aOutputString.AppendLiteral("auto");
- }
- else if (aInputString->EqualsLiteral("left") ||
- aInputString->EqualsLiteral("-moz-left")) {
- aOutputString.AppendLiteral("auto");
- }
- else {
- aOutputString.AppendLiteral("0px");
- }
- }
-}
-
-const CSSEditUtils::CSSEquivTable boldEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_font_weight, ProcessBValue, nullptr, nullptr, nullptr, true, false },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-const CSSEditUtils::CSSEquivTable italicEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_font_style, ProcessDefaultValue, "italic", nullptr, nullptr, true, false },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-const CSSEditUtils::CSSEquivTable underlineEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_text_decoration, ProcessDefaultValue, "underline", nullptr, nullptr, true, false },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-const CSSEditUtils::CSSEquivTable strikeEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_text_decoration, ProcessDefaultValue, "line-through", nullptr, nullptr, true, false },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-const CSSEditUtils::CSSEquivTable ttEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_font_family, ProcessDefaultValue, "monospace", nullptr, nullptr, true, false },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-const CSSEditUtils::CSSEquivTable fontColorEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_color, ProcessSameValue, nullptr, nullptr, nullptr, true, false },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-const CSSEditUtils::CSSEquivTable fontFaceEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_font_family, ProcessSameValue, nullptr, nullptr, nullptr, true, false },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-const CSSEditUtils::CSSEquivTable bgcolorEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_background_color, ProcessSameValue, nullptr, nullptr, nullptr, true, false },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-const CSSEditUtils::CSSEquivTable backgroundImageEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_background_image, ProcessExtendedValue, nullptr, "url(", ")", true, true },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-const CSSEditUtils::CSSEquivTable textColorEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_color, ProcessSameValue, nullptr, nullptr, nullptr, true, false },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-const CSSEditUtils::CSSEquivTable borderEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_border, ProcessExtendedValue, nullptr, nullptr, "px solid", true, false },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-const CSSEditUtils::CSSEquivTable textAlignEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_text_align, ProcessSameValue, nullptr, nullptr, nullptr, true, false },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-const CSSEditUtils::CSSEquivTable captionAlignEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_caption_side, ProcessSameValue, nullptr, nullptr, nullptr, true, false },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-const CSSEditUtils::CSSEquivTable verticalAlignEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_vertical_align, ProcessSameValue, nullptr, nullptr, nullptr, true, false },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-const CSSEditUtils::CSSEquivTable nowrapEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_whitespace, ProcessDefaultValue, "nowrap", nullptr, nullptr, true, false },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-const CSSEditUtils::CSSEquivTable widthEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_width, ProcessLengthValue, nullptr, nullptr, nullptr, true, false },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-const CSSEditUtils::CSSEquivTable heightEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_height, ProcessLengthValue, nullptr, nullptr, nullptr, true, false },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-const CSSEditUtils::CSSEquivTable listStyleTypeEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_list_style_type, ProcessListStyleTypeValue, nullptr, nullptr, nullptr, true, true },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-const CSSEditUtils::CSSEquivTable tableAlignEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_text_align, ProcessDefaultValue, "left", nullptr, nullptr, false, false },
- { CSSEditUtils::eCSSEditableProperty_margin_left, ProcessMarginLeftValue, nullptr, nullptr, nullptr, true, false },
- { CSSEditUtils::eCSSEditableProperty_margin_right, ProcessMarginRightValue, nullptr, nullptr, nullptr, true, false },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-const CSSEditUtils::CSSEquivTable hrAlignEquivTable[] = {
- { CSSEditUtils::eCSSEditableProperty_margin_left, ProcessMarginLeftValue, nullptr, nullptr, nullptr, true, false },
- { CSSEditUtils::eCSSEditableProperty_margin_right, ProcessMarginRightValue, nullptr, nullptr, nullptr, true, false },
- { CSSEditUtils::eCSSEditableProperty_NONE, 0 }
-};
-
-CSSEditUtils::CSSEditUtils(HTMLEditor* aHTMLEditor)
- : mHTMLEditor(aHTMLEditor)
- , mIsCSSPrefChecked(true)
-{
- // let's retrieve the value of the "CSS editing" pref
- mIsCSSPrefChecked = Preferences::GetBool("editor.use_css", mIsCSSPrefChecked);
-}
-
-CSSEditUtils::~CSSEditUtils()
-{
-}
-
-// Answers true if we have some CSS equivalence for the HTML style defined
-// by aProperty and/or aAttribute for the node aNode
-bool
-CSSEditUtils::IsCSSEditableProperty(nsINode* aNode,
- nsIAtom* aProperty,
- const nsAString* aAttribute)
-{
- nsCOMPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
- return IsCSSEditableProperty(aNode, aProperty, attribute);
-}
-
-bool
-CSSEditUtils::IsCSSEditableProperty(nsINode* aNode,
- nsIAtom* aProperty,
- nsIAtom* aAttribute)
-{
- MOZ_ASSERT(aNode);
-
- nsINode* node = aNode;
- // we need an element node here
- if (node->NodeType() == nsIDOMNode::TEXT_NODE) {
- node = node->GetParentNode();
- NS_ENSURE_TRUE(node, false);
- }
-
- // html inline styles B I TT U STRIKE and COLOR/FACE on FONT
- if (nsGkAtoms::b == aProperty ||
- nsGkAtoms::i == aProperty ||
- nsGkAtoms::tt == aProperty ||
- nsGkAtoms::u == aProperty ||
- nsGkAtoms::strike == aProperty ||
- (nsGkAtoms::font == aProperty && aAttribute &&
- (aAttribute == nsGkAtoms::color || aAttribute == nsGkAtoms::face))) {
- return true;
- }
-
- // ALIGN attribute on elements supporting it
- if (aAttribute == nsGkAtoms::align &&
- node->IsAnyOfHTMLElements(nsGkAtoms::div,
- nsGkAtoms::p,
- nsGkAtoms::h1,
- nsGkAtoms::h2,
- nsGkAtoms::h3,
- nsGkAtoms::h4,
- nsGkAtoms::h5,
- nsGkAtoms::h6,
- nsGkAtoms::td,
- nsGkAtoms::th,
- nsGkAtoms::table,
- nsGkAtoms::hr,
- // For the above, why not use
- // HTMLEditUtils::SupportsAlignAttr?
- // It also checks for tbody, tfoot, thead.
- // Let's add the following elements here even
- // if "align" has a different meaning for them
- nsGkAtoms::legend,
- nsGkAtoms::caption)) {
- return true;
- }
-
- if (aAttribute == nsGkAtoms::valign &&
- node->IsAnyOfHTMLElements(nsGkAtoms::col,
- nsGkAtoms::colgroup,
- nsGkAtoms::tbody,
- nsGkAtoms::td,
- nsGkAtoms::th,
- nsGkAtoms::tfoot,
- nsGkAtoms::thead,
- nsGkAtoms::tr)) {
- return true;
- }
-
- // attributes TEXT, BACKGROUND and BGCOLOR on BODY
- if (node->IsHTMLElement(nsGkAtoms::body) &&
- (aAttribute == nsGkAtoms::text || aAttribute == nsGkAtoms::background ||
- aAttribute == nsGkAtoms::bgcolor)) {
- return true;
- }
-
- // attribute BGCOLOR on other elements
- if (aAttribute == nsGkAtoms::bgcolor) {
- return true;
- }
-
- // attributes HEIGHT, WIDTH and NOWRAP on TD and TH
- if (node->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th) &&
- (aAttribute == nsGkAtoms::height || aAttribute == nsGkAtoms::width ||
- aAttribute == nsGkAtoms::nowrap)) {
- return true;
- }
-
- // attributes HEIGHT and WIDTH on TABLE
- if (node->IsHTMLElement(nsGkAtoms::table) &&
- (aAttribute == nsGkAtoms::height || aAttribute == nsGkAtoms::width)) {
- return true;
- }
-
- // attributes SIZE and WIDTH on HR
- if (node->IsHTMLElement(nsGkAtoms::hr) &&
- (aAttribute == nsGkAtoms::size || aAttribute == nsGkAtoms::width)) {
- return true;
- }
-
- // attribute TYPE on OL UL LI
- if (node->IsAnyOfHTMLElements(nsGkAtoms::ol, nsGkAtoms::ul,
- nsGkAtoms::li) &&
- aAttribute == nsGkAtoms::type) {
- return true;
- }
-
- if (node->IsHTMLElement(nsGkAtoms::img) &&
- (aAttribute == nsGkAtoms::border || aAttribute == nsGkAtoms::width ||
- aAttribute == nsGkAtoms::height)) {
- return true;
- }
-
- // other elements that we can align using CSS even if they
- // can't carry the html ALIGN attribute
- if (aAttribute == nsGkAtoms::align &&
- node->IsAnyOfHTMLElements(nsGkAtoms::ul,
- nsGkAtoms::ol,
- nsGkAtoms::dl,
- nsGkAtoms::li,
- nsGkAtoms::dd,
- nsGkAtoms::dt,
- nsGkAtoms::address,
- nsGkAtoms::pre)) {
- return true;
- }
-
- return false;
-}
-
-// The lowest level above the transaction; adds the CSS declaration
-// "aProperty : aValue" to the inline styles carried by aElement
-nsresult
-CSSEditUtils::SetCSSProperty(Element& aElement,
- nsIAtom& aProperty,
- const nsAString& aValue,
- bool aSuppressTxn)
-{
- RefPtr<ChangeStyleTransaction> transaction =
- CreateCSSPropertyTxn(aElement, aProperty, aValue,
- ChangeStyleTransaction::eSet);
- if (aSuppressTxn) {
- return transaction->DoTransaction();
- }
- return mHTMLEditor->DoTransaction(transaction);
-}
-
-nsresult
-CSSEditUtils::SetCSSPropertyPixels(Element& aElement,
- nsIAtom& aProperty,
- int32_t aIntValue)
-{
- nsAutoString s;
- s.AppendInt(aIntValue);
- return SetCSSProperty(aElement, aProperty, s + NS_LITERAL_STRING("px"),
- /* suppress txn */ false);
-}
-
-// The lowest level above the transaction; removes the value aValue from the
-// list of values specified for the CSS property aProperty, or totally remove
-// the declaration if this property accepts only one value
-nsresult
-CSSEditUtils::RemoveCSSProperty(Element& aElement,
- nsIAtom& aProperty,
- const nsAString& aValue,
- bool aSuppressTxn)
-{
- RefPtr<ChangeStyleTransaction> transaction =
- CreateCSSPropertyTxn(aElement, aProperty, aValue,
- ChangeStyleTransaction::eRemove);
- if (aSuppressTxn) {
- return transaction->DoTransaction();
- }
- return mHTMLEditor->DoTransaction(transaction);
-}
-
-already_AddRefed<ChangeStyleTransaction>
-CSSEditUtils::CreateCSSPropertyTxn(
- Element& aElement,
- nsIAtom& aAttribute,
- const nsAString& aValue,
- ChangeStyleTransaction::EChangeType aChangeType)
-{
- RefPtr<ChangeStyleTransaction> transaction =
- new ChangeStyleTransaction(aElement, aAttribute, aValue, aChangeType);
- return transaction.forget();
-}
-
-nsresult
-CSSEditUtils::GetSpecifiedProperty(nsINode& aNode,
- nsIAtom& aProperty,
- nsAString& aValue)
-{
- return GetCSSInlinePropertyBase(&aNode, &aProperty, aValue, eSpecified);
-}
-
-nsresult
-CSSEditUtils::GetComputedProperty(nsINode& aNode,
- nsIAtom& aProperty,
- nsAString& aValue)
-{
- return GetCSSInlinePropertyBase(&aNode, &aProperty, aValue, eComputed);
-}
-
-nsresult
-CSSEditUtils::GetCSSInlinePropertyBase(nsINode* aNode,
- nsIAtom* aProperty,
- nsAString& aValue,
- StyleType aStyleType)
-{
- MOZ_ASSERT(aNode && aProperty);
- aValue.Truncate();
-
- nsCOMPtr<Element> element = GetElementContainerOrSelf(aNode);
- NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
-
- if (aStyleType == eComputed) {
- // Get the all the computed css styles attached to the element node
- RefPtr<nsComputedDOMStyle> cssDecl = GetComputedStyle(element);
- NS_ENSURE_STATE(cssDecl);
-
- // from these declarations, get the one we want and that one only
- MOZ_ALWAYS_SUCCEEDS(
- cssDecl->GetPropertyValue(nsDependentAtomString(aProperty), aValue));
-
- return NS_OK;
- }
-
- MOZ_ASSERT(aStyleType == eSpecified);
- RefPtr<DeclarationBlock> decl = element->GetInlineStyleDeclaration();
- if (!decl) {
- return NS_OK;
- }
- if (decl->IsServo()) {
- MOZ_CRASH("stylo: not implemented");
- return NS_ERROR_NOT_IMPLEMENTED;
- }
- nsCSSPropertyID prop =
- nsCSSProps::LookupProperty(nsDependentAtomString(aProperty),
- CSSEnabledState::eForAllContent);
- MOZ_ASSERT(prop != eCSSProperty_UNKNOWN);
- decl->AsGecko()->GetPropertyValueByID(prop, aValue);
-
- return NS_OK;
-}
-
-already_AddRefed<nsComputedDOMStyle>
-CSSEditUtils::GetComputedStyle(Element* aElement)
-{
- MOZ_ASSERT(aElement);
-
- nsIDocument* doc = aElement->GetUncomposedDoc();
- NS_ENSURE_TRUE(doc, nullptr);
-
- RefPtr<nsComputedDOMStyle> style =
- NS_NewComputedDOMStyle(aElement, EmptyString(), doc);
-
- return style.forget();
-}
-
-// remove the CSS style "aProperty : aPropertyValue" and possibly remove the whole node
-// if it is a span and if its only attribute is _moz_dirty
-nsresult
-CSSEditUtils::RemoveCSSInlineStyle(nsIDOMNode* aNode,
- nsIAtom* aProperty,
- const nsAString& aPropertyValue)
-{
- nsCOMPtr<Element> element = do_QueryInterface(aNode);
- NS_ENSURE_STATE(element);
-
- // remove the property from the style attribute
- nsresult rv = RemoveCSSProperty(*element, *aProperty, aPropertyValue);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!element->IsHTMLElement(nsGkAtoms::span) ||
- HTMLEditor::HasAttributes(element)) {
- return NS_OK;
- }
-
- return mHTMLEditor->RemoveContainer(element);
-}
-
-// Answers true if the property can be removed by setting a "none" CSS value
-// on a node
-bool
-CSSEditUtils::IsCSSInvertible(nsIAtom& aProperty,
- const nsAString* aAttribute)
-{
- return nsGkAtoms::b == &aProperty;
-}
-
-// Get the default browser background color if we need it for GetCSSBackgroundColorState
-void
-CSSEditUtils::GetDefaultBackgroundColor(nsAString& aColor)
-{
- if (Preferences::GetBool("editor.use_custom_colors", false)) {
- nsresult rv = Preferences::GetString("editor.background_color", &aColor);
- // XXX Why don't you validate the pref value?
- if (NS_FAILED(rv)) {
- NS_WARNING("failed to get editor.background_color");
- aColor.AssignLiteral("#ffffff"); // Default to white
- }
- return;
- }
-
- if (Preferences::GetBool("browser.display.use_system_colors", false)) {
- return;
- }
-
- nsresult rv =
- Preferences::GetString("browser.display.background_color", &aColor);
- // XXX Why don't you validate the pref value?
- if (NS_FAILED(rv)) {
- NS_WARNING("failed to get browser.display.background_color");
- aColor.AssignLiteral("#ffffff"); // Default to white
- }
-}
-
-// Get the default length unit used for CSS Indent/Outdent
-void
-CSSEditUtils::GetDefaultLengthUnit(nsAString& aLengthUnit)
-{
- nsresult rv =
- Preferences::GetString("editor.css.default_length_unit", &aLengthUnit);
- // XXX Why don't you validate the pref value?
- if (NS_FAILED(rv)) {
- aLengthUnit.AssignLiteral("px");
- }
-}
-
-// Unfortunately, CSSStyleDeclaration::GetPropertyCSSValue is not yet
-// implemented... We need then a way to determine the number part and the unit
-// from aString, aString being the result of a GetPropertyValue query...
-void
-CSSEditUtils::ParseLength(const nsAString& aString,
- float* aValue,
- nsIAtom** aUnit)
-{
- if (aString.IsEmpty()) {
- *aValue = 0;
- *aUnit = NS_Atomize(aString).take();
- return;
- }
-
- nsAString::const_iterator iter;
- aString.BeginReading(iter);
-
- float a = 10.0f , b = 1.0f, value = 0;
- int8_t sign = 1;
- int32_t i = 0, j = aString.Length();
- char16_t c;
- bool floatingPointFound = false;
- c = *iter;
- if (char16_t('-') == c) { sign = -1; iter++; i++; }
- else if (char16_t('+') == c) { iter++; i++; }
- while (i < j) {
- c = *iter;
- if ((char16_t('0') == c) ||
- (char16_t('1') == c) ||
- (char16_t('2') == c) ||
- (char16_t('3') == c) ||
- (char16_t('4') == c) ||
- (char16_t('5') == c) ||
- (char16_t('6') == c) ||
- (char16_t('7') == c) ||
- (char16_t('8') == c) ||
- (char16_t('9') == c)) {
- value = (value * a) + (b * (c - char16_t('0')));
- b = b / 10 * a;
- }
- else if (!floatingPointFound && (char16_t('.') == c)) {
- floatingPointFound = true;
- a = 1.0f; b = 0.1f;
- }
- else break;
- iter++;
- i++;
- }
- *aValue = value * sign;
- *aUnit = NS_Atomize(StringTail(aString, j-i)).take();
-}
-
-void
-CSSEditUtils::GetCSSPropertyAtom(nsCSSEditableProperty aProperty,
- nsIAtom** aAtom)
-{
- *aAtom = nullptr;
- switch (aProperty) {
- case eCSSEditableProperty_background_color:
- *aAtom = nsGkAtoms::backgroundColor;
- break;
- case eCSSEditableProperty_background_image:
- *aAtom = nsGkAtoms::background_image;
- break;
- case eCSSEditableProperty_border:
- *aAtom = nsGkAtoms::border;
- break;
- case eCSSEditableProperty_caption_side:
- *aAtom = nsGkAtoms::caption_side;
- break;
- case eCSSEditableProperty_color:
- *aAtom = nsGkAtoms::color;
- break;
- case eCSSEditableProperty_float:
- *aAtom = nsGkAtoms::_float;
- break;
- case eCSSEditableProperty_font_family:
- *aAtom = nsGkAtoms::font_family;
- break;
- case eCSSEditableProperty_font_size:
- *aAtom = nsGkAtoms::font_size;
- break;
- case eCSSEditableProperty_font_style:
- *aAtom = nsGkAtoms::font_style;
- break;
- case eCSSEditableProperty_font_weight:
- *aAtom = nsGkAtoms::fontWeight;
- break;
- case eCSSEditableProperty_height:
- *aAtom = nsGkAtoms::height;
- break;
- case eCSSEditableProperty_list_style_type:
- *aAtom = nsGkAtoms::list_style_type;
- break;
- case eCSSEditableProperty_margin_left:
- *aAtom = nsGkAtoms::marginLeft;
- break;
- case eCSSEditableProperty_margin_right:
- *aAtom = nsGkAtoms::marginRight;
- break;
- case eCSSEditableProperty_text_align:
- *aAtom = nsGkAtoms::textAlign;
- break;
- case eCSSEditableProperty_text_decoration:
- *aAtom = nsGkAtoms::text_decoration;
- break;
- case eCSSEditableProperty_vertical_align:
- *aAtom = nsGkAtoms::vertical_align;
- break;
- case eCSSEditableProperty_whitespace:
- *aAtom = nsGkAtoms::white_space;
- break;
- case eCSSEditableProperty_width:
- *aAtom = nsGkAtoms::width;
- break;
- case eCSSEditableProperty_NONE:
- // intentionally empty
- break;
- }
-}
-
-// Populate aProperty and aValueArray with the CSS declarations equivalent to the
-// value aValue according to the equivalence table aEquivTable
-void
-CSSEditUtils::BuildCSSDeclarations(nsTArray<nsIAtom*>& aPropertyArray,
- nsTArray<nsString>& aValueArray,
- const CSSEquivTable* aEquivTable,
- const nsAString* aValue,
- bool aGetOrRemoveRequest)
-{
- // clear arrays
- aPropertyArray.Clear();
- aValueArray.Clear();
-
- // if we have an input value, let's use it
- nsAutoString value, lowerCasedValue;
- if (aValue) {
- value.Assign(*aValue);
- lowerCasedValue.Assign(*aValue);
- ToLowerCase(lowerCasedValue);
- }
-
- int8_t index = 0;
- nsCSSEditableProperty cssProperty = aEquivTable[index].cssProperty;
- while (cssProperty) {
- if (!aGetOrRemoveRequest|| aEquivTable[index].gettable) {
- nsAutoString cssValue, cssPropertyString;
- nsIAtom * cssPropertyAtom;
- // find the equivalent css value for the index-th property in
- // the equivalence table
- (*aEquivTable[index].processValueFunctor) ((!aGetOrRemoveRequest || aEquivTable[index].caseSensitiveValue) ? &value : &lowerCasedValue,
- cssValue,
- aEquivTable[index].defaultValue,
- aEquivTable[index].prependValue,
- aEquivTable[index].appendValue);
- GetCSSPropertyAtom(cssProperty, &cssPropertyAtom);
- aPropertyArray.AppendElement(cssPropertyAtom);
- aValueArray.AppendElement(cssValue);
- }
- index++;
- cssProperty = aEquivTable[index].cssProperty;
- }
-}
-
-// Populate cssPropertyArray and cssValueArray with the declarations equivalent
-// to aHTMLProperty/aAttribute/aValue for the node aNode
-void
-CSSEditUtils::GenerateCSSDeclarationsFromHTMLStyle(
- Element* aElement,
- nsIAtom* aHTMLProperty,
- nsIAtom* aAttribute,
- const nsAString* aValue,
- nsTArray<nsIAtom*>& cssPropertyArray,
- nsTArray<nsString>& cssValueArray,
- bool aGetOrRemoveRequest)
-{
- MOZ_ASSERT(aElement);
- const CSSEditUtils::CSSEquivTable* equivTable = nullptr;
-
- if (nsGkAtoms::b == aHTMLProperty) {
- equivTable = boldEquivTable;
- } else if (nsGkAtoms::i == aHTMLProperty) {
- equivTable = italicEquivTable;
- } else if (nsGkAtoms::u == aHTMLProperty) {
- equivTable = underlineEquivTable;
- } else if (nsGkAtoms::strike == aHTMLProperty) {
- equivTable = strikeEquivTable;
- } else if (nsGkAtoms::tt == aHTMLProperty) {
- equivTable = ttEquivTable;
- } else if (aAttribute) {
- if (nsGkAtoms::font == aHTMLProperty && aAttribute == nsGkAtoms::color) {
- equivTable = fontColorEquivTable;
- } else if (nsGkAtoms::font == aHTMLProperty &&
- aAttribute == nsGkAtoms::face) {
- equivTable = fontFaceEquivTable;
- } else if (aAttribute == nsGkAtoms::bgcolor) {
- equivTable = bgcolorEquivTable;
- } else if (aAttribute == nsGkAtoms::background) {
- equivTable = backgroundImageEquivTable;
- } else if (aAttribute == nsGkAtoms::text) {
- equivTable = textColorEquivTable;
- } else if (aAttribute == nsGkAtoms::border) {
- equivTable = borderEquivTable;
- } else if (aAttribute == nsGkAtoms::align) {
- if (aElement->IsHTMLElement(nsGkAtoms::table)) {
- equivTable = tableAlignEquivTable;
- } else if (aElement->IsHTMLElement(nsGkAtoms::hr)) {
- equivTable = hrAlignEquivTable;
- } else if (aElement->IsAnyOfHTMLElements(nsGkAtoms::legend,
- nsGkAtoms::caption)) {
- equivTable = captionAlignEquivTable;
- } else {
- equivTable = textAlignEquivTable;
- }
- } else if (aAttribute == nsGkAtoms::valign) {
- equivTable = verticalAlignEquivTable;
- } else if (aAttribute == nsGkAtoms::nowrap) {
- equivTable = nowrapEquivTable;
- } else if (aAttribute == nsGkAtoms::width) {
- equivTable = widthEquivTable;
- } else if (aAttribute == nsGkAtoms::height ||
- (aElement->IsHTMLElement(nsGkAtoms::hr) &&
- aAttribute == nsGkAtoms::size)) {
- equivTable = heightEquivTable;
- } else if (aAttribute == nsGkAtoms::type &&
- aElement->IsAnyOfHTMLElements(nsGkAtoms::ol,
- nsGkAtoms::ul,
- nsGkAtoms::li)) {
- equivTable = listStyleTypeEquivTable;
- }
- }
- if (equivTable) {
- BuildCSSDeclarations(cssPropertyArray, cssValueArray, equivTable,
- aValue, aGetOrRemoveRequest);
- }
-}
-
-// Add to aNode the CSS inline style equivalent to HTMLProperty/aAttribute/
-// aValue for the node, and return in aCount the number of CSS properties set
-// by the call. The Element version returns aCount instead.
-int32_t
-CSSEditUtils::SetCSSEquivalentToHTMLStyle(nsIDOMNode* aNode,
- nsIAtom* aProperty,
- const nsAString* aAttribute,
- const nsAString* aValue,
- bool aSuppressTransaction)
-{
- MOZ_ASSERT_IF(aAttribute, aValue);
- // This can only fail if SetCSSProperty fails, which should only happen if
- // something is pretty badly wrong. In this case we assert so that hopefully
- // someone will notice, but there's nothing more sensible to do than just
- // return the count and carry on.
- nsCOMPtr<Element> element = do_QueryInterface(aNode);
- return SetCSSEquivalentToHTMLStyle(element,
- aProperty, aAttribute,
- aValue, aSuppressTransaction);
-}
-
-int32_t
-CSSEditUtils::SetCSSEquivalentToHTMLStyle(Element* aElement,
- nsIAtom* aHTMLProperty,
- const nsAString* aAttribute,
- const nsAString* aValue,
- bool aSuppressTransaction)
-{
- nsCOMPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
- return SetCSSEquivalentToHTMLStyle(aElement, aHTMLProperty, attribute,
- aValue, aSuppressTransaction);
-}
-
-int32_t
-CSSEditUtils::SetCSSEquivalentToHTMLStyle(Element* aElement,
- nsIAtom* aHTMLProperty,
- nsIAtom* aAttribute,
- const nsAString* aValue,
- bool aSuppressTransaction)
-{
- MOZ_ASSERT(aElement);
-
- if (!IsCSSEditableProperty(aElement, aHTMLProperty, aAttribute)) {
- return 0;
- }
-
- // we can apply the styles only if the node is an element and if we have
- // an equivalence for the requested HTML style in this implementation
-
- // Find the CSS equivalence to the HTML style
- nsTArray<nsIAtom*> cssPropertyArray;
- nsTArray<nsString> cssValueArray;
- GenerateCSSDeclarationsFromHTMLStyle(aElement, aHTMLProperty, aAttribute,
- aValue, cssPropertyArray, cssValueArray,
- false);
-
- // set the individual CSS inline styles
- size_t count = cssPropertyArray.Length();
- for (size_t index = 0; index < count; index++) {
- nsresult rv = SetCSSProperty(*aElement, *cssPropertyArray[index],
- cssValueArray[index], aSuppressTransaction);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return 0;
- }
- }
- return count;
-}
-
-// Remove from aNode the CSS inline style equivalent to HTMLProperty/aAttribute/aValue for the node
-nsresult
-CSSEditUtils::RemoveCSSEquivalentToHTMLStyle(nsIDOMNode* aNode,
- nsIAtom* aHTMLProperty,
- const nsAString* aAttribute,
- const nsAString* aValue,
- bool aSuppressTransaction)
-{
- nsCOMPtr<Element> element = do_QueryInterface(aNode);
- nsCOMPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
-
- return RemoveCSSEquivalentToHTMLStyle(element, aHTMLProperty, attribute,
- aValue, aSuppressTransaction);
-}
-
-nsresult
-CSSEditUtils::RemoveCSSEquivalentToHTMLStyle(Element* aElement,
- nsIAtom* aHTMLProperty,
- nsIAtom* aAttribute,
- const nsAString* aValue,
- bool aSuppressTransaction)
-{
- if (NS_WARN_IF(!aElement)) {
- return NS_OK;
- }
-
- if (!IsCSSEditableProperty(aElement, aHTMLProperty, aAttribute)) {
- return NS_OK;
- }
-
- // we can apply the styles only if the node is an element and if we have
- // an equivalence for the requested HTML style in this implementation
-
- // Find the CSS equivalence to the HTML style
- nsTArray<nsIAtom*> cssPropertyArray;
- nsTArray<nsString> cssValueArray;
- GenerateCSSDeclarationsFromHTMLStyle(aElement, aHTMLProperty, aAttribute,
- aValue, cssPropertyArray, cssValueArray,
- true);
-
- // remove the individual CSS inline styles
- int32_t count = cssPropertyArray.Length();
- for (int32_t index = 0; index < count; index++) {
- nsresult rv = RemoveCSSProperty(*aElement,
- *cssPropertyArray[index],
- cssValueArray[index],
- aSuppressTransaction);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
-}
-
-// returns in aValueString the list of values for the CSS equivalences to
-// the HTML style aHTMLProperty/aAttribute/aValueString for the node aNode;
-// the value of aStyleType controls the styles we retrieve : specified or
-// computed.
-nsresult
-CSSEditUtils::GetCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode,
- nsIAtom* aHTMLProperty,
- nsIAtom* aAttribute,
- nsAString& aValueString,
- StyleType aStyleType)
-{
- aValueString.Truncate();
- nsCOMPtr<Element> theElement = GetElementContainerOrSelf(aNode);
- NS_ENSURE_TRUE(theElement, NS_ERROR_NULL_POINTER);
-
- if (!theElement || !IsCSSEditableProperty(theElement, aHTMLProperty, aAttribute)) {
- return NS_OK;
- }
-
- // Yes, the requested HTML style has a CSS equivalence in this implementation
- nsTArray<nsIAtom*> cssPropertyArray;
- nsTArray<nsString> cssValueArray;
- // get the CSS equivalence with last param true indicating we want only the
- // "gettable" properties
- GenerateCSSDeclarationsFromHTMLStyle(theElement, aHTMLProperty, aAttribute,
- nullptr,
- cssPropertyArray, cssValueArray, true);
- int32_t count = cssPropertyArray.Length();
- for (int32_t index = 0; index < count; index++) {
- nsAutoString valueString;
- // retrieve the specified/computed value of the property
- nsresult rv = GetCSSInlinePropertyBase(theElement, cssPropertyArray[index],
- valueString, aStyleType);
- NS_ENSURE_SUCCESS(rv, rv);
- // append the value to aValueString (possibly with a leading whitespace)
- if (index) {
- aValueString.Append(char16_t(' '));
- }
- aValueString.Append(valueString);
- }
- return NS_OK;
-}
-
-// Does the node aNode (or its parent, if it's not an element node) have a CSS
-// style equivalent to the HTML style aHTMLProperty/aHTMLAttribute/valueString?
-// The value of aStyleType controls the styles we retrieve: specified or
-// computed. The return value aIsSet is true if the CSS styles are set.
-//
-// The nsIContent variant returns aIsSet instead of using an out parameter, and
-// does not modify aValue.
-bool
-CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode,
- nsIAtom* aProperty,
- const nsAString* aAttribute,
- const nsAString& aValue,
- StyleType aStyleType)
-{
- // Use aValue as only an in param, not in-out
- nsAutoString value(aValue);
- return IsCSSEquivalentToHTMLInlineStyleSet(aNode, aProperty, aAttribute,
- value, aStyleType);
-}
-
-bool
-CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode,
- nsIAtom* aProperty,
- const nsAString* aAttribute,
- nsAString& aValue,
- StyleType aStyleType)
-{
- MOZ_ASSERT(aNode && aProperty);
- nsCOMPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
- return IsCSSEquivalentToHTMLInlineStyleSet(aNode,
- aProperty, attribute,
- aValue, aStyleType);
-}
-
-bool
-CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsIDOMNode* aNode,
- nsIAtom* aProperty,
- const nsAString* aAttribute,
- nsAString& aValue,
- StyleType aStyleType)
-{
- MOZ_ASSERT(aNode && aProperty);
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- nsCOMPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
- return IsCSSEquivalentToHTMLInlineStyleSet(node, aProperty, attribute,
- aValue, aStyleType);
-}
-
-bool
-CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(
- nsINode* aNode,
- nsIAtom* aHTMLProperty,
- nsIAtom* aHTMLAttribute,
- nsAString& valueString,
- StyleType aStyleType)
-{
- NS_ENSURE_TRUE(aNode, false);
-
- nsAutoString htmlValueString(valueString);
- bool isSet = false;
- do {
- valueString.Assign(htmlValueString);
- // get the value of the CSS equivalent styles
- nsresult rv =
- GetCSSEquivalentToHTMLInlineStyleSet(aNode, aHTMLProperty, aHTMLAttribute,
- valueString, aStyleType);
- NS_ENSURE_SUCCESS(rv, false);
-
- // early way out if we can
- if (valueString.IsEmpty()) {
- return isSet;
- }
-
- if (nsGkAtoms::b == aHTMLProperty) {
- if (valueString.EqualsLiteral("bold")) {
- isSet = true;
- } else if (valueString.EqualsLiteral("normal")) {
- isSet = false;
- } else if (valueString.EqualsLiteral("bolder")) {
- isSet = true;
- valueString.AssignLiteral("bold");
- } else {
- int32_t weight = 0;
- nsresult errorCode;
- nsAutoString value(valueString);
- weight = value.ToInteger(&errorCode);
- if (400 < weight) {
- isSet = true;
- valueString.AssignLiteral("bold");
- } else {
- isSet = false;
- valueString.AssignLiteral("normal");
- }
- }
- } else if (nsGkAtoms::i == aHTMLProperty) {
- if (valueString.EqualsLiteral("italic") ||
- valueString.EqualsLiteral("oblique")) {
- isSet = true;
- }
- } else if (nsGkAtoms::u == aHTMLProperty) {
- nsAutoString val;
- val.AssignLiteral("underline");
- isSet = ChangeStyleTransaction::ValueIncludes(valueString, val);
- } else if (nsGkAtoms::strike == aHTMLProperty) {
- nsAutoString val;
- val.AssignLiteral("line-through");
- isSet = ChangeStyleTransaction::ValueIncludes(valueString, val);
- } else if ((nsGkAtoms::font == aHTMLProperty &&
- aHTMLAttribute == nsGkAtoms::color) ||
- aHTMLAttribute == nsGkAtoms::bgcolor) {
- if (htmlValueString.IsEmpty()) {
- isSet = true;
- } else {
- nscolor rgba;
- nsAutoString subStr;
- htmlValueString.Right(subStr, htmlValueString.Length() - 1);
- if (NS_ColorNameToRGB(htmlValueString, &rgba) ||
- NS_HexToRGBA(subStr, nsHexColorType::NoAlpha, &rgba)) {
- nsAutoString htmlColor, tmpStr;
-
- if (NS_GET_A(rgba) != 255) {
- // This should only be hit by the "transparent" keyword, which
- // currently serializes to "transparent" (not "rgba(0, 0, 0, 0)").
- MOZ_ASSERT(NS_GET_R(rgba) == 0 && NS_GET_G(rgba) == 0 &&
- NS_GET_B(rgba) == 0 && NS_GET_A(rgba) == 0);
- htmlColor.AppendLiteral("transparent");
- } else {
- htmlColor.AppendLiteral("rgb(");
-
- NS_NAMED_LITERAL_STRING(comma, ", ");
-
- tmpStr.AppendInt(NS_GET_R(rgba), 10);
- htmlColor.Append(tmpStr + comma);
-
- tmpStr.Truncate();
- tmpStr.AppendInt(NS_GET_G(rgba), 10);
- htmlColor.Append(tmpStr + comma);
-
- tmpStr.Truncate();
- tmpStr.AppendInt(NS_GET_B(rgba), 10);
- htmlColor.Append(tmpStr);
-
- htmlColor.Append(char16_t(')'));
- }
-
- isSet = htmlColor.Equals(valueString,
- nsCaseInsensitiveStringComparator());
- } else {
- isSet = htmlValueString.Equals(valueString,
- nsCaseInsensitiveStringComparator());
- }
- }
- } else if (nsGkAtoms::tt == aHTMLProperty) {
- isSet = StringBeginsWith(valueString, NS_LITERAL_STRING("monospace"));
- } else if (nsGkAtoms::font == aHTMLProperty && aHTMLAttribute &&
- aHTMLAttribute == nsGkAtoms::face) {
- if (!htmlValueString.IsEmpty()) {
- const char16_t commaSpace[] = { char16_t(','), char16_t(' '), 0 };
- const char16_t comma[] = { char16_t(','), 0 };
- htmlValueString.ReplaceSubstring(commaSpace, comma);
- nsAutoString valueStringNorm(valueString);
- valueStringNorm.ReplaceSubstring(commaSpace, comma);
- isSet = htmlValueString.Equals(valueStringNorm,
- nsCaseInsensitiveStringComparator());
- } else {
- isSet = true;
- }
- return isSet;
- } else if (aHTMLAttribute == nsGkAtoms::align) {
- isSet = true;
- } else {
- return false;
- }
-
- if (!htmlValueString.IsEmpty() &&
- htmlValueString.Equals(valueString,
- nsCaseInsensitiveStringComparator())) {
- isSet = true;
- }
-
- if (htmlValueString.EqualsLiteral("-moz-editor-invert-value")) {
- isSet = !isSet;
- }
-
- if (nsGkAtoms::u == aHTMLProperty || nsGkAtoms::strike == aHTMLProperty) {
- // unfortunately, the value of the text-decoration property is not inherited.
- // that means that we have to look at ancestors of node to see if they are underlined
- aNode = aNode->GetParentElement(); // set to null if it's not a dom element
- }
- } while ((nsGkAtoms::u == aHTMLProperty ||
- nsGkAtoms::strike == aHTMLProperty) && !isSet && aNode);
- return isSet;
-}
-
-void
-CSSEditUtils::SetCSSEnabled(bool aIsCSSPrefChecked)
-{
- mIsCSSPrefChecked = aIsCSSPrefChecked;
-}
-
-bool
-CSSEditUtils::IsCSSPrefChecked()
-{
- return mIsCSSPrefChecked ;
-}
-
-// ElementsSameStyle compares two elements and checks if they have the same
-// specified CSS declarations in the STYLE attribute
-// The answer is always negative if at least one of them carries an ID or a class
-bool
-CSSEditUtils::ElementsSameStyle(nsIDOMNode* aFirstNode,
- nsIDOMNode* aSecondNode)
-{
- nsCOMPtr<Element> firstElement = do_QueryInterface(aFirstNode);
- nsCOMPtr<Element> secondElement = do_QueryInterface(aSecondNode);
-
- NS_ASSERTION((firstElement && secondElement), "Non element nodes passed to ElementsSameStyle.");
- NS_ENSURE_TRUE(firstElement, false);
- NS_ENSURE_TRUE(secondElement, false);
-
- return ElementsSameStyle(firstElement, secondElement);
-}
-
-bool
-CSSEditUtils::ElementsSameStyle(Element* aFirstElement,
- Element* aSecondElement)
-{
- MOZ_ASSERT(aFirstElement);
- MOZ_ASSERT(aSecondElement);
-
- if (aFirstElement->HasAttr(kNameSpaceID_None, nsGkAtoms::id) ||
- aSecondElement->HasAttr(kNameSpaceID_None, nsGkAtoms::id)) {
- // at least one of the spans carries an ID ; suspect a CSS rule applies to it and
- // refuse to merge the nodes
- return false;
- }
-
- nsAutoString firstClass, secondClass;
- bool isFirstClassSet = aFirstElement->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, firstClass);
- bool isSecondClassSet = aSecondElement->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, secondClass);
- if (isFirstClassSet && isSecondClassSet) {
- // both spans carry a class, let's compare them
- if (!firstClass.Equals(secondClass)) {
- // WARNING : technically, the comparison just above is questionable :
- // from a pure HTML/CSS point of view class="a b" is NOT the same than
- // class="b a" because a CSS rule could test the exact value of the class
- // attribute to be "a b" for instance ; from a user's point of view, a
- // wysiwyg editor should probably NOT make any difference. CSS people
- // need to discuss this issue before any modification.
- return false;
- }
- } else if (isFirstClassSet || isSecondClassSet) {
- // one span only carries a class, early way out
- return false;
- }
-
- nsCOMPtr<nsIDOMCSSStyleDeclaration> firstCSSDecl, secondCSSDecl;
- uint32_t firstLength, secondLength;
- nsresult rv = GetInlineStyles(aFirstElement, getter_AddRefs(firstCSSDecl), &firstLength);
- if (NS_FAILED(rv) || !firstCSSDecl) {
- return false;
- }
- rv = GetInlineStyles(aSecondElement, getter_AddRefs(secondCSSDecl), &secondLength);
- if (NS_FAILED(rv) || !secondCSSDecl) {
- return false;
- }
-
- if (firstLength != secondLength) {
- // early way out if we can
- return false;
- }
-
- if (!firstLength) {
- // no inline style !
- return true;
- }
-
- nsAutoString propertyNameString;
- nsAutoString firstValue, secondValue;
- for (uint32_t i = 0; i < firstLength; i++) {
- firstCSSDecl->Item(i, propertyNameString);
- firstCSSDecl->GetPropertyValue(propertyNameString, firstValue);
- secondCSSDecl->GetPropertyValue(propertyNameString, secondValue);
- if (!firstValue.Equals(secondValue)) {
- return false;
- }
- }
- for (uint32_t i = 0; i < secondLength; i++) {
- secondCSSDecl->Item(i, propertyNameString);
- secondCSSDecl->GetPropertyValue(propertyNameString, secondValue);
- firstCSSDecl->GetPropertyValue(propertyNameString, firstValue);
- if (!firstValue.Equals(secondValue)) {
- return false;
- }
- }
-
- return true;
-}
-
-nsresult
-CSSEditUtils::GetInlineStyles(Element* aElement,
- nsIDOMCSSStyleDeclaration** aCssDecl,
- uint32_t* aLength)
-{
- return GetInlineStyles(static_cast<nsISupports*>(aElement), aCssDecl, aLength);
-}
-
-nsresult
-CSSEditUtils::GetInlineStyles(nsIDOMElement* aElement,
- nsIDOMCSSStyleDeclaration** aCssDecl,
- uint32_t* aLength)
-{
- return GetInlineStyles(static_cast<nsISupports*>(aElement), aCssDecl, aLength);
-}
-
-nsresult
-CSSEditUtils::GetInlineStyles(nsISupports* aElement,
- nsIDOMCSSStyleDeclaration** aCssDecl,
- uint32_t* aLength)
-{
- NS_ENSURE_TRUE(aElement && aLength, NS_ERROR_NULL_POINTER);
- *aLength = 0;
- nsCOMPtr<nsStyledElement> inlineStyles = do_QueryInterface(aElement);
- NS_ENSURE_TRUE(inlineStyles, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl =
- do_QueryInterface(inlineStyles->Style());
- MOZ_ASSERT(cssDecl);
-
- cssDecl.forget(aCssDecl);
- (*aCssDecl)->GetLength(aLength);
- return NS_OK;
-}
-
-already_AddRefed<nsIDOMElement>
-CSSEditUtils::GetElementContainerOrSelf(nsIDOMNode* aNode)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- NS_ENSURE_TRUE(node, nullptr);
- nsCOMPtr<nsIDOMElement> element =
- do_QueryInterface(GetElementContainerOrSelf(node));
- return element.forget();
-}
-
-Element*
-CSSEditUtils::GetElementContainerOrSelf(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
- if (nsIDOMNode::DOCUMENT_NODE == aNode->NodeType()) {
- return nullptr;
- }
-
- nsINode* node = aNode;
- // Loop until we find an element.
- while (node && !node->IsElement()) {
- node = node->GetParentNode();
- }
-
- NS_ENSURE_TRUE(node, nullptr);
- return node->AsElement();
-}
-
-nsresult
-CSSEditUtils::SetCSSProperty(nsIDOMElement* aElement,
- const nsAString& aProperty,
- const nsAString& aValue)
-{
- nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
- uint32_t length;
- nsresult rv = GetInlineStyles(aElement, getter_AddRefs(cssDecl), &length);
- if (NS_FAILED(rv) || !cssDecl) {
- return rv;
- }
-
- return cssDecl->SetProperty(aProperty,
- aValue,
- EmptyString());
-}
-
-nsresult
-CSSEditUtils::SetCSSPropertyPixels(nsIDOMElement* aElement,
- const nsAString& aProperty,
- int32_t aIntValue)
-{
- nsAutoString s;
- s.AppendInt(aIntValue);
- return SetCSSProperty(aElement, aProperty, s + NS_LITERAL_STRING("px"));
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/CSSEditUtils.h b/editor/libeditor/CSSEditUtils.h
deleted file mode 100644
index 5129ab88d..000000000
--- a/editor/libeditor/CSSEditUtils.h
+++ /dev/null
@@ -1,480 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_CSSEditUtils_h
-#define mozilla_CSSEditUtils_h
-
-#include "mozilla/ChangeStyleTransaction.h" // for ChangeStyleTransaction
-#include "nsCOMPtr.h" // for already_AddRefed
-#include "nsTArray.h" // for nsTArray
-#include "nscore.h" // for nsAString, nsresult, nullptr
-
-class nsComputedDOMStyle;
-class nsIAtom;
-class nsIContent;
-class nsIDOMCSSStyleDeclaration;
-class nsIDOMElement;
-class nsIDOMNode;
-class nsINode;
-class nsString;
-
-namespace mozilla {
-
-class HTMLEditor;
-namespace dom {
-class Element;
-} // namespace dom
-
-typedef void (*nsProcessValueFunc)(const nsAString* aInputString,
- nsAString& aOutputString,
- const char* aDefaultValueString,
- const char* aPrependString,
- const char* aAppendString);
-
-class CSSEditUtils final
-{
-public:
- explicit CSSEditUtils(HTMLEditor* aEditor);
- ~CSSEditUtils();
-
- enum nsCSSEditableProperty
- {
- eCSSEditableProperty_NONE=0,
- eCSSEditableProperty_background_color,
- eCSSEditableProperty_background_image,
- eCSSEditableProperty_border,
- eCSSEditableProperty_caption_side,
- eCSSEditableProperty_color,
- eCSSEditableProperty_float,
- eCSSEditableProperty_font_family,
- eCSSEditableProperty_font_size,
- eCSSEditableProperty_font_style,
- eCSSEditableProperty_font_weight,
- eCSSEditableProperty_height,
- eCSSEditableProperty_list_style_type,
- eCSSEditableProperty_margin_left,
- eCSSEditableProperty_margin_right,
- eCSSEditableProperty_text_align,
- eCSSEditableProperty_text_decoration,
- eCSSEditableProperty_vertical_align,
- eCSSEditableProperty_whitespace,
- eCSSEditableProperty_width
- };
-
- enum StyleType { eSpecified, eComputed };
-
-
- struct CSSEquivTable
- {
- nsCSSEditableProperty cssProperty;
- nsProcessValueFunc processValueFunctor;
- const char* defaultValue;
- const char* prependValue;
- const char* appendValue;
- bool gettable;
- bool caseSensitiveValue;
- };
-
- /**
- * Answers true if the given combination element_name/attribute_name
- * has a CSS equivalence in this implementation.
- *
- * @param aNode [IN] A DOM node.
- * @param aProperty [IN] An atom containing a HTML tag name.
- * @param aAttribute [IN] A string containing the name of a HTML
- * attribute carried by the element above.
- * @return A boolean saying if the tag/attribute has a CSS
- * equiv.
- */
- bool IsCSSEditableProperty(nsINode* aNode, nsIAtom* aProperty,
- const nsAString* aAttribute);
- bool IsCSSEditableProperty(nsINode* aNode, nsIAtom* aProperty,
- nsIAtom* aAttribute);
-
- /**
- * Adds/remove a CSS declaration to the STYLE atrribute carried by a given
- * element.
- *
- * @param aElement [IN] A DOM element.
- * @param aProperty [IN] An atom containing the CSS property to set.
- * @param aValue [IN] A string containing the value of the CSS
- * property.
- * @param aSuppressTransaction [IN] A boolean indicating, when true,
- * that no transaction should be recorded.
- */
- nsresult SetCSSProperty(dom::Element& aElement, nsIAtom& aProperty,
- const nsAString& aValue, bool aSuppressTxn = false);
- nsresult SetCSSPropertyPixels(dom::Element& aElement,
- nsIAtom& aProperty, int32_t aIntValue);
- nsresult RemoveCSSProperty(dom::Element& aElement,
- nsIAtom& aProperty,
- const nsAString& aPropertyValue,
- bool aSuppressTxn = false);
-
- /**
- * Directly adds/remove a CSS declaration to the STYLE atrribute carried by
- * a given element without going through the transaction manager.
- *
- * @param aElement [IN] A DOM element.
- * @param aProperty [IN] A string containing the CSS property to
- * set/remove.
- * @param aValue [IN] A string containing the new value of the CSS
- * property.
- */
- nsresult SetCSSProperty(nsIDOMElement* aElement,
- const nsAString& aProperty,
- const nsAString& aValue);
- nsresult SetCSSPropertyPixels(nsIDOMElement* aElement,
- const nsAString& aProperty,
- int32_t aIntValue);
-
- /**
- * Gets the specified/computed style value of a CSS property for a given
- * node (or its element ancestor if it is not an element).
- *
- * @param aNode [IN] A DOM node.
- * @param aProperty [IN] An atom containing the CSS property to get.
- * @param aPropertyValue [OUT] The retrieved value of the property.
- */
- nsresult GetSpecifiedProperty(nsINode& aNode, nsIAtom& aProperty,
- nsAString& aValue);
- nsresult GetComputedProperty(nsINode& aNode, nsIAtom& aProperty,
- nsAString& aValue);
-
- /**
- * Removes a CSS property from the specified declarations in STYLE attribute
- * and removes the node if it is an useless span.
- *
- * @param aNode [IN] The specific node we want to remove a style
- * from.
- * @param aProperty [IN] The CSS property atom to remove.
- * @param aPropertyValue [IN] The value of the property we have to remove
- * if the property accepts more than one value.
- */
- nsresult RemoveCSSInlineStyle(nsIDOMNode* aNode, nsIAtom* aProperty,
- const nsAString& aPropertyValue);
-
- /**
- * Answers true is the property can be removed by setting a "none" CSS value
- * on a node.
- *
- * @param aProperty [IN] An atom containing a CSS property.
- * @param aAttribute [IN] Pointer to an attribute name or null if this
- * information is irrelevant.
- * @return A boolean saying if the property can be remove by
- * setting a "none" value.
- */
- bool IsCSSInvertible(nsIAtom& aProperty, const nsAString* aAttribute);
-
- /**
- * Get the default browser background color if we need it for
- * GetCSSBackgroundColorState().
- *
- * @param aColor [OUT] The default color as it is defined in prefs.
- */
- void GetDefaultBackgroundColor(nsAString& aColor);
-
- /**
- * Get the default length unit used for CSS Indent/Outdent.
- *
- * @param aLengthUnit [OUT] The default length unit as it is defined in
- * prefs.
- */
- void GetDefaultLengthUnit(nsAString & aLengthUnit);
-
- /**
- * Returns the list of values for the CSS equivalences to
- * the passed HTML style for the passed node.
- *
- * @param aNode [IN] A DOM node.
- * @param aHTMLProperty [IN] An atom containing an HTML property.
- * @param aAttribute [IN] An atom of attribute name or nullptr if
- * irrelevant.
- * @param aValueString [OUT] The list of CSS values.
- * @param aStyleType [IN] eSpecified or eComputed.
- */
- nsresult GetCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode,
- nsIAtom* aHTMLProperty,
- nsIAtom* aAttribute,
- nsAString& aValueString,
- StyleType aStyleType);
-
- /**
- * Does the node aNode (or his parent if it is not an element node) carries
- * the CSS equivalent styles to the HTML style for this node ?
- *
- * @param aNode [IN] A DOM node.
- * @param aHTMLProperty [IN] An atom containing an HTML property.
- * @param aAttribute [IN] A pointer/atom to an attribute name or nullptr
- * if irrelevant.
- * @param aValueString [IN/OUT] The attribute value (in) the list of CSS
- * values (out).
- * @param aStyleType [IN] eSpecified or eComputed.
- * @return A boolean being true if the css properties are
- * set.
- */
- bool IsCSSEquivalentToHTMLInlineStyleSet(nsINode* aContent,
- nsIAtom* aProperty,
- nsIAtom* aAttribute,
- nsAString& aValue,
- StyleType aStyleType);
-
- bool IsCSSEquivalentToHTMLInlineStyleSet(nsINode* aContent,
- nsIAtom* aProperty,
- const nsAString* aAttribute,
- const nsAString& aValue,
- StyleType aStyleType);
-
- bool IsCSSEquivalentToHTMLInlineStyleSet(nsINode* aContent,
- nsIAtom* aProperty,
- const nsAString* aAttribute,
- nsAString& aValue,
- StyleType aStyleType);
-
- bool IsCSSEquivalentToHTMLInlineStyleSet(nsIDOMNode* aNode,
- nsIAtom* aProperty,
- const nsAString* aAttribute,
- nsAString& aValue,
- StyleType aStyleType);
-
- /**
- * Adds to the node the CSS inline styles equivalent to the HTML style
- * and return the number of CSS properties set by the call.
- *
- * @param aNode [IN] A DOM node.
- * @param aHTMLProperty [IN] An atom containing an HTML property.
- * @param aAttribute [IN] A pointer/atom to an attribute name or nullptr
- * if irrelevant.
- * @param aValue [IN] The attribute value.
- * @param aSuppressTransaction [IN] A boolean indicating, when true,
- * that no transaction should be recorded.
- *
- * @return The number of CSS properties set by the call.
- */
- int32_t SetCSSEquivalentToHTMLStyle(dom::Element* aElement,
- nsIAtom* aProperty,
- nsIAtom* aAttribute,
- const nsAString* aValue,
- bool aSuppressTransaction);
- int32_t SetCSSEquivalentToHTMLStyle(dom::Element* aElement,
- nsIAtom* aProperty,
- const nsAString* aAttribute,
- const nsAString* aValue,
- bool aSuppressTransaction);
- int32_t SetCSSEquivalentToHTMLStyle(nsIDOMNode* aNode,
- nsIAtom* aHTMLProperty,
- const nsAString* aAttribute,
- const nsAString* aValue,
- bool aSuppressTransaction);
-
- /**
- * Removes from the node the CSS inline styles equivalent to the HTML style.
- *
- * @param aNode [IN] A DOM node.
- * @param aHTMLProperty [IN] An atom containing an HTML property.
- * @param aAttribute [IN] A pointer to an attribute name or nullptr if
- * irrelevant.
- * @param aValue [IN] The attribute value.
- * @param aSuppressTransaction [IN] A boolean indicating, when true,
- * that no transaction should be recorded.
- */
- nsresult RemoveCSSEquivalentToHTMLStyle(nsIDOMNode* aNode,
- nsIAtom* aHTMLProperty,
- const nsAString* aAttribute,
- const nsAString* aValue,
- bool aSuppressTransaction);
-
- /**
- * Removes from the node the CSS inline styles equivalent to the HTML style.
- *
- * @param aElement [IN] A DOM Element (must not be null).
- * @param aHTMLProperty [IN] An atom containing an HTML property.
- * @param aAttribute [IN] An atom to an attribute name or nullptr if
- * irrelevant.
- * @param aValue [IN] The attribute value.
- * @param aSuppressTransaction [IN] A boolean indicating, when true,
- * that no transaction should be recorded.
- */
- nsresult RemoveCSSEquivalentToHTMLStyle(dom::Element* aElement,
- nsIAtom* aHTMLProperty,
- nsIAtom* aAttribute,
- const nsAString* aValue,
- bool aSuppressTransaction);
-
- /**
- * Parses a "xxxx.xxxxxuuu" string where x is a digit and u an alpha char
- * we need such a parser because
- * nsIDOMCSSStyleDeclaration::GetPropertyCSSValue() is not implemented.
- *
- * @param aString [IN] Input string to parse.
- * @param aValue [OUT] Numeric part.
- * @param aUnit [OUT] Unit part.
- */
- void ParseLength(const nsAString& aString, float* aValue, nsIAtom** aUnit);
-
- /**
- * Sets the mIsCSSPrefChecked private member; used as callback from observer
- * when the CSS pref state is changed.
- *
- * @param aIsCSSPrefChecked [IN] The new boolean state for the pref.
- */
- void SetCSSEnabled(bool aIsCSSPrefChecked);
-
- /**
- * Retrieves the mIsCSSPrefChecked private member, true if the CSS pref is
- * checked, false if it is not.
- *
- * @return the boolean value of the CSS pref.
- */
- bool IsCSSPrefChecked();
-
- /**
- * ElementsSameStyle compares two elements and checks if they have the same
- * specified CSS declarations in the STYLE attribute.
- * The answer is always false if at least one of them carries an ID or a
- * class.
- *
- * @param aFirstNode [IN] A DOM node.
- * @param aSecondNode [IN] A DOM node.
- * @return true if the two elements are considered to
- * have same styles.
- */
- bool ElementsSameStyle(dom::Element* aFirstNode,
- dom::Element* aSecondNode);
- bool ElementsSameStyle(nsIDOMNode* aFirstNode, nsIDOMNode* aSecondNode);
-
- /**
- * Get the specified inline styles (style attribute) for an element.
- *
- * @param aElement [IN] The element node.
- * @param aCssDecl [OUT] The CSS declaration corresponding to the
- * style attribute.
- * @param aLength [OUT] The number of declarations in aCssDecl.
- */
- nsresult GetInlineStyles(dom::Element* aElement,
- nsIDOMCSSStyleDeclaration** aCssDecl,
- uint32_t* aLength);
- nsresult GetInlineStyles(nsIDOMElement* aElement,
- nsIDOMCSSStyleDeclaration** aCssDecl,
- uint32_t* aLength);
-private:
- nsresult GetInlineStyles(nsISupports* aElement,
- nsIDOMCSSStyleDeclaration** aCssDecl,
- uint32_t* aLength);
-
-public:
- /**
- * Returns aNode itself if it is an element node, or the first ancestors
- * being an element node if aNode is not one itself.
- *
- * @param aNode [IN] A node
- * @param aElement [OUT] The deepest element node containing aNode
- * (possibly aNode itself)
- */
- dom::Element* GetElementContainerOrSelf(nsINode* aNode);
- already_AddRefed<nsIDOMElement> GetElementContainerOrSelf(nsIDOMNode* aNode);
-
- /**
- * Gets the computed style for a given element. Can return null.
- */
- already_AddRefed<nsComputedDOMStyle> GetComputedStyle(dom::Element* aElement);
-
-private:
- /**
- * Retrieves the CSS property atom from an enum.
- *
- * @param aProperty [IN] The enum value for the property.
- * @param aAtom [OUT] The corresponding atom.
- */
- void GetCSSPropertyAtom(nsCSSEditableProperty aProperty, nsIAtom** aAtom);
-
- /**
- * Retrieves the CSS declarations equivalent to a HTML style value for
- * a given equivalence table.
- *
- * @param aPropertyArray [OUT] The array of css properties.
- * @param aValueArray [OUT] The array of values for the CSS properties
- * above.
- * @param aEquivTable [IN] The equivalence table.
- * @param aValue [IN] The HTML style value.
- * @param aGetOrRemoveRequest [IN] A boolean value being true if the call to
- * the current method is made for
- * GetCSSEquivalentToHTMLInlineStyleSet() or
- * RemoveCSSEquivalentToHTMLInlineStyleSet().
- */
- void BuildCSSDeclarations(nsTArray<nsIAtom*>& aPropertyArray,
- nsTArray<nsString>& cssValueArray,
- const CSSEquivTable* aEquivTable,
- const nsAString* aValue,
- bool aGetOrRemoveRequest);
-
- /**
- * Retrieves the CSS declarations equivalent to the given HTML
- * property/attribute/value for a given node.
- *
- * @param aNode [IN] The DOM node.
- * @param aHTMLProperty [IN] An atom containing an HTML property.
- * @param aAttribute [IN] An atom to an attribute name or nullptr
- * if irrelevant
- * @param aValue [IN] The attribute value.
- * @param aPropertyArray [OUT] The array of CSS properties.
- * @param aValueArray [OUT] The array of values for the CSS properties
- * above.
- * @param aGetOrRemoveRequest [IN] A boolean value being true if the call to
- * the current method is made for
- * GetCSSEquivalentToHTMLInlineStyleSet() or
- * RemoveCSSEquivalentToHTMLInlineStyleSet().
- */
- void GenerateCSSDeclarationsFromHTMLStyle(dom::Element* aNode,
- nsIAtom* aHTMLProperty,
- nsIAtom* aAttribute,
- const nsAString* aValue,
- nsTArray<nsIAtom*>& aPropertyArray,
- nsTArray<nsString>& aValueArray,
- bool aGetOrRemoveRequest);
-
- /**
- * Creates a Transaction for setting or removing a CSS property. Never
- * returns null.
- *
- * @param aElement [IN] A DOM element.
- * @param aProperty [IN] A CSS property.
- * @param aValue [IN] The value to set for this CSS property.
- * @param aChangeType [IN] eSet to set, eRemove to remove.
- */
- already_AddRefed<ChangeStyleTransaction>
- CreateCSSPropertyTxn(dom::Element& aElement,
- nsIAtom& aProperty, const nsAString& aValue,
- ChangeStyleTransaction::EChangeType aChangeType);
-
- /**
- * Back-end for GetSpecifiedProperty and GetComputedProperty.
- *
- * @param aNode [IN] A DOM node.
- * @param aProperty [IN] A CSS property.
- * @param aValue [OUT] The retrieved value for this property.
- * @param aStyleType [IN] eSpecified or eComputed.
- */
- nsresult GetCSSInlinePropertyBase(nsINode* aNode, nsIAtom* aProperty,
- nsAString& aValue, StyleType aStyleType);
-
-private:
- HTMLEditor* mHTMLEditor;
- bool mIsCSSPrefChecked;
-};
-
-#define NS_EDITOR_INDENT_INCREMENT_IN 0.4134f
-#define NS_EDITOR_INDENT_INCREMENT_CM 1.05f
-#define NS_EDITOR_INDENT_INCREMENT_MM 10.5f
-#define NS_EDITOR_INDENT_INCREMENT_PT 29.76f
-#define NS_EDITOR_INDENT_INCREMENT_PC 2.48f
-#define NS_EDITOR_INDENT_INCREMENT_EM 3
-#define NS_EDITOR_INDENT_INCREMENT_EX 6
-#define NS_EDITOR_INDENT_INCREMENT_PX 40
-#define NS_EDITOR_INDENT_INCREMENT_PERCENT 4
-
-} // namespace mozilla
-
-#endif // #ifndef mozilla_CSSEditUtils_h
diff --git a/editor/libeditor/ChangeAttributeTransaction.cpp b/editor/libeditor/ChangeAttributeTransaction.cpp
deleted file mode 100644
index 04f539856..000000000
--- a/editor/libeditor/ChangeAttributeTransaction.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "ChangeAttributeTransaction.h"
-
-#include "mozilla/dom/Element.h" // for Element
-
-#include "nsAString.h"
-#include "nsError.h" // for NS_ERROR_NOT_INITIALIZED, etc.
-
-namespace mozilla {
-
-using namespace dom;
-
-ChangeAttributeTransaction::ChangeAttributeTransaction(Element& aElement,
- nsIAtom& aAttribute,
- const nsAString* aValue)
- : EditTransactionBase()
- , mElement(&aElement)
- , mAttribute(&aAttribute)
- , mValue(aValue ? *aValue : EmptyString())
- , mRemoveAttribute(!aValue)
- , mAttributeWasSet(false)
- , mUndoValue()
-{
-}
-
-ChangeAttributeTransaction::~ChangeAttributeTransaction()
-{
-}
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(ChangeAttributeTransaction,
- EditTransactionBase,
- mElement)
-
-NS_IMPL_ADDREF_INHERITED(ChangeAttributeTransaction, EditTransactionBase)
-NS_IMPL_RELEASE_INHERITED(ChangeAttributeTransaction, EditTransactionBase)
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ChangeAttributeTransaction)
-NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
-
-NS_IMETHODIMP
-ChangeAttributeTransaction::DoTransaction()
-{
- // Need to get the current value of the attribute and save it, and set
- // mAttributeWasSet
- mAttributeWasSet = mElement->GetAttr(kNameSpaceID_None, mAttribute,
- mUndoValue);
-
- // XXX: hack until attribute-was-set code is implemented
- if (!mUndoValue.IsEmpty()) {
- mAttributeWasSet = true;
- }
- // XXX: end hack
-
- // Now set the attribute to the new value
- if (mRemoveAttribute) {
- return mElement->UnsetAttr(kNameSpaceID_None, mAttribute, true);
- }
-
- return mElement->SetAttr(kNameSpaceID_None, mAttribute, mValue, true);
-}
-
-NS_IMETHODIMP
-ChangeAttributeTransaction::UndoTransaction()
-{
- if (mAttributeWasSet) {
- return mElement->SetAttr(kNameSpaceID_None, mAttribute, mUndoValue, true);
- }
- return mElement->UnsetAttr(kNameSpaceID_None, mAttribute, true);
-}
-
-NS_IMETHODIMP
-ChangeAttributeTransaction::RedoTransaction()
-{
- if (mRemoveAttribute) {
- return mElement->UnsetAttr(kNameSpaceID_None, mAttribute, true);
- }
-
- return mElement->SetAttr(kNameSpaceID_None, mAttribute, mValue, true);
-}
-
-NS_IMETHODIMP
-ChangeAttributeTransaction::GetTxnDescription(nsAString& aString)
-{
- aString.AssignLiteral("ChangeAttributeTransaction: [mRemoveAttribute == ");
-
- if (mRemoveAttribute) {
- aString.AppendLiteral("true] ");
- } else {
- aString.AppendLiteral("false] ");
- }
- aString += nsDependentAtomString(mAttribute);
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/ChangeAttributeTransaction.h b/editor/libeditor/ChangeAttributeTransaction.h
deleted file mode 100644
index bb0c26c38..000000000
--- a/editor/libeditor/ChangeAttributeTransaction.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef ChangeAttributeTransaction_h
-#define ChangeAttributeTransaction_h
-
-#include "mozilla/Attributes.h" // override
-#include "mozilla/EditTransactionBase.h" // base class
-#include "nsCOMPtr.h" // nsCOMPtr members
-#include "nsCycleCollectionParticipant.h" // NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED
-#include "nsISupportsImpl.h" // NS_DECL_ISUPPORTS_INHERITED
-#include "nsString.h" // nsString members
-
-class nsIAtom;
-
-namespace mozilla {
-
-namespace dom {
-class Element;
-} // namespace dom
-
-/**
- * A transaction that changes an attribute of a content node. This transaction
- * covers add, remove, and change attribute.
- */
-class ChangeAttributeTransaction final : public EditTransactionBase
-{
-public:
- /**
- * @param aElement the element whose attribute will be changed
- * @param aAttribute the name of the attribute to change
- * @param aValue the new value for aAttribute, or null to remove
- */
- ChangeAttributeTransaction(dom::Element& aElement,
- nsIAtom& aAttribute,
- const nsAString* aValue);
-
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ChangeAttributeTransaction,
- EditTransactionBase)
-
- NS_DECL_EDITTRANSACTIONBASE
-
- NS_IMETHOD RedoTransaction() override;
-
-private:
- virtual ~ChangeAttributeTransaction();
-
- // The element to operate upon
- nsCOMPtr<dom::Element> mElement;
-
- // The attribute to change
- nsCOMPtr<nsIAtom> mAttribute;
-
- // The value to set the attribute to (ignored if mRemoveAttribute==true)
- nsString mValue;
-
- // True if the operation is to remove mAttribute from mElement
- bool mRemoveAttribute;
-
- // True if the mAttribute was set on mElement at the time of execution
- bool mAttributeWasSet;
-
- // The value to set the attribute to for undo
- nsString mUndoValue;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef ChangeAttributeTransaction_h
diff --git a/editor/libeditor/ChangeStyleTransaction.cpp b/editor/libeditor/ChangeStyleTransaction.cpp
deleted file mode 100644
index 103d9c455..000000000
--- a/editor/libeditor/ChangeStyleTransaction.cpp
+++ /dev/null
@@ -1,287 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/ChangeStyleTransaction.h"
-
-#include "mozilla/dom/Element.h" // for Element
-#include "nsAString.h" // for nsAString_internal::Append, etc.
-#include "nsCRT.h" // for nsCRT::IsAsciiSpace
-#include "nsDebug.h" // for NS_ENSURE_SUCCESS, etc.
-#include "nsError.h" // for NS_ERROR_NULL_POINTER, etc.
-#include "nsGkAtoms.h" // for nsGkAtoms, etc.
-#include "nsICSSDeclaration.h" // for nsICSSDeclaration.
-#include "nsLiteralString.h" // for NS_LITERAL_STRING, etc.
-#include "nsReadableUtils.h" // for ToNewUnicode
-#include "nsString.h" // for nsAutoString, nsString, etc.
-#include "nsStyledElement.h" // for nsStyledElement.
-#include "nsUnicharUtils.h" // for nsCaseInsensitiveStringComparator
-
-namespace mozilla {
-
-using namespace dom;
-
-#define kNullCh (char16_t('\0'))
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(ChangeStyleTransaction, EditTransactionBase,
- mElement)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ChangeStyleTransaction)
-NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
-
-NS_IMPL_ADDREF_INHERITED(ChangeStyleTransaction, EditTransactionBase)
-NS_IMPL_RELEASE_INHERITED(ChangeStyleTransaction, EditTransactionBase)
-
-ChangeStyleTransaction::~ChangeStyleTransaction()
-{
-}
-
-// Answers true if aValue is in the string list of white-space separated values
-// aValueList.
-bool
-ChangeStyleTransaction::ValueIncludes(const nsAString& aValueList,
- const nsAString& aValue)
-{
- nsAutoString valueList(aValueList);
- bool result = false;
-
- // put an extra null at the end
- valueList.Append(kNullCh);
-
- char16_t* value = ToNewUnicode(aValue);
- char16_t* start = valueList.BeginWriting();
- char16_t* end = start;
-
- while (kNullCh != *start) {
- while (kNullCh != *start && nsCRT::IsAsciiSpace(*start)) {
- // skip leading space
- start++;
- }
- end = start;
-
- while (kNullCh != *end && !nsCRT::IsAsciiSpace(*end)) {
- // look for space or end
- end++;
- }
- // end string here
- *end = kNullCh;
-
- if (start < end) {
- if (nsDependentString(value).Equals(nsDependentString(start),
- nsCaseInsensitiveStringComparator())) {
- result = true;
- break;
- }
- }
- start = ++end;
- }
- free(value);
- return result;
-}
-
-// Removes the value aRemoveValue from the string list of white-space separated
-// values aValueList
-void
-ChangeStyleTransaction::RemoveValueFromListOfValues(
- nsAString& aValues,
- const nsAString& aRemoveValue)
-{
- nsAutoString classStr(aValues);
- nsAutoString outString;
- // put an extra null at the end
- classStr.Append(kNullCh);
-
- char16_t* start = classStr.BeginWriting();
- char16_t* end = start;
-
- while (kNullCh != *start) {
- while (kNullCh != *start && nsCRT::IsAsciiSpace(*start)) {
- // skip leading space
- start++;
- }
- end = start;
-
- while (kNullCh != *end && !nsCRT::IsAsciiSpace(*end)) {
- // look for space or end
- end++;
- }
- // end string here
- *end = kNullCh;
-
- if (start < end && !aRemoveValue.Equals(start)) {
- outString.Append(start);
- outString.Append(char16_t(' '));
- }
-
- start = ++end;
- }
- aValues.Assign(outString);
-}
-
-ChangeStyleTransaction::ChangeStyleTransaction(Element& aElement,
- nsIAtom& aProperty,
- const nsAString& aValue,
- EChangeType aChangeType)
- : EditTransactionBase()
- , mElement(&aElement)
- , mProperty(&aProperty)
- , mValue(aValue)
- , mRemoveProperty(aChangeType == eRemove)
- , mUndoValue()
- , mRedoValue()
- , mUndoAttributeWasSet(false)
- , mRedoAttributeWasSet(false)
-{
-}
-
-NS_IMETHODIMP
-ChangeStyleTransaction::DoTransaction()
-{
- nsCOMPtr<nsStyledElement> inlineStyles = do_QueryInterface(mElement);
- NS_ENSURE_TRUE(inlineStyles, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsICSSDeclaration> cssDecl = inlineStyles->Style();
-
- nsAutoString propertyNameString;
- mProperty->ToString(propertyNameString);
-
- mUndoAttributeWasSet = mElement->HasAttr(kNameSpaceID_None,
- nsGkAtoms::style);
-
- nsAutoString values;
- nsresult rv = cssDecl->GetPropertyValue(propertyNameString, values);
- NS_ENSURE_SUCCESS(rv, rv);
- mUndoValue.Assign(values);
-
- // Does this property accept more than one value? (bug 62682)
- bool multiple = AcceptsMoreThanOneValue(*mProperty);
-
- if (mRemoveProperty) {
- nsAutoString returnString;
- if (multiple) {
- // Let's remove only the value we have to remove and not the others
-
- // The two lines below are a workaround because
- // nsDOMCSSDeclaration::GetPropertyCSSValue is not yet implemented (bug
- // 62682)
- RemoveValueFromListOfValues(values, NS_LITERAL_STRING("none"));
- RemoveValueFromListOfValues(values, mValue);
- if (values.IsEmpty()) {
- rv = cssDecl->RemoveProperty(propertyNameString, returnString);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- nsAutoString priority;
- cssDecl->GetPropertyPriority(propertyNameString, priority);
- rv = cssDecl->SetProperty(propertyNameString, values, priority);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- } else {
- rv = cssDecl->RemoveProperty(propertyNameString, returnString);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- } else {
- nsAutoString priority;
- cssDecl->GetPropertyPriority(propertyNameString, priority);
- if (multiple) {
- // Let's add the value we have to add to the others
-
- // The line below is a workaround because
- // nsDOMCSSDeclaration::GetPropertyCSSValue is not yet implemented (bug
- // 62682)
- AddValueToMultivalueProperty(values, mValue);
- } else {
- values.Assign(mValue);
- }
- rv = cssDecl->SetProperty(propertyNameString, values, priority);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // Let's be sure we don't keep an empty style attribute
- uint32_t length;
- rv = cssDecl->GetLength(&length);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!length) {
- rv = mElement->UnsetAttr(kNameSpaceID_None, nsGkAtoms::style, true);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- mRedoAttributeWasSet = true;
- }
-
- return cssDecl->GetPropertyValue(propertyNameString, mRedoValue);
-}
-
-nsresult
-ChangeStyleTransaction::SetStyle(bool aAttributeWasSet,
- nsAString& aValue)
-{
- if (aAttributeWasSet) {
- // The style attribute was not empty, let's recreate the declaration
- nsAutoString propertyNameString;
- mProperty->ToString(propertyNameString);
-
- nsCOMPtr<nsStyledElement> inlineStyles = do_QueryInterface(mElement);
- NS_ENSURE_TRUE(inlineStyles, NS_ERROR_NULL_POINTER);
- nsCOMPtr<nsICSSDeclaration> cssDecl = inlineStyles->Style();
-
- if (aValue.IsEmpty()) {
- // An empty value means we have to remove the property
- nsAutoString returnString;
- return cssDecl->RemoveProperty(propertyNameString, returnString);
- }
- // Let's recreate the declaration as it was
- nsAutoString priority;
- cssDecl->GetPropertyPriority(propertyNameString, priority);
- return cssDecl->SetProperty(propertyNameString, aValue, priority);
- }
- return mElement->UnsetAttr(kNameSpaceID_None, nsGkAtoms::style, true);
-}
-
-NS_IMETHODIMP
-ChangeStyleTransaction::UndoTransaction()
-{
- return SetStyle(mUndoAttributeWasSet, mUndoValue);
-}
-
-NS_IMETHODIMP
-ChangeStyleTransaction::RedoTransaction()
-{
- return SetStyle(mRedoAttributeWasSet, mRedoValue);
-}
-
-NS_IMETHODIMP
-ChangeStyleTransaction::GetTxnDescription(nsAString& aString)
-{
- aString.AssignLiteral("ChangeStyleTransaction: [mRemoveProperty == ");
-
- if (mRemoveProperty) {
- aString.AppendLiteral("true] ");
- } else {
- aString.AppendLiteral("false] ");
- }
- aString += nsDependentAtomString(mProperty);
- return NS_OK;
-}
-
-// True if the CSS property accepts more than one value
-bool
-ChangeStyleTransaction::AcceptsMoreThanOneValue(nsIAtom& aCSSProperty)
-{
- return &aCSSProperty == nsGkAtoms::text_decoration;
-}
-
-// Adds the value aNewValue to the list of white-space separated values aValues
-void
-ChangeStyleTransaction::AddValueToMultivalueProperty(nsAString& aValues,
- const nsAString& aNewValue)
-{
- if (aValues.IsEmpty() || aValues.LowerCaseEqualsLiteral("none")) {
- aValues.Assign(aNewValue);
- } else if (!ValueIncludes(aValues, aNewValue)) {
- // We already have another value but not this one; add it
- aValues.Append(char16_t(' '));
- aValues.Append(aNewValue);
- }
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/ChangeStyleTransaction.h b/editor/libeditor/ChangeStyleTransaction.h
deleted file mode 100644
index 14c2cdcb5..000000000
--- a/editor/libeditor/ChangeStyleTransaction.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_ChangeStyleTransaction_h
-#define mozilla_ChangeStyleTransaction_h
-
-#include "mozilla/EditTransactionBase.h" // base class
-#include "nsCOMPtr.h" // nsCOMPtr members
-#include "nsCycleCollectionParticipant.h" // various macros
-#include "nsString.h" // nsString members
-
-class nsAString;
-class nsIAtom;
-
-namespace mozilla {
-
-namespace dom {
-class Element;
-} // namespace dom
-
-/**
- * A transaction that changes the value of a CSS inline style of a content
- * node. This transaction covers add, remove, and change a property's value.
- */
-class ChangeStyleTransaction final : public EditTransactionBase
-{
-public:
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ChangeStyleTransaction,
- EditTransactionBase)
-
- NS_DECL_ISUPPORTS_INHERITED
-
- NS_DECL_EDITTRANSACTIONBASE
-
- NS_IMETHOD RedoTransaction() override;
-
- enum EChangeType { eSet, eRemove };
-
- /**
- * @param aNode [IN] the node whose style attribute will be changed
- * @param aProperty [IN] the name of the property to change
- * @param aValue [IN] new value for aProperty, or value to remove
- * @param aChangeType [IN] whether to set or remove
- */
- ChangeStyleTransaction(dom::Element& aElement,
- nsIAtom& aProperty,
- const nsAString& aValue,
- EChangeType aChangeType);
-
- /**
- * Returns true if the list of white-space separated values contains aValue
- *
- * @param aValueList [IN] a list of white-space separated values
- * @param aValue [IN] the value to look for in the list
- * @return true if the value is in the list of values
- */
- static bool ValueIncludes(const nsAString& aValueList,
- const nsAString& aValue);
-
-private:
- virtual ~ChangeStyleTransaction();
-
- /*
- * Adds the value aNewValue to list of white-space separated values aValues.
- *
- * @param aValues [IN/OUT] a list of wite-space separated values
- * @param aNewValue [IN] a value this code adds to aValues if it is not
- * already in
- */
- void AddValueToMultivalueProperty(nsAString& aValues,
- const nsAString& aNewValue);
-
- /**
- * Returns true if the property accepts more than one value.
- *
- * @param aCSSProperty [IN] the CSS property
- * @return true if the property accepts more than one value
- */
- bool AcceptsMoreThanOneValue(nsIAtom& aCSSProperty);
-
- /**
- * Remove a value from a list of white-space separated values.
- * @param aValues [IN] a list of white-space separated values
- * @param aRemoveValue [IN] the value to remove from the list
- */
- void RemoveValueFromListOfValues(nsAString& aValues,
- const nsAString& aRemoveValue);
-
- /**
- * If the boolean is true and if the value is not the empty string,
- * set the property in the transaction to that value; if the value
- * is empty, remove the property from element's styles. If the boolean
- * is false, just remove the style attribute.
- */
- nsresult SetStyle(bool aAttributeWasSet, nsAString& aValue);
-
- // The element to operate upon.
- nsCOMPtr<dom::Element> mElement;
-
- // The CSS property to change.
- nsCOMPtr<nsIAtom> mProperty;
-
- // The value to set the property to (ignored if mRemoveProperty==true).
- nsString mValue;
-
- // true if the operation is to remove mProperty from mElement.
- bool mRemoveProperty;
-
- // The value to set the property to for undo.
- nsString mUndoValue;
- // The value to set the property to for redo.
- nsString mRedoValue;
- // True if the style attribute was present and not empty before DoTransaction.
- bool mUndoAttributeWasSet;
- // True if the style attribute is present and not empty after DoTransaction.
- bool mRedoAttributeWasSet;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef mozilla_ChangeStyleTransaction_h
diff --git a/editor/libeditor/CompositionTransaction.cpp b/editor/libeditor/CompositionTransaction.cpp
deleted file mode 100644
index bde53d2e5..000000000
--- a/editor/libeditor/CompositionTransaction.cpp
+++ /dev/null
@@ -1,344 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "CompositionTransaction.h"
-
-#include "mozilla/EditorBase.h" // mEditorBase
-#include "mozilla/SelectionState.h" // RangeUpdater
-#include "mozilla/dom/Selection.h" // local var
-#include "mozilla/dom/Text.h" // mTextNode
-#include "nsAString.h" // params
-#include "nsDebug.h" // for NS_ASSERTION, etc
-#include "nsError.h" // for NS_SUCCEEDED, NS_FAILED, etc
-#include "nsIPresShell.h" // nsISelectionController constants
-#include "nsRange.h" // local var
-#include "nsQueryObject.h" // for do_QueryObject
-
-namespace mozilla {
-
-using namespace dom;
-
-CompositionTransaction::CompositionTransaction(
- Text& aTextNode,
- uint32_t aOffset,
- uint32_t aReplaceLength,
- TextRangeArray* aTextRangeArray,
- const nsAString& aStringToInsert,
- EditorBase& aEditorBase,
- RangeUpdater* aRangeUpdater)
- : mTextNode(&aTextNode)
- , mOffset(aOffset)
- , mReplaceLength(aReplaceLength)
- , mRanges(aTextRangeArray)
- , mStringToInsert(aStringToInsert)
- , mEditorBase(&aEditorBase)
- , mRangeUpdater(aRangeUpdater)
- , mFixed(false)
-{
- MOZ_ASSERT(mTextNode->TextLength() >= mOffset);
-}
-
-CompositionTransaction::~CompositionTransaction()
-{
-}
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(CompositionTransaction, EditTransactionBase,
- mEditorBase,
- mTextNode)
-// mRangeList can't lead to cycles
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CompositionTransaction)
- if (aIID.Equals(NS_GET_IID(CompositionTransaction))) {
- foundInterface = static_cast<nsITransaction*>(this);
- } else
-NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
-
-NS_IMPL_ADDREF_INHERITED(CompositionTransaction, EditTransactionBase)
-NS_IMPL_RELEASE_INHERITED(CompositionTransaction, EditTransactionBase)
-
-NS_IMETHODIMP
-CompositionTransaction::DoTransaction()
-{
- if (NS_WARN_IF(!mEditorBase)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // Fail before making any changes if there's no selection controller
- nsCOMPtr<nsISelectionController> selCon;
- mEditorBase->GetSelectionController(getter_AddRefs(selCon));
- NS_ENSURE_TRUE(selCon, NS_ERROR_NOT_INITIALIZED);
-
- // Advance caret: This requires the presentation shell to get the selection.
- if (mReplaceLength == 0) {
- nsresult rv = mTextNode->InsertData(mOffset, mStringToInsert);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- mRangeUpdater->SelAdjInsertText(*mTextNode, mOffset, mStringToInsert);
- } else {
- uint32_t replaceableLength = mTextNode->TextLength() - mOffset;
- nsresult rv =
- mTextNode->ReplaceData(mOffset, mReplaceLength, mStringToInsert);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- mRangeUpdater->SelAdjDeleteText(mTextNode, mOffset, mReplaceLength);
- mRangeUpdater->SelAdjInsertText(*mTextNode, mOffset, mStringToInsert);
-
- // If IME text node is multiple node, ReplaceData doesn't remove all IME
- // text. So we need remove remained text into other text node.
- if (replaceableLength < mReplaceLength) {
- int32_t remainLength = mReplaceLength - replaceableLength;
- nsCOMPtr<nsINode> node = mTextNode->GetNextSibling();
- while (node && node->IsNodeOfType(nsINode::eTEXT) &&
- remainLength > 0) {
- Text* text = static_cast<Text*>(node.get());
- uint32_t textLength = text->TextLength();
- text->DeleteData(0, remainLength);
- mRangeUpdater->SelAdjDeleteText(text, 0, remainLength);
- remainLength -= textLength;
- node = node->GetNextSibling();
- }
- }
- }
-
- nsresult rv = SetSelectionForRanges();
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-CompositionTransaction::UndoTransaction()
-{
- if (NS_WARN_IF(!mEditorBase)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // Get the selection first so we'll fail before making any changes if we
- // can't get it
- RefPtr<Selection> selection = mEditorBase->GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
-
- nsresult rv = mTextNode->DeleteData(mOffset, mStringToInsert.Length());
- NS_ENSURE_SUCCESS(rv, rv);
-
- // set the selection to the insertion point where the string was removed
- rv = selection->Collapse(mTextNode, mOffset);
- NS_ASSERTION(NS_SUCCEEDED(rv),
- "Selection could not be collapsed after undo of IME insert.");
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-CompositionTransaction::Merge(nsITransaction* aTransaction,
- bool* aDidMerge)
-{
- NS_ENSURE_ARG_POINTER(aTransaction && aDidMerge);
-
- // Check to make sure we aren't fixed, if we are then nothing gets absorbed
- if (mFixed) {
- *aDidMerge = false;
- return NS_OK;
- }
-
- // If aTransaction is another CompositionTransaction then absorb it
- RefPtr<CompositionTransaction> otherTransaction =
- do_QueryObject(aTransaction);
- if (otherTransaction) {
- // We absorb the next IME transaction by adopting its insert string
- mStringToInsert = otherTransaction->mStringToInsert;
- mRanges = otherTransaction->mRanges;
- *aDidMerge = true;
- return NS_OK;
- }
-
- *aDidMerge = false;
- return NS_OK;
-}
-
-void
-CompositionTransaction::MarkFixed()
-{
- mFixed = true;
-}
-
-NS_IMETHODIMP
-CompositionTransaction::GetTxnDescription(nsAString& aString)
-{
- aString.AssignLiteral("CompositionTransaction: ");
- aString += mStringToInsert;
- return NS_OK;
-}
-
-/* ============ private methods ================== */
-
-nsresult
-CompositionTransaction::SetSelectionForRanges()
-{
- if (NS_WARN_IF(!mEditorBase)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- return SetIMESelection(*mEditorBase, mTextNode, mOffset,
- mStringToInsert.Length(), mRanges);
-}
-
-// static
-nsresult
-CompositionTransaction::SetIMESelection(EditorBase& aEditorBase,
- Text* aTextNode,
- uint32_t aOffsetInNode,
- uint32_t aLengthOfCompositionString,
- const TextRangeArray* aRanges)
-{
- RefPtr<Selection> selection = aEditorBase.GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
-
- nsresult rv = selection->StartBatchChanges();
- NS_ENSURE_SUCCESS(rv, rv);
-
- // First, remove all selections of IME composition.
- static const RawSelectionType kIMESelections[] = {
- nsISelectionController::SELECTION_IME_RAWINPUT,
- nsISelectionController::SELECTION_IME_SELECTEDRAWTEXT,
- nsISelectionController::SELECTION_IME_CONVERTEDTEXT,
- nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT
- };
-
- nsCOMPtr<nsISelectionController> selCon;
- aEditorBase.GetSelectionController(getter_AddRefs(selCon));
- NS_ENSURE_TRUE(selCon, NS_ERROR_NOT_INITIALIZED);
-
- for (uint32_t i = 0; i < ArrayLength(kIMESelections); ++i) {
- nsCOMPtr<nsISelection> selectionOfIME;
- if (NS_FAILED(selCon->GetSelection(kIMESelections[i],
- getter_AddRefs(selectionOfIME)))) {
- continue;
- }
- rv = selectionOfIME->RemoveAllRanges();
- NS_ASSERTION(NS_SUCCEEDED(rv),
- "Failed to remove all ranges of IME selection");
- }
-
- // Set caret position and selection of IME composition with TextRangeArray.
- bool setCaret = false;
- uint32_t countOfRanges = aRanges ? aRanges->Length() : 0;
-
-#ifdef DEBUG
- // Bounds-checking on debug builds
- uint32_t maxOffset = aTextNode->Length();
-#endif
-
- // NOTE: composition string may be truncated when it's committed and
- // maxlength attribute value doesn't allow input of all text of this
- // composition.
- for (uint32_t i = 0; i < countOfRanges; ++i) {
- const TextRange& textRange = aRanges->ElementAt(i);
-
- // Caret needs special handling since its length may be 0 and if it's not
- // specified explicitly, we need to handle it ourselves later.
- if (textRange.mRangeType == TextRangeType::eCaret) {
- NS_ASSERTION(!setCaret, "The ranges already has caret position");
- NS_ASSERTION(!textRange.Length(),
- "EditorBase doesn't support wide caret");
- int32_t caretOffset = static_cast<int32_t>(
- aOffsetInNode +
- std::min(textRange.mStartOffset, aLengthOfCompositionString));
- MOZ_ASSERT(caretOffset >= 0 &&
- static_cast<uint32_t>(caretOffset) <= maxOffset);
- rv = selection->Collapse(aTextNode, caretOffset);
- setCaret = setCaret || NS_SUCCEEDED(rv);
- if (NS_WARN_IF(!setCaret)) {
- continue;
- }
- // If caret range is specified explicitly, we should show the caret if
- // it should be so.
- aEditorBase.HideCaret(false);
- continue;
- }
-
- // If the clause length is 0, it should be a bug.
- if (!textRange.Length()) {
- NS_WARNING("Any clauses must not be empty");
- continue;
- }
-
- RefPtr<nsRange> clauseRange;
- int32_t startOffset = static_cast<int32_t>(
- aOffsetInNode +
- std::min(textRange.mStartOffset, aLengthOfCompositionString));
- MOZ_ASSERT(startOffset >= 0 &&
- static_cast<uint32_t>(startOffset) <= maxOffset);
- int32_t endOffset = static_cast<int32_t>(
- aOffsetInNode +
- std::min(textRange.mEndOffset, aLengthOfCompositionString));
- MOZ_ASSERT(endOffset >= startOffset &&
- static_cast<uint32_t>(endOffset) <= maxOffset);
- rv = nsRange::CreateRange(aTextNode, startOffset,
- aTextNode, endOffset,
- getter_AddRefs(clauseRange));
- if (NS_FAILED(rv)) {
- NS_WARNING("Failed to create a DOM range for a clause of composition");
- break;
- }
-
- // Set the range of the clause to selection.
- nsCOMPtr<nsISelection> selectionOfIME;
- rv = selCon->GetSelection(ToRawSelectionType(textRange.mRangeType),
- getter_AddRefs(selectionOfIME));
- if (NS_FAILED(rv)) {
- NS_WARNING("Failed to get IME selection");
- break;
- }
-
- rv = selectionOfIME->AddRange(clauseRange);
- if (NS_FAILED(rv)) {
- NS_WARNING("Failed to add selection range for a clause of composition");
- break;
- }
-
- // Set the style of the clause.
- nsCOMPtr<nsISelectionPrivate> selectionOfIMEPriv =
- do_QueryInterface(selectionOfIME);
- if (!selectionOfIMEPriv) {
- NS_WARNING("Failed to get nsISelectionPrivate interface from selection");
- continue; // Since this is additional feature, we can continue this job.
- }
- rv = selectionOfIMEPriv->SetTextRangeStyle(clauseRange,
- textRange.mRangeStyle);
- if (NS_FAILED(rv)) {
- NS_WARNING("Failed to set selection style");
- break; // but this is unexpected...
- }
- }
-
- // If the ranges doesn't include explicit caret position, let's set the
- // caret to the end of composition string.
- if (!setCaret) {
- int32_t caretOffset =
- static_cast<int32_t>(aOffsetInNode + aLengthOfCompositionString);
- MOZ_ASSERT(caretOffset >= 0 &&
- static_cast<uint32_t>(caretOffset) <= maxOffset);
- rv = selection->Collapse(aTextNode, caretOffset);
- NS_ASSERTION(NS_SUCCEEDED(rv),
- "Failed to set caret at the end of composition string");
-
- // If caret range isn't specified explicitly, we should hide the caret.
- // Hiding the caret benefits a Windows build (see bug 555642 comment #6).
- // However, when there is no range, we should keep showing caret.
- if (countOfRanges) {
- aEditorBase.HideCaret(true);
- }
- }
-
- rv = selection->EndBatchChangesInternal();
- NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to end batch changes");
-
- return rv;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/CompositionTransaction.h b/editor/libeditor/CompositionTransaction.h
deleted file mode 100644
index c2134bedd..000000000
--- a/editor/libeditor/CompositionTransaction.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef CompositionTransaction_h
-#define CompositionTransaction_h
-
-#include "mozilla/EditTransactionBase.h" // base class
-#include "nsCycleCollectionParticipant.h" // various macros
-#include "nsString.h" // mStringToInsert
-
-#define NS_IMETEXTTXN_IID \
- { 0xb391355d, 0x346c, 0x43d1, \
- { 0x85, 0xed, 0x9e, 0x65, 0xbe, 0xe7, 0x7e, 0x48 } }
-
-namespace mozilla {
-
-class EditorBase;
-class RangeUpdater;
-class TextRangeArray;
-
-namespace dom {
-class Text;
-} // namespace dom
-
-/**
- * CompositionTransaction stores all edit for a composition, i.e.,
- * from compositionstart event to compositionend event. E.g., inserting a
- * composition string, modifying the composition string or its IME selection
- * ranges and commit or cancel the composition.
- */
-class CompositionTransaction final : public EditTransactionBase
-{
-public:
- NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMETEXTTXN_IID)
-
- /**
- * @param aTextNode The start node of text content.
- * @param aOffset The location in aTextNode to do the insertion.
- * @param aReplaceLength The length of text to replace. 0 means not
- * replacing existing text.
- * @param aTextRangeArray Clauses and/or caret information. This may be
- * null.
- * @param aString The new text to insert.
- * @param aEditorBase Used to get and set the selection.
- * @param aRangeUpdater The range updater
- */
- CompositionTransaction(dom::Text& aTextNode,
- uint32_t aOffset, uint32_t aReplaceLength,
- TextRangeArray* aTextRangeArray,
- const nsAString& aString,
- EditorBase& aEditorBase,
- RangeUpdater* aRangeUpdater);
-
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CompositionTransaction,
- EditTransactionBase)
-
- NS_DECL_ISUPPORTS_INHERITED
-
- NS_DECL_EDITTRANSACTIONBASE
-
- NS_IMETHOD Merge(nsITransaction* aTransaction, bool* aDidMerge) override;
-
- void MarkFixed();
-
- static nsresult SetIMESelection(EditorBase& aEditorBase,
- dom::Text* aTextNode,
- uint32_t aOffsetInNode,
- uint32_t aLengthOfCompositionString,
- const TextRangeArray* aRanges);
-
-private:
- ~CompositionTransaction();
-
- nsresult SetSelectionForRanges();
-
- // The text element to operate upon.
- RefPtr<dom::Text> mTextNode;
-
- // The offsets into mTextNode where the insertion should be placed.
- uint32_t mOffset;
-
- uint32_t mReplaceLength;
-
- // The range list.
- RefPtr<TextRangeArray> mRanges;
-
- // The text to insert into mTextNode at mOffset.
- nsString mStringToInsert;
-
- // The editor, which is used to get the selection controller.
- RefPtr<EditorBase> mEditorBase;
-
- RangeUpdater* mRangeUpdater;
-
- bool mFixed;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(CompositionTransaction, NS_IMETEXTTXN_IID)
-
-} // namespace mozilla
-
-#endif // #ifndef CompositionTransaction_h
diff --git a/editor/libeditor/CreateElementTransaction.cpp b/editor/libeditor/CreateElementTransaction.cpp
deleted file mode 100644
index 5e2b9e1ad..000000000
--- a/editor/libeditor/CreateElementTransaction.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "CreateElementTransaction.h"
-
-#include <algorithm>
-#include <stdio.h>
-
-#include "mozilla/dom/Element.h"
-#include "mozilla/dom/Selection.h"
-
-#include "mozilla/Casting.h"
-#include "mozilla/EditorBase.h"
-
-#include "nsAlgorithm.h"
-#include "nsAString.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsIContent.h"
-#include "nsIDOMCharacterData.h"
-#include "nsIEditor.h"
-#include "nsINode.h"
-#include "nsISupportsUtils.h"
-#include "nsMemory.h"
-#include "nsReadableUtils.h"
-#include "nsStringFwd.h"
-#include "nsString.h"
-
-namespace mozilla {
-
-using namespace dom;
-
-CreateElementTransaction::CreateElementTransaction(EditorBase& aEditorBase,
- nsIAtom& aTag,
- nsINode& aParent,
- int32_t aOffsetInParent)
- : EditTransactionBase()
- , mEditorBase(&aEditorBase)
- , mTag(&aTag)
- , mParent(&aParent)
- , mOffsetInParent(aOffsetInParent)
-{
-}
-
-CreateElementTransaction::~CreateElementTransaction()
-{
-}
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(CreateElementTransaction,
- EditTransactionBase,
- mEditorBase,
- mParent,
- mNewNode,
- mRefNode)
-
-NS_IMPL_ADDREF_INHERITED(CreateElementTransaction, EditTransactionBase)
-NS_IMPL_RELEASE_INHERITED(CreateElementTransaction, EditTransactionBase)
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CreateElementTransaction)
-NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
-
-
-NS_IMETHODIMP
-CreateElementTransaction::DoTransaction()
-{
- if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTag) || NS_WARN_IF(!mParent)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- mNewNode = mEditorBase->CreateHTMLContent(mTag);
- NS_ENSURE_STATE(mNewNode);
-
- // Try to insert formatting whitespace for the new node:
- mEditorBase->MarkNodeDirty(GetAsDOMNode(mNewNode));
-
- // Insert the new node
- ErrorResult rv;
- if (mOffsetInParent == -1) {
- mParent->AppendChild(*mNewNode, rv);
- return rv.StealNSResult();
- }
-
- mOffsetInParent = std::min(mOffsetInParent,
- static_cast<int32_t>(mParent->GetChildCount()));
-
- // Note, it's ok for mRefNode to be null. That means append
- mRefNode = mParent->GetChildAt(mOffsetInParent);
-
- nsCOMPtr<nsIContent> refNode = mRefNode;
- mParent->InsertBefore(*mNewNode, refNode, rv);
- NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult());
-
- // Only set selection to insertion point if editor gives permission
- if (!mEditorBase->GetShouldTxnSetSelection()) {
- // Do nothing - DOM range gravity will adjust selection
- return NS_OK;
- }
-
- RefPtr<Selection> selection = mEditorBase->GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- rv = selection->CollapseNative(mParent, mParent->IndexOf(mNewNode) + 1);
- NS_ASSERTION(!rv.Failed(),
- "selection could not be collapsed after insert");
- return NS_OK;
-}
-
-NS_IMETHODIMP
-CreateElementTransaction::UndoTransaction()
-{
- if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mParent)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- ErrorResult rv;
- mParent->RemoveChild(*mNewNode, rv);
-
- return rv.StealNSResult();
-}
-
-NS_IMETHODIMP
-CreateElementTransaction::RedoTransaction()
-{
- if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mParent)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // First, reset mNewNode so it has no attributes or content
- // XXX We never actually did this, we only cleared mNewNode's contents if it
- // was a CharacterData node (which it's not, it's an Element)
-
- // Now, reinsert mNewNode
- ErrorResult rv;
- nsCOMPtr<nsIContent> refNode = mRefNode;
- mParent->InsertBefore(*mNewNode, refNode, rv);
- return rv.StealNSResult();
-}
-
-NS_IMETHODIMP
-CreateElementTransaction::GetTxnDescription(nsAString& aString)
-{
- aString.AssignLiteral("CreateElementTransaction: ");
- aString += nsDependentAtomString(mTag);
- return NS_OK;
-}
-
-already_AddRefed<Element>
-CreateElementTransaction::GetNewNode()
-{
- return nsCOMPtr<Element>(mNewNode).forget();
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/CreateElementTransaction.h b/editor/libeditor/CreateElementTransaction.h
deleted file mode 100644
index fd5abb8a8..000000000
--- a/editor/libeditor/CreateElementTransaction.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef CreateElementTransaction_h
-#define CreateElementTransaction_h
-
-#include "mozilla/EditTransactionBase.h"
-#include "nsCOMPtr.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsISupportsImpl.h"
-
-class nsIAtom;
-class nsIContent;
-class nsINode;
-
-/**
- * A transaction that creates a new node in the content tree.
- */
-namespace mozilla {
-
-class EditorBase;
-namespace dom {
-class Element;
-} // namespace dom
-
-class CreateElementTransaction final : public EditTransactionBase
-{
-public:
- /**
- * Initialize the transaction.
- * @param aEditorBase The provider of basic editing functionality.
- * @param aTag The tag (P, HR, TABLE, etc.) for the new element.
- * @param aParent The node into which the new element will be
- * inserted.
- * @param aOffsetInParent The location in aParent to insert the new element.
- * If eAppend, the new element is appended as the last
- * child.
- */
- CreateElementTransaction(EditorBase& aEditorBase,
- nsIAtom& aTag,
- nsINode& aParent,
- int32_t aOffsetInParent);
-
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CreateElementTransaction,
- EditTransactionBase)
-
- NS_DECL_EDITTRANSACTIONBASE
-
- NS_IMETHOD RedoTransaction() override;
-
- already_AddRefed<dom::Element> GetNewNode();
-
-protected:
- virtual ~CreateElementTransaction();
-
- // The document into which the new node will be inserted.
- RefPtr<EditorBase> mEditorBase;
-
- // The tag (mapping to object type) for the new element.
- nsCOMPtr<nsIAtom> mTag;
-
- // The node into which the new node will be inserted.
- nsCOMPtr<nsINode> mParent;
-
- // The index in mParent for the new node.
- int32_t mOffsetInParent;
-
- // The new node to insert.
- nsCOMPtr<dom::Element> mNewNode;
-
- // The node we will insert mNewNode before. We compute this ourselves.
- nsCOMPtr<nsIContent> mRefNode;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef CreateElementTransaction_h
diff --git a/editor/libeditor/DeleteNodeTransaction.cpp b/editor/libeditor/DeleteNodeTransaction.cpp
deleted file mode 100644
index ae9951e28..000000000
--- a/editor/libeditor/DeleteNodeTransaction.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "DeleteNodeTransaction.h"
-#include "mozilla/EditorBase.h"
-#include "mozilla/SelectionState.h" // RangeUpdater
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsAString.h"
-
-namespace mozilla {
-
-DeleteNodeTransaction::DeleteNodeTransaction()
- : mEditorBase(nullptr)
- , mRangeUpdater(nullptr)
-{
-}
-
-DeleteNodeTransaction::~DeleteNodeTransaction()
-{
-}
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(DeleteNodeTransaction, EditTransactionBase,
- mEditorBase,
- mNode,
- mParent,
- mRefNode)
-
-NS_IMPL_ADDREF_INHERITED(DeleteNodeTransaction, EditTransactionBase)
-NS_IMPL_RELEASE_INHERITED(DeleteNodeTransaction, EditTransactionBase)
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeleteNodeTransaction)
-NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
-
-nsresult
-DeleteNodeTransaction::Init(EditorBase* aEditorBase,
- nsINode* aNode,
- RangeUpdater* aRangeUpdater)
-{
- NS_ENSURE_TRUE(aEditorBase && aNode, NS_ERROR_NULL_POINTER);
- mEditorBase = aEditorBase;
- mNode = aNode;
- mParent = aNode->GetParentNode();
-
- // do nothing if the node has a parent and it's read-only
- NS_ENSURE_TRUE(!mParent || mEditorBase->IsModifiableNode(mParent),
- NS_ERROR_FAILURE);
-
- mRangeUpdater = aRangeUpdater;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-DeleteNodeTransaction::DoTransaction()
-{
- NS_ENSURE_TRUE(mNode, NS_ERROR_NOT_INITIALIZED);
-
- if (!mParent) {
- // this is a no-op, there's no parent to delete mNode from
- return NS_OK;
- }
-
- // remember which child mNode was (by remembering which child was next);
- // mRefNode can be null
- mRefNode = mNode->GetNextSibling();
-
- // give range updater a chance. SelAdjDeleteNode() needs to be called
- // *before* we do the action, unlike some of the other RangeItem update
- // methods.
- if (mRangeUpdater) {
- mRangeUpdater->SelAdjDeleteNode(mNode->AsDOMNode());
- }
-
- ErrorResult error;
- mParent->RemoveChild(*mNode, error);
- return error.StealNSResult();
-}
-
-NS_IMETHODIMP
-DeleteNodeTransaction::UndoTransaction()
-{
- if (!mParent) {
- // this is a legal state, the txn is a no-op
- return NS_OK;
- }
- if (!mNode) {
- return NS_ERROR_NULL_POINTER;
- }
-
- ErrorResult error;
- nsCOMPtr<nsIContent> refNode = mRefNode;
- mParent->InsertBefore(*mNode, refNode, error);
- return error.StealNSResult();
-}
-
-NS_IMETHODIMP
-DeleteNodeTransaction::RedoTransaction()
-{
- if (!mParent) {
- // this is a legal state, the txn is a no-op
- return NS_OK;
- }
- if (!mNode) {
- return NS_ERROR_NULL_POINTER;
- }
-
- if (mRangeUpdater) {
- mRangeUpdater->SelAdjDeleteNode(mNode->AsDOMNode());
- }
-
- ErrorResult error;
- mParent->RemoveChild(*mNode, error);
- return error.StealNSResult();
-}
-
-NS_IMETHODIMP
-DeleteNodeTransaction::GetTxnDescription(nsAString& aString)
-{
- aString.AssignLiteral("DeleteNodeTransaction");
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/DeleteNodeTransaction.h b/editor/libeditor/DeleteNodeTransaction.h
deleted file mode 100644
index 369bbdf56..000000000
--- a/editor/libeditor/DeleteNodeTransaction.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef DeleteNodeTransaction_h
-#define DeleteNodeTransaction_h
-
-#include "mozilla/EditTransactionBase.h"
-#include "nsCOMPtr.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsIContent.h"
-#include "nsINode.h"
-#include "nsISupportsImpl.h"
-#include "nscore.h"
-
-namespace mozilla {
-
-class EditorBase;
-class RangeUpdater;
-
-/**
- * A transaction that deletes a single element
- */
-class DeleteNodeTransaction final : public EditTransactionBase
-{
-public:
- /**
- * Initialize the transaction.
- * @param aElement The node to delete.
- */
- nsresult Init(EditorBase* aEditorBase, nsINode* aNode,
- RangeUpdater* aRangeUpdater);
-
- DeleteNodeTransaction();
-
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DeleteNodeTransaction,
- EditTransactionBase)
-
- NS_DECL_EDITTRANSACTIONBASE
-
- NS_IMETHOD RedoTransaction() override;
-
-protected:
- virtual ~DeleteNodeTransaction();
-
- // The element to delete.
- nsCOMPtr<nsINode> mNode;
-
- // Parent of node to delete.
- nsCOMPtr<nsINode> mParent;
-
- // Next sibling to remember for undo/redo purposes.
- nsCOMPtr<nsIContent> mRefNode;
-
- // The editor for this transaction.
- RefPtr<EditorBase> mEditorBase;
-
- // Range updater object.
- RangeUpdater* mRangeUpdater;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef DeleteNodeTransaction_h
diff --git a/editor/libeditor/DeleteRangeTransaction.cpp b/editor/libeditor/DeleteRangeTransaction.cpp
deleted file mode 100644
index 16d2344ba..000000000
--- a/editor/libeditor/DeleteRangeTransaction.cpp
+++ /dev/null
@@ -1,256 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "DeleteRangeTransaction.h"
-
-#include "DeleteNodeTransaction.h"
-#include "DeleteTextTransaction.h"
-#include "mozilla/Assertions.h"
-#include "mozilla/EditorBase.h"
-#include "mozilla/dom/Selection.h"
-#include "mozilla/mozalloc.h"
-#include "nsCOMPtr.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsIContent.h"
-#include "nsIContentIterator.h"
-#include "nsIDOMCharacterData.h"
-#include "nsINode.h"
-#include "nsAString.h"
-
-namespace mozilla {
-
-using namespace dom;
-
-// note that aEditorBase is not refcounted
-DeleteRangeTransaction::DeleteRangeTransaction()
- : mEditorBase(nullptr)
- , mRangeUpdater(nullptr)
-{
-}
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(DeleteRangeTransaction,
- EditAggregateTransaction,
- mEditorBase,
- mRange)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeleteRangeTransaction)
-NS_INTERFACE_MAP_END_INHERITING(EditAggregateTransaction)
-
-nsresult
-DeleteRangeTransaction::Init(EditorBase* aEditorBase,
- nsRange* aRange,
- RangeUpdater* aRangeUpdater)
-{
- MOZ_ASSERT(aEditorBase && aRange);
-
- mEditorBase = aEditorBase;
- mRange = aRange->CloneRange();
- mRangeUpdater = aRangeUpdater;
-
- NS_ENSURE_TRUE(mEditorBase->IsModifiableNode(mRange->GetStartParent()),
- NS_ERROR_FAILURE);
- NS_ENSURE_TRUE(mEditorBase->IsModifiableNode(mRange->GetEndParent()),
- NS_ERROR_FAILURE);
- NS_ENSURE_TRUE(mEditorBase->IsModifiableNode(mRange->GetCommonAncestor()),
- NS_ERROR_FAILURE);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-DeleteRangeTransaction::DoTransaction()
-{
- if (NS_WARN_IF(!mRange) || NS_WARN_IF(!mEditorBase)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // build the child transactions
- nsCOMPtr<nsINode> startParent = mRange->GetStartParent();
- int32_t startOffset = mRange->StartOffset();
- nsCOMPtr<nsINode> endParent = mRange->GetEndParent();
- int32_t endOffset = mRange->EndOffset();
- MOZ_ASSERT(startParent && endParent);
-
- if (startParent == endParent) {
- // the selection begins and ends in the same node
- nsresult rv =
- CreateTxnsToDeleteBetween(startParent, startOffset, endOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // the selection ends in a different node from where it started. delete
- // the relevant content in the start node
- nsresult rv =
- CreateTxnsToDeleteContent(startParent, startOffset, nsIEditor::eNext);
- NS_ENSURE_SUCCESS(rv, rv);
- // delete the intervening nodes
- rv = CreateTxnsToDeleteNodesBetween();
- NS_ENSURE_SUCCESS(rv, rv);
- // delete the relevant content in the end node
- rv = CreateTxnsToDeleteContent(endParent, endOffset, nsIEditor::ePrevious);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // if we've successfully built this aggregate transaction, then do it.
- nsresult rv = EditAggregateTransaction::DoTransaction();
- NS_ENSURE_SUCCESS(rv, rv);
-
- // only set selection to deletion point if editor gives permission
- bool bAdjustSelection;
- mEditorBase->ShouldTxnSetSelection(&bAdjustSelection);
- if (bAdjustSelection) {
- RefPtr<Selection> selection = mEditorBase->GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- rv = selection->Collapse(startParent, startOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // else do nothing - dom range gravity will adjust selection
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-DeleteRangeTransaction::UndoTransaction()
-{
- if (NS_WARN_IF(!mRange) || NS_WARN_IF(!mEditorBase)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- return EditAggregateTransaction::UndoTransaction();
-}
-
-NS_IMETHODIMP
-DeleteRangeTransaction::RedoTransaction()
-{
- if (NS_WARN_IF(!mRange) || NS_WARN_IF(!mEditorBase)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- return EditAggregateTransaction::RedoTransaction();
-}
-
-NS_IMETHODIMP
-DeleteRangeTransaction::GetTxnDescription(nsAString& aString)
-{
- aString.AssignLiteral("DeleteRangeTransaction");
- return NS_OK;
-}
-
-nsresult
-DeleteRangeTransaction::CreateTxnsToDeleteBetween(nsINode* aNode,
- int32_t aStartOffset,
- int32_t aEndOffset)
-{
- if (NS_WARN_IF(!mEditorBase)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // see what kind of node we have
- if (aNode->IsNodeOfType(nsINode::eDATA_NODE)) {
- // if the node is a chardata node, then delete chardata content
- int32_t numToDel;
- if (aStartOffset == aEndOffset) {
- numToDel = 1;
- } else {
- numToDel = aEndOffset - aStartOffset;
- }
-
- RefPtr<nsGenericDOMDataNode> charDataNode =
- static_cast<nsGenericDOMDataNode*>(aNode);
-
- RefPtr<DeleteTextTransaction> transaction =
- new DeleteTextTransaction(*mEditorBase, *charDataNode, aStartOffset,
- numToDel, mRangeUpdater);
-
- nsresult rv = transaction->Init();
- NS_ENSURE_SUCCESS(rv, rv);
-
- AppendChild(transaction);
- return NS_OK;
- }
-
- nsCOMPtr<nsIContent> child = aNode->GetChildAt(aStartOffset);
- NS_ENSURE_STATE(child);
-
- // XXX This looks odd. Only when the last transaction causes error at
- // calling Init(), the result becomes error. Otherwise, always NS_OK.
- nsresult rv = NS_OK;
- for (int32_t i = aStartOffset; i < aEndOffset; ++i) {
- RefPtr<DeleteNodeTransaction> transaction = new DeleteNodeTransaction();
- rv = transaction->Init(mEditorBase, child, mRangeUpdater);
- if (NS_SUCCEEDED(rv)) {
- AppendChild(transaction);
- }
-
- child = child->GetNextSibling();
- }
-
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
-}
-
-nsresult
-DeleteRangeTransaction::CreateTxnsToDeleteContent(nsINode* aNode,
- int32_t aOffset,
- nsIEditor::EDirection aAction)
-{
- if (NS_WARN_IF(!mEditorBase)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // see what kind of node we have
- if (aNode->IsNodeOfType(nsINode::eDATA_NODE)) {
- // if the node is a chardata node, then delete chardata content
- uint32_t start, numToDelete;
- if (nsIEditor::eNext == aAction) {
- start = aOffset;
- numToDelete = aNode->Length() - aOffset;
- } else {
- start = 0;
- numToDelete = aOffset;
- }
-
- if (numToDelete) {
- RefPtr<nsGenericDOMDataNode> dataNode =
- static_cast<nsGenericDOMDataNode*>(aNode);
- RefPtr<DeleteTextTransaction> transaction =
- new DeleteTextTransaction(*mEditorBase, *dataNode, start, numToDelete,
- mRangeUpdater);
-
- nsresult rv = transaction->Init();
- NS_ENSURE_SUCCESS(rv, rv);
-
- AppendChild(transaction);
- }
- }
-
- return NS_OK;
-}
-
-nsresult
-DeleteRangeTransaction::CreateTxnsToDeleteNodesBetween()
-{
- if (NS_WARN_IF(!mEditorBase)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- nsCOMPtr<nsIContentIterator> iter = NS_NewContentSubtreeIterator();
-
- nsresult rv = iter->Init(mRange);
- NS_ENSURE_SUCCESS(rv, rv);
-
- while (!iter->IsDone()) {
- nsCOMPtr<nsINode> node = iter->GetCurrentNode();
- NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
-
- RefPtr<DeleteNodeTransaction> transaction = new DeleteNodeTransaction();
- rv = transaction->Init(mEditorBase, node, mRangeUpdater);
- NS_ENSURE_SUCCESS(rv, rv);
- AppendChild(transaction);
-
- iter->Next();
- }
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/DeleteRangeTransaction.h b/editor/libeditor/DeleteRangeTransaction.h
deleted file mode 100644
index 9bb4f520a..000000000
--- a/editor/libeditor/DeleteRangeTransaction.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef DeleteRangeTransaction_h
-#define DeleteRangeTransaction_h
-
-#include "EditAggregateTransaction.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsID.h"
-#include "nsIEditor.h"
-#include "nsISupportsImpl.h"
-#include "nsRange.h"
-#include "nscore.h"
-
-class nsINode;
-
-namespace mozilla {
-
-class EditorBase;
-class RangeUpdater;
-
-/**
- * A transaction that deletes an entire range in the content tree
- */
-class DeleteRangeTransaction final : public EditAggregateTransaction
-{
-public:
- /**
- * Initialize the transaction.
- * @param aEditorBase The object providing basic editing operations.
- * @param aRange The range to delete.
- */
- nsresult Init(EditorBase* aEditorBase,
- nsRange* aRange,
- RangeUpdater* aRangeUpdater);
-
- DeleteRangeTransaction();
-
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DeleteRangeTransaction,
- EditAggregateTransaction)
- NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
-
- NS_DECL_EDITTRANSACTIONBASE
-
- NS_IMETHOD RedoTransaction() override;
-
- virtual void LastRelease() override
- {
- mRange = nullptr;
- EditAggregateTransaction::LastRelease();
- }
-
-protected:
- nsresult CreateTxnsToDeleteBetween(nsINode* aNode,
- int32_t aStartOffset,
- int32_t aEndOffset);
-
- nsresult CreateTxnsToDeleteNodesBetween();
-
- nsresult CreateTxnsToDeleteContent(nsINode* aParent,
- int32_t aOffset,
- nsIEditor::EDirection aAction);
-
- // P1 in the range.
- RefPtr<nsRange> mRange;
-
- // The editor for this transaction.
- RefPtr<EditorBase> mEditorBase;
-
- // Range updater object.
- RangeUpdater* mRangeUpdater;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef DeleteRangeTransaction_h
diff --git a/editor/libeditor/DeleteTextTransaction.cpp b/editor/libeditor/DeleteTextTransaction.cpp
deleted file mode 100644
index 624aeaa3c..000000000
--- a/editor/libeditor/DeleteTextTransaction.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "DeleteTextTransaction.h"
-
-#include "mozilla/Assertions.h"
-#include "mozilla/EditorBase.h"
-#include "mozilla/SelectionState.h"
-#include "mozilla/dom/Selection.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsIEditor.h"
-#include "nsISupportsImpl.h"
-#include "nsAString.h"
-
-namespace mozilla {
-
-using namespace dom;
-
-DeleteTextTransaction::DeleteTextTransaction(
- EditorBase& aEditorBase,
- nsGenericDOMDataNode& aCharData,
- uint32_t aOffset,
- uint32_t aNumCharsToDelete,
- RangeUpdater* aRangeUpdater)
- : mEditorBase(&aEditorBase)
- , mCharData(&aCharData)
- , mOffset(aOffset)
- , mNumCharsToDelete(aNumCharsToDelete)
- , mRangeUpdater(aRangeUpdater)
-{
- NS_ASSERTION(mCharData->Length() >= aOffset + aNumCharsToDelete,
- "Trying to delete more characters than in node");
-}
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(DeleteTextTransaction, EditTransactionBase,
- mEditorBase,
- mCharData)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeleteTextTransaction)
-NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
-
-nsresult
-DeleteTextTransaction::Init()
-{
- // Do nothing if the node is read-only
- if (NS_WARN_IF(!mEditorBase) || !mEditorBase->IsModifiableNode(mCharData)) {
- return NS_ERROR_FAILURE;
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-DeleteTextTransaction::DoTransaction()
-{
- if (NS_WARN_IF(!mCharData) || NS_WARN_IF(!mEditorBase)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // Get the text that we're about to delete
- nsresult rv = mCharData->SubstringData(mOffset, mNumCharsToDelete,
- mDeletedText);
- MOZ_ASSERT(NS_SUCCEEDED(rv));
- rv = mCharData->DeleteData(mOffset, mNumCharsToDelete);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (mRangeUpdater) {
- mRangeUpdater->SelAdjDeleteText(mCharData, mOffset, mNumCharsToDelete);
- }
-
- // Only set selection to deletion point if editor gives permission
- if (mEditorBase->GetShouldTxnSetSelection()) {
- RefPtr<Selection> selection = mEditorBase->GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- rv = selection->Collapse(mCharData, mOffset);
- NS_ASSERTION(NS_SUCCEEDED(rv),
- "Selection could not be collapsed after undo of deletetext");
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // Else do nothing - DOM Range gravity will adjust selection
- return NS_OK;
-}
-
-//XXX: We may want to store the selection state and restore it properly. Was
-// it an insertion point or an extended selection?
-NS_IMETHODIMP
-DeleteTextTransaction::UndoTransaction()
-{
- if (NS_WARN_IF(!mCharData)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- return mCharData->InsertData(mOffset, mDeletedText);
-}
-
-NS_IMETHODIMP
-DeleteTextTransaction::GetTxnDescription(nsAString& aString)
-{
- aString.AssignLiteral("DeleteTextTransaction: ");
- aString += mDeletedText;
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/DeleteTextTransaction.h b/editor/libeditor/DeleteTextTransaction.h
deleted file mode 100644
index 0c8dafbc3..000000000
--- a/editor/libeditor/DeleteTextTransaction.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef DeleteTextTransaction_h
-#define DeleteTextTransaction_h
-
-#include "mozilla/EditTransactionBase.h"
-#include "nsCOMPtr.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsGenericDOMDataNode.h"
-#include "nsID.h"
-#include "nsString.h"
-#include "nscore.h"
-
-namespace mozilla {
-
-class EditorBase;
-class RangeUpdater;
-
-/**
- * A transaction that removes text from a content node.
- */
-class DeleteTextTransaction final : public EditTransactionBase
-{
-public:
- /**
- * Initialize the transaction.
- * @param aEditorBase The provider of basic editing operations.
- * @param aElement The content node to remove text from.
- * @param aOffset The location in aElement to begin the deletion.
- * @param aNumCharsToDelete The number of characters to delete. Not the
- * number of bytes!
- */
- DeleteTextTransaction(EditorBase& aEditorBase,
- nsGenericDOMDataNode& aCharData,
- uint32_t aOffset,
- uint32_t aNumCharsToDelete,
- RangeUpdater* aRangeUpdater);
-
- nsresult Init();
-
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DeleteTextTransaction,
- EditTransactionBase)
- NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
-
- NS_DECL_EDITTRANSACTIONBASE
-
- uint32_t GetOffset() { return mOffset; }
-
- uint32_t GetNumCharsToDelete() { return mNumCharsToDelete; }
-
-protected:
- // The provider of basic editing operations.
- RefPtr<EditorBase> mEditorBase;
-
- // The CharacterData node to operate upon.
- RefPtr<nsGenericDOMDataNode> mCharData;
-
- // The offset into mCharData where the deletion is to take place.
- uint32_t mOffset;
-
- // The number of characters to delete.
- uint32_t mNumCharsToDelete;
-
- // The text that was deleted.
- nsString mDeletedText;
-
- // Range updater object.
- RangeUpdater* mRangeUpdater;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef DeleteTextTransaction_h
diff --git a/editor/libeditor/EditActionListener.h b/editor/libeditor/EditActionListener.h
deleted file mode 100644
index 834ec76b9..000000000
--- a/editor/libeditor/EditActionListener.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef __editActionListener_h__
-#define __editActionListener_h__
-
-class EditActionListener
-{
-public:
-
- virtual void EditAction() = 0;
-
-};
-
-#endif /* __editActionListener_h__ */
diff --git a/editor/libeditor/EditAggregateTransaction.cpp b/editor/libeditor/EditAggregateTransaction.cpp
deleted file mode 100644
index f50e8a67c..000000000
--- a/editor/libeditor/EditAggregateTransaction.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "EditAggregateTransaction.h"
-#include "nsAString.h"
-#include "nsCOMPtr.h" // for nsCOMPtr
-#include "nsError.h" // for NS_OK, etc.
-#include "nsISupportsUtils.h" // for NS_ADDREF
-#include "nsITransaction.h" // for nsITransaction
-#include "nsString.h" // for nsAutoString
-
-namespace mozilla {
-
-EditAggregateTransaction::EditAggregateTransaction()
-{
-}
-
-EditAggregateTransaction::~EditAggregateTransaction()
-{
-}
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(EditAggregateTransaction,
- EditTransactionBase,
- mChildren)
-
-NS_IMPL_ADDREF_INHERITED(EditAggregateTransaction, EditTransactionBase)
-NS_IMPL_RELEASE_INHERITED(EditAggregateTransaction, EditTransactionBase)
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EditAggregateTransaction)
-NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
-
-NS_IMETHODIMP
-EditAggregateTransaction::DoTransaction()
-{
- // FYI: It's legal (but not very useful) to have an empty child list.
- for (uint32_t i = 0, length = mChildren.Length(); i < length; ++i) {
- nsITransaction *txn = mChildren[i];
- if (!txn) {
- return NS_ERROR_NULL_POINTER;
- }
- nsresult rv = txn->DoTransaction();
- if (NS_FAILED(rv)) {
- return rv;
- }
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditAggregateTransaction::UndoTransaction()
-{
- // FYI: It's legal (but not very useful) to have an empty child list.
- // Undo goes through children backwards.
- for (uint32_t i = mChildren.Length(); i--; ) {
- nsITransaction *txn = mChildren[i];
- if (!txn) {
- return NS_ERROR_NULL_POINTER;
- }
- nsresult rv = txn->UndoTransaction();
- if (NS_FAILED(rv)) {
- return rv;
- }
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditAggregateTransaction::RedoTransaction()
-{
- // It's legal (but not very useful) to have an empty child list.
- for (uint32_t i = 0, length = mChildren.Length(); i < length; ++i) {
- nsITransaction *txn = mChildren[i];
- if (!txn) {
- return NS_ERROR_NULL_POINTER;
- }
- nsresult rv = txn->RedoTransaction();
- if (NS_FAILED(rv)) {
- return rv;
- }
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditAggregateTransaction::Merge(nsITransaction* aTransaction,
- bool* aDidMerge)
-{
- if (aDidMerge) {
- *aDidMerge = false;
- }
- if (mChildren.IsEmpty()) {
- return NS_OK;
- }
- // FIXME: Is this really intended not to loop? It looks like the code
- // that used to be here sort of intended to loop, but didn't.
- nsITransaction *txn = mChildren[0];
- if (!txn) {
- return NS_ERROR_NULL_POINTER;
- }
- return txn->Merge(aTransaction, aDidMerge);
-}
-
-NS_IMETHODIMP
-EditAggregateTransaction::GetTxnDescription(nsAString& aString)
-{
- aString.AssignLiteral("EditAggregateTransaction: ");
-
- if (mName) {
- nsAutoString name;
- mName->ToString(name);
- aString += name;
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditAggregateTransaction::AppendChild(EditTransactionBase* aTransaction)
-{
- if (!aTransaction) {
- return NS_ERROR_NULL_POINTER;
- }
-
- RefPtr<EditTransactionBase>* slot = mChildren.AppendElement();
- if (!slot) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- *slot = aTransaction;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditAggregateTransaction::GetName(nsIAtom** aName)
-{
- if (aName && mName) {
- *aName = mName;
- NS_ADDREF(*aName);
- return NS_OK;
- }
- return NS_ERROR_NULL_POINTER;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/EditAggregateTransaction.h b/editor/libeditor/EditAggregateTransaction.h
deleted file mode 100644
index 6ba27a01f..000000000
--- a/editor/libeditor/EditAggregateTransaction.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef EditAggregateTransaction_h
-#define EditAggregateTransaction_h
-
-#include "mozilla/EditTransactionBase.h"
-#include "nsCOMPtr.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsIAtom.h"
-#include "nsISupportsImpl.h"
-#include "nsTArray.h"
-#include "nscore.h"
-
-class nsITransaction;
-
-namespace mozilla {
-
-/**
- * base class for all document editing transactions that require aggregation.
- * provides a list of child transactions.
- */
-class EditAggregateTransaction : public EditTransactionBase
-{
-public:
- EditAggregateTransaction();
-
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(EditAggregateTransaction,
- EditTransactionBase)
-
- NS_DECL_EDITTRANSACTIONBASE
-
- NS_IMETHOD RedoTransaction() override;
- NS_IMETHOD Merge(nsITransaction* aTransaction, bool* aDidMerge) override;
-
- /**
- * Append a transaction to this aggregate.
- */
- NS_IMETHOD AppendChild(EditTransactionBase* aTransaction);
-
- /**
- * Get the name assigned to this transaction.
- */
- NS_IMETHOD GetName(nsIAtom** aName);
-
-protected:
- virtual ~EditAggregateTransaction();
-
- nsTArray<RefPtr<EditTransactionBase>> mChildren;
- nsCOMPtr<nsIAtom> mName;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef EditAggregateTransaction_h
diff --git a/editor/libeditor/EditTransactionBase.cpp b/editor/libeditor/EditTransactionBase.cpp
deleted file mode 100644
index 2905baa8c..000000000
--- a/editor/libeditor/EditTransactionBase.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/EditTransactionBase.h"
-#include "nsError.h"
-#include "nsISupportsBase.h"
-
-namespace mozilla {
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(EditTransactionBase)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_0(EditTransactionBase)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(EditTransactionBase)
- // We don't have anything to traverse, but some of our subclasses do.
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EditTransactionBase)
- NS_INTERFACE_MAP_ENTRY(nsITransaction)
- NS_INTERFACE_MAP_ENTRY(nsPIEditorTransaction)
- NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITransaction)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(EditTransactionBase)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(EditTransactionBase,
- LastRelease())
-
-EditTransactionBase::~EditTransactionBase()
-{
-}
-
-NS_IMETHODIMP
-EditTransactionBase::RedoTransaction()
-{
- return DoTransaction();
-}
-
-NS_IMETHODIMP
-EditTransactionBase::GetIsTransient(bool* aIsTransient)
-{
- *aIsTransient = false;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditTransactionBase::Merge(nsITransaction* aTransaction, bool* aDidMerge)
-{
- *aDidMerge = false;
-
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/EditTransactionBase.h b/editor/libeditor/EditTransactionBase.h
deleted file mode 100644
index f09449f07..000000000
--- a/editor/libeditor/EditTransactionBase.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_EditTransactionBase_h
-#define mozilla_EditTransactionBase_h
-
-#include "nsCycleCollectionParticipant.h"
-#include "nsISupportsImpl.h"
-#include "nsITransaction.h"
-#include "nsPIEditorTransaction.h"
-#include "nscore.h"
-
-namespace mozilla {
-
-/**
- * Base class for all document editing transactions.
- */
-class EditTransactionBase : public nsITransaction
- , public nsPIEditorTransaction
-{
-public:
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EditTransactionBase, nsITransaction)
-
- virtual void LastRelease() {}
-
- NS_IMETHOD RedoTransaction(void) override;
- NS_IMETHOD GetIsTransient(bool* aIsTransient) override;
- NS_IMETHOD Merge(nsITransaction* aTransaction, bool* aDidMerge) override;
-
-protected:
- virtual ~EditTransactionBase();
-};
-
-} // namespace mozilla
-
-#define NS_DECL_EDITTRANSACTIONBASE \
- NS_IMETHOD DoTransaction() override; \
- NS_IMETHOD UndoTransaction() override; \
- NS_IMETHOD GetTxnDescription(nsAString& aTransactionDescription) override;
-
-#endif // #ifndef mozilla_EditTransactionBase_h
diff --git a/editor/libeditor/EditorBase.cpp b/editor/libeditor/EditorBase.cpp
deleted file mode 100644
index 60df3571e..000000000
--- a/editor/libeditor/EditorBase.cpp
+++ /dev/null
@@ -1,5359 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/EditorBase.h"
-
-#include "mozilla/DebugOnly.h" // for DebugOnly
-
-#include <stdio.h> // for nullptr, stdout
-#include <string.h> // for strcmp
-
-#include "ChangeAttributeTransaction.h" // for ChangeAttributeTransaction
-#include "CompositionTransaction.h" // for CompositionTransaction
-#include "CreateElementTransaction.h" // for CreateElementTransaction
-#include "DeleteNodeTransaction.h" // for DeleteNodeTransaction
-#include "DeleteRangeTransaction.h" // for DeleteRangeTransaction
-#include "DeleteTextTransaction.h" // for DeleteTextTransaction
-#include "EditAggregateTransaction.h" // for EditAggregateTransaction
-#include "EditorEventListener.h" // for EditorEventListener
-#include "InsertNodeTransaction.h" // for InsertNodeTransaction
-#include "InsertTextTransaction.h" // for InsertTextTransaction
-#include "JoinNodeTransaction.h" // for JoinNodeTransaction
-#include "PlaceholderTransaction.h" // for PlaceholderTransaction
-#include "SplitNodeTransaction.h" // for SplitNodeTransaction
-#include "StyleSheetTransactions.h" // for AddStyleSheetTransaction, etc.
-#include "TextEditUtils.h" // for TextEditUtils
-#include "mozFlushType.h" // for mozFlushType::Flush_Frames
-#include "mozInlineSpellChecker.h" // for mozInlineSpellChecker
-#include "mozilla/CheckedInt.h" // for CheckedInt
-#include "mozilla/EditorUtils.h" // for AutoRules, etc.
-#include "mozilla/EditTransactionBase.h" // for EditTransactionBase
-#include "mozilla/IMEStateManager.h" // for IMEStateManager
-#include "mozilla/Preferences.h" // for Preferences
-#include "mozilla/dom/Selection.h" // for Selection, etc.
-#include "mozilla/Services.h" // for GetObserverService
-#include "mozilla/TextComposition.h" // for TextComposition
-#include "mozilla/TextEvents.h"
-#include "mozilla/dom/Element.h" // for Element, nsINode::AsElement
-#include "mozilla/dom/HTMLBodyElement.h"
-#include "mozilla/dom/Text.h"
-#include "mozilla/dom/Event.h"
-#include "mozilla/mozalloc.h" // for operator new, etc.
-#include "nsAString.h" // for nsAString_internal::Length, etc.
-#include "nsCCUncollectableMarker.h" // for nsCCUncollectableMarker
-#include "nsCaret.h" // for nsCaret
-#include "nsCaseTreatment.h"
-#include "nsCharTraits.h" // for NS_IS_HIGH_SURROGATE, etc.
-#include "nsComponentManagerUtils.h" // for do_CreateInstance
-#include "nsComputedDOMStyle.h" // for nsComputedDOMStyle
-#include "nsContentUtils.h" // for nsContentUtils
-#include "nsDOMString.h" // for DOMStringIsNull
-#include "nsDebug.h" // for NS_ENSURE_TRUE, etc.
-#include "nsError.h" // for NS_OK, etc.
-#include "nsFocusManager.h" // for nsFocusManager
-#include "nsFrameSelection.h" // for nsFrameSelection
-#include "nsGkAtoms.h" // for nsGkAtoms, nsGkAtoms::dir
-#include "nsIAbsorbingTransaction.h" // for nsIAbsorbingTransaction
-#include "nsIAtom.h" // for nsIAtom
-#include "nsIContent.h" // for nsIContent
-#include "nsIDOMAttr.h" // for nsIDOMAttr
-#include "nsIDOMCharacterData.h" // for nsIDOMCharacterData
-#include "nsIDOMDocument.h" // for nsIDOMDocument
-#include "nsIDOMElement.h" // for nsIDOMElement
-#include "nsIDOMEvent.h" // for nsIDOMEvent
-#include "nsIDOMEventListener.h" // for nsIDOMEventListener
-#include "nsIDOMEventTarget.h" // for nsIDOMEventTarget
-#include "nsIDOMHTMLElement.h" // for nsIDOMHTMLElement
-#include "nsIDOMKeyEvent.h" // for nsIDOMKeyEvent, etc.
-#include "nsIDOMMozNamedAttrMap.h" // for nsIDOMMozNamedAttrMap
-#include "nsIDOMMouseEvent.h" // for nsIDOMMouseEvent
-#include "nsIDOMNode.h" // for nsIDOMNode, etc.
-#include "nsIDOMNodeList.h" // for nsIDOMNodeList
-#include "nsIDOMText.h" // for nsIDOMText
-#include "nsIDocumentStateListener.h" // for nsIDocumentStateListener
-#include "nsIEditActionListener.h" // for nsIEditActionListener
-#include "nsIEditorObserver.h" // for nsIEditorObserver
-#include "nsIEditorSpellCheck.h" // for nsIEditorSpellCheck
-#include "nsIFrame.h" // for nsIFrame
-#include "nsIHTMLDocument.h" // for nsIHTMLDocument
-#include "nsIInlineSpellChecker.h" // for nsIInlineSpellChecker, etc.
-#include "nsNameSpaceManager.h" // for kNameSpaceID_None, etc.
-#include "nsINode.h" // for nsINode, etc.
-#include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc.
-#include "nsIPresShell.h" // for nsIPresShell
-#include "nsISelectionController.h" // for nsISelectionController, etc.
-#include "nsISelectionDisplay.h" // for nsISelectionDisplay, etc.
-#include "nsISupportsBase.h" // for nsISupports
-#include "nsISupportsUtils.h" // for NS_ADDREF, NS_IF_ADDREF
-#include "nsITransaction.h" // for nsITransaction
-#include "nsITransactionManager.h"
-#include "nsIWeakReference.h" // for nsISupportsWeakReference
-#include "nsIWidget.h" // for nsIWidget, IMEState, etc.
-#include "nsPIDOMWindow.h" // for nsPIDOMWindow
-#include "nsPresContext.h" // for nsPresContext
-#include "nsRange.h" // for nsRange
-#include "nsReadableUtils.h" // for EmptyString, ToNewCString
-#include "nsString.h" // for nsAutoString, nsString, etc.
-#include "nsStringFwd.h" // for nsAFlatString
-#include "nsStyleConsts.h" // for NS_STYLE_DIRECTION_RTL, etc.
-#include "nsStyleContext.h" // for nsStyleContext
-#include "nsStyleStruct.h" // for nsStyleDisplay, nsStyleText, etc.
-#include "nsStyleStructFwd.h" // for nsIFrame::StyleUIReset, etc.
-#include "nsTextNode.h" // for nsTextNode
-#include "nsThreadUtils.h" // for nsRunnable
-#include "nsTransactionManager.h" // for nsTransactionManager
-#include "prtime.h" // for PR_Now
-
-class nsIOutputStream;
-class nsITransferable;
-
-#ifdef DEBUG
-#include "nsIDOMHTMLDocument.h" // for nsIDOMHTMLDocument
-#endif
-
-namespace mozilla {
-
-using namespace dom;
-using namespace widget;
-
-/*****************************************************************************
- * mozilla::EditorBase
- *****************************************************************************/
-
-EditorBase::EditorBase()
- : mPlaceholderName(nullptr)
- , mSelState(nullptr)
- , mPhonetic(nullptr)
- , mModCount(0)
- , mFlags(0)
- , mUpdateCount(0)
- , mPlaceholderBatch(0)
- , mAction(EditAction::none)
- , mIMETextOffset(0)
- , mIMETextLength(0)
- , mDirection(eNone)
- , mDocDirtyState(-1)
- , mSpellcheckCheckboxState(eTriUnset)
- , mShouldTxnSetSelection(true)
- , mDidPreDestroy(false)
- , mDidPostCreate(false)
- , mDispatchInputEvent(true)
- , mIsInEditAction(false)
- , mHidingCaret(false)
-{
-}
-
-EditorBase::~EditorBase()
-{
- MOZ_ASSERT(!IsInitialized() || mDidPreDestroy,
- "Why PreDestroy hasn't been called?");
-
- if (mComposition) {
- mComposition->OnEditorDestroyed();
- mComposition = nullptr;
- }
- // If this editor is still hiding the caret, we need to restore it.
- HideCaret(false);
- mTxnMgr = nullptr;
-
- delete mPhonetic;
-}
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(EditorBase)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(EditorBase)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mRootElement)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mInlineSpellChecker)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mTxnMgr)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mIMETextNode)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mActionListeners)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditorObservers)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocStateListeners)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventTarget)
-
- if (tmp->mEventListener) {
- EditorEventListener* listener =
- reinterpret_cast<EditorEventListener*>(tmp->mEventListener.get());
- listener->Disconnect();
- tmp->mEventListener = nullptr;
- }
-
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mSavedSel);
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mRangeUpdater);
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(EditorBase)
- nsIDocument* currentDoc =
- tmp->mRootElement ? tmp->mRootElement->GetUncomposedDoc() : nullptr;
- if (currentDoc &&
- nsCCUncollectableMarker::InGeneration(cb, currentDoc->GetMarkedCCGeneration())) {
- return NS_SUCCESS_INTERRUPTED_TRAVERSE;
- }
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRootElement)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInlineSpellChecker)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTxnMgr)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIMETextNode)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mActionListeners)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEditorObservers)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocStateListeners)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventTarget)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventListener)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSavedSel);
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRangeUpdater);
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EditorBase)
- NS_INTERFACE_MAP_ENTRY(nsIPhonetic)
- NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
- NS_INTERFACE_MAP_ENTRY(nsIEditorIMESupport)
- NS_INTERFACE_MAP_ENTRY(nsIEditor)
- NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIEditor)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(EditorBase)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(EditorBase)
-
-
-NS_IMETHODIMP
-EditorBase::Init(nsIDOMDocument* aDOMDocument,
- nsIContent* aRoot,
- nsISelectionController* aSelectionController,
- uint32_t aFlags,
- const nsAString& aValue)
-{
- MOZ_ASSERT(mAction == EditAction::none,
- "Initializing during an edit action is an error");
- MOZ_ASSERT(aDOMDocument);
- if (!aDOMDocument) {
- return NS_ERROR_NULL_POINTER;
- }
-
- // First only set flags, but other stuff shouldn't be initialized now.
- // Don't move this call after initializing mDocumentWeak.
- // SetFlags() can check whether it's called during initialization or not by
- // them. Note that SetFlags() will be called by PostCreate().
-#ifdef DEBUG
- nsresult rv =
-#endif
- SetFlags(aFlags);
- NS_ASSERTION(NS_SUCCEEDED(rv), "SetFlags() failed");
-
- nsCOMPtr<nsIDocument> document = do_QueryInterface(aDOMDocument);
- mDocumentWeak = document.get();
- // HTML editors currently don't have their own selection controller,
- // so they'll pass null as aSelCon, and we'll get the selection controller
- // off of the presshell.
- nsCOMPtr<nsISelectionController> selectionController;
- if (aSelectionController) {
- mSelectionControllerWeak = aSelectionController;
- selectionController = aSelectionController;
- } else {
- nsCOMPtr<nsIPresShell> presShell = GetPresShell();
- selectionController = do_QueryInterface(presShell);
- }
- MOZ_ASSERT(selectionController,
- "Selection controller should be available at this point");
-
- //set up root element if we are passed one.
- if (aRoot)
- mRootElement = do_QueryInterface(aRoot);
-
- mUpdateCount=0;
-
- // If this is an editor for <input> or <textarea>, mIMETextNode is always
- // recreated with same content. Therefore, we need to forget mIMETextNode,
- // but we need to keep storing mIMETextOffset and mIMETextLength becuase
- // they are necessary to restore IME selection and replacing composing string
- // when this receives eCompositionChange event next time.
- if (mIMETextNode && !mIMETextNode->IsInComposedDoc()) {
- mIMETextNode = nullptr;
- }
-
- // Show the caret.
- selectionController->SetCaretReadOnly(false);
- selectionController->SetDisplaySelection(
- nsISelectionController::SELECTION_ON);
- // Show all the selection reflected to user.
- selectionController->SetSelectionFlags(nsISelectionDisplay::DISPLAY_ALL);
-
- MOZ_ASSERT(IsInitialized());
-
- // Make sure that the editor will be destroyed properly
- mDidPreDestroy = false;
- // Make sure that the ediotr will be created properly
- mDidPostCreate = false;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::PostCreate()
-{
- // Synchronize some stuff for the flags. SetFlags() will initialize
- // something by the flag difference. This is first time of that, so, all
- // initializations must be run. For such reason, we need to invert mFlags
- // value first.
- mFlags = ~mFlags;
- nsresult rv = SetFlags(~mFlags);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // These operations only need to happen on the first PostCreate call
- if (!mDidPostCreate) {
- mDidPostCreate = true;
-
- // Set up listeners
- CreateEventListeners();
- rv = InstallEventListeners();
- NS_ENSURE_SUCCESS(rv, rv);
-
- // nuke the modification count, so the doc appears unmodified
- // do this before we notify listeners
- ResetModificationCount();
-
- // update the UI with our state
- NotifyDocumentListeners(eDocumentCreated);
- NotifyDocumentListeners(eDocumentStateChanged);
- }
-
- // update nsTextStateManager and caret if we have focus
- nsCOMPtr<nsIContent> focusedContent = GetFocusedContent();
- if (focusedContent) {
- nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(focusedContent);
- if (target) {
- InitializeSelection(target);
- }
-
- // If the text control gets reframed during focus, Focus() would not be
- // called, so take a chance here to see if we need to spell check the text
- // control.
- EditorEventListener* listener =
- reinterpret_cast<EditorEventListener*>(mEventListener.get());
- listener->SpellCheckIfNeeded();
-
- IMEState newState;
- rv = GetPreferredIMEState(&newState);
- NS_ENSURE_SUCCESS(rv, NS_OK);
- nsCOMPtr<nsIContent> content = GetFocusedContentForIME();
- IMEStateManager::UpdateIMEState(newState, content, *this);
- }
-
- // FYI: This call might cause destroying this editor.
- IMEStateManager::OnEditorInitialized(this);
-
- return NS_OK;
-}
-
-void
-EditorBase::CreateEventListeners()
-{
- // Don't create the handler twice
- if (!mEventListener) {
- mEventListener = new EditorEventListener();
- }
-}
-
-nsresult
-EditorBase::InstallEventListeners()
-{
- if (NS_WARN_IF(!IsInitialized()) || NS_WARN_IF(!mEventListener)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // Initialize the event target.
- nsCOMPtr<nsIContent> rootContent = GetRoot();
- NS_ENSURE_TRUE(rootContent, NS_ERROR_NOT_AVAILABLE);
- mEventTarget = do_QueryInterface(rootContent->GetParent());
- NS_ENSURE_TRUE(mEventTarget, NS_ERROR_NOT_AVAILABLE);
-
- EditorEventListener* listener =
- reinterpret_cast<EditorEventListener*>(mEventListener.get());
- nsresult rv = listener->Connect(this);
- if (mComposition) {
- // Restart to handle composition with new editor contents.
- mComposition->StartHandlingComposition(this);
- }
- return rv;
-}
-
-void
-EditorBase::RemoveEventListeners()
-{
- if (!IsInitialized() || !mEventListener) {
- return;
- }
- reinterpret_cast<EditorEventListener*>(mEventListener.get())->Disconnect();
- if (mComposition) {
- // Even if this is called, don't release mComposition because this is
- // may be reused after reframing.
- mComposition->EndHandlingComposition(this);
- }
- mEventTarget = nullptr;
-}
-
-bool
-EditorBase::GetDesiredSpellCheckState()
-{
- // Check user override on this element
- if (mSpellcheckCheckboxState != eTriUnset) {
- return (mSpellcheckCheckboxState == eTriTrue);
- }
-
- // Check user preferences
- int32_t spellcheckLevel = Preferences::GetInt("layout.spellcheckDefault", 1);
-
- if (!spellcheckLevel) {
- return false; // Spellchecking forced off globally
- }
-
- if (!CanEnableSpellCheck()) {
- return false;
- }
-
- nsCOMPtr<nsIPresShell> presShell = GetPresShell();
- if (presShell) {
- nsPresContext* context = presShell->GetPresContext();
- if (context && !context->IsDynamic()) {
- return false;
- }
- }
-
- // Check DOM state
- nsCOMPtr<nsIContent> content = GetExposedRoot();
- if (!content) {
- return false;
- }
-
- nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(content);
- if (!element) {
- return false;
- }
-
- if (!IsPlaintextEditor()) {
- // Some of the page content might be editable and some not, if spellcheck=
- // is explicitly set anywhere, so if there's anything editable on the page,
- // return true and let the spellchecker figure it out.
- nsCOMPtr<nsIHTMLDocument> doc = do_QueryInterface(content->GetUncomposedDoc());
- return doc && doc->IsEditingOn();
- }
-
- bool enable;
- element->GetSpellcheck(&enable);
-
- return enable;
-}
-
-NS_IMETHODIMP
-EditorBase::PreDestroy(bool aDestroyingFrames)
-{
- if (mDidPreDestroy)
- return NS_OK;
-
- IMEStateManager::OnEditorDestroying(this);
-
- // Let spellchecker clean up its observers etc. It is important not to
- // actually free the spellchecker here, since the spellchecker could have
- // caused flush notifications, which could have gotten here if a textbox
- // is being removed. Setting the spellchecker to nullptr could free the
- // object that is still in use! It will be freed when the editor is
- // destroyed.
- if (mInlineSpellChecker)
- mInlineSpellChecker->Cleanup(aDestroyingFrames);
-
- // tell our listeners that the doc is going away
- NotifyDocumentListeners(eDocumentToBeDestroyed);
-
- // Unregister event listeners
- RemoveEventListeners();
- // If this editor is still hiding the caret, we need to restore it.
- HideCaret(false);
- mActionListeners.Clear();
- mEditorObservers.Clear();
- mDocStateListeners.Clear();
- mInlineSpellChecker = nullptr;
- mSpellcheckCheckboxState = eTriUnset;
- mRootElement = nullptr;
-
- // Transaction may grab this instance. Therefore, they should be released
- // here for stopping the circular reference with this instance.
- if (mTxnMgr) {
- mTxnMgr->Clear();
- mTxnMgr = nullptr;
- }
-
- mDidPreDestroy = true;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::GetFlags(uint32_t* aFlags)
-{
- *aFlags = mFlags;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::SetFlags(uint32_t aFlags)
-{
- if (mFlags == aFlags) {
- return NS_OK;
- }
-
- bool spellcheckerWasEnabled = CanEnableSpellCheck();
- mFlags = aFlags;
-
- if (!IsInitialized()) {
- // If we're initializing, we shouldn't do anything now.
- // SetFlags() will be called by PostCreate(),
- // we should synchronize some stuff for the flags at that time.
- return NS_OK;
- }
-
- // The flag change may cause the spellchecker state change
- if (CanEnableSpellCheck() != spellcheckerWasEnabled) {
- nsresult rv = SyncRealTimeSpell();
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // If this is called from PostCreate(), it will update the IME state if it's
- // necessary.
- if (!mDidPostCreate) {
- return NS_OK;
- }
-
- // Might be changing editable state, so, we need to reset current IME state
- // if we're focused and the flag change causes IME state change.
- nsCOMPtr<nsIContent> focusedContent = GetFocusedContent();
- if (focusedContent) {
- IMEState newState;
- nsresult rv = GetPreferredIMEState(&newState);
- if (NS_SUCCEEDED(rv)) {
- // NOTE: When the enabled state isn't going to be modified, this method
- // is going to do nothing.
- nsCOMPtr<nsIContent> content = GetFocusedContentForIME();
- IMEStateManager::UpdateIMEState(newState, content, *this);
- }
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::GetIsSelectionEditable(bool* aIsSelectionEditable)
-{
- NS_ENSURE_ARG_POINTER(aIsSelectionEditable);
-
- // get current selection
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- // XXX we just check that the anchor node is editable at the moment
- // we should check that all nodes in the selection are editable
- nsCOMPtr<nsINode> anchorNode = selection->GetAnchorNode();
- *aIsSelectionEditable = anchorNode && IsEditable(anchorNode);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::GetIsDocumentEditable(bool* aIsDocumentEditable)
-{
- NS_ENSURE_ARG_POINTER(aIsDocumentEditable);
- nsCOMPtr<nsIDocument> doc = GetDocument();
- *aIsDocumentEditable = !!doc;
-
- return NS_OK;
-}
-
-already_AddRefed<nsIDocument>
-EditorBase::GetDocument()
-{
- nsCOMPtr<nsIDocument> document = mDocumentWeak.get();
- return document.forget();
-}
-
-already_AddRefed<nsIDOMDocument>
-EditorBase::GetDOMDocument()
-{
- nsCOMPtr<nsIDOMDocument> domDocument = do_QueryInterface(mDocumentWeak);
- return domDocument.forget();
-}
-
-NS_IMETHODIMP
-EditorBase::GetDocument(nsIDOMDocument** aDoc)
-{
- *aDoc = GetDOMDocument().take();
- return *aDoc ? NS_OK : NS_ERROR_NOT_INITIALIZED;
-}
-
-already_AddRefed<nsIPresShell>
-EditorBase::GetPresShell()
-{
- nsCOMPtr<nsIDocument> document = GetDocument();
- if (NS_WARN_IF(!document)) {
- return nullptr;
- }
- nsCOMPtr<nsIPresShell> presShell = document->GetShell();
- return presShell.forget();
-}
-
-already_AddRefed<nsIWidget>
-EditorBase::GetWidget()
-{
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
- NS_ENSURE_TRUE(ps, nullptr);
- nsPresContext* pc = ps->GetPresContext();
- NS_ENSURE_TRUE(pc, nullptr);
- nsCOMPtr<nsIWidget> widget = pc->GetRootWidget();
- NS_ENSURE_TRUE(widget.get(), nullptr);
- return widget.forget();
-}
-
-NS_IMETHODIMP
-EditorBase::GetContentsMIMEType(char** aContentsMIMEType)
-{
- NS_ENSURE_ARG_POINTER(aContentsMIMEType);
- *aContentsMIMEType = ToNewCString(mContentMIMEType);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::SetContentsMIMEType(const char* aContentsMIMEType)
-{
- mContentMIMEType.Assign(aContentsMIMEType ? aContentsMIMEType : "");
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::GetSelectionController(nsISelectionController** aSel)
-{
- NS_ENSURE_TRUE(aSel, NS_ERROR_NULL_POINTER);
- *aSel = nullptr; // init out param
- nsCOMPtr<nsISelectionController> selCon = GetSelectionController();
- if (NS_WARN_IF(!selCon)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- selCon.forget(aSel);
- return NS_OK;
-}
-
-already_AddRefed<nsISelectionController>
-EditorBase::GetSelectionController()
-{
- nsCOMPtr<nsISelectionController> selectionController;
- if (mSelectionControllerWeak) {
- selectionController = mSelectionControllerWeak.get();
- } else {
- nsCOMPtr<nsIPresShell> presShell = GetPresShell();
- selectionController = do_QueryInterface(presShell);
- }
- return selectionController.forget();
-}
-
-NS_IMETHODIMP
-EditorBase::DeleteSelection(EDirection aAction,
- EStripWrappers aStripWrappers)
-{
- MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
- return DeleteSelectionImpl(aAction, aStripWrappers);
-}
-
-NS_IMETHODIMP
-EditorBase::GetSelection(nsISelection** aSelection)
-{
- return GetSelection(SelectionType::eNormal, aSelection);
-}
-
-nsresult
-EditorBase::GetSelection(SelectionType aSelectionType,
- nsISelection** aSelection)
-{
- NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
- *aSelection = nullptr;
- nsCOMPtr<nsISelectionController> selcon = GetSelectionController();
- if (!selcon) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- return selcon->GetSelection(ToRawSelectionType(aSelectionType), aSelection);
-}
-
-Selection*
-EditorBase::GetSelection(SelectionType aSelectionType)
-{
- nsCOMPtr<nsISelection> sel;
- nsresult rv = GetSelection(aSelectionType, getter_AddRefs(sel));
- if (NS_WARN_IF(NS_FAILED(rv)) || NS_WARN_IF(!sel)) {
- return nullptr;
- }
-
- return sel->AsSelection();
-}
-
-NS_IMETHODIMP
-EditorBase::DoTransaction(nsITransaction* aTxn)
-{
- if (mPlaceholderBatch && !mPlaceholderTransactionWeak) {
- RefPtr<PlaceholderTransaction> placeholderTransaction =
- new PlaceholderTransaction(*this, mPlaceholderName, Move(mSelState));
-
- // Save off weak reference to placeholder transaction
- mPlaceholderTransactionWeak = placeholderTransaction;
-
- // We will recurse, but will not hit this case in the nested call
- DoTransaction(placeholderTransaction);
-
- if (mTxnMgr) {
- nsCOMPtr<nsITransaction> topTransaction = mTxnMgr->PeekUndoStack();
- nsCOMPtr<nsIAbsorbingTransaction> topAbsorbingTransaction =
- do_QueryInterface(topTransaction);
- if (topAbsorbingTransaction) {
- RefPtr<PlaceholderTransaction> topPlaceholderTransaction =
- topAbsorbingTransaction->AsPlaceholderTransaction();
- if (topPlaceholderTransaction) {
- // there is a placeholder transaction on top of the undo stack. It
- // is either the one we just created, or an earlier one that we are
- // now merging into. From here on out remember this placeholder
- // instead of the one we just created.
- mPlaceholderTransactionWeak = topPlaceholderTransaction;
- }
- }
- }
- }
-
- if (aTxn) {
- // XXX: Why are we doing selection specific batching stuff here?
- // XXX: Most entry points into the editor have auto variables that
- // XXX: should trigger Begin/EndUpdateViewBatch() calls that will make
- // XXX: these selection batch calls no-ops.
- // XXX:
- // XXX: I suspect that this was placed here to avoid multiple
- // XXX: selection changed notifications from happening until after
- // XXX: the transaction was done. I suppose that can still happen
- // XXX: if an embedding application called DoTransaction() directly
- // XXX: to pump its own transactions through the system, but in that
- // XXX: case, wouldn't we want to use Begin/EndUpdateViewBatch() or
- // XXX: its auto equivalent AutoUpdateViewBatch to ensure that
- // XXX: selection listeners have access to accurate frame data?
- // XXX:
- // XXX: Note that if we did add Begin/EndUpdateViewBatch() calls
- // XXX: we will need to make sure that they are disabled during
- // XXX: the init of the editor for text widgets to avoid layout
- // XXX: re-entry during initial reflow. - kin
-
- // get the selection and start a batch change
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- selection->StartBatchChanges();
-
- nsresult rv;
- if (mTxnMgr) {
- RefPtr<nsTransactionManager> txnMgr = mTxnMgr;
- rv = txnMgr->DoTransaction(aTxn);
- } else {
- rv = aTxn->DoTransaction();
- }
- if (NS_SUCCEEDED(rv)) {
- DoAfterDoTransaction(aTxn);
- }
-
- // no need to check rv here, don't lose result of operation
- selection->EndBatchChanges();
-
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::EnableUndo(bool aEnable)
-{
- if (aEnable) {
- if (!mTxnMgr) {
- mTxnMgr = new nsTransactionManager();
- }
- mTxnMgr->SetMaxTransactionCount(-1);
- } else if (mTxnMgr) {
- // disable the transaction manager if it is enabled
- mTxnMgr->Clear();
- mTxnMgr->SetMaxTransactionCount(0);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::GetNumberOfUndoItems(int32_t* aNumItems)
-{
- *aNumItems = 0;
- return mTxnMgr ? mTxnMgr->GetNumberOfUndoItems(aNumItems) : NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::GetNumberOfRedoItems(int32_t* aNumItems)
-{
- *aNumItems = 0;
- return mTxnMgr ? mTxnMgr->GetNumberOfRedoItems(aNumItems) : NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::GetTransactionManager(nsITransactionManager** aTxnManager)
-{
- NS_ENSURE_ARG_POINTER(aTxnManager);
-
- *aTxnManager = nullptr;
- NS_ENSURE_TRUE(mTxnMgr, NS_ERROR_FAILURE);
-
- NS_ADDREF(*aTxnManager = mTxnMgr);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::SetTransactionManager(nsITransactionManager* aTxnManager)
-{
- NS_ENSURE_TRUE(aTxnManager, NS_ERROR_FAILURE);
-
- // nsITransactionManager is builtinclass, so this is safe
- mTxnMgr = static_cast<nsTransactionManager*>(aTxnManager);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::Undo(uint32_t aCount)
-{
- ForceCompositionEnd();
-
- bool hasTxnMgr, hasTransaction = false;
- CanUndo(&hasTxnMgr, &hasTransaction);
- NS_ENSURE_TRUE(hasTransaction, NS_OK);
-
- AutoRules beginRulesSniffing(this, EditAction::undo, nsIEditor::eNone);
-
- if (!mTxnMgr) {
- return NS_OK;
- }
-
- RefPtr<nsTransactionManager> txnMgr = mTxnMgr;
- for (uint32_t i = 0; i < aCount; ++i) {
- nsresult rv = txnMgr->UndoTransaction();
- NS_ENSURE_SUCCESS(rv, rv);
-
- DoAfterUndoTransaction();
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::CanUndo(bool* aIsEnabled,
- bool* aCanUndo)
-{
- NS_ENSURE_TRUE(aIsEnabled && aCanUndo, NS_ERROR_NULL_POINTER);
- *aIsEnabled = !!mTxnMgr;
- if (*aIsEnabled) {
- int32_t numTxns = 0;
- mTxnMgr->GetNumberOfUndoItems(&numTxns);
- *aCanUndo = !!numTxns;
- } else {
- *aCanUndo = false;
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::Redo(uint32_t aCount)
-{
- bool hasTxnMgr, hasTransaction = false;
- CanRedo(&hasTxnMgr, &hasTransaction);
- NS_ENSURE_TRUE(hasTransaction, NS_OK);
-
- AutoRules beginRulesSniffing(this, EditAction::redo, nsIEditor::eNone);
-
- if (!mTxnMgr) {
- return NS_OK;
- }
-
- RefPtr<nsTransactionManager> txnMgr = mTxnMgr;
- for (uint32_t i = 0; i < aCount; ++i) {
- nsresult rv = txnMgr->RedoTransaction();
- NS_ENSURE_SUCCESS(rv, rv);
-
- DoAfterRedoTransaction();
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::CanRedo(bool* aIsEnabled, bool* aCanRedo)
-{
- NS_ENSURE_TRUE(aIsEnabled && aCanRedo, NS_ERROR_NULL_POINTER);
-
- *aIsEnabled = !!mTxnMgr;
- if (*aIsEnabled) {
- int32_t numTxns = 0;
- mTxnMgr->GetNumberOfRedoItems(&numTxns);
- *aCanRedo = !!numTxns;
- } else {
- *aCanRedo = false;
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::BeginTransaction()
-{
- BeginUpdateViewBatch();
-
- if (mTxnMgr) {
- RefPtr<nsTransactionManager> txnMgr = mTxnMgr;
- txnMgr->BeginBatch(nullptr);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::EndTransaction()
-{
- if (mTxnMgr) {
- RefPtr<nsTransactionManager> txnMgr = mTxnMgr;
- txnMgr->EndBatch(false);
- }
-
- EndUpdateViewBatch();
-
- return NS_OK;
-}
-
-
-// These two routines are similar to the above, but do not use
-// the transaction managers batching feature. Instead we use
-// a placeholder transaction to wrap up any further transaction
-// while the batch is open. The advantage of this is that
-// placeholder transactions can later merge, if needed. Merging
-// is unavailable between transaction manager batches.
-
-NS_IMETHODIMP
-EditorBase::BeginPlaceHolderTransaction(nsIAtom* aName)
-{
- MOZ_ASSERT(mPlaceholderBatch >= 0, "negative placeholder batch count!");
- if (!mPlaceholderBatch) {
- NotifyEditorObservers(eNotifyEditorObserversOfBefore);
- // time to turn on the batch
- BeginUpdateViewBatch();
- mPlaceholderTransactionWeak = nullptr;
- mPlaceholderName = aName;
- RefPtr<Selection> selection = GetSelection();
- if (selection) {
- mSelState = MakeUnique<SelectionState>();
- mSelState->SaveSelection(selection);
- // Composition transaction can modify multiple nodes and it merges text
- // node for ime into single text node.
- // So if current selection is into IME text node, it might be failed
- // to restore selection by UndoTransaction.
- // So we need update selection by range updater.
- if (mPlaceholderName == nsGkAtoms::IMETxnName) {
- mRangeUpdater.RegisterSelectionState(*mSelState);
- }
- }
- }
- mPlaceholderBatch++;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::EndPlaceHolderTransaction()
-{
- MOZ_ASSERT(mPlaceholderBatch > 0,
- "zero or negative placeholder batch count when ending batch!");
- if (mPlaceholderBatch == 1) {
- RefPtr<Selection> selection = GetSelection();
-
- // By making the assumption that no reflow happens during the calls
- // to EndUpdateViewBatch and ScrollSelectionIntoView, we are able to
- // allow the selection to cache a frame offset which is used by the
- // caret drawing code. We only enable this cache here; at other times,
- // we have no way to know whether reflow invalidates it
- // See bugs 35296 and 199412.
- if (selection) {
- selection->SetCanCacheFrameOffset(true);
- }
-
- {
- // Hide the caret here to avoid hiding it twice, once in EndUpdateViewBatch
- // and once in ScrollSelectionIntoView.
- RefPtr<nsCaret> caret;
- nsCOMPtr<nsIPresShell> presShell = GetPresShell();
-
- if (presShell) {
- caret = presShell->GetCaret();
- }
-
- // time to turn off the batch
- EndUpdateViewBatch();
- // make sure selection is in view
-
- // After ScrollSelectionIntoView(), the pending notifications might be
- // flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
- ScrollSelectionIntoView(false);
- }
-
- // cached for frame offset are Not available now
- if (selection) {
- selection->SetCanCacheFrameOffset(false);
- }
-
- if (mSelState) {
- // we saved the selection state, but never got to hand it to placeholder
- // (else we ould have nulled out this pointer), so destroy it to prevent leaks.
- if (mPlaceholderName == nsGkAtoms::IMETxnName) {
- mRangeUpdater.DropSelectionState(*mSelState);
- }
- mSelState = nullptr;
- }
- // We might have never made a placeholder if no action took place.
- if (mPlaceholderTransactionWeak) {
- RefPtr<PlaceholderTransaction> placeholderTransaction =
- mPlaceholderTransactionWeak.get();
- placeholderTransaction->EndPlaceHolderBatch();
- // notify editor observers of action but if composing, it's done by
- // compositionchange event handler.
- if (!mComposition) {
- NotifyEditorObservers(eNotifyEditorObserversOfEnd);
- }
- } else {
- NotifyEditorObservers(eNotifyEditorObserversOfCancel);
- }
- }
- mPlaceholderBatch--;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::ShouldTxnSetSelection(bool* aResult)
-{
- NS_ENSURE_TRUE(aResult, NS_ERROR_NULL_POINTER);
- *aResult = mShouldTxnSetSelection;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::SetShouldTxnSetSelection(bool aShould)
-{
- mShouldTxnSetSelection = aShould;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::GetDocumentIsEmpty(bool* aDocumentIsEmpty)
-{
- *aDocumentIsEmpty = true;
-
- dom::Element* root = GetRoot();
- NS_ENSURE_TRUE(root, NS_ERROR_NULL_POINTER);
-
- *aDocumentIsEmpty = !root->HasChildren();
- return NS_OK;
-}
-
-// XXX: The rule system should tell us which node to select all on (ie, the
-// root, or the body)
-NS_IMETHODIMP
-EditorBase::SelectAll()
-{
- // XXX Why doesn't this check if the document is alive?
- if (!IsInitialized()) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- ForceCompositionEnd();
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
- return SelectEntireDocument(selection);
-}
-
-NS_IMETHODIMP
-EditorBase::BeginningOfDocument()
-{
- // XXX Why doesn't this check if the document is alive?
- if (!IsInitialized()) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // get the selection
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
-
- // get the root element
- dom::Element* rootElement = GetRoot();
- NS_ENSURE_TRUE(rootElement, NS_ERROR_NULL_POINTER);
-
- // find first editable thingy
- nsCOMPtr<nsINode> firstNode = GetFirstEditableNode(rootElement);
- if (!firstNode) {
- // just the root node, set selection to inside the root
- return selection->CollapseNative(rootElement, 0);
- }
-
- if (firstNode->NodeType() == nsIDOMNode::TEXT_NODE) {
- // If firstNode is text, set selection to beginning of the text node.
- return selection->CollapseNative(firstNode, 0);
- }
-
- // Otherwise, it's a leaf node and we set the selection just in front of it.
- nsCOMPtr<nsIContent> parent = firstNode->GetParent();
- if (!parent) {
- return NS_ERROR_NULL_POINTER;
- }
-
- int32_t offsetInParent = parent->IndexOf(firstNode);
- return selection->CollapseNative(parent, offsetInParent);
-}
-
-NS_IMETHODIMP
-EditorBase::EndOfDocument()
-{
- // XXX Why doesn't this check if the document is alive?
- if (NS_WARN_IF(!IsInitialized())) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // get selection
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- // get the root element
- nsINode* node = GetRoot();
- NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
- nsINode* child = node->GetLastChild();
-
- while (child && IsContainer(child->AsDOMNode())) {
- node = child;
- child = node->GetLastChild();
- }
-
- uint32_t length = node->Length();
- return selection->CollapseNative(node, int32_t(length));
-}
-
-NS_IMETHODIMP
-EditorBase::GetDocumentModified(bool* outDocModified)
-{
- NS_ENSURE_TRUE(outDocModified, NS_ERROR_NULL_POINTER);
-
- int32_t modCount = 0;
- GetModificationCount(&modCount);
-
- *outDocModified = (modCount != 0);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::GetDocumentCharacterSet(nsACString& characterSet)
-{
- nsCOMPtr<nsIDocument> document = GetDocument();
- if (NS_WARN_IF(!document)) {
- return NS_ERROR_UNEXPECTED;
- }
- characterSet = document->GetDocumentCharacterSet();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::SetDocumentCharacterSet(const nsACString& characterSet)
-{
- nsCOMPtr<nsIDocument> document = GetDocument();
- if (NS_WARN_IF(!document)) {
- return NS_ERROR_UNEXPECTED;
- }
- document->SetDocumentCharacterSet(characterSet);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::Cut()
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-EditorBase::CanCut(bool* aCanCut)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-EditorBase::Copy()
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-EditorBase::CanCopy(bool* aCanCut)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-EditorBase::CanDelete(bool* aCanDelete)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-EditorBase::Paste(int32_t aSelectionType)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-EditorBase::PasteTransferable(nsITransferable* aTransferable)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-EditorBase::CanPaste(int32_t aSelectionType, bool* aCanPaste)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-EditorBase::CanPasteTransferable(nsITransferable* aTransferable,
- bool* aCanPaste)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-EditorBase::SetAttribute(nsIDOMElement* aElement,
- const nsAString& aAttribute,
- const nsAString& aValue)
-{
- if (NS_WARN_IF(aAttribute.IsEmpty())) {
- return NS_ERROR_FAILURE;
- }
- nsCOMPtr<Element> element = do_QueryInterface(aElement);
- NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
- nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
-
- return SetAttribute(element, attribute, aValue);
-}
-
-nsresult
-EditorBase::SetAttribute(Element* aElement,
- nsIAtom* aAttribute,
- const nsAString& aValue)
-{
- RefPtr<ChangeAttributeTransaction> transaction =
- CreateTxnForSetAttribute(*aElement, *aAttribute, aValue);
- return DoTransaction(transaction);
-}
-
-NS_IMETHODIMP
-EditorBase::GetAttributeValue(nsIDOMElement* aElement,
- const nsAString& aAttribute,
- nsAString& aResultValue,
- bool* aResultIsSet)
-{
- NS_ENSURE_TRUE(aResultIsSet, NS_ERROR_NULL_POINTER);
- *aResultIsSet = false;
- if (!aElement) {
- return NS_OK;
- }
- nsAutoString value;
- nsresult rv = aElement->GetAttribute(aAttribute, value);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!DOMStringIsNull(value)) {
- *aResultIsSet = true;
- aResultValue = value;
- }
- return rv;
-}
-
-NS_IMETHODIMP
-EditorBase::RemoveAttribute(nsIDOMElement* aElement,
- const nsAString& aAttribute)
-{
- if (NS_WARN_IF(aAttribute.IsEmpty())) {
- return NS_ERROR_FAILURE;
- }
- nsCOMPtr<Element> element = do_QueryInterface(aElement);
- NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
- nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
-
- return RemoveAttribute(element, attribute);
-}
-
-nsresult
-EditorBase::RemoveAttribute(Element* aElement,
- nsIAtom* aAttribute)
-{
- RefPtr<ChangeAttributeTransaction> transaction =
- CreateTxnForRemoveAttribute(*aElement, *aAttribute);
- return DoTransaction(transaction);
-}
-
-bool
-EditorBase::OutputsMozDirty()
-{
- // Return true for Composer (!eEditorAllowInteraction) or mail
- // (eEditorMailMask), but false for webpages.
- return !(mFlags & nsIPlaintextEditor::eEditorAllowInteraction) ||
- (mFlags & nsIPlaintextEditor::eEditorMailMask);
-}
-
-NS_IMETHODIMP
-EditorBase::MarkNodeDirty(nsIDOMNode* aNode)
-{
- // Mark the node dirty, but not for webpages (bug 599983)
- if (!OutputsMozDirty()) {
- return NS_OK;
- }
- nsCOMPtr<dom::Element> element = do_QueryInterface(aNode);
- if (element) {
- element->SetAttr(kNameSpaceID_None, nsGkAtoms::mozdirty,
- EmptyString(), false);
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::GetInlineSpellChecker(bool autoCreate,
- nsIInlineSpellChecker** aInlineSpellChecker)
-{
- NS_ENSURE_ARG_POINTER(aInlineSpellChecker);
-
- if (mDidPreDestroy) {
- // Don't allow people to get or create the spell checker once the editor
- // is going away.
- *aInlineSpellChecker = nullptr;
- return autoCreate ? NS_ERROR_NOT_AVAILABLE : NS_OK;
- }
-
- // We don't want to show the spell checking UI if there are no spell check dictionaries available.
- bool canSpell = mozInlineSpellChecker::CanEnableInlineSpellChecking();
- if (!canSpell) {
- *aInlineSpellChecker = nullptr;
- return NS_ERROR_FAILURE;
- }
-
- nsresult rv;
- if (!mInlineSpellChecker && autoCreate) {
- mInlineSpellChecker = do_CreateInstance(MOZ_INLINESPELLCHECKER_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- if (mInlineSpellChecker) {
- rv = mInlineSpellChecker->Init(this);
- if (NS_FAILED(rv)) {
- mInlineSpellChecker = nullptr;
- }
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- NS_IF_ADDREF(*aInlineSpellChecker = mInlineSpellChecker);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::SyncRealTimeSpell()
-{
- bool enable = GetDesiredSpellCheckState();
-
- // Initializes mInlineSpellChecker
- nsCOMPtr<nsIInlineSpellChecker> spellChecker;
- GetInlineSpellChecker(enable, getter_AddRefs(spellChecker));
-
- if (mInlineSpellChecker) {
- // We might have a mInlineSpellChecker even if there are no dictionaries
- // available since we don't destroy the mInlineSpellChecker when the last
- // dictionariy is removed, but in that case spellChecker is null
- mInlineSpellChecker->SetEnableRealTimeSpell(enable && spellChecker);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::SetSpellcheckUserOverride(bool enable)
-{
- mSpellcheckCheckboxState = enable ? eTriTrue : eTriFalse;
-
- return SyncRealTimeSpell();
-}
-
-NS_IMETHODIMP
-EditorBase::CreateNode(const nsAString& aTag,
- nsIDOMNode* aParent,
- int32_t aPosition,
- nsIDOMNode** aNewNode)
-{
- nsCOMPtr<nsIAtom> tag = NS_Atomize(aTag);
- nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
- NS_ENSURE_STATE(parent);
- *aNewNode = GetAsDOMNode(CreateNode(tag, parent, aPosition).take());
- NS_ENSURE_STATE(*aNewNode);
- return NS_OK;
-}
-
-already_AddRefed<Element>
-EditorBase::CreateNode(nsIAtom* aTag,
- nsINode* aParent,
- int32_t aPosition)
-{
- MOZ_ASSERT(aTag && aParent);
-
- AutoRules beginRulesSniffing(this, EditAction::createNode, nsIEditor::eNext);
-
- {
- AutoActionListenerArray listeners(mActionListeners);
- for (auto& listener : listeners) {
- listener->WillCreateNode(nsDependentAtomString(aTag),
- GetAsDOMNode(aParent), aPosition);
- }
- }
-
- nsCOMPtr<Element> ret;
-
- RefPtr<CreateElementTransaction> transaction =
- CreateTxnForCreateElement(*aTag, *aParent, aPosition);
- nsresult rv = DoTransaction(transaction);
- if (NS_SUCCEEDED(rv)) {
- ret = transaction->GetNewNode();
- MOZ_ASSERT(ret);
- }
-
- mRangeUpdater.SelAdjCreateNode(aParent, aPosition);
-
- {
- AutoActionListenerArray listeners(mActionListeners);
- for (auto& listener : listeners) {
- listener->DidCreateNode(nsDependentAtomString(aTag), GetAsDOMNode(ret),
- GetAsDOMNode(aParent), aPosition, rv);
- }
- }
-
- return ret.forget();
-}
-
-NS_IMETHODIMP
-EditorBase::InsertNode(nsIDOMNode* aNode,
- nsIDOMNode* aParent,
- int32_t aPosition)
-{
- nsCOMPtr<nsIContent> node = do_QueryInterface(aNode);
- nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
- NS_ENSURE_TRUE(node && parent, NS_ERROR_NULL_POINTER);
-
- return InsertNode(*node, *parent, aPosition);
-}
-
-nsresult
-EditorBase::InsertNode(nsIContent& aNode,
- nsINode& aParent,
- int32_t aPosition)
-{
- AutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext);
-
- {
- AutoActionListenerArray listeners(mActionListeners);
- for (auto& listener : listeners) {
- listener->WillInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(),
- aPosition);
- }
- }
-
- RefPtr<InsertNodeTransaction> transaction =
- CreateTxnForInsertNode(aNode, aParent, aPosition);
- nsresult rv = DoTransaction(transaction);
-
- mRangeUpdater.SelAdjInsertNode(aParent.AsDOMNode(), aPosition);
-
- {
- AutoActionListenerArray listeners(mActionListeners);
- for (auto& listener : listeners) {
- listener->DidInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(), aPosition,
- rv);
- }
- }
-
- return rv;
-}
-
-NS_IMETHODIMP
-EditorBase::SplitNode(nsIDOMNode* aNode,
- int32_t aOffset,
- nsIDOMNode** aNewLeftNode)
-{
- nsCOMPtr<nsIContent> node = do_QueryInterface(aNode);
- NS_ENSURE_STATE(node);
- ErrorResult rv;
- nsCOMPtr<nsIContent> newNode = SplitNode(*node, aOffset, rv);
- *aNewLeftNode = GetAsDOMNode(newNode.forget().take());
- return rv.StealNSResult();
-}
-
-nsIContent*
-EditorBase::SplitNode(nsIContent& aNode,
- int32_t aOffset,
- ErrorResult& aResult)
-{
- AutoRules beginRulesSniffing(this, EditAction::splitNode, nsIEditor::eNext);
-
- {
- AutoActionListenerArray listeners(mActionListeners);
- for (auto& listener : listeners) {
- listener->WillSplitNode(aNode.AsDOMNode(), aOffset);
- }
- }
-
- RefPtr<SplitNodeTransaction> transaction =
- CreateTxnForSplitNode(aNode, aOffset);
- aResult = DoTransaction(transaction);
-
- nsCOMPtr<nsIContent> newNode = aResult.Failed() ? nullptr
- : transaction->GetNewNode();
-
- mRangeUpdater.SelAdjSplitNode(aNode, aOffset, newNode);
-
- nsresult rv = aResult.StealNSResult();
- {
- AutoActionListenerArray listeners(mActionListeners);
- for (auto& listener : listeners) {
- listener->DidSplitNode(aNode.AsDOMNode(), aOffset, GetAsDOMNode(newNode),
- rv);
- }
- }
- // Note: result might be a success code, so we can't use Throw() to
- // set it on aResult.
- aResult = rv;
-
- return newNode;
-}
-
-NS_IMETHODIMP
-EditorBase::JoinNodes(nsIDOMNode* aLeftNode,
- nsIDOMNode* aRightNode,
- nsIDOMNode*)
-{
- nsCOMPtr<nsINode> leftNode = do_QueryInterface(aLeftNode);
- nsCOMPtr<nsINode> rightNode = do_QueryInterface(aRightNode);
- NS_ENSURE_STATE(leftNode && rightNode && leftNode->GetParentNode());
- return JoinNodes(*leftNode, *rightNode);
-}
-
-nsresult
-EditorBase::JoinNodes(nsINode& aLeftNode,
- nsINode& aRightNode)
-{
- nsCOMPtr<nsINode> parent = aLeftNode.GetParentNode();
- MOZ_ASSERT(parent);
-
- AutoRules beginRulesSniffing(this, EditAction::joinNode,
- nsIEditor::ePrevious);
-
- // Remember some values; later used for saved selection updating.
- // Find the offset between the nodes to be joined.
- int32_t offset = parent->IndexOf(&aRightNode);
- // Find the number of children of the lefthand node
- uint32_t oldLeftNodeLen = aLeftNode.Length();
-
- {
- AutoActionListenerArray listeners(mActionListeners);
- for (auto& listener : listeners) {
- listener->WillJoinNodes(aLeftNode.AsDOMNode(), aRightNode.AsDOMNode(),
- parent->AsDOMNode());
- }
- }
-
- nsresult rv = NS_OK;
- RefPtr<JoinNodeTransaction> transaction =
- CreateTxnForJoinNode(aLeftNode, aRightNode);
- if (transaction) {
- rv = DoTransaction(transaction);
- }
-
- mRangeUpdater.SelAdjJoinNodes(aLeftNode, aRightNode, *parent, offset,
- (int32_t)oldLeftNodeLen);
-
- {
- AutoActionListenerArray listeners(mActionListeners);
- for (auto& listener : listeners) {
- listener->DidJoinNodes(aLeftNode.AsDOMNode(), aRightNode.AsDOMNode(),
- parent->AsDOMNode(), rv);
- }
- }
-
- return rv;
-}
-
-NS_IMETHODIMP
-EditorBase::DeleteNode(nsIDOMNode* aNode)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- NS_ENSURE_STATE(node);
- return DeleteNode(node);
-}
-
-nsresult
-EditorBase::DeleteNode(nsINode* aNode)
-{
- AutoRules beginRulesSniffing(this, EditAction::createNode,
- nsIEditor::ePrevious);
-
- // save node location for selection updating code.
- {
- AutoActionListenerArray listeners(mActionListeners);
- for (auto& listener : listeners) {
- listener->WillDeleteNode(aNode->AsDOMNode());
- }
- }
-
- RefPtr<DeleteNodeTransaction> transaction;
- nsresult rv = CreateTxnForDeleteNode(aNode, getter_AddRefs(transaction));
- if (NS_SUCCEEDED(rv)) {
- rv = DoTransaction(transaction);
- }
-
- {
- AutoActionListenerArray listeners(mActionListeners);
- for (auto& listener : listeners) {
- listener->DidDeleteNode(aNode->AsDOMNode(), rv);
- }
- }
-
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
-}
-
-/**
- * ReplaceContainer() replaces inNode with a new node (outNode) which is
- * constructed to be of type aNodeType. Put inNodes children into outNode.
- * Callers responsibility to make sure inNode's children can go in outNode.
- */
-already_AddRefed<Element>
-EditorBase::ReplaceContainer(Element* aOldContainer,
- nsIAtom* aNodeType,
- nsIAtom* aAttribute,
- const nsAString* aValue,
- ECloneAttributes aCloneAttributes)
-{
- MOZ_ASSERT(aOldContainer && aNodeType);
-
- nsCOMPtr<nsIContent> parent = aOldContainer->GetParent();
- NS_ENSURE_TRUE(parent, nullptr);
-
- int32_t offset = parent->IndexOf(aOldContainer);
-
- // create new container
- nsCOMPtr<Element> ret = CreateHTMLContent(aNodeType);
- NS_ENSURE_TRUE(ret, nullptr);
-
- // set attribute if needed
- if (aAttribute && aValue && aAttribute != nsGkAtoms::_empty) {
- nsresult rv = ret->SetAttr(kNameSpaceID_None, aAttribute, *aValue, true);
- NS_ENSURE_SUCCESS(rv, nullptr);
- }
- if (aCloneAttributes == eCloneAttributes) {
- CloneAttributes(ret, aOldContainer);
- }
-
- // notify our internal selection state listener
- // (Note: An AutoSelectionRestorer object must be created
- // before calling this to initialize mRangeUpdater)
- AutoReplaceContainerSelNotify selStateNotify(mRangeUpdater, aOldContainer,
- ret);
- {
- AutoTransactionsConserveSelection conserveSelection(this);
- while (aOldContainer->HasChildren()) {
- nsCOMPtr<nsIContent> child = aOldContainer->GetFirstChild();
-
- nsresult rv = DeleteNode(child);
- NS_ENSURE_SUCCESS(rv, nullptr);
-
- rv = InsertNode(*child, *ret, -1);
- NS_ENSURE_SUCCESS(rv, nullptr);
- }
- }
-
- // insert new container into tree
- nsresult rv = InsertNode(*ret, *parent, offset);
- NS_ENSURE_SUCCESS(rv, nullptr);
-
- // delete old container
- rv = DeleteNode(aOldContainer);
- NS_ENSURE_SUCCESS(rv, nullptr);
-
- return ret.forget();
-}
-
-/**
- * RemoveContainer() removes inNode, reparenting its children (if any) into the
- * parent of inNode.
- */
-nsresult
-EditorBase::RemoveContainer(nsIContent* aNode)
-{
- MOZ_ASSERT(aNode);
-
- nsCOMPtr<nsINode> parent = aNode->GetParentNode();
- NS_ENSURE_STATE(parent);
-
- int32_t offset = parent->IndexOf(aNode);
-
- // Loop through the children of inNode and promote them into inNode's parent
- uint32_t nodeOrigLen = aNode->GetChildCount();
-
- // notify our internal selection state listener
- AutoRemoveContainerSelNotify selNotify(mRangeUpdater, aNode, parent,
- offset, nodeOrigLen);
-
- while (aNode->HasChildren()) {
- nsCOMPtr<nsIContent> child = aNode->GetLastChild();
- nsresult rv = DeleteNode(child);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = InsertNode(*child, *parent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return DeleteNode(aNode);
-}
-
-/**
- * InsertContainerAbove() inserts a new parent for inNode, which is contructed
- * to be of type aNodeType. outNode becomes a child of inNode's earlier
- * parent. Caller's responsibility to make sure inNode's can be child of
- * outNode, and outNode can be child of old parent.
- */
-already_AddRefed<Element>
-EditorBase::InsertContainerAbove(nsIContent* aNode,
- nsIAtom* aNodeType,
- nsIAtom* aAttribute,
- const nsAString* aValue)
-{
- MOZ_ASSERT(aNode && aNodeType);
-
- nsCOMPtr<nsIContent> parent = aNode->GetParent();
- NS_ENSURE_TRUE(parent, nullptr);
- int32_t offset = parent->IndexOf(aNode);
-
- // Create new container
- nsCOMPtr<Element> newContent = CreateHTMLContent(aNodeType);
- NS_ENSURE_TRUE(newContent, nullptr);
-
- // Set attribute if needed
- if (aAttribute && aValue && aAttribute != nsGkAtoms::_empty) {
- nsresult rv =
- newContent->SetAttr(kNameSpaceID_None, aAttribute, *aValue, true);
- NS_ENSURE_SUCCESS(rv, nullptr);
- }
-
- // Notify our internal selection state listener
- AutoInsertContainerSelNotify selNotify(mRangeUpdater);
-
- // Put inNode in new parent, outNode
- nsresult rv = DeleteNode(aNode);
- NS_ENSURE_SUCCESS(rv, nullptr);
-
- {
- AutoTransactionsConserveSelection conserveSelection(this);
- rv = InsertNode(*aNode, *newContent, 0);
- NS_ENSURE_SUCCESS(rv, nullptr);
- }
-
- // Put new parent in doc
- rv = InsertNode(*newContent, *parent, offset);
- NS_ENSURE_SUCCESS(rv, nullptr);
-
- return newContent.forget();
-}
-
-/**
- * MoveNode() moves aNode to {aParent,aOffset}.
- */
-nsresult
-EditorBase::MoveNode(nsIContent* aNode,
- nsINode* aParent,
- int32_t aOffset)
-{
- MOZ_ASSERT(aNode);
- MOZ_ASSERT(aParent);
- MOZ_ASSERT(aOffset == -1 ||
- (0 <= aOffset &&
- AssertedCast<uint32_t>(aOffset) <= aParent->Length()));
-
- nsCOMPtr<nsINode> oldParent = aNode->GetParentNode();
- int32_t oldOffset = oldParent ? oldParent->IndexOf(aNode) : -1;
-
- if (aOffset == -1) {
- // Magic value meaning "move to end of aParent"
- aOffset = AssertedCast<int32_t>(aParent->Length());
- }
-
- // Don't do anything if it's already in right place
- if (aParent == oldParent && aOffset == oldOffset) {
- return NS_OK;
- }
-
- // Notify our internal selection state listener
- AutoMoveNodeSelNotify selNotify(mRangeUpdater, oldParent, oldOffset,
- aParent, aOffset);
-
- // Need to adjust aOffset if we're moving aNode later in its current parent
- if (aParent == oldParent && oldOffset < aOffset) {
- // When we delete aNode, it will make the offsets after it off by one
- aOffset--;
- }
-
- // Hold a reference so aNode doesn't go away when we remove it (bug 772282)
- nsCOMPtr<nsINode> kungFuDeathGrip = aNode;
-
- nsresult rv = DeleteNode(aNode);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return InsertNode(*aNode, *aParent, aOffset);
-}
-
-NS_IMETHODIMP
-EditorBase::AddEditorObserver(nsIEditorObserver* aObserver)
-{
- // we don't keep ownership of the observers. They must
- // remove themselves as observers before they are destroyed.
-
- NS_ENSURE_TRUE(aObserver, NS_ERROR_NULL_POINTER);
-
- // Make sure the listener isn't already on the list
- if (!mEditorObservers.Contains(aObserver)) {
- mEditorObservers.AppendElement(*aObserver);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::RemoveEditorObserver(nsIEditorObserver* aObserver)
-{
- NS_ENSURE_TRUE(aObserver, NS_ERROR_FAILURE);
-
- mEditorObservers.RemoveElement(aObserver);
-
- return NS_OK;
-}
-
-class EditorInputEventDispatcher final : public Runnable
-{
-public:
- EditorInputEventDispatcher(EditorBase* aEditorBase,
- nsIContent* aTarget,
- bool aIsComposing)
- : mEditorBase(aEditorBase)
- , mTarget(aTarget)
- , mIsComposing(aIsComposing)
- {
- }
-
- NS_IMETHOD Run() override
- {
- // Note that we don't need to check mDispatchInputEvent here. We need
- // to check it only when the editor requests to dispatch the input event.
-
- if (!mTarget->IsInComposedDoc()) {
- return NS_OK;
- }
-
- nsCOMPtr<nsIPresShell> ps = mEditorBase->GetPresShell();
- if (!ps) {
- return NS_OK;
- }
-
- nsCOMPtr<nsIWidget> widget = mEditorBase->GetWidget();
- if (!widget) {
- return NS_OK;
- }
-
- // Even if the change is caused by untrusted event, we need to dispatch
- // trusted input event since it's a fact.
- InternalEditorInputEvent inputEvent(true, eEditorInput, widget);
- inputEvent.mTime = static_cast<uint64_t>(PR_Now() / 1000);
- inputEvent.mIsComposing = mIsComposing;
- nsEventStatus status = nsEventStatus_eIgnore;
- nsresult rv =
- ps->HandleEventWithTarget(&inputEvent, nullptr, mTarget, &status);
- NS_ENSURE_SUCCESS(rv, NS_OK); // print the warning if error
- return NS_OK;
- }
-
-private:
- RefPtr<EditorBase> mEditorBase;
- nsCOMPtr<nsIContent> mTarget;
- bool mIsComposing;
-};
-
-void
-EditorBase::NotifyEditorObservers(NotificationForEditorObservers aNotification)
-{
- // Copy the observers since EditAction()s can modify mEditorObservers.
- AutoEditorObserverArray observers(mEditorObservers);
- switch (aNotification) {
- case eNotifyEditorObserversOfEnd:
- mIsInEditAction = false;
- for (auto& observer : observers) {
- observer->EditAction();
- }
-
- if (!mDispatchInputEvent) {
- return;
- }
-
- FireInputEvent();
- break;
- case eNotifyEditorObserversOfBefore:
- if (NS_WARN_IF(mIsInEditAction)) {
- break;
- }
- mIsInEditAction = true;
- for (auto& observer : observers) {
- observer->BeforeEditAction();
- }
- break;
- case eNotifyEditorObserversOfCancel:
- mIsInEditAction = false;
- for (auto& observer : observers) {
- observer->CancelEditAction();
- }
- break;
- default:
- MOZ_CRASH("Handle all notifications here");
- break;
- }
-}
-
-void
-EditorBase::FireInputEvent()
-{
- // We don't need to dispatch multiple input events if there is a pending
- // input event. However, it may have different event target. If we resolved
- // this issue, we need to manage the pending events in an array. But it's
- // overwork. We don't need to do it for the very rare case.
-
- nsCOMPtr<nsIContent> target = GetInputEventTargetContent();
- NS_ENSURE_TRUE_VOID(target);
-
- // NOTE: Don't refer IsIMEComposing() because it returns false even before
- // compositionend. However, DOM Level 3 Events defines it should be
- // true after compositionstart and before compositionend.
- nsContentUtils::AddScriptRunner(
- new EditorInputEventDispatcher(this, target, !!GetComposition()));
-}
-
-NS_IMETHODIMP
-EditorBase::AddEditActionListener(nsIEditActionListener* aListener)
-{
- NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER);
-
- // Make sure the listener isn't already on the list
- if (!mActionListeners.Contains(aListener)) {
- mActionListeners.AppendElement(*aListener);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::RemoveEditActionListener(nsIEditActionListener* aListener)
-{
- NS_ENSURE_TRUE(aListener, NS_ERROR_FAILURE);
-
- mActionListeners.RemoveElement(aListener);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::AddDocumentStateListener(nsIDocumentStateListener* aListener)
-{
- NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER);
-
- if (!mDocStateListeners.Contains(aListener)) {
- mDocStateListeners.AppendElement(*aListener);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::RemoveDocumentStateListener(nsIDocumentStateListener* aListener)
-{
- NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER);
-
- mDocStateListeners.RemoveElement(aListener);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::OutputToString(const nsAString& aFormatType,
- uint32_t aFlags,
- nsAString& aOutputString)
-{
- // these should be implemented by derived classes.
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-EditorBase::OutputToStream(nsIOutputStream* aOutputStream,
- const nsAString& aFormatType,
- const nsACString& aCharsetOverride,
- uint32_t aFlags)
-{
- // these should be implemented by derived classes.
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-EditorBase::DumpContentTree()
-{
-#ifdef DEBUG
- if (mRootElement) {
- mRootElement->List(stdout);
- }
-#endif
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::DebugDumpContent()
-{
-#ifdef DEBUG
- nsCOMPtr<nsIDocument> document = GetDocument();
- if (NS_WARN_IF(!document)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- nsCOMPtr<nsIDOMHTMLDocument> domHTMLDocument = do_QueryInterface(document);
- if (NS_WARN_IF(!domHTMLDocument)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- nsCOMPtr<nsIDOMHTMLElement> bodyElement;
- domHTMLDocument->GetBody(getter_AddRefs(bodyElement));
- nsCOMPtr<nsIContent> content = do_QueryInterface(bodyElement);
- if (content) {
- content->List();
- }
-#endif
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::DebugUnitTests(int32_t* outNumTests,
- int32_t* outNumTestsFailed)
-{
-#ifdef DEBUG
- NS_NOTREACHED("This should never get called. Overridden by subclasses");
-#endif
- return NS_OK;
-}
-
-bool
-EditorBase::ArePreservingSelection()
-{
- return !(mSavedSel.IsEmpty());
-}
-
-void
-EditorBase::PreserveSelectionAcrossActions(Selection* aSel)
-{
- mSavedSel.SaveSelection(aSel);
- mRangeUpdater.RegisterSelectionState(mSavedSel);
-}
-
-nsresult
-EditorBase::RestorePreservedSelection(Selection* aSel)
-{
- if (mSavedSel.IsEmpty()) {
- return NS_ERROR_FAILURE;
- }
- mSavedSel.RestoreSelection(aSel);
- StopPreservingSelection();
- return NS_OK;
-}
-
-void
-EditorBase::StopPreservingSelection()
-{
- mRangeUpdater.DropSelectionState(mSavedSel);
- mSavedSel.MakeEmpty();
-}
-
-bool
-EditorBase::EnsureComposition(WidgetCompositionEvent* aCompositionEvent)
-{
- if (mComposition) {
- return true;
- }
- // The compositionstart event must cause creating new TextComposition
- // instance at being dispatched by IMEStateManager.
- mComposition = IMEStateManager::GetTextCompositionFor(aCompositionEvent);
- if (!mComposition) {
- // However, TextComposition may be committed before the composition
- // event comes here.
- return false;
- }
- mComposition->StartHandlingComposition(this);
- return true;
-}
-
-nsresult
-EditorBase::BeginIMEComposition(WidgetCompositionEvent* aCompositionEvent)
-{
- MOZ_ASSERT(!mComposition, "There is composition already");
- if (!EnsureComposition(aCompositionEvent)) {
- return NS_OK;
- }
- if (mPhonetic) {
- mPhonetic->Truncate(0);
- }
- return NS_OK;
-}
-
-void
-EditorBase::EndIMEComposition()
-{
- NS_ENSURE_TRUE_VOID(mComposition); // nothing to do
-
- // commit the IME transaction..we can get at it via the transaction mgr.
- // Note that this means IME won't work without an undo stack!
- if (mTxnMgr) {
- nsCOMPtr<nsITransaction> txn = mTxnMgr->PeekUndoStack();
- nsCOMPtr<nsIAbsorbingTransaction> plcTxn = do_QueryInterface(txn);
- if (plcTxn) {
- DebugOnly<nsresult> rv = plcTxn->Commit();
- NS_ASSERTION(NS_SUCCEEDED(rv),
- "nsIAbsorbingTransaction::Commit() failed");
- }
- }
-
- // Composition string may have hidden the caret. Therefore, we need to
- // cancel it here.
- HideCaret(false);
-
- /* reset the data we need to construct a transaction */
- mIMETextNode = nullptr;
- mIMETextOffset = 0;
- mIMETextLength = 0;
- mComposition->EndHandlingComposition(this);
- mComposition = nullptr;
-
- // notify editor observers of action
- NotifyEditorObservers(eNotifyEditorObserversOfEnd);
-}
-
-NS_IMETHODIMP
-EditorBase::GetPhonetic(nsAString& aPhonetic)
-{
- if (mPhonetic) {
- aPhonetic = *mPhonetic;
- } else {
- aPhonetic.Truncate(0);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::ForceCompositionEnd()
-{
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
- if (!ps) {
- return NS_ERROR_NOT_AVAILABLE;
- }
- nsPresContext* pc = ps->GetPresContext();
- if (!pc) {
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- return mComposition ?
- IMEStateManager::NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, pc) : NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::GetPreferredIMEState(IMEState* aState)
-{
- NS_ENSURE_ARG_POINTER(aState);
- aState->mEnabled = IMEState::ENABLED;
- aState->mOpen = IMEState::DONT_CHANGE_OPEN_STATE;
-
- if (IsReadonly() || IsDisabled()) {
- aState->mEnabled = IMEState::DISABLED;
- return NS_OK;
- }
-
- nsCOMPtr<nsIContent> content = GetRoot();
- NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
-
- nsIFrame* frame = content->GetPrimaryFrame();
- NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
-
- switch (frame->StyleUIReset()->mIMEMode) {
- case NS_STYLE_IME_MODE_AUTO:
- if (IsPasswordEditor())
- aState->mEnabled = IMEState::PASSWORD;
- break;
- case NS_STYLE_IME_MODE_DISABLED:
- // we should use password state for |ime-mode: disabled;|.
- aState->mEnabled = IMEState::PASSWORD;
- break;
- case NS_STYLE_IME_MODE_ACTIVE:
- aState->mOpen = IMEState::OPEN;
- break;
- case NS_STYLE_IME_MODE_INACTIVE:
- aState->mOpen = IMEState::CLOSED;
- break;
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::GetComposing(bool* aResult)
-{
- NS_ENSURE_ARG_POINTER(aResult);
- *aResult = IsIMEComposing();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::GetRootElement(nsIDOMElement** aRootElement)
-{
- NS_ENSURE_ARG_POINTER(aRootElement);
- NS_ENSURE_TRUE(mRootElement, NS_ERROR_NOT_AVAILABLE);
- nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(mRootElement);
- rootElement.forget(aRootElement);
- return NS_OK;
-}
-
-/**
- * All editor operations which alter the doc should be prefaced
- * with a call to StartOperation, naming the action and direction.
- */
-NS_IMETHODIMP
-EditorBase::StartOperation(EditAction opID,
- nsIEditor::EDirection aDirection)
-{
- mAction = opID;
- mDirection = aDirection;
- return NS_OK;
-}
-
-/**
- * All editor operations which alter the doc should be followed
- * with a call to EndOperation.
- */
-NS_IMETHODIMP
-EditorBase::EndOperation()
-{
- mAction = EditAction::none;
- mDirection = eNone;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::CloneAttribute(const nsAString& aAttribute,
- nsIDOMNode* aDestNode,
- nsIDOMNode* aSourceNode)
-{
- NS_ENSURE_TRUE(aDestNode && aSourceNode, NS_ERROR_NULL_POINTER);
- if (NS_WARN_IF(aAttribute.IsEmpty())) {
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<Element> destElement = do_QueryInterface(aDestNode);
- nsCOMPtr<Element> sourceElement = do_QueryInterface(aSourceNode);
- NS_ENSURE_TRUE(destElement && sourceElement, NS_ERROR_NO_INTERFACE);
-
- nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
- return CloneAttribute(attribute, destElement, sourceElement);
-}
-
-nsresult
-EditorBase::CloneAttribute(nsIAtom* aAttribute,
- Element* aDestElement,
- Element* aSourceElement)
-{
- nsAutoString attrValue;
- if (aSourceElement->GetAttr(kNameSpaceID_None, aAttribute, attrValue)) {
- return SetAttribute(aDestElement, aAttribute, attrValue);
- }
- return RemoveAttribute(aDestElement, aAttribute);
-}
-
-/**
- * @param aDest Must be a DOM element.
- * @param aSource Must be a DOM element.
- */
-NS_IMETHODIMP
-EditorBase::CloneAttributes(nsIDOMNode* aDest,
- nsIDOMNode* aSource)
-{
- NS_ENSURE_TRUE(aDest && aSource, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<Element> dest = do_QueryInterface(aDest);
- nsCOMPtr<Element> source = do_QueryInterface(aSource);
- NS_ENSURE_TRUE(dest && source, NS_ERROR_NO_INTERFACE);
-
- CloneAttributes(dest, source);
-
- return NS_OK;
-}
-
-void
-EditorBase::CloneAttributes(Element* aDest,
- Element* aSource)
-{
- MOZ_ASSERT(aDest && aSource);
-
- AutoEditBatch beginBatching(this);
-
- // Use transaction system for undo only if destination is already in the
- // document
- NS_ENSURE_TRUE(GetRoot(), );
- bool destInBody = GetRoot()->Contains(aDest);
-
- // Clear existing attributes
- RefPtr<nsDOMAttributeMap> destAttributes = aDest->Attributes();
- while (RefPtr<Attr> attr = destAttributes->Item(0)) {
- if (destInBody) {
- RemoveAttribute(aDest, attr->NodeInfo()->NameAtom());
- } else {
- aDest->UnsetAttr(kNameSpaceID_None, attr->NodeInfo()->NameAtom(), true);
- }
- }
-
- // Set just the attributes that the source element has
- RefPtr<nsDOMAttributeMap> sourceAttributes = aSource->Attributes();
- uint32_t sourceCount = sourceAttributes->Length();
- for (uint32_t i = 0; i < sourceCount; i++) {
- RefPtr<Attr> attr = sourceAttributes->Item(i);
- nsAutoString value;
- attr->GetValue(value);
- if (destInBody) {
- SetAttributeOrEquivalent(aDest, attr->NodeInfo()->NameAtom(), value,
- false);
- } else {
- // The element is not inserted in the document yet, we don't want to put
- // a transaction on the UndoStack
- SetAttributeOrEquivalent(aDest, attr->NodeInfo()->NameAtom(), value,
- true);
- }
- }
-}
-
-NS_IMETHODIMP
-EditorBase::ScrollSelectionIntoView(bool aScrollToAnchor)
-{
- nsCOMPtr<nsISelectionController> selectionController =
- GetSelectionController();
- if (!selectionController) {
- return NS_OK;
- }
-
- int16_t region = nsISelectionController::SELECTION_FOCUS_REGION;
- if (aScrollToAnchor) {
- region = nsISelectionController::SELECTION_ANCHOR_REGION;
- }
- selectionController->ScrollSelectionIntoView(
- nsISelectionController::SELECTION_NORMAL,
- region,
- nsISelectionController::SCROLL_OVERFLOW_HIDDEN);
- return NS_OK;
-}
-
-void
-EditorBase::FindBetterInsertionPoint(nsCOMPtr<nsIDOMNode>& aNode,
- int32_t& aOffset)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- FindBetterInsertionPoint(node, aOffset);
- aNode = do_QueryInterface(node);
-}
-
-void
-EditorBase::FindBetterInsertionPoint(nsCOMPtr<nsINode>& aNode,
- int32_t& aOffset)
-{
- if (aNode->IsNodeOfType(nsINode::eTEXT)) {
- // There is no "better" insertion point.
- return;
- }
-
- if (!IsPlaintextEditor()) {
- // We cannot find "better" insertion point in HTML editor.
- // WARNING: When you add some code to find better node in HTML editor,
- // you need to call this before calling InsertTextImpl() in
- // HTMLEditRules.
- return;
- }
-
- nsCOMPtr<nsINode> node = aNode;
- int32_t offset = aOffset;
-
- nsCOMPtr<nsINode> root = GetRoot();
- if (aNode == root) {
- // In some cases, aNode is the anonymous DIV, and offset is 0. To avoid
- // injecting unneeded text nodes, we first look to see if we have one
- // available. In that case, we'll just adjust node and offset accordingly.
- if (!offset && node->HasChildren() &&
- node->GetFirstChild()->IsNodeOfType(nsINode::eTEXT)) {
- aNode = node->GetFirstChild();
- aOffset = 0;
- return;
- }
-
- // In some other cases, aNode is the anonymous DIV, and offset points to the
- // terminating mozBR. In that case, we'll adjust aInOutNode and
- // aInOutOffset to the preceding text node, if any.
- if (offset > 0 && node->GetChildAt(offset - 1) &&
- node->GetChildAt(offset - 1)->IsNodeOfType(nsINode::eTEXT)) {
- NS_ENSURE_TRUE_VOID(node->Length() <= INT32_MAX);
- aNode = node->GetChildAt(offset - 1);
- aOffset = static_cast<int32_t>(aNode->Length());
- return;
- }
- }
-
- // Sometimes, aNode is the mozBR element itself. In that case, we'll adjust
- // the insertion point to the previous text node, if one exists, or to the
- // parent anonymous DIV.
- if (TextEditUtils::IsMozBR(node) && !offset) {
- if (node->GetPreviousSibling() &&
- node->GetPreviousSibling()->IsNodeOfType(nsINode::eTEXT)) {
- NS_ENSURE_TRUE_VOID(node->Length() <= INT32_MAX);
- aNode = node->GetPreviousSibling();
- aOffset = static_cast<int32_t>(aNode->Length());
- return;
- }
-
- if (node->GetParentNode() && node->GetParentNode() == root) {
- aNode = node->GetParentNode();
- aOffset = 0;
- return;
- }
- }
-}
-
-nsresult
-EditorBase::InsertTextImpl(const nsAString& aStringToInsert,
- nsCOMPtr<nsINode>* aInOutNode,
- int32_t* aInOutOffset,
- nsIDocument* aDoc)
-{
- // NOTE: caller *must* have already used AutoTransactionsConserveSelection
- // stack-based class to turn off txn selection updating. Caller also turned
- // on rules sniffing if desired.
-
- NS_ENSURE_TRUE(aInOutNode && *aInOutNode && aInOutOffset && aDoc,
- NS_ERROR_NULL_POINTER);
-
- if (!ShouldHandleIMEComposition() && aStringToInsert.IsEmpty()) {
- return NS_OK;
- }
-
- // This method doesn't support over INT32_MAX length text since aInOutOffset
- // is int32_t*.
- CheckedInt<int32_t> lengthToInsert(aStringToInsert.Length());
- NS_ENSURE_TRUE(lengthToInsert.isValid(), NS_ERROR_INVALID_ARG);
-
- nsCOMPtr<nsINode> node = *aInOutNode;
- int32_t offset = *aInOutOffset;
-
- // In some cases, the node may be the anonymous div elemnt or a mozBR
- // element. Let's try to look for better insertion point in the nearest
- // text node if there is.
- FindBetterInsertionPoint(node, offset);
-
- if (ShouldHandleIMEComposition()) {
- CheckedInt<int32_t> newOffset;
- if (!node->IsNodeOfType(nsINode::eTEXT)) {
- // create a text node
- RefPtr<nsTextNode> newNode = aDoc->CreateTextNode(EmptyString());
- // then we insert it into the dom tree
- nsresult rv = InsertNode(*newNode, *node, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- node = newNode;
- offset = 0;
- newOffset = lengthToInsert;
- } else {
- newOffset = lengthToInsert + offset;
- NS_ENSURE_TRUE(newOffset.isValid(), NS_ERROR_FAILURE);
- }
- nsresult rv =
- InsertTextIntoTextNodeImpl(aStringToInsert, *node->GetAsText(), offset);
- NS_ENSURE_SUCCESS(rv, rv);
- offset = newOffset.value();
- } else {
- if (node->IsNodeOfType(nsINode::eTEXT)) {
- CheckedInt<int32_t> newOffset = lengthToInsert + offset;
- NS_ENSURE_TRUE(newOffset.isValid(), NS_ERROR_FAILURE);
- // we are inserting text into an existing text node.
- nsresult rv =
- InsertTextIntoTextNodeImpl(aStringToInsert, *node->GetAsText(), offset);
- NS_ENSURE_SUCCESS(rv, rv);
- offset = newOffset.value();
- } else {
- // we are inserting text into a non-text node. first we have to create a
- // textnode (this also populates it with the text)
- RefPtr<nsTextNode> newNode = aDoc->CreateTextNode(aStringToInsert);
- // then we insert it into the dom tree
- nsresult rv = InsertNode(*newNode, *node, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- node = newNode;
- offset = lengthToInsert.value();
- }
- }
-
- *aInOutNode = node;
- *aInOutOffset = offset;
- return NS_OK;
-}
-
-nsresult
-EditorBase::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
- Text& aTextNode,
- int32_t aOffset,
- bool aSuppressIME)
-{
- RefPtr<EditTransactionBase> transaction;
- bool isIMETransaction = false;
- RefPtr<Text> insertedTextNode = &aTextNode;
- int32_t insertedOffset = aOffset;
- // aSuppressIME is used when editor must insert text, yet this text is not
- // part of the current IME operation. Example: adjusting whitespace around an
- // IME insertion.
- if (ShouldHandleIMEComposition() && !aSuppressIME) {
- if (!mIMETextNode) {
- mIMETextNode = &aTextNode;
- mIMETextOffset = aOffset;
- }
- // Modify mPhonetic with raw text input clauses.
- const TextRangeArray* ranges = mComposition->GetRanges();
- for (uint32_t i = 0; i < (ranges ? ranges->Length() : 0); ++i) {
- const TextRange& textRange = ranges->ElementAt(i);
- if (!textRange.Length() ||
- textRange.mRangeType != TextRangeType::eRawClause) {
- continue;
- }
- if (!mPhonetic) {
- mPhonetic = new nsString();
- }
- nsAutoString stringToInsert(aStringToInsert);
- stringToInsert.Mid(*mPhonetic,
- textRange.mStartOffset, textRange.Length());
- }
-
- transaction = CreateTxnForComposition(aStringToInsert);
- isIMETransaction = true;
- // All characters of the composition string will be replaced with
- // aStringToInsert. So, we need to emulate to remove the composition
- // string.
- insertedTextNode = mIMETextNode;
- insertedOffset = mIMETextOffset;
- mIMETextLength = aStringToInsert.Length();
- } else {
- transaction = CreateTxnForInsertText(aStringToInsert, aTextNode, aOffset);
- }
-
- // Let listeners know what's up
- {
- AutoActionListenerArray listeners(mActionListeners);
- for (auto& listener : listeners) {
- listener->WillInsertText(
- static_cast<nsIDOMCharacterData*>(insertedTextNode->AsDOMNode()),
- insertedOffset, aStringToInsert);
- }
- }
-
- // XXX We may not need these view batches anymore. This is handled at a
- // higher level now I believe.
- BeginUpdateViewBatch();
- nsresult rv = DoTransaction(transaction);
- EndUpdateViewBatch();
-
- // let listeners know what happened
- {
- AutoActionListenerArray listeners(mActionListeners);
- for (auto& listener : listeners) {
- listener->DidInsertText(
- static_cast<nsIDOMCharacterData*>(insertedTextNode->AsDOMNode()),
- insertedOffset, aStringToInsert, rv);
- }
- }
-
- // Added some cruft here for bug 43366. Layout was crashing because we left
- // an empty text node lying around in the document. So I delete empty text
- // nodes caused by IME. I have to mark the IME transaction as "fixed", which
- // means that furure IME txns won't merge with it. This is because we don't
- // want future IME txns trying to put their text into a node that is no
- // longer in the document. This does not break undo/redo, because all these
- // txns are wrapped in a parent PlaceHolder txn, and placeholder txns are
- // already savvy to having multiple ime txns inside them.
-
- // Delete empty IME text node if there is one
- if (isIMETransaction && mIMETextNode) {
- uint32_t len = mIMETextNode->Length();
- if (!len) {
- DeleteNode(mIMETextNode);
- mIMETextNode = nullptr;
- static_cast<CompositionTransaction*>(transaction.get())->MarkFixed();
- }
- }
-
- return rv;
-}
-
-nsresult
-EditorBase::SelectEntireDocument(Selection* aSelection)
-{
- if (!aSelection) {
- return NS_ERROR_NULL_POINTER;
- }
-
- nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(GetRoot());
- if (!rootElement) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- return aSelection->SelectAllChildren(rootElement);
-}
-
-nsINode*
-EditorBase::GetFirstEditableNode(nsINode* aRoot)
-{
- MOZ_ASSERT(aRoot);
-
- nsIContent* node = GetLeftmostChild(aRoot);
- if (node && !IsEditable(node)) {
- node = GetNextNode(node, /* aEditableNode = */ true);
- }
-
- return (node != aRoot) ? node : nullptr;
-}
-
-NS_IMETHODIMP
-EditorBase::NotifyDocumentListeners(
- TDocumentListenerNotification aNotificationType)
-{
- if (!mDocStateListeners.Length()) {
- // Maybe there just aren't any.
- return NS_OK;
- }
-
- AutoDocumentStateListenerArray listeners(mDocStateListeners);
- nsresult rv = NS_OK;
-
- switch (aNotificationType) {
- case eDocumentCreated:
- for (auto& listener : listeners) {
- rv = listener->NotifyDocumentCreated();
- if (NS_FAILED(rv)) {
- break;
- }
- }
- break;
-
- case eDocumentToBeDestroyed:
- for (auto& listener : listeners) {
- rv = listener->NotifyDocumentWillBeDestroyed();
- if (NS_FAILED(rv)) {
- break;
- }
- }
- break;
-
- case eDocumentStateChanged: {
- bool docIsDirty;
- rv = GetDocumentModified(&docIsDirty);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (static_cast<int8_t>(docIsDirty) == mDocDirtyState) {
- return NS_OK;
- }
-
- mDocDirtyState = docIsDirty;
-
- for (auto& listener : listeners) {
- rv = listener->NotifyDocumentStateChanged(mDocDirtyState);
- if (NS_FAILED(rv)) {
- break;
- }
- }
- break;
- }
- default:
- NS_NOTREACHED("Unknown notification");
- }
-
- return rv;
-}
-
-already_AddRefed<InsertTextTransaction>
-EditorBase::CreateTxnForInsertText(const nsAString& aStringToInsert,
- Text& aTextNode,
- int32_t aOffset)
-{
- RefPtr<InsertTextTransaction> transaction =
- new InsertTextTransaction(aTextNode, aOffset, aStringToInsert, *this,
- &mRangeUpdater);
- return transaction.forget();
-}
-
-nsresult
-EditorBase::DeleteText(nsGenericDOMDataNode& aCharData,
- uint32_t aOffset,
- uint32_t aLength)
-{
- RefPtr<DeleteTextTransaction> transaction =
- CreateTxnForDeleteText(aCharData, aOffset, aLength);
- NS_ENSURE_STATE(transaction);
-
- AutoRules beginRulesSniffing(this, EditAction::deleteText,
- nsIEditor::ePrevious);
-
- // Let listeners know what's up
- {
- AutoActionListenerArray listeners(mActionListeners);
- for (auto& listener : listeners) {
- listener->WillDeleteText(
- static_cast<nsIDOMCharacterData*>(GetAsDOMNode(&aCharData)), aOffset,
- aLength);
- }
- }
-
- nsresult rv = DoTransaction(transaction);
-
- // Let listeners know what happened
- {
- AutoActionListenerArray listeners(mActionListeners);
- for (auto& listener : listeners) {
- listener->DidDeleteText(
- static_cast<nsIDOMCharacterData*>(GetAsDOMNode(&aCharData)), aOffset,
- aLength, rv);
- }
- }
-
- return rv;
-}
-
-already_AddRefed<DeleteTextTransaction>
-EditorBase::CreateTxnForDeleteText(nsGenericDOMDataNode& aCharData,
- uint32_t aOffset,
- uint32_t aLength)
-{
- RefPtr<DeleteTextTransaction> transaction =
- new DeleteTextTransaction(*this, aCharData, aOffset, aLength,
- &mRangeUpdater);
- nsresult rv = transaction->Init();
- NS_ENSURE_SUCCESS(rv, nullptr);
-
- return transaction.forget();
-}
-
-already_AddRefed<SplitNodeTransaction>
-EditorBase::CreateTxnForSplitNode(nsIContent& aNode,
- uint32_t aOffset)
-{
- RefPtr<SplitNodeTransaction> transaction =
- new SplitNodeTransaction(*this, aNode, aOffset);
- return transaction.forget();
-}
-
-already_AddRefed<JoinNodeTransaction>
-EditorBase::CreateTxnForJoinNode(nsINode& aLeftNode,
- nsINode& aRightNode)
-{
- RefPtr<JoinNodeTransaction> transaction =
- new JoinNodeTransaction(*this, aLeftNode, aRightNode);
-
- NS_ENSURE_SUCCESS(transaction->CheckValidity(), nullptr);
-
- return transaction.forget();
-}
-
-struct SavedRange final
-{
- RefPtr<Selection> mSelection;
- nsCOMPtr<nsINode> mStartNode;
- nsCOMPtr<nsINode> mEndNode;
- int32_t mStartOffset;
- int32_t mEndOffset;
-};
-
-nsresult
-EditorBase::SplitNodeImpl(nsIContent& aExistingRightNode,
- int32_t aOffset,
- nsIContent& aNewLeftNode)
-{
- // Remember all selection points.
- AutoTArray<SavedRange, 10> savedRanges;
- for (size_t i = 0; i < kPresentSelectionTypeCount; ++i) {
- SelectionType selectionType(ToSelectionType(1 << i));
- SavedRange range;
- range.mSelection = GetSelection(selectionType);
- if (selectionType == SelectionType::eNormal) {
- NS_ENSURE_TRUE(range.mSelection, NS_ERROR_NULL_POINTER);
- } else if (!range.mSelection) {
- // For non-normal selections, skip over the non-existing ones.
- continue;
- }
-
- for (uint32_t j = 0; j < range.mSelection->RangeCount(); ++j) {
- RefPtr<nsRange> r = range.mSelection->GetRangeAt(j);
- MOZ_ASSERT(r->IsPositioned());
- range.mStartNode = r->GetStartParent();
- range.mStartOffset = r->StartOffset();
- range.mEndNode = r->GetEndParent();
- range.mEndOffset = r->EndOffset();
-
- savedRanges.AppendElement(range);
- }
- }
-
- nsCOMPtr<nsINode> parent = aExistingRightNode.GetParentNode();
- NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
-
- ErrorResult rv;
- nsCOMPtr<nsINode> refNode = &aExistingRightNode;
- parent->InsertBefore(aNewLeftNode, refNode, rv);
- NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult());
-
- // Split the children between the two nodes. At this point,
- // aExistingRightNode has all the children. Move all the children whose
- // index is < aOffset to aNewLeftNode.
- if (aOffset < 0) {
- // This means move no children
- return NS_OK;
- }
-
- // If it's a text node, just shuffle around some text
- if (aExistingRightNode.GetAsText() && aNewLeftNode.GetAsText()) {
- // Fix right node
- nsAutoString leftText;
- aExistingRightNode.GetAsText()->SubstringData(0, aOffset, leftText);
- aExistingRightNode.GetAsText()->DeleteData(0, aOffset);
- // Fix left node
- aNewLeftNode.GetAsText()->SetData(leftText);
- } else {
- // Otherwise it's an interior node, so shuffle around the children. Go
- // through list backwards so deletes don't interfere with the iteration.
- nsCOMPtr<nsINodeList> childNodes = aExistingRightNode.ChildNodes();
- for (int32_t i = aOffset - 1; i >= 0; i--) {
- nsCOMPtr<nsIContent> childNode = childNodes->Item(i);
- if (childNode) {
- aExistingRightNode.RemoveChild(*childNode, rv);
- if (!rv.Failed()) {
- nsCOMPtr<nsIContent> firstChild = aNewLeftNode.GetFirstChild();
- aNewLeftNode.InsertBefore(*childNode, firstChild, rv);
- }
- }
- if (rv.Failed()) {
- break;
- }
- }
- }
-
- // Handle selection
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
- if (ps) {
- ps->FlushPendingNotifications(Flush_Frames);
- }
-
- bool shouldSetSelection = GetShouldTxnSetSelection();
-
- RefPtr<Selection> previousSelection;
- for (size_t i = 0; i < savedRanges.Length(); ++i) {
- // Adjust the selection if needed.
- SavedRange& range = savedRanges[i];
-
- // If we have not seen the selection yet, clear all of its ranges.
- if (range.mSelection != previousSelection) {
- nsresult rv = range.mSelection->RemoveAllRanges();
- NS_ENSURE_SUCCESS(rv, rv);
- previousSelection = range.mSelection;
- }
-
- if (shouldSetSelection &&
- range.mSelection->Type() == SelectionType::eNormal) {
- // If the editor should adjust the selection, don't bother restoring
- // the ranges for the normal selection here.
- continue;
- }
-
- // Split the selection into existing node and new node.
- if (range.mStartNode == &aExistingRightNode) {
- if (range.mStartOffset < aOffset) {
- range.mStartNode = &aNewLeftNode;
- } else {
- range.mStartOffset -= aOffset;
- }
- }
-
- if (range.mEndNode == &aExistingRightNode) {
- if (range.mEndOffset < aOffset) {
- range.mEndNode = &aNewLeftNode;
- } else {
- range.mEndOffset -= aOffset;
- }
- }
-
- RefPtr<nsRange> newRange;
- nsresult rv = nsRange::CreateRange(range.mStartNode, range.mStartOffset,
- range.mEndNode, range.mEndOffset,
- getter_AddRefs(newRange));
- NS_ENSURE_SUCCESS(rv, rv);
- rv = range.mSelection->AddRange(newRange);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- if (shouldSetSelection) {
- // Editor wants us to set selection at split point.
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- selection->Collapse(&aNewLeftNode, aOffset);
- }
-
- return NS_OK;
-}
-
-nsresult
-EditorBase::JoinNodesImpl(nsINode* aNodeToKeep,
- nsINode* aNodeToJoin,
- nsINode* aParent)
-{
- MOZ_ASSERT(aNodeToKeep);
- MOZ_ASSERT(aNodeToJoin);
- MOZ_ASSERT(aParent);
-
- uint32_t firstNodeLength = aNodeToJoin->Length();
-
- int32_t joinOffset;
- GetNodeLocation(aNodeToJoin, &joinOffset);
- int32_t keepOffset;
- nsINode* parent = GetNodeLocation(aNodeToKeep, &keepOffset);
-
- // Remember all selection points.
- AutoTArray<SavedRange, 10> savedRanges;
- for (size_t i = 0; i < kPresentSelectionTypeCount; ++i) {
- SelectionType selectionType(ToSelectionType(1 << i));
- SavedRange range;
- range.mSelection = GetSelection(selectionType);
- if (selectionType == SelectionType::eNormal) {
- NS_ENSURE_TRUE(range.mSelection, NS_ERROR_NULL_POINTER);
- } else if (!range.mSelection) {
- // For non-normal selections, skip over the non-existing ones.
- continue;
- }
-
- for (uint32_t j = 0; j < range.mSelection->RangeCount(); ++j) {
- RefPtr<nsRange> r = range.mSelection->GetRangeAt(j);
- MOZ_ASSERT(r->IsPositioned());
- range.mStartNode = r->GetStartParent();
- range.mStartOffset = r->StartOffset();
- range.mEndNode = r->GetEndParent();
- range.mEndOffset = r->EndOffset();
-
- // If selection endpoint is between the nodes, remember it as being
- // in the one that is going away instead. This simplifies later selection
- // adjustment logic at end of this method.
- if (range.mStartNode) {
- if (range.mStartNode == parent &&
- joinOffset < range.mStartOffset &&
- range.mStartOffset <= keepOffset) {
- range.mStartNode = aNodeToJoin;
- range.mStartOffset = firstNodeLength;
- }
- if (range.mEndNode == parent &&
- joinOffset < range.mEndOffset &&
- range.mEndOffset <= keepOffset) {
- range.mEndNode = aNodeToJoin;
- range.mEndOffset = firstNodeLength;
- }
- }
-
- savedRanges.AppendElement(range);
- }
- }
-
- // OK, ready to do join now.
- // If it's a text node, just shuffle around some text.
- nsCOMPtr<nsIDOMCharacterData> keepNodeAsText( do_QueryInterface(aNodeToKeep) );
- nsCOMPtr<nsIDOMCharacterData> joinNodeAsText( do_QueryInterface(aNodeToJoin) );
- if (keepNodeAsText && joinNodeAsText) {
- nsAutoString rightText;
- nsAutoString leftText;
- keepNodeAsText->GetData(rightText);
- joinNodeAsText->GetData(leftText);
- leftText += rightText;
- keepNodeAsText->SetData(leftText);
- } else {
- // Otherwise it's an interior node, so shuffle around the children.
- nsCOMPtr<nsINodeList> childNodes = aNodeToJoin->ChildNodes();
- MOZ_ASSERT(childNodes);
-
- // Remember the first child in aNodeToKeep, we'll insert all the children of aNodeToJoin in front of it
- // GetFirstChild returns nullptr firstNode if aNodeToKeep has no children, that's OK.
- nsCOMPtr<nsIContent> firstNode = aNodeToKeep->GetFirstChild();
-
- // Have to go through the list backwards to keep deletes from interfering with iteration.
- for (uint32_t i = childNodes->Length(); i; --i) {
- nsCOMPtr<nsIContent> childNode = childNodes->Item(i - 1);
- if (childNode) {
- // prepend children of aNodeToJoin
- ErrorResult err;
- aNodeToKeep->InsertBefore(*childNode, firstNode, err);
- NS_ENSURE_TRUE(!err.Failed(), err.StealNSResult());
- firstNode = childNode.forget();
- }
- }
- }
-
- // Delete the extra node.
- ErrorResult err;
- aParent->RemoveChild(*aNodeToJoin, err);
-
- bool shouldSetSelection = GetShouldTxnSetSelection();
-
- RefPtr<Selection> previousSelection;
- for (size_t i = 0; i < savedRanges.Length(); ++i) {
- // And adjust the selection if needed.
- SavedRange& range = savedRanges[i];
-
- // If we have not seen the selection yet, clear all of its ranges.
- if (range.mSelection != previousSelection) {
- nsresult rv = range.mSelection->RemoveAllRanges();
- NS_ENSURE_SUCCESS(rv, rv);
- previousSelection = range.mSelection;
- }
-
- if (shouldSetSelection &&
- range.mSelection->Type() == SelectionType::eNormal) {
- // If the editor should adjust the selection, don't bother restoring
- // the ranges for the normal selection here.
- continue;
- }
-
- // Check to see if we joined nodes where selection starts.
- if (range.mStartNode == aNodeToJoin) {
- range.mStartNode = aNodeToKeep;
- } else if (range.mStartNode == aNodeToKeep) {
- range.mStartOffset += firstNodeLength;
- }
-
- // Check to see if we joined nodes where selection ends.
- if (range.mEndNode == aNodeToJoin) {
- range.mEndNode = aNodeToKeep;
- } else if (range.mEndNode == aNodeToKeep) {
- range.mEndOffset += firstNodeLength;
- }
-
- RefPtr<nsRange> newRange;
- nsresult rv = nsRange::CreateRange(range.mStartNode, range.mStartOffset,
- range.mEndNode, range.mEndOffset,
- getter_AddRefs(newRange));
- NS_ENSURE_SUCCESS(rv, rv);
- rv = range.mSelection->AddRange(newRange);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- if (shouldSetSelection) {
- // Editor wants us to set selection at join point.
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- selection->Collapse(aNodeToKeep, AssertedCast<int32_t>(firstNodeLength));
- }
-
- return err.StealNSResult();
-}
-
-int32_t
-EditorBase::GetChildOffset(nsIDOMNode* aChild,
- nsIDOMNode* aParent)
-{
- MOZ_ASSERT(aChild && aParent);
-
- nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
- nsCOMPtr<nsINode> child = do_QueryInterface(aChild);
- MOZ_ASSERT(parent && child);
-
- int32_t idx = parent->IndexOf(child);
- MOZ_ASSERT(idx != -1);
- return idx;
-}
-
-// static
-already_AddRefed<nsIDOMNode>
-EditorBase::GetNodeLocation(nsIDOMNode* aChild,
- int32_t* outOffset)
-{
- MOZ_ASSERT(aChild && outOffset);
- NS_ENSURE_TRUE(aChild && outOffset, nullptr);
- *outOffset = -1;
-
- nsCOMPtr<nsIDOMNode> parent;
-
- MOZ_ALWAYS_SUCCEEDS(aChild->GetParentNode(getter_AddRefs(parent)));
- if (parent) {
- *outOffset = GetChildOffset(aChild, parent);
- }
-
- return parent.forget();
-}
-
-nsINode*
-EditorBase::GetNodeLocation(nsINode* aChild,
- int32_t* aOffset)
-{
- MOZ_ASSERT(aChild);
- MOZ_ASSERT(aOffset);
-
- nsINode* parent = aChild->GetParentNode();
- if (parent) {
- *aOffset = parent->IndexOf(aChild);
- MOZ_ASSERT(*aOffset != -1);
- } else {
- *aOffset = -1;
- }
- return parent;
-}
-
-/**
- * Returns the number of things inside aNode. If aNode is text, returns number
- * of characters. If not, returns number of children nodes.
- */
-nsresult
-EditorBase::GetLengthOfDOMNode(nsIDOMNode* aNode,
- uint32_t& aCount)
-{
- aCount = 0;
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
- aCount = node->Length();
- return NS_OK;
-}
-
-nsIContent*
-EditorBase::GetPriorNode(nsINode* aParentNode,
- int32_t aOffset,
- bool aEditableNode,
- bool aNoBlockCrossing)
-{
- MOZ_ASSERT(aParentNode);
-
- // If we are at the beginning of the node, or it is a text node, then just
- // look before it.
- if (!aOffset || aParentNode->NodeType() == nsIDOMNode::TEXT_NODE) {
- if (aNoBlockCrossing && IsBlockNode(aParentNode)) {
- // If we aren't allowed to cross blocks, don't look before this block.
- return nullptr;
- }
- return GetPriorNode(aParentNode, aEditableNode, aNoBlockCrossing);
- }
-
- // else look before the child at 'aOffset'
- if (nsIContent* child = aParentNode->GetChildAt(aOffset)) {
- return GetPriorNode(child, aEditableNode, aNoBlockCrossing);
- }
-
- // unless there isn't one, in which case we are at the end of the node
- // and want the deep-right child.
- nsIContent* resultNode = GetRightmostChild(aParentNode, aNoBlockCrossing);
- if (!resultNode || !aEditableNode || IsEditable(resultNode)) {
- return resultNode;
- }
-
- // restart the search from the non-editable node we just found
- return GetPriorNode(resultNode, aEditableNode, aNoBlockCrossing);
-}
-
-nsIContent*
-EditorBase::GetNextNode(nsINode* aParentNode,
- int32_t aOffset,
- bool aEditableNode,
- bool aNoBlockCrossing)
-{
- MOZ_ASSERT(aParentNode);
-
- // if aParentNode is a text node, use its location instead
- if (aParentNode->NodeType() == nsIDOMNode::TEXT_NODE) {
- nsINode* parent = aParentNode->GetParentNode();
- NS_ENSURE_TRUE(parent, nullptr);
- aOffset = parent->IndexOf(aParentNode) + 1; // _after_ the text node
- aParentNode = parent;
- }
-
- // look at the child at 'aOffset'
- nsIContent* child = aParentNode->GetChildAt(aOffset);
- if (child) {
- if (aNoBlockCrossing && IsBlockNode(child)) {
- return child;
- }
-
- nsIContent* resultNode = GetLeftmostChild(child, aNoBlockCrossing);
- if (!resultNode) {
- return child;
- }
-
- if (!IsDescendantOfEditorRoot(resultNode)) {
- return nullptr;
- }
-
- if (!aEditableNode || IsEditable(resultNode)) {
- return resultNode;
- }
-
- // restart the search from the non-editable node we just found
- return GetNextNode(resultNode, aEditableNode, aNoBlockCrossing);
- }
-
- // unless there isn't one, in which case we are at the end of the node
- // and want the next one.
- if (aNoBlockCrossing && IsBlockNode(aParentNode)) {
- // don't cross out of parent block
- return nullptr;
- }
-
- return GetNextNode(aParentNode, aEditableNode, aNoBlockCrossing);
-}
-
-nsIContent*
-EditorBase::GetPriorNode(nsINode* aCurrentNode,
- bool aEditableNode,
- bool aNoBlockCrossing /* = false */)
-{
- MOZ_ASSERT(aCurrentNode);
-
- if (!IsDescendantOfEditorRoot(aCurrentNode)) {
- return nullptr;
- }
-
- return FindNode(aCurrentNode, false, aEditableNode, aNoBlockCrossing);
-}
-
-nsIContent*
-EditorBase::FindNextLeafNode(nsINode* aCurrentNode,
- bool aGoForward,
- bool bNoBlockCrossing)
-{
- // called only by GetPriorNode so we don't need to check params.
- NS_PRECONDITION(IsDescendantOfEditorRoot(aCurrentNode) &&
- !IsEditorRoot(aCurrentNode),
- "Bogus arguments");
-
- nsINode* cur = aCurrentNode;
- for (;;) {
- // if aCurrentNode has a sibling in the right direction, return
- // that sibling's closest child (or itself if it has no children)
- nsIContent* sibling =
- aGoForward ? cur->GetNextSibling() : cur->GetPreviousSibling();
- if (sibling) {
- if (bNoBlockCrossing && IsBlockNode(sibling)) {
- // don't look inside prevsib, since it is a block
- return sibling;
- }
- nsIContent *leaf =
- aGoForward ? GetLeftmostChild(sibling, bNoBlockCrossing) :
- GetRightmostChild(sibling, bNoBlockCrossing);
- if (!leaf) {
- return sibling;
- }
-
- return leaf;
- }
-
- nsINode *parent = cur->GetParentNode();
- if (!parent) {
- return nullptr;
- }
-
- NS_ASSERTION(IsDescendantOfEditorRoot(parent),
- "We started with a proper descendant of root, and should stop "
- "if we ever hit the root, so we better have a descendant of "
- "root now!");
- if (IsEditorRoot(parent) ||
- (bNoBlockCrossing && IsBlockNode(parent))) {
- return nullptr;
- }
-
- cur = parent;
- }
-
- NS_NOTREACHED("What part of for(;;) do you not understand?");
- return nullptr;
-}
-
-nsIContent*
-EditorBase::GetNextNode(nsINode* aCurrentNode,
- bool aEditableNode,
- bool bNoBlockCrossing)
-{
- MOZ_ASSERT(aCurrentNode);
-
- if (!IsDescendantOfEditorRoot(aCurrentNode)) {
- return nullptr;
- }
-
- return FindNode(aCurrentNode, true, aEditableNode, bNoBlockCrossing);
-}
-
-nsIContent*
-EditorBase::FindNode(nsINode* aCurrentNode,
- bool aGoForward,
- bool aEditableNode,
- bool bNoBlockCrossing)
-{
- if (IsEditorRoot(aCurrentNode)) {
- // Don't allow traversal above the root node! This helps
- // prevent us from accidentally editing browser content
- // when the editor is in a text widget.
-
- return nullptr;
- }
-
- nsCOMPtr<nsIContent> candidate =
- FindNextLeafNode(aCurrentNode, aGoForward, bNoBlockCrossing);
-
- if (!candidate) {
- return nullptr;
- }
-
- if (!aEditableNode || IsEditable(candidate)) {
- return candidate;
- }
-
- return FindNode(candidate, aGoForward, aEditableNode, bNoBlockCrossing);
-}
-
-nsIContent*
-EditorBase::GetRightmostChild(nsINode* aCurrentNode,
- bool bNoBlockCrossing)
-{
- NS_ENSURE_TRUE(aCurrentNode, nullptr);
- nsIContent *cur = aCurrentNode->GetLastChild();
- if (!cur) {
- return nullptr;
- }
- for (;;) {
- if (bNoBlockCrossing && IsBlockNode(cur)) {
- return cur;
- }
- nsIContent* next = cur->GetLastChild();
- if (!next) {
- return cur;
- }
- cur = next;
- }
-
- NS_NOTREACHED("What part of for(;;) do you not understand?");
- return nullptr;
-}
-
-nsIContent*
-EditorBase::GetLeftmostChild(nsINode* aCurrentNode,
- bool bNoBlockCrossing)
-{
- NS_ENSURE_TRUE(aCurrentNode, nullptr);
- nsIContent *cur = aCurrentNode->GetFirstChild();
- if (!cur) {
- return nullptr;
- }
- for (;;) {
- if (bNoBlockCrossing && IsBlockNode(cur)) {
- return cur;
- }
- nsIContent *next = cur->GetFirstChild();
- if (!next) {
- return cur;
- }
- cur = next;
- }
-
- NS_NOTREACHED("What part of for(;;) do you not understand?");
- return nullptr;
-}
-
-bool
-EditorBase::IsBlockNode(nsINode* aNode)
-{
- // stub to be overridden in HTMLEditor.
- // screwing around with the class hierarchy here in order
- // to not duplicate the code in GetNextNode/GetPrevNode
- // across both EditorBase/HTMLEditor.
- return false;
-}
-
-bool
-EditorBase::CanContain(nsINode& aParent,
- nsIContent& aChild)
-{
- switch (aParent.NodeType()) {
- case nsIDOMNode::ELEMENT_NODE:
- case nsIDOMNode::DOCUMENT_FRAGMENT_NODE:
- return TagCanContain(*aParent.NodeInfo()->NameAtom(), aChild);
- }
- return false;
-}
-
-bool
-EditorBase::CanContainTag(nsINode& aParent,
- nsIAtom& aChildTag)
-{
- switch (aParent.NodeType()) {
- case nsIDOMNode::ELEMENT_NODE:
- case nsIDOMNode::DOCUMENT_FRAGMENT_NODE:
- return TagCanContainTag(*aParent.NodeInfo()->NameAtom(), aChildTag);
- }
- return false;
-}
-
-bool
-EditorBase::TagCanContain(nsIAtom& aParentTag,
- nsIContent& aChild)
-{
- switch (aChild.NodeType()) {
- case nsIDOMNode::TEXT_NODE:
- case nsIDOMNode::ELEMENT_NODE:
- case nsIDOMNode::DOCUMENT_FRAGMENT_NODE:
- return TagCanContainTag(aParentTag, *aChild.NodeInfo()->NameAtom());
- }
- return false;
-}
-
-bool
-EditorBase::TagCanContainTag(nsIAtom& aParentTag,
- nsIAtom& aChildTag)
-{
- return true;
-}
-
-bool
-EditorBase::IsRoot(nsIDOMNode* inNode)
-{
- NS_ENSURE_TRUE(inNode, false);
-
- nsCOMPtr<nsIDOMNode> rootNode = do_QueryInterface(GetRoot());
-
- return inNode == rootNode;
-}
-
-bool
-EditorBase::IsRoot(nsINode* inNode)
-{
- NS_ENSURE_TRUE(inNode, false);
-
- nsCOMPtr<nsINode> rootNode = GetRoot();
-
- return inNode == rootNode;
-}
-
-bool
-EditorBase::IsEditorRoot(nsINode* aNode)
-{
- NS_ENSURE_TRUE(aNode, false);
- nsCOMPtr<nsINode> rootNode = GetEditorRoot();
- return aNode == rootNode;
-}
-
-bool
-EditorBase::IsDescendantOfRoot(nsIDOMNode* inNode)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(inNode);
- return IsDescendantOfRoot(node);
-}
-
-bool
-EditorBase::IsDescendantOfRoot(nsINode* inNode)
-{
- NS_ENSURE_TRUE(inNode, false);
- nsCOMPtr<nsIContent> root = GetRoot();
- NS_ENSURE_TRUE(root, false);
-
- return nsContentUtils::ContentIsDescendantOf(inNode, root);
-}
-
-bool
-EditorBase::IsDescendantOfEditorRoot(nsINode* aNode)
-{
- NS_ENSURE_TRUE(aNode, false);
- nsCOMPtr<nsIContent> root = GetEditorRoot();
- NS_ENSURE_TRUE(root, false);
-
- return nsContentUtils::ContentIsDescendantOf(aNode, root);
-}
-
-bool
-EditorBase::IsContainer(nsINode* aNode)
-{
- return aNode ? true : false;
-}
-
-bool
-EditorBase::IsContainer(nsIDOMNode* aNode)
-{
- return aNode ? true : false;
-}
-
-static inline bool
-IsElementVisible(Element* aElement)
-{
- if (aElement->GetPrimaryFrame()) {
- // It's visible, for our purposes
- return true;
- }
-
- nsIContent *cur = aElement;
- for (;;) {
- // Walk up the tree looking for the nearest ancestor with a frame.
- // The state of the child right below it will determine whether
- // we might possibly have a frame or not.
- bool haveLazyBitOnChild = cur->HasFlag(NODE_NEEDS_FRAME);
- cur = cur->GetFlattenedTreeParent();
- if (!cur) {
- if (!haveLazyBitOnChild) {
- // None of our ancestors have lazy bits set, so we shouldn't
- // have a frame
- return false;
- }
-
- // The root has a lazy frame construction bit. We need to check
- // our style.
- break;
- }
-
- if (cur->GetPrimaryFrame()) {
- if (!haveLazyBitOnChild) {
- // Our ancestor directly under |cur| doesn't have lazy bits;
- // that means we won't get a frame
- return false;
- }
-
- if (cur->GetPrimaryFrame()->IsLeaf()) {
- // Nothing under here will ever get frames
- return false;
- }
-
- // Otherwise, we might end up with a frame when that lazy bit is
- // processed. Figure out our actual style.
- break;
- }
- }
-
- // Now it might be that we have no frame because we're in a
- // display:none subtree, or it might be that we're just dealing with
- // lazy frame construction and it hasn't happened yet. Check which
- // one it is.
- RefPtr<nsStyleContext> styleContext =
- nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement,
- nullptr, nullptr);
- if (styleContext) {
- return styleContext->StyleDisplay()->mDisplay != StyleDisplay::None;
- }
- return false;
-}
-
-bool
-EditorBase::IsEditable(nsIDOMNode* aNode)
-{
- nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
- return IsEditable(content);
-}
-
-bool
-EditorBase::IsEditable(nsINode* aNode)
-{
- NS_ENSURE_TRUE(aNode, false);
-
- if (!aNode->IsNodeOfType(nsINode::eCONTENT) || IsMozEditorBogusNode(aNode) ||
- !IsModifiableNode(aNode)) {
- return false;
- }
-
- // see if it has a frame. If so, we'll edit it.
- // special case for textnodes: frame must have width.
- if (aNode->IsElement() && !IsElementVisible(aNode->AsElement())) {
- // If the element has no frame, it's not editable. Note that we
- // need to check IsElement() here, because some of our tests
- // rely on frameless textnodes being visible.
- return false;
- }
- switch (aNode->NodeType()) {
- case nsIDOMNode::ELEMENT_NODE:
- case nsIDOMNode::TEXT_NODE:
- return true; // element or text node; not invisible
- default:
- return false;
- }
-}
-
-bool
-EditorBase::IsMozEditorBogusNode(nsINode* element)
-{
- return element && element->IsElement() &&
- element->AsElement()->AttrValueIs(kNameSpaceID_None,
- kMOZEditorBogusNodeAttrAtom, kMOZEditorBogusNodeValue,
- eCaseMatters);
-}
-
-uint32_t
-EditorBase::CountEditableChildren(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
- uint32_t count = 0;
- for (nsIContent* child = aNode->GetFirstChild();
- child;
- child = child->GetNextSibling()) {
- if (IsEditable(child)) {
- ++count;
- }
- }
- return count;
-}
-
-NS_IMETHODIMP
-EditorBase::IncrementModificationCount(int32_t inNumMods)
-{
- uint32_t oldModCount = mModCount;
-
- mModCount += inNumMods;
-
- if ((!oldModCount && mModCount) ||
- (oldModCount && !mModCount)) {
- NotifyDocumentListeners(eDocumentStateChanged);
- }
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-EditorBase::GetModificationCount(int32_t* outModCount)
-{
- NS_ENSURE_ARG_POINTER(outModCount);
- *outModCount = mModCount;
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-EditorBase::ResetModificationCount()
-{
- bool doNotify = (mModCount != 0);
-
- mModCount = 0;
-
- if (doNotify) {
- NotifyDocumentListeners(eDocumentStateChanged);
- }
- return NS_OK;
-}
-
-nsIAtom*
-EditorBase::GetTag(nsIDOMNode* aNode)
-{
- nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
-
- if (!content) {
- NS_ASSERTION(aNode, "null node passed to EditorBase::GetTag()");
- return nullptr;
- }
-
- return content->NodeInfo()->NameAtom();
-}
-
-nsresult
-EditorBase::GetTagString(nsIDOMNode* aNode,
- nsAString& outString)
-{
- if (!aNode) {
- NS_NOTREACHED("null node passed to EditorBase::GetTagString()");
- return NS_ERROR_NULL_POINTER;
- }
-
- nsIAtom *atom = GetTag(aNode);
- if (!atom) {
- return NS_ERROR_FAILURE;
- }
-
- atom->ToString(outString);
- return NS_OK;
-}
-
-bool
-EditorBase::NodesSameType(nsIDOMNode* aNode1,
- nsIDOMNode* aNode2)
-{
- if (!aNode1 || !aNode2) {
- NS_NOTREACHED("null node passed to EditorBase::NodesSameType()");
- return false;
- }
-
- nsCOMPtr<nsIContent> content1 = do_QueryInterface(aNode1);
- NS_ENSURE_TRUE(content1, false);
-
- nsCOMPtr<nsIContent> content2 = do_QueryInterface(aNode2);
- NS_ENSURE_TRUE(content2, false);
-
- return AreNodesSameType(content1, content2);
-}
-
-bool
-EditorBase::AreNodesSameType(nsIContent* aNode1,
- nsIContent* aNode2)
-{
- MOZ_ASSERT(aNode1);
- MOZ_ASSERT(aNode2);
- return aNode1->NodeInfo()->NameAtom() == aNode2->NodeInfo()->NameAtom();
-}
-
-bool
-EditorBase::IsTextNode(nsIDOMNode* aNode)
-{
- if (!aNode) {
- NS_NOTREACHED("null node passed to IsTextNode()");
- return false;
- }
-
- uint16_t nodeType;
- aNode->GetNodeType(&nodeType);
- return (nodeType == nsIDOMNode::TEXT_NODE);
-}
-
-bool
-EditorBase::IsTextNode(nsINode* aNode)
-{
- return aNode->NodeType() == nsIDOMNode::TEXT_NODE;
-}
-
-nsCOMPtr<nsIDOMNode>
-EditorBase::GetChildAt(nsIDOMNode* aParent, int32_t aOffset)
-{
- nsCOMPtr<nsIDOMNode> resultNode;
-
- nsCOMPtr<nsIContent> parent = do_QueryInterface(aParent);
-
- NS_ENSURE_TRUE(parent, resultNode);
-
- resultNode = do_QueryInterface(parent->GetChildAt(aOffset));
-
- return resultNode;
-}
-
-/**
- * GetNodeAtRangeOffsetPoint() returns the node at this position in a range,
- * assuming that aParentOrNode is the node itself if it's a text node, or
- * the node's parent otherwise.
- */
-nsIContent*
-EditorBase::GetNodeAtRangeOffsetPoint(nsIDOMNode* aParentOrNode,
- int32_t aOffset)
-{
- nsCOMPtr<nsINode> parentOrNode = do_QueryInterface(aParentOrNode);
- NS_ENSURE_TRUE(parentOrNode || !aParentOrNode, nullptr);
- if (parentOrNode->GetAsText()) {
- return parentOrNode->AsContent();
- }
- return parentOrNode->GetChildAt(aOffset);
-}
-
-/**
- * GetStartNodeAndOffset() returns whatever the start parent & offset is of
- * the first range in the selection.
- */
-nsresult
-EditorBase::GetStartNodeAndOffset(Selection* aSelection,
- nsIDOMNode** outStartNode,
- int32_t* outStartOffset)
-{
- NS_ENSURE_TRUE(outStartNode && outStartOffset && aSelection, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsINode> startNode;
- nsresult rv = GetStartNodeAndOffset(aSelection, getter_AddRefs(startNode),
- outStartOffset);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- if (startNode) {
- NS_ADDREF(*outStartNode = startNode->AsDOMNode());
- } else {
- *outStartNode = nullptr;
- }
- return NS_OK;
-}
-
-nsresult
-EditorBase::GetStartNodeAndOffset(Selection* aSelection,
- nsINode** aStartNode,
- int32_t* aStartOffset)
-{
- MOZ_ASSERT(aSelection);
- MOZ_ASSERT(aStartNode);
- MOZ_ASSERT(aStartOffset);
-
- *aStartNode = nullptr;
- *aStartOffset = 0;
-
- if (!aSelection->RangeCount()) {
- return NS_ERROR_FAILURE;
- }
-
- const nsRange* range = aSelection->GetRangeAt(0);
- NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
-
- NS_ENSURE_TRUE(range->IsPositioned(), NS_ERROR_FAILURE);
-
- NS_IF_ADDREF(*aStartNode = range->GetStartParent());
- *aStartOffset = range->StartOffset();
- return NS_OK;
-}
-
-/**
- * GetEndNodeAndOffset() returns whatever the end parent & offset is of
- * the first range in the selection.
- */
-nsresult
-EditorBase::GetEndNodeAndOffset(Selection* aSelection,
- nsIDOMNode** outEndNode,
- int32_t* outEndOffset)
-{
- NS_ENSURE_TRUE(outEndNode && outEndOffset && aSelection, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsINode> endNode;
- nsresult rv = GetEndNodeAndOffset(aSelection, getter_AddRefs(endNode),
- outEndOffset);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (endNode) {
- NS_ADDREF(*outEndNode = endNode->AsDOMNode());
- } else {
- *outEndNode = nullptr;
- }
- return NS_OK;
-}
-
-nsresult
-EditorBase::GetEndNodeAndOffset(Selection* aSelection,
- nsINode** aEndNode,
- int32_t* aEndOffset)
-{
- MOZ_ASSERT(aSelection);
- MOZ_ASSERT(aEndNode);
- MOZ_ASSERT(aEndOffset);
-
- *aEndNode = nullptr;
- *aEndOffset = 0;
-
- NS_ENSURE_TRUE(aSelection->RangeCount(), NS_ERROR_FAILURE);
-
- const nsRange* range = aSelection->GetRangeAt(0);
- NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
-
- NS_ENSURE_TRUE(range->IsPositioned(), NS_ERROR_FAILURE);
-
- NS_IF_ADDREF(*aEndNode = range->GetEndParent());
- *aEndOffset = range->EndOffset();
- return NS_OK;
-}
-
-/**
- * IsPreformatted() checks the style info for the node for the preformatted
- * text style.
- */
-nsresult
-EditorBase::IsPreformatted(nsIDOMNode* aNode,
- bool* aResult)
-{
- nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
-
- NS_ENSURE_TRUE(aResult && content, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
- NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
-
- // Look at the node (and its parent if it's not an element), and grab its style context
- RefPtr<nsStyleContext> elementStyle;
- if (!content->IsElement()) {
- content = content->GetParent();
- }
- if (content && content->IsElement()) {
- elementStyle = nsComputedDOMStyle::GetStyleContextForElementNoFlush(content->AsElement(),
- nullptr,
- ps);
- }
-
- if (!elementStyle) {
- // Consider nodes without a style context to be NOT preformatted:
- // For instance, this is true of JS tags inside the body (which show
- // up as #text nodes but have no style context).
- *aResult = false;
- return NS_OK;
- }
-
- const nsStyleText* styleText = elementStyle->StyleText();
-
- *aResult = styleText->WhiteSpaceIsSignificant();
- return NS_OK;
-}
-
-
-/**
- * This splits a node "deeply", splitting children as appropriate. The place
- * to split is represented by a DOM point at {splitPointParent,
- * splitPointOffset}. That DOM point must be inside aNode, which is the node
- * to split. We return the offset in the parent of aNode where the split
- * terminates - where you would want to insert a new element, for instance, if
- * that's why you were splitting the node.
- *
- * -1 is returned on failure, in unlikely cases like the selection being
- * unavailable or cloning the node failing. Make sure not to use the returned
- * offset for anything without checking that it's valid! If you're not using
- * the offset, it's okay to ignore the return value.
- */
-int32_t
-EditorBase::SplitNodeDeep(nsIContent& aNode,
- nsIContent& aSplitPointParent,
- int32_t aSplitPointOffset,
- EmptyContainers aEmptyContainers,
- nsIContent** aOutLeftNode,
- nsIContent** aOutRightNode)
-{
- MOZ_ASSERT(&aSplitPointParent == &aNode ||
- EditorUtils::IsDescendantOf(&aSplitPointParent, &aNode));
- int32_t offset = aSplitPointOffset;
-
- nsCOMPtr<nsIContent> leftNode, rightNode;
- OwningNonNull<nsIContent> nodeToSplit = aSplitPointParent;
- while (true) {
- // Need to insert rules code call here to do things like not split a list
- // if you are after the last <li> or before the first, etc. For now we
- // just have some smarts about unneccessarily splitting text nodes, which
- // should be universal enough to put straight in this EditorBase routine.
-
- bool didSplit = false;
-
- if ((aEmptyContainers == EmptyContainers::yes &&
- !nodeToSplit->GetAsText()) ||
- (offset && offset != (int32_t)nodeToSplit->Length())) {
- didSplit = true;
- ErrorResult rv;
- nsCOMPtr<nsIContent> newLeftNode = SplitNode(nodeToSplit, offset, rv);
- NS_ENSURE_TRUE(!NS_FAILED(rv.StealNSResult()), -1);
-
- rightNode = nodeToSplit;
- leftNode = newLeftNode;
- }
-
- NS_ENSURE_TRUE(nodeToSplit->GetParent(), -1);
- OwningNonNull<nsIContent> parentNode = *nodeToSplit->GetParent();
-
- if (!didSplit && offset) {
- // Must be "end of text node" case, we didn't split it, just move past it
- offset = parentNode->IndexOf(nodeToSplit) + 1;
- leftNode = nodeToSplit;
- } else {
- offset = parentNode->IndexOf(nodeToSplit);
- rightNode = nodeToSplit;
- }
-
- if (nodeToSplit == &aNode) {
- // we split all the way up to (and including) aNode; we're done
- break;
- }
-
- nodeToSplit = parentNode;
- }
-
- if (aOutLeftNode) {
- leftNode.forget(aOutLeftNode);
- }
- if (aOutRightNode) {
- rightNode.forget(aOutRightNode);
- }
-
- return offset;
-}
-
-/**
- * This joins two like nodes "deeply", joining children as appropriate.
- * Returns the point of the join, or (nullptr, -1) in case of error.
- */
-EditorDOMPoint
-EditorBase::JoinNodeDeep(nsIContent& aLeftNode,
- nsIContent& aRightNode)
-{
- // While the rightmost children and their descendants of the left node match
- // the leftmost children and their descendants of the right node, join them
- // up.
-
- nsCOMPtr<nsIContent> leftNodeToJoin = &aLeftNode;
- nsCOMPtr<nsIContent> rightNodeToJoin = &aRightNode;
- nsCOMPtr<nsINode> parentNode = aRightNode.GetParentNode();
-
- EditorDOMPoint ret;
-
- while (leftNodeToJoin && rightNodeToJoin && parentNode &&
- AreNodesSameType(leftNodeToJoin, rightNodeToJoin)) {
- uint32_t length = leftNodeToJoin->Length();
-
- ret.node = rightNodeToJoin;
- ret.offset = length;
-
- // Do the join
- nsresult rv = JoinNodes(*leftNodeToJoin, *rightNodeToJoin);
- NS_ENSURE_SUCCESS(rv, EditorDOMPoint());
-
- if (parentNode->GetAsText()) {
- // We've joined all the way down to text nodes, we're done!
- return ret;
- }
-
- // Get new left and right nodes, and begin anew
- parentNode = rightNodeToJoin;
- leftNodeToJoin = parentNode->GetChildAt(length - 1);
- rightNodeToJoin = parentNode->GetChildAt(length);
-
- // Skip over non-editable nodes
- while (leftNodeToJoin && !IsEditable(leftNodeToJoin)) {
- leftNodeToJoin = leftNodeToJoin->GetPreviousSibling();
- }
- if (!leftNodeToJoin) {
- return ret;
- }
-
- while (rightNodeToJoin && !IsEditable(rightNodeToJoin)) {
- rightNodeToJoin = rightNodeToJoin->GetNextSibling();
- }
- if (!rightNodeToJoin) {
- return ret;
- }
- }
-
- return ret;
-}
-
-void
-EditorBase::BeginUpdateViewBatch()
-{
- NS_PRECONDITION(mUpdateCount >= 0, "bad state");
-
- if (!mUpdateCount) {
- // Turn off selection updates and notifications.
- RefPtr<Selection> selection = GetSelection();
- if (selection) {
- selection->StartBatchChanges();
- }
- }
-
- mUpdateCount++;
-}
-
-nsresult
-EditorBase::EndUpdateViewBatch()
-{
- NS_PRECONDITION(mUpdateCount > 0, "bad state");
-
- if (mUpdateCount <= 0) {
- mUpdateCount = 0;
- return NS_ERROR_FAILURE;
- }
-
- mUpdateCount--;
-
- if (!mUpdateCount) {
- // Turn selection updating and notifications back on.
- RefPtr<Selection> selection = GetSelection();
- if (selection) {
- selection->EndBatchChanges();
- }
- }
-
- return NS_OK;
-}
-
-bool
-EditorBase::GetShouldTxnSetSelection()
-{
- return mShouldTxnSetSelection;
-}
-
-NS_IMETHODIMP
-EditorBase::DeleteSelectionImpl(EDirection aAction,
- EStripWrappers aStripWrappers)
-{
- MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_STATE(selection);
- RefPtr<EditAggregateTransaction> transaction;
- nsCOMPtr<nsINode> deleteNode;
- int32_t deleteCharOffset = 0, deleteCharLength = 0;
- nsresult rv = CreateTxnForDeleteSelection(aAction,
- getter_AddRefs(transaction),
- getter_AddRefs(deleteNode),
- &deleteCharOffset,
- &deleteCharLength);
- nsCOMPtr<nsIDOMCharacterData> deleteCharData(do_QueryInterface(deleteNode));
-
- if (NS_SUCCEEDED(rv)) {
- AutoRules beginRulesSniffing(this, EditAction::deleteSelection, aAction);
- // Notify nsIEditActionListener::WillDelete[Selection|Text|Node]
- {
- AutoActionListenerArray listeners(mActionListeners);
- if (!deleteNode) {
- for (auto& listener : listeners) {
- listener->WillDeleteSelection(selection);
- }
- } else if (deleteCharData) {
- for (auto& listener : listeners) {
- listener->WillDeleteText(deleteCharData, deleteCharOffset, 1);
- }
- } else {
- for (auto& listener : listeners) {
- listener->WillDeleteNode(deleteNode->AsDOMNode());
- }
- }
- }
-
- // Delete the specified amount
- rv = DoTransaction(transaction);
-
- // Notify nsIEditActionListener::DidDelete[Selection|Text|Node]
- {
- AutoActionListenerArray listeners(mActionListeners);
- if (!deleteNode) {
- for (auto& listener : mActionListeners) {
- listener->DidDeleteSelection(selection);
- }
- } else if (deleteCharData) {
- for (auto& listener : mActionListeners) {
- listener->DidDeleteText(deleteCharData, deleteCharOffset, 1, rv);
- }
- } else {
- for (auto& listener : mActionListeners) {
- listener->DidDeleteNode(deleteNode->AsDOMNode(), rv);
- }
- }
- }
- }
-
- return rv;
-}
-
-already_AddRefed<Element>
-EditorBase::DeleteSelectionAndCreateElement(nsIAtom& aTag)
-{
- nsresult rv = DeleteSelectionAndPrepareToCreateNode();
- NS_ENSURE_SUCCESS(rv, nullptr);
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, nullptr);
-
- nsCOMPtr<nsINode> node = selection->GetAnchorNode();
- uint32_t offset = selection->AnchorOffset();
-
- nsCOMPtr<Element> newElement = CreateNode(&aTag, node, offset);
-
- // We want the selection to be just after the new node
- rv = selection->Collapse(node, offset + 1);
- NS_ENSURE_SUCCESS(rv, nullptr);
-
- return newElement.forget();
-}
-
-TextComposition*
-EditorBase::GetComposition() const
-{
- return mComposition;
-}
-
-bool
-EditorBase::IsIMEComposing() const
-{
- return mComposition && mComposition->IsComposing();
-}
-
-bool
-EditorBase::ShouldHandleIMEComposition() const
-{
- // When the editor is being reframed, the old value may be restored with
- // InsertText(). In this time, the text should be inserted as not a part
- // of the composition.
- return mComposition && mDidPostCreate;
-}
-
-nsresult
-EditorBase::DeleteSelectionAndPrepareToCreateNode()
-{
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- MOZ_ASSERT(selection->GetAnchorFocusRange());
-
- if (!selection->GetAnchorFocusRange()->Collapsed()) {
- nsresult rv = DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
- NS_ENSURE_SUCCESS(rv, rv);
-
- MOZ_ASSERT(selection->GetAnchorFocusRange() &&
- selection->GetAnchorFocusRange()->Collapsed(),
- "Selection not collapsed after delete");
- }
-
- // If the selection is a chardata node, split it if necessary and compute
- // where to put the new node
- nsCOMPtr<nsINode> node = selection->GetAnchorNode();
- MOZ_ASSERT(node, "Selection has no ranges in it");
-
- if (node && node->IsNodeOfType(nsINode::eDATA_NODE)) {
- NS_ASSERTION(node->GetParentNode(),
- "It's impossible to insert into chardata with no parent -- "
- "fix the caller");
- NS_ENSURE_STATE(node->GetParentNode());
-
- uint32_t offset = selection->AnchorOffset();
-
- if (!offset) {
- nsresult rv = selection->Collapse(node->GetParentNode(),
- node->GetParentNode()->IndexOf(node));
- MOZ_ASSERT(NS_SUCCEEDED(rv));
- NS_ENSURE_SUCCESS(rv, rv);
- } else if (offset == node->Length()) {
- nsresult rv =
- selection->Collapse(node->GetParentNode(),
- node->GetParentNode()->IndexOf(node) + 1);
- MOZ_ASSERT(NS_SUCCEEDED(rv));
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- nsCOMPtr<nsIDOMNode> tmp;
- nsresult rv = SplitNode(node->AsDOMNode(), offset, getter_AddRefs(tmp));
- NS_ENSURE_SUCCESS(rv, rv);
- rv = selection->Collapse(node->GetParentNode(),
- node->GetParentNode()->IndexOf(node));
- MOZ_ASSERT(NS_SUCCEEDED(rv));
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- return NS_OK;
-}
-
-void
-EditorBase::DoAfterDoTransaction(nsITransaction* aTxn)
-{
- bool isTransientTransaction;
- MOZ_ALWAYS_SUCCEEDS(aTxn->GetIsTransient(&isTransientTransaction));
-
- if (!isTransientTransaction) {
- // we need to deal here with the case where the user saved after some
- // edits, then undid one or more times. Then, the undo count is -ve,
- // but we can't let a do take it back to zero. So we flip it up to
- // a +ve number.
- int32_t modCount;
- GetModificationCount(&modCount);
- if (modCount < 0) {
- modCount = -modCount;
- }
-
- // don't count transient transactions
- MOZ_ALWAYS_SUCCEEDS(IncrementModificationCount(1));
- }
-}
-
-void
-EditorBase::DoAfterUndoTransaction()
-{
- // all undoable transactions are non-transient
- MOZ_ALWAYS_SUCCEEDS(IncrementModificationCount(-1));
-}
-
-void
-EditorBase::DoAfterRedoTransaction()
-{
- // all redoable transactions are non-transient
- MOZ_ALWAYS_SUCCEEDS(IncrementModificationCount(1));
-}
-
-already_AddRefed<ChangeAttributeTransaction>
-EditorBase::CreateTxnForSetAttribute(Element& aElement,
- nsIAtom& aAttribute,
- const nsAString& aValue)
-{
- RefPtr<ChangeAttributeTransaction> transaction =
- new ChangeAttributeTransaction(aElement, aAttribute, &aValue);
-
- return transaction.forget();
-}
-
-already_AddRefed<ChangeAttributeTransaction>
-EditorBase::CreateTxnForRemoveAttribute(Element& aElement,
- nsIAtom& aAttribute)
-{
- RefPtr<ChangeAttributeTransaction> transaction =
- new ChangeAttributeTransaction(aElement, aAttribute, nullptr);
-
- return transaction.forget();
-}
-
-already_AddRefed<CreateElementTransaction>
-EditorBase::CreateTxnForCreateElement(nsIAtom& aTag,
- nsINode& aParent,
- int32_t aPosition)
-{
- RefPtr<CreateElementTransaction> transaction =
- new CreateElementTransaction(*this, aTag, aParent, aPosition);
-
- return transaction.forget();
-}
-
-
-already_AddRefed<InsertNodeTransaction>
-EditorBase::CreateTxnForInsertNode(nsIContent& aNode,
- nsINode& aParent,
- int32_t aPosition)
-{
- RefPtr<InsertNodeTransaction> transaction =
- new InsertNodeTransaction(aNode, aParent, aPosition, *this);
- return transaction.forget();
-}
-
-nsresult
-EditorBase::CreateTxnForDeleteNode(nsINode* aNode,
- DeleteNodeTransaction** aTransaction)
-{
- NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
-
- RefPtr<DeleteNodeTransaction> transaction = new DeleteNodeTransaction();
-
- nsresult rv = transaction->Init(this, aNode, &mRangeUpdater);
- NS_ENSURE_SUCCESS(rv, rv);
-
- transaction.forget(aTransaction);
- return NS_OK;
-}
-
-already_AddRefed<CompositionTransaction>
-EditorBase::CreateTxnForComposition(const nsAString& aStringToInsert)
-{
- MOZ_ASSERT(mIMETextNode);
- // During handling IME composition, mComposition must have been initialized.
- // TODO: We can simplify CompositionTransaction::Init() with TextComposition
- // class.
- RefPtr<CompositionTransaction> transaction =
- new CompositionTransaction(*mIMETextNode, mIMETextOffset, mIMETextLength,
- mComposition->GetRanges(), aStringToInsert,
- *this, &mRangeUpdater);
- return transaction.forget();
-}
-
-NS_IMETHODIMP
-EditorBase::CreateTxnForAddStyleSheet(StyleSheet* aSheet,
- AddStyleSheetTransaction** aTransaction)
-{
- RefPtr<AddStyleSheetTransaction> transaction = new AddStyleSheetTransaction();
-
- nsresult rv = transaction->Init(this, aSheet);
- if (NS_SUCCEEDED(rv)) {
- transaction.forget(aTransaction);
- }
-
- return rv;
-}
-
-NS_IMETHODIMP
-EditorBase::CreateTxnForRemoveStyleSheet(
- StyleSheet* aSheet,
- RemoveStyleSheetTransaction** aTransaction)
-{
- RefPtr<RemoveStyleSheetTransaction> transaction =
- new RemoveStyleSheetTransaction();
-
- nsresult rv = transaction->Init(this, aSheet);
- if (NS_SUCCEEDED(rv)) {
- transaction.forget(aTransaction);
- }
-
- return rv;
-}
-
-nsresult
-EditorBase::CreateTxnForDeleteSelection(EDirection aAction,
- EditAggregateTransaction** aTransaction,
- nsINode** aNode,
- int32_t* aOffset,
- int32_t* aLength)
-{
- MOZ_ASSERT(aTransaction);
- *aTransaction = nullptr;
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_STATE(selection);
-
- // Check whether the selection is collapsed and we should do nothing:
- if (selection->Collapsed() && aAction == eNone) {
- return NS_OK;
- }
-
- // allocate the out-param transaction
- RefPtr<EditAggregateTransaction> aggregateTransaction =
- new EditAggregateTransaction();
-
- for (uint32_t rangeIdx = 0; rangeIdx < selection->RangeCount(); ++rangeIdx) {
- RefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
- NS_ENSURE_STATE(range);
-
- // Same with range as with selection; if it is collapsed and action
- // is eNone, do nothing.
- if (!range->Collapsed()) {
- RefPtr<DeleteRangeTransaction> transaction = new DeleteRangeTransaction();
- transaction->Init(this, range, &mRangeUpdater);
- aggregateTransaction->AppendChild(transaction);
- } else if (aAction != eNone) {
- // we have an insertion point. delete the thing in front of it or
- // behind it, depending on aAction
- nsresult rv = CreateTxnForDeleteInsertionPoint(range, aAction,
- aggregateTransaction,
- aNode, aOffset, aLength);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- aggregateTransaction.forget(aTransaction);
-
- return NS_OK;
-}
-
-already_AddRefed<DeleteTextTransaction>
-EditorBase::CreateTxnForDeleteCharacter(nsGenericDOMDataNode& aData,
- uint32_t aOffset,
- EDirection aDirection)
-{
- NS_ASSERTION(aDirection == eNext || aDirection == ePrevious,
- "Invalid direction");
- nsAutoString data;
- aData.GetData(data);
- NS_ASSERTION(data.Length(), "Trying to delete from a zero-length node");
- NS_ENSURE_TRUE(data.Length(), nullptr);
-
- uint32_t segOffset = aOffset, segLength = 1;
- if (aDirection == eNext) {
- if (segOffset + 1 < data.Length() &&
- NS_IS_HIGH_SURROGATE(data[segOffset]) &&
- NS_IS_LOW_SURROGATE(data[segOffset+1])) {
- // Delete both halves of the surrogate pair
- ++segLength;
- }
- } else if (aOffset > 0) {
- --segOffset;
- if (segOffset > 0 &&
- NS_IS_LOW_SURROGATE(data[segOffset]) &&
- NS_IS_HIGH_SURROGATE(data[segOffset-1])) {
- ++segLength;
- --segOffset;
- }
- } else {
- return nullptr;
- }
- return CreateTxnForDeleteText(aData, segOffset, segLength);
-}
-
-//XXX: currently, this doesn't handle edge conditions because GetNext/GetPrior
-//are not implemented
-nsresult
-EditorBase::CreateTxnForDeleteInsertionPoint(
- nsRange* aRange,
- EDirection aAction,
- EditAggregateTransaction* aTransaction,
- nsINode** aNode,
- int32_t* aOffset,
- int32_t* aLength)
-{
- MOZ_ASSERT(aAction != eNone);
-
- // get the node and offset of the insertion point
- nsCOMPtr<nsINode> node = aRange->GetStartParent();
- NS_ENSURE_STATE(node);
-
- int32_t offset = aRange->StartOffset();
-
- // determine if the insertion point is at the beginning, middle, or end of
- // the node
-
- uint32_t count = node->Length();
-
- bool isFirst = !offset;
- bool isLast = (count == (uint32_t)offset);
-
- // XXX: if isFirst && isLast, then we'll need to delete the node
- // as well as the 1 child
-
- // build a transaction for deleting the appropriate data
- // XXX: this has to come from rule section
- if (aAction == ePrevious && isFirst) {
- // we're backspacing from the beginning of the node. Delete the first
- // thing to our left
- nsCOMPtr<nsIContent> priorNode = GetPriorNode(node, true);
- NS_ENSURE_STATE(priorNode);
-
- // there is a priorNode, so delete its last child (if chardata, delete the
- // last char). if it has no children, delete it
- if (priorNode->IsNodeOfType(nsINode::eDATA_NODE)) {
- RefPtr<nsGenericDOMDataNode> priorNodeAsCharData =
- static_cast<nsGenericDOMDataNode*>(priorNode.get());
- uint32_t length = priorNode->Length();
- // Bail out for empty chardata XXX: Do we want to do something else?
- NS_ENSURE_STATE(length);
- RefPtr<DeleteTextTransaction> transaction =
- CreateTxnForDeleteCharacter(*priorNodeAsCharData, length, ePrevious);
- NS_ENSURE_STATE(transaction);
-
- *aOffset = transaction->GetOffset();
- *aLength = transaction->GetNumCharsToDelete();
- aTransaction->AppendChild(transaction);
- } else {
- // priorNode is not chardata, so tell its parent to delete it
- RefPtr<DeleteNodeTransaction> transaction;
- nsresult rv =
- CreateTxnForDeleteNode(priorNode, getter_AddRefs(transaction));
- NS_ENSURE_SUCCESS(rv, rv);
-
- aTransaction->AppendChild(transaction);
- }
-
- NS_ADDREF(*aNode = priorNode);
-
- return NS_OK;
- }
-
- if (aAction == eNext && isLast) {
- // we're deleting from the end of the node. Delete the first thing to our
- // right
- nsCOMPtr<nsIContent> nextNode = GetNextNode(node, true);
- NS_ENSURE_STATE(nextNode);
-
- // there is a nextNode, so delete its first child (if chardata, delete the
- // first char). if it has no children, delete it
- if (nextNode->IsNodeOfType(nsINode::eDATA_NODE)) {
- RefPtr<nsGenericDOMDataNode> nextNodeAsCharData =
- static_cast<nsGenericDOMDataNode*>(nextNode.get());
- uint32_t length = nextNode->Length();
- // Bail out for empty chardata XXX: Do we want to do something else?
- NS_ENSURE_STATE(length);
- RefPtr<DeleteTextTransaction> transaction =
- CreateTxnForDeleteCharacter(*nextNodeAsCharData, 0, eNext);
- NS_ENSURE_STATE(transaction);
-
- *aOffset = transaction->GetOffset();
- *aLength = transaction->GetNumCharsToDelete();
- aTransaction->AppendChild(transaction);
- } else {
- // nextNode is not chardata, so tell its parent to delete it
- RefPtr<DeleteNodeTransaction> transaction;
- nsresult rv =
- CreateTxnForDeleteNode(nextNode, getter_AddRefs(transaction));
- NS_ENSURE_SUCCESS(rv, rv);
- aTransaction->AppendChild(transaction);
- }
-
- NS_ADDREF(*aNode = nextNode);
-
- return NS_OK;
- }
-
- if (node->IsNodeOfType(nsINode::eDATA_NODE)) {
- RefPtr<nsGenericDOMDataNode> nodeAsCharData =
- static_cast<nsGenericDOMDataNode*>(node.get());
- // we have chardata, so delete a char at the proper offset
- RefPtr<DeleteTextTransaction> transaction =
- CreateTxnForDeleteCharacter(*nodeAsCharData, offset, aAction);
- NS_ENSURE_STATE(transaction);
-
- aTransaction->AppendChild(transaction);
- NS_ADDREF(*aNode = node);
- *aOffset = transaction->GetOffset();
- *aLength = transaction->GetNumCharsToDelete();
- } else {
- // we're either deleting a node or chardata, need to dig into the next/prev
- // node to find out
- nsCOMPtr<nsINode> selectedNode;
- if (aAction == ePrevious) {
- selectedNode = GetPriorNode(node, offset, true);
- } else if (aAction == eNext) {
- selectedNode = GetNextNode(node, offset, true);
- }
-
- while (selectedNode &&
- selectedNode->IsNodeOfType(nsINode::eDATA_NODE) &&
- !selectedNode->Length()) {
- // Can't delete an empty chardata node (bug 762183)
- if (aAction == ePrevious) {
- selectedNode = GetPriorNode(selectedNode, true);
- } else if (aAction == eNext) {
- selectedNode = GetNextNode(selectedNode, true);
- }
- }
- NS_ENSURE_STATE(selectedNode);
-
- if (selectedNode->IsNodeOfType(nsINode::eDATA_NODE)) {
- RefPtr<nsGenericDOMDataNode> selectedNodeAsCharData =
- static_cast<nsGenericDOMDataNode*>(selectedNode.get());
- // we are deleting from a chardata node, so do a character deletion
- uint32_t position = 0;
- if (aAction == ePrevious) {
- position = selectedNode->Length();
- }
- RefPtr<DeleteTextTransaction> deleteTextTransaction =
- CreateTxnForDeleteCharacter(*selectedNodeAsCharData, position,
- aAction);
- NS_ENSURE_TRUE(deleteTextTransaction, NS_ERROR_NULL_POINTER);
-
- aTransaction->AppendChild(deleteTextTransaction);
- *aOffset = deleteTextTransaction->GetOffset();
- *aLength = deleteTextTransaction->GetNumCharsToDelete();
- } else {
- RefPtr<DeleteNodeTransaction> deleteNodeTransaction;
- nsresult rv =
- CreateTxnForDeleteNode(selectedNode,
- getter_AddRefs(deleteNodeTransaction));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(deleteNodeTransaction, NS_ERROR_NULL_POINTER);
-
- aTransaction->AppendChild(deleteNodeTransaction);
- }
-
- NS_ADDREF(*aNode = selectedNode);
- }
-
- return NS_OK;
-}
-
-nsresult
-EditorBase::CreateRange(nsIDOMNode* aStartParent,
- int32_t aStartOffset,
- nsIDOMNode* aEndParent,
- int32_t aEndOffset,
- nsRange** aRange)
-{
- return nsRange::CreateRange(aStartParent, aStartOffset, aEndParent,
- aEndOffset, aRange);
-}
-
-nsresult
-EditorBase::AppendNodeToSelectionAsRange(nsIDOMNode* aNode)
-{
- NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIDOMNode> parentNode;
- nsresult rv = aNode->GetParentNode(getter_AddRefs(parentNode));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(parentNode, NS_ERROR_NULL_POINTER);
-
- int32_t offset = GetChildOffset(aNode, parentNode);
-
- RefPtr<nsRange> range;
- rv = CreateRange(parentNode, offset, parentNode, offset + 1,
- getter_AddRefs(range));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(range, NS_ERROR_NULL_POINTER);
-
- return selection->AddRange(range);
-}
-
-nsresult
-EditorBase::ClearSelection()
-{
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
- return selection->RemoveAllRanges();
-}
-
-already_AddRefed<Element>
-EditorBase::CreateHTMLContent(nsIAtom* aTag)
-{
- MOZ_ASSERT(aTag);
-
- nsCOMPtr<nsIDocument> doc = GetDocument();
- if (!doc) {
- return nullptr;
- }
-
- // XXX Wallpaper over editor bug (editor tries to create elements with an
- // empty nodename).
- if (aTag == nsGkAtoms::_empty) {
- NS_ERROR("Don't pass an empty tag to EditorBase::CreateHTMLContent, "
- "check caller.");
- return nullptr;
- }
-
- return doc->CreateElem(nsDependentAtomString(aTag), nullptr,
- kNameSpaceID_XHTML);
-}
-
-NS_IMETHODIMP
-EditorBase::SetAttributeOrEquivalent(nsIDOMElement* aElement,
- const nsAString& aAttribute,
- const nsAString& aValue,
- bool aSuppressTransaction)
-{
- nsCOMPtr<Element> element = do_QueryInterface(aElement);
- if (NS_WARN_IF(!element)) {
- return NS_ERROR_NULL_POINTER;
- }
- nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
- return SetAttributeOrEquivalent(element, attribute, aValue,
- aSuppressTransaction);
-}
-
-NS_IMETHODIMP
-EditorBase::RemoveAttributeOrEquivalent(nsIDOMElement* aElement,
- const nsAString& aAttribute,
- bool aSuppressTransaction)
-{
- nsCOMPtr<Element> element = do_QueryInterface(aElement);
- if (NS_WARN_IF(!element)) {
- return NS_ERROR_NULL_POINTER;
- }
- nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
- return RemoveAttributeOrEquivalent(element, attribute, aSuppressTransaction);
-}
-
-nsresult
-EditorBase::HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent)
-{
- // NOTE: When you change this method, you should also change:
- // * editor/libeditor/tests/test_texteditor_keyevent_handling.html
- // * editor/libeditor/tests/test_htmleditor_keyevent_handling.html
- //
- // And also when you add new key handling, you need to change the subclass's
- // HandleKeyPressEvent()'s switch statement.
-
- WidgetKeyboardEvent* nativeKeyEvent =
- aKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
- NS_ENSURE_TRUE(nativeKeyEvent, NS_ERROR_UNEXPECTED);
- NS_ASSERTION(nativeKeyEvent->mMessage == eKeyPress,
- "HandleKeyPressEvent gets non-keypress event");
-
- // if we are readonly or disabled, then do nothing.
- if (IsReadonly() || IsDisabled()) {
- // consume backspace for disabled and readonly textfields, to prevent
- // back in history, which could be confusing to users
- if (nativeKeyEvent->mKeyCode == NS_VK_BACK) {
- aKeyEvent->AsEvent()->PreventDefault();
- }
- return NS_OK;
- }
-
- switch (nativeKeyEvent->mKeyCode) {
- case NS_VK_META:
- case NS_VK_WIN:
- case NS_VK_SHIFT:
- case NS_VK_CONTROL:
- case NS_VK_ALT:
- aKeyEvent->AsEvent()->PreventDefault(); // consumed
- return NS_OK;
- case NS_VK_BACK:
- if (nativeKeyEvent->IsControl() || nativeKeyEvent->IsAlt() ||
- nativeKeyEvent->IsMeta() || nativeKeyEvent->IsOS()) {
- return NS_OK;
- }
- DeleteSelection(nsIEditor::ePrevious, nsIEditor::eStrip);
- aKeyEvent->AsEvent()->PreventDefault(); // consumed
- return NS_OK;
- case NS_VK_DELETE:
- // on certain platforms (such as windows) the shift key
- // modifies what delete does (cmd_cut in this case).
- // bailing here to allow the keybindings to do the cut.
- if (nativeKeyEvent->IsShift() || nativeKeyEvent->IsControl() ||
- nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta() ||
- nativeKeyEvent->IsOS()) {
- return NS_OK;
- }
- DeleteSelection(nsIEditor::eNext, nsIEditor::eStrip);
- aKeyEvent->AsEvent()->PreventDefault(); // consumed
- return NS_OK;
- }
- return NS_OK;
-}
-
-nsresult
-EditorBase::HandleInlineSpellCheck(EditAction action,
- Selection* aSelection,
- nsIDOMNode* previousSelectedNode,
- int32_t previousSelectedOffset,
- nsIDOMNode* aStartNode,
- int32_t aStartOffset,
- nsIDOMNode* aEndNode,
- int32_t aEndOffset)
-{
- // Have to cast action here because this method is from an IDL
- return mInlineSpellChecker ? mInlineSpellChecker->SpellCheckAfterEditorChange(
- (int32_t)action, aSelection,
- previousSelectedNode, previousSelectedOffset,
- aStartNode, aStartOffset, aEndNode,
- aEndOffset)
- : NS_OK;
-}
-
-already_AddRefed<nsIContent>
-EditorBase::FindSelectionRoot(nsINode* aNode)
-{
- nsCOMPtr<nsIContent> rootContent = GetRoot();
- return rootContent.forget();
-}
-
-nsresult
-EditorBase::InitializeSelection(nsIDOMEventTarget* aFocusEventTarget)
-{
- nsCOMPtr<nsINode> targetNode = do_QueryInterface(aFocusEventTarget);
- NS_ENSURE_TRUE(targetNode, NS_ERROR_INVALID_ARG);
- nsCOMPtr<nsIContent> selectionRootContent = FindSelectionRoot(targetNode);
- if (!selectionRootContent) {
- return NS_OK;
- }
-
- bool isTargetDoc =
- targetNode->NodeType() == nsIDOMNode::DOCUMENT_NODE &&
- targetNode->HasFlag(NODE_IS_EDITABLE);
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_STATE(selection);
-
- nsCOMPtr<nsIPresShell> presShell = GetPresShell();
- NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_INITIALIZED);
-
- nsCOMPtr<nsISelectionController> selectionController =
- GetSelectionController();
- if (NS_WARN_IF(!selectionController)) {
- return NS_ERROR_FAILURE;
- }
-
- // Init the caret
- RefPtr<nsCaret> caret = presShell->GetCaret();
- NS_ENSURE_TRUE(caret, NS_ERROR_UNEXPECTED);
- caret->SetIgnoreUserModify(false);
- caret->SetSelection(selection);
- selectionController->SetCaretReadOnly(IsReadonly());
- selectionController->SetCaretEnabled(true);
-
- // Init selection
- selectionController->SetDisplaySelection(
- nsISelectionController::SELECTION_ON);
- selectionController->SetSelectionFlags(
- nsISelectionDisplay::DISPLAY_ALL);
- selectionController->RepaintSelection(
- nsISelectionController::SELECTION_NORMAL);
- // If the computed selection root isn't root content, we should set it
- // as selection ancestor limit. However, if that is root element, it means
- // there is not limitation of the selection, then, we must set nullptr.
- // NOTE: If we set a root element to the ancestor limit, some selection
- // methods don't work fine.
- if (selectionRootContent->GetParent()) {
- selection->SetAncestorLimiter(selectionRootContent);
- } else {
- selection->SetAncestorLimiter(nullptr);
- }
-
- // XXX What case needs this?
- if (isTargetDoc) {
- int32_t rangeCount;
- selection->GetRangeCount(&rangeCount);
- if (!rangeCount) {
- BeginningOfDocument();
- }
- }
-
- // If there is composition when this is called, we may need to restore IME
- // selection because if the editor is reframed, this already forgot IME
- // selection and the transaction.
- if (mComposition && !mIMETextNode && mIMETextLength) {
- // We need to look for the new mIMETextNode from current selection.
- // XXX If selection is changed during reframe, this doesn't work well!
- nsRange* firstRange = selection->GetRangeAt(0);
- NS_ENSURE_TRUE(firstRange, NS_ERROR_FAILURE);
- nsCOMPtr<nsINode> startNode = firstRange->GetStartParent();
- int32_t startOffset = firstRange->StartOffset();
- FindBetterInsertionPoint(startNode, startOffset);
- Text* textNode = startNode->GetAsText();
- MOZ_ASSERT(textNode,
- "There must be text node if mIMETextLength is larger than 0");
- if (textNode) {
- MOZ_ASSERT(textNode->Length() >= mIMETextOffset + mIMETextLength,
- "The text node must be different from the old mIMETextNode");
- CompositionTransaction::SetIMESelection(*this, textNode, mIMETextOffset,
- mIMETextLength,
- mComposition->GetRanges());
- }
- }
-
- return NS_OK;
-}
-
-class RepaintSelectionRunner final : public Runnable {
-public:
- explicit RepaintSelectionRunner(nsISelectionController* aSelectionController)
- : mSelectionController(aSelectionController)
- {
- }
-
- NS_IMETHOD Run() override
- {
- mSelectionController->RepaintSelection(
- nsISelectionController::SELECTION_NORMAL);
- return NS_OK;
- }
-
-private:
- nsCOMPtr<nsISelectionController> mSelectionController;
-};
-
-NS_IMETHODIMP
-EditorBase::FinalizeSelection()
-{
- nsCOMPtr<nsISelectionController> selectionController =
- GetSelectionController();
- if (NS_WARN_IF(!selectionController)) {
- return NS_ERROR_FAILURE;
- }
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_STATE(selection);
-
- selection->SetAncestorLimiter(nullptr);
-
- nsCOMPtr<nsIPresShell> presShell = GetPresShell();
- NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_INITIALIZED);
-
- selectionController->SetCaretEnabled(false);
-
- nsFocusManager* fm = nsFocusManager::GetFocusManager();
- NS_ENSURE_TRUE(fm, NS_ERROR_NOT_INITIALIZED);
- fm->UpdateCaretForCaretBrowsingMode();
-
- if (!HasIndependentSelection()) {
- // If this editor doesn't have an independent selection, i.e., it must
- // mean that it is an HTML editor, the selection controller is shared with
- // presShell. So, even this editor loses focus, other part of the document
- // may still have focus.
- nsCOMPtr<nsIDocument> doc = GetDocument();
- ErrorResult ret;
- if (!doc || !doc->HasFocus(ret)) {
- // If the document already lost focus, mark the selection as disabled.
- selectionController->SetDisplaySelection(
- nsISelectionController::SELECTION_DISABLED);
- } else {
- // Otherwise, mark selection as normal because outside of a
- // contenteditable element should be selected with normal selection
- // color after here.
- selectionController->SetDisplaySelection(
- nsISelectionController::SELECTION_ON);
- }
- } else if (IsFormWidget() || IsPasswordEditor() ||
- IsReadonly() || IsDisabled() || IsInputFiltered()) {
- // In <input> or <textarea>, the independent selection should be hidden
- // while this editor doesn't have focus.
- selectionController->SetDisplaySelection(
- nsISelectionController::SELECTION_HIDDEN);
- } else {
- // Otherwise, although we're not sure how this case happens, the
- // independent selection should be marked as disabled.
- selectionController->SetDisplaySelection(
- nsISelectionController::SELECTION_DISABLED);
- }
-
-
- // FinalizeSelection might be called from ContentRemoved even if selection
- // isn't updated. So we need to call RepaintSelection after updated it.
- nsContentUtils::AddScriptRunner(
- new RepaintSelectionRunner(selectionController));
- return NS_OK;
-}
-
-Element*
-EditorBase::GetRoot()
-{
- if (!mRootElement) {
- // Let GetRootElement() do the work
- nsCOMPtr<nsIDOMElement> root;
- GetRootElement(getter_AddRefs(root));
- }
-
- return mRootElement;
-}
-
-Element*
-EditorBase::GetEditorRoot()
-{
- return GetRoot();
-}
-
-Element*
-EditorBase::GetExposedRoot()
-{
- Element* rootElement = GetRoot();
-
- // For plaintext editors, we need to ask the input/textarea element directly.
- if (rootElement && rootElement->IsRootOfNativeAnonymousSubtree()) {
- rootElement = rootElement->GetParent()->AsElement();
- }
-
- return rootElement;
-}
-
-nsresult
-EditorBase::DetermineCurrentDirection()
-{
- // Get the current root direction from its frame
- nsIContent* rootElement = GetExposedRoot();
- NS_ENSURE_TRUE(rootElement, NS_ERROR_FAILURE);
-
- // If we don't have an explicit direction, determine our direction
- // from the content's direction
- if (!(mFlags & (nsIPlaintextEditor::eEditorLeftToRight |
- nsIPlaintextEditor::eEditorRightToLeft))) {
- nsIFrame* frame = rootElement->GetPrimaryFrame();
- NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
-
- // Set the flag here, to enable us to use the same code path below.
- // It will be flipped before returning from the function.
- if (frame->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
- mFlags |= nsIPlaintextEditor::eEditorRightToLeft;
- } else {
- mFlags |= nsIPlaintextEditor::eEditorLeftToRight;
- }
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::SwitchTextDirection()
-{
- // Get the current root direction from its frame
- nsIContent* rootElement = GetExposedRoot();
-
- nsresult rv = DetermineCurrentDirection();
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Apply the opposite direction
- if (mFlags & nsIPlaintextEditor::eEditorRightToLeft) {
- NS_ASSERTION(!(mFlags & nsIPlaintextEditor::eEditorLeftToRight),
- "Unexpected mutually exclusive flag");
- mFlags &= ~nsIPlaintextEditor::eEditorRightToLeft;
- mFlags |= nsIPlaintextEditor::eEditorLeftToRight;
- rv = rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::dir, NS_LITERAL_STRING("ltr"), true);
- } else if (mFlags & nsIPlaintextEditor::eEditorLeftToRight) {
- NS_ASSERTION(!(mFlags & nsIPlaintextEditor::eEditorRightToLeft),
- "Unexpected mutually exclusive flag");
- mFlags |= nsIPlaintextEditor::eEditorRightToLeft;
- mFlags &= ~nsIPlaintextEditor::eEditorLeftToRight;
- rv = rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::dir, NS_LITERAL_STRING("rtl"), true);
- }
-
- if (NS_SUCCEEDED(rv)) {
- FireInputEvent();
- }
-
- return rv;
-}
-
-void
-EditorBase::SwitchTextDirectionTo(uint32_t aDirection)
-{
- // Get the current root direction from its frame
- nsIContent* rootElement = GetExposedRoot();
-
- nsresult rv = DetermineCurrentDirection();
- NS_ENSURE_SUCCESS_VOID(rv);
-
- // Apply the requested direction
- if (aDirection == nsIPlaintextEditor::eEditorLeftToRight &&
- (mFlags & nsIPlaintextEditor::eEditorRightToLeft)) {
- NS_ASSERTION(!(mFlags & nsIPlaintextEditor::eEditorLeftToRight),
- "Unexpected mutually exclusive flag");
- mFlags &= ~nsIPlaintextEditor::eEditorRightToLeft;
- mFlags |= nsIPlaintextEditor::eEditorLeftToRight;
- rv = rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::dir, NS_LITERAL_STRING("ltr"), true);
- } else if (aDirection == nsIPlaintextEditor::eEditorRightToLeft &&
- (mFlags & nsIPlaintextEditor::eEditorLeftToRight)) {
- NS_ASSERTION(!(mFlags & nsIPlaintextEditor::eEditorRightToLeft),
- "Unexpected mutually exclusive flag");
- mFlags |= nsIPlaintextEditor::eEditorRightToLeft;
- mFlags &= ~nsIPlaintextEditor::eEditorLeftToRight;
- rv = rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::dir, NS_LITERAL_STRING("rtl"), true);
- }
-
- if (NS_SUCCEEDED(rv)) {
- FireInputEvent();
- }
-}
-
-#if DEBUG_JOE
-void
-EditorBase::DumpNode(nsIDOMNode* aNode,
- int32_t indent)
-{
- for (int32_t i = 0; i < indent; i++) {
- printf(" ");
- }
-
- nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
- nsCOMPtr<nsIDOMDocumentFragment> docfrag = do_QueryInterface(aNode);
-
- if (element || docfrag) {
- if (element) {
- nsAutoString tag;
- element->GetTagName(tag);
- printf("<%s>\n", NS_LossyConvertUTF16toASCII(tag).get());
- } else {
- printf("<document fragment>\n");
- }
- nsCOMPtr<nsIDOMNodeList> childList;
- aNode->GetChildNodes(getter_AddRefs(childList));
- NS_ENSURE_TRUE(childList, NS_ERROR_NULL_POINTER);
- uint32_t numChildren;
- childList->GetLength(&numChildren);
- nsCOMPtr<nsIDOMNode> child, tmp;
- aNode->GetFirstChild(getter_AddRefs(child));
- for (uint32_t i = 0; i < numChildren; i++) {
- DumpNode(child, indent + 1);
- child->GetNextSibling(getter_AddRefs(tmp));
- child = tmp;
- }
- } else if (IsTextNode(aNode)) {
- nsCOMPtr<nsIDOMCharacterData> textNode = do_QueryInterface(aNode);
- nsAutoString str;
- textNode->GetData(str);
- nsAutoCString cstr;
- LossyCopyUTF16toASCII(str, cstr);
- cstr.ReplaceChar('\n', ' ');
- printf("<textnode> %s\n", cstr.get());
- }
-}
-#endif
-
-bool
-EditorBase::IsModifiableNode(nsIDOMNode* aNode)
-{
- return true;
-}
-
-bool
-EditorBase::IsModifiableNode(nsINode* aNode)
-{
- return true;
-}
-
-already_AddRefed<nsIContent>
-EditorBase::GetFocusedContent()
-{
- nsCOMPtr<nsIDOMEventTarget> piTarget = GetDOMEventTarget();
- if (!piTarget) {
- return nullptr;
- }
-
- nsFocusManager* fm = nsFocusManager::GetFocusManager();
- NS_ENSURE_TRUE(fm, nullptr);
-
- nsCOMPtr<nsIContent> content = fm->GetFocusedContent();
- return SameCOMIdentity(content, piTarget) ? content.forget() : nullptr;
-}
-
-already_AddRefed<nsIContent>
-EditorBase::GetFocusedContentForIME()
-{
- return GetFocusedContent();
-}
-
-bool
-EditorBase::IsActiveInDOMWindow()
-{
- nsCOMPtr<nsIDOMEventTarget> piTarget = GetDOMEventTarget();
- if (!piTarget) {
- return false;
- }
-
- nsFocusManager* fm = nsFocusManager::GetFocusManager();
- NS_ENSURE_TRUE(fm, false);
-
- nsCOMPtr<nsIDocument> document = GetDocument();
- if (NS_WARN_IF(!document)) {
- return false;
- }
- nsPIDOMWindowOuter* ourWindow = document->GetWindow();
- nsCOMPtr<nsPIDOMWindowOuter> win;
- nsIContent* content =
- nsFocusManager::GetFocusedDescendant(ourWindow, false,
- getter_AddRefs(win));
- return SameCOMIdentity(content, piTarget);
-}
-
-bool
-EditorBase::IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent)
-{
- // If the event is trusted, the event should always cause input.
- if (NS_WARN_IF(!aGUIEvent)) {
- return false;
- }
-
- // If this is dispatched by using cordinates but this editor doesn't have
- // focus, we shouldn't handle it.
- if (aGUIEvent->IsUsingCoordinates()) {
- nsCOMPtr<nsIContent> focusedContent = GetFocusedContent();
- if (!focusedContent) {
- return false;
- }
- }
-
- // If a composition event isn't dispatched via widget, we need to ignore them
- // since they cannot be managed by TextComposition. E.g., the event was
- // created by chrome JS.
- // Note that if we allow to handle such events, editor may be confused by
- // strange event order.
- bool needsWidget = false;
- switch (aGUIEvent->mMessage) {
- case eUnidentifiedEvent:
- // If events are not created with proper event interface, their message
- // are initialized with eUnidentifiedEvent. Let's ignore such event.
- return false;
- case eCompositionStart:
- case eCompositionEnd:
- case eCompositionUpdate:
- case eCompositionChange:
- case eCompositionCommitAsIs:
- // Don't allow composition events whose internal event are not
- // WidgetCompositionEvent.
- if (!aGUIEvent->AsCompositionEvent()) {
- return false;
- }
- needsWidget = true;
- break;
- default:
- break;
- }
- if (needsWidget && !aGUIEvent->mWidget) {
- return false;
- }
-
- // Accept all trusted events.
- if (aGUIEvent->IsTrusted()) {
- return true;
- }
-
- // Ignore untrusted mouse event.
- // XXX Why are we handling other untrusted input events?
- if (aGUIEvent->AsMouseEventBase()) {
- return false;
- }
-
- // Otherwise, we shouldn't handle any input events when we're not an active
- // element of the DOM window.
- return IsActiveInDOMWindow();
-}
-
-void
-EditorBase::OnFocus(nsIDOMEventTarget* aFocusEventTarget)
-{
- InitializeSelection(aFocusEventTarget);
- if (mInlineSpellChecker) {
- mInlineSpellChecker->UpdateCurrentDictionary();
- }
-}
-
-NS_IMETHODIMP
-EditorBase::GetSuppressDispatchingInputEvent(bool* aSuppressed)
-{
- NS_ENSURE_ARG_POINTER(aSuppressed);
- *aSuppressed = !mDispatchInputEvent;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::SetSuppressDispatchingInputEvent(bool aSuppress)
-{
- mDispatchInputEvent = !aSuppress;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-EditorBase::GetIsInEditAction(bool* aIsInEditAction)
-{
- MOZ_ASSERT(aIsInEditAction, "aIsInEditAction must not be null");
- *aIsInEditAction = mIsInEditAction;
- return NS_OK;
-}
-
-int32_t
-EditorBase::GetIMESelectionStartOffsetIn(nsINode* aTextNode)
-{
- MOZ_ASSERT(aTextNode, "aTextNode must not be nullptr");
-
- nsCOMPtr<nsISelectionController> selectionController =
- GetSelectionController();
- if (NS_WARN_IF(!selectionController)) {
- return -1;
- }
-
- uint32_t minOffset = UINT32_MAX;
- static const SelectionType kIMESelectionTypes[] = {
- SelectionType::eIMERawClause,
- SelectionType::eIMESelectedRawClause,
- SelectionType::eIMEConvertedClause,
- SelectionType::eIMESelectedClause
- };
- for (auto selectionType : kIMESelectionTypes) {
- RefPtr<Selection> selection = GetSelection(selectionType);
- if (!selection) {
- continue;
- }
- for (uint32_t i = 0; i < selection->RangeCount(); i++) {
- RefPtr<nsRange> range = selection->GetRangeAt(i);
- if (NS_WARN_IF(!range)) {
- continue;
- }
- if (NS_WARN_IF(range->GetStartParent() != aTextNode)) {
- // ignore the start offset...
- } else {
- minOffset = std::min(minOffset, range->StartOffset());
- }
- if (NS_WARN_IF(range->GetEndParent() != aTextNode)) {
- // ignore the end offset...
- } else {
- minOffset = std::min(minOffset, range->EndOffset());
- }
- }
- }
- return minOffset < INT32_MAX ? minOffset : -1;
-}
-
-void
-EditorBase::HideCaret(bool aHide)
-{
- if (mHidingCaret == aHide) {
- return;
- }
-
- nsCOMPtr<nsIPresShell> presShell = GetPresShell();
- NS_ENSURE_TRUE_VOID(presShell);
- RefPtr<nsCaret> caret = presShell->GetCaret();
- NS_ENSURE_TRUE_VOID(caret);
-
- mHidingCaret = aHide;
- if (aHide) {
- caret->AddForceHide();
- } else {
- caret->RemoveForceHide();
- }
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/EditorBase.h b/editor/libeditor/EditorBase.h
deleted file mode 100644
index 08a895dcd..000000000
--- a/editor/libeditor/EditorBase.h
+++ /dev/null
@@ -1,1126 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_EditorBase_h
-#define mozilla_EditorBase_h
-
-#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc.
-#include "mozFlushType.h" // for mozFlushType enum
-#include "mozilla/OwningNonNull.h" // for OwningNonNull
-#include "mozilla/SelectionState.h" // for RangeUpdater, etc.
-#include "mozilla/StyleSheet.h" // for StyleSheet
-#include "mozilla/UniquePtr.h"
-#include "mozilla/WeakPtr.h" // for WeakPtr
-#include "mozilla/dom/Text.h"
-#include "nsCOMPtr.h" // for already_AddRefed, nsCOMPtr
-#include "nsCycleCollectionParticipant.h"
-#include "nsGkAtoms.h"
-#include "nsIDocument.h" // for nsIDocument
-#include "nsIEditor.h" // for nsIEditor::EDirection, etc.
-#include "nsIEditorIMESupport.h" // for NS_DECL_NSIEDITORIMESUPPORT, etc.
-#include "nsIObserver.h" // for NS_DECL_NSIOBSERVER, etc.
-#include "nsIPhonetic.h" // for NS_DECL_NSIPHONETIC, etc.
-#include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc.
-#include "nsISelectionController.h" // for nsISelectionController constants
-#include "nsISupportsImpl.h" // for EditorBase::Release, etc.
-#include "nsIWeakReferenceUtils.h" // for nsWeakPtr
-#include "nsLiteralString.h" // for NS_LITERAL_STRING
-#include "nsString.h" // for nsCString
-#include "nsWeakReference.h" // for nsSupportsWeakReference
-#include "nscore.h" // for nsresult, nsAString, etc.
-
-class nsIAtom;
-class nsIContent;
-class nsIDOMEvent;
-class nsIDOMEventListener;
-class nsIDOMEventTarget;
-class nsIDOMKeyEvent;
-class nsIDOMNode;
-class nsIDocument;
-class nsIDocumentStateListener;
-class nsIEditActionListener;
-class nsIEditorObserver;
-class nsIInlineSpellChecker;
-class nsINode;
-class nsIPresShell;
-class nsISupports;
-class nsITransaction;
-class nsIWidget;
-class nsRange;
-class nsString;
-class nsTransactionManager;
-
-// This is int32_t instead of int16_t because nsIInlineSpellChecker.idl's
-// spellCheckAfterEditorChange is defined to take it as a long.
-// XXX EditAction causes unnecessary include of EditorBase from some places.
-// Why don't you move this to nsIEditor.idl?
-enum class EditAction : int32_t
-{
- ignore = -1,
- none = 0,
- undo,
- redo,
- insertNode,
- createNode,
- deleteNode,
- splitNode,
- joinNode,
- deleteText = 1003,
-
- // text commands
- insertText = 2000,
- insertIMEText = 2001,
- deleteSelection = 2002,
- setTextProperty = 2003,
- removeTextProperty = 2004,
- outputText = 2005,
-
- // html only action
- insertBreak = 3000,
- makeList = 3001,
- indent = 3002,
- outdent = 3003,
- align = 3004,
- makeBasicBlock = 3005,
- removeList = 3006,
- makeDefListItem = 3007,
- insertElement = 3008,
- insertQuotation = 3009,
- htmlPaste = 3012,
- loadHTML = 3013,
- resetTextProperties = 3014,
- setAbsolutePosition = 3015,
- removeAbsolutePosition = 3016,
- decreaseZIndex = 3017,
- increaseZIndex = 3018
-};
-
-inline bool operator!(const EditAction& aOp)
-{
- return aOp == EditAction::none;
-}
-
-namespace mozilla {
-class AddStyleSheetTransaction;
-class AutoRules;
-class AutoSelectionRestorer;
-class AutoTransactionsConserveSelection;
-class ChangeAttributeTransaction;
-class CompositionTransaction;
-class CreateElementTransaction;
-class DeleteNodeTransaction;
-class DeleteTextTransaction;
-class EditAggregateTransaction;
-class ErrorResult;
-class InsertNodeTransaction;
-class InsertTextTransaction;
-class JoinNodeTransaction;
-class PlaceholderTransaction;
-class RemoveStyleSheetTransaction;
-class SplitNodeTransaction;
-class TextComposition;
-struct EditorDOMPoint;
-
-namespace dom {
-class DataTransfer;
-class Element;
-class EventTarget;
-class Selection;
-class Text;
-} // namespace dom
-
-namespace widget {
-struct IMEState;
-} // namespace widget
-
-/**
- * CachedWeakPtr stores a pointer to a class which inherits nsIWeakReference.
- * If the instance of the class has already been destroyed, this returns
- * nullptr. Otherwise, returns cached pointer.
- */
-template<class T>
-class CachedWeakPtr final
-{
-public:
- CachedWeakPtr<T>()
- : mCache(nullptr)
- {
- }
-
- CachedWeakPtr<T>& operator=(T* aObject)
- {
- mWeakPtr = do_GetWeakReference(aObject);
- mCache = aObject;
- return *this;
- }
- CachedWeakPtr<T>& operator=(const nsCOMPtr<T>& aOther)
- {
- mWeakPtr = do_GetWeakReference(aOther);
- mCache = aOther;
- return *this;
- }
- CachedWeakPtr<T>& operator=(already_AddRefed<T>& aOther)
- {
- nsCOMPtr<T> other = aOther;
- mWeakPtr = do_GetWeakReference(other);
- mCache = other;
- return *this;
- }
-
- bool IsAlive() const { return mWeakPtr && mWeakPtr->IsAlive(); }
-
- explicit operator bool() const { return mWeakPtr; }
- operator T*() const { return get(); }
- T* get() const
- {
- if (mCache && !mWeakPtr->IsAlive()) {
- const_cast<CachedWeakPtr<T>*>(this)->mCache = nullptr;
- }
- return mCache;
- }
-
-private:
- nsWeakPtr mWeakPtr;
- T* MOZ_NON_OWNING_REF mCache;
-};
-
-#define kMOZEditorBogusNodeAttrAtom nsGkAtoms::mozeditorbogusnode
-#define kMOZEditorBogusNodeValue NS_LITERAL_STRING("TRUE")
-
-/**
- * Implementation of an editor object. it will be the controller/focal point
- * for the main editor services. i.e. the GUIManager, publishing, transaction
- * manager, event interfaces. the idea for the event interfaces is to have them
- * delegate the actual commands to the editor independent of the XPFE
- * implementation.
- */
-class EditorBase : public nsIEditor
- , public nsIEditorIMESupport
- , public nsSupportsWeakReference
- , public nsIPhonetic
-{
-public:
- typedef dom::Element Element;
- typedef dom::Selection Selection;
- typedef dom::Text Text;
-
- enum IterDirection
- {
- kIterForward,
- kIterBackward
- };
-
- /**
- * The default constructor. This should suffice. the setting of the
- * interfaces is done after the construction of the editor class.
- */
- EditorBase();
-
-protected:
- /**
- * The default destructor. This should suffice. Should this be pure virtual
- * for someone to derive from the EditorBase later? I don't believe so.
- */
- virtual ~EditorBase();
-
-public:
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EditorBase, nsIEditor)
-
- bool IsInitialized() const { return !!mDocumentWeak; }
- already_AddRefed<nsIDOMDocument> GetDOMDocument();
- already_AddRefed<nsIDocument> GetDocument();
- already_AddRefed<nsIPresShell> GetPresShell();
- already_AddRefed<nsIWidget> GetWidget();
- enum NotificationForEditorObservers
- {
- eNotifyEditorObserversOfEnd,
- eNotifyEditorObserversOfBefore,
- eNotifyEditorObserversOfCancel
- };
- void NotifyEditorObservers(NotificationForEditorObservers aNotification);
-
- // nsIEditor methods
- NS_DECL_NSIEDITOR
-
- // nsIEditorIMESupport methods
- NS_DECL_NSIEDITORIMESUPPORT
-
- // nsIPhonetic
- NS_DECL_NSIPHONETIC
-
-public:
- virtual bool IsModifiableNode(nsINode* aNode);
-
- virtual nsresult InsertTextImpl(const nsAString& aStringToInsert,
- nsCOMPtr<nsINode>* aInOutNode,
- int32_t* aInOutOffset,
- nsIDocument* aDoc);
- nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
- Text& aTextNode, int32_t aOffset,
- bool aSuppressIME = false);
- NS_IMETHOD DeleteSelectionImpl(EDirection aAction,
- EStripWrappers aStripWrappers);
-
- already_AddRefed<Element> DeleteSelectionAndCreateElement(nsIAtom& aTag);
-
- /**
- * Helper routines for node/parent manipulations.
- */
- nsresult DeleteNode(nsINode* aNode);
- nsresult InsertNode(nsIContent& aNode, nsINode& aParent, int32_t aPosition);
- enum ECloneAttributes { eDontCloneAttributes, eCloneAttributes };
- already_AddRefed<Element> ReplaceContainer(Element* aOldContainer,
- nsIAtom* aNodeType,
- nsIAtom* aAttribute = nullptr,
- const nsAString* aValue = nullptr,
- ECloneAttributes aCloneAttributes
- = eDontCloneAttributes);
- void CloneAttributes(Element* aDest, Element* aSource);
-
- nsresult RemoveContainer(nsIContent* aNode);
- already_AddRefed<Element> InsertContainerAbove(nsIContent* aNode,
- nsIAtom* aNodeType,
- nsIAtom* aAttribute = nullptr,
- const nsAString* aValue =
- nullptr);
- nsIContent* SplitNode(nsIContent& aNode, int32_t aOffset,
- ErrorResult& aResult);
- nsresult JoinNodes(nsINode& aLeftNode, nsINode& aRightNode);
- nsresult MoveNode(nsIContent* aNode, nsINode* aParent, int32_t aOffset);
-
- nsresult CloneAttribute(nsIAtom* aAttribute, Element* aDestElement,
- Element* aSourceElement);
- nsresult RemoveAttribute(Element* aElement, nsIAtom* aAttribute);
- virtual nsresult RemoveAttributeOrEquivalent(Element* aElement,
- nsIAtom* aAttribute,
- bool aSuppressTransaction) = 0;
- nsresult SetAttribute(Element* aElement, nsIAtom* aAttribute,
- const nsAString& aValue);
- virtual nsresult SetAttributeOrEquivalent(Element* aElement,
- nsIAtom* aAttribute,
- const nsAString& aValue,
- bool aSuppressTransaction) = 0;
-
- /**
- * Method to replace certain CreateElementNS() calls.
- *
- * @param aTag Tag you want.
- */
- already_AddRefed<Element> CreateHTMLContent(nsIAtom* aTag);
-
- /**
- * IME event handlers.
- */
- virtual nsresult BeginIMEComposition(WidgetCompositionEvent* aEvent);
- virtual nsresult UpdateIMEComposition(
- WidgetCompositionEvent* aCompositionChangeEvent) = 0;
- void EndIMEComposition();
-
- void SwitchTextDirectionTo(uint32_t aDirection);
-
-protected:
- nsresult DetermineCurrentDirection();
- void FireInputEvent();
-
- /**
- * Create a transaction for setting aAttribute to aValue on aElement. Never
- * returns null.
- */
- already_AddRefed<ChangeAttributeTransaction>
- CreateTxnForSetAttribute(Element& aElement, nsIAtom& aAttribute,
- const nsAString& aValue);
-
- /**
- * Create a transaction for removing aAttribute on aElement. Never returns
- * null.
- */
- already_AddRefed<ChangeAttributeTransaction>
- CreateTxnForRemoveAttribute(Element& aElement, nsIAtom& aAttribute);
-
- /**
- * Create a transaction for creating a new child node of aParent of type aTag.
- */
- already_AddRefed<CreateElementTransaction>
- CreateTxnForCreateElement(nsIAtom& aTag,
- nsINode& aParent,
- int32_t aPosition);
-
- already_AddRefed<Element> CreateNode(nsIAtom* aTag, nsINode* aParent,
- int32_t aPosition);
-
- /**
- * Create a transaction for inserting aNode as a child of aParent.
- */
- already_AddRefed<InsertNodeTransaction>
- CreateTxnForInsertNode(nsIContent& aNode, nsINode& aParent,
- int32_t aOffset);
-
- /**
- * Create a transaction for removing aNode from its parent.
- */
- nsresult CreateTxnForDeleteNode(nsINode* aNode,
- DeleteNodeTransaction** aTransaction);
-
- nsresult CreateTxnForDeleteSelection(
- EDirection aAction,
- EditAggregateTransaction** aTransaction,
- nsINode** aNode,
- int32_t* aOffset,
- int32_t* aLength);
-
- nsresult CreateTxnForDeleteInsertionPoint(
- nsRange* aRange,
- EDirection aAction,
- EditAggregateTransaction* aTransaction,
- nsINode** aNode,
- int32_t* aOffset,
- int32_t* aLength);
-
-
- /**
- * Create a transaction for inserting aStringToInsert into aTextNode. Never
- * returns null.
- */
- already_AddRefed<mozilla::InsertTextTransaction>
- CreateTxnForInsertText(const nsAString& aStringToInsert, Text& aTextNode,
- int32_t aOffset);
-
- /**
- * Never returns null.
- */
- already_AddRefed<mozilla::CompositionTransaction>
- CreateTxnForComposition(const nsAString& aStringToInsert);
-
- /**
- * Create a transaction for adding a style sheet.
- */
- NS_IMETHOD CreateTxnForAddStyleSheet(
- StyleSheet* aSheet,
- AddStyleSheetTransaction** aTransaction);
-
- /**
- * Create a transaction for removing a style sheet.
- */
- NS_IMETHOD CreateTxnForRemoveStyleSheet(
- StyleSheet* aSheet,
- RemoveStyleSheetTransaction** aTransaction);
-
- nsresult DeleteText(nsGenericDOMDataNode& aElement,
- uint32_t aOffset, uint32_t aLength);
-
- already_AddRefed<DeleteTextTransaction>
- CreateTxnForDeleteText(nsGenericDOMDataNode& aElement,
- uint32_t aOffset, uint32_t aLength);
-
- already_AddRefed<DeleteTextTransaction>
- CreateTxnForDeleteCharacter(nsGenericDOMDataNode& aData, uint32_t aOffset,
- EDirection aDirection);
-
- already_AddRefed<SplitNodeTransaction>
- CreateTxnForSplitNode(nsIContent& aNode, uint32_t aOffset);
-
- already_AddRefed<JoinNodeTransaction>
- CreateTxnForJoinNode(nsINode& aLeftNode, nsINode& aRightNode);
-
- /**
- * This method first deletes the selection, if it's not collapsed. Then if
- * the selection lies in a CharacterData node, it splits it. If the
- * selection is at this point collapsed in a CharacterData node, it's
- * adjusted to be collapsed right before or after the node instead (which is
- * always possible, since the node was split).
- */
- nsresult DeleteSelectionAndPrepareToCreateNode();
-
- /**
- * Called after a transaction is done successfully.
- */
- void DoAfterDoTransaction(nsITransaction *aTxn);
-
- /**
- * Called after a transaction is undone successfully.
- */
-
- void DoAfterUndoTransaction();
-
- /**
- * Called after a transaction is redone successfully.
- */
- void DoAfterRedoTransaction();
-
- enum TDocumentListenerNotification
- {
- eDocumentCreated,
- eDocumentToBeDestroyed,
- eDocumentStateChanged
- };
-
- /**
- * Tell the doc state listeners that the doc state has changed.
- */
- NS_IMETHOD NotifyDocumentListeners(
- TDocumentListenerNotification aNotificationType);
-
- /**
- * Make the given selection span the entire document.
- */
- virtual nsresult SelectEntireDocument(Selection* aSelection);
-
- /**
- * Helper method for scrolling the selection into view after
- * an edit operation. aScrollToAnchor should be true if you
- * want to scroll to the point where the selection was started.
- * If false, it attempts to scroll the end of the selection into view.
- *
- * Editor methods *should* call this method instead of the versions
- * in the various selection interfaces, since this version makes sure
- * that the editor's sync/async settings for reflowing, painting, and
- * scrolling match.
- */
- NS_IMETHOD ScrollSelectionIntoView(bool aScrollToAnchor);
-
- virtual bool IsBlockNode(nsINode* aNode);
-
- /**
- * Helper for GetPriorNode() and GetNextNode().
- */
- nsIContent* FindNextLeafNode(nsINode* aCurrentNode,
- bool aGoForward,
- bool bNoBlockCrossing);
-
- virtual nsresult InstallEventListeners();
- virtual void CreateEventListeners();
- virtual void RemoveEventListeners();
-
- /**
- * Return true if spellchecking should be enabled for this editor.
- */
- bool GetDesiredSpellCheckState();
-
- bool CanEnableSpellCheck()
- {
- // Check for password/readonly/disabled, which are not spellchecked
- // regardless of DOM. Also, check to see if spell check should be skipped
- // or not.
- return !IsPasswordEditor() && !IsReadonly() && !IsDisabled() &&
- !ShouldSkipSpellCheck();
- }
-
- /**
- * EnsureComposition() should be called by composition event handlers. This
- * tries to get the composition for the event and set it to mComposition.
- * However, this may fail because the composition may be committed before
- * the event comes to the editor.
- *
- * @return true if there is a composition. Otherwise, for example,
- * a composition event handler in web contents moved focus
- * for committing the composition, returns false.
- */
- bool EnsureComposition(WidgetCompositionEvent* aCompositionEvent);
-
- already_AddRefed<nsISelectionController> GetSelectionController();
- nsresult GetSelection(SelectionType aSelectionType,
- nsISelection** aSelection);
-
-public:
- /**
- * All editor operations which alter the doc should be prefaced
- * with a call to StartOperation, naming the action and direction.
- */
- NS_IMETHOD StartOperation(EditAction opID,
- nsIEditor::EDirection aDirection);
-
- /**
- * All editor operations which alter the doc should be followed
- * with a call to EndOperation.
- */
- NS_IMETHOD EndOperation();
-
- /**
- * Routines for managing the preservation of selection across
- * various editor actions.
- */
- bool ArePreservingSelection();
- void PreserveSelectionAcrossActions(Selection* aSel);
- nsresult RestorePreservedSelection(Selection* aSel);
- void StopPreservingSelection();
-
- /**
- * SplitNode() creates a new node identical to an existing node, and split
- * the contents between the two nodes
- * @param aExistingRightNode The node to split. It will become the new
- * node's next sibling.
- * @param aOffset The offset of aExistingRightNode's
- * content|children to do the split at
- * @param aNewLeftNode The new node resulting from the split, becomes
- * aExistingRightNode's previous sibling.
- */
- nsresult SplitNodeImpl(nsIContent& aExistingRightNode,
- int32_t aOffset,
- nsIContent& aNewLeftNode);
-
- /**
- * JoinNodes() takes 2 nodes and merge their content|children.
- * @param aNodeToKeep The node that will remain after the join.
- * @param aNodeToJoin The node that will be joined with aNodeToKeep.
- * There is no requirement that the two nodes be of the
- * same type.
- * @param aParent The parent of aNodeToKeep
- */
- nsresult JoinNodesImpl(nsINode* aNodeToKeep,
- nsINode* aNodeToJoin,
- nsINode* aParent);
-
- /**
- * Return the offset of aChild in aParent. Asserts fatally if parent or
- * child is null, or parent is not child's parent.
- */
- static int32_t GetChildOffset(nsIDOMNode* aChild,
- nsIDOMNode* aParent);
-
- /**
- * Set outOffset to the offset of aChild in the parent.
- * Returns the parent of aChild.
- */
- static already_AddRefed<nsIDOMNode> GetNodeLocation(nsIDOMNode* aChild,
- int32_t* outOffset);
- static nsINode* GetNodeLocation(nsINode* aChild, int32_t* aOffset);
-
- /**
- * Returns the number of things inside aNode in the out-param aCount.
- * @param aNode is the node to get the length of.
- * If aNode is text, returns number of characters.
- * If not, returns number of children nodes.
- * @param aCount [OUT] the result of the above calculation.
- */
- static nsresult GetLengthOfDOMNode(nsIDOMNode *aNode, uint32_t &aCount);
-
- /**
- * Get the node immediately prior to aCurrentNode.
- * @param aCurrentNode the node from which we start the search
- * @param aEditableNode if true, only return an editable node
- * @param aResultNode [OUT] the node that occurs before aCurrentNode in
- * the tree, skipping non-editable nodes if
- * aEditableNode is true. If there is no prior
- * node, aResultNode will be nullptr.
- * @param bNoBlockCrossing If true, don't move across "block" nodes,
- * whatever that means.
- */
- nsIContent* GetPriorNode(nsINode* aCurrentNode, bool aEditableNode,
- bool aNoBlockCrossing = false);
-
- /**
- * And another version that takes a {parent,offset} pair rather than a node.
- */
- nsIContent* GetPriorNode(nsINode* aParentNode,
- int32_t aOffset,
- bool aEditableNode,
- bool aNoBlockCrossing = false);
-
-
- /**
- * Get the node immediately after to aCurrentNode.
- * @param aCurrentNode the node from which we start the search
- * @param aEditableNode if true, only return an editable node
- * @param aResultNode [OUT] the node that occurs after aCurrentNode in the
- * tree, skipping non-editable nodes if
- * aEditableNode is true. If there is no prior
- * node, aResultNode will be nullptr.
- */
- nsIContent* GetNextNode(nsINode* aCurrentNode,
- bool aEditableNode,
- bool bNoBlockCrossing = false);
-
- /**
- * And another version that takes a {parent,offset} pair rather than a node.
- */
- nsIContent* GetNextNode(nsINode* aParentNode,
- int32_t aOffset,
- bool aEditableNode,
- bool aNoBlockCrossing = false);
-
- /**
- * Helper for GetNextNode() and GetPriorNode().
- */
- nsIContent* FindNode(nsINode* aCurrentNode,
- bool aGoForward,
- bool aEditableNode,
- bool bNoBlockCrossing);
- /**
- * Get the rightmost child of aCurrentNode;
- * return nullptr if aCurrentNode has no children.
- */
- nsIContent* GetRightmostChild(nsINode* aCurrentNode,
- bool bNoBlockCrossing = false);
-
- /**
- * Get the leftmost child of aCurrentNode;
- * return nullptr if aCurrentNode has no children.
- */
- nsIContent* GetLeftmostChild(nsINode *aCurrentNode,
- bool bNoBlockCrossing = false);
-
- /**
- * Returns true if aNode is of the type implied by aTag.
- */
- static inline bool NodeIsType(nsIDOMNode* aNode, nsIAtom* aTag)
- {
- return GetTag(aNode) == aTag;
- }
-
- /**
- * Returns true if aParent can contain a child of type aTag.
- */
- bool CanContain(nsINode& aParent, nsIContent& aChild);
- bool CanContainTag(nsINode& aParent, nsIAtom& aTag);
- bool TagCanContain(nsIAtom& aParentTag, nsIContent& aChild);
- virtual bool TagCanContainTag(nsIAtom& aParentTag, nsIAtom& aChildTag);
-
- /**
- * Returns true if aNode is our root node.
- */
- bool IsRoot(nsIDOMNode* inNode);
- bool IsRoot(nsINode* inNode);
- bool IsEditorRoot(nsINode* aNode);
-
- /**
- * Returns true if aNode is a descendant of our root node.
- */
- bool IsDescendantOfRoot(nsIDOMNode* inNode);
- bool IsDescendantOfRoot(nsINode* inNode);
- bool IsDescendantOfEditorRoot(nsINode* aNode);
-
- /**
- * Returns true if aNode is a container.
- */
- virtual bool IsContainer(nsINode* aNode);
- virtual bool IsContainer(nsIDOMNode* aNode);
-
- /**
- * returns true if aNode is an editable node.
- */
- bool IsEditable(nsIDOMNode* aNode);
- virtual bool IsEditable(nsINode* aNode);
-
- /**
- * Returns true if aNode is a MozEditorBogus node.
- */
- bool IsMozEditorBogusNode(nsINode* aNode);
-
- /**
- * Counts number of editable child nodes.
- */
- uint32_t CountEditableChildren(nsINode* aNode);
-
- /**
- * Find the deep first and last children.
- */
- nsINode* GetFirstEditableNode(nsINode* aRoot);
-
- /**
- * Returns current composition.
- */
- TextComposition* GetComposition() const;
-
- /**
- * Returns true if there is composition string and not fixed.
- */
- bool IsIMEComposing() const;
-
- /**
- * Returns true when inserting text should be a part of current composition.
- */
- bool ShouldHandleIMEComposition() const;
-
- /**
- * From html rules code - migration in progress.
- */
- static nsresult GetTagString(nsIDOMNode* aNode, nsAString& outString);
- static nsIAtom* GetTag(nsIDOMNode* aNode);
-
- bool NodesSameType(nsIDOMNode* aNode1, nsIDOMNode* aNode2);
- virtual bool AreNodesSameType(nsIContent* aNode1, nsIContent* aNode2);
-
- static bool IsTextNode(nsIDOMNode* aNode);
- static bool IsTextNode(nsINode* aNode);
-
- static nsCOMPtr<nsIDOMNode> GetChildAt(nsIDOMNode* aParent, int32_t aOffset);
- static nsIContent* GetNodeAtRangeOffsetPoint(nsIDOMNode* aParentOrNode,
- int32_t aOffset);
-
- static nsresult GetStartNodeAndOffset(Selection* aSelection,
- nsIDOMNode** outStartNode,
- int32_t* outStartOffset);
- static nsresult GetStartNodeAndOffset(Selection* aSelection,
- nsINode** aStartNode,
- int32_t* aStartOffset);
- static nsresult GetEndNodeAndOffset(Selection* aSelection,
- nsIDOMNode** outEndNode,
- int32_t* outEndOffset);
- static nsresult GetEndNodeAndOffset(Selection* aSelection,
- nsINode** aEndNode,
- int32_t* aEndOffset);
-#if DEBUG_JOE
- static void DumpNode(nsIDOMNode* aNode, int32_t indent = 0);
-#endif
- Selection* GetSelection(SelectionType aSelectionType =
- SelectionType::eNormal);
-
- /**
- * Helpers to add a node to the selection.
- * Used by table cell selection methods.
- */
- nsresult CreateRange(nsIDOMNode* aStartParent, int32_t aStartOffset,
- nsIDOMNode* aEndParent, int32_t aEndOffset,
- nsRange** aRange);
-
- /**
- * Creates a range with just the supplied node and appends that to the
- * selection.
- */
- nsresult AppendNodeToSelectionAsRange(nsIDOMNode *aNode);
-
- /**
- * When you are using AppendNodeToSelectionAsRange(), call this first to
- * start a new selection.
- */
- nsresult ClearSelection();
-
- nsresult IsPreformatted(nsIDOMNode* aNode, bool* aResult);
-
- enum class EmptyContainers { no, yes };
- int32_t SplitNodeDeep(nsIContent& aNode, nsIContent& aSplitPointParent,
- int32_t aSplitPointOffset,
- EmptyContainers aEmptyContainers =
- EmptyContainers::yes,
- nsIContent** outLeftNode = nullptr,
- nsIContent** outRightNode = nullptr);
- EditorDOMPoint JoinNodeDeep(nsIContent& aLeftNode,
- nsIContent& aRightNode);
-
- nsresult GetString(const nsAString& name, nsAString& value);
-
- void BeginUpdateViewBatch();
- virtual nsresult EndUpdateViewBatch();
-
- bool GetShouldTxnSetSelection();
-
- virtual nsresult HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent);
-
- nsresult HandleInlineSpellCheck(EditAction action,
- Selection* aSelection,
- nsIDOMNode* previousSelectedNode,
- int32_t previousSelectedOffset,
- nsIDOMNode* aStartNode,
- int32_t aStartOffset,
- nsIDOMNode* aEndNode,
- int32_t aEndOffset);
-
- virtual already_AddRefed<dom::EventTarget> GetDOMEventTarget() = 0;
-
- /**
- * Fast non-refcounting editor root element accessor
- */
- Element* GetRoot();
-
- /**
- * Likewise, but gets the editor's root instead, which is different for HTML
- * editors.
- */
- virtual Element* GetEditorRoot();
-
- /**
- * Likewise, but gets the text control element instead of the root for
- * plaintext editors.
- */
- Element* GetExposedRoot();
-
- /**
- * Accessor methods to flags.
- */
- bool IsPlaintextEditor() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorPlaintextMask) != 0;
- }
-
- bool IsSingleLineEditor() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorSingleLineMask) != 0;
- }
-
- bool IsPasswordEditor() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorPasswordMask) != 0;
- }
-
- bool IsReadonly() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorReadonlyMask) != 0;
- }
-
- bool IsDisabled() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorDisabledMask) != 0;
- }
-
- bool IsInputFiltered() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorFilterInputMask) != 0;
- }
-
- bool IsMailEditor() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorMailMask) != 0;
- }
-
- bool IsWrapHackEnabled() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorEnableWrapHackMask) != 0;
- }
-
- bool IsFormWidget() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorWidgetMask) != 0;
- }
-
- bool NoCSS() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorNoCSSMask) != 0;
- }
-
- bool IsInteractionAllowed() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorAllowInteraction) != 0;
- }
-
- bool DontEchoPassword() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorDontEchoPassword) != 0;
- }
-
- bool ShouldSkipSpellCheck() const
- {
- return (mFlags & nsIPlaintextEditor::eEditorSkipSpellCheck) != 0;
- }
-
- bool IsTabbable() const
- {
- return IsSingleLineEditor() || IsPasswordEditor() || IsFormWidget() ||
- IsInteractionAllowed();
- }
-
- bool HasIndependentSelection() const
- {
- return !!mSelectionControllerWeak;
- }
-
- /**
- * Get the input event target. This might return null.
- */
- virtual already_AddRefed<nsIContent> GetInputEventTargetContent() = 0;
-
- /**
- * Get the focused content, if we're focused. Returns null otherwise.
- */
- virtual already_AddRefed<nsIContent> GetFocusedContent();
-
- /**
- * Get the focused content for the argument of some IMEStateManager's
- * methods.
- */
- virtual already_AddRefed<nsIContent> GetFocusedContentForIME();
-
- /**
- * Whether the editor is active on the DOM window. Note that when this
- * returns true but GetFocusedContent() returns null, it means that this editor was
- * focused when the DOM window was active.
- */
- virtual bool IsActiveInDOMWindow();
-
- /**
- * Whether the aGUIEvent should be handled by this editor or not. When this
- * returns false, The aGUIEvent shouldn't be handled on this editor,
- * i.e., The aGUIEvent should be handled by another inner editor or ancestor
- * elements.
- */
- virtual bool IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent);
-
- /**
- * FindSelectionRoot() returns a selection root of this editor when aNode
- * gets focus. aNode must be a content node or a document node. When the
- * target isn't a part of this editor, returns nullptr. If this is for
- * designMode, you should set the document node to aNode except that an
- * element in the document has focus.
- */
- virtual already_AddRefed<nsIContent> FindSelectionRoot(nsINode* aNode);
-
- /**
- * Initializes selection and caret for the editor. If aEventTarget isn't
- * a host of the editor, i.e., the editor doesn't get focus, this does
- * nothing.
- */
- nsresult InitializeSelection(nsIDOMEventTarget* aFocusEventTarget);
-
- /**
- * This method has to be called by EditorEventListener::Focus.
- * All actions that have to be done when the editor is focused needs to be
- * added here.
- */
- void OnFocus(nsIDOMEventTarget* aFocusEventTarget);
-
- /**
- * Used to insert content from a data transfer into the editable area.
- * This is called for each item in the data transfer, with the index of
- * each item passed as aIndex.
- */
- virtual nsresult InsertFromDataTransfer(dom::DataTransfer* aDataTransfer,
- int32_t aIndex,
- nsIDOMDocument* aSourceDoc,
- nsIDOMNode* aDestinationNode,
- int32_t aDestOffset,
- bool aDoDeleteSelection) = 0;
-
- virtual nsresult InsertFromDrop(nsIDOMEvent* aDropEvent) = 0;
-
- virtual already_AddRefed<nsIDOMNode> FindUserSelectAllNode(nsIDOMNode* aNode)
- {
- return nullptr;
- }
-
- /**
- * GetIMESelectionStartOffsetIn() returns the start offset of IME selection in
- * the aTextNode. If there is no IME selection, returns -1.
- */
- int32_t GetIMESelectionStartOffsetIn(nsINode* aTextNode);
-
- /**
- * FindBetterInsertionPoint() tries to look for better insertion point which
- * is typically the nearest text node and offset in it.
- */
- void FindBetterInsertionPoint(nsCOMPtr<nsIDOMNode>& aNode,
- int32_t& aOffset);
- void FindBetterInsertionPoint(nsCOMPtr<nsINode>& aNode,
- int32_t& aOffset);
-
- /**
- * HideCaret() hides caret with nsCaret::AddForceHide() or may show carent
- * with nsCaret::RemoveForceHide(). This does NOT set visibility of
- * nsCaret. Therefore, this is stateless.
- */
- void HideCaret(bool aHide);
-
- void FlushFrames()
- {
- nsCOMPtr<nsIDocument> doc = GetDocument();
- if (doc) {
- doc->FlushPendingNotifications(Flush_Frames);
- }
- }
-
-private:
- // Weak reference to the nsISelectionController.
- // Use GetSelectionController() to retrieve actual pointer.
- CachedWeakPtr<nsISelectionController> mSelectionControllerWeak;
- // Weak reference to the nsIDocument.
- // Use GetDocument() to retrieve actual pointer.
- CachedWeakPtr<nsIDocument> mDocumentWeak;
-
-protected:
- enum Tristate
- {
- eTriUnset,
- eTriFalse,
- eTriTrue
- };
-
- // MIME type of the doc we are editing.
- nsCString mContentMIMEType;
-
- nsCOMPtr<nsIInlineSpellChecker> mInlineSpellChecker;
-
- RefPtr<nsTransactionManager> mTxnMgr;
- // Cached root node.
- nsCOMPtr<Element> mRootElement;
- // Current IME text node.
- RefPtr<Text> mIMETextNode;
- // The form field as an event receiver.
- nsCOMPtr<dom::EventTarget> mEventTarget;
- nsCOMPtr<nsIDOMEventListener> mEventListener;
- // Weak reference to placeholder for begin/end batch purposes.
- WeakPtr<PlaceholderTransaction> mPlaceholderTransactionWeak;
- // Name of placeholder transaction.
- nsIAtom* mPlaceholderName;
- // Saved selection state for placeholder transaction batching.
- mozilla::UniquePtr<SelectionState> mSelState;
- nsString* mPhonetic;
- // IME composition this is not null between compositionstart and
- // compositionend.
- RefPtr<TextComposition> mComposition;
-
- // Listens to all low level actions on the doc.
- typedef AutoTArray<OwningNonNull<nsIEditActionListener>, 5>
- AutoActionListenerArray;
- AutoActionListenerArray mActionListeners;
- // Just notify once per high level change.
- typedef AutoTArray<OwningNonNull<nsIEditorObserver>, 3>
- AutoEditorObserverArray;
- AutoEditorObserverArray mEditorObservers;
- // Listen to overall doc state (dirty or not, just created, etc.).
- typedef AutoTArray<OwningNonNull<nsIDocumentStateListener>, 1>
- AutoDocumentStateListenerArray;
- AutoDocumentStateListenerArray mDocStateListeners;
-
- // Cached selection for AutoSelectionRestorer.
- SelectionState mSavedSel;
- // Utility class object for maintaining preserved ranges.
- RangeUpdater mRangeUpdater;
-
- // Number of modifications (for undo/redo stack).
- uint32_t mModCount;
- // Behavior flags. See nsIPlaintextEditor.idl for the flags we use.
- uint32_t mFlags;
-
- int32_t mUpdateCount;
-
- // Nesting count for batching.
- int32_t mPlaceholderBatch;
- // The current editor action.
- EditAction mAction;
-
- // Offset in text node where IME comp string begins.
- uint32_t mIMETextOffset;
- // The Length of the composition string or commit string. If this is length
- // of commit string, the length is truncated by maxlength attribute.
- uint32_t mIMETextLength;
-
- // The current direction of editor action.
- EDirection mDirection;
- // -1 = not initialized
- int8_t mDocDirtyState;
- // A Tristate value.
- uint8_t mSpellcheckCheckboxState;
-
- // Turn off for conservative selection adjustment by transactions.
- bool mShouldTxnSetSelection;
- // Whether PreDestroy has been called.
- bool mDidPreDestroy;
- // Whether PostCreate has been called.
- bool mDidPostCreate;
- bool mDispatchInputEvent;
- // True while the instance is handling an edit action.
- bool mIsInEditAction;
- // Whether caret is hidden forcibly.
- bool mHidingCaret;
-
- friend bool NSCanUnload(nsISupports* serviceMgr);
- friend class AutoRules;
- friend class AutoSelectionRestorer;
- friend class AutoTransactionsConserveSelection;
- friend class RangeUpdater;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef mozilla_EditorBase_h
diff --git a/editor/libeditor/EditorCommands.cpp b/editor/libeditor/EditorCommands.cpp
deleted file mode 100644
index 2bb32e2aa..000000000
--- a/editor/libeditor/EditorCommands.cpp
+++ /dev/null
@@ -1,1169 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "EditorCommands.h"
-
-#include "mozFlushType.h"
-#include "mozilla/ArrayUtils.h"
-#include "mozilla/Assertions.h"
-#include "mozilla/TextEditor.h"
-#include "nsCOMPtr.h"
-#include "nsCRT.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsIClipboard.h"
-#include "nsICommandParams.h"
-#include "nsID.h"
-#include "nsIDOMDocument.h"
-#include "nsIDocument.h"
-#include "nsIEditor.h"
-#include "nsIEditorMailSupport.h"
-#include "nsIPlaintextEditor.h"
-#include "nsISelection.h"
-#include "nsISelectionController.h"
-#include "nsITransferable.h"
-#include "nsString.h"
-#include "nsAString.h"
-
-class nsISupports;
-
-#define STATE_ENABLED "state_enabled"
-#define STATE_DATA "state_data"
-
-namespace mozilla {
-
-/******************************************************************************
- * mozilla::EditorCommandBase
- ******************************************************************************/
-
-EditorCommandBase::EditorCommandBase()
-{
-}
-
-NS_IMPL_ISUPPORTS(EditorCommandBase, nsIControllerCommand)
-
-/******************************************************************************
- * mozilla::UndoCommand
- ******************************************************************************/
-
-NS_IMETHODIMP
-UndoCommand::IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled)
-{
- NS_ENSURE_ARG_POINTER(aIsEnabled);
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor) {
- bool isEnabled, isEditable = false;
- nsresult rv = editor->GetIsSelectionEditable(&isEditable);
- NS_ENSURE_SUCCESS(rv, rv);
- if (isEditable)
- return editor->CanUndo(&isEnabled, aIsEnabled);
- }
-
- *aIsEnabled = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-UndoCommand::DoCommand(const char* aCommandName,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor)
- return editor->Undo(1);
-
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-UndoCommand::DoCommandParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- return DoCommand(aCommandName, aCommandRefCon);
-}
-
-NS_IMETHODIMP
-UndoCommand::GetCommandStateParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- bool canUndo;
- IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
- return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
-}
-
-/******************************************************************************
- * mozilla::RedoCommand
- ******************************************************************************/
-
-NS_IMETHODIMP
-RedoCommand::IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled)
-{
- NS_ENSURE_ARG_POINTER(aIsEnabled);
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor) {
- bool isEnabled, isEditable = false;
- nsresult rv = editor->GetIsSelectionEditable(&isEditable);
- NS_ENSURE_SUCCESS(rv, rv);
- if (isEditable)
- return editor->CanRedo(&isEnabled, aIsEnabled);
- }
-
- *aIsEnabled = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-RedoCommand::DoCommand(const char* aCommandName,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor)
- return editor->Redo(1);
-
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-RedoCommand::DoCommandParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- return DoCommand(aCommandName, aCommandRefCon);
-}
-
-NS_IMETHODIMP
-RedoCommand::GetCommandStateParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- bool canUndo;
- IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
- return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
-}
-
-/******************************************************************************
- * mozilla::ClearUndoCommand
- ******************************************************************************/
-
-NS_IMETHODIMP
-ClearUndoCommand::IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled)
-{
- NS_ENSURE_ARG_POINTER(aIsEnabled);
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor)
- return editor->GetIsSelectionEditable(aIsEnabled);
-
- *aIsEnabled = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-ClearUndoCommand::DoCommand(const char* aCommandName,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- NS_ENSURE_TRUE(editor, NS_ERROR_NOT_IMPLEMENTED);
-
- editor->EnableUndo(false); // Turning off undo clears undo/redo stacks.
- editor->EnableUndo(true); // This re-enables undo/redo.
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-ClearUndoCommand::DoCommandParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- return DoCommand(aCommandName, aCommandRefCon);
-}
-
-NS_IMETHODIMP
-ClearUndoCommand::GetCommandStateParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- NS_ENSURE_ARG_POINTER(aParams);
-
- bool enabled;
- nsresult rv = IsCommandEnabled(aCommandName, aCommandRefCon, &enabled);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return aParams->SetBooleanValue(STATE_ENABLED, enabled);
-}
-
-/******************************************************************************
- * mozilla::CutCommand
- ******************************************************************************/
-
-NS_IMETHODIMP
-CutCommand::IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled)
-{
- NS_ENSURE_ARG_POINTER(aIsEnabled);
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor) {
- bool isEditable = false;
- nsresult rv = editor->GetIsSelectionEditable(&isEditable);
- NS_ENSURE_SUCCESS(rv, rv);
- if (isEditable)
- return editor->CanCut(aIsEnabled);
- }
-
- *aIsEnabled = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-CutCommand::DoCommand(const char* aCommandName,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor)
- return editor->Cut();
-
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-CutCommand::DoCommandParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- return DoCommand(aCommandName, aCommandRefCon);
-}
-
-NS_IMETHODIMP
-CutCommand::GetCommandStateParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- bool canUndo;
- IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
- return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
-}
-
-/******************************************************************************
- * mozilla::CutOrDeleteCommand
- ******************************************************************************/
-
-NS_IMETHODIMP
-CutOrDeleteCommand::IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled)
-{
- NS_ENSURE_ARG_POINTER(aIsEnabled);
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor)
- return editor->GetIsSelectionEditable(aIsEnabled);
-
- *aIsEnabled = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-CutOrDeleteCommand::DoCommand(const char* aCommandName,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor) {
- nsCOMPtr<nsISelection> selection;
- nsresult rv = editor->GetSelection(getter_AddRefs(selection));
- if (NS_SUCCEEDED(rv) && selection && selection->Collapsed()) {
- return editor->DeleteSelection(nsIEditor::eNext, nsIEditor::eStrip);
- }
- return editor->Cut();
- }
-
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-CutOrDeleteCommand::DoCommandParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- return DoCommand(aCommandName, aCommandRefCon);
-}
-
-NS_IMETHODIMP
-CutOrDeleteCommand::GetCommandStateParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- bool canUndo;
- IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
- return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
-}
-
-/******************************************************************************
- * mozilla::CopyCommand
- ******************************************************************************/
-
-NS_IMETHODIMP
-CopyCommand::IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled)
-{
- NS_ENSURE_ARG_POINTER(aIsEnabled);
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor)
- return editor->CanCopy(aIsEnabled);
-
- *aIsEnabled = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-CopyCommand::DoCommand(const char* aCommandName,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor)
- return editor->Copy();
-
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-CopyCommand::DoCommandParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- return DoCommand(aCommandName, aCommandRefCon);
-}
-
-NS_IMETHODIMP
-CopyCommand::GetCommandStateParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- bool canUndo;
- IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
- return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
-}
-
-/******************************************************************************
- * mozilla::CopyOrDeleteCommand
- ******************************************************************************/
-
-NS_IMETHODIMP
-CopyOrDeleteCommand::IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled)
-{
- NS_ENSURE_ARG_POINTER(aIsEnabled);
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor)
- return editor->GetIsSelectionEditable(aIsEnabled);
-
- *aIsEnabled = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-CopyOrDeleteCommand::DoCommand(const char* aCommandName,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor) {
- nsCOMPtr<nsISelection> selection;
- nsresult rv = editor->GetSelection(getter_AddRefs(selection));
- if (NS_SUCCEEDED(rv) && selection && selection->Collapsed()) {
- return editor->DeleteSelection(nsIEditor::eNextWord, nsIEditor::eStrip);
- }
- return editor->Copy();
- }
-
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-CopyOrDeleteCommand::DoCommandParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- return DoCommand(aCommandName, aCommandRefCon);
-}
-
-NS_IMETHODIMP
-CopyOrDeleteCommand::GetCommandStateParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- bool canUndo;
- IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
- return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
-}
-
-/******************************************************************************
- * mozilla::CopyAndCollapseToEndCommand
- ******************************************************************************/
-
-NS_IMETHODIMP
-CopyAndCollapseToEndCommand::IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled)
-{
- NS_ENSURE_ARG_POINTER(aIsEnabled);
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor)
- return editor->CanCopy(aIsEnabled);
-
- *aIsEnabled = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-CopyAndCollapseToEndCommand::DoCommand(const char* aCommandName,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor) {
- nsresult rv = editor->Copy();
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- nsCOMPtr<nsISelection> selection;
- rv = editor->GetSelection(getter_AddRefs(selection));
- if (NS_SUCCEEDED(rv) && selection) {
- selection->CollapseToEnd();
- }
- return rv;
- }
-
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-CopyAndCollapseToEndCommand::DoCommandParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- return DoCommand(aCommandName, aCommandRefCon);
-}
-
-NS_IMETHODIMP
-CopyAndCollapseToEndCommand::GetCommandStateParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- bool canUndo;
- IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
- return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
-}
-
-/******************************************************************************
- * mozilla::PasteCommand
- ******************************************************************************/
-
-NS_IMETHODIMP
-PasteCommand::IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled)
-{
- NS_ENSURE_ARG_POINTER(aIsEnabled);
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor) {
- bool isEditable = false;
- nsresult rv = editor->GetIsSelectionEditable(&isEditable);
- NS_ENSURE_SUCCESS(rv, rv);
- if (isEditable)
- return editor->CanPaste(nsIClipboard::kGlobalClipboard, aIsEnabled);
- }
-
- *aIsEnabled = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-PasteCommand::DoCommand(const char* aCommandName,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE);
-
- return editor->Paste(nsIClipboard::kGlobalClipboard);
-}
-
-NS_IMETHODIMP
-PasteCommand::DoCommandParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- return DoCommand(aCommandName, aCommandRefCon);
-}
-
-NS_IMETHODIMP
-PasteCommand::GetCommandStateParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- bool canUndo;
- IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
- return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
-}
-
-/******************************************************************************
- * mozilla::PasteTransferableCommand
- ******************************************************************************/
-
-NS_IMETHODIMP
-PasteTransferableCommand::IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled)
-{
- NS_ENSURE_ARG_POINTER(aIsEnabled);
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor) {
- bool isEditable = false;
- nsresult rv = editor->GetIsSelectionEditable(&isEditable);
- NS_ENSURE_SUCCESS(rv, rv);
- if (isEditable)
- return editor->CanPasteTransferable(nullptr, aIsEnabled);
- }
-
- *aIsEnabled = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-PasteTransferableCommand::DoCommand(const char* aCommandName,
- nsISupports* aCommandRefCon)
-{
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-PasteTransferableCommand::DoCommandParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsISupports> supports;
- aParams->GetISupportsValue("transferable", getter_AddRefs(supports));
- NS_ENSURE_TRUE(supports, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsITransferable> trans = do_QueryInterface(supports);
- NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE);
-
- return editor->PasteTransferable(trans);
-}
-
-NS_IMETHODIMP
-PasteTransferableCommand::GetCommandStateParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsITransferable> trans;
-
- nsCOMPtr<nsISupports> supports;
- aParams->GetISupportsValue("transferable", getter_AddRefs(supports));
- if (supports) {
- trans = do_QueryInterface(supports);
- NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE);
- }
-
- bool canPaste;
- nsresult rv = editor->CanPasteTransferable(trans, &canPaste);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return aParams->SetBooleanValue(STATE_ENABLED, canPaste);
-}
-
-/******************************************************************************
- * mozilla::SwitchTextDirectionCommand
- ******************************************************************************/
-
-NS_IMETHODIMP
-SwitchTextDirectionCommand::IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled)
-{
- NS_ENSURE_ARG_POINTER(aIsEnabled);
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor)
- return editor->GetIsSelectionEditable(aIsEnabled);
-
- *aIsEnabled = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-SwitchTextDirectionCommand::DoCommand(const char* aCommandName,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE);
-
- return editor->SwitchTextDirection();
-}
-
-NS_IMETHODIMP
-SwitchTextDirectionCommand::DoCommandParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- return DoCommand(aCommandName, aCommandRefCon);
-}
-
-NS_IMETHODIMP
-SwitchTextDirectionCommand::GetCommandStateParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- bool canSwitchTextDirection = true;
- IsCommandEnabled(aCommandName, aCommandRefCon, &canSwitchTextDirection);
- return aParams->SetBooleanValue(STATE_ENABLED, canSwitchTextDirection);
-}
-
-/******************************************************************************
- * mozilla::DeleteCommand
- ******************************************************************************/
-
-NS_IMETHODIMP
-DeleteCommand::IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled)
-{
- NS_ENSURE_ARG_POINTER(aIsEnabled);
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- *aIsEnabled = false;
-
- if (!editor) {
- return NS_OK;
- }
-
- // We can generally delete whenever the selection is editable. However,
- // cmd_delete doesn't make sense if the selection is collapsed because it's
- // directionless, which is the same condition under which we can't cut.
- nsresult rv = editor->GetIsSelectionEditable(aIsEnabled);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!nsCRT::strcmp("cmd_delete", aCommandName) && *aIsEnabled) {
- rv = editor->CanDelete(aIsEnabled);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-DeleteCommand::DoCommand(const char* aCommandName,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE);
-
- nsIEditor::EDirection deleteDir = nsIEditor::eNone;
-
- if (!nsCRT::strcmp("cmd_delete", aCommandName)) {
- // Really this should probably be eNone, but it only makes a difference if
- // the selection is collapsed, and then this command is disabled. So let's
- // keep it as it always was to avoid breaking things.
- deleteDir = nsIEditor::ePrevious;
- } else if (!nsCRT::strcmp("cmd_deleteCharForward", aCommandName)) {
- deleteDir = nsIEditor::eNext;
- } else if (!nsCRT::strcmp("cmd_deleteCharBackward", aCommandName)) {
- deleteDir = nsIEditor::ePrevious;
- } else if (!nsCRT::strcmp("cmd_deleteWordBackward", aCommandName)) {
- deleteDir = nsIEditor::ePreviousWord;
- } else if (!nsCRT::strcmp("cmd_deleteWordForward", aCommandName)) {
- deleteDir = nsIEditor::eNextWord;
- } else if (!nsCRT::strcmp("cmd_deleteToBeginningOfLine", aCommandName)) {
- deleteDir = nsIEditor::eToBeginningOfLine;
- } else if (!nsCRT::strcmp("cmd_deleteToEndOfLine", aCommandName)) {
- deleteDir = nsIEditor::eToEndOfLine;
- } else {
- MOZ_CRASH("Unrecognized nsDeleteCommand");
- }
-
- return editor->DeleteSelection(deleteDir, nsIEditor::eStrip);
-}
-
-NS_IMETHODIMP
-DeleteCommand::DoCommandParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- return DoCommand(aCommandName, aCommandRefCon);
-}
-
-NS_IMETHODIMP
-DeleteCommand::GetCommandStateParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- bool canUndo;
- IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
- return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
-}
-
-/******************************************************************************
- * mozilla::SelectAllCommand
- ******************************************************************************/
-
-NS_IMETHODIMP
-SelectAllCommand::IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled)
-{
- NS_ENSURE_ARG_POINTER(aIsEnabled);
-
- nsresult rv = NS_OK;
- // You can always select all, unless the selection is editable,
- // and the editable region is empty!
- *aIsEnabled = true;
- bool docIsEmpty;
-
- // you can select all if there is an editor which is non-empty
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor) {
- rv = editor->GetDocumentIsEmpty(&docIsEmpty);
- NS_ENSURE_SUCCESS(rv, rv);
- *aIsEnabled = !docIsEmpty;
- }
-
- return rv;
-}
-
-NS_IMETHODIMP
-SelectAllCommand::DoCommand(const char* aCommandName,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor)
- return editor->SelectAll();
-
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-SelectAllCommand::DoCommandParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- return DoCommand(aCommandName, aCommandRefCon);
-}
-
-NS_IMETHODIMP
-SelectAllCommand::GetCommandStateParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- bool canUndo;
- IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
- return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
-}
-
-/******************************************************************************
- * mozilla::SelectionMoveCommands
- ******************************************************************************/
-
-NS_IMETHODIMP
-SelectionMoveCommands::IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled)
-{
- NS_ENSURE_ARG_POINTER(aIsEnabled);
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor)
- return editor->GetIsSelectionEditable(aIsEnabled);
-
- *aIsEnabled = false;
- return NS_OK;
-}
-
-static const struct ScrollCommand {
- const char *reverseScroll;
- const char *forwardScroll;
- nsresult (NS_STDCALL nsISelectionController::*scroll)(bool);
-} scrollCommands[] = {
- { "cmd_scrollTop", "cmd_scrollBottom",
- &nsISelectionController::CompleteScroll },
- { "cmd_scrollPageUp", "cmd_scrollPageDown",
- &nsISelectionController::ScrollPage },
- { "cmd_scrollLineUp", "cmd_scrollLineDown",
- &nsISelectionController::ScrollLine }
-};
-
-static const struct MoveCommand {
- const char *reverseMove;
- const char *forwardMove;
- const char *reverseSelect;
- const char *forwardSelect;
- nsresult (NS_STDCALL nsISelectionController::*move)(bool, bool);
-} moveCommands[] = {
- { "cmd_charPrevious", "cmd_charNext",
- "cmd_selectCharPrevious", "cmd_selectCharNext",
- &nsISelectionController::CharacterMove },
- { "cmd_linePrevious", "cmd_lineNext",
- "cmd_selectLinePrevious", "cmd_selectLineNext",
- &nsISelectionController::LineMove },
- { "cmd_wordPrevious", "cmd_wordNext",
- "cmd_selectWordPrevious", "cmd_selectWordNext",
- &nsISelectionController::WordMove },
- { "cmd_beginLine", "cmd_endLine",
- "cmd_selectBeginLine", "cmd_selectEndLine",
- &nsISelectionController::IntraLineMove },
- { "cmd_movePageUp", "cmd_movePageDown",
- "cmd_selectPageUp", "cmd_selectPageDown",
- &nsISelectionController::PageMove },
- { "cmd_moveTop", "cmd_moveBottom",
- "cmd_selectTop", "cmd_selectBottom",
- &nsISelectionController::CompleteMove }
-};
-
-static const struct PhysicalCommand {
- const char *move;
- const char *select;
- int16_t direction;
- int16_t amount;
-} physicalCommands[] = {
- { "cmd_moveLeft", "cmd_selectLeft",
- nsISelectionController::MOVE_LEFT, 0 },
- { "cmd_moveRight", "cmd_selectRight",
- nsISelectionController::MOVE_RIGHT, 0 },
- { "cmd_moveUp", "cmd_selectUp",
- nsISelectionController::MOVE_UP, 0 },
- { "cmd_moveDown", "cmd_selectDown",
- nsISelectionController::MOVE_DOWN, 0 },
- { "cmd_moveLeft2", "cmd_selectLeft2",
- nsISelectionController::MOVE_LEFT, 1 },
- { "cmd_moveRight2", "cmd_selectRight2",
- nsISelectionController::MOVE_RIGHT, 1 },
- { "cmd_moveUp2", "cmd_selectUp2",
- nsISelectionController::MOVE_UP, 1 },
- { "cmd_moveDown2", "cmd_selectDown2",
- nsISelectionController::MOVE_DOWN, 1 }
-};
-
-NS_IMETHODIMP
-SelectionMoveCommands::DoCommand(const char* aCommandName,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIDOMDocument> domDoc;
- editor->GetDocument(getter_AddRefs(domDoc));
- nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
- if (doc) {
- // Most of the commands below (possibly all of them) need layout to
- // be up to date.
- doc->FlushPendingNotifications(Flush_Layout);
- }
-
- nsCOMPtr<nsISelectionController> selCont;
- nsresult rv = editor->GetSelectionController(getter_AddRefs(selCont));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(selCont, NS_ERROR_FAILURE);
-
- // scroll commands
- for (size_t i = 0; i < mozilla::ArrayLength(scrollCommands); i++) {
- const ScrollCommand &cmd = scrollCommands[i];
- if (!nsCRT::strcmp(aCommandName, cmd.reverseScroll)) {
- return (selCont->*(cmd.scroll))(false);
- } else if (!nsCRT::strcmp(aCommandName, cmd.forwardScroll)) {
- return (selCont->*(cmd.scroll))(true);
- }
- }
-
- // caret movement/selection commands
- for (size_t i = 0; i < mozilla::ArrayLength(moveCommands); i++) {
- const MoveCommand &cmd = moveCommands[i];
- if (!nsCRT::strcmp(aCommandName, cmd.reverseMove)) {
- return (selCont->*(cmd.move))(false, false);
- } else if (!nsCRT::strcmp(aCommandName, cmd.forwardMove)) {
- return (selCont->*(cmd.move))(true, false);
- } else if (!nsCRT::strcmp(aCommandName, cmd.reverseSelect)) {
- return (selCont->*(cmd.move))(false, true);
- } else if (!nsCRT::strcmp(aCommandName, cmd.forwardSelect)) {
- return (selCont->*(cmd.move))(true, true);
- }
- }
-
- // physical-direction movement/selection
- for (size_t i = 0; i < mozilla::ArrayLength(physicalCommands); i++) {
- const PhysicalCommand &cmd = physicalCommands[i];
- if (!nsCRT::strcmp(aCommandName, cmd.move)) {
- return selCont->PhysicalMove(cmd.direction, cmd.amount, false);
- } else if (!nsCRT::strcmp(aCommandName, cmd.select)) {
- return selCont->PhysicalMove(cmd.direction, cmd.amount, true);
- }
- }
-
- return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-SelectionMoveCommands::DoCommandParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- return DoCommand(aCommandName, aCommandRefCon);
-}
-
-NS_IMETHODIMP
-SelectionMoveCommands::GetCommandStateParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- bool canUndo;
- IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
- return aParams->SetBooleanValue(STATE_ENABLED, canUndo);
-}
-
-/******************************************************************************
- * mozilla::InsertPlaintextCommand
- ******************************************************************************/
-
-NS_IMETHODIMP
-InsertPlaintextCommand::IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled)
-{
- NS_ENSURE_ARG_POINTER(aIsEnabled);
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor)
- return editor->GetIsSelectionEditable(aIsEnabled);
-
- *aIsEnabled = false;
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-InsertPlaintextCommand::DoCommand(const char* aCommandName,
- nsISupports* aCommandRefCon)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-InsertPlaintextCommand::DoCommandParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- NS_ENSURE_ARG_POINTER(aParams);
-
- nsCOMPtr<nsIPlaintextEditor> editor = do_QueryInterface(aCommandRefCon);
- NS_ENSURE_TRUE(editor, NS_ERROR_NOT_IMPLEMENTED);
-
- // Get text to insert from command params
- nsAutoString text;
- nsresult rv = aParams->GetStringValue(STATE_DATA, text);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!text.IsEmpty())
- return editor->InsertText(text);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-InsertPlaintextCommand::GetCommandStateParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- if (NS_WARN_IF(!aParams)) {
- return NS_ERROR_INVALID_ARG;
- }
-
- bool aIsEnabled = false;
- IsCommandEnabled(aCommandName, aCommandRefCon, &aIsEnabled);
- return aParams->SetBooleanValue(STATE_ENABLED, aIsEnabled);
-}
-
-/******************************************************************************
- * mozilla::InsertParagraphCommand
- ******************************************************************************/
-
-NS_IMETHODIMP
-InsertParagraphCommand::IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled)
-{
- if (NS_WARN_IF(!aIsEnabled)) {
- return NS_ERROR_INVALID_ARG;
- }
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (NS_WARN_IF(!editor)) {
- *aIsEnabled = false;
- return NS_ERROR_NOT_IMPLEMENTED;
- }
-
- return editor->GetIsSelectionEditable(aIsEnabled);
-}
-
-NS_IMETHODIMP
-InsertParagraphCommand::DoCommand(const char* aCommandName,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIPlaintextEditor> editor = do_QueryInterface(aCommandRefCon);
- if (NS_WARN_IF(!editor)) {
- return NS_ERROR_NOT_IMPLEMENTED;
- }
-
- TextEditor* textEditor = static_cast<TextEditor*>(editor.get());
-
- return textEditor->TypedText(EmptyString(), TextEditor::eTypedBreak);
-}
-
-NS_IMETHODIMP
-InsertParagraphCommand::DoCommandParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- return DoCommand(aCommandName, aCommandRefCon);
-}
-
-NS_IMETHODIMP
-InsertParagraphCommand::GetCommandStateParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- if (NS_WARN_IF(!aParams)) {
- return NS_ERROR_INVALID_ARG;
- }
-
- bool aIsEnabled = false;
- IsCommandEnabled(aCommandName, aCommandRefCon, &aIsEnabled);
- return aParams->SetBooleanValue(STATE_ENABLED, aIsEnabled);
-}
-
-/******************************************************************************
- * mozilla::InsertLineBreakCommand
- ******************************************************************************/
-
-NS_IMETHODIMP
-InsertLineBreakCommand::IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled)
-{
- if (NS_WARN_IF(!aIsEnabled)) {
- return NS_ERROR_INVALID_ARG;
- }
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (NS_WARN_IF(!editor)) {
- *aIsEnabled = false;
- return NS_ERROR_NOT_IMPLEMENTED;
- }
-
- return editor->GetIsSelectionEditable(aIsEnabled);
-}
-
-NS_IMETHODIMP
-InsertLineBreakCommand::DoCommand(const char* aCommandName,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIPlaintextEditor> editor = do_QueryInterface(aCommandRefCon);
- if (NS_WARN_IF(!editor)) {
- return NS_ERROR_NOT_IMPLEMENTED;
- }
-
- TextEditor* textEditor = static_cast<TextEditor*>(editor.get());
-
- return textEditor->TypedText(EmptyString(), TextEditor::eTypedBR);
-}
-
-NS_IMETHODIMP
-InsertLineBreakCommand::DoCommandParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- return DoCommand(aCommandName, aCommandRefCon);
-}
-
-NS_IMETHODIMP
-InsertLineBreakCommand::GetCommandStateParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- if (NS_WARN_IF(!aParams)) {
- return NS_ERROR_INVALID_ARG;
- }
-
- bool aIsEnabled = false;
- IsCommandEnabled(aCommandName, aCommandRefCon, &aIsEnabled);
- return aParams->SetBooleanValue(STATE_ENABLED, aIsEnabled);
-}
-
-/******************************************************************************
- * mozilla::PasteQuotationCommand
- ******************************************************************************/
-
-NS_IMETHODIMP
-PasteQuotationCommand::IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled)
-{
- NS_ENSURE_ARG_POINTER(aIsEnabled);
-
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- nsCOMPtr<nsIEditorMailSupport> mailEditor = do_QueryInterface(aCommandRefCon);
- if (editor && mailEditor) {
- uint32_t flags;
- editor->GetFlags(&flags);
- if (!(flags & nsIPlaintextEditor::eEditorSingleLineMask))
- return editor->CanPaste(nsIClipboard::kGlobalClipboard, aIsEnabled);
- }
-
- *aIsEnabled = false;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-PasteQuotationCommand::DoCommand(const char* aCommandName,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIEditorMailSupport> mailEditor = do_QueryInterface(aCommandRefCon);
- if (mailEditor)
- return mailEditor->PasteAsQuotation(nsIClipboard::kGlobalClipboard);
-
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-PasteQuotationCommand::DoCommandParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIEditorMailSupport> mailEditor = do_QueryInterface(aCommandRefCon);
- if (mailEditor)
- return mailEditor->PasteAsQuotation(nsIClipboard::kGlobalClipboard);
-
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-PasteQuotationCommand::GetCommandStateParams(const char* aCommandName,
- nsICommandParams* aParams,
- nsISupports* aCommandRefCon)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
- if (editor) {
- bool enabled = false;
- editor->CanPaste(nsIClipboard::kGlobalClipboard, &enabled);
- aParams->SetBooleanValue(STATE_ENABLED, enabled);
- }
-
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/EditorCommands.h b/editor/libeditor/EditorCommands.h
deleted file mode 100644
index d7dc27b94..000000000
--- a/editor/libeditor/EditorCommands.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef EditorCommands_h_
-#define EditorCommands_h_
-
-#include "nsIControllerCommand.h"
-#include "nsISupportsImpl.h"
-#include "nscore.h"
-
-class nsICommandParams;
-class nsISupports;
-
-namespace mozilla {
-
-/**
- * This is a virtual base class for commands registered with the editor
- * controller. Note that such commands can be shared by more than on editor
- * instance, so MUST be stateless. Any state must be stored via the refCon
- * (an nsIEditor).
- */
-
-class EditorCommandBase : public nsIControllerCommand
-{
-public:
- EditorCommandBase();
-
- NS_DECL_ISUPPORTS
-
- NS_IMETHOD IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled) override = 0;
- NS_IMETHOD DoCommand(const char* aCommandName,
- nsISupports* aCommandRefCon) override = 0;
-
-protected:
- virtual ~EditorCommandBase() {}
-};
-
-
-#define NS_DECL_EDITOR_COMMAND(_cmd) \
-class _cmd final : public EditorCommandBase \
-{ \
-public: \
- NS_IMETHOD IsCommandEnabled(const char* aCommandName, \
- nsISupports* aCommandRefCon, \
- bool* aIsEnabled) override; \
- NS_IMETHOD DoCommand(const char* aCommandName, \
- nsISupports* aCommandRefCon) override; \
- NS_IMETHOD DoCommandParams(const char* aCommandName, \
- nsICommandParams* aParams, \
- nsISupports* aCommandRefCon) override; \
- NS_IMETHOD GetCommandStateParams(const char* aCommandName, \
- nsICommandParams* aParams, \
- nsISupports* aCommandRefCon) override; \
-};
-
-// basic editor commands
-NS_DECL_EDITOR_COMMAND(UndoCommand)
-NS_DECL_EDITOR_COMMAND(RedoCommand)
-NS_DECL_EDITOR_COMMAND(ClearUndoCommand)
-
-NS_DECL_EDITOR_COMMAND(CutCommand)
-NS_DECL_EDITOR_COMMAND(CutOrDeleteCommand)
-NS_DECL_EDITOR_COMMAND(CopyCommand)
-NS_DECL_EDITOR_COMMAND(CopyOrDeleteCommand)
-NS_DECL_EDITOR_COMMAND(CopyAndCollapseToEndCommand)
-NS_DECL_EDITOR_COMMAND(PasteCommand)
-NS_DECL_EDITOR_COMMAND(PasteTransferableCommand)
-NS_DECL_EDITOR_COMMAND(SwitchTextDirectionCommand)
-NS_DECL_EDITOR_COMMAND(DeleteCommand)
-NS_DECL_EDITOR_COMMAND(SelectAllCommand)
-
-NS_DECL_EDITOR_COMMAND(SelectionMoveCommands)
-
-// Insert content commands
-NS_DECL_EDITOR_COMMAND(InsertPlaintextCommand)
-NS_DECL_EDITOR_COMMAND(InsertParagraphCommand)
-NS_DECL_EDITOR_COMMAND(InsertLineBreakCommand)
-NS_DECL_EDITOR_COMMAND(PasteQuotationCommand)
-
-
-#if 0
-// template for new command
-NS_IMETHODIMP
-FooCommand::IsCommandEnabled(const char* aCommandName,
- nsISupports* aCommandRefCon,
- bool* aIsEnabled)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-FooCommand::DoCommand(const char* aCommandName,
- const nsAString& aCommandParams,
- nsISupports* aCommandRefCon)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-#endif
-
-} // namespace mozilla
-
-#endif // #ifndef EditorCommands_h_
diff --git a/editor/libeditor/EditorController.cpp b/editor/libeditor/EditorController.cpp
deleted file mode 100644
index b9e499978..000000000
--- a/editor/libeditor/EditorController.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/EditorController.h"
-
-#include "EditorCommands.h"
-#include "mozilla/mozalloc.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsIControllerCommandTable.h"
-
-class nsIControllerCommand;
-
-namespace mozilla {
-
-#define NS_REGISTER_ONE_COMMAND(_cmdClass, _cmdName) \
- { \
- _cmdClass* theCmd = new _cmdClass(); \
- NS_ENSURE_TRUE(theCmd, NS_ERROR_OUT_OF_MEMORY); \
- aCommandTable->RegisterCommand( \
- _cmdName, \
- static_cast<nsIControllerCommand *>(theCmd)); \
- }
-
-#define NS_REGISTER_FIRST_COMMAND(_cmdClass, _cmdName) \
- { \
- _cmdClass* theCmd = new _cmdClass(); \
- NS_ENSURE_TRUE(theCmd, NS_ERROR_OUT_OF_MEMORY); \
- aCommandTable->RegisterCommand( \
- _cmdName, \
- static_cast<nsIControllerCommand *>(theCmd));
-
-#define NS_REGISTER_NEXT_COMMAND(_cmdClass, _cmdName) \
- aCommandTable->RegisterCommand( \
- _cmdName, \
- static_cast<nsIControllerCommand *>(theCmd));
-
-#define NS_REGISTER_LAST_COMMAND(_cmdClass, _cmdName) \
- aCommandTable->RegisterCommand( \
- _cmdName, \
- static_cast<nsIControllerCommand *>(theCmd)); \
- }
-
-// static
-nsresult
-EditorController::RegisterEditingCommands(
- nsIControllerCommandTable* aCommandTable)
-{
- // now register all our commands
- // These are commands that will be used in text widgets, and in composer
-
- NS_REGISTER_ONE_COMMAND(UndoCommand, "cmd_undo");
- NS_REGISTER_ONE_COMMAND(RedoCommand, "cmd_redo");
- NS_REGISTER_ONE_COMMAND(ClearUndoCommand, "cmd_clearUndo");
-
- NS_REGISTER_ONE_COMMAND(CutCommand, "cmd_cut");
- NS_REGISTER_ONE_COMMAND(CutOrDeleteCommand, "cmd_cutOrDelete");
- NS_REGISTER_ONE_COMMAND(CopyCommand, "cmd_copy");
- NS_REGISTER_ONE_COMMAND(CopyOrDeleteCommand, "cmd_copyOrDelete");
- NS_REGISTER_ONE_COMMAND(CopyAndCollapseToEndCommand,
- "cmd_copyAndCollapseToEnd");
- NS_REGISTER_ONE_COMMAND(SelectAllCommand, "cmd_selectAll");
-
- NS_REGISTER_ONE_COMMAND(PasteCommand, "cmd_paste");
- NS_REGISTER_ONE_COMMAND(PasteTransferableCommand, "cmd_pasteTransferable");
-
- NS_REGISTER_ONE_COMMAND(SwitchTextDirectionCommand,
- "cmd_switchTextDirection");
-
- NS_REGISTER_FIRST_COMMAND(DeleteCommand, "cmd_delete");
- NS_REGISTER_NEXT_COMMAND(DeleteCommand, "cmd_deleteCharBackward");
- NS_REGISTER_NEXT_COMMAND(DeleteCommand, "cmd_deleteCharForward");
- NS_REGISTER_NEXT_COMMAND(DeleteCommand, "cmd_deleteWordBackward");
- NS_REGISTER_NEXT_COMMAND(DeleteCommand, "cmd_deleteWordForward");
- NS_REGISTER_NEXT_COMMAND(DeleteCommand, "cmd_deleteToBeginningOfLine");
- NS_REGISTER_LAST_COMMAND(DeleteCommand, "cmd_deleteToEndOfLine");
-
- // Insert content
- NS_REGISTER_ONE_COMMAND(InsertPlaintextCommand, "cmd_insertText");
- NS_REGISTER_ONE_COMMAND(InsertParagraphCommand, "cmd_insertParagraph");
- NS_REGISTER_ONE_COMMAND(InsertLineBreakCommand, "cmd_insertLineBreak");
- NS_REGISTER_ONE_COMMAND(PasteQuotationCommand, "cmd_pasteQuote");
-
- return NS_OK;
-}
-
-// static
-nsresult
-EditorController::RegisterEditorCommands(
- nsIControllerCommandTable* aCommandTable)
-{
- // These are commands that will be used in text widgets only.
-
- NS_REGISTER_FIRST_COMMAND(SelectionMoveCommands, "cmd_scrollTop");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_scrollBottom");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_moveTop");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_moveBottom");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectTop");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectBottom");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_lineNext");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_linePrevious");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectLineNext");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectLinePrevious");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_charPrevious");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_charNext");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectCharPrevious");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectCharNext");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_beginLine");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_endLine");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectBeginLine");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectEndLine");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_wordPrevious");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_wordNext");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectWordPrevious");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectWordNext");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_scrollPageUp");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_scrollPageDown");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_scrollLineUp");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_scrollLineDown");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_movePageUp");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_movePageDown");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectPageUp");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectPageDown");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_moveLeft");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_moveRight");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_moveUp");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_moveDown");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_moveLeft2");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_moveRight2");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_moveUp2");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_moveDown2");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectLeft");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectRight");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectUp");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectDown");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectLeft2");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectRight2");
- NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectUp2");
- NS_REGISTER_LAST_COMMAND(SelectionMoveCommands, "cmd_selectDown2");
-
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/EditorController.h b/editor/libeditor/EditorController.h
deleted file mode 100644
index e9fb654b8..000000000
--- a/editor/libeditor/EditorController.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_EditorController_h
-#define mozilla_EditorController_h
-
-#include "nscore.h"
-
-#define NS_EDITORCONTROLLER_CID \
-{ 0x26fb965c, 0x9de6, 0x11d3, \
- { 0xbc, 0xcc, 0x0, 0x60, 0xb0, 0xfc, 0x76, 0xbd } }
-
-#define NS_EDITINGCONTROLLER_CID \
-{ 0x2c5a5cdd, 0xe742, 0x4dfe, \
- { 0x86, 0xb8, 0x06, 0x93, 0x09, 0xbf, 0x6c, 0x91 } }
-
-class nsIControllerCommandTable;
-
-namespace mozilla {
-
-// the editor controller is used for both text widgets, and basic text editing
-// commands in composer. The refCon that gets passed to its commands is an nsIEditor.
-
-class EditorController final
-{
-public:
- static nsresult RegisterEditorCommands(
- nsIControllerCommandTable* aCommandTable);
- static nsresult RegisterEditingCommands(
- nsIControllerCommandTable* aCommandTable);
-};
-
-} // namespace mozilla
-
-#endif // #ifndef mozilla_EditorController_h
diff --git a/editor/libeditor/EditorEventListener.cpp b/editor/libeditor/EditorEventListener.cpp
deleted file mode 100644
index 1a3beca6e..000000000
--- a/editor/libeditor/EditorEventListener.cpp
+++ /dev/null
@@ -1,1279 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "EditorEventListener.h"
-
-#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc.
-#include "mozilla/EditorBase.h" // for EditorBase, etc.
-#include "mozilla/EventListenerManager.h" // for EventListenerManager
-#include "mozilla/IMEStateManager.h" // for IMEStateManager
-#include "mozilla/Preferences.h" // for Preferences
-#include "mozilla/TextEvents.h" // for WidgetCompositionEvent
-#include "mozilla/dom/Element.h" // for Element
-#include "mozilla/dom/Event.h" // for Event
-#include "mozilla/dom/EventTarget.h" // for EventTarget
-#include "mozilla/dom/Selection.h"
-#include "nsAString.h"
-#include "nsCaret.h" // for nsCaret
-#include "nsDebug.h" // for NS_ENSURE_TRUE, etc.
-#include "nsFocusManager.h" // for nsFocusManager
-#include "nsGkAtoms.h" // for nsGkAtoms, nsGkAtoms::input
-#include "nsIClipboard.h" // for nsIClipboard, etc.
-#include "nsIContent.h" // for nsIContent
-#include "nsIController.h" // for nsIController
-#include "nsID.h"
-#include "mozilla/dom/DOMStringList.h"
-#include "mozilla/dom/DataTransfer.h"
-#include "nsIDOMDocument.h" // for nsIDOMDocument
-#include "nsIDOMDragEvent.h" // for nsIDOMDragEvent
-#include "nsIDOMElement.h" // for nsIDOMElement
-#include "nsIDOMEvent.h" // for nsIDOMEvent
-#include "nsIDOMEventTarget.h" // for nsIDOMEventTarget
-#include "nsIDOMKeyEvent.h" // for nsIDOMKeyEvent
-#include "nsIDOMMouseEvent.h" // for nsIDOMMouseEvent
-#include "nsIDOMNode.h" // for nsIDOMNode
-#include "nsIDocument.h" // for nsIDocument
-#include "nsIEditor.h" // for EditorBase::GetSelection, etc.
-#include "nsIEditorIMESupport.h"
-#include "nsIEditorMailSupport.h" // for nsIEditorMailSupport
-#include "nsIFocusManager.h" // for nsIFocusManager
-#include "nsIFormControl.h" // for nsIFormControl, etc.
-#include "nsIHTMLEditor.h" // for nsIHTMLEditor
-#include "nsINode.h" // for nsINode, ::NODE_IS_EDITABLE, etc.
-#include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc.
-#include "nsIPresShell.h" // for nsIPresShell
-#include "nsISelectionController.h" // for nsISelectionController, etc.
-#include "nsITransferable.h" // for kFileMime, kHTMLMime, etc.
-#include "nsIWidget.h" // for nsIWidget
-#include "nsLiteralString.h" // for NS_LITERAL_STRING
-#include "nsPIWindowRoot.h" // for nsPIWindowRoot
-#include "nsPrintfCString.h" // for nsPrintfCString
-#include "nsRange.h"
-#include "nsServiceManagerUtils.h" // for do_GetService
-#include "nsString.h" // for nsAutoString
-#include "nsQueryObject.h" // for do_QueryObject
-#ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
-#include "nsContentUtils.h" // for nsContentUtils, etc.
-#include "nsIBidiKeyboard.h" // for nsIBidiKeyboard
-#endif
-
-#include "mozilla/dom/TabParent.h"
-
-class nsPresContext;
-
-namespace mozilla {
-
-using namespace dom;
-
-static void
-DoCommandCallback(Command aCommand, void* aData)
-{
- nsIDocument* doc = static_cast<nsIDocument*>(aData);
- nsPIDOMWindowOuter* win = doc->GetWindow();
- if (!win) {
- return;
- }
- nsCOMPtr<nsPIWindowRoot> root = win->GetTopWindowRoot();
- if (!root) {
- return;
- }
-
- const char* commandStr = WidgetKeyboardEvent::GetCommandStr(aCommand);
-
- nsCOMPtr<nsIController> controller;
- root->GetControllerForCommand(commandStr, getter_AddRefs(controller));
- if (!controller) {
- return;
- }
-
- bool commandEnabled;
- nsresult rv = controller->IsCommandEnabled(commandStr, &commandEnabled);
- NS_ENSURE_SUCCESS_VOID(rv);
- if (commandEnabled) {
- controller->DoCommand(commandStr);
- }
-}
-
-EditorEventListener::EditorEventListener()
- : mEditorBase(nullptr)
- , mCommitText(false)
- , mInTransaction(false)
- , mMouseDownOrUpConsumedByIME(false)
-#ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
- , mHaveBidiKeyboards(false)
- , mShouldSwitchTextDirection(false)
- , mSwitchToRTL(false)
-#endif
-{
-}
-
-EditorEventListener::~EditorEventListener()
-{
- if (mEditorBase) {
- NS_WARNING("We're not uninstalled");
- Disconnect();
- }
-}
-
-nsresult
-EditorEventListener::Connect(EditorBase* aEditorBase)
-{
- NS_ENSURE_ARG(aEditorBase);
-
-#ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
- nsIBidiKeyboard* bidiKeyboard = nsContentUtils::GetBidiKeyboard();
- if (bidiKeyboard) {
- bool haveBidiKeyboards = false;
- bidiKeyboard->GetHaveBidiKeyboards(&haveBidiKeyboards);
- mHaveBidiKeyboards = haveBidiKeyboards;
- }
-#endif
-
- mEditorBase = aEditorBase;
-
- nsresult rv = InstallToEditor();
- if (NS_FAILED(rv)) {
- Disconnect();
- }
- return rv;
-}
-
-nsresult
-EditorEventListener::InstallToEditor()
-{
- NS_PRECONDITION(mEditorBase, "The caller must set mEditorBase");
-
- nsCOMPtr<EventTarget> piTarget = mEditorBase->GetDOMEventTarget();
- NS_ENSURE_TRUE(piTarget, NS_ERROR_FAILURE);
-
- // register the event listeners with the listener manager
- EventListenerManager* elmP = piTarget->GetOrCreateListenerManager();
- NS_ENSURE_STATE(elmP);
-
-#ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
- elmP->AddEventListenerByType(this,
- NS_LITERAL_STRING("keydown"),
- TrustedEventsAtSystemGroupBubble());
- elmP->AddEventListenerByType(this,
- NS_LITERAL_STRING("keyup"),
- TrustedEventsAtSystemGroupBubble());
-#endif
- elmP->AddEventListenerByType(this,
- NS_LITERAL_STRING("keypress"),
- TrustedEventsAtSystemGroupBubble());
- elmP->AddEventListenerByType(this,
- NS_LITERAL_STRING("dragenter"),
- TrustedEventsAtSystemGroupBubble());
- elmP->AddEventListenerByType(this,
- NS_LITERAL_STRING("dragover"),
- TrustedEventsAtSystemGroupBubble());
- elmP->AddEventListenerByType(this,
- NS_LITERAL_STRING("dragexit"),
- TrustedEventsAtSystemGroupBubble());
- elmP->AddEventListenerByType(this,
- NS_LITERAL_STRING("drop"),
- TrustedEventsAtSystemGroupBubble());
- // XXX We should add the mouse event listeners as system event group.
- // E.g., web applications cannot prevent middle mouse paste by
- // preventDefault() of click event at bubble phase.
- // However, if we do so, all click handlers in any frames and frontend
- // code need to check if it's editable. It makes easier create new bugs.
- elmP->AddEventListenerByType(this,
- NS_LITERAL_STRING("mousedown"),
- TrustedEventsAtCapture());
- elmP->AddEventListenerByType(this,
- NS_LITERAL_STRING("mouseup"),
- TrustedEventsAtCapture());
- elmP->AddEventListenerByType(this,
- NS_LITERAL_STRING("click"),
- TrustedEventsAtCapture());
-// Focus event doesn't bubble so adding the listener to capturing phase.
-// Make sure this works after bug 235441 gets fixed.
- elmP->AddEventListenerByType(this,
- NS_LITERAL_STRING("blur"),
- TrustedEventsAtCapture());
- elmP->AddEventListenerByType(this,
- NS_LITERAL_STRING("focus"),
- TrustedEventsAtCapture());
- elmP->AddEventListenerByType(this,
- NS_LITERAL_STRING("text"),
- TrustedEventsAtSystemGroupBubble());
- elmP->AddEventListenerByType(this,
- NS_LITERAL_STRING("compositionstart"),
- TrustedEventsAtSystemGroupBubble());
- elmP->AddEventListenerByType(this,
- NS_LITERAL_STRING("compositionend"),
- TrustedEventsAtSystemGroupBubble());
-
- return NS_OK;
-}
-
-void
-EditorEventListener::Disconnect()
-{
- if (DetachedFromEditor()) {
- return;
- }
- UninstallFromEditor();
-
- nsIFocusManager* fm = nsFocusManager::GetFocusManager();
- if (fm) {
- nsCOMPtr<nsIDOMElement> domFocus;
- fm->GetFocusedElement(getter_AddRefs(domFocus));
- nsCOMPtr<nsINode> focusedElement = do_QueryInterface(domFocus);
- mozilla::dom::Element* root = mEditorBase->GetRoot();
- if (focusedElement && root &&
- nsContentUtils::ContentIsDescendantOf(focusedElement, root)) {
- // Reset the Selection ancestor limiter and SelectionController state
- // that EditorBase::InitializeSelection set up.
- mEditorBase->FinalizeSelection();
- }
- }
-
- mEditorBase = nullptr;
-}
-
-void
-EditorEventListener::UninstallFromEditor()
-{
- nsCOMPtr<EventTarget> piTarget = mEditorBase->GetDOMEventTarget();
- if (!piTarget) {
- return;
- }
-
- EventListenerManager* elmP = piTarget->GetOrCreateListenerManager();
- if (!elmP) {
- return;
- }
-
-#ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
- elmP->RemoveEventListenerByType(this,
- NS_LITERAL_STRING("keydown"),
- TrustedEventsAtSystemGroupBubble());
- elmP->RemoveEventListenerByType(this,
- NS_LITERAL_STRING("keyup"),
- TrustedEventsAtSystemGroupBubble());
-#endif
- elmP->RemoveEventListenerByType(this,
- NS_LITERAL_STRING("keypress"),
- TrustedEventsAtSystemGroupBubble());
- elmP->RemoveEventListenerByType(this,
- NS_LITERAL_STRING("dragenter"),
- TrustedEventsAtSystemGroupBubble());
- elmP->RemoveEventListenerByType(this,
- NS_LITERAL_STRING("dragover"),
- TrustedEventsAtSystemGroupBubble());
- elmP->RemoveEventListenerByType(this,
- NS_LITERAL_STRING("dragexit"),
- TrustedEventsAtSystemGroupBubble());
- elmP->RemoveEventListenerByType(this,
- NS_LITERAL_STRING("drop"),
- TrustedEventsAtSystemGroupBubble());
- elmP->RemoveEventListenerByType(this,
- NS_LITERAL_STRING("mousedown"),
- TrustedEventsAtCapture());
- elmP->RemoveEventListenerByType(this,
- NS_LITERAL_STRING("mouseup"),
- TrustedEventsAtCapture());
- elmP->RemoveEventListenerByType(this,
- NS_LITERAL_STRING("click"),
- TrustedEventsAtCapture());
- elmP->RemoveEventListenerByType(this,
- NS_LITERAL_STRING("blur"),
- TrustedEventsAtCapture());
- elmP->RemoveEventListenerByType(this,
- NS_LITERAL_STRING("focus"),
- TrustedEventsAtCapture());
- elmP->RemoveEventListenerByType(this,
- NS_LITERAL_STRING("text"),
- TrustedEventsAtSystemGroupBubble());
- elmP->RemoveEventListenerByType(this,
- NS_LITERAL_STRING("compositionstart"),
- TrustedEventsAtSystemGroupBubble());
- elmP->RemoveEventListenerByType(this,
- NS_LITERAL_STRING("compositionend"),
- TrustedEventsAtSystemGroupBubble());
-}
-
-already_AddRefed<nsIPresShell>
-EditorEventListener::GetPresShell()
-{
- MOZ_ASSERT(!DetachedFromEditor());
- return mEditorBase->GetPresShell();
-}
-
-nsPresContext*
-EditorEventListener::GetPresContext()
-{
- nsCOMPtr<nsIPresShell> presShell = GetPresShell();
- return presShell ? presShell->GetPresContext() : nullptr;
-}
-
-nsIContent*
-EditorEventListener::GetFocusedRootContent()
-{
- MOZ_ASSERT(!DetachedFromEditor());
- nsCOMPtr<nsIContent> focusedContent = mEditorBase->GetFocusedContent();
- if (!focusedContent) {
- return nullptr;
- }
-
- nsIDocument* composedDoc = focusedContent->GetComposedDoc();
- NS_ENSURE_TRUE(composedDoc, nullptr);
-
- if (composedDoc->HasFlag(NODE_IS_EDITABLE)) {
- return nullptr;
- }
-
- return focusedContent;
-}
-
-bool
-EditorEventListener::EditorHasFocus()
-{
- MOZ_ASSERT(!DetachedFromEditor());
- nsCOMPtr<nsIContent> focusedContent = mEditorBase->GetFocusedContent();
- if (!focusedContent) {
- return false;
- }
- nsIDocument* composedDoc = focusedContent->GetComposedDoc();
- return !!composedDoc;
-}
-
-NS_IMPL_ISUPPORTS(EditorEventListener, nsIDOMEventListener)
-
-bool
-EditorEventListener::DetachedFromEditor() const
-{
- return !mEditorBase;
-}
-
-bool
-EditorEventListener::DetachedFromEditorOrDefaultPrevented(
- WidgetEvent* aWidgetEvent) const
-{
- return NS_WARN_IF(!aWidgetEvent) || DetachedFromEditor() ||
- aWidgetEvent->DefaultPrevented();
-}
-
-NS_IMETHODIMP
-EditorEventListener::HandleEvent(nsIDOMEvent* aEvent)
-{
- // Let's handle each event with the message of the internal event of the
- // coming event. If the DOM event was created with improper interface,
- // e.g., keydown event is created with |new MouseEvent("keydown", {});|,
- // its message is always 0. Therefore, we can ban such strange event easy.
- // However, we need to handle strange "focus" and "blur" event. See the
- // following code of this switch statement.
- // NOTE: Each event handler may require specific event interface. Before
- // calling it, this queries the specific interface. If it would fail,
- // each event handler would just ignore the event. So, in this method,
- // you don't need to check if the QI succeeded before each call.
- WidgetEvent* internalEvent = aEvent->WidgetEventPtr();
- switch (internalEvent->mMessage) {
- // dragenter
- case eDragEnter: {
- nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent);
- return DragEnter(dragEvent);
- }
- // dragover
- case eDragOver: {
- nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent);
- return DragOver(dragEvent);
- }
- // dragexit
- case eDragExit: {
- nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent);
- return DragExit(dragEvent);
- }
- // drop
- case eDrop: {
- nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent);
- return Drop(dragEvent);
- }
-#ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
- // keydown
- case eKeyDown: {
- nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aEvent);
- return KeyDown(keyEvent);
- }
- // keyup
- case eKeyUp: {
- nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aEvent);
- return KeyUp(keyEvent);
- }
-#endif // #ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
- // keypress
- case eKeyPress: {
- nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aEvent);
- return KeyPress(keyEvent);
- }
- // mousedown
- case eMouseDown: {
- nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aEvent);
- NS_ENSURE_TRUE(mouseEvent, NS_OK);
- // EditorEventListener may receive (1) all mousedown, mouseup and click
- // events, (2) only mousedown event or (3) only mouseup event.
- // mMouseDownOrUpConsumedByIME is used only for ignoring click event if
- // preceding mousedown and/or mouseup event is consumed by IME.
- // Therefore, even if case #2 or case #3 occurs,
- // mMouseDownOrUpConsumedByIME is true here. Therefore, we should always
- // overwrite it here.
- mMouseDownOrUpConsumedByIME = NotifyIMEOfMouseButtonEvent(mouseEvent);
- return mMouseDownOrUpConsumedByIME ? NS_OK : MouseDown(mouseEvent);
- }
- // mouseup
- case eMouseUp: {
- nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aEvent);
- NS_ENSURE_TRUE(mouseEvent, NS_OK);
- // See above comment in the eMouseDown case, first.
- // This code assumes that case #1 is occuring. However, if case #3 may
- // occurs after case #2 and the mousedown is consumed,
- // mMouseDownOrUpConsumedByIME is true even though EditorEventListener
- // has not received the preceding mousedown event of this mouseup event.
- // So, mMouseDownOrUpConsumedByIME may be invalid here. However,
- // this is not a matter because mMouseDownOrUpConsumedByIME is referred
- // only by eMouseClick case but click event is fired only in case #1.
- // So, before a click event is fired, mMouseDownOrUpConsumedByIME is
- // always initialized in the eMouseDown case if it's referred.
- if (NotifyIMEOfMouseButtonEvent(mouseEvent)) {
- mMouseDownOrUpConsumedByIME = true;
- }
- return mMouseDownOrUpConsumedByIME ? NS_OK : MouseUp(mouseEvent);
- }
- // click
- case eMouseClick: {
- nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aEvent);
- NS_ENSURE_TRUE(mouseEvent, NS_OK);
- // If the preceding mousedown event or mouseup event was consumed,
- // editor shouldn't handle this click event.
- if (mMouseDownOrUpConsumedByIME) {
- mMouseDownOrUpConsumedByIME = false;
- mouseEvent->AsEvent()->PreventDefault();
- return NS_OK;
- }
- return MouseClick(mouseEvent);
- }
- // focus
- case eFocus:
- return Focus(internalEvent);
- // blur
- case eBlur:
- return Blur(internalEvent);
- // text
- case eCompositionChange:
- return HandleChangeComposition(internalEvent->AsCompositionEvent());
- // compositionstart
- case eCompositionStart:
- return HandleStartComposition(internalEvent->AsCompositionEvent());
- // compositionend
- case eCompositionEnd:
- HandleEndComposition(internalEvent->AsCompositionEvent());
- return NS_OK;
- default:
- break;
- }
-
- nsAutoString eventType;
- aEvent->GetType(eventType);
- // We should accept "focus" and "blur" event even if it's synthesized with
- // wrong interface for compatibility with older Gecko.
- if (eventType.EqualsLiteral("focus")) {
- return Focus(internalEvent);
- }
- if (eventType.EqualsLiteral("blur")) {
- return Blur(internalEvent);
- }
-#ifdef DEBUG
- nsPrintfCString assertMessage("Editor doesn't handle \"%s\" event "
- "because its internal event doesn't have proper message",
- NS_ConvertUTF16toUTF8(eventType).get());
- NS_ASSERTION(false, assertMessage.get());
-#endif
-
- return NS_OK;
-}
-
-#ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
-namespace {
-
-// This function is borrowed from Chromium's ImeInput::IsCtrlShiftPressed
-bool IsCtrlShiftPressed(nsIDOMKeyEvent* aEvent, bool& isRTL)
-{
- // To check if a user is pressing only a control key and a right-shift key
- // (or a left-shift key), we use the steps below:
- // 1. Check if a user is pressing a control key and a right-shift key (or
- // a left-shift key).
- // 2. If the condition 1 is true, we should check if there are any other
- // keys pressed at the same time.
- // To ignore the keys checked in 1, we set their status to 0 before
- // checking the key status.
- WidgetKeyboardEvent* keyboardEvent =
- aEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
- MOZ_ASSERT(keyboardEvent,
- "DOM key event's internal event must be WidgetKeyboardEvent");
-
- if (!keyboardEvent->IsControl()) {
- return false;
- }
-
- uint32_t location = keyboardEvent->mLocation;
- if (location == nsIDOMKeyEvent::DOM_KEY_LOCATION_RIGHT) {
- isRTL = true;
- } else if (location == nsIDOMKeyEvent::DOM_KEY_LOCATION_LEFT) {
- isRTL = false;
- } else {
- return false;
- }
-
- // Scan the key status to find pressed keys. We should abandon changing the
- // text direction when there are other pressed keys.
- if (keyboardEvent->IsAlt() || keyboardEvent->IsOS()) {
- return false;
- }
-
- return true;
-}
-
-}
-
-// This logic is mostly borrowed from Chromium's
-// RenderWidgetHostViewWin::OnKeyEvent.
-
-nsresult
-EditorEventListener::KeyUp(nsIDOMKeyEvent* aKeyEvent)
-{
- if (NS_WARN_IF(!aKeyEvent) || DetachedFromEditor()) {
- return NS_OK;
- }
-
- if (!mHaveBidiKeyboards) {
- return NS_OK;
- }
-
- // XXX Why doesn't this method check if it's consumed?
- RefPtr<EditorBase> editorBase(mEditorBase);
- uint32_t keyCode = 0;
- aKeyEvent->GetKeyCode(&keyCode);
- if ((keyCode == nsIDOMKeyEvent::DOM_VK_SHIFT ||
- keyCode == nsIDOMKeyEvent::DOM_VK_CONTROL) &&
- mShouldSwitchTextDirection && editorBase->IsPlaintextEditor()) {
- editorBase->SwitchTextDirectionTo(mSwitchToRTL ?
- nsIPlaintextEditor::eEditorRightToLeft :
- nsIPlaintextEditor::eEditorLeftToRight);
- mShouldSwitchTextDirection = false;
- }
- return NS_OK;
-}
-
-nsresult
-EditorEventListener::KeyDown(nsIDOMKeyEvent* aKeyEvent)
-{
- if (NS_WARN_IF(!aKeyEvent) || DetachedFromEditor()) {
- return NS_OK;
- }
-
- if (!mHaveBidiKeyboards) {
- return NS_OK;
- }
-
- // XXX Why isn't this method check if it's consumed?
- uint32_t keyCode = 0;
- aKeyEvent->GetKeyCode(&keyCode);
- if (keyCode == nsIDOMKeyEvent::DOM_VK_SHIFT) {
- bool switchToRTL;
- if (IsCtrlShiftPressed(aKeyEvent, switchToRTL)) {
- mShouldSwitchTextDirection = true;
- mSwitchToRTL = switchToRTL;
- }
- } else if (keyCode != nsIDOMKeyEvent::DOM_VK_CONTROL) {
- // In case the user presses any other key besides Ctrl and Shift
- mShouldSwitchTextDirection = false;
- }
- return NS_OK;
-}
-#endif
-
-nsresult
-EditorEventListener::KeyPress(nsIDOMKeyEvent* aKeyEvent)
-{
- if (NS_WARN_IF(!aKeyEvent)) {
- return NS_OK;
- }
-
- RefPtr<EditorBase> editorBase(mEditorBase);
- WidgetKeyboardEvent* keypressEvent =
- aKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
- MOZ_ASSERT(keypressEvent,
- "DOM key event's internal event must be WidgetKeyboardEvent");
- if (!editorBase->IsAcceptableInputEvent(keypressEvent) ||
- DetachedFromEditorOrDefaultPrevented(keypressEvent)) {
- return NS_OK;
- }
-
- nsresult rv = editorBase->HandleKeyPressEvent(aKeyEvent);
- NS_ENSURE_SUCCESS(rv, rv);
- if (DetachedFromEditorOrDefaultPrevented(keypressEvent)) {
- return NS_OK;
- }
-
- if (!ShouldHandleNativeKeyBindings(aKeyEvent)) {
- return NS_OK;
- }
-
- // Now, ask the native key bindings to handle the event.
- nsIWidget* widget = keypressEvent->mWidget;
- // If the event is created by chrome script, the widget is always nullptr.
- if (!widget) {
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
- nsPresContext* pc = ps ? ps->GetPresContext() : nullptr;
- widget = pc ? pc->GetNearestWidget() : nullptr;
- NS_ENSURE_TRUE(widget, NS_OK);
- }
-
- nsCOMPtr<nsIDocument> doc = editorBase->GetDocument();
- bool handled = widget->ExecuteNativeKeyBinding(
- nsIWidget::NativeKeyBindingsForRichTextEditor,
- *keypressEvent, DoCommandCallback, doc);
- if (handled) {
- aKeyEvent->AsEvent()->PreventDefault();
- }
- return NS_OK;
-}
-
-nsresult
-EditorEventListener::MouseClick(nsIDOMMouseEvent* aMouseEvent)
-{
- if (NS_WARN_IF(!aMouseEvent) || DetachedFromEditor()) {
- return NS_OK;
- }
- // nothing to do if editor isn't editable or clicked on out of the editor.
- RefPtr<EditorBase> editorBase(mEditorBase);
- WidgetMouseEvent* clickEvent =
- aMouseEvent->AsEvent()->WidgetEventPtr()->AsMouseEvent();
- if (editorBase->IsReadonly() || editorBase->IsDisabled() ||
- !editorBase->IsAcceptableInputEvent(clickEvent)) {
- return NS_OK;
- }
-
- // Notifies clicking on editor to IMEStateManager even when the event was
- // consumed.
- if (EditorHasFocus()) {
- nsPresContext* presContext = GetPresContext();
- if (presContext) {
- IMEStateManager::OnClickInEditor(presContext, GetFocusedRootContent(),
- aMouseEvent);
- if (DetachedFromEditor()) {
- return NS_OK;
- }
- }
- }
-
- if (DetachedFromEditorOrDefaultPrevented(clickEvent)) {
- // We're done if 'preventdefault' is true (see for example bug 70698).
- return NS_OK;
- }
-
- // If we got a mouse down inside the editing area, we should force the
- // IME to commit before we change the cursor position
- editorBase->ForceCompositionEnd();
- if (DetachedFromEditor()) {
- return NS_OK;
- }
-
- int16_t button = -1;
- aMouseEvent->GetButton(&button);
- if (button == 1) {
- return HandleMiddleClickPaste(aMouseEvent);
- }
- return NS_OK;
-}
-
-nsresult
-EditorEventListener::HandleMiddleClickPaste(nsIDOMMouseEvent* aMouseEvent)
-{
- MOZ_ASSERT(aMouseEvent);
- MOZ_ASSERT(!DetachedFromEditorOrDefaultPrevented(
- aMouseEvent->AsEvent()->WidgetEventPtr()));
-
- if (!Preferences::GetBool("middlemouse.paste", false)) {
- // Middle click paste isn't enabled.
- return NS_OK;
- }
-
- // Set the selection to the point under the mouse cursor:
- nsCOMPtr<nsIDOMNode> parent;
- if (NS_FAILED(aMouseEvent->GetRangeParent(getter_AddRefs(parent)))) {
- return NS_ERROR_NULL_POINTER;
- }
- int32_t offset = 0;
- if (NS_FAILED(aMouseEvent->GetRangeOffset(&offset))) {
- return NS_ERROR_NULL_POINTER;
- }
-
- RefPtr<EditorBase> editorBase(mEditorBase);
- RefPtr<Selection> selection = editorBase->GetSelection();
- if (selection) {
- selection->Collapse(parent, offset);
- }
-
- // If the ctrl key is pressed, we'll do paste as quotation.
- // Would've used the alt key, but the kde wmgr treats alt-middle specially.
- bool ctrlKey = false;
- aMouseEvent->GetCtrlKey(&ctrlKey);
-
- nsCOMPtr<nsIEditorMailSupport> mailEditor;
- if (ctrlKey) {
- mailEditor = do_QueryObject(editorBase);
- }
-
- nsresult rv;
- int32_t clipboard = nsIClipboard::kGlobalClipboard;
- nsCOMPtr<nsIClipboard> clipboardService =
- do_GetService("@mozilla.org/widget/clipboard;1", &rv);
- if (NS_SUCCEEDED(rv)) {
- bool selectionSupported;
- rv = clipboardService->SupportsSelectionClipboard(&selectionSupported);
- if (NS_SUCCEEDED(rv) && selectionSupported) {
- clipboard = nsIClipboard::kSelectionClipboard;
- }
- }
-
- if (mailEditor) {
- mailEditor->PasteAsQuotation(clipboard);
- } else {
- editorBase->Paste(clipboard);
- }
-
- // Prevent the event from propagating up to be possibly handled
- // again by the containing window:
- aMouseEvent->AsEvent()->StopPropagation();
- aMouseEvent->AsEvent()->PreventDefault();
-
- // We processed the event, whether drop/paste succeeded or not
- return NS_OK;
-}
-
-bool
-EditorEventListener::NotifyIMEOfMouseButtonEvent(
- nsIDOMMouseEvent* aMouseEvent)
-{
- MOZ_ASSERT(aMouseEvent);
-
- if (!EditorHasFocus()) {
- return false;
- }
-
- nsPresContext* presContext = GetPresContext();
- NS_ENSURE_TRUE(presContext, false);
- return IMEStateManager::OnMouseButtonEventInEditor(presContext,
- GetFocusedRootContent(),
- aMouseEvent);
-}
-
-nsresult
-EditorEventListener::MouseDown(nsIDOMMouseEvent* aMouseEvent)
-{
- // FYI: We don't need to check if it's already consumed here because
- // we need to commit composition at mouse button operation.
- // FYI: This may be called by HTMLEditorEventListener::MouseDown() even
- // when the event is not acceptable for committing composition.
- if (DetachedFromEditor()) {
- return NS_OK;
- }
- RefPtr<EditorBase> editorBase(mEditorBase);
- editorBase->ForceCompositionEnd();
- return NS_OK;
-}
-
-nsresult
-EditorEventListener::HandleChangeComposition(
- WidgetCompositionEvent* aCompositionChangeEvent)
-{
- MOZ_ASSERT(!aCompositionChangeEvent->DefaultPrevented(),
- "eCompositionChange event shouldn't be cancelable");
- RefPtr<EditorBase> editorBase(mEditorBase);
- if (DetachedFromEditor() ||
- !editorBase->IsAcceptableInputEvent(aCompositionChangeEvent)) {
- return NS_OK;
- }
-
- // if we are readonly or disabled, then do nothing.
- if (editorBase->IsReadonly() || editorBase->IsDisabled()) {
- return NS_OK;
- }
-
- return editorBase->UpdateIMEComposition(aCompositionChangeEvent);
-}
-
-/**
- * Drag event implementation
- */
-
-nsresult
-EditorEventListener::DragEnter(nsIDOMDragEvent* aDragEvent)
-{
- if (NS_WARN_IF(!aDragEvent) || DetachedFromEditor()) {
- return NS_OK;
- }
-
- nsCOMPtr<nsIPresShell> presShell = GetPresShell();
- NS_ENSURE_TRUE(presShell, NS_OK);
-
- if (!mCaret) {
- mCaret = new nsCaret();
- mCaret->Init(presShell);
- mCaret->SetCaretReadOnly(true);
- // This is to avoid the requirement that the Selection is Collapsed which
- // it can't be when dragging a selection in the same shell.
- // See nsCaret::IsVisible().
- mCaret->SetVisibilityDuringSelection(true);
- }
-
- presShell->SetCaret(mCaret);
-
- return DragOver(aDragEvent);
-}
-
-nsresult
-EditorEventListener::DragOver(nsIDOMDragEvent* aDragEvent)
-{
- if (NS_WARN_IF(!aDragEvent) ||
- DetachedFromEditorOrDefaultPrevented(
- aDragEvent->AsEvent()->WidgetEventPtr())) {
- return NS_OK;
- }
-
- nsCOMPtr<nsIDOMNode> parent;
- aDragEvent->GetRangeParent(getter_AddRefs(parent));
- nsCOMPtr<nsIContent> dropParent = do_QueryInterface(parent);
- NS_ENSURE_TRUE(dropParent, NS_ERROR_FAILURE);
-
- if (dropParent->IsEditable() && CanDrop(aDragEvent)) {
- aDragEvent->AsEvent()->PreventDefault(); // consumed
-
- if (!mCaret) {
- return NS_OK;
- }
-
- int32_t offset = 0;
- nsresult rv = aDragEvent->GetRangeOffset(&offset);
- NS_ENSURE_SUCCESS(rv, rv);
-
- mCaret->SetVisible(true);
- mCaret->SetCaretPosition(parent, offset);
-
- return NS_OK;
- }
-
- if (!IsFileControlTextBox()) {
- // This is needed when dropping on an input, to prevent the editor for
- // the editable parent from receiving the event.
- aDragEvent->AsEvent()->StopPropagation();
- }
-
- if (mCaret) {
- mCaret->SetVisible(false);
- }
- return NS_OK;
-}
-
-void
-EditorEventListener::CleanupDragDropCaret()
-{
- if (!mCaret) {
- return;
- }
-
- mCaret->SetVisible(false); // hide it, so that it turns off its timer
-
- nsCOMPtr<nsIPresShell> presShell = GetPresShell();
- if (presShell) {
- presShell->RestoreCaret();
- }
-
- mCaret->Terminate();
- mCaret = nullptr;
-}
-
-nsresult
-EditorEventListener::DragExit(nsIDOMDragEvent* aDragEvent)
-{
- // XXX If aDragEvent was created by chrome script, its defaultPrevented
- // may be true, though. We shouldn't handle such event but we don't
- // have a way to distinguish if coming event is created by chrome script.
- NS_WARNING_ASSERTION(
- !aDragEvent->AsEvent()->WidgetEventPtr()->DefaultPrevented(),
- "eDragExit shouldn't be cancelable");
- if (NS_WARN_IF(!aDragEvent) || DetachedFromEditor()) {
- return NS_OK;
- }
-
- CleanupDragDropCaret();
-
- return NS_OK;
-}
-
-nsresult
-EditorEventListener::Drop(nsIDOMDragEvent* aDragEvent)
-{
- CleanupDragDropCaret();
-
- if (NS_WARN_IF(!aDragEvent) ||
- DetachedFromEditorOrDefaultPrevented(
- aDragEvent->AsEvent()->WidgetEventPtr())) {
- return NS_OK;
- }
-
- nsCOMPtr<nsIDOMNode> parent;
- aDragEvent->GetRangeParent(getter_AddRefs(parent));
- nsCOMPtr<nsIContent> dropParent = do_QueryInterface(parent);
- NS_ENSURE_TRUE(dropParent, NS_ERROR_FAILURE);
-
- if (!dropParent->IsEditable() || !CanDrop(aDragEvent)) {
- // was it because we're read-only?
- RefPtr<EditorBase> editorBase(mEditorBase);
- if ((editorBase->IsReadonly() || editorBase->IsDisabled()) &&
- !IsFileControlTextBox()) {
- // it was decided to "eat" the event as this is the "least surprise"
- // since someone else handling it might be unintentional and the
- // user could probably re-drag to be not over the disabled/readonly
- // editfields if that is what is desired.
- return aDragEvent->AsEvent()->StopPropagation();
- }
- return NS_OK;
- }
-
- aDragEvent->AsEvent()->StopPropagation();
- aDragEvent->AsEvent()->PreventDefault();
- RefPtr<EditorBase> editorBase(mEditorBase);
- return editorBase->InsertFromDrop(aDragEvent->AsEvent());
-}
-
-bool
-EditorEventListener::CanDrop(nsIDOMDragEvent* aEvent)
-{
- MOZ_ASSERT(!DetachedFromEditorOrDefaultPrevented(
- aEvent->AsEvent()->WidgetEventPtr()));
-
- // if the target doc is read-only, we can't drop
- RefPtr<EditorBase> editorBase(mEditorBase);
- if (editorBase->IsReadonly() || editorBase->IsDisabled()) {
- return false;
- }
-
- nsCOMPtr<nsIDOMDataTransfer> domDataTransfer;
- aEvent->GetDataTransfer(getter_AddRefs(domDataTransfer));
- nsCOMPtr<DataTransfer> dataTransfer = do_QueryInterface(domDataTransfer);
- NS_ENSURE_TRUE(dataTransfer, false);
-
- nsTArray<nsString> types;
- dataTransfer->GetTypes(types, *nsContentUtils::GetSystemPrincipal());
-
- // Plaintext editors only support dropping text. Otherwise, HTML and files
- // can be dropped as well.
- if (!types.Contains(NS_LITERAL_STRING(kTextMime)) &&
- !types.Contains(NS_LITERAL_STRING(kMozTextInternal)) &&
- (editorBase->IsPlaintextEditor() ||
- (!types.Contains(NS_LITERAL_STRING(kHTMLMime)) &&
- !types.Contains(NS_LITERAL_STRING(kFileMime))))) {
- return false;
- }
-
- // If there is no source node, this is probably an external drag and the
- // drop is allowed. The later checks rely on checking if the drag target
- // is the same as the drag source.
- nsCOMPtr<nsIDOMNode> sourceNode;
- dataTransfer->GetMozSourceNode(getter_AddRefs(sourceNode));
- if (!sourceNode) {
- return true;
- }
-
- // There is a source node, so compare the source documents and this document.
- // Disallow drops on the same document.
-
- nsCOMPtr<nsIDOMDocument> domdoc = editorBase->GetDOMDocument();
- NS_ENSURE_TRUE(domdoc, false);
-
- nsCOMPtr<nsIDOMDocument> sourceDoc;
- nsresult rv = sourceNode->GetOwnerDocument(getter_AddRefs(sourceDoc));
- NS_ENSURE_SUCCESS(rv, false);
-
- // If the source and the dest are not same document, allow to drop it always.
- if (domdoc != sourceDoc) {
- return true;
- }
-
- // If the source node is a remote browser, treat this as coming from a
- // different document and allow the drop.
- nsCOMPtr<nsIContent> sourceContent = do_QueryInterface(sourceNode);
- TabParent* tp = TabParent::GetFrom(sourceContent);
- if (tp) {
- return true;
- }
-
- RefPtr<Selection> selection = editorBase->GetSelection();
- if (!selection) {
- return false;
- }
-
- // If selection is collapsed, allow to drop it always.
- if (selection->Collapsed()) {
- return true;
- }
-
- nsCOMPtr<nsIDOMNode> parent;
- rv = aEvent->GetRangeParent(getter_AddRefs(parent));
- if (NS_FAILED(rv) || !parent) {
- return false;
- }
-
- int32_t offset = 0;
- rv = aEvent->GetRangeOffset(&offset);
- NS_ENSURE_SUCCESS(rv, false);
-
- int32_t rangeCount;
- rv = selection->GetRangeCount(&rangeCount);
- NS_ENSURE_SUCCESS(rv, false);
-
- for (int32_t i = 0; i < rangeCount; i++) {
- RefPtr<nsRange> range = selection->GetRangeAt(i);
- if (!range) {
- // Don't bail yet, iterate through them all
- continue;
- }
-
- bool inRange = true;
- range->IsPointInRange(parent, offset, &inRange);
- if (inRange) {
- // Okay, now you can bail, we are over the orginal selection
- return false;
- }
- }
- return true;
-}
-
-nsresult
-EditorEventListener::HandleStartComposition(
- WidgetCompositionEvent* aCompositionStartEvent)
-{
- RefPtr<EditorBase> editorBase(mEditorBase);
- if (DetachedFromEditor() ||
- !editorBase->IsAcceptableInputEvent(aCompositionStartEvent)) {
- return NS_OK;
- }
- // Although, "compositionstart" should be cancelable, but currently,
- // eCompositionStart event coming from widget is not cancelable.
- MOZ_ASSERT(!aCompositionStartEvent->DefaultPrevented(),
- "eCompositionStart shouldn't be cancelable");
- return editorBase->BeginIMEComposition(aCompositionStartEvent);
-}
-
-void
-EditorEventListener::HandleEndComposition(
- WidgetCompositionEvent* aCompositionEndEvent)
-{
- RefPtr<EditorBase> editorBase(mEditorBase);
- if (DetachedFromEditor() ||
- !editorBase->IsAcceptableInputEvent(aCompositionEndEvent)) {
- return;
- }
- MOZ_ASSERT(!aCompositionEndEvent->DefaultPrevented(),
- "eCompositionEnd shouldn't be cancelable");
- editorBase->EndIMEComposition();
-}
-
-nsresult
-EditorEventListener::Focus(WidgetEvent* aFocusEvent)
-{
- if (NS_WARN_IF(!aFocusEvent) || DetachedFromEditor()) {
- return NS_OK;
- }
-
- // XXX If aFocusEvent was created by chrome script, its defaultPrevented
- // may be true, though. We shouldn't handle such event but we don't
- // have a way to distinguish if coming event is created by chrome script.
- NS_WARNING_ASSERTION(!aFocusEvent->DefaultPrevented(),
- "eFocus event shouldn't be cancelable");
-
- // Don't turn on selection and caret when the editor is disabled.
- RefPtr<EditorBase> editorBase(mEditorBase);
- if (editorBase->IsDisabled()) {
- return NS_OK;
- }
-
- // Spell check a textarea the first time that it is focused.
- SpellCheckIfNeeded();
- if (!editorBase) {
- // In e10s, this can cause us to flush notifications, which can destroy
- // the node we're about to focus.
- return NS_OK;
- }
-
- nsCOMPtr<nsIDOMEventTarget> target = aFocusEvent->GetDOMEventTarget();
- nsCOMPtr<nsINode> node = do_QueryInterface(target);
- NS_ENSURE_TRUE(node, NS_ERROR_UNEXPECTED);
-
- // If the target is a document node but it's not editable, we should ignore
- // it because actual focused element's event is going to come.
- if (node->IsNodeOfType(nsINode::eDOCUMENT) &&
- !node->HasFlag(NODE_IS_EDITABLE)) {
- return NS_OK;
- }
-
- if (node->IsNodeOfType(nsINode::eCONTENT)) {
- // XXX If the focus event target is a form control in contenteditable
- // element, perhaps, the parent HTML editor should do nothing by this
- // handler. However, FindSelectionRoot() returns the root element of the
- // contenteditable editor. So, the editableRoot value is invalid for
- // the plain text editor, and it will be set to the wrong limiter of
- // the selection. However, fortunately, actual bugs are not found yet.
- nsCOMPtr<nsIContent> editableRoot = editorBase->FindSelectionRoot(node);
-
- // make sure that the element is really focused in case an earlier
- // listener in the chain changed the focus.
- if (editableRoot) {
- nsIFocusManager* fm = nsFocusManager::GetFocusManager();
- NS_ENSURE_TRUE(fm, NS_OK);
-
- nsCOMPtr<nsIDOMElement> element;
- fm->GetFocusedElement(getter_AddRefs(element));
- if (!element) {
- return NS_OK;
- }
-
- nsCOMPtr<nsIDOMEventTarget> originalTarget =
- aFocusEvent->GetOriginalDOMEventTarget();
-
- nsCOMPtr<nsIContent> originalTargetAsContent =
- do_QueryInterface(originalTarget);
- nsCOMPtr<nsIContent> focusedElementAsContent =
- do_QueryInterface(element);
-
- if (!SameCOMIdentity(
- focusedElementAsContent->FindFirstNonChromeOnlyAccessContent(),
- originalTargetAsContent->FindFirstNonChromeOnlyAccessContent())) {
- return NS_OK;
- }
- }
- }
-
- editorBase->OnFocus(target);
- if (DetachedFromEditorOrDefaultPrevented(aFocusEvent)) {
- return NS_OK;
- }
-
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
- NS_ENSURE_TRUE(ps, NS_OK);
- nsCOMPtr<nsIContent> focusedContent = editorBase->GetFocusedContentForIME();
- IMEStateManager::OnFocusInEditor(ps->GetPresContext(), focusedContent,
- editorBase);
-
- return NS_OK;
-}
-
-nsresult
-EditorEventListener::Blur(WidgetEvent* aBlurEvent)
-{
- if (NS_WARN_IF(!aBlurEvent) || DetachedFromEditor()) {
- return NS_OK;
- }
-
- // XXX If aBlurEvent was created by chrome script, its defaultPrevented
- // may be true, though. We shouldn't handle such event but we don't
- // have a way to distinguish if coming event is created by chrome script.
- NS_WARNING_ASSERTION(!aBlurEvent->DefaultPrevented(),
- "eBlur event shouldn't be cancelable");
-
- // check if something else is focused. If another element is focused, then
- // we should not change the selection.
- nsIFocusManager* fm = nsFocusManager::GetFocusManager();
- NS_ENSURE_TRUE(fm, NS_OK);
-
- nsCOMPtr<nsIDOMElement> element;
- fm->GetFocusedElement(getter_AddRefs(element));
- if (!element) {
- RefPtr<EditorBase> editorBase(mEditorBase);
- editorBase->FinalizeSelection();
- }
- return NS_OK;
-}
-
-void
-EditorEventListener::SpellCheckIfNeeded()
-{
- MOZ_ASSERT(!DetachedFromEditor());
-
- // If the spell check skip flag is still enabled from creation time,
- // disable it because focused editors are allowed to spell check.
- RefPtr<EditorBase> editorBase(mEditorBase);
- uint32_t currentFlags = 0;
- editorBase->GetFlags(&currentFlags);
- if(currentFlags & nsIPlaintextEditor::eEditorSkipSpellCheck) {
- currentFlags ^= nsIPlaintextEditor::eEditorSkipSpellCheck;
- editorBase->SetFlags(currentFlags);
- }
-}
-
-bool
-EditorEventListener::IsFileControlTextBox()
-{
- MOZ_ASSERT(!DetachedFromEditor());
-
- RefPtr<EditorBase> editorBase(mEditorBase);
- Element* root = editorBase->GetRoot();
- if (!root || !root->ChromeOnlyAccess()) {
- return false;
- }
- nsIContent* parent = root->FindFirstNonChromeOnlyAccessContent();
- if (!parent || !parent->IsHTMLElement(nsGkAtoms::input)) {
- return false;
- }
- nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(parent);
- return formControl->GetType() == NS_FORM_INPUT_FILE;
-}
-
-bool
-EditorEventListener::ShouldHandleNativeKeyBindings(nsIDOMKeyEvent* aKeyEvent)
-{
- MOZ_ASSERT(!DetachedFromEditor());
-
- // Only return true if the target of the event is a desendant of the active
- // editing host in order to match the similar decision made in
- // nsXBLWindowKeyHandler.
- // Note that IsAcceptableInputEvent doesn't check for the active editing
- // host for keyboard events, otherwise this check would have been
- // unnecessary. IsAcceptableInputEvent currently makes a similar check for
- // mouse events.
-
- nsCOMPtr<nsIDOMEventTarget> target;
- aKeyEvent->AsEvent()->GetTarget(getter_AddRefs(target));
- nsCOMPtr<nsIContent> targetContent = do_QueryInterface(target);
- if (!targetContent) {
- return false;
- }
-
- RefPtr<EditorBase> editorBase(mEditorBase);
- nsCOMPtr<nsIHTMLEditor> htmlEditor =
- do_QueryInterface(static_cast<nsIEditor*>(editorBase));
- if (!htmlEditor) {
- return false;
- }
-
- nsCOMPtr<nsIDocument> doc = editorBase->GetDocument();
- if (doc->HasFlag(NODE_IS_EDITABLE)) {
- // Don't need to perform any checks in designMode documents.
- return true;
- }
-
- nsIContent* editingHost = htmlEditor->GetActiveEditingHost();
- if (!editingHost) {
- return false;
- }
-
- return nsContentUtils::ContentIsDescendantOf(targetContent, editingHost);
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/EditorEventListener.h b/editor/libeditor/EditorEventListener.h
deleted file mode 100644
index 7244ebea4..000000000
--- a/editor/libeditor/EditorEventListener.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef EditorEventListener_h
-#define EditorEventListener_h
-
-#include "mozilla/EventForwards.h"
-#include "nsCOMPtr.h"
-#include "nsError.h"
-#include "nsIDOMEventListener.h"
-#include "nsISupportsImpl.h"
-#include "nscore.h"
-
-class nsCaret;
-class nsIContent;
-class nsIDOMDragEvent;
-class nsIDOMEvent;
-class nsIDOMKeyEvent;
-class nsIDOMMouseEvent;
-class nsIPresShell;
-class nsPresContext;
-
-// X.h defines KeyPress
-#ifdef KeyPress
-#undef KeyPress
-#endif
-
-#ifdef XP_WIN
-// On Windows, we support switching the text direction by pressing Ctrl+Shift
-#define HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
-#endif
-
-namespace mozilla {
-
-class EditorBase;
-
-class EditorEventListener : public nsIDOMEventListener
-{
-public:
- EditorEventListener();
-
- virtual nsresult Connect(EditorBase* aEditorBase);
-
- void Disconnect();
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSIDOMEVENTLISTENER
-
- void SpellCheckIfNeeded();
-
-protected:
- virtual ~EditorEventListener();
-
- nsresult InstallToEditor();
- void UninstallFromEditor();
-
-#ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
- nsresult KeyDown(nsIDOMKeyEvent* aKeyEvent);
- nsresult KeyUp(nsIDOMKeyEvent* aKeyEvent);
-#endif
- nsresult KeyPress(nsIDOMKeyEvent* aKeyEvent);
- nsresult HandleChangeComposition(WidgetCompositionEvent* aCompositionEvent);
- nsresult HandleStartComposition(WidgetCompositionEvent* aCompositionEvent);
- void HandleEndComposition(WidgetCompositionEvent* aCompositionEvent);
- virtual nsresult MouseDown(nsIDOMMouseEvent* aMouseEvent);
- virtual nsresult MouseUp(nsIDOMMouseEvent* aMouseEvent) { return NS_OK; }
- virtual nsresult MouseClick(nsIDOMMouseEvent* aMouseEvent);
- nsresult Focus(WidgetEvent* aFocusEvent);
- nsresult Blur(WidgetEvent* aBlurEvent);
- nsresult DragEnter(nsIDOMDragEvent* aDragEvent);
- nsresult DragOver(nsIDOMDragEvent* aDragEvent);
- nsresult DragExit(nsIDOMDragEvent* aDragEvent);
- nsresult Drop(nsIDOMDragEvent* aDragEvent);
-
- bool CanDrop(nsIDOMDragEvent* aEvent);
- void CleanupDragDropCaret();
- already_AddRefed<nsIPresShell> GetPresShell();
- nsPresContext* GetPresContext();
- nsIContent* GetFocusedRootContent();
- // Returns true if IME consumes the mouse event.
- bool NotifyIMEOfMouseButtonEvent(nsIDOMMouseEvent* aMouseEvent);
- bool EditorHasFocus();
- bool IsFileControlTextBox();
- bool ShouldHandleNativeKeyBindings(nsIDOMKeyEvent* aKeyEvent);
- nsresult HandleMiddleClickPaste(nsIDOMMouseEvent* aMouseEvent);
-
- /**
- * DetachedFromEditor() returns true if editor was detached.
- * Otherwise, false.
- */
- bool DetachedFromEditor() const;
-
- /**
- * DetachedFromEditorOrDefaultPrevented() returns true if editor was detached
- * and/or the event was consumed. Otherwise, i.e., attached editor can
- * handle the event, returns true.
- */
- bool DetachedFromEditorOrDefaultPrevented(WidgetEvent* aEvent) const;
-
- EditorBase* mEditorBase; // weak
- RefPtr<nsCaret> mCaret;
- bool mCommitText;
- bool mInTransaction;
- bool mMouseDownOrUpConsumedByIME;
-#ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
- bool mHaveBidiKeyboards;
- bool mShouldSwitchTextDirection;
- bool mSwitchToRTL;
-#endif
-};
-
-} // namespace mozilla
-
-#endif // #ifndef EditorEventListener_h
diff --git a/editor/libeditor/EditorUtils.cpp b/editor/libeditor/EditorUtils.cpp
deleted file mode 100644
index 4ec60c830..000000000
--- a/editor/libeditor/EditorUtils.cpp
+++ /dev/null
@@ -1,227 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/EditorUtils.h"
-
-#include "mozilla/OwningNonNull.h"
-#include "mozilla/dom/Selection.h"
-#include "nsComponentManagerUtils.h"
-#include "nsError.h"
-#include "nsIClipboardDragDropHookList.h"
-// hooks
-#include "nsIClipboardDragDropHooks.h"
-#include "nsIContent.h"
-#include "nsIContentIterator.h"
-#include "nsIDOMDocument.h"
-#include "nsIDocShell.h"
-#include "nsIDocument.h"
-#include "nsIInterfaceRequestorUtils.h"
-#include "nsINode.h"
-#include "nsISimpleEnumerator.h"
-
-class nsISupports;
-class nsRange;
-
-namespace mozilla {
-
-using namespace dom;
-
-/******************************************************************************
- * AutoSelectionRestorer
- *****************************************************************************/
-
-AutoSelectionRestorer::AutoSelectionRestorer(
- Selection* aSelection,
- EditorBase* aEditorBase
- MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
- : mEditorBase(nullptr)
-{
- MOZ_GUARD_OBJECT_NOTIFIER_INIT;
- if (NS_WARN_IF(!aSelection) || NS_WARN_IF(!aEditorBase)) {
- return;
- }
- if (aEditorBase->ArePreservingSelection()) {
- // We already have initialized mSavedSel, so this must be nested call.
- return;
- }
- mSelection = aSelection;
- mEditorBase = aEditorBase;
- mEditorBase->PreserveSelectionAcrossActions(mSelection);
-}
-
-AutoSelectionRestorer::~AutoSelectionRestorer()
-{
- NS_ASSERTION(!mSelection || mEditorBase,
- "mEditorBase should be non-null when mSelection is");
- // mSelection will be null if this was nested call.
- if (mSelection && mEditorBase->ArePreservingSelection()) {
- mEditorBase->RestorePreservedSelection(mSelection);
- }
-}
-
-void
-AutoSelectionRestorer::Abort()
-{
- NS_ASSERTION(!mSelection || mEditorBase,
- "mEditorBase should be non-null when mSelection is");
- if (mSelection) {
- mEditorBase->StopPreservingSelection();
- }
-}
-
-/******************************************************************************
- * some helper classes for iterating the dom tree
- *****************************************************************************/
-
-DOMIterator::DOMIterator(nsINode& aNode MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
-{
- MOZ_GUARD_OBJECT_NOTIFIER_INIT;
- mIter = NS_NewContentIterator();
- DebugOnly<nsresult> rv = mIter->Init(&aNode);
- MOZ_ASSERT(NS_SUCCEEDED(rv));
-}
-
-nsresult
-DOMIterator::Init(nsRange& aRange)
-{
- mIter = NS_NewContentIterator();
- return mIter->Init(&aRange);
-}
-
-DOMIterator::DOMIterator(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
-{
- MOZ_GUARD_OBJECT_NOTIFIER_INIT;
-}
-
-DOMIterator::~DOMIterator()
-{
-}
-
-void
-DOMIterator::AppendList(const BoolDomIterFunctor& functor,
- nsTArray<OwningNonNull<nsINode>>& arrayOfNodes) const
-{
- // Iterate through dom and build list
- for (; !mIter->IsDone(); mIter->Next()) {
- nsCOMPtr<nsINode> node = mIter->GetCurrentNode();
-
- if (functor(node)) {
- arrayOfNodes.AppendElement(*node);
- }
- }
-}
-
-DOMSubtreeIterator::DOMSubtreeIterator(
- MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
- : DOMIterator(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT)
-{
-}
-
-nsresult
-DOMSubtreeIterator::Init(nsRange& aRange)
-{
- mIter = NS_NewContentSubtreeIterator();
- return mIter->Init(&aRange);
-}
-
-DOMSubtreeIterator::~DOMSubtreeIterator()
-{
-}
-
-/******************************************************************************
- * some general purpose editor utils
- *****************************************************************************/
-
-bool
-EditorUtils::IsDescendantOf(nsINode* aNode,
- nsINode* aParent,
- int32_t* aOffset)
-{
- MOZ_ASSERT(aNode && aParent);
- if (aNode == aParent) {
- return false;
- }
-
- for (nsCOMPtr<nsINode> node = aNode; node; node = node->GetParentNode()) {
- if (node->GetParentNode() == aParent) {
- if (aOffset) {
- *aOffset = aParent->IndexOf(node);
- }
- return true;
- }
- }
-
- return false;
-}
-
-bool
-EditorUtils::IsDescendantOf(nsIDOMNode* aNode,
- nsIDOMNode* aParent,
- int32_t* aOffset)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
- NS_ENSURE_TRUE(node && parent, false);
- return IsDescendantOf(node, parent, aOffset);
-}
-
-bool
-EditorUtils::IsLeafNode(nsIDOMNode* aNode)
-{
- bool hasChildren = false;
- if (aNode)
- aNode->HasChildNodes(&hasChildren);
- return !hasChildren;
-}
-
-/******************************************************************************
- * utility methods for drag/drop/copy/paste hooks
- *****************************************************************************/
-
-nsresult
-EditorHookUtils::GetHookEnumeratorFromDocument(nsIDOMDocument* aDoc,
- nsISimpleEnumerator** aResult)
-{
- nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
- NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIDocShell> docShell = doc->GetDocShell();
- nsCOMPtr<nsIClipboardDragDropHookList> hookObj = do_GetInterface(docShell);
- NS_ENSURE_TRUE(hookObj, NS_ERROR_FAILURE);
-
- return hookObj->GetHookEnumerator(aResult);
-}
-
-bool
-EditorHookUtils::DoInsertionHook(nsIDOMDocument* aDoc,
- nsIDOMEvent* aDropEvent,
- nsITransferable *aTrans)
-{
- nsCOMPtr<nsISimpleEnumerator> enumerator;
- GetHookEnumeratorFromDocument(aDoc, getter_AddRefs(enumerator));
- NS_ENSURE_TRUE(enumerator, true);
-
- bool hasMoreHooks = false;
- while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks)) &&
- hasMoreHooks) {
- nsCOMPtr<nsISupports> isupp;
- if (NS_FAILED(enumerator->GetNext(getter_AddRefs(isupp)))) {
- break;
- }
-
- nsCOMPtr<nsIClipboardDragDropHooks> override = do_QueryInterface(isupp);
- if (override) {
- bool doInsert = true;
- DebugOnly<nsresult> hookResult =
- override->OnPasteOrDrop(aDropEvent, aTrans, &doInsert);
- NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in OnPasteOrDrop");
- NS_ENSURE_TRUE(doInsert, false);
- }
- }
-
- return true;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/EditorUtils.h b/editor/libeditor/EditorUtils.h
deleted file mode 100644
index 15ec0b62d..000000000
--- a/editor/libeditor/EditorUtils.h
+++ /dev/null
@@ -1,428 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-#ifndef mozilla_EditorUtils_h
-#define mozilla_EditorUtils_h
-
-#include "mozilla/EditorBase.h"
-#include "mozilla/GuardObjects.h"
-#include "nsCOMPtr.h"
-#include "nsDebug.h"
-#include "nsIDOMNode.h"
-#include "nsIEditor.h"
-#include "nscore.h"
-
-class nsIAtom;
-class nsIContentIterator;
-class nsIDOMDocument;
-class nsIDOMEvent;
-class nsISimpleEnumerator;
-class nsITransferable;
-class nsRange;
-
-namespace mozilla {
-template <class T> class OwningNonNull;
-
-namespace dom {
-class Selection;
-} // namespace dom
-
-/***************************************************************************
- * EditActionResult is useful to return multiple results of an editor
- * action handler without out params.
- * Note that when you return an anonymous instance from a method, you should
- * use EditActionIgnored(), EditActionHandled() or EditActionCanceled() for
- * easier to read. In other words, EditActionResult should be used when
- * declaring return type of a method, being an argument or defined as a local
- * variable.
- */
-class MOZ_STACK_CLASS EditActionResult final
-{
-public:
- bool Succeeded() const { return NS_SUCCEEDED(mRv); }
- bool Failed() const { return NS_FAILED(mRv); }
- nsresult Rv() const { return mRv; }
- bool Canceled() const { return mCanceled; }
- bool Handled() const { return mHandled; }
-
- EditActionResult SetResult(nsresult aRv)
- {
- mRv = aRv;
- return *this;
- }
- EditActionResult MarkAsCanceled()
- {
- mCanceled = true;
- return *this;
- }
- EditActionResult MarkAsHandled()
- {
- mHandled = true;
- return *this;
- }
-
- explicit EditActionResult(nsresult aRv)
- : mRv(aRv)
- , mCanceled(false)
- , mHandled(false)
- {
- }
-
- EditActionResult& operator|=(const EditActionResult& aOther)
- {
- mCanceled |= aOther.mCanceled;
- mHandled |= aOther.mHandled;
- // When both result are same, keep the result.
- if (mRv == aOther.mRv) {
- return *this;
- }
- // If one of the results is error, use NS_ERROR_FAILURE.
- if (Failed() || aOther.Failed()) {
- mRv = NS_ERROR_FAILURE;
- } else {
- // Otherwise, use generic success code, NS_OK.
- mRv = NS_OK;
- }
- return *this;
- }
-
-private:
- nsresult mRv;
- bool mCanceled;
- bool mHandled;
-
- EditActionResult(nsresult aRv, bool aCanceled, bool aHandled)
- : mRv(aRv)
- , mCanceled(aCanceled)
- , mHandled(aHandled)
- {
- }
-
- EditActionResult()
- : mRv(NS_ERROR_NOT_INITIALIZED)
- , mCanceled(false)
- , mHandled(false)
- {
- }
-
- friend EditActionResult EditActionIgnored(nsresult aRv);
- friend EditActionResult EditActionHandled(nsresult aRv);
- friend EditActionResult EditActionCanceled(nsresult aRv);
-};
-
-/***************************************************************************
- * When an edit action handler (or its helper) does nothing,
- * EditActionIgnored should be returned.
- */
-inline EditActionResult
-EditActionIgnored(nsresult aRv = NS_OK)
-{
- return EditActionResult(aRv, false, false);
-}
-
-/***************************************************************************
- * When an edit action handler (or its helper) handled and not canceled,
- * EditActionHandled should be returned.
- */
-inline EditActionResult
-EditActionHandled(nsresult aRv = NS_OK)
-{
- return EditActionResult(aRv, false, true);
-}
-
-/***************************************************************************
- * When an edit action handler (or its helper) handled and canceled,
- * EditActionHandled should be returned.
- */
-inline EditActionResult
-EditActionCanceled(nsresult aRv = NS_OK)
-{
- return EditActionResult(aRv, true, true);
-}
-
-/***************************************************************************
- * stack based helper class for batching a collection of txns inside a
- * placeholder txn.
- */
-class MOZ_RAII AutoPlaceHolderBatch
-{
-private:
- nsCOMPtr<nsIEditor> mEditor;
- MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
-
-public:
- AutoPlaceHolderBatch(nsIEditor* aEditor,
- nsIAtom* aAtom
- MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
- : mEditor(aEditor)
- {
- MOZ_GUARD_OBJECT_NOTIFIER_INIT;
- if (mEditor) {
- mEditor->BeginPlaceHolderTransaction(aAtom);
- }
- }
- ~AutoPlaceHolderBatch()
- {
- if (mEditor) {
- mEditor->EndPlaceHolderTransaction();
- }
- }
-};
-
-/***************************************************************************
- * stack based helper class for batching a collection of txns.
- * Note: I changed this to use placeholder batching so that we get
- * proper selection save/restore across undo/redo.
- */
-class MOZ_RAII AutoEditBatch final : public AutoPlaceHolderBatch
-{
-private:
- MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
-
-public:
- explicit AutoEditBatch(nsIEditor* aEditor
- MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
- : AutoPlaceHolderBatch(aEditor, nullptr)
- {
- MOZ_GUARD_OBJECT_NOTIFIER_INIT;
- }
- ~AutoEditBatch() {}
-};
-
-/***************************************************************************
- * stack based helper class for saving/restoring selection. Note that this
- * assumes that the nodes involved are still around afterwards!
- */
-class MOZ_RAII AutoSelectionRestorer final
-{
-private:
- // Ref-counted reference to the selection that we are supposed to restore.
- RefPtr<dom::Selection> mSelection;
- EditorBase* mEditorBase; // Non-owning ref to EditorBase.
- MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
-
-public:
- /**
- * Constructor responsible for remembering all state needed to restore
- * aSelection.
- */
- AutoSelectionRestorer(dom::Selection* aSelection,
- EditorBase* aEditorBase
- MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
-
- /**
- * Destructor restores mSelection to its former state
- */
- ~AutoSelectionRestorer();
-
- /**
- * Abort() cancels to restore the selection.
- */
- void Abort();
-};
-
-/***************************************************************************
- * stack based helper class for StartOperation()/EndOperation() sandwich
- */
-class MOZ_RAII AutoRules final
-{
-public:
- AutoRules(EditorBase* aEditorBase, EditAction aAction,
- nsIEditor::EDirection aDirection
- MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
- : mEditorBase(aEditorBase)
- , mDoNothing(false)
- {
- MOZ_GUARD_OBJECT_NOTIFIER_INIT;
- // mAction will already be set if this is nested call
- if (mEditorBase && !mEditorBase->mAction) {
- mEditorBase->StartOperation(aAction, aDirection);
- } else {
- mDoNothing = true; // nested calls will end up here
- }
- }
-
- ~AutoRules()
- {
- if (mEditorBase && !mDoNothing) {
- mEditorBase->EndOperation();
- }
- }
-
-protected:
- EditorBase* mEditorBase;
- bool mDoNothing;
- MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
-};
-
-/***************************************************************************
- * stack based helper class for turning off active selection adjustment
- * by low level transactions
- */
-class MOZ_RAII AutoTransactionsConserveSelection final
-{
-public:
- explicit AutoTransactionsConserveSelection(EditorBase* aEditorBase
- MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
- : mEditorBase(aEditorBase)
- , mOldState(true)
- {
- MOZ_GUARD_OBJECT_NOTIFIER_INIT;
- if (mEditorBase) {
- mOldState = mEditorBase->GetShouldTxnSetSelection();
- mEditorBase->SetShouldTxnSetSelection(false);
- }
- }
-
- ~AutoTransactionsConserveSelection()
- {
- if (mEditorBase) {
- mEditorBase->SetShouldTxnSetSelection(mOldState);
- }
- }
-
-protected:
- EditorBase* mEditorBase;
- bool mOldState;
- MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
-};
-
-/***************************************************************************
- * stack based helper class for batching reflow and paint requests.
- */
-class MOZ_RAII AutoUpdateViewBatch final
-{
-public:
- explicit AutoUpdateViewBatch(EditorBase* aEditorBase
- MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
- : mEditorBase(aEditorBase)
- {
- MOZ_GUARD_OBJECT_NOTIFIER_INIT;
- NS_ASSERTION(mEditorBase, "null mEditorBase pointer!");
-
- if (mEditorBase) {
- mEditorBase->BeginUpdateViewBatch();
- }
- }
-
- ~AutoUpdateViewBatch()
- {
- if (mEditorBase) {
- mEditorBase->EndUpdateViewBatch();
- }
- }
-
-protected:
- EditorBase* mEditorBase;
- MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
-};
-
-/******************************************************************************
- * some helper classes for iterating the dom tree
- *****************************************************************************/
-
-class BoolDomIterFunctor
-{
-public:
- virtual bool operator()(nsINode* aNode) const = 0;
-};
-
-class MOZ_RAII DOMIterator
-{
-public:
- explicit DOMIterator(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
-
- explicit DOMIterator(nsINode& aNode MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
- virtual ~DOMIterator();
-
- nsresult Init(nsRange& aRange);
-
- void AppendList(
- const BoolDomIterFunctor& functor,
- nsTArray<mozilla::OwningNonNull<nsINode>>& arrayOfNodes) const;
-
-protected:
- nsCOMPtr<nsIContentIterator> mIter;
- MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
-};
-
-class MOZ_RAII DOMSubtreeIterator final : public DOMIterator
-{
-public:
- explicit DOMSubtreeIterator(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
- virtual ~DOMSubtreeIterator();
-
- nsresult Init(nsRange& aRange);
-};
-
-class TrivialFunctor final : public BoolDomIterFunctor
-{
-public:
- // Used to build list of all nodes iterator covers
- virtual bool operator()(nsINode* aNode) const
- {
- return true;
- }
-};
-
-/******************************************************************************
- * general dom point utility struct
- *****************************************************************************/
-struct MOZ_STACK_CLASS EditorDOMPoint final
-{
- nsCOMPtr<nsINode> node;
- int32_t offset;
-
- EditorDOMPoint()
- : node(nullptr)
- , offset(-1)
- {}
- EditorDOMPoint(nsINode* aNode, int32_t aOffset)
- : node(aNode)
- , offset(aOffset)
- {}
- EditorDOMPoint(nsIDOMNode* aNode, int32_t aOffset)
- : node(do_QueryInterface(aNode))
- , offset(aOffset)
- {}
-
- void SetPoint(nsINode* aNode, int32_t aOffset)
- {
- node = aNode;
- offset = aOffset;
- }
- void SetPoint(nsIDOMNode* aNode, int32_t aOffset)
- {
- node = do_QueryInterface(aNode);
- offset = aOffset;
- }
-};
-
-class EditorUtils final
-{
-public:
- static bool IsDescendantOf(nsINode* aNode, nsINode* aParent,
- int32_t* aOffset = 0);
- static bool IsDescendantOf(nsIDOMNode* aNode, nsIDOMNode* aParent,
- int32_t* aOffset = 0);
- static bool IsLeafNode(nsIDOMNode* aNode);
-};
-
-class EditorHookUtils final
-{
-public:
- static bool DoInsertionHook(nsIDOMDocument* aDoc, nsIDOMEvent* aEvent,
- nsITransferable* aTrans);
-
-private:
- static nsresult GetHookEnumeratorFromDocument(
- nsIDOMDocument*aDoc,
- nsISimpleEnumerator** aEnumerator);
-};
-
-} // namespace mozilla
-
-#endif // #ifndef mozilla_EditorUtils_h
diff --git a/editor/libeditor/EditorUtils.js b/editor/libeditor/EditorUtils.js
deleted file mode 100644
index 2959f67ab..000000000
--- a/editor/libeditor/EditorUtils.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-"use strict";
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-const EDITORUTILS_CID = Components.ID('{12e63991-86ac-4dff-bb1a-703495d67d17}');
-
-function EditorUtils() {
-}
-
-EditorUtils.prototype = {
- classID: EDITORUTILS_CID,
- QueryInterface: XPCOMUtils.generateQI([ Ci.nsIEditorUtils ]),
-
- slurpBlob(aBlob, aScope, aListener) {
- let reader = new aScope.FileReader();
- reader.addEventListener("load", (event) => {
- aListener.onResult(event.target.result);
- });
- reader.addEventListener("error", (event) => {
- aListener.onError(event.target.error.message);
- });
-
- reader.readAsBinaryString(aBlob);
- },
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([EditorUtils]);
diff --git a/editor/libeditor/EditorUtils.manifest b/editor/libeditor/EditorUtils.manifest
deleted file mode 100644
index 5c479e0b2..000000000
--- a/editor/libeditor/EditorUtils.manifest
+++ /dev/null
@@ -1,2 +0,0 @@
-component {12e63991-86ac-4dff-bb1a-703495d67d17} EditorUtils.js
-contract @mozilla.org/editor-utils;1 {12e63991-86ac-4dff-bb1a-703495d67d17}
diff --git a/editor/libeditor/HTMLAbsPositionEditor.cpp b/editor/libeditor/HTMLAbsPositionEditor.cpp
deleted file mode 100644
index 670da78ae..000000000
--- a/editor/libeditor/HTMLAbsPositionEditor.cpp
+++ /dev/null
@@ -1,682 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/HTMLEditor.h"
-
-#include <math.h>
-
-#include "HTMLEditorObjectResizerUtils.h"
-#include "HTMLEditRules.h"
-#include "HTMLEditUtils.h"
-#include "TextEditUtils.h"
-#include "mozilla/EditorUtils.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/dom/Selection.h"
-#include "mozilla/dom/Element.h"
-#include "mozilla/mozalloc.h"
-#include "nsAString.h"
-#include "nsAlgorithm.h"
-#include "nsCOMPtr.h"
-#include "nsComputedDOMStyle.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsGkAtoms.h"
-#include "nsIContent.h"
-#include "nsROCSSPrimitiveValue.h"
-#include "nsIDOMCSSStyleDeclaration.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMEventListener.h"
-#include "nsIDOMEventTarget.h"
-#include "nsIDOMNode.h"
-#include "nsDOMCSSRGBColor.h"
-#include "nsIDOMWindow.h"
-#include "nsIEditor.h"
-#include "nsIEditRules.h"
-#include "nsIHTMLEditor.h"
-#include "nsIHTMLObjectResizer.h"
-#include "nsINode.h"
-#include "nsIPresShell.h"
-#include "nsISupportsImpl.h"
-#include "nsISupportsUtils.h"
-#include "nsLiteralString.h"
-#include "nsReadableUtils.h"
-#include "nsString.h"
-#include "nsStringFwd.h"
-#include "nscore.h"
-#include <algorithm>
-
-namespace mozilla {
-
-using namespace dom;
-
-#define BLACK_BG_RGB_TRIGGER 0xd0
-
-NS_IMETHODIMP
-HTMLEditor::AbsolutePositionSelection(bool aEnabled)
-{
- AutoEditBatch beginBatching(this);
- AutoRules beginRulesSniffing(this,
- aEnabled ? EditAction::setAbsolutePosition :
- EditAction::removeAbsolutePosition,
- nsIEditor::eNext);
-
- // the line below does not match the code; should it be removed?
- // Find out if the selection is collapsed:
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- TextRulesInfo ruleInfo(aEnabled ? EditAction::setAbsolutePosition :
- EditAction::removeAbsolutePosition);
- bool cancel, handled;
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- if (NS_FAILED(rv) || cancel) {
- return rv;
- }
-
- return rules->DidDoAction(selection, &ruleInfo, rv);
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetAbsolutelyPositionedSelectionContainer(nsIDOMElement** _retval)
-{
- nsAutoString positionStr;
- nsCOMPtr<nsINode> node = GetSelectionContainer();
- nsCOMPtr<nsIDOMNode> resultNode;
-
- while (!resultNode && node && !node->IsHTMLElement(nsGkAtoms::html)) {
- nsresult rv =
- mCSSEditUtils->GetComputedProperty(*node, *nsGkAtoms::position,
- positionStr);
- NS_ENSURE_SUCCESS(rv, rv);
- if (positionStr.EqualsLiteral("absolute"))
- resultNode = GetAsDOMNode(node);
- else {
- node = node->GetParentNode();
- }
- }
-
- nsCOMPtr<nsIDOMElement> element = do_QueryInterface(resultNode);
- element.forget(_retval);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetSelectionContainerAbsolutelyPositioned(
- bool* aIsSelectionContainerAbsolutelyPositioned)
-{
- *aIsSelectionContainerAbsolutelyPositioned = (mAbsolutelyPositionedObject != nullptr);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetAbsolutePositioningEnabled(bool* aIsEnabled)
-{
- *aIsEnabled = mIsAbsolutelyPositioningEnabled;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::SetAbsolutePositioningEnabled(bool aIsEnabled)
-{
- mIsAbsolutelyPositioningEnabled = aIsEnabled;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::RelativeChangeElementZIndex(nsIDOMElement* aElement,
- int32_t aChange,
- int32_t* aReturn)
-{
- NS_ENSURE_ARG_POINTER(aElement);
- NS_ENSURE_ARG_POINTER(aReturn);
- if (!aChange) // early way out, no change
- return NS_OK;
-
- int32_t zIndex;
- nsresult rv = GetElementZIndex(aElement, &zIndex);
- NS_ENSURE_SUCCESS(rv, rv);
-
- zIndex = std::max(zIndex + aChange, 0);
- SetElementZIndex(aElement, zIndex);
- *aReturn = zIndex;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::SetElementZIndex(nsIDOMElement* aElement,
- int32_t aZindex)
-{
- nsCOMPtr<Element> element = do_QueryInterface(aElement);
- NS_ENSURE_ARG_POINTER(element);
-
- nsAutoString zIndexStr;
- zIndexStr.AppendInt(aZindex);
-
- mCSSEditUtils->SetCSSProperty(*element, *nsGkAtoms::z_index, zIndexStr);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::RelativeChangeZIndex(int32_t aChange)
-{
- AutoEditBatch beginBatching(this);
- AutoRules beginRulesSniffing(this,
- (aChange < 0) ? EditAction::decreaseZIndex :
- EditAction::increaseZIndex,
- nsIEditor::eNext);
-
- // brade: can we get rid of this comment?
- // Find out if the selection is collapsed:
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- TextRulesInfo ruleInfo(aChange < 0 ? EditAction::decreaseZIndex :
- EditAction::increaseZIndex);
- bool cancel, handled;
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- if (cancel || NS_FAILED(rv)) {
- return rv;
- }
-
- return rules->DidDoAction(selection, &ruleInfo, rv);
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetElementZIndex(nsIDOMElement* aElement,
- int32_t* aZindex)
-{
- nsCOMPtr<Element> element = do_QueryInterface(aElement);
- NS_ENSURE_STATE(element || !aElement);
- nsAutoString zIndexStr;
- *aZindex = 0;
-
- nsresult rv =
- mCSSEditUtils->GetSpecifiedProperty(*element, *nsGkAtoms::z_index,
- zIndexStr);
- NS_ENSURE_SUCCESS(rv, rv);
- if (zIndexStr.EqualsLiteral("auto")) {
- // we have to look at the positioned ancestors
- // cf. CSS 2 spec section 9.9.1
- nsCOMPtr<nsIDOMNode> parentNode;
- rv = aElement->GetParentNode(getter_AddRefs(parentNode));
- NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsINode> node = do_QueryInterface(parentNode);
- nsAutoString positionStr;
- while (node && zIndexStr.EqualsLiteral("auto") &&
- !node->IsHTMLElement(nsGkAtoms::body)) {
- rv = mCSSEditUtils->GetComputedProperty(*node, *nsGkAtoms::position,
- positionStr);
- NS_ENSURE_SUCCESS(rv, rv);
- if (positionStr.EqualsLiteral("absolute")) {
- // ah, we found one, what's its z-index ? If its z-index is auto,
- // we have to continue climbing the document's tree
- rv = mCSSEditUtils->GetComputedProperty(*node, *nsGkAtoms::z_index,
- zIndexStr);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- node = node->GetParentNode();
- }
- }
-
- if (!zIndexStr.EqualsLiteral("auto")) {
- nsresult errorCode;
- *aZindex = zIndexStr.ToInteger(&errorCode);
- }
-
- return NS_OK;
-}
-
-already_AddRefed<Element>
-HTMLEditor::CreateGrabber(nsINode* aParentNode)
-{
- // let's create a grabber through the element factory
- nsCOMPtr<nsIDOMElement> retDOM;
- CreateAnonymousElement(NS_LITERAL_STRING("span"), GetAsDOMNode(aParentNode),
- NS_LITERAL_STRING("mozGrabber"), false,
- getter_AddRefs(retDOM));
-
- NS_ENSURE_TRUE(retDOM, nullptr);
-
- // add the mouse listener so we can detect a click on a resizer
- nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(retDOM));
- evtTarget->AddEventListener(NS_LITERAL_STRING("mousedown"),
- mEventListener, false);
-
- nsCOMPtr<Element> ret = do_QueryInterface(retDOM);
- return ret.forget();
-}
-
-NS_IMETHODIMP
-HTMLEditor::RefreshGrabber()
-{
- NS_ENSURE_TRUE(mAbsolutelyPositionedObject, NS_ERROR_NULL_POINTER);
-
- nsresult rv =
- GetPositionAndDimensions(
- static_cast<nsIDOMElement*>(GetAsDOMNode(mAbsolutelyPositionedObject)),
- mPositionedObjectX,
- mPositionedObjectY,
- mPositionedObjectWidth,
- mPositionedObjectHeight,
- mPositionedObjectBorderLeft,
- mPositionedObjectBorderTop,
- mPositionedObjectMarginLeft,
- mPositionedObjectMarginTop);
- NS_ENSURE_SUCCESS(rv, rv);
-
- SetAnonymousElementPosition(mPositionedObjectX+12,
- mPositionedObjectY-14,
- static_cast<nsIDOMElement*>(GetAsDOMNode(mGrabber)));
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::HideGrabber()
-{
- nsresult rv = mAbsolutelyPositionedObject->UnsetAttr(kNameSpaceID_None,
- nsGkAtoms::_moz_abspos,
- true);
- NS_ENSURE_SUCCESS(rv, rv);
-
- mAbsolutelyPositionedObject = nullptr;
- NS_ENSURE_TRUE(mGrabber, NS_ERROR_NULL_POINTER);
-
- // get the presshell's document observer interface.
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
- // We allow the pres shell to be null; when it is, we presume there
- // are no document observers to notify, but we still want to
- // UnbindFromTree.
-
- nsCOMPtr<nsIContent> parentContent = mGrabber->GetParent();
- NS_ENSURE_TRUE(parentContent, NS_ERROR_NULL_POINTER);
-
- DeleteRefToAnonymousNode(static_cast<nsIDOMElement*>(GetAsDOMNode(mGrabber)), parentContent, ps);
- mGrabber = nullptr;
- DeleteRefToAnonymousNode(static_cast<nsIDOMElement*>(GetAsDOMNode(mPositioningShadow)), parentContent, ps);
- mPositioningShadow = nullptr;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::ShowGrabberOnElement(nsIDOMElement* aElement)
-{
- nsCOMPtr<Element> element = do_QueryInterface(aElement);
- NS_ENSURE_ARG_POINTER(element);
-
- if (NS_WARN_IF(!IsDescendantOfEditorRoot(element))) {
- return NS_ERROR_UNEXPECTED;
- }
-
- if (mGrabber) {
- NS_ERROR("call HideGrabber first");
- return NS_ERROR_UNEXPECTED;
- }
-
- nsAutoString classValue;
- nsresult rv = CheckPositionedElementBGandFG(aElement, classValue);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = element->SetAttr(kNameSpaceID_None, nsGkAtoms::_moz_abspos,
- classValue, true);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // first, let's keep track of that element...
- mAbsolutelyPositionedObject = element;
-
- mGrabber = CreateGrabber(element->GetParentNode());
- NS_ENSURE_TRUE(mGrabber, NS_ERROR_FAILURE);
-
- // and set its position
- return RefreshGrabber();
-}
-
-nsresult
-HTMLEditor::StartMoving(nsIDOMElement* aHandle)
-{
- nsCOMPtr<nsINode> parentNode = mGrabber->GetParentNode();
-
- // now, let's create the resizing shadow
- mPositioningShadow = CreateShadow(GetAsDOMNode(parentNode),
- static_cast<nsIDOMElement*>(GetAsDOMNode(mAbsolutelyPositionedObject)));
- NS_ENSURE_TRUE(mPositioningShadow, NS_ERROR_FAILURE);
- nsresult rv = SetShadowPosition(mPositioningShadow,
- mAbsolutelyPositionedObject,
- mPositionedObjectX, mPositionedObjectY);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // make the shadow appear
- mPositioningShadow->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_class, true);
-
- // position it
- mCSSEditUtils->SetCSSPropertyPixels(*mPositioningShadow, *nsGkAtoms::width,
- mPositionedObjectWidth);
- mCSSEditUtils->SetCSSPropertyPixels(*mPositioningShadow, *nsGkAtoms::height,
- mPositionedObjectHeight);
-
- mIsMoving = true;
- return NS_OK; // XXX Looks like nobody refers this result
-}
-
-void
-HTMLEditor::SnapToGrid(int32_t& newX, int32_t& newY)
-{
- if (mSnapToGridEnabled && mGridSize) {
- newX = (int32_t) floor( ((float)newX / (float)mGridSize) + 0.5f ) * mGridSize;
- newY = (int32_t) floor( ((float)newY / (float)mGridSize) + 0.5f ) * mGridSize;
- }
-}
-
-nsresult
-HTMLEditor::GrabberClicked()
-{
- // add a mouse move listener to the editor
- nsresult rv = NS_OK;
- if (!mMouseMotionListenerP) {
- mMouseMotionListenerP = new ResizerMouseMotionListener(this);
- if (!mMouseMotionListenerP) {return NS_ERROR_NULL_POINTER;}
-
- nsCOMPtr<nsIDOMEventTarget> piTarget = GetDOMEventTarget();
- NS_ENSURE_TRUE(piTarget, NS_ERROR_FAILURE);
-
- rv = piTarget->AddEventListener(NS_LITERAL_STRING("mousemove"),
- mMouseMotionListenerP,
- false, false);
- NS_ASSERTION(NS_SUCCEEDED(rv),
- "failed to register mouse motion listener");
- }
- mGrabberClicked = true;
- return rv;
-}
-
-nsresult
-HTMLEditor::EndMoving()
-{
- if (mPositioningShadow) {
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
- NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
-
- nsCOMPtr<nsIContent> parentContent = mGrabber->GetParent();
- NS_ENSURE_TRUE(parentContent, NS_ERROR_FAILURE);
-
- DeleteRefToAnonymousNode(static_cast<nsIDOMElement*>(GetAsDOMNode(mPositioningShadow)),
- parentContent, ps);
-
- mPositioningShadow = nullptr;
- }
- nsCOMPtr<nsIDOMEventTarget> piTarget = GetDOMEventTarget();
-
- if (piTarget && mMouseMotionListenerP) {
- DebugOnly<nsresult> rv =
- piTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"),
- mMouseMotionListenerP,
- false);
- NS_ASSERTION(NS_SUCCEEDED(rv), "failed to remove mouse motion listener");
- }
- mMouseMotionListenerP = nullptr;
-
- mGrabberClicked = false;
- mIsMoving = false;
- RefPtr<Selection> selection = GetSelection();
- if (!selection) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- return CheckSelectionStateForAnonymousButtons(selection);
-}
-nsresult
-HTMLEditor::SetFinalPosition(int32_t aX,
- int32_t aY)
-{
- nsresult rv = EndMoving();
- NS_ENSURE_SUCCESS(rv, rv);
-
- // we have now to set the new width and height of the resized object
- // we don't set the x and y position because we don't control that in
- // a normal HTML layout
- int32_t newX = mPositionedObjectX + aX - mOriginalX - (mPositionedObjectBorderLeft+mPositionedObjectMarginLeft);
- int32_t newY = mPositionedObjectY + aY - mOriginalY - (mPositionedObjectBorderTop+mPositionedObjectMarginTop);
-
- SnapToGrid(newX, newY);
-
- nsAutoString x, y;
- x.AppendInt(newX);
- y.AppendInt(newY);
-
- // we want one transaction only from a user's point of view
- AutoEditBatch batchIt(this);
-
- nsCOMPtr<Element> absolutelyPositionedObject =
- do_QueryInterface(mAbsolutelyPositionedObject);
- NS_ENSURE_STATE(absolutelyPositionedObject);
- mCSSEditUtils->SetCSSPropertyPixels(*absolutelyPositionedObject,
- *nsGkAtoms::top, newY);
- mCSSEditUtils->SetCSSPropertyPixels(*absolutelyPositionedObject,
- *nsGkAtoms::left, newX);
- // keep track of that size
- mPositionedObjectX = newX;
- mPositionedObjectY = newY;
-
- return RefreshResizers();
-}
-
-void
-HTMLEditor::AddPositioningOffset(int32_t& aX,
- int32_t& aY)
-{
- // Get the positioning offset
- int32_t positioningOffset =
- Preferences::GetInt("editor.positioning.offset", 0);
-
- aX += positioningOffset;
- aY += positioningOffset;
-}
-
-NS_IMETHODIMP
-HTMLEditor::AbsolutelyPositionElement(nsIDOMElement* aElement,
- bool aEnabled)
-{
- nsCOMPtr<Element> element = do_QueryInterface(aElement);
- NS_ENSURE_ARG_POINTER(element);
-
- nsAutoString positionStr;
- mCSSEditUtils->GetComputedProperty(*element, *nsGkAtoms::position,
- positionStr);
- bool isPositioned = (positionStr.EqualsLiteral("absolute"));
-
- // nothing to do if the element is already in the state we want
- if (isPositioned == aEnabled)
- return NS_OK;
-
- AutoEditBatch batchIt(this);
-
- if (aEnabled) {
- int32_t x, y;
- GetElementOrigin(aElement, x, y);
-
- mCSSEditUtils->SetCSSProperty(*element, *nsGkAtoms::position,
- NS_LITERAL_STRING("absolute"));
-
- AddPositioningOffset(x, y);
- SnapToGrid(x, y);
- SetElementPosition(*element, x, y);
-
- // we may need to create a br if the positioned element is alone in its
- // container
- nsCOMPtr<nsINode> element = do_QueryInterface(aElement);
- NS_ENSURE_STATE(element);
-
- nsINode* parentNode = element->GetParentNode();
- if (parentNode->GetChildCount() == 1) {
- nsCOMPtr<nsIDOMNode> brNode;
- nsresult rv = CreateBR(parentNode->AsDOMNode(), 0, address_of(brNode));
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- else {
- mCSSEditUtils->RemoveCSSProperty(*element, *nsGkAtoms::position,
- EmptyString());
- mCSSEditUtils->RemoveCSSProperty(*element, *nsGkAtoms::top,
- EmptyString());
- mCSSEditUtils->RemoveCSSProperty(*element, *nsGkAtoms::left,
- EmptyString());
- mCSSEditUtils->RemoveCSSProperty(*element, *nsGkAtoms::z_index,
- EmptyString());
-
- if (!HTMLEditUtils::IsImage(aElement)) {
- mCSSEditUtils->RemoveCSSProperty(*element, *nsGkAtoms::width,
- EmptyString());
- mCSSEditUtils->RemoveCSSProperty(*element, *nsGkAtoms::height,
- EmptyString());
- }
-
- nsCOMPtr<dom::Element> element = do_QueryInterface(aElement);
- if (element && element->IsHTMLElement(nsGkAtoms::div) &&
- !HasStyleOrIdOrClass(element)) {
- RefPtr<HTMLEditRules> htmlRules =
- static_cast<HTMLEditRules*>(mRules.get());
- NS_ENSURE_TRUE(htmlRules, NS_ERROR_FAILURE);
- nsresult rv = htmlRules->MakeSureElemStartsOrEndsOnCR(aElement);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = RemoveContainer(element);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::SetSnapToGridEnabled(bool aEnabled)
-{
- mSnapToGridEnabled = aEnabled;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetSnapToGridEnabled(bool* aIsEnabled)
-{
- *aIsEnabled = mSnapToGridEnabled;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::SetGridSize(uint32_t aSize)
-{
- mGridSize = aSize;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetGridSize(uint32_t* aSize)
-{
- *aSize = mGridSize;
- return NS_OK;
-}
-
-// self-explanatory
-NS_IMETHODIMP
-HTMLEditor::SetElementPosition(nsIDOMElement* aElement,
- int32_t aX,
- int32_t aY)
-{
- nsCOMPtr<Element> element = do_QueryInterface(aElement);
- NS_ENSURE_STATE(element);
-
- SetElementPosition(*element, aX, aY);
- return NS_OK;
-}
-
-void
-HTMLEditor::SetElementPosition(Element& aElement,
- int32_t aX,
- int32_t aY)
-{
- AutoEditBatch batchIt(this);
- mCSSEditUtils->SetCSSPropertyPixels(aElement, *nsGkAtoms::left, aX);
- mCSSEditUtils->SetCSSPropertyPixels(aElement, *nsGkAtoms::top, aY);
-}
-
-// self-explanatory
-NS_IMETHODIMP
-HTMLEditor::GetPositionedElement(nsIDOMElement** aReturn)
-{
- nsCOMPtr<nsIDOMElement> ret =
- static_cast<nsIDOMElement*>(GetAsDOMNode(mAbsolutelyPositionedObject));
- ret.forget(aReturn);
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::CheckPositionedElementBGandFG(nsIDOMElement* aElement,
- nsAString& aReturn)
-{
- // we are going to outline the positioned element and bring it to the
- // front to overlap any other element intersecting with it. But
- // first, let's see what's the background and foreground colors of the
- // positioned element.
- // if background-image computed value is 'none,
- // If the background color is 'auto' and R G B values of the foreground are
- // each above #d0, use a black background
- // If the background color is 'auto' and at least one of R G B values of
- // the foreground is below #d0, use a white background
- // Otherwise don't change background/foreground
- nsCOMPtr<Element> element = do_QueryInterface(aElement);
- NS_ENSURE_STATE(element || !aElement);
-
- aReturn.Truncate();
-
- nsAutoString bgImageStr;
- nsresult rv =
- mCSSEditUtils->GetComputedProperty(*element, *nsGkAtoms::background_image,
- bgImageStr);
- NS_ENSURE_SUCCESS(rv, rv);
- if (bgImageStr.EqualsLiteral("none")) {
- nsAutoString bgColorStr;
- rv =
- mCSSEditUtils->GetComputedProperty(*element, *nsGkAtoms::backgroundColor,
- bgColorStr);
- NS_ENSURE_SUCCESS(rv, rv);
- if (bgColorStr.EqualsLiteral("transparent")) {
- RefPtr<nsComputedDOMStyle> cssDecl =
- mCSSEditUtils->GetComputedStyle(element);
- NS_ENSURE_STATE(cssDecl);
-
- // from these declarations, get the one we want and that one only
- ErrorResult error;
- RefPtr<dom::CSSValue> cssVal = cssDecl->GetPropertyCSSValue(NS_LITERAL_STRING("color"), error);
- NS_ENSURE_TRUE(!error.Failed(), error.StealNSResult());
-
- nsROCSSPrimitiveValue* val = cssVal->AsPrimitiveValue();
- NS_ENSURE_TRUE(val, NS_ERROR_FAILURE);
-
- if (nsIDOMCSSPrimitiveValue::CSS_RGBCOLOR == val->PrimitiveType()) {
- nsDOMCSSRGBColor* rgbVal = val->GetRGBColorValue(error);
- NS_ENSURE_TRUE(!error.Failed(), error.StealNSResult());
- float r = rgbVal->Red()->
- GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, error);
- NS_ENSURE_TRUE(!error.Failed(), error.StealNSResult());
- float g = rgbVal->Green()->
- GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, error);
- NS_ENSURE_TRUE(!error.Failed(), error.StealNSResult());
- float b = rgbVal->Blue()->
- GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, error);
- NS_ENSURE_TRUE(!error.Failed(), error.StealNSResult());
- if (r >= BLACK_BG_RGB_TRIGGER &&
- g >= BLACK_BG_RGB_TRIGGER &&
- b >= BLACK_BG_RGB_TRIGGER)
- aReturn.AssignLiteral("black");
- else
- aReturn.AssignLiteral("white");
- return NS_OK;
- }
- }
- }
-
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/HTMLAnonymousNodeEditor.cpp b/editor/libeditor/HTMLAnonymousNodeEditor.cpp
deleted file mode 100644
index 798f5c330..000000000
--- a/editor/libeditor/HTMLAnonymousNodeEditor.cpp
+++ /dev/null
@@ -1,551 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/HTMLEditor.h"
-
-#include "mozilla/Attributes.h"
-#include "mozilla/dom/Element.h"
-#include "mozilla/mozalloc.h"
-#include "nsAString.h"
-#include "nsCOMPtr.h"
-#include "nsComputedDOMStyle.h"
-#include "nsDebug.h"
-#ifdef DEBUG
-#include "nsDocument.h"
-#endif
-#include "nsError.h"
-#include "nsGkAtoms.h"
-#include "nsIAtom.h"
-#include "nsIContent.h"
-#include "nsID.h"
-#include "nsIDOMCSSPrimitiveValue.h"
-#include "nsIDOMCSSStyleDeclaration.h"
-#include "nsIDOMCSSValue.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMEventTarget.h"
-#include "nsIDOMHTMLElement.h"
-#include "nsIDOMNode.h"
-#include "nsIDOMWindow.h"
-#include "nsIDocument.h"
-#include "nsIDocumentObserver.h"
-#include "nsIHTMLAbsPosEditor.h"
-#include "nsIHTMLInlineTableEditor.h"
-#include "nsIHTMLObjectResizer.h"
-#include "nsStubMutationObserver.h"
-#include "nsINode.h"
-#include "nsIPresShell.h"
-#include "nsISupportsImpl.h"
-#include "nsISupportsUtils.h"
-#include "nsLiteralString.h"
-#include "nsPresContext.h"
-#include "nsReadableUtils.h"
-#include "nsString.h"
-#include "nsStringFwd.h"
-#include "nsUnicharUtils.h"
-#include "nscore.h"
-#include "nsContentUtils.h" // for nsAutoScriptBlocker
-
-class nsIDOMEventListener;
-class nsISelection;
-
-namespace mozilla {
-
-using namespace dom;
-
-// retrieve an integer stored into a CSS computed float value
-static int32_t GetCSSFloatValue(nsIDOMCSSStyleDeclaration * aDecl,
- const nsAString & aProperty)
-{
- MOZ_ASSERT(aDecl);
-
- nsCOMPtr<nsIDOMCSSValue> value;
- // get the computed CSSValue of the property
- nsresult rv = aDecl->GetPropertyCSSValue(aProperty, getter_AddRefs(value));
- if (NS_FAILED(rv) || !value) {
- return 0;
- }
-
- // check the type of the returned CSSValue; we handle here only
- // pixel and enum types
- nsCOMPtr<nsIDOMCSSPrimitiveValue> val = do_QueryInterface(value);
- uint16_t type;
- val->GetPrimitiveType(&type);
-
- float f = 0;
- switch (type) {
- case nsIDOMCSSPrimitiveValue::CSS_PX:
- // the value is in pixels, just get it
- rv = val->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_PX, &f);
- NS_ENSURE_SUCCESS(rv, 0);
- break;
- case nsIDOMCSSPrimitiveValue::CSS_IDENT: {
- // the value is keyword, we have to map these keywords into
- // numeric values
- nsAutoString str;
- val->GetStringValue(str);
- if (str.EqualsLiteral("thin")) {
- f = 1;
- } else if (str.EqualsLiteral("medium")) {
- f = 3;
- } else if (str.EqualsLiteral("thick")) {
- f = 5;
- }
- break;
- }
- }
-
- return (int32_t) f;
-}
-
-class ElementDeletionObserver final : public nsStubMutationObserver
-{
-public:
- ElementDeletionObserver(nsIContent* aNativeAnonNode,
- nsIContent* aObservedNode)
- : mNativeAnonNode(aNativeAnonNode)
- , mObservedNode(aObservedNode)
- {}
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
- NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
-
-protected:
- ~ElementDeletionObserver() {}
- nsIContent* mNativeAnonNode;
- nsIContent* mObservedNode;
-};
-
-NS_IMPL_ISUPPORTS(ElementDeletionObserver, nsIMutationObserver)
-
-void
-ElementDeletionObserver::ParentChainChanged(nsIContent* aContent)
-{
- // If the native anonymous content has been unbound already in
- // DeleteRefToAnonymousNode, mNativeAnonNode's parentNode is null.
- if (aContent == mObservedNode && mNativeAnonNode &&
- mNativeAnonNode->GetParentNode() == aContent) {
- // If the observed node has been moved to another document, there isn't much
- // we can do easily. But at least be safe and unbind the native anonymous
- // content and stop observing changes.
- if (mNativeAnonNode->OwnerDoc() != mObservedNode->OwnerDoc()) {
- mObservedNode->RemoveMutationObserver(this);
- mObservedNode = nullptr;
- mNativeAnonNode->RemoveMutationObserver(this);
- mNativeAnonNode->UnbindFromTree();
- mNativeAnonNode = nullptr;
- NS_RELEASE_THIS();
- return;
- }
-
- // We're staying in the same document, just rebind the native anonymous
- // node so that the subtree root points to the right object etc.
- mNativeAnonNode->UnbindFromTree();
- mNativeAnonNode->BindToTree(mObservedNode->GetUncomposedDoc(), mObservedNode,
- mObservedNode, true);
- }
-}
-
-void
-ElementDeletionObserver::NodeWillBeDestroyed(const nsINode* aNode)
-{
- NS_ASSERTION(aNode == mNativeAnonNode || aNode == mObservedNode,
- "Wrong aNode!");
- if (aNode == mNativeAnonNode) {
- mObservedNode->RemoveMutationObserver(this);
- mObservedNode = nullptr;
- } else {
- mNativeAnonNode->RemoveMutationObserver(this);
- mNativeAnonNode->UnbindFromTree();
- mNativeAnonNode = nullptr;
- }
-
- NS_RELEASE_THIS();
-}
-
-// Returns in *aReturn an anonymous nsDOMElement of type aTag,
-// child of aParentNode. If aIsCreatedHidden is true, the class
-// "hidden" is added to the created element. If aAnonClass is not
-// the empty string, it becomes the value of the attribute "_moz_anonclass"
-nsresult
-HTMLEditor::CreateAnonymousElement(const nsAString& aTag,
- nsIDOMNode* aParentNode,
- const nsAString& aAnonClass,
- bool aIsCreatedHidden,
- nsIDOMElement** aReturn)
-{
- NS_ENSURE_ARG_POINTER(aParentNode);
- NS_ENSURE_ARG_POINTER(aReturn);
- *aReturn = nullptr;
-
- nsCOMPtr<nsIContent> parentContent( do_QueryInterface(aParentNode) );
- NS_ENSURE_TRUE(parentContent, NS_OK);
-
- nsCOMPtr<nsIDocument> doc = GetDocument();
- NS_ENSURE_TRUE(doc, NS_ERROR_NULL_POINTER);
-
- // Get the pres shell
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
- NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
-
- // Create a new node through the element factory
- nsCOMPtr<nsIAtom> tagAtom = NS_Atomize(aTag);
- nsCOMPtr<Element> newContent = CreateHTMLContent(tagAtom);
- NS_ENSURE_STATE(newContent);
-
- nsCOMPtr<nsIDOMElement> newElement = do_QueryInterface(newContent);
- NS_ENSURE_TRUE(newElement, NS_ERROR_FAILURE);
-
- // add the "hidden" class if needed
- if (aIsCreatedHidden) {
- nsresult rv = newElement->SetAttribute(NS_LITERAL_STRING("class"),
- NS_LITERAL_STRING("hidden"));
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // add an _moz_anonclass attribute if needed
- if (!aAnonClass.IsEmpty()) {
- nsresult rv = newElement->SetAttribute(NS_LITERAL_STRING("_moz_anonclass"),
- aAnonClass);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- {
- nsAutoScriptBlocker scriptBlocker;
-
- // establish parenthood of the element
- newContent->SetIsNativeAnonymousRoot();
- nsresult rv =
- newContent->BindToTree(doc, parentContent, parentContent, true);
- if (NS_FAILED(rv)) {
- newContent->UnbindFromTree();
- return rv;
- }
- }
-
- ElementDeletionObserver* observer =
- new ElementDeletionObserver(newContent, parentContent);
- NS_ADDREF(observer); // NodeWillBeDestroyed releases.
- parentContent->AddMutationObserver(observer);
- newContent->AddMutationObserver(observer);
-
-#ifdef DEBUG
- // Editor anonymous content gets passed to RecreateFramesFor... which can't
- // _really_ deal with anonymous content (because it can't get the frame tree
- // ordering right). But for us the ordering doesn't matter so this is sort of
- // ok.
- newContent->SetProperty(nsGkAtoms::restylableAnonymousNode,
- reinterpret_cast<void*>(true));
-#endif // DEBUG
-
- // display the element
- ps->RecreateFramesFor(newContent);
-
- newElement.forget(aReturn);
- return NS_OK;
-}
-
-// Removes event listener and calls DeleteRefToAnonymousNode.
-void
-HTMLEditor::RemoveListenerAndDeleteRef(const nsAString& aEvent,
- nsIDOMEventListener* aListener,
- bool aUseCapture,
- Element* aElement,
- nsIContent* aParentContent,
- nsIPresShell* aShell)
-{
- nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aElement));
- if (evtTarget) {
- evtTarget->RemoveEventListener(aEvent, aListener, aUseCapture);
- }
- DeleteRefToAnonymousNode(static_cast<nsIDOMElement*>(GetAsDOMNode(aElement)), aParentContent, aShell);
-}
-
-// Deletes all references to an anonymous element
-void
-HTMLEditor::DeleteRefToAnonymousNode(nsIDOMElement* aElement,
- nsIContent* aParentContent,
- nsIPresShell* aShell)
-{
- // call ContentRemoved() for the anonymous content
- // node so its references get removed from the frame manager's
- // undisplay map, and its layout frames get destroyed!
-
- if (aElement) {
- nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
- if (content) {
- nsAutoScriptBlocker scriptBlocker;
- // Need to check whether aShell has been destroyed (but not yet deleted).
- // In that case presContext->GetPresShell() returns nullptr.
- // See bug 338129.
- if (content->IsInComposedDoc() && aShell && aShell->GetPresContext() &&
- aShell->GetPresContext()->GetPresShell() == aShell) {
- nsCOMPtr<nsIDocumentObserver> docObserver = do_QueryInterface(aShell);
- if (docObserver) {
- // Call BeginUpdate() so that the nsCSSFrameConstructor/PresShell
- // knows we're messing with the frame tree.
- nsCOMPtr<nsIDocument> document = GetDocument();
- if (document) {
- docObserver->BeginUpdate(document, UPDATE_CONTENT_MODEL);
- }
-
- // XXX This is wrong (bug 439258). Once it's fixed, the NS_WARNING
- // in RestyleManager::RestyleForRemove should be changed back
- // to an assertion.
- docObserver->ContentRemoved(content->GetComposedDoc(),
- aParentContent, content, -1,
- content->GetPreviousSibling());
- if (document) {
- docObserver->EndUpdate(document, UPDATE_CONTENT_MODEL);
- }
- }
- }
- content->UnbindFromTree();
- }
- }
-}
-
-// The following method is mostly called by a selection listener. When a
-// selection change is notified, the method is called to check if resizing
-// handles, a grabber and/or inline table editing UI need to be displayed
-// or refreshed
-NS_IMETHODIMP
-HTMLEditor::CheckSelectionStateForAnonymousButtons(nsISelection* aSelection)
-{
- NS_ENSURE_ARG_POINTER(aSelection);
-
- // early way out if all contextual UI extensions are disabled
- NS_ENSURE_TRUE(mIsObjectResizingEnabled ||
- mIsAbsolutelyPositioningEnabled ||
- mIsInlineTableEditingEnabled, NS_OK);
-
- // Don't change selection state if we're moving.
- if (mIsMoving) {
- return NS_OK;
- }
-
- nsCOMPtr<nsIDOMElement> focusElement;
- // let's get the containing element of the selection
- nsresult rv = GetSelectionContainer(getter_AddRefs(focusElement));
- NS_ENSURE_TRUE(focusElement, NS_OK);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // If we're not in a document, don't try to add resizers
- nsCOMPtr<dom::Element> focusElementNode = do_QueryInterface(focusElement);
- NS_ENSURE_STATE(focusElementNode);
- if (!focusElementNode->IsInUncomposedDoc()) {
- return NS_OK;
- }
-
- // what's its tag?
- nsAutoString focusTagName;
- rv = focusElement->GetTagName(focusTagName);
- NS_ENSURE_SUCCESS(rv, rv);
- ToLowerCase(focusTagName);
- nsCOMPtr<nsIAtom> focusTagAtom = NS_Atomize(focusTagName);
-
- nsCOMPtr<nsIDOMElement> absPosElement;
- if (mIsAbsolutelyPositioningEnabled) {
- // Absolute Positioning support is enabled, is the selection contained
- // in an absolutely positioned element ?
- rv =
- GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(absPosElement));
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- nsCOMPtr<nsIDOMElement> cellElement;
- if (mIsObjectResizingEnabled || mIsInlineTableEditingEnabled) {
- // Resizing or Inline Table Editing is enabled, we need to check if the
- // selection is contained in a table cell
- rv = GetElementOrParentByTagName(NS_LITERAL_STRING("td"),
- nullptr,
- getter_AddRefs(cellElement));
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- if (mIsObjectResizingEnabled && cellElement) {
- // we are here because Resizing is enabled AND selection is contained in
- // a cell
-
- // get the enclosing table
- if (nsGkAtoms::img != focusTagAtom) {
- // the element container of the selection is not an image, so we'll show
- // the resizers around the table
- nsCOMPtr<nsIDOMNode> tableNode = GetEnclosingTable(cellElement);
- focusElement = do_QueryInterface(tableNode);
- focusTagAtom = nsGkAtoms::table;
- }
- }
-
- // we allow resizers only around images, tables, and absolutely positioned
- // elements. If we don't have image/table, let's look at the latter case.
- if (nsGkAtoms::img != focusTagAtom && nsGkAtoms::table != focusTagAtom) {
- focusElement = absPosElement;
- }
-
- // at this point, focusElement contains the element for Resizing,
- // cellElement contains the element for InlineTableEditing
- // absPosElement contains the element for Positioning
-
- // Note: All the Hide/Show methods below may change attributes on real
- // content which means a DOMAttrModified handler may cause arbitrary
- // side effects while this code runs (bug 420439).
-
- if (mIsAbsolutelyPositioningEnabled && mAbsolutelyPositionedObject &&
- absPosElement != GetAsDOMNode(mAbsolutelyPositionedObject)) {
- rv = HideGrabber();
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ASSERTION(!mAbsolutelyPositionedObject, "HideGrabber failed");
- }
-
- if (mIsObjectResizingEnabled && mResizedObject &&
- GetAsDOMNode(mResizedObject) != focusElement) {
- rv = HideResizers();
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ASSERTION(!mResizedObject, "HideResizers failed");
- }
-
- if (mIsInlineTableEditingEnabled && mInlineEditedCell &&
- mInlineEditedCell != cellElement) {
- rv = HideInlineTableEditingUI();
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ASSERTION(!mInlineEditedCell, "HideInlineTableEditingUI failed");
- }
-
- // now, let's display all contextual UI for good
- nsIContent* hostContent = GetActiveEditingHost();
- nsCOMPtr<nsIDOMNode> hostNode = do_QueryInterface(hostContent);
-
- if (mIsObjectResizingEnabled && focusElement &&
- IsModifiableNode(focusElement) && focusElement != hostNode) {
- if (nsGkAtoms::img == focusTagAtom) {
- mResizedObjectIsAnImage = true;
- }
- if (mResizedObject) {
- nsresult rv = RefreshResizers();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- nsresult rv = ShowResizers(focusElement);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- }
-
- if (mIsAbsolutelyPositioningEnabled && absPosElement &&
- IsModifiableNode(absPosElement) && absPosElement != hostNode) {
- if (mAbsolutelyPositionedObject) {
- nsresult rv = RefreshGrabber();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- nsresult rv = ShowGrabberOnElement(absPosElement);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- }
-
- if (mIsInlineTableEditingEnabled && cellElement &&
- IsModifiableNode(cellElement) && cellElement != hostNode) {
- if (mInlineEditedCell) {
- nsresult rv = RefreshInlineTableEditingUI();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- nsresult rv = ShowInlineTableEditingUI(cellElement);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- }
-
- return NS_OK;
-}
-
-// Resizing and Absolute Positioning need to know everything about the
-// containing box of the element: position, size, margins, borders
-nsresult
-HTMLEditor::GetPositionAndDimensions(nsIDOMElement* aElement,
- int32_t& aX,
- int32_t& aY,
- int32_t& aW,
- int32_t& aH,
- int32_t& aBorderLeft,
- int32_t& aBorderTop,
- int32_t& aMarginLeft,
- int32_t& aMarginTop)
-{
- nsCOMPtr<Element> element = do_QueryInterface(aElement);
- NS_ENSURE_ARG_POINTER(element);
-
- // Is the element positioned ? let's check the cheap way first...
- bool isPositioned = false;
- nsresult rv =
- aElement->HasAttribute(NS_LITERAL_STRING("_moz_abspos"), &isPositioned);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!isPositioned) {
- // hmmm... the expensive way now...
- nsAutoString positionStr;
- mCSSEditUtils->GetComputedProperty(*element, *nsGkAtoms::position,
- positionStr);
- isPositioned = positionStr.EqualsLiteral("absolute");
- }
-
- if (isPositioned) {
- // Yes, it is absolutely positioned
- mResizedObjectIsAbsolutelyPositioned = true;
-
- // Get the all the computed css styles attached to the element node
- RefPtr<nsComputedDOMStyle> cssDecl =
- mCSSEditUtils->GetComputedStyle(element);
- NS_ENSURE_STATE(cssDecl);
-
- aBorderLeft = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("border-left-width"));
- aBorderTop = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("border-top-width"));
- aMarginLeft = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("margin-left"));
- aMarginTop = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("margin-top"));
-
- aX = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("left")) +
- aMarginLeft + aBorderLeft;
- aY = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("top")) +
- aMarginTop + aBorderTop;
- aW = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("width"));
- aH = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("height"));
- } else {
- mResizedObjectIsAbsolutelyPositioned = false;
- nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(aElement);
- if (!htmlElement) {
- return NS_ERROR_NULL_POINTER;
- }
- GetElementOrigin(aElement, aX, aY);
-
- if (NS_WARN_IF(NS_FAILED(htmlElement->GetOffsetWidth(&aW))) ||
- NS_WARN_IF(NS_FAILED(htmlElement->GetOffsetHeight(&aH)))) {
- return rv;
- }
-
- aBorderLeft = 0;
- aBorderTop = 0;
- aMarginLeft = 0;
- aMarginTop = 0;
- }
- return NS_OK;
-}
-
-// self-explanatory
-void
-HTMLEditor::SetAnonymousElementPosition(int32_t aX,
- int32_t aY,
- nsIDOMElement* aElement)
-{
- mCSSEditUtils->SetCSSPropertyPixels(aElement, NS_LITERAL_STRING("left"), aX);
- mCSSEditUtils->SetCSSPropertyPixels(aElement, NS_LITERAL_STRING("top"), aY);
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/HTMLEditRules.cpp b/editor/libeditor/HTMLEditRules.cpp
deleted file mode 100644
index ac1c4ce6f..000000000
--- a/editor/libeditor/HTMLEditRules.cpp
+++ /dev/null
@@ -1,8909 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "HTMLEditRules.h"
-
-#include <stdlib.h>
-
-#include "HTMLEditUtils.h"
-#include "TextEditUtils.h"
-#include "WSRunObject.h"
-#include "mozilla/Assertions.h"
-#include "mozilla/CSSEditUtils.h"
-#include "mozilla/EditorUtils.h"
-#include "mozilla/HTMLEditor.h"
-#include "mozilla/MathAlgorithms.h"
-#include "mozilla/Move.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/UniquePtr.h"
-#include "mozilla/dom/Selection.h"
-#include "mozilla/dom/Element.h"
-#include "mozilla/OwningNonNull.h"
-#include "mozilla/mozalloc.h"
-#include "nsAString.h"
-#include "nsAlgorithm.h"
-#include "nsCRT.h"
-#include "nsCRTGlue.h"
-#include "nsComponentManagerUtils.h"
-#include "nsContentUtils.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsGkAtoms.h"
-#include "nsIAtom.h"
-#include "nsIContent.h"
-#include "nsIContentIterator.h"
-#include "nsID.h"
-#include "nsIDOMCharacterData.h"
-#include "nsIDOMDocument.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMNode.h"
-#include "nsIDOMText.h"
-#include "nsIFrame.h"
-#include "nsIHTMLAbsPosEditor.h"
-#include "nsIHTMLDocument.h"
-#include "nsINode.h"
-#include "nsLiteralString.h"
-#include "nsRange.h"
-#include "nsReadableUtils.h"
-#include "nsString.h"
-#include "nsStringFwd.h"
-#include "nsTArray.h"
-#include "nsTextNode.h"
-#include "nsThreadUtils.h"
-#include "nsUnicharUtils.h"
-#include <algorithm>
-
-// Workaround for windows headers
-#ifdef SetProp
-#undef SetProp
-#endif
-
-class nsISupports;
-
-namespace mozilla {
-
-class RulesInfo;
-
-using namespace dom;
-
-//const static char* kMOZEditorBogusNodeAttr="MOZ_EDITOR_BOGUS_NODE";
-//const static char* kMOZEditorBogusNodeValue="TRUE";
-
-enum
-{
- kLonely = 0,
- kPrevSib = 1,
- kNextSib = 2,
- kBothSibs = 3
-};
-
-/********************************************************
- * first some helpful functors we will use
- ********************************************************/
-
-static bool IsBlockNode(const nsINode& node)
-{
- return HTMLEditor::NodeIsBlockStatic(&node);
-}
-
-static bool IsInlineNode(const nsINode& node)
-{
- return !IsBlockNode(node);
-}
-
-static bool
-IsStyleCachePreservingAction(EditAction action)
-{
- return action == EditAction::deleteSelection ||
- action == EditAction::insertBreak ||
- action == EditAction::makeList ||
- action == EditAction::indent ||
- action == EditAction::outdent ||
- action == EditAction::align ||
- action == EditAction::makeBasicBlock ||
- action == EditAction::removeList ||
- action == EditAction::makeDefListItem ||
- action == EditAction::insertElement ||
- action == EditAction::insertQuotation;
-}
-
-class TableCellAndListItemFunctor final : public BoolDomIterFunctor
-{
-public:
- // Used to build list of all li's, td's & th's iterator covers
- virtual bool operator()(nsINode* aNode) const
- {
- return HTMLEditUtils::IsTableCell(aNode) ||
- HTMLEditUtils::IsListItem(aNode);
- }
-};
-
-class BRNodeFunctor final : public BoolDomIterFunctor
-{
-public:
- virtual bool operator()(nsINode* aNode) const
- {
- return aNode->IsHTMLElement(nsGkAtoms::br);
- }
-};
-
-class EmptyEditableFunctor final : public BoolDomIterFunctor
-{
-public:
- explicit EmptyEditableFunctor(HTMLEditor* aHTMLEditor)
- : mHTMLEditor(aHTMLEditor)
- {}
-
- virtual bool operator()(nsINode* aNode) const
- {
- if (mHTMLEditor->IsEditable(aNode) &&
- (HTMLEditUtils::IsListItem(aNode) ||
- HTMLEditUtils::IsTableCellOrCaption(*aNode))) {
- bool bIsEmptyNode;
- nsresult rv =
- mHTMLEditor->IsEmptyNode(aNode, &bIsEmptyNode, false, false);
- NS_ENSURE_SUCCESS(rv, false);
- if (bIsEmptyNode) {
- return true;
- }
- }
- return false;
- }
-
-protected:
- HTMLEditor* mHTMLEditor;
-};
-
-/********************************************************
- * mozilla::HTMLEditRules
- ********************************************************/
-
-HTMLEditRules::HTMLEditRules()
- : mHTMLEditor(nullptr)
- , mListenerEnabled(false)
- , mReturnInEmptyLIKillsList(false)
- , mDidDeleteSelection(false)
- , mDidRangedDelete(false)
- , mRestoreContentEditableCount(false)
- , mJoinOffset(0)
-{
- InitFields();
-}
-
-void
-HTMLEditRules::InitFields()
-{
- mHTMLEditor = nullptr;
- mDocChangeRange = nullptr;
- mListenerEnabled = true;
- mReturnInEmptyLIKillsList = true;
- mDidDeleteSelection = false;
- mDidRangedDelete = false;
- mRestoreContentEditableCount = false;
- mUtilRange = nullptr;
- mJoinOffset = 0;
- mNewBlock = nullptr;
- mRangeItem = new RangeItem();
- // populate mCachedStyles
- mCachedStyles[0] = StyleCache(nsGkAtoms::b, EmptyString(), EmptyString());
- mCachedStyles[1] = StyleCache(nsGkAtoms::i, EmptyString(), EmptyString());
- mCachedStyles[2] = StyleCache(nsGkAtoms::u, EmptyString(), EmptyString());
- mCachedStyles[3] = StyleCache(nsGkAtoms::font, NS_LITERAL_STRING("face"), EmptyString());
- mCachedStyles[4] = StyleCache(nsGkAtoms::font, NS_LITERAL_STRING("size"), EmptyString());
- mCachedStyles[5] = StyleCache(nsGkAtoms::font, NS_LITERAL_STRING("color"), EmptyString());
- mCachedStyles[6] = StyleCache(nsGkAtoms::tt, EmptyString(), EmptyString());
- mCachedStyles[7] = StyleCache(nsGkAtoms::em, EmptyString(), EmptyString());
- mCachedStyles[8] = StyleCache(nsGkAtoms::strong, EmptyString(), EmptyString());
- mCachedStyles[9] = StyleCache(nsGkAtoms::dfn, EmptyString(), EmptyString());
- mCachedStyles[10] = StyleCache(nsGkAtoms::code, EmptyString(), EmptyString());
- mCachedStyles[11] = StyleCache(nsGkAtoms::samp, EmptyString(), EmptyString());
- mCachedStyles[12] = StyleCache(nsGkAtoms::var, EmptyString(), EmptyString());
- mCachedStyles[13] = StyleCache(nsGkAtoms::cite, EmptyString(), EmptyString());
- mCachedStyles[14] = StyleCache(nsGkAtoms::abbr, EmptyString(), EmptyString());
- mCachedStyles[15] = StyleCache(nsGkAtoms::acronym, EmptyString(), EmptyString());
- mCachedStyles[16] = StyleCache(nsGkAtoms::backgroundColor, EmptyString(), EmptyString());
- mCachedStyles[17] = StyleCache(nsGkAtoms::sub, EmptyString(), EmptyString());
- mCachedStyles[18] = StyleCache(nsGkAtoms::sup, EmptyString(), EmptyString());
-}
-
-HTMLEditRules::~HTMLEditRules()
-{
- // remove ourselves as a listener to edit actions
- // In some cases, we have already been removed by
- // ~HTMLEditor, in which case we will get a null pointer here
- // which we ignore. But this allows us to add the ability to
- // switch rule sets on the fly if we want.
- if (mHTMLEditor) {
- mHTMLEditor->RemoveEditActionListener(this);
- }
-}
-
-NS_IMPL_ADDREF_INHERITED(HTMLEditRules, TextEditRules)
-NS_IMPL_RELEASE_INHERITED(HTMLEditRules, TextEditRules)
-NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLEditRules)
- NS_INTERFACE_TABLE_INHERITED(HTMLEditRules, nsIEditActionListener)
-NS_INTERFACE_TABLE_TAIL_INHERITING(TextEditRules)
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLEditRules, TextEditRules,
- mDocChangeRange, mUtilRange, mNewBlock,
- mRangeItem)
-
-NS_IMETHODIMP
-HTMLEditRules::Init(TextEditor* aTextEditor)
-{
- InitFields();
-
- mHTMLEditor = static_cast<HTMLEditor*>(aTextEditor);
-
- // call through to base class Init
- nsresult rv = TextEditRules::Init(aTextEditor);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // cache any prefs we care about
- static const char kPrefName[] =
- "editor.html.typing.returnInEmptyListItemClosesList";
- nsAdoptingCString returnInEmptyLIKillsList =
- Preferences::GetCString(kPrefName);
-
- // only when "false", becomes FALSE. Otherwise (including empty), TRUE.
- // XXX Why was this pref designed as a string and not bool?
- mReturnInEmptyLIKillsList = !returnInEmptyLIKillsList.EqualsLiteral("false");
-
- // make a utility range for use by the listenter
- nsCOMPtr<nsINode> node = mHTMLEditor->GetRoot();
- if (!node) {
- node = mHTMLEditor->GetDocument();
- }
-
- NS_ENSURE_STATE(node);
-
- mUtilRange = new nsRange(node);
-
- // set up mDocChangeRange to be whole doc
- // temporarily turn off rules sniffing
- AutoLockRulesSniffing lockIt(this);
- if (!mDocChangeRange) {
- mDocChangeRange = new nsRange(node);
- }
-
- if (node->IsElement()) {
- ErrorResult rv;
- mDocChangeRange->SelectNode(*node, rv);
- NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult());
- AdjustSpecialBreaks();
- }
-
- // add ourselves as a listener to edit actions
- return mHTMLEditor->AddEditActionListener(this);
-}
-
-NS_IMETHODIMP
-HTMLEditRules::DetachEditor()
-{
- if (mHTMLEditor) {
- mHTMLEditor->RemoveEditActionListener(this);
- }
- mHTMLEditor = nullptr;
- return TextEditRules::DetachEditor();
-}
-
-NS_IMETHODIMP
-HTMLEditRules::BeforeEdit(EditAction action,
- nsIEditor::EDirection aDirection)
-{
- if (mLockRulesSniffing) {
- return NS_OK;
- }
-
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- AutoLockRulesSniffing lockIt(this);
- mDidExplicitlySetInterline = false;
-
- if (!mActionNesting) {
- mActionNesting++;
-
- // Clear our flag about if just deleted a range
- mDidRangedDelete = false;
-
- // Remember where our selection was before edit action took place:
-
- // Get selection
- RefPtr<Selection> selection = htmlEditor->GetSelection();
-
- // Get the selection location
- if (NS_WARN_IF(!selection) || !selection->RangeCount()) {
- return NS_ERROR_UNEXPECTED;
- }
- mRangeItem->startNode = selection->GetRangeAt(0)->GetStartParent();
- mRangeItem->startOffset = selection->GetRangeAt(0)->StartOffset();
- mRangeItem->endNode = selection->GetRangeAt(0)->GetEndParent();
- mRangeItem->endOffset = selection->GetRangeAt(0)->EndOffset();
- nsCOMPtr<nsINode> selStartNode = mRangeItem->startNode;
- nsCOMPtr<nsINode> selEndNode = mRangeItem->endNode;
-
- // Register with range updater to track this as we perturb the doc
- htmlEditor->mRangeUpdater.RegisterRangeItem(mRangeItem);
-
- // Clear deletion state bool
- mDidDeleteSelection = false;
-
- // Clear out mDocChangeRange and mUtilRange
- if (mDocChangeRange) {
- // Clear out our accounting of what changed
- mDocChangeRange->Reset();
- }
- if (mUtilRange) {
- // Ditto for mUtilRange.
- mUtilRange->Reset();
- }
-
- // Remember current inline styles for deletion and normal insertion ops
- if (action == EditAction::insertText ||
- action == EditAction::insertIMEText ||
- action == EditAction::deleteSelection ||
- IsStyleCachePreservingAction(action)) {
- nsCOMPtr<nsINode> selNode =
- aDirection == nsIEditor::eNext ? selEndNode : selStartNode;
- nsresult rv = CacheInlineStyles(GetAsDOMNode(selNode));
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // Stabilize the document against contenteditable count changes
- nsCOMPtr<nsIDOMDocument> doc = htmlEditor->GetDOMDocument();
- NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
- nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(doc);
- NS_ENSURE_TRUE(htmlDoc, NS_ERROR_FAILURE);
- if (htmlDoc->GetEditingState() == nsIHTMLDocument::eContentEditable) {
- htmlDoc->ChangeContentEditableCount(nullptr, +1);
- mRestoreContentEditableCount = true;
- }
-
- // Check that selection is in subtree defined by body node
- ConfirmSelectionInBody();
- // Let rules remember the top level action
- mTheAction = action;
- }
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-HTMLEditRules::AfterEdit(EditAction action,
- nsIEditor::EDirection aDirection)
-{
- if (mLockRulesSniffing) {
- return NS_OK;
- }
-
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- AutoLockRulesSniffing lockIt(this);
-
- MOZ_ASSERT(mActionNesting > 0);
- nsresult rv = NS_OK;
- mActionNesting--;
- if (!mActionNesting) {
- // Do all the tricky stuff
- rv = AfterEditInner(action, aDirection);
-
- // Free up selectionState range item
- htmlEditor->mRangeUpdater.DropRangeItem(mRangeItem);
-
- // Reset the contenteditable count to its previous value
- if (mRestoreContentEditableCount) {
- nsCOMPtr<nsIDOMDocument> doc = htmlEditor->GetDOMDocument();
- NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
- nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(doc);
- NS_ENSURE_TRUE(htmlDoc, NS_ERROR_FAILURE);
- if (htmlDoc->GetEditingState() == nsIHTMLDocument::eContentEditable) {
- htmlDoc->ChangeContentEditableCount(nullptr, -1);
- }
- mRestoreContentEditableCount = false;
- }
- }
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::AfterEditInner(EditAction action,
- nsIEditor::EDirection aDirection)
-{
- ConfirmSelectionInBody();
- if (action == EditAction::ignore) {
- return NS_OK;
- }
-
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<Selection> selection = mHTMLEditor->GetSelection();
- NS_ENSURE_STATE(selection);
-
- nsCOMPtr<nsIDOMNode> rangeStartParent, rangeEndParent;
- uint32_t rangeStartOffset = 0, rangeEndOffset = 0;
- // do we have a real range to act on?
- bool bDamagedRange = false;
- if (mDocChangeRange) {
- mDocChangeRange->GetStartContainer(getter_AddRefs(rangeStartParent));
- mDocChangeRange->GetEndContainer(getter_AddRefs(rangeEndParent));
- mDocChangeRange->GetStartOffset(&rangeStartOffset);
- mDocChangeRange->GetEndOffset(&rangeEndOffset);
- if (rangeStartParent && rangeEndParent)
- bDamagedRange = true;
- }
-
- if (bDamagedRange && !((action == EditAction::undo) ||
- (action == EditAction::redo))) {
- // don't let any txns in here move the selection around behind our back.
- // Note that this won't prevent explicit selection setting from working.
- NS_ENSURE_STATE(mHTMLEditor);
- AutoTransactionsConserveSelection dontSpazMySelection(mHTMLEditor);
-
- // expand the "changed doc range" as needed
- PromoteRange(*mDocChangeRange, action);
-
- // if we did a ranged deletion or handling backspace key, make sure we have
- // a place to put caret.
- // Note we only want to do this if the overall operation was deletion,
- // not if deletion was done along the way for EditAction::loadHTML, EditAction::insertText, etc.
- // That's why this is here rather than DidDeleteSelection().
- if (action == EditAction::deleteSelection && mDidRangedDelete) {
- nsresult rv = InsertBRIfNeeded(selection);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // add in any needed <br>s, and remove any unneeded ones.
- AdjustSpecialBreaks();
-
- // merge any adjacent text nodes
- if (action != EditAction::insertText &&
- action != EditAction::insertIMEText) {
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv = mHTMLEditor->CollapseAdjacentTextNodes(mDocChangeRange);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // clean up any empty nodes in the selection
- nsresult rv = RemoveEmptyNodes();
- NS_ENSURE_SUCCESS(rv, rv);
-
- // attempt to transform any unneeded nbsp's into spaces after doing various operations
- if (action == EditAction::insertText ||
- action == EditAction::insertIMEText ||
- action == EditAction::deleteSelection ||
- action == EditAction::insertBreak ||
- action == EditAction::htmlPaste ||
- action == EditAction::loadHTML) {
- rv = AdjustWhitespace(selection);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // also do this for original selection endpoints.
- NS_ENSURE_STATE(mHTMLEditor);
- NS_ENSURE_STATE(mRangeItem->startNode);
- NS_ENSURE_STATE(mRangeItem->endNode);
- WSRunObject(mHTMLEditor, mRangeItem->startNode,
- mRangeItem->startOffset).AdjustWhitespace();
- // we only need to handle old selection endpoint if it was different from start
- if (mRangeItem->startNode != mRangeItem->endNode ||
- mRangeItem->startOffset != mRangeItem->endOffset) {
- NS_ENSURE_STATE(mHTMLEditor);
- WSRunObject(mHTMLEditor, mRangeItem->endNode,
- mRangeItem->endOffset).AdjustWhitespace();
- }
- }
-
- // if we created a new block, make sure selection lands in it
- if (mNewBlock) {
- rv = PinSelectionToNewBlock(selection);
- mNewBlock = nullptr;
- }
-
- // adjust selection for insert text, html paste, and delete actions
- if (action == EditAction::insertText ||
- action == EditAction::insertIMEText ||
- action == EditAction::deleteSelection ||
- action == EditAction::insertBreak ||
- action == EditAction::htmlPaste ||
- action == EditAction::loadHTML) {
- rv = AdjustSelection(selection, aDirection);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // check for any styles which were removed inappropriately
- if (action == EditAction::insertText ||
- action == EditAction::insertIMEText ||
- action == EditAction::deleteSelection ||
- IsStyleCachePreservingAction(action)) {
- NS_ENSURE_STATE(mHTMLEditor);
- mHTMLEditor->mTypeInState->UpdateSelState(selection);
- rv = ReapplyCachedStyles();
- NS_ENSURE_SUCCESS(rv, rv);
- ClearCachedStyles();
- }
- }
-
- NS_ENSURE_STATE(mHTMLEditor);
-
- nsresult rv =
- mHTMLEditor->HandleInlineSpellCheck(action, selection,
- GetAsDOMNode(mRangeItem->startNode),
- mRangeItem->startOffset,
- rangeStartParent, static_cast<int32_t>(rangeStartOffset),
- rangeEndParent, static_cast<int32_t>(rangeEndOffset));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // detect empty doc
- rv = CreateBogusNodeIfNeeded(selection);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // adjust selection HINT if needed
- if (!mDidExplicitlySetInterline) {
- CheckInterlinePosition(*selection);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditRules::WillDoAction(Selection* aSelection,
- RulesInfo* aInfo,
- bool* aCancel,
- bool* aHandled)
-{
- MOZ_ASSERT(aInfo && aCancel && aHandled);
-
- *aCancel = false;
- *aHandled = false;
-
- // my kingdom for dynamic cast
- TextRulesInfo* info = static_cast<TextRulesInfo*>(aInfo);
-
- // Deal with actions for which we don't need to check whether the selection is
- // editable.
- if (info->action == EditAction::outputText ||
- info->action == EditAction::undo ||
- info->action == EditAction::redo) {
- return TextEditRules::WillDoAction(aSelection, aInfo, aCancel, aHandled);
- }
-
- // Nothing to do if there's no selection to act on
- if (!aSelection) {
- return NS_OK;
- }
- NS_ENSURE_TRUE(aSelection->RangeCount(), NS_OK);
-
- RefPtr<nsRange> range = aSelection->GetRangeAt(0);
- nsCOMPtr<nsINode> selStartNode = range->GetStartParent();
-
- NS_ENSURE_STATE(mHTMLEditor);
- if (!mHTMLEditor->IsModifiableNode(selStartNode)) {
- *aCancel = true;
- return NS_OK;
- }
-
- nsCOMPtr<nsINode> selEndNode = range->GetEndParent();
-
- if (selStartNode != selEndNode) {
- NS_ENSURE_STATE(mHTMLEditor);
- if (!mHTMLEditor->IsModifiableNode(selEndNode)) {
- *aCancel = true;
- return NS_OK;
- }
-
- NS_ENSURE_STATE(mHTMLEditor);
- if (!mHTMLEditor->IsModifiableNode(range->GetCommonAncestor())) {
- *aCancel = true;
- return NS_OK;
- }
- }
-
- switch (info->action) {
- case EditAction::insertText:
- case EditAction::insertIMEText:
- UndefineCaretBidiLevel(aSelection);
- return WillInsertText(info->action, aSelection, aCancel, aHandled,
- info->inString, info->outString, info->maxLength);
- case EditAction::loadHTML:
- return WillLoadHTML(aSelection, aCancel);
- case EditAction::insertBreak:
- UndefineCaretBidiLevel(aSelection);
- return WillInsertBreak(*aSelection, aCancel, aHandled);
- case EditAction::deleteSelection:
- return WillDeleteSelection(aSelection, info->collapsedAction,
- info->stripWrappers, aCancel, aHandled);
- case EditAction::makeList:
- return WillMakeList(aSelection, info->blockType, info->entireList,
- info->bulletType, aCancel, aHandled);
- case EditAction::indent:
- return WillIndent(aSelection, aCancel, aHandled);
- case EditAction::outdent:
- return WillOutdent(*aSelection, aCancel, aHandled);
- case EditAction::setAbsolutePosition:
- return WillAbsolutePosition(*aSelection, aCancel, aHandled);
- case EditAction::removeAbsolutePosition:
- return WillRemoveAbsolutePosition(aSelection, aCancel, aHandled);
- case EditAction::align:
- return WillAlign(*aSelection, *info->alignType, aCancel, aHandled);
- case EditAction::makeBasicBlock:
- return WillMakeBasicBlock(*aSelection, *info->blockType, aCancel,
- aHandled);
- case EditAction::removeList:
- return WillRemoveList(aSelection, info->bOrdered, aCancel, aHandled);
- case EditAction::makeDefListItem:
- return WillMakeDefListItem(aSelection, info->blockType, info->entireList,
- aCancel, aHandled);
- case EditAction::insertElement:
- WillInsert(*aSelection, aCancel);
- return NS_OK;
- case EditAction::decreaseZIndex:
- return WillRelativeChangeZIndex(aSelection, -1, aCancel, aHandled);
- case EditAction::increaseZIndex:
- return WillRelativeChangeZIndex(aSelection, 1, aCancel, aHandled);
- default:
- return TextEditRules::WillDoAction(aSelection, aInfo,
- aCancel, aHandled);
- }
-}
-
-NS_IMETHODIMP
-HTMLEditRules::DidDoAction(Selection* aSelection,
- RulesInfo* aInfo,
- nsresult aResult)
-{
- TextRulesInfo* info = static_cast<TextRulesInfo*>(aInfo);
- switch (info->action) {
- case EditAction::insertBreak:
- return DidInsertBreak(aSelection, aResult);
- case EditAction::deleteSelection:
- return DidDeleteSelection(aSelection, info->collapsedAction, aResult);
- case EditAction::makeBasicBlock:
- case EditAction::indent:
- case EditAction::outdent:
- case EditAction::align:
- return DidMakeBasicBlock(aSelection, aInfo, aResult);
- case EditAction::setAbsolutePosition: {
- nsresult rv = DidMakeBasicBlock(aSelection, aInfo, aResult);
- NS_ENSURE_SUCCESS(rv, rv);
- return DidAbsolutePosition();
- }
- default:
- // pass through to TextEditRules
- return TextEditRules::DidDoAction(aSelection, aInfo, aResult);
- }
-}
-
-nsresult
-HTMLEditRules::GetListState(bool* aMixed,
- bool* aOL,
- bool* aUL,
- bool* aDL)
-{
- NS_ENSURE_TRUE(aMixed && aOL && aUL && aDL, NS_ERROR_NULL_POINTER);
- *aMixed = false;
- *aOL = false;
- *aUL = false;
- *aDL = false;
- bool bNonList = false;
-
- nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
- nsresult rv = GetListActionNodes(arrayOfNodes, EntireList::no,
- TouchContent::no);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Examine list type for nodes in selection.
- for (const auto& curNode : arrayOfNodes) {
- if (!curNode->IsElement()) {
- bNonList = true;
- } else if (curNode->IsHTMLElement(nsGkAtoms::ul)) {
- *aUL = true;
- } else if (curNode->IsHTMLElement(nsGkAtoms::ol)) {
- *aOL = true;
- } else if (curNode->IsHTMLElement(nsGkAtoms::li)) {
- if (dom::Element* parent = curNode->GetParentElement()) {
- if (parent->IsHTMLElement(nsGkAtoms::ul)) {
- *aUL = true;
- } else if (parent->IsHTMLElement(nsGkAtoms::ol)) {
- *aOL = true;
- }
- }
- } else if (curNode->IsAnyOfHTMLElements(nsGkAtoms::dl,
- nsGkAtoms::dt,
- nsGkAtoms::dd)) {
- *aDL = true;
- } else {
- bNonList = true;
- }
- }
-
- // hokey arithmetic with booleans
- if ((*aUL + *aOL + *aDL + bNonList) > 1) {
- *aMixed = true;
- }
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::GetListItemState(bool* aMixed,
- bool* aLI,
- bool* aDT,
- bool* aDD)
-{
- NS_ENSURE_TRUE(aMixed && aLI && aDT && aDD, NS_ERROR_NULL_POINTER);
- *aMixed = false;
- *aLI = false;
- *aDT = false;
- *aDD = false;
- bool bNonList = false;
-
- nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
- nsresult rv = GetListActionNodes(arrayOfNodes, EntireList::no,
- TouchContent::no);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // examine list type for nodes in selection
- for (const auto& node : arrayOfNodes) {
- if (!node->IsElement()) {
- bNonList = true;
- } else if (node->IsAnyOfHTMLElements(nsGkAtoms::ul,
- nsGkAtoms::ol,
- nsGkAtoms::li)) {
- *aLI = true;
- } else if (node->IsHTMLElement(nsGkAtoms::dt)) {
- *aDT = true;
- } else if (node->IsHTMLElement(nsGkAtoms::dd)) {
- *aDD = true;
- } else if (node->IsHTMLElement(nsGkAtoms::dl)) {
- // need to look inside dl and see which types of items it has
- bool bDT, bDD;
- GetDefinitionListItemTypes(node->AsElement(), &bDT, &bDD);
- *aDT |= bDT;
- *aDD |= bDD;
- } else {
- bNonList = true;
- }
- }
-
- // hokey arithmetic with booleans
- if (*aDT + *aDD + bNonList > 1) {
- *aMixed = true;
- }
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::GetAlignment(bool* aMixed,
- nsIHTMLEditor::EAlignment* aAlign)
-{
- MOZ_ASSERT(aMixed && aAlign);
-
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- // For now, just return first alignment. We'll lie about if it's mixed.
- // This is for efficiency given that our current ui doesn't care if it's
- // mixed.
- // cmanske: NOT TRUE! We would like to pay attention to mixed state in Format
- // | Align submenu!
-
- // This routine assumes that alignment is done ONLY via divs
-
- // Default alignment is left
- *aMixed = false;
- *aAlign = nsIHTMLEditor::eLeft;
-
- // Get selection
- NS_ENSURE_STATE(htmlEditor->GetSelection());
- OwningNonNull<Selection> selection = *htmlEditor->GetSelection();
-
- // Get selection location
- NS_ENSURE_TRUE(htmlEditor->GetRoot(), NS_ERROR_FAILURE);
- OwningNonNull<Element> root = *htmlEditor->GetRoot();
-
- int32_t rootOffset = root->GetParentNode() ?
- root->GetParentNode()->IndexOf(root) : -1;
-
- NS_ENSURE_STATE(selection->GetRangeAt(0) &&
- selection->GetRangeAt(0)->GetStartParent());
- OwningNonNull<nsINode> parent = *selection->GetRangeAt(0)->GetStartParent();
- int32_t offset = selection->GetRangeAt(0)->StartOffset();
-
- // Is the selection collapsed?
- nsCOMPtr<nsINode> nodeToExamine;
- if (selection->Collapsed() || parent->GetAsText()) {
- // If selection is collapsed, we want to look at 'parent' and its ancestors
- // for divs with alignment on them. If we are in a text node, then that is
- // the node of interest.
- nodeToExamine = parent;
- } else if (parent->IsHTMLElement(nsGkAtoms::html) && offset == rootOffset) {
- // If we have selected the body, let's look at the first editable node
- nodeToExamine = htmlEditor->GetNextNode(parent, offset, true);
- } else {
- nsTArray<RefPtr<nsRange>> arrayOfRanges;
- GetPromotedRanges(selection, arrayOfRanges, EditAction::align);
-
- // Use these ranges to construct a list of nodes to act on.
- nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
- nsresult rv = GetNodesForOperation(arrayOfRanges, arrayOfNodes,
- EditAction::align, TouchContent::no);
- NS_ENSURE_SUCCESS(rv, rv);
- nodeToExamine = arrayOfNodes.SafeElementAt(0);
- }
-
- NS_ENSURE_TRUE(nodeToExamine, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<Element> blockParent = htmlEditor->GetBlock(*nodeToExamine);
-
- NS_ENSURE_TRUE(blockParent, NS_ERROR_FAILURE);
-
- if (htmlEditor->IsCSSEnabled() &&
- htmlEditor->mCSSEditUtils->IsCSSEditableProperty(blockParent, nullptr,
- nsGkAtoms::align)) {
- // We are in CSS mode and we know how to align this element with CSS
- nsAutoString value;
- // Let's get the value(s) of text-align or margin-left/margin-right
- htmlEditor->mCSSEditUtils->GetCSSEquivalentToHTMLInlineStyleSet(
- blockParent, nullptr, nsGkAtoms::align, value, CSSEditUtils::eComputed);
- if (value.EqualsLiteral("center") ||
- value.EqualsLiteral("-moz-center") ||
- value.EqualsLiteral("auto auto")) {
- *aAlign = nsIHTMLEditor::eCenter;
- return NS_OK;
- }
- if (value.EqualsLiteral("right") ||
- value.EqualsLiteral("-moz-right") ||
- value.EqualsLiteral("auto 0px")) {
- *aAlign = nsIHTMLEditor::eRight;
- return NS_OK;
- }
- if (value.EqualsLiteral("justify")) {
- *aAlign = nsIHTMLEditor::eJustify;
- return NS_OK;
- }
- *aAlign = nsIHTMLEditor::eLeft;
- return NS_OK;
- }
-
- // Check up the ladder for divs with alignment
- bool isFirstNodeToExamine = true;
- for (; nodeToExamine; nodeToExamine = nodeToExamine->GetParentNode()) {
- if (!isFirstNodeToExamine &&
- nodeToExamine->IsHTMLElement(nsGkAtoms::table)) {
- // The node to examine is a table and this is not the first node we
- // examine; let's break here to materialize the 'inline-block' behaviour
- // of html tables regarding to text alignment
- return NS_OK;
- }
- if (HTMLEditUtils::SupportsAlignAttr(GetAsDOMNode(nodeToExamine))) {
- // Check for alignment
- nsAutoString typeAttrVal;
- nodeToExamine->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::align,
- typeAttrVal);
- ToLowerCase(typeAttrVal);
- if (!typeAttrVal.IsEmpty()) {
- if (typeAttrVal.EqualsLiteral("center")) {
- *aAlign = nsIHTMLEditor::eCenter;
- } else if (typeAttrVal.EqualsLiteral("right")) {
- *aAlign = nsIHTMLEditor::eRight;
- } else if (typeAttrVal.EqualsLiteral("justify")) {
- *aAlign = nsIHTMLEditor::eJustify;
- } else {
- *aAlign = nsIHTMLEditor::eLeft;
- }
- return NS_OK;
- }
- }
- isFirstNodeToExamine = false;
- }
- return NS_OK;
-}
-
-static nsIAtom& MarginPropertyAtomForIndent(CSSEditUtils& aHTMLCSSUtils,
- nsINode& aNode)
-{
- nsAutoString direction;
- aHTMLCSSUtils.GetComputedProperty(aNode, *nsGkAtoms::direction, direction);
- return direction.EqualsLiteral("rtl") ?
- *nsGkAtoms::marginRight : *nsGkAtoms::marginLeft;
-}
-
-nsresult
-HTMLEditRules::GetIndentState(bool* aCanIndent,
- bool* aCanOutdent)
-{
- // XXX Looks like that this is implementation of
- // nsIHTMLEditor::getIndentState() however nobody calls this method
- // even with the interface method.
- NS_ENSURE_TRUE(aCanIndent && aCanOutdent, NS_ERROR_FAILURE);
- *aCanIndent = true;
- *aCanOutdent = false;
-
- // get selection
- NS_ENSURE_STATE(mHTMLEditor && mHTMLEditor->GetSelection());
- OwningNonNull<Selection> selection = *mHTMLEditor->GetSelection();
-
- // contruct a list of nodes to act on.
- nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
- nsresult rv = GetNodesFromSelection(*selection, EditAction::indent,
- arrayOfNodes, TouchContent::no);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // examine nodes in selection for blockquotes or list elements;
- // these we can outdent. Note that we return true for canOutdent
- // if *any* of the selection is outdentable, rather than all of it.
- NS_ENSURE_STATE(mHTMLEditor);
- bool useCSS = mHTMLEditor->IsCSSEnabled();
- for (auto& curNode : Reversed(arrayOfNodes)) {
- if (HTMLEditUtils::IsNodeThatCanOutdent(GetAsDOMNode(curNode))) {
- *aCanOutdent = true;
- break;
- } else if (useCSS) {
- // we are in CSS mode, indentation is done using the margin-left (or margin-right) property
- NS_ENSURE_STATE(mHTMLEditor);
- nsIAtom& marginProperty =
- MarginPropertyAtomForIndent(*mHTMLEditor->mCSSEditUtils, curNode);
- nsAutoString value;
- // retrieve its specified value
- NS_ENSURE_STATE(mHTMLEditor);
- mHTMLEditor->mCSSEditUtils->GetSpecifiedProperty(*curNode,
- marginProperty, value);
- float f;
- nsCOMPtr<nsIAtom> unit;
- // get its number part and its unit
- NS_ENSURE_STATE(mHTMLEditor);
- mHTMLEditor->mCSSEditUtils->ParseLength(value, &f, getter_AddRefs(unit));
- // if the number part is strictly positive, outdent is possible
- if (0 < f) {
- *aCanOutdent = true;
- break;
- }
- }
- }
-
- if (!*aCanOutdent) {
- // if we haven't found something to outdent yet, also check the parents
- // of selection endpoints. We might have a blockquote or list item
- // in the parent hierarchy.
-
- // gather up info we need for test
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<nsIDOMNode> parent, tmp, root = do_QueryInterface(mHTMLEditor->GetRoot());
- NS_ENSURE_TRUE(root, NS_ERROR_NULL_POINTER);
- int32_t selOffset;
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<Selection> selection = mHTMLEditor->GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- // test start parent hierarchy
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->GetStartNodeAndOffset(selection, getter_AddRefs(parent),
- &selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- while (parent && parent != root) {
- if (HTMLEditUtils::IsNodeThatCanOutdent(parent)) {
- *aCanOutdent = true;
- break;
- }
- tmp = parent;
- tmp->GetParentNode(getter_AddRefs(parent));
- }
-
- // test end parent hierarchy
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->GetEndNodeAndOffset(selection, getter_AddRefs(parent),
- &selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- while (parent && parent != root) {
- if (HTMLEditUtils::IsNodeThatCanOutdent(parent)) {
- *aCanOutdent = true;
- break;
- }
- tmp = parent;
- tmp->GetParentNode(getter_AddRefs(parent));
- }
- }
- return NS_OK;
-}
-
-
-nsresult
-HTMLEditRules::GetParagraphState(bool* aMixed,
- nsAString& outFormat)
-{
- // This routine is *heavily* tied to our ui choices in the paragraph
- // style popup. I can't see a way around that.
- NS_ENSURE_TRUE(aMixed, NS_ERROR_NULL_POINTER);
- *aMixed = true;
- outFormat.Truncate(0);
-
- bool bMixed = false;
- // using "x" as an uninitialized value, since "" is meaningful
- nsAutoString formatStr(NS_LITERAL_STRING("x"));
-
- nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
- nsresult rv = GetParagraphFormatNodes(arrayOfNodes, TouchContent::no);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // post process list. We need to replace any block nodes that are not format
- // nodes with their content. This is so we only have to look "up" the hierarchy
- // to find format nodes, instead of both up and down.
- for (int32_t i = arrayOfNodes.Length() - 1; i >= 0; i--) {
- auto& curNode = arrayOfNodes[i];
- nsAutoString format;
- // if it is a known format node we have it easy
- if (IsBlockNode(curNode) && !HTMLEditUtils::IsFormatNode(curNode)) {
- // arrayOfNodes.RemoveObject(curNode);
- rv = AppendInnerFormatNodes(arrayOfNodes, curNode);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- // we might have an empty node list. if so, find selection parent
- // and put that on the list
- if (arrayOfNodes.IsEmpty()) {
- nsCOMPtr<nsINode> selNode;
- int32_t selOffset;
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<Selection> selection = mHTMLEditor->GetSelection();
- NS_ENSURE_STATE(selection);
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->GetStartNodeAndOffset(selection, getter_AddRefs(selNode),
- &selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(selNode, NS_ERROR_NULL_POINTER);
- arrayOfNodes.AppendElement(*selNode);
- }
-
- // remember root node
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<nsIDOMElement> rootElem = do_QueryInterface(mHTMLEditor->GetRoot());
- NS_ENSURE_TRUE(rootElem, NS_ERROR_NULL_POINTER);
-
- // loop through the nodes in selection and examine their paragraph format
- for (auto& curNode : Reversed(arrayOfNodes)) {
- nsAutoString format;
- // if it is a known format node we have it easy
- if (HTMLEditUtils::IsFormatNode(curNode)) {
- GetFormatString(GetAsDOMNode(curNode), format);
- } else if (IsBlockNode(curNode)) {
- // this is a div or some other non-format block.
- // we should ignore it. Its children were appended to this list
- // by AppendInnerFormatNodes() call above. We will get needed
- // info when we examine them instead.
- continue;
- } else {
- nsCOMPtr<nsIDOMNode> node, tmp = GetAsDOMNode(curNode);
- tmp->GetParentNode(getter_AddRefs(node));
- while (node) {
- if (node == rootElem) {
- format.Truncate(0);
- break;
- } else if (HTMLEditUtils::IsFormatNode(node)) {
- GetFormatString(node, format);
- break;
- }
- // else keep looking up
- tmp = node;
- tmp->GetParentNode(getter_AddRefs(node));
- }
- }
-
- // if this is the first node, we've found, remember it as the format
- if (formatStr.EqualsLiteral("x")) {
- formatStr = format;
- }
- // else make sure it matches previously found format
- else if (format != formatStr) {
- bMixed = true;
- break;
- }
- }
-
- *aMixed = bMixed;
- outFormat = formatStr;
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::AppendInnerFormatNodes(nsTArray<OwningNonNull<nsINode>>& aArray,
- nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
-
- // we only need to place any one inline inside this node onto
- // the list. They are all the same for purposes of determining
- // paragraph style. We use foundInline to track this as we are
- // going through the children in the loop below.
- bool foundInline = false;
- for (nsIContent* child = aNode->GetFirstChild();
- child;
- child = child->GetNextSibling()) {
- bool isBlock = IsBlockNode(*child);
- bool isFormat = HTMLEditUtils::IsFormatNode(child);
- if (isBlock && !isFormat) {
- // if it's a div, etc., recurse
- AppendInnerFormatNodes(aArray, child);
- } else if (isFormat) {
- aArray.AppendElement(*child);
- } else if (!foundInline) {
- // if this is the first inline we've found, use it
- foundInline = true;
- aArray.AppendElement(*child);
- }
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::GetFormatString(nsIDOMNode* aNode,
- nsAString& outFormat)
-{
- NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
-
- if (HTMLEditUtils::IsFormatNode(aNode)) {
- nsCOMPtr<nsIAtom> atom = EditorBase::GetTag(aNode);
- atom->ToString(outFormat);
- } else {
- outFormat.Truncate();
- }
- return NS_OK;
-}
-
-void
-HTMLEditRules::WillInsert(Selection& aSelection,
- bool* aCancel)
-{
- MOZ_ASSERT(aCancel);
-
- TextEditRules::WillInsert(aSelection, aCancel);
-
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- // Adjust selection to prevent insertion after a moz-BR. This next only
- // works for collapsed selections right now, because selection is a pain to
- // work with when not collapsed. (no good way to extend start or end of
- // selection), so we ignore those types of selections.
- if (!aSelection.Collapsed()) {
- return;
- }
-
- // If we are after a mozBR in the same block, then move selection to be
- // before it
- NS_ENSURE_TRUE_VOID(aSelection.GetRangeAt(0) &&
- aSelection.GetRangeAt(0)->GetStartParent());
- OwningNonNull<nsINode> selNode = *aSelection.GetRangeAt(0)->GetStartParent();
- int32_t selOffset = aSelection.GetRangeAt(0)->StartOffset();
-
- // Get prior node
- nsCOMPtr<nsIContent> priorNode = htmlEditor->GetPriorHTMLNode(selNode,
- selOffset);
- if (priorNode && TextEditUtils::IsMozBR(priorNode)) {
- nsCOMPtr<Element> block1 = htmlEditor->GetBlock(selNode);
- nsCOMPtr<Element> block2 = htmlEditor->GetBlockNodeParent(priorNode);
-
- if (block1 && block1 == block2) {
- // If we are here then the selection is right after a mozBR that is in
- // the same block as the selection. We need to move the selection start
- // to be before the mozBR.
- selNode = priorNode->GetParentNode();
- selOffset = selNode->IndexOf(priorNode);
- nsresult rv = aSelection.Collapse(selNode, selOffset);
- NS_ENSURE_SUCCESS_VOID(rv);
- }
- }
-
- if (mDidDeleteSelection &&
- (mTheAction == EditAction::insertText ||
- mTheAction == EditAction::insertIMEText ||
- mTheAction == EditAction::deleteSelection)) {
- nsresult rv = ReapplyCachedStyles();
- NS_ENSURE_SUCCESS_VOID(rv);
- }
- // For most actions we want to clear the cached styles, but there are
- // exceptions
- if (!IsStyleCachePreservingAction(mTheAction)) {
- ClearCachedStyles();
- }
-}
-
-nsresult
-HTMLEditRules::WillInsertText(EditAction aAction,
- Selection* aSelection,
- bool* aCancel,
- bool* aHandled,
- const nsAString* inString,
- nsAString* outString,
- int32_t aMaxLength)
-{
- if (!aSelection || !aCancel || !aHandled) {
- return NS_ERROR_NULL_POINTER;
- }
-
- if (inString->IsEmpty() && aAction != EditAction::insertIMEText) {
- // HACK: this is a fix for bug 19395
- // I can't outlaw all empty insertions
- // because IME transaction depend on them
- // There is more work to do to make the
- // world safe for IME.
- *aCancel = true;
- *aHandled = false;
- return NS_OK;
- }
-
- // initialize out param
- *aCancel = false;
- *aHandled = true;
- // If the selection isn't collapsed, delete it. Don't delete existing inline
- // tags, because we're hopefully going to insert text (bug 787432).
- if (!aSelection->Collapsed()) {
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->DeleteSelection(nsIEditor::eNone, nsIEditor::eNoStrip);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- WillInsert(*aSelection, aCancel);
- // initialize out param
- // we want to ignore result of WillInsert()
- *aCancel = false;
-
- // we need to get the doc
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<nsIDocument> doc = mHTMLEditor->GetDocument();
- NS_ENSURE_STATE(doc);
-
- // for every property that is set, insert a new inline style node
- nsresult rv = CreateStyleForInsertText(*aSelection, *doc);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // get the (collapsed) selection location
- NS_ENSURE_STATE(mHTMLEditor);
- NS_ENSURE_STATE(aSelection->GetRangeAt(0));
- nsCOMPtr<nsINode> selNode = aSelection->GetRangeAt(0)->GetStartParent();
- int32_t selOffset = aSelection->GetRangeAt(0)->StartOffset();
- NS_ENSURE_STATE(selNode);
-
- // dont put text in places that can't have it
- NS_ENSURE_STATE(mHTMLEditor);
- if (!mHTMLEditor->IsTextNode(selNode) &&
- (!mHTMLEditor || !mHTMLEditor->CanContainTag(*selNode,
- *nsGkAtoms::textTagName))) {
- return NS_ERROR_FAILURE;
- }
-
- if (aAction == EditAction::insertIMEText) {
- // Right now the WSRunObject code bails on empty strings, but IME needs
- // the InsertTextImpl() call to still happen since empty strings are meaningful there.
- NS_ENSURE_STATE(mHTMLEditor);
- // If there is one or more IME selections, its minimum offset should be
- // the insertion point.
- int32_t IMESelectionOffset =
- mHTMLEditor->GetIMESelectionStartOffsetIn(selNode);
- if (IMESelectionOffset >= 0) {
- selOffset = IMESelectionOffset;
- }
- if (inString->IsEmpty()) {
- rv = mHTMLEditor->InsertTextImpl(*inString, address_of(selNode),
- &selOffset, doc);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- WSRunObject wsObj(mHTMLEditor, selNode, selOffset);
- rv = wsObj.InsertText(*inString, address_of(selNode), &selOffset, doc);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- }
- // aAction == kInsertText
- else {
- // find where we are
- nsCOMPtr<nsINode> curNode = selNode;
- int32_t curOffset = selOffset;
-
- // is our text going to be PREformatted?
- // We remember this so that we know how to handle tabs.
- bool isPRE;
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->IsPreformatted(GetAsDOMNode(selNode), &isPRE);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // turn off the edit listener: we know how to
- // build the "doc changed range" ourselves, and it's
- // must faster to do it once here than to track all
- // the changes one at a time.
- AutoLockListener lockit(&mListenerEnabled);
-
- // don't spaz my selection in subtransactions
- NS_ENSURE_STATE(mHTMLEditor);
- AutoTransactionsConserveSelection dontSpazMySelection(mHTMLEditor);
- nsAutoString tString(*inString);
- const char16_t *unicodeBuf = tString.get();
- int32_t pos = 0;
- NS_NAMED_LITERAL_STRING(newlineStr, LFSTR);
-
- // for efficiency, break out the pre case separately. This is because
- // its a lot cheaper to search the input string for only newlines than
- // it is to search for both tabs and newlines.
- if (isPRE || IsPlaintextEditor()) {
- while (unicodeBuf && pos != -1 &&
- pos < static_cast<int32_t>(inString->Length())) {
- int32_t oldPos = pos;
- int32_t subStrLen;
- pos = tString.FindChar(nsCRT::LF, oldPos);
-
- if (pos != -1) {
- subStrLen = pos - oldPos;
- // if first char is newline, then use just it
- if (!subStrLen) {
- subStrLen = 1;
- }
- } else {
- subStrLen = tString.Length() - oldPos;
- pos = tString.Length();
- }
-
- nsDependentSubstring subStr(tString, oldPos, subStrLen);
-
- // is it a return?
- if (subStr.Equals(newlineStr)) {
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<Element> br =
- mHTMLEditor->CreateBRImpl(address_of(curNode), &curOffset,
- nsIEditor::eNone);
- NS_ENSURE_STATE(br);
- pos++;
- } else {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->InsertTextImpl(subStr, address_of(curNode),
- &curOffset, doc);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- } else {
- NS_NAMED_LITERAL_STRING(tabStr, "\t");
- NS_NAMED_LITERAL_STRING(spacesStr, " ");
- char specialChars[] = {TAB, nsCRT::LF, 0};
- while (unicodeBuf && pos != -1 &&
- pos < static_cast<int32_t>(inString->Length())) {
- int32_t oldPos = pos;
- int32_t subStrLen;
- pos = tString.FindCharInSet(specialChars, oldPos);
-
- if (pos != -1) {
- subStrLen = pos - oldPos;
- // if first char is newline, then use just it
- if (!subStrLen) {
- subStrLen = 1;
- }
- } else {
- subStrLen = tString.Length() - oldPos;
- pos = tString.Length();
- }
-
- nsDependentSubstring subStr(tString, oldPos, subStrLen);
- NS_ENSURE_STATE(mHTMLEditor);
- WSRunObject wsObj(mHTMLEditor, curNode, curOffset);
-
- // is it a tab?
- if (subStr.Equals(tabStr)) {
- rv =
- wsObj.InsertText(spacesStr, address_of(curNode), &curOffset, doc);
- NS_ENSURE_SUCCESS(rv, rv);
- pos++;
- }
- // is it a return?
- else if (subStr.Equals(newlineStr)) {
- nsCOMPtr<Element> br = wsObj.InsertBreak(address_of(curNode),
- &curOffset,
- nsIEditor::eNone);
- NS_ENSURE_TRUE(br, NS_ERROR_FAILURE);
- pos++;
- } else {
- rv = wsObj.InsertText(subStr, address_of(curNode), &curOffset, doc);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- }
- aSelection->SetInterlinePosition(false);
- if (curNode) aSelection->Collapse(curNode, curOffset);
- // manually update the doc changed range so that AfterEdit will clean up
- // the correct portion of the document.
- if (!mDocChangeRange) {
- mDocChangeRange = new nsRange(selNode);
- }
-
- if (curNode) {
- rv = mDocChangeRange->SetStartAndEnd(selNode, selOffset,
- curNode, curOffset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- rv = mDocChangeRange->CollapseTo(selNode, selOffset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::WillLoadHTML(Selection* aSelection,
- bool* aCancel)
-{
- NS_ENSURE_TRUE(aSelection && aCancel, NS_ERROR_NULL_POINTER);
-
- *aCancel = false;
-
- // Delete mBogusNode if it exists. If we really need one,
- // it will be added during post-processing in AfterEditInner().
-
- if (mBogusNode) {
- mTextEditor->DeleteNode(mBogusNode);
- mBogusNode = nullptr;
- }
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::WillInsertBreak(Selection& aSelection,
- bool* aCancel,
- bool* aHandled)
-{
- MOZ_ASSERT(aCancel && aHandled);
- *aCancel = false;
- *aHandled = false;
-
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- // If the selection isn't collapsed, delete it.
- if (!aSelection.Collapsed()) {
- nsresult rv =
- htmlEditor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- WillInsert(aSelection, aCancel);
-
- // Initialize out param. We want to ignore result of WillInsert().
- *aCancel = false;
-
- // Split any mailcites in the way. Should we abort this if we encounter
- // table cell boundaries?
- if (IsMailEditor()) {
- nsresult rv = SplitMailCites(&aSelection, aHandled);
- NS_ENSURE_SUCCESS(rv, rv);
- if (*aHandled) {
- return NS_OK;
- }
- }
-
- // Smart splitting rules
- NS_ENSURE_TRUE(aSelection.GetRangeAt(0) &&
- aSelection.GetRangeAt(0)->GetStartParent(),
- NS_ERROR_FAILURE);
- OwningNonNull<nsINode> node = *aSelection.GetRangeAt(0)->GetStartParent();
- int32_t offset = aSelection.GetRangeAt(0)->StartOffset();
-
- // Do nothing if the node is read-only
- if (!htmlEditor->IsModifiableNode(node)) {
- *aCancel = true;
- return NS_OK;
- }
-
- // Identify the block
- nsCOMPtr<Element> blockParent = htmlEditor->GetBlock(node);
- NS_ENSURE_TRUE(blockParent, NS_ERROR_FAILURE);
-
- // When there is an active editing host (the <body> if it's in designMode)
- // and a block which becomes the parent of line breaker is in it, do the
- // standard thing.
- nsCOMPtr<Element> host = htmlEditor->GetActiveEditingHost();
- if (host && !EditorUtils::IsDescendantOf(blockParent, host)) {
- nsresult rv = StandardBreakImpl(node, offset, aSelection);
- NS_ENSURE_SUCCESS(rv, rv);
- *aHandled = true;
- return NS_OK;
- }
-
- // If block is empty, populate with br. (For example, imagine a div that
- // contains the word "text". The user selects "text" and types return.
- // "Text" is deleted leaving an empty block. We want to put in one br to
- // make block have a line. Then code further below will put in a second br.)
- bool isEmpty;
- IsEmptyBlock(*blockParent, &isEmpty);
- if (isEmpty) {
- nsCOMPtr<Element> br = htmlEditor->CreateBR(blockParent,
- blockParent->Length());
- NS_ENSURE_STATE(br);
- }
-
- nsCOMPtr<Element> listItem = IsInListItem(blockParent);
- if (listItem && listItem != host) {
- ReturnInListItem(aSelection, *listItem, node, offset);
- *aHandled = true;
- return NS_OK;
- } else if (HTMLEditUtils::IsHeader(*blockParent)) {
- // Headers: close (or split) header
- ReturnInHeader(aSelection, *blockParent, node, offset);
- *aHandled = true;
- return NS_OK;
- } else if (blockParent->IsHTMLElement(nsGkAtoms::p)) {
- // Paragraphs: special rules to look for <br>s
- nsresult rv =
- ReturnInParagraph(&aSelection, GetAsDOMNode(blockParent),
- GetAsDOMNode(node), offset, aCancel, aHandled);
- NS_ENSURE_SUCCESS(rv, rv);
- // Fall through, we may not have handled it in ReturnInParagraph()
- }
-
- // If not already handled then do the standard thing
- if (!(*aHandled)) {
- *aHandled = true;
- return StandardBreakImpl(node, offset, aSelection);
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::StandardBreakImpl(nsINode& aNode,
- int32_t aOffset,
- Selection& aSelection)
-{
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- nsCOMPtr<Element> brNode;
- bool bAfterBlock = false;
- bool bBeforeBlock = false;
- nsCOMPtr<nsINode> node = &aNode;
-
- if (IsPlaintextEditor()) {
- brNode = htmlEditor->CreateBR(node, aOffset);
- NS_ENSURE_STATE(brNode);
- } else {
- WSRunObject wsObj(htmlEditor, node, aOffset);
- int32_t visOffset = 0;
- WSType wsType;
- nsCOMPtr<nsINode> visNode;
- wsObj.PriorVisibleNode(node, aOffset, address_of(visNode),
- &visOffset, &wsType);
- if (wsType & WSType::block) {
- bAfterBlock = true;
- }
- wsObj.NextVisibleNode(node, aOffset, address_of(visNode),
- &visOffset, &wsType);
- if (wsType & WSType::block) {
- bBeforeBlock = true;
- }
- nsCOMPtr<nsIDOMNode> linkDOMNode;
- if (htmlEditor->IsInLink(GetAsDOMNode(node), address_of(linkDOMNode))) {
- // Split the link
- nsCOMPtr<Element> linkNode = do_QueryInterface(linkDOMNode);
- NS_ENSURE_STATE(linkNode || !linkDOMNode);
- nsCOMPtr<nsINode> linkParent = linkNode->GetParentNode();
- aOffset = htmlEditor->SplitNodeDeep(*linkNode, *node->AsContent(),
- aOffset,
- HTMLEditor::EmptyContainers::no);
- NS_ENSURE_STATE(aOffset != -1);
- node = linkParent;
- }
- brNode = wsObj.InsertBreak(address_of(node), &aOffset, nsIEditor::eNone);
- NS_ENSURE_TRUE(brNode, NS_ERROR_FAILURE);
- }
- node = brNode->GetParentNode();
- NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
- int32_t offset = node->IndexOf(brNode);
- if (bAfterBlock && bBeforeBlock) {
- // We just placed a br between block boundaries. This is the one case
- // where we want the selection to be before the br we just placed, as the
- // br will be on a new line, rather than at end of prior line.
- aSelection.SetInterlinePosition(true);
- nsresult rv = aSelection.Collapse(node, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- WSRunObject wsObj(htmlEditor, node, offset + 1);
- nsCOMPtr<nsINode> secondBR;
- int32_t visOffset = 0;
- WSType wsType;
- wsObj.NextVisibleNode(node, offset + 1, address_of(secondBR),
- &visOffset, &wsType);
- if (wsType == WSType::br) {
- // The next thing after the break we inserted is another break. Move the
- // second break to be the first break's sibling. This will prevent them
- // from being in different inline nodes, which would break
- // SetInterlinePosition(). It will also assure that if the user clicks
- // away and then clicks back on their new blank line, they will still get
- // the style from the line above.
- nsCOMPtr<nsINode> brParent = secondBR->GetParentNode();
- int32_t brOffset = brParent ? brParent->IndexOf(secondBR) : -1;
- if (brParent != node || brOffset != offset + 1) {
- nsresult rv =
- htmlEditor->MoveNode(secondBR->AsContent(), node, offset + 1);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- // SetInterlinePosition(true) means we want the caret to stick to the
- // content on the "right". We want the caret to stick to whatever is past
- // the break. This is because the break is on the same line we were on,
- // but the next content will be on the following line.
-
- // An exception to this is if the break has a next sibling that is a block
- // node. Then we stick to the left to avoid an uber caret.
- nsCOMPtr<nsIContent> siblingNode = brNode->GetNextSibling();
- if (siblingNode && IsBlockNode(*siblingNode)) {
- aSelection.SetInterlinePosition(false);
- } else {
- aSelection.SetInterlinePosition(true);
- }
- nsresult rv = aSelection.Collapse(node, offset + 1);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::DidInsertBreak(Selection* aSelection,
- nsresult aResult)
-{
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::SplitMailCites(Selection* aSelection,
- bool* aHandled)
-{
- NS_ENSURE_TRUE(aSelection && aHandled, NS_ERROR_NULL_POINTER);
- nsCOMPtr<nsIContent> leftCite, rightCite;
- nsCOMPtr<nsINode> selNode;
- nsCOMPtr<Element> citeNode;
- int32_t selOffset;
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(selNode),
- &selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- citeNode = GetTopEnclosingMailCite(*selNode);
- if (citeNode) {
- // If our selection is just before a break, nudge it to be
- // just after it. This does two things for us. It saves us the trouble of having to add
- // a break here ourselves to preserve the "blockness" of the inline span mailquote
- // (in the inline case), and :
- // it means the break won't end up making an empty line that happens to be inside a
- // mailquote (in either inline or block case).
- // The latter can confuse a user if they click there and start typing,
- // because being in the mailquote may affect wrapping behavior, or font color, etc.
- NS_ENSURE_STATE(mHTMLEditor);
- WSRunObject wsObj(mHTMLEditor, selNode, selOffset);
- nsCOMPtr<nsINode> visNode;
- int32_t visOffset=0;
- WSType wsType;
- wsObj.NextVisibleNode(selNode, selOffset, address_of(visNode),
- &visOffset, &wsType);
- if (wsType == WSType::br) {
- // ok, we are just before a break. is it inside the mailquote?
- if (visNode != citeNode && citeNode->Contains(visNode)) {
- // it is. so lets reset our selection to be just after it.
- NS_ENSURE_STATE(mHTMLEditor);
- selNode = mHTMLEditor->GetNodeLocation(visNode, &selOffset);
- ++selOffset;
- }
- }
-
- NS_ENSURE_STATE(mHTMLEditor);
- NS_ENSURE_STATE(selNode->IsContent());
- int32_t newOffset = mHTMLEditor->SplitNodeDeep(*citeNode,
- *selNode->AsContent(), selOffset, HTMLEditor::EmptyContainers::no,
- getter_AddRefs(leftCite), getter_AddRefs(rightCite));
- NS_ENSURE_STATE(newOffset != -1);
-
- // Add an invisible <br> to the end of the left part if it was a <span> of
- // style="display: block". This is important, since when serialising the
- // cite to plain text, the span which caused the visual break is discarded.
- // So the added <br> will guarantee that the serialiser will insert a
- // break where the user saw one.
- if (leftCite &&
- leftCite->IsHTMLElement(nsGkAtoms::span) &&
- leftCite->GetPrimaryFrame()->IsFrameOfType(nsIFrame::eBlockFrame)) {
- nsCOMPtr<nsINode> lastChild = leftCite->GetLastChild();
- if (lastChild && !lastChild->IsHTMLElement(nsGkAtoms::br)) {
- // We ignore the result here.
- nsCOMPtr<Element> invisBR =
- mHTMLEditor->CreateBR(leftCite, leftCite->Length());
- }
- }
-
- selNode = citeNode->GetParentNode();
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<Element> brNode = mHTMLEditor->CreateBR(selNode, newOffset);
- NS_ENSURE_STATE(brNode);
-
- // want selection before the break, and on same line
- aSelection->SetInterlinePosition(true);
- rv = aSelection->Collapse(selNode, newOffset);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // if citeNode wasn't a block, we might also want another break before it.
- // We need to examine the content both before the br we just added and also
- // just after it. If we don't have another br or block boundary adjacent,
- // then we will need a 2nd br added to achieve blank line that user expects.
- if (IsInlineNode(*citeNode)) {
- NS_ENSURE_STATE(mHTMLEditor);
- WSRunObject wsObj(mHTMLEditor, selNode, newOffset);
- nsCOMPtr<nsINode> visNode;
- int32_t visOffset=0;
- WSType wsType;
- wsObj.PriorVisibleNode(selNode, newOffset, address_of(visNode),
- &visOffset, &wsType);
- if (wsType == WSType::normalWS || wsType == WSType::text ||
- wsType == WSType::special) {
- NS_ENSURE_STATE(mHTMLEditor);
- WSRunObject wsObjAfterBR(mHTMLEditor, selNode, newOffset+1);
- wsObjAfterBR.NextVisibleNode(selNode, newOffset + 1,
- address_of(visNode), &visOffset, &wsType);
- if (wsType == WSType::normalWS || wsType == WSType::text ||
- wsType == WSType::special ||
- // In case we're at the very end.
- wsType == WSType::thisBlock) {
- NS_ENSURE_STATE(mHTMLEditor);
- brNode = mHTMLEditor->CreateBR(selNode, newOffset);
- NS_ENSURE_STATE(brNode);
- }
- }
- }
-
- // delete any empty cites
- bool bEmptyCite = false;
- if (leftCite) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->IsEmptyNode(leftCite, &bEmptyCite, true, false);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- if (bEmptyCite) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->DeleteNode(leftCite);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- }
-
- if (rightCite) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->IsEmptyNode(rightCite, &bEmptyCite, true, false);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- if (bEmptyCite) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->DeleteNode(rightCite);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- }
- *aHandled = true;
- }
- return NS_OK;
-}
-
-
-nsresult
-HTMLEditRules::WillDeleteSelection(Selection* aSelection,
- nsIEditor::EDirection aAction,
- nsIEditor::EStripWrappers aStripWrappers,
- bool* aCancel,
- bool* aHandled)
-{
- MOZ_ASSERT(aStripWrappers == nsIEditor::eStrip ||
- aStripWrappers == nsIEditor::eNoStrip);
-
- if (!aSelection || !aCancel || !aHandled) {
- return NS_ERROR_NULL_POINTER;
- }
- // Initialize out params
- *aCancel = false;
- *aHandled = false;
-
- // Remember that we did a selection deletion. Used by CreateStyleForInsertText()
- mDidDeleteSelection = true;
-
- // If there is only bogus content, cancel the operation
- if (mBogusNode) {
- *aCancel = true;
- return NS_OK;
- }
-
- // First check for table selection mode. If so, hand off to table editor.
- nsCOMPtr<nsIDOMElement> cell;
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->GetFirstSelectedCell(nullptr, getter_AddRefs(cell));
- if (NS_SUCCEEDED(rv) && cell) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->DeleteTableCellContents();
- *aHandled = true;
- return rv;
- }
- cell = nullptr;
-
- // origCollapsed is used later to determine whether we should join blocks. We
- // don't really care about bCollapsed because it will be modified by
- // ExtendSelectionForDelete later. TryToJoinBlocks() should happen if the
- // original selection is collapsed and the cursor is at the end of a block
- // element, in which case ExtendSelectionForDelete would always make the
- // selection not collapsed.
- bool bCollapsed = aSelection->Collapsed();
- bool join = false;
- bool origCollapsed = bCollapsed;
-
- nsCOMPtr<nsINode> selNode;
- int32_t selOffset;
-
- NS_ENSURE_STATE(aSelection->GetRangeAt(0));
- nsCOMPtr<nsINode> startNode = aSelection->GetRangeAt(0)->GetStartParent();
- int32_t startOffset = aSelection->GetRangeAt(0)->StartOffset();
- NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
-
- if (bCollapsed) {
- // If we are inside an empty block, delete it.
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<Element> host = mHTMLEditor->GetActiveEditingHost();
- NS_ENSURE_TRUE(host, NS_ERROR_FAILURE);
- rv = CheckForEmptyBlock(startNode, host, aSelection, aAction, aHandled);
- NS_ENSURE_SUCCESS(rv, rv);
- if (*aHandled) {
- return NS_OK;
- }
-
- // Test for distance between caret and text that will be deleted
- rv = CheckBidiLevelForDeletion(aSelection, GetAsDOMNode(startNode),
- startOffset, aAction, aCancel);
- NS_ENSURE_SUCCESS(rv, rv);
- if (*aCancel) {
- return NS_OK;
- }
-
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->ExtendSelectionForDelete(aSelection, &aAction);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // We should delete nothing.
- if (aAction == nsIEditor::eNone) {
- return NS_OK;
- }
-
- // ExtendSelectionForDelete() may have changed the selection, update it
- NS_ENSURE_STATE(aSelection->GetRangeAt(0));
- startNode = aSelection->GetRangeAt(0)->GetStartParent();
- startOffset = aSelection->GetRangeAt(0)->StartOffset();
- NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
-
- bCollapsed = aSelection->Collapsed();
- }
-
- if (bCollapsed) {
- // What's in the direction we are deleting?
- NS_ENSURE_STATE(mHTMLEditor);
- WSRunObject wsObj(mHTMLEditor, startNode, startOffset);
- nsCOMPtr<nsINode> visNode;
- int32_t visOffset;
- WSType wsType;
-
- // Find next visible node
- if (aAction == nsIEditor::eNext) {
- wsObj.NextVisibleNode(startNode, startOffset, address_of(visNode),
- &visOffset, &wsType);
- } else {
- wsObj.PriorVisibleNode(startNode, startOffset, address_of(visNode),
- &visOffset, &wsType);
- }
-
- if (!visNode) {
- // Can't find anything to delete!
- *aCancel = true;
- // XXX This is the result of mHTMLEditor->GetFirstSelectedCell().
- // The value could be both an error and NS_OK.
- return rv;
- }
-
- if (wsType == WSType::normalWS) {
- // We found some visible ws to delete. Let ws code handle it.
- *aHandled = true;
- if (aAction == nsIEditor::eNext) {
- rv = wsObj.DeleteWSForward();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- rv = wsObj.DeleteWSBackward();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- return InsertBRIfNeeded(aSelection);
- }
-
- if (wsType == WSType::text) {
- // Found normal text to delete.
- OwningNonNull<Text> nodeAsText = *visNode->GetAsText();
- int32_t so = visOffset;
- int32_t eo = visOffset + 1;
- if (aAction == nsIEditor::ePrevious) {
- if (!so) {
- return NS_ERROR_UNEXPECTED;
- }
- so--;
- eo--;
- // Bug 1068979: delete both codepoints if surrogate pair
- if (so > 0) {
- const nsTextFragment *text = nodeAsText->GetText();
- if (NS_IS_LOW_SURROGATE(text->CharAt(so)) &&
- NS_IS_HIGH_SURROGATE(text->CharAt(so - 1))) {
- so--;
- }
- }
- } else {
- RefPtr<nsRange> range = aSelection->GetRangeAt(0);
- NS_ENSURE_STATE(range);
-
- NS_ASSERTION(range->GetStartParent() == visNode,
- "selection start not in visNode");
- NS_ASSERTION(range->GetEndParent() == visNode,
- "selection end not in visNode");
-
- so = range->StartOffset();
- eo = range->EndOffset();
- }
- NS_ENSURE_STATE(mHTMLEditor);
- rv = WSRunObject::PrepareToDeleteRange(mHTMLEditor, address_of(visNode),
- &so, address_of(visNode), &eo);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_STATE(mHTMLEditor);
- *aHandled = true;
- rv = mHTMLEditor->DeleteText(nodeAsText, std::min(so, eo),
- DeprecatedAbs(eo - so));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // XXX When Backspace key is pressed, Chromium removes following empty
- // text nodes when removing the last character of the non-empty text
- // node. However, Edge never removes empty text nodes even if
- // selection is in the following empty text node(s). For now, we
- // should keep our traditional behavior same as Edge for backward
- // compatibility.
- // XXX When Delete key is pressed, Edge removes all preceding empty
- // text nodes when removing the first character of the non-empty
- // text node. Chromium removes only selected empty text node and
- // following empty text nodes and the first character of the
- // non-empty text node. For now, we should keep our traditional
- // behavior same as Chromium for backward compatibility.
-
- DeleteNodeIfCollapsedText(nodeAsText);
-
- rv = InsertBRIfNeeded(aSelection);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Remember that we did a ranged delete for the benefit of
- // AfterEditInner().
- mDidRangedDelete = true;
-
- return NS_OK;
- }
-
- if (wsType == WSType::special || wsType == WSType::br ||
- visNode->IsHTMLElement(nsGkAtoms::hr)) {
- // Short circuit for invisible breaks. delete them and recurse.
- if (visNode->IsHTMLElement(nsGkAtoms::br) &&
- (!mHTMLEditor || !mHTMLEditor->IsVisBreak(visNode))) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->DeleteNode(visNode);
- NS_ENSURE_SUCCESS(rv, rv);
- return WillDeleteSelection(aSelection, aAction, aStripWrappers,
- aCancel, aHandled);
- }
-
- // Special handling for backspace when positioned after <hr>
- if (aAction == nsIEditor::ePrevious &&
- visNode->IsHTMLElement(nsGkAtoms::hr)) {
- // Only if the caret is positioned at the end-of-hr-line position, we
- // want to delete the <hr>.
- //
- // In other words, we only want to delete, if our selection position
- // (indicated by startNode and startOffset) is the position directly
- // after the <hr>, on the same line as the <hr>.
- //
- // To detect this case we check:
- // startNode == parentOfVisNode
- // and
- // startOffset -1 == visNodeOffsetToVisNodeParent
- // and
- // interline position is false (left)
- //
- // In any other case we set the position to startnode -1 and
- // interlineposition to false, only moving the caret to the
- // end-of-hr-line position.
- bool moveOnly = true;
-
- selNode = visNode->GetParentNode();
- selOffset = selNode ? selNode->IndexOf(visNode) : -1;
-
- bool interLineIsRight;
- rv = aSelection->GetInterlinePosition(&interLineIsRight);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (startNode == selNode && startOffset - 1 == selOffset &&
- !interLineIsRight) {
- moveOnly = false;
- }
-
- if (moveOnly) {
- // Go to the position after the <hr>, but to the end of the <hr> line
- // by setting the interline position to left.
- ++selOffset;
- aSelection->Collapse(selNode, selOffset);
- aSelection->SetInterlinePosition(false);
- mDidExplicitlySetInterline = true;
- *aHandled = true;
-
- // There is one exception to the move only case. If the <hr> is
- // followed by a <br> we want to delete the <br>.
-
- WSType otherWSType;
- nsCOMPtr<nsINode> otherNode;
- int32_t otherOffset;
-
- wsObj.NextVisibleNode(startNode, startOffset, address_of(otherNode),
- &otherOffset, &otherWSType);
-
- if (otherWSType == WSType::br) {
- // Delete the <br>
-
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<nsIContent> otherContent(do_QueryInterface(otherNode));
- rv = WSRunObject::PrepareToDeleteNode(mHTMLEditor, otherContent);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->DeleteNode(otherNode);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
- }
- // Else continue with normal delete code
- }
-
- // Found break or image, or hr.
- NS_ENSURE_STATE(mHTMLEditor);
- NS_ENSURE_STATE(visNode->IsContent());
- rv = WSRunObject::PrepareToDeleteNode(mHTMLEditor, visNode->AsContent());
- NS_ENSURE_SUCCESS(rv, rv);
- // Remember sibling to visnode, if any
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<nsIContent> sibling = mHTMLEditor->GetPriorHTMLSibling(visNode);
- // Delete the node, and join like nodes if appropriate
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->DeleteNode(visNode);
- NS_ENSURE_SUCCESS(rv, rv);
- // We did something, so let's say so.
- *aHandled = true;
- // Is there a prior node and are they siblings?
- nsCOMPtr<nsINode> stepbrother;
- if (sibling) {
- NS_ENSURE_STATE(mHTMLEditor);
- stepbrother = mHTMLEditor->GetNextHTMLSibling(sibling);
- }
- // Are they both text nodes? If so, join them!
- if (startNode == stepbrother && startNode->GetAsText() &&
- sibling->GetAsText()) {
- EditorDOMPoint pt = JoinNodesSmart(*sibling, *startNode->AsContent());
- NS_ENSURE_STATE(pt.node);
- // Fix up selection
- rv = aSelection->Collapse(pt.node, pt.offset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- rv = InsertBRIfNeeded(aSelection);
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
- }
-
- if (wsType == WSType::otherBlock) {
- // Make sure it's not a table element. If so, cancel the operation
- // (translation: users cannot backspace or delete across table cells)
- if (HTMLEditUtils::IsTableElement(visNode)) {
- *aCancel = true;
- return NS_OK;
- }
-
- // Next to a block. See if we are between a block and a br. If so, we
- // really want to delete the br. Else join content at selection to the
- // block.
- bool bDeletedBR = false;
- WSType otherWSType;
- nsCOMPtr<nsINode> otherNode;
- int32_t otherOffset;
-
- // Find node in other direction
- if (aAction == nsIEditor::eNext) {
- wsObj.PriorVisibleNode(startNode, startOffset, address_of(otherNode),
- &otherOffset, &otherWSType);
- } else {
- wsObj.NextVisibleNode(startNode, startOffset, address_of(otherNode),
- &otherOffset, &otherWSType);
- }
-
- // First find the adjacent node in the block
- nsCOMPtr<nsIContent> leafNode;
- nsCOMPtr<nsINode> leftNode, rightNode;
- if (aAction == nsIEditor::ePrevious) {
- NS_ENSURE_STATE(mHTMLEditor);
- leafNode = mHTMLEditor->GetLastEditableLeaf(*visNode);
- leftNode = leafNode;
- rightNode = startNode;
- } else {
- NS_ENSURE_STATE(mHTMLEditor);
- leafNode = mHTMLEditor->GetFirstEditableLeaf(*visNode);
- leftNode = startNode;
- rightNode = leafNode;
- }
-
- if (otherNode->IsHTMLElement(nsGkAtoms::br)) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->DeleteNode(otherNode);
- NS_ENSURE_SUCCESS(rv, rv);
- // XXX Only in this case, setting "handled" to true only when it
- // succeeds?
- *aHandled = true;
- bDeletedBR = true;
- }
-
- // Don't cross table boundaries
- if (leftNode && rightNode &&
- InDifferentTableElements(leftNode, rightNode)) {
- return NS_OK;
- }
-
- if (bDeletedBR) {
- // Put selection at edge of block and we are done.
- NS_ENSURE_STATE(leafNode);
- EditorDOMPoint newSel = GetGoodSelPointForNode(*leafNode, aAction);
- NS_ENSURE_STATE(newSel.node);
- aSelection->Collapse(newSel.node, newSel.offset);
- return NS_OK;
- }
-
- // Else we are joining content to block
-
- nsCOMPtr<nsINode> selPointNode = startNode;
- int32_t selPointOffset = startOffset;
- {
- NS_ENSURE_STATE(mHTMLEditor);
- AutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater,
- address_of(selPointNode), &selPointOffset);
- NS_ENSURE_STATE(leftNode && leftNode->IsContent() &&
- rightNode && rightNode->IsContent());
- EditActionResult ret =
- TryToJoinBlocks(*leftNode->AsContent(), *rightNode->AsContent());
- *aHandled |= ret.Handled();
- *aCancel |= ret.Canceled();
- if (NS_WARN_IF(ret.Failed())) {
- return ret.Rv();
- }
- }
-
- // If TryToJoinBlocks() didn't handle it and it's not canceled,
- // user may want to modify the start leaf node or the last leaf node
- // of the block.
- if (!*aHandled && !*aCancel && leafNode != startNode) {
- int32_t offset =
- aAction == nsIEditor::ePrevious ?
- static_cast<int32_t>(leafNode->Length()) : 0;
- aSelection->Collapse(leafNode, offset);
- return WillDeleteSelection(aSelection, aAction, aStripWrappers,
- aCancel, aHandled);
- }
-
- // Otherwise, we must have deleted the selection as user expected.
- aSelection->Collapse(selPointNode, selPointOffset);
- return NS_OK;
- }
-
- if (wsType == WSType::thisBlock) {
- // At edge of our block. Look beside it and see if we can join to an
- // adjacent block
-
- // Make sure it's not a table element. If so, cancel the operation
- // (translation: users cannot backspace or delete across table cells)
- if (HTMLEditUtils::IsTableElement(visNode)) {
- *aCancel = true;
- return NS_OK;
- }
-
- // First find the relevant nodes
- nsCOMPtr<nsINode> leftNode, rightNode;
- if (aAction == nsIEditor::ePrevious) {
- NS_ENSURE_STATE(mHTMLEditor);
- leftNode = mHTMLEditor->GetPriorHTMLNode(visNode);
- rightNode = startNode;
- } else {
- NS_ENSURE_STATE(mHTMLEditor);
- rightNode = mHTMLEditor->GetNextHTMLNode(visNode);
- leftNode = startNode;
- }
-
- // Nothing to join
- if (!leftNode || !rightNode) {
- *aCancel = true;
- return NS_OK;
- }
-
- // Don't cross table boundaries -- cancel it
- if (InDifferentTableElements(leftNode, rightNode)) {
- *aCancel = true;
- return NS_OK;
- }
-
- nsCOMPtr<nsINode> selPointNode = startNode;
- int32_t selPointOffset = startOffset;
- {
- NS_ENSURE_STATE(mHTMLEditor);
- AutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater,
- address_of(selPointNode), &selPointOffset);
- NS_ENSURE_STATE(leftNode->IsContent() && rightNode->IsContent());
- EditActionResult ret =
- TryToJoinBlocks(*leftNode->AsContent(), *rightNode->AsContent());
- // This should claim that trying to join the block means that
- // this handles the action because the caller shouldn't do anything
- // anymore in this case.
- *aHandled = true;
- *aCancel |= ret.Canceled();
- if (NS_WARN_IF(ret.Failed())) {
- return ret.Rv();
- }
- }
- aSelection->Collapse(selPointNode, selPointOffset);
- return NS_OK;
- }
- }
-
-
- // Else we have a non-collapsed selection. First adjust the selection.
- rv = ExpandSelectionForDeletion(*aSelection);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Remember that we did a ranged delete for the benefit of AfterEditInner().
- mDidRangedDelete = true;
-
- // Refresh start and end points
- NS_ENSURE_STATE(aSelection->GetRangeAt(0));
- startNode = aSelection->GetRangeAt(0)->GetStartParent();
- startOffset = aSelection->GetRangeAt(0)->StartOffset();
- NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
- nsCOMPtr<nsINode> endNode = aSelection->GetRangeAt(0)->GetEndParent();
- int32_t endOffset = aSelection->GetRangeAt(0)->EndOffset();
- NS_ENSURE_TRUE(endNode, NS_ERROR_FAILURE);
-
- // Figure out if the endpoints are in nodes that can be merged. Adjust
- // surrounding whitespace in preparation to delete selection.
- if (!IsPlaintextEditor()) {
- NS_ENSURE_STATE(mHTMLEditor);
- AutoTransactionsConserveSelection dontSpazMySelection(mHTMLEditor);
- rv = WSRunObject::PrepareToDeleteRange(mHTMLEditor,
- address_of(startNode), &startOffset,
- address_of(endNode), &endOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- {
- // Track location of where we are deleting
- NS_ENSURE_STATE(mHTMLEditor);
- AutoTrackDOMPoint startTracker(mHTMLEditor->mRangeUpdater,
- address_of(startNode), &startOffset);
- AutoTrackDOMPoint endTracker(mHTMLEditor->mRangeUpdater,
- address_of(endNode), &endOffset);
- // We are handling all ranged deletions directly now.
- *aHandled = true;
-
- if (endNode == startNode) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->DeleteSelectionImpl(aAction, aStripWrappers);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // Figure out mailcite ancestors
- nsCOMPtr<Element> startCiteNode = GetTopEnclosingMailCite(*startNode);
- nsCOMPtr<Element> endCiteNode = GetTopEnclosingMailCite(*endNode);
-
- // If we only have a mailcite at one of the two endpoints, set the
- // directionality of the deletion so that the selection will end up
- // outside the mailcite.
- if (startCiteNode && !endCiteNode) {
- aAction = nsIEditor::eNext;
- } else if (!startCiteNode && endCiteNode) {
- aAction = nsIEditor::ePrevious;
- }
-
- // Figure out block parents
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<Element> leftParent = mHTMLEditor->GetBlock(*startNode);
- nsCOMPtr<Element> rightParent = mHTMLEditor->GetBlock(*endNode);
-
- // Are endpoint block parents the same? Use default deletion
- if (leftParent && leftParent == rightParent) {
- NS_ENSURE_STATE(mHTMLEditor);
- mHTMLEditor->DeleteSelectionImpl(aAction, aStripWrappers);
- } else {
- // Deleting across blocks. Are the blocks of same type?
- NS_ENSURE_STATE(leftParent && rightParent);
-
- // Are the blocks siblings?
- nsCOMPtr<nsINode> leftBlockParent = leftParent->GetParentNode();
- nsCOMPtr<nsINode> rightBlockParent = rightParent->GetParentNode();
-
- // MOOSE: this could conceivably screw up a table.. fix me.
- NS_ENSURE_STATE(mHTMLEditor);
- if (leftBlockParent == rightBlockParent &&
- mHTMLEditor->NodesSameType(GetAsDOMNode(leftParent),
- GetAsDOMNode(rightParent)) &&
- // XXX What's special about these three types of block?
- (leftParent->IsHTMLElement(nsGkAtoms::p) ||
- HTMLEditUtils::IsListItem(leftParent) ||
- HTMLEditUtils::IsHeader(*leftParent))) {
- // First delete the selection
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->DeleteSelectionImpl(aAction, aStripWrappers);
- NS_ENSURE_SUCCESS(rv, rv);
- // Join blocks
- NS_ENSURE_STATE(mHTMLEditor);
- EditorDOMPoint pt =
- mHTMLEditor->JoinNodeDeep(*leftParent, *rightParent);
- NS_ENSURE_STATE(pt.node);
- // Fix up selection
- rv = aSelection->Collapse(pt.node, pt.offset);
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
- }
-
- // Else blocks not same type, or not siblings. Delete everything
- // except table elements.
- join = true;
-
- uint32_t rangeCount = aSelection->RangeCount();
- for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
- OwningNonNull<nsRange> range = *aSelection->GetRangeAt(rangeIdx);
-
- // Build a list of nodes in the range
- nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
- TrivialFunctor functor;
- DOMSubtreeIterator iter;
- nsresult rv = iter.Init(*range);
- NS_ENSURE_SUCCESS(rv, rv);
- iter.AppendList(functor, arrayOfNodes);
-
- // Now that we have the list, delete non-table elements
- int32_t listCount = arrayOfNodes.Length();
- for (int32_t j = 0; j < listCount; j++) {
- nsCOMPtr<nsINode> somenode = do_QueryInterface(arrayOfNodes[0]);
- NS_ENSURE_STATE(somenode);
- DeleteNonTableElements(somenode);
- arrayOfNodes.RemoveElementAt(0);
- // If something visible is deleted, no need to join. Visible means
- // all nodes except non-visible textnodes and breaks.
- if (join && origCollapsed) {
- if (!somenode->IsContent()) {
- join = false;
- continue;
- }
- nsCOMPtr<nsIContent> content = somenode->AsContent();
- if (content->NodeType() == nsIDOMNode::TEXT_NODE) {
- NS_ENSURE_STATE(mHTMLEditor);
- mHTMLEditor->IsVisTextNode(content, &join, true);
- } else {
- NS_ENSURE_STATE(mHTMLEditor);
- join = content->IsHTMLElement(nsGkAtoms::br) &&
- !mHTMLEditor->IsVisBreak(somenode);
- }
- }
- }
- }
-
- // Check endpoints for possible text deletion. We can assume that if
- // text node is found, we can delete to end or to begining as
- // appropriate, since the case where both sel endpoints in same text
- // node was already handled (we wouldn't be here)
- if (startNode->GetAsText() &&
- startNode->Length() > static_cast<uint32_t>(startOffset)) {
- // Delete to last character
- OwningNonNull<nsGenericDOMDataNode> dataNode =
- *static_cast<nsGenericDOMDataNode*>(startNode.get());
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->DeleteText(dataNode, startOffset,
- startNode->Length() - startOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- if (endNode->GetAsText() && endOffset) {
- // Delete to first character
- NS_ENSURE_STATE(mHTMLEditor);
- OwningNonNull<nsGenericDOMDataNode> dataNode =
- *static_cast<nsGenericDOMDataNode*>(endNode.get());
- rv = mHTMLEditor->DeleteText(dataNode, 0, endOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- if (join) {
- EditActionResult ret = TryToJoinBlocks(*leftParent, *rightParent);
- MOZ_ASSERT(*aHandled);
- *aCancel |= ret.Canceled();
- if (NS_WARN_IF(ret.Failed())) {
- return ret.Rv();
- }
- }
- }
- }
- }
-
- // We might have left only collapsed whitespace in the start/end nodes
- {
- AutoTrackDOMPoint startTracker(mHTMLEditor->mRangeUpdater,
- address_of(startNode), &startOffset);
- AutoTrackDOMPoint endTracker(mHTMLEditor->mRangeUpdater,
- address_of(endNode), &endOffset);
-
- DeleteNodeIfCollapsedText(*startNode);
- DeleteNodeIfCollapsedText(*endNode);
- }
-
- // If we're joining blocks: if deleting forward the selection should be
- // collapsed to the end of the selection, if deleting backward the selection
- // should be collapsed to the beginning of the selection. But if we're not
- // joining then the selection should collapse to the beginning of the
- // selection if we'redeleting forward, because the end of the selection will
- // still be in the next block. And same thing for deleting backwards
- // (selection should collapse to the end, because the beginning will still be
- // in the first block). See Bug 507936
- if (aAction == (join ? nsIEditor::eNext : nsIEditor::ePrevious)) {
- rv = aSelection->Collapse(endNode, endOffset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- rv = aSelection->Collapse(startNode, startOffset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- return NS_OK;
-}
-
-/**
- * If aNode is a text node that contains only collapsed whitespace, delete it.
- * It doesn't serve any useful purpose, and we don't want it to confuse code
- * that doesn't correctly skip over it.
- *
- * If deleting the node fails (like if it's not editable), the caller should
- * proceed as usual, so don't return any errors.
- */
-void
-HTMLEditRules::DeleteNodeIfCollapsedText(nsINode& aNode)
-{
- if (!aNode.GetAsText()) {
- return;
- }
- bool empty;
- nsresult rv = mHTMLEditor->IsVisTextNode(aNode.AsContent(), &empty, false);
- NS_ENSURE_SUCCESS_VOID(rv);
- if (empty) {
- mHTMLEditor->DeleteNode(&aNode);
- }
-}
-
-
-/**
- * InsertBRIfNeeded() determines if a br is needed for current selection to not
- * be spastic. If so, it inserts one. Callers responsibility to only call
- * with collapsed selection.
- *
- * @param aSelection The collapsed selection.
- */
-nsresult
-HTMLEditRules::InsertBRIfNeeded(Selection* aSelection)
-{
- NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
-
- // get selection
- nsCOMPtr<nsINode> node;
- int32_t offset;
- nsresult rv =
- mTextEditor->GetStartNodeAndOffset(aSelection,
- getter_AddRefs(node), &offset);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
-
- // inline elements don't need any br
- if (!IsBlockNode(*node)) {
- return NS_OK;
- }
-
- // examine selection
- NS_ENSURE_STATE(mHTMLEditor);
- WSRunObject wsObj(mHTMLEditor, node, offset);
- if (((wsObj.mStartReason & WSType::block) ||
- (wsObj.mStartReason & WSType::br)) &&
- (wsObj.mEndReason & WSType::block)) {
- // if we are tucked between block boundaries then insert a br
- // first check that we are allowed to
- NS_ENSURE_STATE(mHTMLEditor);
- if (mHTMLEditor->CanContainTag(*node, *nsGkAtoms::br)) {
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<Element> br =
- mHTMLEditor->CreateBR(node, offset, nsIEditor::ePrevious);
- return br ? NS_OK : NS_ERROR_FAILURE;
- }
- }
- return NS_OK;
-}
-
-/**
- * GetGoodSelPointForNode() finds where at a node you would want to set the
- * selection if you were trying to have a caret next to it. Always returns a
- * valid value (unless mHTMLEditor has gone away).
- *
- * @param aNode The node
- * @param aAction Which edge to find:
- * eNext/eNextWord/eToEndOfLine indicates beginning,
- * ePrevious/PreviousWord/eToBeginningOfLine ending.
- */
-EditorDOMPoint
-HTMLEditRules::GetGoodSelPointForNode(nsINode& aNode,
- nsIEditor::EDirection aAction)
-{
- MOZ_ASSERT(aAction == nsIEditor::eNext ||
- aAction == nsIEditor::eNextWord ||
- aAction == nsIEditor::ePrevious ||
- aAction == nsIEditor::ePreviousWord ||
- aAction == nsIEditor::eToBeginningOfLine ||
- aAction == nsIEditor::eToEndOfLine);
-
- bool isPreviousAction = (aAction == nsIEditor::ePrevious ||
- aAction == nsIEditor::ePreviousWord ||
- aAction == nsIEditor::eToBeginningOfLine);
-
- NS_ENSURE_TRUE(mHTMLEditor, EditorDOMPoint());
- if (aNode.GetAsText() || mHTMLEditor->IsContainer(&aNode) ||
- NS_WARN_IF(!aNode.GetParentNode())) {
- return EditorDOMPoint(&aNode, isPreviousAction ? aNode.Length() : 0);
- }
-
- EditorDOMPoint ret;
- ret.node = aNode.GetParentNode();
- ret.offset = ret.node ? ret.node->IndexOf(&aNode) : -1;
- NS_ENSURE_TRUE(mHTMLEditor, EditorDOMPoint());
- if ((!aNode.IsHTMLElement(nsGkAtoms::br) ||
- mHTMLEditor->IsVisBreak(&aNode)) && isPreviousAction) {
- ret.offset++;
- }
- return ret;
-}
-
-EditActionResult
-HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
- nsIContent& aRightNode)
-{
- if (NS_WARN_IF(!mHTMLEditor)) {
- return EditActionIgnored(NS_ERROR_UNEXPECTED);
- }
-
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- nsCOMPtr<Element> leftBlock = htmlEditor->GetBlock(aLeftNode);
- nsCOMPtr<Element> rightBlock = htmlEditor->GetBlock(aRightNode);
-
- // Sanity checks
- if (NS_WARN_IF(!leftBlock) || NS_WARN_IF(!rightBlock)) {
- return EditActionIgnored(NS_ERROR_NULL_POINTER);
- }
- if (NS_WARN_IF(leftBlock == rightBlock)) {
- return EditActionIgnored(NS_ERROR_UNEXPECTED);
- }
-
- if (HTMLEditUtils::IsTableElement(leftBlock) ||
- HTMLEditUtils::IsTableElement(rightBlock)) {
- // Do not try to merge table elements
- return EditActionCanceled();
- }
-
- // Make sure we don't try to move things into HR's, which look like blocks
- // but aren't containers
- if (leftBlock->IsHTMLElement(nsGkAtoms::hr)) {
- leftBlock = htmlEditor->GetBlockNodeParent(leftBlock);
- if (NS_WARN_IF(!leftBlock)) {
- return EditActionIgnored(NS_ERROR_UNEXPECTED);
- }
- }
- if (rightBlock->IsHTMLElement(nsGkAtoms::hr)) {
- rightBlock = htmlEditor->GetBlockNodeParent(rightBlock);
- if (NS_WARN_IF(!rightBlock)) {
- return EditActionIgnored(NS_ERROR_UNEXPECTED);
- }
- }
-
- // Bail if both blocks the same
- if (leftBlock == rightBlock) {
- return EditActionIgnored();
- }
-
- // Joining a list item to its parent is a NOP.
- if (HTMLEditUtils::IsList(leftBlock) &&
- HTMLEditUtils::IsListItem(rightBlock) &&
- rightBlock->GetParentNode() == leftBlock) {
- return EditActionHandled();
- }
-
- // Special rule here: if we are trying to join list items, and they are in
- // different lists, join the lists instead.
- bool mergeLists = false;
- nsIAtom* existingList = nsGkAtoms::_empty;
- int32_t offset;
- nsCOMPtr<Element> leftList, rightList;
- if (HTMLEditUtils::IsListItem(leftBlock) &&
- HTMLEditUtils::IsListItem(rightBlock)) {
- leftList = leftBlock->GetParentElement();
- rightList = rightBlock->GetParentElement();
- if (leftList && rightList && leftList != rightList &&
- !EditorUtils::IsDescendantOf(leftList, rightBlock, &offset) &&
- !EditorUtils::IsDescendantOf(rightList, leftBlock, &offset)) {
- // There are some special complications if the lists are descendants of
- // the other lists' items. Note that it is okay for them to be
- // descendants of the other lists themselves, which is the usual case for
- // sublists in our implementation.
- leftBlock = leftList;
- rightBlock = rightList;
- mergeLists = true;
- existingList = leftList->NodeInfo()->NameAtom();
- }
- }
-
- AutoTransactionsConserveSelection dontSpazMySelection(htmlEditor);
-
- int32_t rightOffset = 0;
- int32_t leftOffset = -1;
-
- // offset below is where you find yourself in rightBlock when you traverse
- // upwards from leftBlock
- if (EditorUtils::IsDescendantOf(leftBlock, rightBlock, &rightOffset)) {
- // Tricky case. Left block is inside right block. Do ws adjustment. This
- // just destroys non-visible ws at boundaries we will be joining.
- rightOffset++;
- nsresult rv = WSRunObject::ScrubBlockBoundary(htmlEditor,
- WSRunObject::kBlockEnd,
- leftBlock);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return EditActionIgnored(rv);
- }
-
- {
- // We can't just track rightBlock because it's an Element.
- nsCOMPtr<nsINode> trackingRightBlock(rightBlock);
- AutoTrackDOMPoint tracker(htmlEditor->mRangeUpdater,
- address_of(trackingRightBlock), &rightOffset);
- rv = WSRunObject::ScrubBlockBoundary(htmlEditor,
- WSRunObject::kAfterBlock,
- rightBlock, rightOffset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return EditActionIgnored(rv);
- }
-
- if (trackingRightBlock->IsElement()) {
- rightBlock = trackingRightBlock->AsElement();
- } else {
- if (NS_WARN_IF(!trackingRightBlock->GetParentElement())) {
- return EditActionIgnored(NS_ERROR_UNEXPECTED);
- }
- rightBlock = trackingRightBlock->GetParentElement();
- }
- }
- // Do br adjustment.
- nsCOMPtr<Element> brNode =
- CheckForInvisibleBR(*leftBlock, BRLocation::blockEnd);
- EditActionResult ret(NS_OK);
- if (mergeLists) {
- // The idea here is to take all children in rightList that are past
- // offset, and pull them into leftlist.
- for (nsCOMPtr<nsIContent> child = rightList->GetChildAt(offset);
- child; child = rightList->GetChildAt(rightOffset)) {
- rv = htmlEditor->MoveNode(child, leftList, -1);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return EditActionIgnored(rv);
- }
- }
- // XXX Should this set to true only when above for loop moves the node?
- ret.MarkAsHandled();
- } else {
- // XXX Why do we ignore the result of MoveBlock()?
- EditActionResult retMoveBlock =
- MoveBlock(*leftBlock, *rightBlock, leftOffset, rightOffset);
- if (retMoveBlock.Handled()) {
- ret.MarkAsHandled();
- }
- }
- if (brNode && NS_SUCCEEDED(htmlEditor->DeleteNode(brNode))) {
- ret.MarkAsHandled();
- }
- return ret;
- }
-
- // Offset below is where you find yourself in leftBlock when you traverse
- // upwards from rightBlock
- if (EditorUtils::IsDescendantOf(rightBlock, leftBlock, &leftOffset)) {
- // Tricky case. Right block is inside left block. Do ws adjustment. This
- // just destroys non-visible ws at boundaries we will be joining.
- nsresult rv = WSRunObject::ScrubBlockBoundary(htmlEditor,
- WSRunObject::kBlockStart,
- rightBlock);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return EditActionIgnored(rv);
- }
-
- {
- // We can't just track leftBlock because it's an Element, so track
- // something else.
- nsCOMPtr<nsINode> trackingLeftBlock(leftBlock);
- AutoTrackDOMPoint tracker(htmlEditor->mRangeUpdater,
- address_of(trackingLeftBlock), &leftOffset);
- rv = WSRunObject::ScrubBlockBoundary(htmlEditor,
- WSRunObject::kBeforeBlock,
- leftBlock, leftOffset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return EditActionIgnored(rv);
- }
-
- if (trackingLeftBlock->IsElement()) {
- leftBlock = trackingLeftBlock->AsElement();
- } else {
- if (NS_WARN_IF(!trackingLeftBlock->GetParentElement())) {
- return EditActionIgnored(NS_ERROR_UNEXPECTED);
- }
- leftBlock = trackingLeftBlock->GetParentElement();
- }
- }
- // Do br adjustment.
- nsCOMPtr<Element> brNode =
- CheckForInvisibleBR(*leftBlock, BRLocation::beforeBlock, leftOffset);
- EditActionResult ret(NS_OK);
- if (mergeLists) {
- // XXX Why do we ignore the result of MoveContents()?
- EditActionResult retMoveContents =
- MoveContents(*rightList, *leftList, &leftOffset);
- if (retMoveContents.Handled()) {
- ret.MarkAsHandled();
- }
- } else {
- // Left block is a parent of right block, and the parent of the previous
- // visible content. Right block is a child and contains the contents we
- // want to move.
-
- int32_t previousContentOffset;
- nsCOMPtr<nsINode> previousContentParent;
-
- if (&aLeftNode == leftBlock) {
- // We are working with valid HTML, aLeftNode is a block node, and is
- // therefore allowed to contain rightBlock. This is the simple case,
- // we will simply move the content in rightBlock out of its block.
- previousContentParent = leftBlock;
- previousContentOffset = leftOffset;
- } else {
- // We try to work as well as possible with HTML that's already invalid.
- // Although "right block" is a block, and a block must not be contained
- // in inline elements, reality is that broken documents do exist. The
- // DIRECT parent of "left NODE" might be an inline element. Previous
- // versions of this code skipped inline parents until the first block
- // parent was found (and used "left block" as the destination).
- // However, in some situations this strategy moves the content to an
- // unexpected position. (see bug 200416) The new idea is to make the
- // moving content a sibling, next to the previous visible content.
-
- previousContentParent = aLeftNode.GetParentNode();
- previousContentOffset = previousContentParent ?
- previousContentParent->IndexOf(&aLeftNode) : -1;
-
- // We want to move our content just after the previous visible node.
- previousContentOffset++;
- }
-
- // Because we don't want the moving content to receive the style of the
- // previous content, we split the previous content's style.
-
- nsCOMPtr<Element> editorRoot = htmlEditor->GetEditorRoot();
- if (!editorRoot || &aLeftNode != editorRoot) {
- nsCOMPtr<nsIContent> splittedPreviousContent;
- rv = htmlEditor->SplitStyleAbovePoint(
- address_of(previousContentParent),
- &previousContentOffset,
- nullptr, nullptr, nullptr,
- getter_AddRefs(splittedPreviousContent));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return EditActionIgnored(rv);
- }
-
- if (splittedPreviousContent) {
- previousContentParent = splittedPreviousContent->GetParentNode();
- previousContentOffset = previousContentParent ?
- previousContentParent->IndexOf(splittedPreviousContent) : -1;
- }
- }
-
- if (NS_WARN_IF(!previousContentParent)) {
- return EditActionIgnored(NS_ERROR_NULL_POINTER);
- }
-
- ret |= MoveBlock(*previousContentParent->AsElement(), *rightBlock,
- previousContentOffset, rightOffset);
- if (NS_WARN_IF(ret.Failed())) {
- return ret;
- }
- }
- if (brNode && NS_SUCCEEDED(htmlEditor->DeleteNode(brNode))) {
- ret.MarkAsHandled();
- }
- return ret;
- }
-
- // Normal case. Blocks are siblings, or at least close enough. An example
- // of the latter is <p>paragraph</p><ul><li>one<li>two<li>three</ul>. The
- // first li and the p are not true siblings, but we still want to join them
- // if you backspace from li into p.
-
- // Adjust whitespace at block boundaries
- nsresult rv =
- WSRunObject::PrepareToJoinBlocks(htmlEditor, leftBlock, rightBlock);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return EditActionIgnored(rv);
- }
- // Do br adjustment.
- nsCOMPtr<Element> brNode =
- CheckForInvisibleBR(*leftBlock, BRLocation::blockEnd);
- EditActionResult ret(NS_OK);
- if (mergeLists || leftBlock->NodeInfo()->NameAtom() ==
- rightBlock->NodeInfo()->NameAtom()) {
- // Nodes are same type. merge them.
- EditorDOMPoint pt = JoinNodesSmart(*leftBlock, *rightBlock);
- if (pt.node && mergeLists) {
- nsCOMPtr<Element> newBlock;
- ConvertListType(rightBlock, getter_AddRefs(newBlock),
- existingList, nsGkAtoms::li);
- }
- ret.MarkAsHandled();
- } else {
- // Nodes are dissimilar types.
- ret |= MoveBlock(*leftBlock, *rightBlock, leftOffset, rightOffset);
- if (NS_WARN_IF(ret.Failed())) {
- return ret;
- }
- }
- if (brNode) {
- rv = htmlEditor->DeleteNode(brNode);
- // XXX In other top level if blocks, the result of DeleteNode()
- // is ignored. Why does only this result is respected?
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return ret.SetResult(rv);
- }
- ret.MarkAsHandled();
- }
- return ret;
-}
-
-EditActionResult
-HTMLEditRules::MoveBlock(Element& aLeftBlock,
- Element& aRightBlock,
- int32_t aLeftOffset,
- int32_t aRightOffset)
-{
- nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
- // GetNodesFromPoint is the workhorse that figures out what we wnat to move.
- nsresult rv = GetNodesFromPoint(EditorDOMPoint(&aRightBlock, aRightOffset),
- EditAction::makeList, arrayOfNodes,
- TouchContent::yes);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return EditActionIgnored(rv);
- }
-
- EditActionResult ret(NS_OK);
- for (uint32_t i = 0; i < arrayOfNodes.Length(); i++) {
- // get the node to act on
- if (IsBlockNode(arrayOfNodes[i])) {
- // For block nodes, move their contents only, then delete block.
- ret |=
- MoveContents(*arrayOfNodes[i]->AsElement(), aLeftBlock, &aLeftOffset);
- if (NS_WARN_IF(ret.Failed())) {
- return ret;
- }
- if (NS_WARN_IF(!mHTMLEditor)) {
- return ret.SetResult(NS_ERROR_UNEXPECTED);
- }
- rv = mHTMLEditor->DeleteNode(arrayOfNodes[i]);
- ret.MarkAsHandled();
- } else {
- // Otherwise move the content as is, checking against the DTD.
- ret |=
- MoveNodeSmart(*arrayOfNodes[i]->AsContent(), aLeftBlock, &aLeftOffset);
- }
- }
-
- // XXX We're only checking return value of the last iteration
- if (NS_WARN_IF(ret.Failed())) {
- return ret;
- }
-
- return ret;
-}
-
-EditActionResult
-HTMLEditRules::MoveNodeSmart(nsIContent& aNode,
- Element& aDestElement,
- int32_t* aInOutDestOffset)
-{
- MOZ_ASSERT(aInOutDestOffset);
-
- if (NS_WARN_IF(!mHTMLEditor)) {
- return EditActionIgnored(NS_ERROR_UNEXPECTED);
- }
-
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- // Check if this node can go into the destination node
- if (htmlEditor->CanContain(aDestElement, aNode)) {
- // If it can, move it there
- nsresult rv =
- htmlEditor->MoveNode(&aNode, &aDestElement, *aInOutDestOffset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return EditActionIgnored(rv);
- }
- if (*aInOutDestOffset != -1) {
- (*aInOutDestOffset)++;
- }
- // XXX Should we check if the node is actually moved in this case?
- return EditActionHandled();
- }
-
- // If it can't, move its children (if any), and then delete it.
- EditActionResult ret(NS_OK);
- if (aNode.IsElement()) {
- ret = MoveContents(*aNode.AsElement(), aDestElement, aInOutDestOffset);
- if (NS_WARN_IF(ret.Failed())) {
- return ret;
- }
- }
-
- nsresult rv = htmlEditor->DeleteNode(&aNode);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return ret.SetResult(rv);
- }
- return ret.MarkAsHandled();
-}
-
-EditActionResult
-HTMLEditRules::MoveContents(Element& aElement,
- Element& aDestElement,
- int32_t* aInOutDestOffset)
-{
- MOZ_ASSERT(aInOutDestOffset);
-
- if (NS_WARN_IF(&aElement == &aDestElement)) {
- return EditActionIgnored(NS_ERROR_ILLEGAL_VALUE);
- }
-
- EditActionResult ret(NS_OK);
- while (aElement.GetFirstChild()) {
- ret |=
- MoveNodeSmart(*aElement.GetFirstChild(), aDestElement, aInOutDestOffset);
- if (NS_WARN_IF(ret.Failed())) {
- return ret;
- }
- }
- return ret;
-}
-
-
-nsresult
-HTMLEditRules::DeleteNonTableElements(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
- if (!HTMLEditUtils::IsTableElementButNotTable(aNode)) {
- NS_ENSURE_STATE(mHTMLEditor);
- return mHTMLEditor->DeleteNode(aNode->AsDOMNode());
- }
-
- for (int32_t i = aNode->GetChildCount() - 1; i >= 0; --i) {
- nsresult rv = DeleteNonTableElements(aNode->GetChildAt(i));
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::DidDeleteSelection(Selection* aSelection,
- nsIEditor::EDirection aDir,
- nsresult aResult)
-{
- if (!aSelection) {
- return NS_ERROR_NULL_POINTER;
- }
-
- // find where we are
- nsCOMPtr<nsINode> startNode;
- int32_t startOffset;
- nsresult rv = mTextEditor->GetStartNodeAndOffset(aSelection,
- getter_AddRefs(startNode),
- &startOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
-
- // find any enclosing mailcite
- nsCOMPtr<Element> citeNode = GetTopEnclosingMailCite(*startNode);
- if (citeNode) {
- bool isEmpty = true, seenBR = false;
- NS_ENSURE_STATE(mHTMLEditor);
- mHTMLEditor->IsEmptyNodeImpl(citeNode, &isEmpty, true, true, false,
- &seenBR);
- if (isEmpty) {
- int32_t offset;
- nsCOMPtr<nsINode> parent = EditorBase::GetNodeLocation(citeNode, &offset);
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->DeleteNode(citeNode);
- NS_ENSURE_SUCCESS(rv, rv);
- if (parent && seenBR) {
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<Element> brNode = mHTMLEditor->CreateBR(parent, offset);
- NS_ENSURE_STATE(brNode);
- aSelection->Collapse(parent, offset);
- }
- }
- }
-
- // call through to base class
- return TextEditRules::DidDeleteSelection(aSelection, aDir, aResult);
-}
-
-nsresult
-HTMLEditRules::WillMakeList(Selection* aSelection,
- const nsAString* aListType,
- bool aEntireList,
- const nsAString* aBulletType,
- bool* aCancel,
- bool* aHandled,
- const nsAString* aItemType)
-{
- if (!aSelection || !aListType || !aCancel || !aHandled) {
- return NS_ERROR_NULL_POINTER;
- }
- OwningNonNull<nsIAtom> listType = NS_Atomize(*aListType);
-
- WillInsert(*aSelection, aCancel);
-
- // initialize out param
- // we want to ignore result of WillInsert()
- *aCancel = false;
- *aHandled = false;
-
- // deduce what tag to use for list items
- nsCOMPtr<nsIAtom> itemType;
- if (aItemType) {
- itemType = NS_Atomize(*aItemType);
- NS_ENSURE_TRUE(itemType, NS_ERROR_OUT_OF_MEMORY);
- } else if (listType == nsGkAtoms::dl) {
- itemType = nsGkAtoms::dd;
- } else {
- itemType = nsGkAtoms::li;
- }
-
- // convert the selection ranges into "promoted" selection ranges:
- // this basically just expands the range to include the immediate
- // block parent, and then further expands to include any ancestors
- // whose children are all in the range
-
- *aHandled = true;
-
- nsresult rv = NormalizeSelection(aSelection);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_STATE(mHTMLEditor);
- AutoSelectionRestorer selectionRestorer(aSelection, mHTMLEditor);
-
- nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
- rv = GetListActionNodes(arrayOfNodes,
- aEntireList ? EntireList::yes : EntireList::no);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // check if all our nodes are <br>s, or empty inlines
- bool bOnlyBreaks = true;
- for (auto& curNode : arrayOfNodes) {
- // if curNode is not a Break or empty inline, we're done
- if (!TextEditUtils::IsBreak(curNode) &&
- !IsEmptyInline(curNode)) {
- bOnlyBreaks = false;
- break;
- }
- }
-
- // if no nodes, we make empty list. Ditto if the user tried to make a list
- // of some # of breaks.
- if (arrayOfNodes.IsEmpty() || bOnlyBreaks) {
- // if only breaks, delete them
- if (bOnlyBreaks) {
- for (auto& node : arrayOfNodes) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->DeleteNode(node);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- // get selection location
- NS_ENSURE_STATE(aSelection->RangeCount());
- nsCOMPtr<nsINode> parent = aSelection->GetRangeAt(0)->GetStartParent();
- int32_t offset = aSelection->GetRangeAt(0)->StartOffset();
- NS_ENSURE_STATE(parent);
-
- // make sure we can put a list here
- NS_ENSURE_STATE(mHTMLEditor);
- if (!mHTMLEditor->CanContainTag(*parent, listType)) {
- *aCancel = true;
- return NS_OK;
- }
- rv = SplitAsNeeded(listType, parent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<Element> theList =
- mHTMLEditor->CreateNode(listType, parent, offset);
- NS_ENSURE_STATE(theList);
-
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<Element> theListItem =
- mHTMLEditor->CreateNode(itemType, theList, 0);
- NS_ENSURE_STATE(theListItem);
-
- // remember our new block for postprocessing
- mNewBlock = theListItem;
- // put selection in new list item
- *aHandled = true;
- rv = aSelection->Collapse(theListItem, 0);
- // Don't restore the selection
- selectionRestorer.Abort();
- return rv;
- }
-
- // if there is only one node in the array, and it is a list, div, or
- // blockquote, then look inside of it until we find inner list or content.
-
- LookInsideDivBQandList(arrayOfNodes);
-
- // Ok, now go through all the nodes and put then in the list,
- // or whatever is approriate. Wohoo!
-
- uint32_t listCount = arrayOfNodes.Length();
- nsCOMPtr<nsINode> curParent;
- nsCOMPtr<Element> curList, prevListItem;
-
- for (uint32_t i = 0; i < listCount; i++) {
- // here's where we actually figure out what to do
- nsCOMPtr<Element> newBlock;
- NS_ENSURE_STATE(arrayOfNodes[i]->IsContent());
- OwningNonNull<nsIContent> curNode = *arrayOfNodes[i]->AsContent();
- int32_t offset;
- curParent = EditorBase::GetNodeLocation(curNode, &offset);
-
- // make sure we don't assemble content that is in different table cells
- // into the same list. respect table cell boundaries when listifying.
- if (curList && InDifferentTableElements(curList, curNode)) {
- curList = nullptr;
- }
-
- // if curNode is a Break, delete it, and quit remembering prev list item
- if (TextEditUtils::IsBreak(curNode)) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->DeleteNode(curNode);
- NS_ENSURE_SUCCESS(rv, rv);
- prevListItem = nullptr;
- continue;
- } else if (IsEmptyInline(curNode)) {
- // if curNode is an empty inline container, delete it
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->DeleteNode(curNode);
- NS_ENSURE_SUCCESS(rv, rv);
- continue;
- }
-
- if (HTMLEditUtils::IsList(curNode)) {
- // do we have a curList already?
- if (curList && !EditorUtils::IsDescendantOf(curNode, curList)) {
- // move all of our children into curList. cheezy way to do it: move
- // whole list and then RemoveContainer() on the list. ConvertListType
- // first: that routine handles converting the list item types, if
- // needed
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->MoveNode(curNode, curList, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = ConvertListType(curNode->AsElement(), getter_AddRefs(newBlock),
- listType, itemType);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->RemoveBlockContainer(*newBlock);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // replace list with new list type
- rv = ConvertListType(curNode->AsElement(), getter_AddRefs(newBlock),
- listType, itemType);
- NS_ENSURE_SUCCESS(rv, rv);
- curList = newBlock;
- }
- prevListItem = nullptr;
- continue;
- }
-
- if (HTMLEditUtils::IsListItem(curNode)) {
- NS_ENSURE_STATE(mHTMLEditor);
- if (!curParent->IsHTMLElement(listType)) {
- // list item is in wrong type of list. if we don't have a curList,
- // split the old list and make a new list of correct type.
- if (!curList || EditorUtils::IsDescendantOf(curNode, curList)) {
- NS_ENSURE_STATE(mHTMLEditor);
- NS_ENSURE_STATE(curParent->IsContent());
- ErrorResult rv;
- nsCOMPtr<nsIContent> splitNode =
- mHTMLEditor->SplitNode(*curParent->AsContent(), offset, rv);
- NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult());
- newBlock = splitNode ? splitNode->AsElement() : nullptr;
- int32_t offset;
- nsCOMPtr<nsINode> parent = EditorBase::GetNodeLocation(curParent,
- &offset);
- NS_ENSURE_STATE(mHTMLEditor);
- curList = mHTMLEditor->CreateNode(listType, parent, offset);
- NS_ENSURE_STATE(curList);
- }
- // move list item to new list
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->MoveNode(curNode, curList, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- // convert list item type if needed
- NS_ENSURE_STATE(mHTMLEditor);
- if (!curNode->IsHTMLElement(itemType)) {
- NS_ENSURE_STATE(mHTMLEditor);
- newBlock = mHTMLEditor->ReplaceContainer(curNode->AsElement(),
- itemType);
- NS_ENSURE_STATE(newBlock);
- }
- } else {
- // item is in right type of list. But we might still have to move it.
- // and we might need to convert list item types.
- if (!curList) {
- curList = curParent->AsElement();
- } else if (curParent != curList) {
- // move list item to new list
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->MoveNode(curNode, curList, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- NS_ENSURE_STATE(mHTMLEditor);
- if (!curNode->IsHTMLElement(itemType)) {
- NS_ENSURE_STATE(mHTMLEditor);
- newBlock = mHTMLEditor->ReplaceContainer(curNode->AsElement(),
- itemType);
- NS_ENSURE_STATE(newBlock);
- }
- }
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<Element> curElement = do_QueryInterface(curNode);
- if (aBulletType && !aBulletType->IsEmpty()) {
- rv = mHTMLEditor->SetAttribute(curElement, nsGkAtoms::type,
- *aBulletType);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- rv = mHTMLEditor->RemoveAttribute(curElement, nsGkAtoms::type);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- continue;
- }
-
- // if we hit a div clear our prevListItem, insert divs contents
- // into our node array, and remove the div
- if (curNode->IsHTMLElement(nsGkAtoms::div)) {
- prevListItem = nullptr;
- int32_t j = i + 1;
- GetInnerContent(*curNode, arrayOfNodes, &j);
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->RemoveContainer(curNode);
- NS_ENSURE_SUCCESS(rv, rv);
- listCount = arrayOfNodes.Length();
- continue;
- }
-
- // need to make a list to put things in if we haven't already,
- if (!curList) {
- rv = SplitAsNeeded(listType, curParent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_STATE(mHTMLEditor);
- curList = mHTMLEditor->CreateNode(listType, curParent, offset);
- // remember our new block for postprocessing
- mNewBlock = curList;
- // curList is now the correct thing to put curNode in
- prevListItem = nullptr;
- }
-
- // if curNode isn't a list item, we must wrap it in one
- nsCOMPtr<Element> listItem;
- if (!HTMLEditUtils::IsListItem(curNode)) {
- if (IsInlineNode(curNode) && prevListItem) {
- // this is a continuation of some inline nodes that belong together in
- // the same list item. use prevListItem
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->MoveNode(curNode, prevListItem, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // don't wrap li around a paragraph. instead replace paragraph with li
- if (curNode->IsHTMLElement(nsGkAtoms::p)) {
- NS_ENSURE_STATE(mHTMLEditor);
- listItem = mHTMLEditor->ReplaceContainer(curNode->AsElement(),
- itemType);
- NS_ENSURE_STATE(listItem);
- } else {
- NS_ENSURE_STATE(mHTMLEditor);
- listItem = mHTMLEditor->InsertContainerAbove(curNode, itemType);
- NS_ENSURE_STATE(listItem);
- }
- if (IsInlineNode(curNode)) {
- prevListItem = listItem;
- } else {
- prevListItem = nullptr;
- }
- }
- } else {
- listItem = curNode->AsElement();
- }
-
- if (listItem) {
- // if we made a new list item, deal with it: tuck the listItem into the
- // end of the active list
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->MoveNode(listItem, curList, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- return NS_OK;
-}
-
-
-nsresult
-HTMLEditRules::WillRemoveList(Selection* aSelection,
- bool aOrdered,
- bool* aCancel,
- bool* aHandled)
-{
- if (!aSelection || !aCancel || !aHandled) {
- return NS_ERROR_NULL_POINTER;
- }
- // initialize out param
- *aCancel = false;
- *aHandled = true;
-
- nsresult rv = NormalizeSelection(aSelection);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_STATE(mHTMLEditor);
- AutoSelectionRestorer selectionRestorer(aSelection, mHTMLEditor);
-
- nsTArray<RefPtr<nsRange>> arrayOfRanges;
- GetPromotedRanges(*aSelection, arrayOfRanges, EditAction::makeList);
-
- // use these ranges to contruct a list of nodes to act on.
- nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
- rv = GetListActionNodes(arrayOfNodes, EntireList::no);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Remove all non-editable nodes. Leave them be.
- for (int32_t i = arrayOfNodes.Length() - 1; i >= 0; i--) {
- OwningNonNull<nsINode> testNode = arrayOfNodes[i];
- NS_ENSURE_STATE(mHTMLEditor);
- if (!mHTMLEditor->IsEditable(testNode)) {
- arrayOfNodes.RemoveElementAt(i);
- }
- }
-
- // Only act on lists or list items in the array
- for (auto& curNode : arrayOfNodes) {
- // here's where we actually figure out what to do
- if (HTMLEditUtils::IsListItem(curNode)) {
- // unlist this listitem
- bool bOutOfList;
- do {
- rv = PopListItem(GetAsDOMNode(curNode), &bOutOfList);
- NS_ENSURE_SUCCESS(rv, rv);
- } while (!bOutOfList); // keep popping it out until it's not in a list anymore
- } else if (HTMLEditUtils::IsList(curNode)) {
- // node is a list, move list items out
- rv = RemoveListStructure(*curNode->AsElement());
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::WillMakeDefListItem(Selection* aSelection,
- const nsAString *aItemType,
- bool aEntireList,
- bool* aCancel,
- bool* aHandled)
-{
- // for now we let WillMakeList handle this
- NS_NAMED_LITERAL_STRING(listType, "dl");
- return WillMakeList(aSelection, &listType, aEntireList, nullptr, aCancel, aHandled, aItemType);
-}
-
-nsresult
-HTMLEditRules::WillMakeBasicBlock(Selection& aSelection,
- const nsAString& aBlockType,
- bool* aCancel,
- bool* aHandled)
-{
- MOZ_ASSERT(aCancel && aHandled);
-
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- OwningNonNull<nsIAtom> blockType = NS_Atomize(aBlockType);
-
- WillInsert(aSelection, aCancel);
- // We want to ignore result of WillInsert()
- *aCancel = false;
- *aHandled = false;
-
- nsresult rv = NormalizeSelection(&aSelection);
- NS_ENSURE_SUCCESS(rv, rv);
- AutoSelectionRestorer selectionRestorer(&aSelection, htmlEditor);
- AutoTransactionsConserveSelection dontSpazMySelection(htmlEditor);
- *aHandled = true;
-
- // Contruct a list of nodes to act on.
- nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
- rv = GetNodesFromSelection(aSelection, EditAction::makeBasicBlock,
- arrayOfNodes);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Remove all non-editable nodes. Leave them be.
- for (int32_t i = arrayOfNodes.Length() - 1; i >= 0; i--) {
- if (!htmlEditor->IsEditable(arrayOfNodes[i])) {
- arrayOfNodes.RemoveElementAt(i);
- }
- }
-
- // If nothing visible in list, make an empty block
- if (ListIsEmptyLine(arrayOfNodes)) {
- // Get selection location
- NS_ENSURE_STATE(aSelection.GetRangeAt(0) &&
- aSelection.GetRangeAt(0)->GetStartParent());
- OwningNonNull<nsINode> parent =
- *aSelection.GetRangeAt(0)->GetStartParent();
- int32_t offset = aSelection.GetRangeAt(0)->StartOffset();
-
- if (blockType == nsGkAtoms::normal ||
- blockType == nsGkAtoms::_empty) {
- // We are removing blocks (going to "body text")
- NS_ENSURE_TRUE(htmlEditor->GetBlock(parent), NS_ERROR_NULL_POINTER);
- OwningNonNull<Element> curBlock = *htmlEditor->GetBlock(parent);
- if (HTMLEditUtils::IsFormatNode(curBlock)) {
- // If the first editable node after selection is a br, consume it.
- // Otherwise it gets pushed into a following block after the split,
- // which is visually bad.
- nsCOMPtr<nsIContent> brNode =
- htmlEditor->GetNextHTMLNode(parent, offset);
- if (brNode && brNode->IsHTMLElement(nsGkAtoms::br)) {
- rv = htmlEditor->DeleteNode(brNode);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // Do the splits!
- offset = htmlEditor->SplitNodeDeep(curBlock, *parent->AsContent(),
- offset,
- HTMLEditor::EmptyContainers::no);
- NS_ENSURE_STATE(offset != -1);
- // Put a br at the split point
- brNode = htmlEditor->CreateBR(curBlock->GetParentNode(), offset);
- NS_ENSURE_STATE(brNode);
- // Put selection at the split point
- *aHandled = true;
- rv = aSelection.Collapse(curBlock->GetParentNode(), offset);
- // Don't restore the selection
- selectionRestorer.Abort();
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // Else nothing to do!
- } else {
- // We are making a block. Consume a br, if needed.
- nsCOMPtr<nsIContent> brNode =
- htmlEditor->GetNextHTMLNode(parent, offset, true);
- if (brNode && brNode->IsHTMLElement(nsGkAtoms::br)) {
- rv = htmlEditor->DeleteNode(brNode);
- NS_ENSURE_SUCCESS(rv, rv);
- // We don't need to act on this node any more
- arrayOfNodes.RemoveElement(brNode);
- }
- // Make sure we can put a block here
- rv = SplitAsNeeded(blockType, parent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<Element> block =
- htmlEditor->CreateNode(blockType, parent, offset);
- NS_ENSURE_STATE(block);
- // Remember our new block for postprocessing
- mNewBlock = block;
- // Delete anything that was in the list of nodes
- while (!arrayOfNodes.IsEmpty()) {
- OwningNonNull<nsINode> curNode = arrayOfNodes[0];
- rv = htmlEditor->DeleteNode(curNode);
- NS_ENSURE_SUCCESS(rv, rv);
- arrayOfNodes.RemoveElementAt(0);
- }
- // Put selection in new block
- *aHandled = true;
- rv = aSelection.Collapse(block, 0);
- // Don't restore the selection
- selectionRestorer.Abort();
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
- }
- // Okay, now go through all the nodes and make the right kind of blocks, or
- // whatever is approriate. Woohoo! Note: blockquote is handled a little
- // differently.
- if (blockType == nsGkAtoms::blockquote) {
- rv = MakeBlockquote(arrayOfNodes);
- NS_ENSURE_SUCCESS(rv, rv);
- } else if (blockType == nsGkAtoms::normal ||
- blockType == nsGkAtoms::_empty) {
- rv = RemoveBlockStyle(arrayOfNodes);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- rv = ApplyBlockStyle(arrayOfNodes, blockType);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::DidMakeBasicBlock(Selection* aSelection,
- RulesInfo* aInfo,
- nsresult aResult)
-{
- NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
- // check for empty block. if so, put a moz br in it.
- if (!aSelection->Collapsed()) {
- return NS_OK;
- }
-
- NS_ENSURE_STATE(aSelection->GetRangeAt(0) &&
- aSelection->GetRangeAt(0)->GetStartParent());
- nsresult rv =
- InsertMozBRIfNeeded(*aSelection->GetRangeAt(0)->GetStartParent());
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::WillIndent(Selection* aSelection,
- bool* aCancel,
- bool* aHandled)
-{
- NS_ENSURE_STATE(mHTMLEditor);
- if (mHTMLEditor->IsCSSEnabled()) {
- nsresult rv = WillCSSIndent(aSelection, aCancel, aHandled);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- nsresult rv = WillHTMLIndent(aSelection, aCancel, aHandled);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::WillCSSIndent(Selection* aSelection,
- bool* aCancel,
- bool* aHandled)
-{
- if (!aSelection || !aCancel || !aHandled) {
- return NS_ERROR_NULL_POINTER;
- }
-
- WillInsert(*aSelection, aCancel);
-
- // initialize out param
- // we want to ignore result of WillInsert()
- *aCancel = false;
- *aHandled = true;
-
- nsresult rv = NormalizeSelection(aSelection);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_STATE(mHTMLEditor);
- AutoSelectionRestorer selectionRestorer(aSelection, mHTMLEditor);
- nsTArray<OwningNonNull<nsRange>> arrayOfRanges;
- nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
-
- // short circuit: detect case of collapsed selection inside an <li>.
- // just sublist that <li>. This prevents bug 97797.
-
- nsCOMPtr<Element> liNode;
- if (aSelection->Collapsed()) {
- nsCOMPtr<nsINode> node;
- int32_t offset;
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->GetStartNodeAndOffset(aSelection,
- getter_AddRefs(node), &offset);
- NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<Element> block = mHTMLEditor->GetBlock(*node);
- if (block && HTMLEditUtils::IsListItem(block)) {
- liNode = block;
- }
- }
-
- if (liNode) {
- arrayOfNodes.AppendElement(*liNode);
- } else {
- // convert the selection ranges into "promoted" selection ranges:
- // this basically just expands the range to include the immediate
- // block parent, and then further expands to include any ancestors
- // whose children are all in the range
- rv = GetNodesFromSelection(*aSelection, EditAction::indent, arrayOfNodes);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // if nothing visible in list, make an empty block
- if (ListIsEmptyLine(arrayOfNodes)) {
- // get selection location
- NS_ENSURE_STATE(aSelection->RangeCount());
- nsCOMPtr<nsINode> parent = aSelection->GetRangeAt(0)->GetStartParent();
- int32_t offset = aSelection->GetRangeAt(0)->StartOffset();
- NS_ENSURE_STATE(parent);
-
- // make sure we can put a block here
- rv = SplitAsNeeded(*nsGkAtoms::div, parent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<Element> theBlock = mHTMLEditor->CreateNode(nsGkAtoms::div,
- parent, offset);
- NS_ENSURE_STATE(theBlock);
- // remember our new block for postprocessing
- mNewBlock = theBlock;
- ChangeIndentation(*theBlock, Change::plus);
- // delete anything that was in the list of nodes
- while (!arrayOfNodes.IsEmpty()) {
- OwningNonNull<nsINode> curNode = arrayOfNodes[0];
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->DeleteNode(curNode);
- NS_ENSURE_SUCCESS(rv, rv);
- arrayOfNodes.RemoveElementAt(0);
- }
- // put selection in new block
- *aHandled = true;
- rv = aSelection->Collapse(theBlock, 0);
- // Don't restore the selection
- selectionRestorer.Abort();
- return rv;
- }
-
- // Ok, now go through all the nodes and put them in a blockquote,
- // or whatever is appropriate. Wohoo!
- nsCOMPtr<nsINode> curParent;
- nsCOMPtr<Element> curList, curQuote;
- nsCOMPtr<nsIContent> sibling;
- int32_t listCount = arrayOfNodes.Length();
- for (int32_t i = 0; i < listCount; i++) {
- // here's where we actually figure out what to do
- NS_ENSURE_STATE(arrayOfNodes[i]->IsContent());
- nsCOMPtr<nsIContent> curNode = arrayOfNodes[i]->AsContent();
-
- // Ignore all non-editable nodes. Leave them be.
- NS_ENSURE_STATE(mHTMLEditor);
- if (!mHTMLEditor->IsEditable(curNode)) {
- continue;
- }
-
- curParent = curNode->GetParentNode();
- int32_t offset = curParent ? curParent->IndexOf(curNode) : -1;
-
- // some logic for putting list items into nested lists...
- if (HTMLEditUtils::IsList(curParent)) {
- sibling = nullptr;
-
- // Check for whether we should join a list that follows curNode.
- // We do this if the next element is a list, and the list is of the
- // same type (li/ol) as curNode was a part it.
- NS_ENSURE_STATE(mHTMLEditor);
- sibling = mHTMLEditor->GetNextHTMLSibling(curNode);
- if (sibling && HTMLEditUtils::IsList(sibling) &&
- curParent->NodeInfo()->NameAtom() ==
- sibling->NodeInfo()->NameAtom() &&
- curParent->NodeInfo()->NamespaceID() ==
- sibling->NodeInfo()->NamespaceID()) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->MoveNode(curNode, sibling, 0);
- NS_ENSURE_SUCCESS(rv, rv);
- continue;
- }
- // Check for whether we should join a list that preceeds curNode.
- // We do this if the previous element is a list, and the list is of
- // the same type (li/ol) as curNode was a part of.
- NS_ENSURE_STATE(mHTMLEditor);
- sibling = mHTMLEditor->GetPriorHTMLSibling(curNode);
- if (sibling && HTMLEditUtils::IsList(sibling) &&
- curParent->NodeInfo()->NameAtom() ==
- sibling->NodeInfo()->NameAtom() &&
- curParent->NodeInfo()->NamespaceID() ==
- sibling->NodeInfo()->NamespaceID()) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->MoveNode(curNode, sibling, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- continue;
- }
- sibling = nullptr;
-
- // check to see if curList is still appropriate. Which it is if
- // curNode is still right after it in the same list.
- if (curList) {
- NS_ENSURE_STATE(mHTMLEditor);
- sibling = mHTMLEditor->GetPriorHTMLSibling(curNode);
- }
-
- if (!curList || (sibling && sibling != curList)) {
- // create a new nested list of correct type
- rv =
- SplitAsNeeded(*curParent->NodeInfo()->NameAtom(), curParent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_STATE(mHTMLEditor);
- curList = mHTMLEditor->CreateNode(curParent->NodeInfo()->NameAtom(),
- curParent, offset);
- NS_ENSURE_STATE(curList);
- // curList is now the correct thing to put curNode in
- // remember our new block for postprocessing
- mNewBlock = curList;
- }
- // tuck the node into the end of the active list
- uint32_t listLen = curList->Length();
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->MoveNode(curNode, curList, listLen);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // Not a list item.
- else {
- if (curNode && IsBlockNode(*curNode)) {
- ChangeIndentation(*curNode->AsElement(), Change::plus);
- curQuote = nullptr;
- } else {
- if (!curQuote) {
- // First, check that our element can contain a div.
- if (!mTextEditor->CanContainTag(*curParent, *nsGkAtoms::div)) {
- return NS_OK; // cancelled
- }
-
- rv = SplitAsNeeded(*nsGkAtoms::div, curParent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_STATE(mHTMLEditor);
- curQuote = mHTMLEditor->CreateNode(nsGkAtoms::div, curParent,
- offset);
- NS_ENSURE_STATE(curQuote);
- ChangeIndentation(*curQuote, Change::plus);
- // remember our new block for postprocessing
- mNewBlock = curQuote;
- // curQuote is now the correct thing to put curNode in
- }
-
- // tuck the node into the end of the active blockquote
- uint32_t quoteLen = curQuote->Length();
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->MoveNode(curNode, curQuote, quoteLen);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::WillHTMLIndent(Selection* aSelection,
- bool* aCancel,
- bool* aHandled)
-{
- if (!aSelection || !aCancel || !aHandled) {
- return NS_ERROR_NULL_POINTER;
- }
- WillInsert(*aSelection, aCancel);
-
- // initialize out param
- // we want to ignore result of WillInsert()
- *aCancel = false;
- *aHandled = true;
-
- nsresult rv = NormalizeSelection(aSelection);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_STATE(mHTMLEditor);
- AutoSelectionRestorer selectionRestorer(aSelection, mHTMLEditor);
-
- // convert the selection ranges into "promoted" selection ranges:
- // this basically just expands the range to include the immediate
- // block parent, and then further expands to include any ancestors
- // whose children are all in the range
-
- nsTArray<RefPtr<nsRange>> arrayOfRanges;
- GetPromotedRanges(*aSelection, arrayOfRanges, EditAction::indent);
-
- // use these ranges to contruct a list of nodes to act on.
- nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
- rv = GetNodesForOperation(arrayOfRanges, arrayOfNodes, EditAction::indent);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // if nothing visible in list, make an empty block
- if (ListIsEmptyLine(arrayOfNodes)) {
- // get selection location
- NS_ENSURE_STATE(aSelection->RangeCount());
- nsCOMPtr<nsINode> parent = aSelection->GetRangeAt(0)->GetStartParent();
- int32_t offset = aSelection->GetRangeAt(0)->StartOffset();
- NS_ENSURE_STATE(parent);
-
- // make sure we can put a block here
- rv = SplitAsNeeded(*nsGkAtoms::blockquote, parent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<Element> theBlock = mHTMLEditor->CreateNode(nsGkAtoms::blockquote,
- parent, offset);
- NS_ENSURE_STATE(theBlock);
- // remember our new block for postprocessing
- mNewBlock = theBlock;
- // delete anything that was in the list of nodes
- while (!arrayOfNodes.IsEmpty()) {
- OwningNonNull<nsINode> curNode = arrayOfNodes[0];
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->DeleteNode(curNode);
- NS_ENSURE_SUCCESS(rv, rv);
- arrayOfNodes.RemoveElementAt(0);
- }
- // put selection in new block
- *aHandled = true;
- rv = aSelection->Collapse(theBlock, 0);
- // Don't restore the selection
- selectionRestorer.Abort();
- return rv;
- }
-
- // Ok, now go through all the nodes and put them in a blockquote,
- // or whatever is appropriate. Wohoo!
- nsCOMPtr<nsINode> curParent;
- nsCOMPtr<nsIContent> sibling;
- nsCOMPtr<Element> curList, curQuote, indentedLI;
- int32_t listCount = arrayOfNodes.Length();
- for (int32_t i = 0; i < listCount; i++) {
- // here's where we actually figure out what to do
- NS_ENSURE_STATE(arrayOfNodes[i]->IsContent());
- nsCOMPtr<nsIContent> curNode = arrayOfNodes[i]->AsContent();
-
- // Ignore all non-editable nodes. Leave them be.
- NS_ENSURE_STATE(mHTMLEditor);
- if (!mHTMLEditor->IsEditable(curNode)) {
- continue;
- }
-
- curParent = curNode->GetParentNode();
- int32_t offset = curParent ? curParent->IndexOf(curNode) : -1;
-
- // some logic for putting list items into nested lists...
- if (HTMLEditUtils::IsList(curParent)) {
- sibling = nullptr;
-
- // Check for whether we should join a list that follows curNode.
- // We do this if the next element is a list, and the list is of the
- // same type (li/ol) as curNode was a part it.
- NS_ENSURE_STATE(mHTMLEditor);
- sibling = mHTMLEditor->GetNextHTMLSibling(curNode);
- if (sibling && HTMLEditUtils::IsList(sibling) &&
- curParent->NodeInfo()->NameAtom() ==
- sibling->NodeInfo()->NameAtom() &&
- curParent->NodeInfo()->NamespaceID() ==
- sibling->NodeInfo()->NamespaceID()) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->MoveNode(curNode, sibling, 0);
- NS_ENSURE_SUCCESS(rv, rv);
- continue;
- }
-
- // Check for whether we should join a list that preceeds curNode.
- // We do this if the previous element is a list, and the list is of
- // the same type (li/ol) as curNode was a part of.
- NS_ENSURE_STATE(mHTMLEditor);
- sibling = mHTMLEditor->GetPriorHTMLSibling(curNode);
- if (sibling && HTMLEditUtils::IsList(sibling) &&
- curParent->NodeInfo()->NameAtom() ==
- sibling->NodeInfo()->NameAtom() &&
- curParent->NodeInfo()->NamespaceID() ==
- sibling->NodeInfo()->NamespaceID()) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->MoveNode(curNode, sibling, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- continue;
- }
-
- sibling = nullptr;
-
- // check to see if curList is still appropriate. Which it is if
- // curNode is still right after it in the same list.
- if (curList) {
- NS_ENSURE_STATE(mHTMLEditor);
- sibling = mHTMLEditor->GetPriorHTMLSibling(curNode);
- }
-
- if (!curList || (sibling && sibling != curList)) {
- // create a new nested list of correct type
- rv =
- SplitAsNeeded(*curParent->NodeInfo()->NameAtom(), curParent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_STATE(mHTMLEditor);
- curList = mHTMLEditor->CreateNode(curParent->NodeInfo()->NameAtom(),
- curParent, offset);
- NS_ENSURE_STATE(curList);
- // curList is now the correct thing to put curNode in
- // remember our new block for postprocessing
- mNewBlock = curList;
- }
- // tuck the node into the end of the active list
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->MoveNode(curNode, curList, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- // forget curQuote, if any
- curQuote = nullptr;
- }
- // Not a list item, use blockquote?
- else {
- // if we are inside a list item, we don't want to blockquote, we want
- // to sublist the list item. We may have several nodes listed in the
- // array of nodes to act on, that are in the same list item. Since
- // we only want to indent that li once, we must keep track of the most
- // recent indented list item, and not indent it if we find another node
- // to act on that is still inside the same li.
- nsCOMPtr<Element> listItem = IsInListItem(curNode);
- if (listItem) {
- if (indentedLI == listItem) {
- // already indented this list item
- continue;
- }
- curParent = listItem->GetParentNode();
- offset = curParent ? curParent->IndexOf(listItem) : -1;
- // check to see if curList is still appropriate. Which it is if
- // curNode is still right after it in the same list.
- if (curList) {
- sibling = nullptr;
- NS_ENSURE_STATE(mHTMLEditor);
- sibling = mHTMLEditor->GetPriorHTMLSibling(curNode);
- }
-
- if (!curList || (sibling && sibling != curList)) {
- // create a new nested list of correct type
- rv = SplitAsNeeded(*curParent->NodeInfo()->NameAtom(), curParent,
- offset);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_STATE(mHTMLEditor);
- curList = mHTMLEditor->CreateNode(curParent->NodeInfo()->NameAtom(),
- curParent, offset);
- NS_ENSURE_STATE(curList);
- }
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->MoveNode(listItem, curList, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- // remember we indented this li
- indentedLI = listItem;
- } else {
- // need to make a blockquote to put things in if we haven't already,
- // or if this node doesn't go in blockquote we used earlier.
- // One reason it might not go in prio blockquote is if we are now
- // in a different table cell.
- if (curQuote && InDifferentTableElements(curQuote, curNode)) {
- curQuote = nullptr;
- }
-
- if (!curQuote) {
- // First, check that our element can contain a blockquote.
- if (!mTextEditor->CanContainTag(*curParent, *nsGkAtoms::blockquote)) {
- return NS_OK; // cancelled
- }
-
- rv = SplitAsNeeded(*nsGkAtoms::blockquote, curParent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_STATE(mHTMLEditor);
- curQuote = mHTMLEditor->CreateNode(nsGkAtoms::blockquote, curParent,
- offset);
- NS_ENSURE_STATE(curQuote);
- // remember our new block for postprocessing
- mNewBlock = curQuote;
- // curQuote is now the correct thing to put curNode in
- }
-
- // tuck the node into the end of the active blockquote
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->MoveNode(curNode, curQuote, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- // forget curList, if any
- curList = nullptr;
- }
- }
- }
- return NS_OK;
-}
-
-
-nsresult
-HTMLEditRules::WillOutdent(Selection& aSelection,
- bool* aCancel,
- bool* aHandled)
-{
- MOZ_ASSERT(aCancel && aHandled);
- *aCancel = false;
- *aHandled = true;
- nsCOMPtr<nsIContent> rememberedLeftBQ, rememberedRightBQ;
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
- bool useCSS = htmlEditor->IsCSSEnabled();
-
- nsresult rv = NormalizeSelection(&aSelection);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Some scoping for selection resetting - we may need to tweak it
- {
- AutoSelectionRestorer selectionRestorer(&aSelection, htmlEditor);
-
- // Convert the selection ranges into "promoted" selection ranges: this
- // basically just expands the range to include the immediate block parent,
- // and then further expands to include any ancestors whose children are all
- // in the range
- nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
- rv = GetNodesFromSelection(aSelection, EditAction::outdent, arrayOfNodes);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Okay, now go through all the nodes and remove a level of blockquoting,
- // or whatever is appropriate. Wohoo!
-
- nsCOMPtr<Element> curBlockQuote;
- nsCOMPtr<nsIContent> firstBQChild, lastBQChild;
- bool curBlockQuoteIsIndentedWithCSS = false;
- for (uint32_t i = 0; i < arrayOfNodes.Length(); i++) {
- if (!arrayOfNodes[i]->IsContent()) {
- continue;
- }
- OwningNonNull<nsIContent> curNode = *arrayOfNodes[i]->AsContent();
-
- // Here's where we actually figure out what to do
- nsCOMPtr<nsINode> curParent = curNode->GetParentNode();
- int32_t offset = curParent ? curParent->IndexOf(curNode) : -1;
-
- // Is it a blockquote?
- if (curNode->IsHTMLElement(nsGkAtoms::blockquote)) {
- // If it is a blockquote, remove it. So we need to finish up dealng
- // with any curBlockQuote first.
- if (curBlockQuote) {
- rv = OutdentPartOfBlock(*curBlockQuote, *firstBQChild, *lastBQChild,
- curBlockQuoteIsIndentedWithCSS,
- getter_AddRefs(rememberedLeftBQ),
- getter_AddRefs(rememberedRightBQ));
- NS_ENSURE_SUCCESS(rv, rv);
- curBlockQuote = nullptr;
- firstBQChild = nullptr;
- lastBQChild = nullptr;
- curBlockQuoteIsIndentedWithCSS = false;
- }
- rv = htmlEditor->RemoveBlockContainer(curNode);
- NS_ENSURE_SUCCESS(rv, rv);
- continue;
- }
- // Is it a block with a 'margin' property?
- if (useCSS && IsBlockNode(curNode)) {
- nsIAtom& marginProperty =
- MarginPropertyAtomForIndent(*htmlEditor->mCSSEditUtils, curNode);
- nsAutoString value;
- htmlEditor->mCSSEditUtils->GetSpecifiedProperty(curNode,
- marginProperty,
- value);
- float f;
- nsCOMPtr<nsIAtom> unit;
- NS_ENSURE_STATE(htmlEditor);
- htmlEditor->mCSSEditUtils->ParseLength(value, &f,
- getter_AddRefs(unit));
- if (f > 0) {
- ChangeIndentation(*curNode->AsElement(), Change::minus);
- continue;
- }
- }
- // Is it a list item?
- if (HTMLEditUtils::IsListItem(curNode)) {
- // If it is a list item, that means we are not outdenting whole list.
- // So we need to finish up dealing with any curBlockQuote, and then pop
- // this list item.
- if (curBlockQuote) {
- rv = OutdentPartOfBlock(*curBlockQuote, *firstBQChild, *lastBQChild,
- curBlockQuoteIsIndentedWithCSS,
- getter_AddRefs(rememberedLeftBQ),
- getter_AddRefs(rememberedRightBQ));
- NS_ENSURE_SUCCESS(rv, rv);
- curBlockQuote = nullptr;
- firstBQChild = nullptr;
- lastBQChild = nullptr;
- curBlockQuoteIsIndentedWithCSS = false;
- }
- bool unused;
- rv = PopListItem(GetAsDOMNode(curNode), &unused);
- NS_ENSURE_SUCCESS(rv, rv);
- continue;
- }
- // Do we have a blockquote that we are already committed to removing?
- if (curBlockQuote) {
- // If so, is this node a descendant?
- if (EditorUtils::IsDescendantOf(curNode, curBlockQuote)) {
- lastBQChild = curNode;
- // Then we don't need to do anything different for this node
- continue;
- }
- // Otherwise, we have progressed beyond end of curBlockQuote, so
- // let's handle it now. We need to remove the portion of
- // curBlockQuote that contains [firstBQChild - lastBQChild].
- rv = OutdentPartOfBlock(*curBlockQuote, *firstBQChild, *lastBQChild,
- curBlockQuoteIsIndentedWithCSS,
- getter_AddRefs(rememberedLeftBQ),
- getter_AddRefs(rememberedRightBQ));
- NS_ENSURE_SUCCESS(rv, rv);
- curBlockQuote = nullptr;
- firstBQChild = nullptr;
- lastBQChild = nullptr;
- curBlockQuoteIsIndentedWithCSS = false;
- // Fall out and handle curNode
- }
-
- // Are we inside a blockquote?
- OwningNonNull<nsINode> n = curNode;
- curBlockQuoteIsIndentedWithCSS = false;
- // Keep looking up the hierarchy as long as we don't hit the body or the
- // active editing host or a table element (other than an entire table)
- while (!n->IsHTMLElement(nsGkAtoms::body) &&
- htmlEditor->IsDescendantOfEditorRoot(n) &&
- (n->IsHTMLElement(nsGkAtoms::table) ||
- !HTMLEditUtils::IsTableElement(n))) {
- if (!n->GetParentNode()) {
- break;
- }
- n = *n->GetParentNode();
- if (n->IsHTMLElement(nsGkAtoms::blockquote)) {
- // If so, remember it and the first node we are taking out of it.
- curBlockQuote = n->AsElement();
- firstBQChild = curNode;
- lastBQChild = curNode;
- break;
- } else if (useCSS) {
- nsIAtom& marginProperty =
- MarginPropertyAtomForIndent(*htmlEditor->mCSSEditUtils, curNode);
- nsAutoString value;
- htmlEditor->mCSSEditUtils->GetSpecifiedProperty(*n, marginProperty,
- value);
- float f;
- nsCOMPtr<nsIAtom> unit;
- htmlEditor->mCSSEditUtils->ParseLength(value, &f, getter_AddRefs(unit));
- if (f > 0 && !(HTMLEditUtils::IsList(curParent) &&
- HTMLEditUtils::IsList(curNode))) {
- curBlockQuote = n->AsElement();
- firstBQChild = curNode;
- lastBQChild = curNode;
- curBlockQuoteIsIndentedWithCSS = true;
- break;
- }
- }
- }
-
- if (!curBlockQuote) {
- // Couldn't find enclosing blockquote. Handle list cases.
- if (HTMLEditUtils::IsList(curParent)) {
- // Move node out of list
- if (HTMLEditUtils::IsList(curNode)) {
- // Just unwrap this sublist
- rv = htmlEditor->RemoveBlockContainer(curNode);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // handled list item case above
- } else if (HTMLEditUtils::IsList(curNode)) {
- // node is a list, but parent is non-list: move list items out
- nsCOMPtr<nsIContent> child = curNode->GetLastChild();
- while (child) {
- if (HTMLEditUtils::IsListItem(child)) {
- bool unused;
- rv = PopListItem(GetAsDOMNode(child), &unused);
- NS_ENSURE_SUCCESS(rv, rv);
- } else if (HTMLEditUtils::IsList(child)) {
- // We have an embedded list, so move it out from under the parent
- // list. Be sure to put it after the parent list because this
- // loop iterates backwards through the parent's list of children.
-
- rv = htmlEditor->MoveNode(child, curParent, offset + 1);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // Delete any non-list items for now
- rv = htmlEditor->DeleteNode(child);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- child = curNode->GetLastChild();
- }
- // Delete the now-empty list
- rv = htmlEditor->RemoveBlockContainer(curNode);
- NS_ENSURE_SUCCESS(rv, rv);
- } else if (useCSS) {
- nsCOMPtr<Element> element;
- if (curNode->GetAsText()) {
- // We want to outdent the parent of text nodes
- element = curNode->GetParentElement();
- } else if (curNode->IsElement()) {
- element = curNode->AsElement();
- }
- if (element) {
- ChangeIndentation(*element, Change::minus);
- }
- }
- }
- }
- if (curBlockQuote) {
- // We have a blockquote we haven't finished handling
- rv = OutdentPartOfBlock(*curBlockQuote, *firstBQChild, *lastBQChild,
- curBlockQuoteIsIndentedWithCSS,
- getter_AddRefs(rememberedLeftBQ),
- getter_AddRefs(rememberedRightBQ));
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- // Make sure selection didn't stick to last piece of content in old bq (only
- // a problem for collapsed selections)
- if (rememberedLeftBQ || rememberedRightBQ) {
- if (aSelection.Collapsed()) {
- // Push selection past end of rememberedLeftBQ
- NS_ENSURE_TRUE(aSelection.GetRangeAt(0), NS_OK);
- nsCOMPtr<nsINode> startNode = aSelection.GetRangeAt(0)->GetStartParent();
- int32_t startOffset = aSelection.GetRangeAt(0)->StartOffset();
- if (rememberedLeftBQ &&
- (startNode == rememberedLeftBQ ||
- EditorUtils::IsDescendantOf(startNode, rememberedLeftBQ))) {
- // Selection is inside rememberedLeftBQ - push it past it.
- startNode = rememberedLeftBQ->GetParentNode();
- startOffset = startNode ? 1 + startNode->IndexOf(rememberedLeftBQ) : 0;
- aSelection.Collapse(startNode, startOffset);
- }
- // And pull selection before beginning of rememberedRightBQ
- startNode = aSelection.GetRangeAt(0)->GetStartParent();
- startOffset = aSelection.GetRangeAt(0)->StartOffset();
- if (rememberedRightBQ &&
- (startNode == rememberedRightBQ ||
- EditorUtils::IsDescendantOf(startNode, rememberedRightBQ))) {
- // Selection is inside rememberedRightBQ - push it before it.
- startNode = rememberedRightBQ->GetParentNode();
- startOffset = startNode ? startNode->IndexOf(rememberedRightBQ) : -1;
- aSelection.Collapse(startNode, startOffset);
- }
- }
- return NS_OK;
- }
- return NS_OK;
-}
-
-
-/**
- * RemovePartOfBlock() splits aBlock and move aStartChild to aEndChild out of
- * aBlock.
- */
-nsresult
-HTMLEditRules::RemovePartOfBlock(Element& aBlock,
- nsIContent& aStartChild,
- nsIContent& aEndChild)
-{
- SplitBlock(aBlock, aStartChild, aEndChild);
- // Get rid of part of blockquote we are outdenting
-
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv = mHTMLEditor->RemoveBlockContainer(aBlock);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-void
-HTMLEditRules::SplitBlock(Element& aBlock,
- nsIContent& aStartChild,
- nsIContent& aEndChild,
- nsIContent** aOutLeftNode,
- nsIContent** aOutRightNode,
- nsIContent** aOutMiddleNode)
-{
- // aStartChild and aEndChild must be exclusive descendants of aBlock
- MOZ_ASSERT(EditorUtils::IsDescendantOf(&aStartChild, &aBlock) &&
- EditorUtils::IsDescendantOf(&aEndChild, &aBlock));
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- // Get split point location
- OwningNonNull<nsIContent> startParent = *aStartChild.GetParent();
- int32_t startOffset = startParent->IndexOf(&aStartChild);
-
- // Do the splits!
- nsCOMPtr<nsIContent> newMiddleNode1;
- htmlEditor->SplitNodeDeep(aBlock, startParent, startOffset,
- HTMLEditor::EmptyContainers::no,
- aOutLeftNode, getter_AddRefs(newMiddleNode1));
-
- // Get split point location
- OwningNonNull<nsIContent> endParent = *aEndChild.GetParent();
- // +1 because we want to be after the child
- int32_t endOffset = 1 + endParent->IndexOf(&aEndChild);
-
- // Do the splits!
- nsCOMPtr<nsIContent> newMiddleNode2;
- htmlEditor->SplitNodeDeep(aBlock, endParent, endOffset,
- HTMLEditor::EmptyContainers::no,
- getter_AddRefs(newMiddleNode2), aOutRightNode);
-
- if (aOutMiddleNode) {
- if (newMiddleNode2) {
- newMiddleNode2.forget(aOutMiddleNode);
- } else {
- newMiddleNode1.forget(aOutMiddleNode);
- }
- }
-}
-
-nsresult
-HTMLEditRules::OutdentPartOfBlock(Element& aBlock,
- nsIContent& aStartChild,
- nsIContent& aEndChild,
- bool aIsBlockIndentedWithCSS,
- nsIContent** aOutLeftNode,
- nsIContent** aOutRightNode)
-{
- MOZ_ASSERT(aOutLeftNode && aOutRightNode);
-
- nsCOMPtr<nsIContent> middleNode;
- SplitBlock(aBlock, aStartChild, aEndChild, aOutLeftNode, aOutRightNode,
- getter_AddRefs(middleNode));
-
- NS_ENSURE_STATE(middleNode);
-
- if (!aIsBlockIndentedWithCSS) {
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv = mHTMLEditor->RemoveBlockContainer(*middleNode);
- NS_ENSURE_SUCCESS(rv, rv);
- } else if (middleNode->IsElement()) {
- // We do nothing if middleNode isn't an element
- nsresult rv = ChangeIndentation(*middleNode->AsElement(), Change::minus);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-/**
- * ConvertListType() converts list type and list item type.
- */
-nsresult
-HTMLEditRules::ConvertListType(Element* aList,
- Element** aOutList,
- nsIAtom* aListType,
- nsIAtom* aItemType)
-{
- MOZ_ASSERT(aList);
- MOZ_ASSERT(aOutList);
- MOZ_ASSERT(aListType);
- MOZ_ASSERT(aItemType);
-
- nsCOMPtr<nsINode> child = aList->GetFirstChild();
- while (child) {
- if (child->IsElement()) {
- dom::Element* element = child->AsElement();
- if (HTMLEditUtils::IsListItem(element) &&
- !element->IsHTMLElement(aItemType)) {
- child = mHTMLEditor->ReplaceContainer(element, aItemType);
- NS_ENSURE_STATE(child);
- } else if (HTMLEditUtils::IsList(element) &&
- !element->IsHTMLElement(aListType)) {
- nsCOMPtr<dom::Element> temp;
- nsresult rv = ConvertListType(child->AsElement(), getter_AddRefs(temp),
- aListType, aItemType);
- NS_ENSURE_SUCCESS(rv, rv);
- child = temp.forget();
- }
- }
- child = child->GetNextSibling();
- }
-
- if (aList->IsHTMLElement(aListType)) {
- nsCOMPtr<dom::Element> list = aList->AsElement();
- list.forget(aOutList);
- return NS_OK;
- }
-
- *aOutList = mHTMLEditor->ReplaceContainer(aList, aListType).take();
- NS_ENSURE_STATE(aOutList);
-
- return NS_OK;
-}
-
-
-/**
- * CreateStyleForInsertText() takes care of clearing and setting appropriate
- * style nodes for text insertion.
- */
-nsresult
-HTMLEditRules::CreateStyleForInsertText(Selection& aSelection,
- nsIDocument& aDoc)
-{
- MOZ_ASSERT(mHTMLEditor->mTypeInState);
-
- bool weDidSomething = false;
- NS_ENSURE_STATE(aSelection.GetRangeAt(0));
- nsCOMPtr<nsINode> node = aSelection.GetRangeAt(0)->GetStartParent();
- int32_t offset = aSelection.GetRangeAt(0)->StartOffset();
-
- // next examine our present style and make sure default styles are either
- // present or explicitly overridden. If neither, add the default style to
- // the TypeInState
- int32_t length = mHTMLEditor->mDefaultStyles.Length();
- for (int32_t j = 0; j < length; j++) {
- PropItem* propItem = mHTMLEditor->mDefaultStyles[j];
- MOZ_ASSERT(propItem);
- bool bFirst, bAny, bAll;
-
- // GetInlineProperty also examine TypeInState. The only gotcha here is
- // that a cleared property looks like an unset property. For now I'm
- // assuming that's not a problem: that default styles will always be
- // multivalue styles (like font face or size) where clearing the style
- // means we want to go back to the default. If we ever wanted a "toggle"
- // style like bold for a default, though, I'll have to add code to detect
- // the difference between unset and explicitly cleared, else user would
- // never be able to unbold, for instance.
- nsAutoString curValue;
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->GetInlinePropertyBase(*propItem->tag, &propItem->attr,
- nullptr, &bFirst, &bAny, &bAll,
- &curValue, false);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!bAny) {
- // no style set for this prop/attr
- mHTMLEditor->mTypeInState->SetProp(propItem->tag, propItem->attr,
- propItem->value);
- }
- }
-
- nsCOMPtr<Element> rootElement = aDoc.GetRootElement();
- NS_ENSURE_STATE(rootElement);
-
- // process clearing any styles first
- UniquePtr<PropItem> item =
- Move(mHTMLEditor->mTypeInState->TakeClearProperty());
- while (item && node != rootElement) {
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->ClearStyle(address_of(node), &offset,
- item->tag, &item->attr);
- NS_ENSURE_SUCCESS(rv, rv);
- item = Move(mHTMLEditor->mTypeInState->TakeClearProperty());
- weDidSomething = true;
- }
-
- // then process setting any styles
- int32_t relFontSize = mHTMLEditor->mTypeInState->TakeRelativeFontSize();
- item = Move(mHTMLEditor->mTypeInState->TakeSetProperty());
-
- if (item || relFontSize) {
- // we have at least one style to add; make a new text node to insert style
- // nodes above.
- if (RefPtr<Text> text = node->GetAsText()) {
- // if we are in a text node, split it
- NS_ENSURE_STATE(mHTMLEditor);
- offset = mHTMLEditor->SplitNodeDeep(*text, *text, offset);
- NS_ENSURE_STATE(offset != -1);
- node = node->GetParentNode();
- }
- if (!mHTMLEditor->IsContainer(node)) {
- return NS_OK;
- }
- OwningNonNull<Text> newNode = aDoc.CreateTextNode(EmptyString());
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv = mHTMLEditor->InsertNode(*newNode, *node, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- node = newNode;
- offset = 0;
- weDidSomething = true;
-
- if (relFontSize) {
- // dir indicated bigger versus smaller. 1 = bigger, -1 = smaller
- HTMLEditor::FontSize dir = relFontSize > 0 ?
- HTMLEditor::FontSize::incr : HTMLEditor::FontSize::decr;
- for (int32_t j = 0; j < DeprecatedAbs(relFontSize); j++) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->RelativeFontChangeOnTextNode(dir, newNode, 0, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- while (item) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->SetInlinePropertyOnNode(*node->AsContent(),
- *item->tag, &item->attr,
- item->value);
- NS_ENSURE_SUCCESS(rv, rv);
- item = mHTMLEditor->mTypeInState->TakeSetProperty();
- }
- }
- if (weDidSomething) {
- return aSelection.Collapse(node, offset);
- }
-
- return NS_OK;
-}
-
-
-/**
- * Figure out if aNode is (or is inside) an empty block. A block can have
- * children and still be considered empty, if the children are empty or
- * non-editable.
- */
-nsresult
-HTMLEditRules::IsEmptyBlock(Element& aNode,
- bool* aOutIsEmptyBlock,
- MozBRCounts aMozBRCounts)
-{
- MOZ_ASSERT(aOutIsEmptyBlock);
- *aOutIsEmptyBlock = true;
-
- NS_ENSURE_TRUE(IsBlockNode(aNode), NS_ERROR_NULL_POINTER);
-
- return mHTMLEditor->IsEmptyNode(aNode.AsDOMNode(), aOutIsEmptyBlock,
- aMozBRCounts == MozBRCounts::yes ? false
- : true);
-}
-
-
-nsresult
-HTMLEditRules::WillAlign(Selection& aSelection,
- const nsAString& aAlignType,
- bool* aCancel,
- bool* aHandled)
-{
- MOZ_ASSERT(aCancel && aHandled);
-
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- WillInsert(aSelection, aCancel);
-
- // Initialize out param. We want to ignore result of WillInsert().
- *aCancel = false;
- *aHandled = false;
-
- nsresult rv = NormalizeSelection(&aSelection);
- NS_ENSURE_SUCCESS(rv, rv);
- AutoSelectionRestorer selectionRestorer(&aSelection, htmlEditor);
-
- // Convert the selection ranges into "promoted" selection ranges: This
- // basically just expands the range to include the immediate block parent,
- // and then further expands to include any ancestors whose children are all
- // in the range
- *aHandled = true;
- nsTArray<OwningNonNull<nsINode>> nodeArray;
- rv = GetNodesFromSelection(aSelection, EditAction::align, nodeArray);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // If we don't have any nodes, or we have only a single br, then we are
- // creating an empty alignment div. We have to do some different things for
- // these.
- bool emptyDiv = nodeArray.IsEmpty();
- if (nodeArray.Length() == 1) {
- OwningNonNull<nsINode> node = nodeArray[0];
-
- if (HTMLEditUtils::SupportsAlignAttr(GetAsDOMNode(node))) {
- // The node is a table element, an hr, a paragraph, a div or a section
- // header; in HTML 4, it can directly carry the ALIGN attribute and we
- // don't need to make a div! If we are in CSS mode, all the work is done
- // in AlignBlock
- rv = AlignBlock(*node->AsElement(), aAlignType, ContentsOnly::yes);
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
- }
-
- if (TextEditUtils::IsBreak(node)) {
- // The special case emptyDiv code (below) that consumes BRs can cause
- // tables to split if the start node of the selection is not in a table
- // cell or caption, for example parent is a <tr>. Avoid this unnecessary
- // splitting if possible by leaving emptyDiv FALSE so that we fall
- // through to the normal case alignment code.
- //
- // XXX: It seems a little error prone for the emptyDiv special case code
- // to assume that the start node of the selection is the parent of the
- // single node in the nodeArray, as the paragraph above points out. Do we
- // rely on the selection start node because of the fact that nodeArray
- // can be empty? We should probably revisit this issue. - kin
-
- NS_ENSURE_STATE(aSelection.GetRangeAt(0) &&
- aSelection.GetRangeAt(0)->GetStartParent());
- OwningNonNull<nsINode> parent =
- *aSelection.GetRangeAt(0)->GetStartParent();
-
- emptyDiv = !HTMLEditUtils::IsTableElement(parent) ||
- HTMLEditUtils::IsTableCellOrCaption(parent);
- }
- }
- if (emptyDiv) {
- nsCOMPtr<nsINode> parent =
- aSelection.GetRangeAt(0) ? aSelection.GetRangeAt(0)->GetStartParent()
- : nullptr;
- NS_ENSURE_STATE(parent);
- int32_t offset = aSelection.GetRangeAt(0)->StartOffset();
-
- rv = SplitAsNeeded(*nsGkAtoms::div, parent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- // Consume a trailing br, if any. This is to keep an alignment from
- // creating extra lines, if possible.
- nsCOMPtr<nsIContent> brContent =
- htmlEditor->GetNextHTMLNode(parent, offset);
- if (brContent && TextEditUtils::IsBreak(brContent)) {
- // Making use of html structure... if next node after where we are
- // putting our div is not a block, then the br we found is in same block
- // we are, so it's safe to consume it.
- nsCOMPtr<nsIContent> sibling = htmlEditor->GetNextHTMLSibling(parent,
- offset);
- if (sibling && !IsBlockNode(*sibling)) {
- rv = htmlEditor->DeleteNode(brContent);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- nsCOMPtr<Element> div = htmlEditor->CreateNode(nsGkAtoms::div, parent,
- offset);
- NS_ENSURE_STATE(div);
- // Remember our new block for postprocessing
- mNewBlock = div;
- // Set up the alignment on the div, using HTML or CSS
- rv = AlignBlock(*div, aAlignType, ContentsOnly::yes);
- NS_ENSURE_SUCCESS(rv, rv);
- *aHandled = true;
- // Put in a moz-br so that it won't get deleted
- rv = CreateMozBR(div->AsDOMNode(), 0);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = aSelection.Collapse(div, 0);
- // Don't restore the selection
- selectionRestorer.Abort();
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
- }
-
- // Next we detect all the transitions in the array, where a transition
- // means that adjacent nodes in the array don't have the same parent.
-
- nsTArray<bool> transitionList;
- MakeTransitionList(nodeArray, transitionList);
-
- // Okay, now go through all the nodes and give them an align attrib or put
- // them in a div, or whatever is appropriate. Woohoo!
-
- nsCOMPtr<Element> curDiv;
- bool useCSS = htmlEditor->IsCSSEnabled();
- for (size_t i = 0; i < nodeArray.Length(); i++) {
- auto& curNode = nodeArray[i];
- // Here's where we actually figure out what to do
-
- // Ignore all non-editable nodes. Leave them be.
- if (!htmlEditor->IsEditable(curNode)) {
- continue;
- }
-
- // The node is a table element, an hr, a paragraph, a div or a section
- // header; in HTML 4, it can directly carry the ALIGN attribute and we
- // don't need to nest it, just set the alignment. In CSS, assign the
- // corresponding CSS styles in AlignBlock
- if (HTMLEditUtils::SupportsAlignAttr(GetAsDOMNode(curNode))) {
- rv = AlignBlock(*curNode->AsElement(), aAlignType, ContentsOnly::no);
- NS_ENSURE_SUCCESS(rv, rv);
- // Clear out curDiv so that we don't put nodes after this one into it
- curDiv = nullptr;
- continue;
- }
-
- nsCOMPtr<nsINode> curParent = curNode->GetParentNode();
- if (!curParent) {
- continue;
- }
-
- int32_t offset = curParent->IndexOf(curNode);
-
- // Skip insignificant formatting text nodes to prevent unnecessary
- // structure splitting!
- bool isEmptyTextNode = false;
- if (curNode->GetAsText() &&
- ((HTMLEditUtils::IsTableElement(curParent) &&
- !HTMLEditUtils::IsTableCellOrCaption(*curParent)) ||
- HTMLEditUtils::IsList(curParent) ||
- (NS_SUCCEEDED(htmlEditor->IsEmptyNode(curNode, &isEmptyTextNode)) &&
- isEmptyTextNode))) {
- continue;
- }
-
- // If it's a list item, or a list inside a list, forget any "current" div,
- // and instead put divs inside the appropriate block (td, li, etc.)
- if (HTMLEditUtils::IsListItem(curNode) ||
- HTMLEditUtils::IsList(curNode)) {
- rv = RemoveAlignment(GetAsDOMNode(curNode), aAlignType, true);
- NS_ENSURE_SUCCESS(rv, rv);
- if (useCSS) {
- htmlEditor->mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
- curNode->AsElement(), nullptr, nsGkAtoms::align,
- &aAlignType, false);
- curDiv = nullptr;
- continue;
- }
- if (HTMLEditUtils::IsList(curParent)) {
- // If we don't use CSS, add a contraint to list element: they have to
- // be inside another list, i.e., >= second level of nesting
- rv = AlignInnerBlocks(*curNode, &aAlignType);
- NS_ENSURE_SUCCESS(rv, rv);
- curDiv = nullptr;
- continue;
- }
- // Clear out curDiv so that we don't put nodes after this one into it
- }
-
- // Need to make a div to put things in if we haven't already, or if this
- // node doesn't go in div we used earlier.
- if (!curDiv || transitionList[i]) {
- // First, check that our element can contain a div.
- if (!mTextEditor->CanContainTag(*curParent, *nsGkAtoms::div)) {
- // Cancelled
- return NS_OK;
- }
-
- rv = SplitAsNeeded(*nsGkAtoms::div, curParent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- curDiv = htmlEditor->CreateNode(nsGkAtoms::div, curParent, offset);
- NS_ENSURE_STATE(curDiv);
- // Remember our new block for postprocessing
- mNewBlock = curDiv;
- // Set up the alignment on the div
- rv = AlignBlock(*curDiv, aAlignType, ContentsOnly::yes);
- }
-
- NS_ENSURE_STATE(curNode->IsContent());
-
- // Tuck the node into the end of the active div
- rv = htmlEditor->MoveNode(curNode->AsContent(), curDiv, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-
-/**
- * AlignInnerBlocks() aligns inside table cells or list items.
- */
-nsresult
-HTMLEditRules::AlignInnerBlocks(nsINode& aNode,
- const nsAString* alignType)
-{
- NS_ENSURE_TRUE(alignType, NS_ERROR_NULL_POINTER);
-
- // Gather list of table cells or list items
- nsTArray<OwningNonNull<nsINode>> nodeArray;
- TableCellAndListItemFunctor functor;
- DOMIterator iter(aNode);
- iter.AppendList(functor, nodeArray);
-
- // Now that we have the list, align their contents as requested
- for (auto& node : nodeArray) {
- nsresult rv = AlignBlockContents(GetAsDOMNode(node), alignType);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-
-/**
- * AlignBlockContents() aligns contents of a block element.
- */
-nsresult
-HTMLEditRules::AlignBlockContents(nsIDOMNode* aNode,
- const nsAString* alignType)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- NS_ENSURE_TRUE(node && alignType, NS_ERROR_NULL_POINTER);
- nsCOMPtr<nsIContent> firstChild, lastChild;
-
- bool useCSS = mHTMLEditor->IsCSSEnabled();
-
- NS_ENSURE_STATE(mHTMLEditor);
- firstChild = mHTMLEditor->GetFirstEditableChild(*node);
- NS_ENSURE_STATE(mHTMLEditor);
- lastChild = mHTMLEditor->GetLastEditableChild(*node);
- if (!firstChild) {
- // this cell has no content, nothing to align
- } else if (firstChild == lastChild &&
- firstChild->IsHTMLElement(nsGkAtoms::div)) {
- // the cell already has a div containing all of its content: just
- // act on this div.
- RefPtr<Element> divElem = firstChild->AsElement();
- if (useCSS) {
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv = mHTMLEditor->SetAttributeOrEquivalent(divElem,
- nsGkAtoms::align,
- *alignType, false);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv = mHTMLEditor->SetAttribute(divElem, nsGkAtoms::align,
- *alignType);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- } else {
- // else we need to put in a div, set the alignment, and toss in all the children
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<Element> divElem = mHTMLEditor->CreateNode(nsGkAtoms::div, node, 0);
- NS_ENSURE_STATE(divElem);
- // set up the alignment on the div
- if (useCSS) {
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->SetAttributeOrEquivalent(divElem, nsGkAtoms::align,
- *alignType, false);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->SetAttribute(divElem, nsGkAtoms::align, *alignType);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- // tuck the children into the end of the active div
- while (lastChild && (lastChild != divElem)) {
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv = mHTMLEditor->MoveNode(lastChild, divElem, 0);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_STATE(mHTMLEditor);
- lastChild = mHTMLEditor->GetLastEditableChild(*node);
- }
- }
- return NS_OK;
-}
-
-/**
- * CheckForEmptyBlock() is called by WillDeleteSelection() to detect and handle
- * case of deleting from inside an empty block.
- */
-nsresult
-HTMLEditRules::CheckForEmptyBlock(nsINode* aStartNode,
- Element* aBodyNode,
- Selection* aSelection,
- nsIEditor::EDirection aAction,
- bool* aHandled)
-{
- // If the editing host is an inline element, bail out early.
- if (aBodyNode && IsInlineNode(*aBodyNode)) {
- return NS_OK;
- }
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- // If we are inside an empty block, delete it. Note: do NOT delete table
- // elements this way.
- nsCOMPtr<Element> block = htmlEditor->GetBlock(*aStartNode);
- bool bIsEmptyNode;
- nsCOMPtr<Element> emptyBlock;
- if (block && block != aBodyNode) {
- // Efficiency hack, avoiding IsEmptyNode() call when in body
- nsresult rv = htmlEditor->IsEmptyNode(block, &bIsEmptyNode, true, false);
- NS_ENSURE_SUCCESS(rv, rv);
- while (block && bIsEmptyNode && !HTMLEditUtils::IsTableElement(block) &&
- block != aBodyNode) {
- emptyBlock = block;
- block = htmlEditor->GetBlockNodeParent(emptyBlock);
- if (block) {
- rv = htmlEditor->IsEmptyNode(block, &bIsEmptyNode, true, false);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- }
-
- if (emptyBlock && emptyBlock->IsEditable()) {
- nsCOMPtr<nsINode> blockParent = emptyBlock->GetParentNode();
- NS_ENSURE_TRUE(blockParent, NS_ERROR_FAILURE);
- int32_t offset = blockParent->IndexOf(emptyBlock);
-
- if (HTMLEditUtils::IsListItem(emptyBlock)) {
- // Are we the first list item in the list?
- bool bIsFirst;
- NS_ENSURE_STATE(htmlEditor);
- nsresult rv =
- htmlEditor->IsFirstEditableChild(GetAsDOMNode(emptyBlock), &bIsFirst);
- NS_ENSURE_SUCCESS(rv, rv);
- if (bIsFirst) {
- nsCOMPtr<nsINode> listParent = blockParent->GetParentNode();
- NS_ENSURE_TRUE(listParent, NS_ERROR_FAILURE);
- int32_t listOffset = listParent->IndexOf(blockParent);
- // If we are a sublist, skip the br creation
- if (!HTMLEditUtils::IsList(listParent)) {
- // Create a br before list
- NS_ENSURE_STATE(htmlEditor);
- nsCOMPtr<Element> br =
- htmlEditor->CreateBR(listParent, listOffset);
- NS_ENSURE_STATE(br);
- // Adjust selection to be right before it
- rv = aSelection->Collapse(listParent, listOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // Else just let selection percolate up. We'll adjust it in
- // AfterEdit()
- }
- } else {
- if (aAction == nsIEditor::eNext || aAction == nsIEditor::eNextWord ||
- aAction == nsIEditor::eToEndOfLine) {
- // Move to the start of the next node, if any
- nsCOMPtr<nsIContent> nextNode = htmlEditor->GetNextNode(blockParent,
- offset + 1, true);
- if (nextNode) {
- EditorDOMPoint pt = GetGoodSelPointForNode(*nextNode, aAction);
- nsresult rv = aSelection->Collapse(pt.node, pt.offset);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // Adjust selection to be right after it.
- nsresult rv = aSelection->Collapse(blockParent, offset + 1);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- } else if (aAction == nsIEditor::ePrevious ||
- aAction == nsIEditor::ePreviousWord ||
- aAction == nsIEditor::eToBeginningOfLine) {
- // Move to the end of the previous node
- nsCOMPtr<nsIContent> priorNode = htmlEditor->GetPriorNode(blockParent,
- offset,
- true);
- if (priorNode) {
- EditorDOMPoint pt = GetGoodSelPointForNode(*priorNode, aAction);
- nsresult rv = aSelection->Collapse(pt.node, pt.offset);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- nsresult rv = aSelection->Collapse(blockParent, offset + 1);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- } else if (aAction != nsIEditor::eNone) {
- NS_RUNTIMEABORT("CheckForEmptyBlock doesn't support this action yet");
- }
- }
- NS_ENSURE_STATE(htmlEditor);
- *aHandled = true;
- nsresult rv = htmlEditor->DeleteNode(emptyBlock);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
-}
-
-Element*
-HTMLEditRules::CheckForInvisibleBR(Element& aBlock,
- BRLocation aWhere,
- int32_t aOffset)
-{
- nsCOMPtr<nsINode> testNode;
- int32_t testOffset = 0;
-
- if (aWhere == BRLocation::blockEnd) {
- // No block crossing
- nsCOMPtr<nsIContent> rightmostNode =
- mHTMLEditor->GetRightmostChild(&aBlock, true);
-
- if (!rightmostNode) {
- return nullptr;
- }
-
- testNode = rightmostNode->GetParentNode();
- // Use offset + 1, so last node is included in our evaluation
- testOffset = testNode->IndexOf(rightmostNode) + 1;
- } else if (aOffset) {
- testNode = &aBlock;
- // We'll check everything to the left of the input position
- testOffset = aOffset;
- } else {
- return nullptr;
- }
-
- WSRunObject wsTester(mHTMLEditor, testNode, testOffset);
- if (WSType::br == wsTester.mStartReason) {
- return wsTester.mStartReasonNode->AsElement();
- }
-
- return nullptr;
-}
-
-/**
- * aLists and aTables allow the caller to specify what kind of content to
- * "look inside". If aTables is Tables::yes, look inside any table content,
- * and insert the inner content into the supplied issupportsarray at offset
- * aIndex. Similarly with aLists and list content. aIndex is updated to
- * point past inserted elements.
- */
-void
-HTMLEditRules::GetInnerContent(
- nsINode& aNode,
- nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
- int32_t* aIndex,
- Lists aLists,
- Tables aTables)
-{
- MOZ_ASSERT(aIndex);
-
- for (nsCOMPtr<nsIContent> node = mHTMLEditor->GetFirstEditableChild(aNode);
- node; node = node->GetNextSibling()) {
- if ((aLists == Lists::yes && (HTMLEditUtils::IsList(node) ||
- HTMLEditUtils::IsListItem(node))) ||
- (aTables == Tables::yes && HTMLEditUtils::IsTableElement(node))) {
- GetInnerContent(*node, aOutArrayOfNodes, aIndex, aLists, aTables);
- } else {
- aOutArrayOfNodes.InsertElementAt(*aIndex, *node);
- (*aIndex)++;
- }
- }
-}
-
-/**
- * Promotes selection to include blocks that have all their children selected.
- */
-nsresult
-HTMLEditRules::ExpandSelectionForDeletion(Selection& aSelection)
-{
- // Don't need to touch collapsed selections
- if (aSelection.Collapsed()) {
- return NS_OK;
- }
-
- // We don't need to mess with cell selections, and we assume multirange
- // selections are those.
- if (aSelection.RangeCount() != 1) {
- return NS_OK;
- }
-
- // Find current sel start and end
- NS_ENSURE_TRUE(aSelection.GetRangeAt(0), NS_ERROR_NULL_POINTER);
- OwningNonNull<nsRange> range = *aSelection.GetRangeAt(0);
-
- nsCOMPtr<nsINode> selStartNode = range->GetStartParent();
- int32_t selStartOffset = range->StartOffset();
- nsCOMPtr<nsINode> selEndNode = range->GetEndParent();
- int32_t selEndOffset = range->EndOffset();
-
- // Find current selection common block parent
- nsCOMPtr<Element> selCommon =
- HTMLEditor::GetBlock(*range->GetCommonAncestor());
- NS_ENSURE_STATE(selCommon);
-
- // Set up for loops and cache our root element
- nsCOMPtr<nsINode> firstBRParent;
- nsCOMPtr<nsINode> unused;
- int32_t visOffset = 0, firstBROffset = 0;
- WSType wsType;
- nsCOMPtr<Element> root = mHTMLEditor->GetActiveEditingHost();
- NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
-
- // Find previous visible thingy before start of selection
- if (selStartNode != selCommon && selStartNode != root) {
- while (true) {
- WSRunObject wsObj(mHTMLEditor, selStartNode, selStartOffset);
- wsObj.PriorVisibleNode(selStartNode, selStartOffset, address_of(unused),
- &visOffset, &wsType);
- if (wsType != WSType::thisBlock) {
- break;
- }
- // We want to keep looking up. But stop if we are crossing table
- // element boundaries, or if we hit the root.
- if (HTMLEditUtils::IsTableElement(wsObj.mStartReasonNode) ||
- selCommon == wsObj.mStartReasonNode ||
- root == wsObj.mStartReasonNode) {
- break;
- }
- selStartNode = wsObj.mStartReasonNode->GetParentNode();
- selStartOffset = selStartNode ?
- selStartNode->IndexOf(wsObj.mStartReasonNode) : -1;
- }
- }
-
- // Find next visible thingy after end of selection
- if (selEndNode != selCommon && selEndNode != root) {
- for (;;) {
- WSRunObject wsObj(mHTMLEditor, selEndNode, selEndOffset);
- wsObj.NextVisibleNode(selEndNode, selEndOffset, address_of(unused),
- &visOffset, &wsType);
- if (wsType == WSType::br) {
- if (mHTMLEditor->IsVisBreak(wsObj.mEndReasonNode)) {
- break;
- }
- if (!firstBRParent) {
- firstBRParent = selEndNode;
- firstBROffset = selEndOffset;
- }
- selEndNode = wsObj.mEndReasonNode->GetParentNode();
- selEndOffset = selEndNode
- ? selEndNode->IndexOf(wsObj.mEndReasonNode) + 1 : 0;
- } else if (wsType == WSType::thisBlock) {
- // We want to keep looking up. But stop if we are crossing table
- // element boundaries, or if we hit the root.
- if (HTMLEditUtils::IsTableElement(wsObj.mEndReasonNode) ||
- selCommon == wsObj.mEndReasonNode ||
- root == wsObj.mEndReasonNode) {
- break;
- }
- selEndNode = wsObj.mEndReasonNode->GetParentNode();
- selEndOffset = 1 + selEndNode->IndexOf(wsObj.mEndReasonNode);
- } else {
- break;
- }
- }
- }
- // Now set the selection to the new range
- aSelection.Collapse(selStartNode, selStartOffset);
-
- // Expand selection endpoint only if we didn't pass a br, or if we really
- // needed to pass that br (i.e., its block is now totally selected)
- bool doEndExpansion = true;
- if (firstBRParent) {
- // Find block node containing br
- nsCOMPtr<Element> brBlock = HTMLEditor::GetBlock(*firstBRParent);
- bool nodeBefore = false, nodeAfter = false;
-
- // Create a range that represents expanded selection
- RefPtr<nsRange> range = new nsRange(selStartNode);
- nsresult rv = range->SetStartAndEnd(selStartNode, selStartOffset,
- selEndNode, selEndOffset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- // Check if block is entirely inside range
- if (brBlock) {
- nsRange::CompareNodeToRange(brBlock, range, &nodeBefore, &nodeAfter);
- }
-
- // If block isn't contained, forgo grabbing the br in expanded selection
- if (nodeBefore || nodeAfter) {
- doEndExpansion = false;
- }
- }
- if (doEndExpansion) {
- nsresult rv = aSelection.Extend(selEndNode, selEndOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // Only expand to just before br
- nsresult rv = aSelection.Extend(firstBRParent, firstBROffset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-/**
- * NormalizeSelection() tweaks non-collapsed selections to be more "natural".
- * Idea here is to adjust selection endpoint so that they do not cross breaks
- * or block boundaries unless something editable beyond that boundary is also
- * selected. This adjustment makes it much easier for the various block
- * operations to determine what nodes to act on.
- */
-nsresult
-HTMLEditRules::NormalizeSelection(Selection* inSelection)
-{
- NS_ENSURE_TRUE(inSelection, NS_ERROR_NULL_POINTER);
-
- // don't need to touch collapsed selections
- if (inSelection->Collapsed()) {
- return NS_OK;
- }
-
- int32_t rangeCount;
- nsresult rv = inSelection->GetRangeCount(&rangeCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // we don't need to mess with cell selections, and we assume multirange selections are those.
- if (rangeCount != 1) {
- return NS_OK;
- }
-
- RefPtr<nsRange> range = inSelection->GetRangeAt(0);
- NS_ENSURE_TRUE(range, NS_ERROR_NULL_POINTER);
- nsCOMPtr<nsIDOMNode> startNode, endNode;
- uint32_t startOffset, endOffset;
- nsCOMPtr<nsIDOMNode> newStartNode, newEndNode;
-
- rv = range->GetStartContainer(getter_AddRefs(startNode));
- NS_ENSURE_SUCCESS(rv, rv);
- rv = range->GetStartOffset(&startOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = range->GetEndContainer(getter_AddRefs(endNode));
- NS_ENSURE_SUCCESS(rv, rv);
- rv = range->GetEndOffset(&endOffset);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // adjusted values default to original values
- newStartNode = startNode;
- uint32_t newStartOffset = startOffset;
- newEndNode = endNode;
- uint32_t newEndOffset = endOffset;
-
- // some locals we need for whitespace code
- nsCOMPtr<nsINode> unused;
- int32_t offset = -1;
- WSType wsType;
-
- // let the whitespace code do the heavy lifting
- WSRunObject wsEndObj(mHTMLEditor, endNode, static_cast<int32_t>(endOffset));
- // is there any intervening visible whitespace? if so we can't push selection past that,
- // it would visibly change maening of users selection
- nsCOMPtr<nsINode> endNode_(do_QueryInterface(endNode));
- wsEndObj.PriorVisibleNode(endNode_, static_cast<int32_t>(endOffset),
- address_of(unused), &offset, &wsType);
- if (wsType != WSType::text && wsType != WSType::normalWS) {
- // eThisBlock and eOtherBlock conveniently distinquish cases
- // of going "down" into a block and "up" out of a block.
- if (wsEndObj.mStartReason == WSType::otherBlock) {
- // endpoint is just after the close of a block.
- nsCOMPtr<nsIDOMNode> child =
- GetAsDOMNode(mHTMLEditor->GetRightmostChild(wsEndObj.mStartReasonNode,
- true));
- if (child) {
- int32_t offset = -1;
- newEndNode = EditorBase::GetNodeLocation(child, &offset);
- // offset *after* child
- newEndOffset = static_cast<uint32_t>(offset + 1);
- }
- // else block is empty - we can leave selection alone here, i think.
- } else if (wsEndObj.mStartReason == WSType::thisBlock) {
- // endpoint is just after start of this block
- nsCOMPtr<nsIDOMNode> child;
- NS_ENSURE_STATE(mHTMLEditor);
- mHTMLEditor->GetPriorHTMLNode(endNode, static_cast<int32_t>(endOffset),
- address_of(child));
- if (child) {
- int32_t offset = -1;
- newEndNode = EditorBase::GetNodeLocation(child, &offset);
- // offset *after* child
- newEndOffset = static_cast<uint32_t>(offset + 1);
- }
- // else block is empty - we can leave selection alone here, i think.
- } else if (wsEndObj.mStartReason == WSType::br) {
- // endpoint is just after break. lets adjust it to before it.
- int32_t offset = -1;
- newEndNode =
- EditorBase::GetNodeLocation(GetAsDOMNode(wsEndObj.mStartReasonNode),
- &offset);
- newEndOffset = static_cast<uint32_t>(offset);;
- }
- }
-
-
- // similar dealio for start of range
- WSRunObject wsStartObj(mHTMLEditor, startNode,
- static_cast<int32_t>(startOffset));
- // is there any intervening visible whitespace? if so we can't push selection past that,
- // it would visibly change maening of users selection
- nsCOMPtr<nsINode> startNode_(do_QueryInterface(startNode));
- wsStartObj.NextVisibleNode(startNode_, static_cast<int32_t>(startOffset),
- address_of(unused), &offset, &wsType);
- if (wsType != WSType::text && wsType != WSType::normalWS) {
- // eThisBlock and eOtherBlock conveniently distinquish cases
- // of going "down" into a block and "up" out of a block.
- if (wsStartObj.mEndReason == WSType::otherBlock) {
- // startpoint is just before the start of a block.
- nsCOMPtr<nsIDOMNode> child =
- GetAsDOMNode(mHTMLEditor->GetLeftmostChild(wsStartObj.mEndReasonNode,
- true));
- if (child) {
- int32_t offset = -1;
- newStartNode = EditorBase::GetNodeLocation(child, &offset);
- newStartOffset = static_cast<uint32_t>(offset);
- }
- // else block is empty - we can leave selection alone here, i think.
- } else if (wsStartObj.mEndReason == WSType::thisBlock) {
- // startpoint is just before end of this block
- nsCOMPtr<nsIDOMNode> child;
- NS_ENSURE_STATE(mHTMLEditor);
- mHTMLEditor->GetNextHTMLNode(startNode, static_cast<int32_t>(startOffset),
- address_of(child));
- if (child) {
- int32_t offset = -1;
- newStartNode = EditorBase::GetNodeLocation(child, &offset);
- newStartOffset = static_cast<uint32_t>(offset);
- }
- // else block is empty - we can leave selection alone here, i think.
- } else if (wsStartObj.mEndReason == WSType::br) {
- // startpoint is just before a break. lets adjust it to after it.
- int32_t offset = -1;
- newStartNode =
- EditorBase::GetNodeLocation(GetAsDOMNode(wsStartObj.mEndReasonNode),
- &offset);
- // offset *after* break
- newStartOffset = static_cast<uint32_t>(offset + 1);
- ++newStartOffset; // offset *after* break
- }
- }
-
- // there is a demented possiblity we have to check for. We might have a very strange selection
- // that is not collapsed and yet does not contain any editable content, and satisfies some of the
- // above conditions that cause tweaking. In this case we don't want to tweak the selection into
- // a block it was never in, etc. There are a variety of strategies one might use to try to
- // detect these cases, but I think the most straightforward is to see if the adjusted locations
- // "cross" the old values: ie, new end before old start, or new start after old end. If so
- // then just leave things alone.
-
- int16_t comp;
- comp = nsContentUtils::ComparePoints(startNode, startOffset,
- newEndNode, newEndOffset);
- if (comp == 1) {
- return NS_OK; // New end before old start.
- }
- comp = nsContentUtils::ComparePoints(newStartNode, newStartOffset,
- endNode, endOffset);
- if (comp == 1) {
- return NS_OK; // New start after old end.
- }
-
- // otherwise set selection to new values.
- inSelection->Collapse(newStartNode, newStartOffset);
- inSelection->Extend(newEndNode, newEndOffset);
- return NS_OK;
-}
-
-/**
- * GetPromotedPoint() figures out where a start or end point for a block
- * operation really is.
- */
-void
-HTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere,
- nsIDOMNode* aNode,
- int32_t aOffset,
- EditAction actionID,
- nsCOMPtr<nsIDOMNode>* outNode,
- int32_t* outOffset)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- MOZ_ASSERT(node && outNode && outOffset);
-
- // default values
- *outNode = node->AsDOMNode();
- *outOffset = aOffset;
-
- // we do one thing for text actions, something else entirely for other
- // actions
- if (actionID == EditAction::insertText ||
- actionID == EditAction::insertIMEText ||
- actionID == EditAction::insertBreak ||
- actionID == EditAction::deleteText) {
- bool isSpace, isNBSP;
- nsCOMPtr<nsIContent> content = do_QueryInterface(node), temp;
- // for text actions, we want to look backwards (or forwards, as
- // appropriate) for additional whitespace or nbsp's. We may have to act on
- // these later even though they are outside of the initial selection. Even
- // if they are in another node!
- while (content) {
- int32_t offset;
- if (aWhere == kStart) {
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- mHTMLEditor->IsPrevCharInNodeWhitespace(content, *outOffset,
- &isSpace, &isNBSP,
- getter_AddRefs(temp), &offset);
- } else {
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- mHTMLEditor->IsNextCharInNodeWhitespace(content, *outOffset,
- &isSpace, &isNBSP,
- getter_AddRefs(temp), &offset);
- }
- if (isSpace || isNBSP) {
- content = temp;
- *outOffset = offset;
- } else {
- break;
- }
- }
-
- *outNode = content->AsDOMNode();
- return;
- }
-
- int32_t offset = aOffset;
-
- // else not a text section. In this case we want to see if we should grab
- // any adjacent inline nodes and/or parents and other ancestors
- if (aWhere == kStart) {
- // some special casing for text nodes
- if (node->IsNodeOfType(nsINode::eTEXT)) {
- if (!node->GetParentNode()) {
- // Okay, can't promote any further
- return;
- }
- offset = node->GetParentNode()->IndexOf(node);
- node = node->GetParentNode();
- }
-
- // look back through any further inline nodes that aren't across a <br>
- // from us, and that are enclosed in the same block.
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- nsCOMPtr<nsINode> priorNode =
- mHTMLEditor->GetPriorHTMLNode(node, offset, true);
-
- while (priorNode && priorNode->GetParentNode() &&
- mHTMLEditor && !mHTMLEditor->IsVisBreak(priorNode) &&
- !IsBlockNode(*priorNode)) {
- offset = priorNode->GetParentNode()->IndexOf(priorNode);
- node = priorNode->GetParentNode();
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- priorNode = mHTMLEditor->GetPriorHTMLNode(node, offset, true);
- }
-
- // finding the real start for this point. look up the tree for as long as
- // we are the first node in the container, and as long as we haven't hit
- // the body node.
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- nsCOMPtr<nsIContent> nearNode =
- mHTMLEditor->GetPriorHTMLNode(node, offset, true);
- while (!nearNode && !node->IsHTMLElement(nsGkAtoms::body) &&
- node->GetParentNode()) {
- // some cutoffs are here: we don't need to also include them in the
- // aWhere == kEnd case. as long as they are in one or the other it will
- // work. special case for outdent: don't keep looking up if we have
- // found a blockquote element to act on
- if (actionID == EditAction::outdent &&
- node->IsHTMLElement(nsGkAtoms::blockquote)) {
- break;
- }
-
- int32_t parentOffset = node->GetParentNode()->IndexOf(node);
- nsCOMPtr<nsINode> parent = node->GetParentNode();
-
- // Don't walk past the editable section. Note that we need to check
- // before walking up to a parent because we need to return the parent
- // object, so the parent itself might not be in the editable area, but
- // it's OK if we're not performing a block-level action.
- bool blockLevelAction = actionID == EditAction::indent ||
- actionID == EditAction::outdent ||
- actionID == EditAction::align ||
- actionID == EditAction::makeBasicBlock;
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- if (!mHTMLEditor->IsDescendantOfEditorRoot(parent) &&
- (blockLevelAction || !mHTMLEditor ||
- !mHTMLEditor->IsDescendantOfEditorRoot(node))) {
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- break;
- }
-
- node = parent;
- offset = parentOffset;
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- nearNode = mHTMLEditor->GetPriorHTMLNode(node, offset, true);
- }
- *outNode = node->AsDOMNode();
- *outOffset = offset;
- return;
- }
-
- // aWhere == kEnd
- // some special casing for text nodes
- if (node->IsNodeOfType(nsINode::eTEXT)) {
- if (!node->GetParentNode()) {
- // Okay, can't promote any further
- return;
- }
- // want to be after the text node
- offset = 1 + node->GetParentNode()->IndexOf(node);
- node = node->GetParentNode();
- }
-
- // look ahead through any further inline nodes that aren't across a <br> from
- // us, and that are enclosed in the same block.
- NS_ENSURE_TRUE(mHTMLEditor, /* void */);
- nsCOMPtr<nsIContent> nextNode =
- mHTMLEditor->GetNextHTMLNode(node, offset, true);
-
- while (nextNode && !IsBlockNode(*nextNode) && nextNode->GetParentNode()) {
- offset = 1 + nextNode->GetParentNode()->IndexOf(nextNode);
- node = nextNode->GetParentNode();
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- if (mHTMLEditor->IsVisBreak(nextNode)) {
- break;
- }
-
- // Check for newlines in pre-formatted text nodes.
- bool isPRE;
- mHTMLEditor->IsPreformatted(nextNode->AsDOMNode(), &isPRE);
- if (isPRE) {
- nsCOMPtr<nsIDOMText> textNode = do_QueryInterface(nextNode);
- if (textNode) {
- nsAutoString tempString;
- textNode->GetData(tempString);
- int32_t newlinePos = tempString.FindChar(nsCRT::LF);
- if (newlinePos >= 0) {
- if (static_cast<uint32_t>(newlinePos) + 1 == tempString.Length()) {
- // No need for special processing if the newline is at the end.
- break;
- }
- *outNode = nextNode->AsDOMNode();
- *outOffset = newlinePos + 1;
- return;
- }
- }
- }
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- nextNode = mHTMLEditor->GetNextHTMLNode(node, offset, true);
- }
-
- // finding the real end for this point. look up the tree for as long as we
- // are the last node in the container, and as long as we haven't hit the body
- // node.
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- nsCOMPtr<nsIContent> nearNode =
- mHTMLEditor->GetNextHTMLNode(node, offset, true);
- while (!nearNode && !node->IsHTMLElement(nsGkAtoms::body) &&
- node->GetParentNode()) {
- int32_t parentOffset = node->GetParentNode()->IndexOf(node);
- nsCOMPtr<nsINode> parent = node->GetParentNode();
-
- // Don't walk past the editable section. Note that we need to check before
- // walking up to a parent because we need to return the parent object, so
- // the parent itself might not be in the editable area, but it's OK.
- if ((!mHTMLEditor || !mHTMLEditor->IsDescendantOfEditorRoot(node)) &&
- (!mHTMLEditor || !mHTMLEditor->IsDescendantOfEditorRoot(parent))) {
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- break;
- }
-
- node = parent;
- // we want to be AFTER nearNode
- offset = parentOffset + 1;
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- nearNode = mHTMLEditor->GetNextHTMLNode(node, offset, true);
- }
- *outNode = node->AsDOMNode();
- *outOffset = offset;
-}
-
-/**
- * GetPromotedRanges() runs all the selection range endpoint through
- * GetPromotedPoint().
- */
-void
-HTMLEditRules::GetPromotedRanges(Selection& aSelection,
- nsTArray<RefPtr<nsRange>>& outArrayOfRanges,
- EditAction inOperationType)
-{
- uint32_t rangeCount = aSelection.RangeCount();
-
- for (uint32_t i = 0; i < rangeCount; i++) {
- RefPtr<nsRange> selectionRange = aSelection.GetRangeAt(i);
- MOZ_ASSERT(selectionRange);
-
- // Clone range so we don't muck with actual selection ranges
- RefPtr<nsRange> opRange = selectionRange->CloneRange();
-
- // Make a new adjusted range to represent the appropriate block content.
- // The basic idea is to push out the range endpoints to truly enclose the
- // blocks that we will affect. This call alters opRange.
- PromoteRange(*opRange, inOperationType);
-
- // Stuff new opRange into array
- outArrayOfRanges.AppendElement(opRange);
- }
-}
-
-/**
- * PromoteRange() expands a range to include any parents for which all editable
- * children are already in range.
- */
-void
-HTMLEditRules::PromoteRange(nsRange& aRange,
- EditAction aOperationType)
-{
- NS_ENSURE_TRUE(mHTMLEditor, );
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- nsCOMPtr<nsINode> startNode = aRange.GetStartParent();
- nsCOMPtr<nsINode> endNode = aRange.GetEndParent();
- int32_t startOffset = aRange.StartOffset();
- int32_t endOffset = aRange.EndOffset();
-
- // MOOSE major hack:
- // GetPromotedPoint doesn't really do the right thing for collapsed ranges
- // inside block elements that contain nothing but a solo <br>. It's easier
- // to put a workaround here than to revamp GetPromotedPoint. :-(
- if (startNode == endNode && startOffset == endOffset) {
- nsCOMPtr<Element> block = htmlEditor->GetBlock(*startNode);
- if (block) {
- bool bIsEmptyNode = false;
- nsCOMPtr<nsIContent> root = htmlEditor->GetActiveEditingHost();
- // Make sure we don't go higher than our root element in the content tree
- NS_ENSURE_TRUE(root, );
- if (!nsContentUtils::ContentIsDescendantOf(root, block)) {
- htmlEditor->IsEmptyNode(block, &bIsEmptyNode, true, false);
- }
- if (bIsEmptyNode) {
- startNode = block;
- endNode = block;
- startOffset = 0;
- endOffset = block->Length();
- }
- }
- }
-
- // Make a new adjusted range to represent the appropriate block content.
- // This is tricky. The basic idea is to push out the range endpoints to
- // truly enclose the blocks that we will affect.
-
- nsCOMPtr<nsIDOMNode> opDOMStartNode;
- nsCOMPtr<nsIDOMNode> opDOMEndNode;
- int32_t opStartOffset, opEndOffset;
-
- GetPromotedPoint(kStart, GetAsDOMNode(startNode), startOffset,
- aOperationType, address_of(opDOMStartNode), &opStartOffset);
- GetPromotedPoint(kEnd, GetAsDOMNode(endNode), endOffset, aOperationType,
- address_of(opDOMEndNode), &opEndOffset);
-
- // Make sure that the new range ends up to be in the editable section.
- if (!htmlEditor->IsDescendantOfEditorRoot(
- EditorBase::GetNodeAtRangeOffsetPoint(opDOMStartNode, opStartOffset)) ||
- !htmlEditor->IsDescendantOfEditorRoot(
- EditorBase::GetNodeAtRangeOffsetPoint(opDOMEndNode, opEndOffset - 1))) {
- return;
- }
-
- nsCOMPtr<nsINode> opStartNode = do_QueryInterface(opDOMStartNode);
- nsCOMPtr<nsINode> opEndNode = do_QueryInterface(opDOMEndNode);
- DebugOnly<nsresult> rv =
- aRange.SetStartAndEnd(opStartNode, opStartOffset, opEndNode, opEndOffset);
- MOZ_ASSERT(NS_SUCCEEDED(rv));
-}
-
-class UniqueFunctor final : public BoolDomIterFunctor
-{
-public:
- explicit UniqueFunctor(nsTArray<OwningNonNull<nsINode>>& aArray)
- : mArray(aArray)
- {
- }
-
- // Used to build list of all nodes iterator covers.
- virtual bool operator()(nsINode* aNode) const
- {
- return !mArray.Contains(aNode);
- }
-
-private:
- nsTArray<OwningNonNull<nsINode>>& mArray;
-};
-
-/**
- * GetNodesForOperation() runs through the ranges in the array and construct a
- * new array of nodes to be acted on.
- */
-nsresult
-HTMLEditRules::GetNodesForOperation(
- nsTArray<RefPtr<nsRange>>& aArrayOfRanges,
- nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
- EditAction aOperationType,
- TouchContent aTouchContent)
-{
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- int32_t rangeCount = aArrayOfRanges.Length();
- if (aTouchContent == TouchContent::yes) {
- // Split text nodes. This is necessary, since GetPromotedPoint() may return a
- // range ending in a text node in case where part of a pre-formatted
- // elements needs to be moved.
- for (int32_t i = 0; i < rangeCount; i++) {
- RefPtr<nsRange> r = aArrayOfRanges[i];
- nsCOMPtr<nsIContent> endParent = do_QueryInterface(r->GetEndParent());
- if (!htmlEditor->IsTextNode(endParent)) {
- continue;
- }
- nsCOMPtr<nsIDOMText> textNode = do_QueryInterface(endParent);
- if (textNode) {
- int32_t offset = r->EndOffset();
- nsAutoString tempString;
- textNode->GetData(tempString);
-
- if (0 < offset && offset < static_cast<int32_t>(tempString.Length())) {
- // Split the text node.
- nsCOMPtr<nsIDOMNode> tempNode;
- nsresult rv = htmlEditor->SplitNode(endParent->AsDOMNode(), offset,
- getter_AddRefs(tempNode));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Correct the range.
- // The new end parent becomes the parent node of the text.
- nsCOMPtr<nsIContent> newParent = endParent->GetParent();
- r->SetEnd(newParent, newParent->IndexOf(endParent));
- }
- }
- }
- }
-
- // Bust up any inlines that cross our range endpoints, but only if we are
- // allowed to touch content.
-
- if (aTouchContent == TouchContent::yes) {
- nsTArray<OwningNonNull<RangeItem>> rangeItemArray;
- rangeItemArray.AppendElements(rangeCount);
-
- // First register ranges for special editor gravity
- for (int32_t i = 0; i < rangeCount; i++) {
- rangeItemArray[i] = new RangeItem();
- rangeItemArray[i]->StoreRange(aArrayOfRanges[0]);
- htmlEditor->mRangeUpdater.RegisterRangeItem(rangeItemArray[i]);
- aArrayOfRanges.RemoveElementAt(0);
- }
- // Now bust up inlines.
- nsresult rv = NS_OK;
- for (auto& item : Reversed(rangeItemArray)) {
- rv = BustUpInlinesAtRangeEndpoints(*item);
- if (NS_FAILED(rv)) {
- break;
- }
- }
- // Then unregister the ranges
- for (auto& item : rangeItemArray) {
- htmlEditor->mRangeUpdater.DropRangeItem(item);
- aArrayOfRanges.AppendElement(item->GetRange());
- }
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // Gather up a list of all the nodes
- for (auto& range : aArrayOfRanges) {
- DOMSubtreeIterator iter;
- nsresult rv = iter.Init(*range);
- NS_ENSURE_SUCCESS(rv, rv);
- if (aOutArrayOfNodes.IsEmpty()) {
- iter.AppendList(TrivialFunctor(), aOutArrayOfNodes);
- } else {
- // We don't want duplicates in aOutArrayOfNodes, so we use an
- // iterator/functor that only return nodes that are not already in
- // aOutArrayOfNodes.
- nsTArray<OwningNonNull<nsINode>> nodes;
- iter.AppendList(UniqueFunctor(aOutArrayOfNodes), nodes);
- aOutArrayOfNodes.AppendElements(nodes);
- }
- }
-
- // Certain operations should not act on li's and td's, but rather inside
- // them. Alter the list as needed.
- if (aOperationType == EditAction::makeBasicBlock) {
- for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
- OwningNonNull<nsINode> node = aOutArrayOfNodes[i];
- if (HTMLEditUtils::IsListItem(node)) {
- int32_t j = i;
- aOutArrayOfNodes.RemoveElementAt(i);
- GetInnerContent(*node, aOutArrayOfNodes, &j);
- }
- }
- }
- // Indent/outdent already do something special for list items, but we still
- // need to make sure we don't act on table elements
- else if (aOperationType == EditAction::outdent ||
- aOperationType == EditAction::indent ||
- aOperationType == EditAction::setAbsolutePosition) {
- for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
- OwningNonNull<nsINode> node = aOutArrayOfNodes[i];
- if (HTMLEditUtils::IsTableElementButNotTable(node)) {
- int32_t j = i;
- aOutArrayOfNodes.RemoveElementAt(i);
- GetInnerContent(*node, aOutArrayOfNodes, &j);
- }
- }
- }
- // Outdent should look inside of divs.
- if (aOperationType == EditAction::outdent &&
- !htmlEditor->IsCSSEnabled()) {
- for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
- OwningNonNull<nsINode> node = aOutArrayOfNodes[i];
- if (node->IsHTMLElement(nsGkAtoms::div)) {
- int32_t j = i;
- aOutArrayOfNodes.RemoveElementAt(i);
- GetInnerContent(*node, aOutArrayOfNodes, &j, Lists::no, Tables::no);
- }
- }
- }
-
-
- // Post-process the list to break up inline containers that contain br's, but
- // only for operations that might care, like making lists or paragraphs
- if (aOperationType == EditAction::makeBasicBlock ||
- aOperationType == EditAction::makeList ||
- aOperationType == EditAction::align ||
- aOperationType == EditAction::setAbsolutePosition ||
- aOperationType == EditAction::indent ||
- aOperationType == EditAction::outdent) {
- for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
- OwningNonNull<nsINode> node = aOutArrayOfNodes[i];
- if (aTouchContent == TouchContent::yes && IsInlineNode(node) &&
- htmlEditor->IsContainer(node) && !htmlEditor->IsTextNode(node)) {
- nsTArray<OwningNonNull<nsINode>> arrayOfInlines;
- nsresult rv = BustUpInlinesAtBRs(*node->AsContent(), arrayOfInlines);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Put these nodes in aOutArrayOfNodes, replacing the current node
- aOutArrayOfNodes.RemoveElementAt(i);
- aOutArrayOfNodes.InsertElementsAt(i, arrayOfInlines);
- }
- }
- }
- return NS_OK;
-}
-
-void
-HTMLEditRules::GetChildNodesForOperation(
- nsINode& aNode,
- nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes)
-{
- for (nsCOMPtr<nsIContent> child = aNode.GetFirstChild();
- child; child = child->GetNextSibling()) {
- outArrayOfNodes.AppendElement(*child);
- }
-}
-
-nsresult
-HTMLEditRules::GetListActionNodes(
- nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
- EntireList aEntireList,
- TouchContent aTouchContent)
-{
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- RefPtr<Selection> selection = htmlEditor->GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
-
- // Added this in so that ui code can ask to change an entire list, even if
- // selection is only in part of it. used by list item dialog.
- if (aEntireList == EntireList::yes) {
- uint32_t rangeCount = selection->RangeCount();
- for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
- RefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
- for (nsCOMPtr<nsINode> parent = range->GetCommonAncestor();
- parent; parent = parent->GetParentNode()) {
- if (HTMLEditUtils::IsList(parent)) {
- aOutArrayOfNodes.AppendElement(*parent);
- break;
- }
- }
- }
- // If we didn't find any nodes this way, then try the normal way. Perhaps
- // the selection spans multiple lists but with no common list parent.
- if (!aOutArrayOfNodes.IsEmpty()) {
- return NS_OK;
- }
- }
-
- {
- // We don't like other people messing with our selection!
- AutoTransactionsConserveSelection dontSpazMySelection(htmlEditor);
-
- // contruct a list of nodes to act on.
- nsresult rv = GetNodesFromSelection(*selection, EditAction::makeList,
- aOutArrayOfNodes, aTouchContent);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // Pre-process our list of nodes
- for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
- OwningNonNull<nsINode> testNode = aOutArrayOfNodes[i];
-
- // Remove all non-editable nodes. Leave them be.
- if (!htmlEditor->IsEditable(testNode)) {
- aOutArrayOfNodes.RemoveElementAt(i);
- continue;
- }
-
- // Scan for table elements and divs. If we find table elements other than
- // table, replace it with a list of any editable non-table content.
- if (HTMLEditUtils::IsTableElementButNotTable(testNode)) {
- int32_t j = i;
- aOutArrayOfNodes.RemoveElementAt(i);
- GetInnerContent(*testNode, aOutArrayOfNodes, &j, Lists::no);
- }
- }
-
- // If there is only one node in the array, and it is a list, div, or
- // blockquote, then look inside of it until we find inner list or content.
- LookInsideDivBQandList(aOutArrayOfNodes);
-
- return NS_OK;
-}
-
-void
-HTMLEditRules::LookInsideDivBQandList(
- nsTArray<OwningNonNull<nsINode>>& aNodeArray)
-{
- NS_ENSURE_TRUE(mHTMLEditor, );
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- // If there is only one node in the array, and it is a list, div, or
- // blockquote, then look inside of it until we find inner list or content.
- if (aNodeArray.Length() != 1) {
- return;
- }
-
- OwningNonNull<nsINode> curNode = aNodeArray[0];
-
- while (curNode->IsHTMLElement(nsGkAtoms::div) ||
- HTMLEditUtils::IsList(curNode) ||
- curNode->IsHTMLElement(nsGkAtoms::blockquote)) {
- // Dive as long as there's only one child, and it's a list, div, blockquote
- uint32_t numChildren = htmlEditor->CountEditableChildren(curNode);
- if (numChildren != 1) {
- break;
- }
-
- // Keep diving! XXX One would expect to dive into the one editable node.
- nsCOMPtr<nsIContent> child = curNode->GetFirstChild();
- if (!child->IsHTMLElement(nsGkAtoms::div) &&
- !HTMLEditUtils::IsList(child) &&
- !child->IsHTMLElement(nsGkAtoms::blockquote)) {
- break;
- }
-
- // check editability XXX floppy moose
- curNode = child;
- }
-
- // We've found innermost list/blockquote/div: replace the one node in the
- // array with these nodes
- aNodeArray.RemoveElementAt(0);
- if (curNode->IsAnyOfHTMLElements(nsGkAtoms::div,
- nsGkAtoms::blockquote)) {
- int32_t j = 0;
- GetInnerContent(*curNode, aNodeArray, &j, Lists::no, Tables::no);
- return;
- }
-
- aNodeArray.AppendElement(*curNode);
-}
-
-void
-HTMLEditRules::GetDefinitionListItemTypes(dom::Element* aElement,
- bool* aDT,
- bool* aDD)
-{
- MOZ_ASSERT(aElement);
- MOZ_ASSERT(aElement->IsHTMLElement(nsGkAtoms::dl));
- MOZ_ASSERT(aDT);
- MOZ_ASSERT(aDD);
-
- *aDT = *aDD = false;
- for (nsIContent* child = aElement->GetFirstChild();
- child;
- child = child->GetNextSibling()) {
- if (child->IsHTMLElement(nsGkAtoms::dt)) {
- *aDT = true;
- } else if (child->IsHTMLElement(nsGkAtoms::dd)) {
- *aDD = true;
- }
- }
-}
-
-nsresult
-HTMLEditRules::GetParagraphFormatNodes(
- nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
- TouchContent aTouchContent)
-{
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- RefPtr<Selection> selection = htmlEditor->GetSelection();
- NS_ENSURE_STATE(selection);
-
- // Contruct a list of nodes to act on.
- nsresult rv = GetNodesFromSelection(*selection, EditAction::makeBasicBlock,
- outArrayOfNodes, aTouchContent);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Pre-process our list of nodes
- for (int32_t i = outArrayOfNodes.Length() - 1; i >= 0; i--) {
- OwningNonNull<nsINode> testNode = outArrayOfNodes[i];
-
- // Remove all non-editable nodes. Leave them be.
- if (!htmlEditor->IsEditable(testNode)) {
- outArrayOfNodes.RemoveElementAt(i);
- continue;
- }
-
- // Scan for table elements. If we find table elements other than table,
- // replace it with a list of any editable non-table content. Ditto for
- // list elements.
- if (HTMLEditUtils::IsTableElement(testNode) ||
- HTMLEditUtils::IsList(testNode) ||
- HTMLEditUtils::IsListItem(testNode)) {
- int32_t j = i;
- outArrayOfNodes.RemoveElementAt(i);
- GetInnerContent(testNode, outArrayOfNodes, &j);
- }
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::BustUpInlinesAtRangeEndpoints(RangeItem& item)
-{
- bool isCollapsed = ((item.startNode == item.endNode) && (item.startOffset == item.endOffset));
-
- nsCOMPtr<nsIContent> endInline = GetHighestInlineParent(*item.endNode);
-
- // if we have inline parents above range endpoints, split them
- if (endInline && !isCollapsed) {
- nsCOMPtr<nsINode> resultEndNode = endInline->GetParentNode();
- NS_ENSURE_STATE(mHTMLEditor);
- // item.endNode must be content if endInline isn't null
- int32_t resultEndOffset =
- mHTMLEditor->SplitNodeDeep(*endInline, *item.endNode->AsContent(),
- item.endOffset,
- EditorBase::EmptyContainers::no);
- NS_ENSURE_TRUE(resultEndOffset != -1, NS_ERROR_FAILURE);
- // reset range
- item.endNode = resultEndNode;
- item.endOffset = resultEndOffset;
- }
-
- nsCOMPtr<nsIContent> startInline = GetHighestInlineParent(*item.startNode);
-
- if (startInline) {
- nsCOMPtr<nsINode> resultStartNode = startInline->GetParentNode();
- NS_ENSURE_STATE(mHTMLEditor);
- int32_t resultStartOffset =
- mHTMLEditor->SplitNodeDeep(*startInline, *item.startNode->AsContent(),
- item.startOffset,
- EditorBase::EmptyContainers::no);
- NS_ENSURE_TRUE(resultStartOffset != -1, NS_ERROR_FAILURE);
- // reset range
- item.startNode = resultStartNode;
- item.startOffset = resultStartOffset;
- }
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::BustUpInlinesAtBRs(
- nsIContent& aNode,
- nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes)
-{
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- // First build up a list of all the break nodes inside the inline container.
- nsTArray<OwningNonNull<nsINode>> arrayOfBreaks;
- BRNodeFunctor functor;
- DOMIterator iter(aNode);
- iter.AppendList(functor, arrayOfBreaks);
-
- // If there aren't any breaks, just put inNode itself in the array
- if (arrayOfBreaks.IsEmpty()) {
- aOutArrayOfNodes.AppendElement(aNode);
- return NS_OK;
- }
-
- // Else we need to bust up inNode along all the breaks
- nsCOMPtr<nsINode> inlineParentNode = aNode.GetParentNode();
- nsCOMPtr<nsIContent> splitDeepNode = &aNode;
- nsCOMPtr<nsIContent> leftNode, rightNode;
-
- for (uint32_t i = 0; i < arrayOfBreaks.Length(); i++) {
- OwningNonNull<Element> breakNode = *arrayOfBreaks[i]->AsElement();
- NS_ENSURE_TRUE(splitDeepNode, NS_ERROR_NULL_POINTER);
- NS_ENSURE_TRUE(breakNode->GetParent(), NS_ERROR_NULL_POINTER);
- OwningNonNull<nsIContent> splitParentNode = *breakNode->GetParent();
- int32_t splitOffset = splitParentNode->IndexOf(breakNode);
-
- int32_t resultOffset =
- htmlEditor->SplitNodeDeep(*splitDeepNode, splitParentNode, splitOffset,
- HTMLEditor::EmptyContainers::yes,
- getter_AddRefs(leftNode),
- getter_AddRefs(rightNode));
- NS_ENSURE_STATE(resultOffset != -1);
-
- // Put left node in node list
- if (leftNode) {
- // Might not be a left node. A break might have been at the very
- // beginning of inline container, in which case SplitNodeDeep would not
- // actually split anything
- aOutArrayOfNodes.AppendElement(*leftNode);
- }
- // Move break outside of container and also put in node list
- nsresult rv =
- htmlEditor->MoveNode(breakNode, inlineParentNode, resultOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- aOutArrayOfNodes.AppendElement(*breakNode);
-
- // Now rightNode becomes the new node to split
- splitDeepNode = rightNode;
- }
- // Now tack on remaining rightNode, if any, to the list
- if (rightNode) {
- aOutArrayOfNodes.AppendElement(*rightNode);
- }
- return NS_OK;
-}
-
-nsIContent*
-HTMLEditRules::GetHighestInlineParent(nsINode& aNode)
-{
- if (!aNode.IsContent() || IsBlockNode(aNode)) {
- return nullptr;
- }
- OwningNonNull<nsIContent> node = *aNode.AsContent();
-
- while (node->GetParent() && IsInlineNode(*node->GetParent())) {
- node = *node->GetParent();
- }
- return node;
-}
-
-/**
- * GetNodesFromPoint() constructs a list of nodes from a point that will be
- * operated on.
- */
-nsresult
-HTMLEditRules::GetNodesFromPoint(
- EditorDOMPoint aPoint,
- EditAction aOperation,
- nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
- TouchContent aTouchContent)
-{
- NS_ENSURE_STATE(aPoint.node);
- RefPtr<nsRange> range = new nsRange(aPoint.node);
- nsresult rv = range->SetStart(aPoint.node, aPoint.offset);
- MOZ_ASSERT(NS_SUCCEEDED(rv));
-
- // Expand the range to include adjacent inlines
- PromoteRange(*range, aOperation);
-
- // Make array of ranges
- nsTArray<RefPtr<nsRange>> arrayOfRanges;
-
- // Stuff new opRange into array
- arrayOfRanges.AppendElement(range);
-
- // Use these ranges to contruct a list of nodes to act on
- rv = GetNodesForOperation(arrayOfRanges, outArrayOfNodes, aOperation,
- aTouchContent);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-/**
- * GetNodesFromSelection() constructs a list of nodes from the selection that
- * will be operated on.
- */
-nsresult
-HTMLEditRules::GetNodesFromSelection(
- Selection& aSelection,
- EditAction aOperation,
- nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
- TouchContent aTouchContent)
-{
- // Promote selection ranges
- nsTArray<RefPtr<nsRange>> arrayOfRanges;
- GetPromotedRanges(aSelection, arrayOfRanges, aOperation);
-
- // Use these ranges to contruct a list of nodes to act on.
- nsresult rv = GetNodesForOperation(arrayOfRanges, outArrayOfNodes,
- aOperation, aTouchContent);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-/**
- * MakeTransitionList() detects all the transitions in the array, where a
- * transition means that adjacent nodes in the array don't have the same parent.
- */
-void
-HTMLEditRules::MakeTransitionList(nsTArray<OwningNonNull<nsINode>>& aNodeArray,
- nsTArray<bool>& aTransitionArray)
-{
- nsCOMPtr<nsINode> prevParent;
-
- aTransitionArray.EnsureLengthAtLeast(aNodeArray.Length());
- for (uint32_t i = 0; i < aNodeArray.Length(); i++) {
- if (aNodeArray[i]->GetParentNode() != prevParent) {
- // Different parents: transition point
- aTransitionArray[i] = true;
- } else {
- // Same parents: these nodes grew up together
- aTransitionArray[i] = false;
- }
- prevParent = aNodeArray[i]->GetParentNode();
- }
-}
-
-/**
- * If aNode is the descendant of a listitem, return that li. But table element
- * boundaries are stoppers on the search. Also stops on the active editor host
- * (contenteditable). Also test if aNode is an li itself.
- */
-Element*
-HTMLEditRules::IsInListItem(nsINode* aNode)
-{
- NS_ENSURE_TRUE(aNode, nullptr);
- if (HTMLEditUtils::IsListItem(aNode)) {
- return aNode->AsElement();
- }
-
- Element* parent = aNode->GetParentElement();
- while (parent &&
- mHTMLEditor && mHTMLEditor->IsDescendantOfEditorRoot(parent) &&
- !HTMLEditUtils::IsTableElement(parent)) {
- if (HTMLEditUtils::IsListItem(parent)) {
- return parent;
- }
- parent = parent->GetParentElement();
- }
- return nullptr;
-}
-
-/**
- * ReturnInHeader: do the right thing for returns pressed in headers
- */
-nsresult
-HTMLEditRules::ReturnInHeader(Selection& aSelection,
- Element& aHeader,
- nsINode& aNode,
- int32_t aOffset)
-{
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- // Remember where the header is
- nsCOMPtr<nsINode> headerParent = aHeader.GetParentNode();
- int32_t offset = headerParent ? headerParent->IndexOf(&aHeader) : -1;
-
- // Get ws code to adjust any ws
- nsCOMPtr<nsINode> node = &aNode;
- nsresult rv = WSRunObject::PrepareToSplitAcrossBlocks(htmlEditor,
- address_of(node),
- &aOffset);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Split the header
- NS_ENSURE_STATE(node->IsContent());
- htmlEditor->SplitNodeDeep(aHeader, *node->AsContent(), aOffset);
-
- // If the left-hand heading is empty, put a mozbr in it
- nsCOMPtr<nsIContent> prevItem = htmlEditor->GetPriorHTMLSibling(&aHeader);
- if (prevItem && HTMLEditUtils::IsHeader(*prevItem)) {
- bool isEmptyNode;
- rv = htmlEditor->IsEmptyNode(prevItem, &isEmptyNode);
- NS_ENSURE_SUCCESS(rv, rv);
- if (isEmptyNode) {
- rv = CreateMozBR(prevItem->AsDOMNode(), 0);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- // If the new (righthand) header node is empty, delete it
- bool isEmpty;
- rv = IsEmptyBlock(aHeader, &isEmpty, MozBRCounts::no);
- NS_ENSURE_SUCCESS(rv, rv);
- if (isEmpty) {
- rv = htmlEditor->DeleteNode(&aHeader);
- NS_ENSURE_SUCCESS(rv, rv);
- // Layout tells the caret to blink in a weird place if we don't place a
- // break after the header.
- nsCOMPtr<nsIContent> sibling =
- htmlEditor->GetNextHTMLSibling(headerParent, offset + 1);
- if (!sibling || !sibling->IsHTMLElement(nsGkAtoms::br)) {
- ClearCachedStyles();
- htmlEditor->mTypeInState->ClearAllProps();
-
- // Create a paragraph
- nsCOMPtr<Element> pNode =
- htmlEditor->CreateNode(nsGkAtoms::p, headerParent, offset + 1);
- NS_ENSURE_STATE(pNode);
-
- // Append a <br> to it
- nsCOMPtr<Element> brNode = htmlEditor->CreateBR(pNode, 0);
- NS_ENSURE_STATE(brNode);
-
- // Set selection to before the break
- rv = aSelection.Collapse(pNode, 0);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- headerParent = sibling->GetParentNode();
- offset = headerParent ? headerParent->IndexOf(sibling) : -1;
- // Put selection after break
- rv = aSelection.Collapse(headerParent, offset + 1);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- } else {
- // Put selection at front of righthand heading
- rv = aSelection.Collapse(&aHeader, 0);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
-}
-
-/**
- * ReturnInParagraph() does the right thing for returns pressed in paragraphs.
- */
-nsresult
-HTMLEditRules::ReturnInParagraph(Selection* aSelection,
- nsIDOMNode* aPara,
- nsIDOMNode* aNode,
- int32_t aOffset,
- bool* aCancel,
- bool* aHandled)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- if (!aSelection || !aPara || !node || !aCancel || !aHandled) {
- return NS_ERROR_NULL_POINTER;
- }
- *aCancel = false;
- *aHandled = false;
-
- int32_t offset;
- nsCOMPtr<nsINode> parent = EditorBase::GetNodeLocation(node, &offset);
-
- NS_ENSURE_STATE(mHTMLEditor);
- bool doesCRCreateNewP = mHTMLEditor->GetReturnInParagraphCreatesNewParagraph();
-
- bool newBRneeded = false;
- bool newSelNode = false;
- nsCOMPtr<nsIContent> sibling;
- nsCOMPtr<nsIDOMNode> selNode = aNode;
- int32_t selOffset = aOffset;
-
- NS_ENSURE_STATE(mHTMLEditor);
- if (aNode == aPara && doesCRCreateNewP) {
- // we are at the edges of the block, newBRneeded not needed!
- sibling = node->AsContent();
- } else if (mHTMLEditor->IsTextNode(aNode)) {
- nsCOMPtr<nsIDOMText> textNode = do_QueryInterface(aNode);
- uint32_t strLength;
- nsresult rv = textNode->GetLength(&strLength);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // at beginning of text node?
- if (!aOffset) {
- // is there a BR prior to it?
- NS_ENSURE_STATE(mHTMLEditor);
- sibling = mHTMLEditor->GetPriorHTMLSibling(node);
- if (!sibling || !mHTMLEditor || !mHTMLEditor->IsVisBreak(sibling) ||
- TextEditUtils::HasMozAttr(GetAsDOMNode(sibling))) {
- NS_ENSURE_STATE(mHTMLEditor);
- newBRneeded = true;
- }
- } else if (aOffset == (int32_t)strLength) {
- // we're at the end of text node...
- // is there a BR after to it?
- NS_ENSURE_STATE(mHTMLEditor);
- sibling = mHTMLEditor->GetNextHTMLSibling(node);
- if (!sibling || !mHTMLEditor || !mHTMLEditor->IsVisBreak(sibling) ||
- TextEditUtils::HasMozAttr(GetAsDOMNode(sibling))) {
- NS_ENSURE_STATE(mHTMLEditor);
- newBRneeded = true;
- offset++;
- }
- } else {
- if (doesCRCreateNewP) {
- nsCOMPtr<nsIDOMNode> tmp;
- rv = mTextEditor->SplitNode(aNode, aOffset, getter_AddRefs(tmp));
- NS_ENSURE_SUCCESS(rv, rv);
- selNode = tmp;
- }
-
- newBRneeded = true;
- offset++;
- }
- } else {
- // not in a text node.
- // is there a BR prior to it?
- nsCOMPtr<nsIContent> nearNode;
- NS_ENSURE_STATE(mHTMLEditor);
- nearNode = mHTMLEditor->GetPriorHTMLNode(node, aOffset);
- NS_ENSURE_STATE(mHTMLEditor);
- if (!nearNode || !mHTMLEditor->IsVisBreak(nearNode) ||
- TextEditUtils::HasMozAttr(GetAsDOMNode(nearNode))) {
- // is there a BR after it?
- NS_ENSURE_STATE(mHTMLEditor);
- nearNode = mHTMLEditor->GetNextHTMLNode(node, aOffset);
- NS_ENSURE_STATE(mHTMLEditor);
- if (!nearNode || !mHTMLEditor->IsVisBreak(nearNode) ||
- TextEditUtils::HasMozAttr(GetAsDOMNode(nearNode))) {
- newBRneeded = true;
- parent = node;
- offset = aOffset;
- newSelNode = true;
- }
- }
- if (!newBRneeded) {
- sibling = nearNode;
- }
- }
- if (newBRneeded) {
- // if CR does not create a new P, default to BR creation
- NS_ENSURE_TRUE(doesCRCreateNewP, NS_OK);
-
- NS_ENSURE_STATE(mHTMLEditor);
- sibling = mHTMLEditor->CreateBR(parent, offset);
- if (newSelNode) {
- // We split the parent after the br we've just inserted.
- selNode = GetAsDOMNode(parent);
- selOffset = offset + 1;
- }
- }
- *aHandled = true;
- return SplitParagraph(aPara, sibling, aSelection, address_of(selNode), &selOffset);
-}
-
-/**
- * SplitParagraph() splits a paragraph at selection point, possibly deleting a
- * br.
- */
-nsresult
-HTMLEditRules::SplitParagraph(nsIDOMNode *aPara,
- nsIContent* aBRNode,
- Selection* aSelection,
- nsCOMPtr<nsIDOMNode>* aSelNode,
- int32_t* aOffset)
-{
- nsCOMPtr<Element> para = do_QueryInterface(aPara);
- NS_ENSURE_TRUE(para && aBRNode && aSelNode && *aSelNode && aOffset &&
- aSelection, NS_ERROR_NULL_POINTER);
-
- // split para
- // get ws code to adjust any ws
- nsCOMPtr<nsIContent> leftPara, rightPara;
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<nsINode> selNode(do_QueryInterface(*aSelNode));
- nsresult rv =
- WSRunObject::PrepareToSplitAcrossBlocks(mHTMLEditor,
- address_of(selNode), aOffset);
- // XXX When it fails, why do we need to return selection node? (Why can the
- // caller trust the result even when it returns error?)
- *aSelNode = GetAsDOMNode(selNode);
- NS_ENSURE_SUCCESS(rv, rv);
- // split the paragraph
- NS_ENSURE_STATE(mHTMLEditor);
- NS_ENSURE_STATE(selNode->IsContent());
- int32_t offset =
- mHTMLEditor->SplitNodeDeep(*para, *selNode->AsContent(), *aOffset,
- HTMLEditor::EmptyContainers::yes,
- getter_AddRefs(leftPara),
- getter_AddRefs(rightPara));
- if (NS_WARN_IF(offset == -1)) {
- return NS_ERROR_FAILURE;
- }
- // get rid of the break, if it is visible (otherwise it may be needed to prevent an empty p)
- NS_ENSURE_STATE(mHTMLEditor);
- if (mHTMLEditor->IsVisBreak(aBRNode)) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->DeleteNode(aBRNode);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // remove ID attribute on the paragraph we just created
- RefPtr<Element> rightElt = rightPara->AsElement();
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->RemoveAttribute(rightElt, nsGkAtoms::id);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // check both halves of para to see if we need mozBR
- rv = InsertMozBRIfNeeded(*leftPara);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = InsertMozBRIfNeeded(*rightPara);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // selection to beginning of right hand para;
- // look inside any containers that are up front.
- nsCOMPtr<nsINode> rightParaNode = do_QueryInterface(rightPara);
- NS_ENSURE_STATE(mHTMLEditor && rightParaNode);
- nsCOMPtr<nsIDOMNode> child =
- GetAsDOMNode(mHTMLEditor->GetLeftmostChild(rightParaNode, true));
- if (mHTMLEditor->IsTextNode(child) ||
- mHTMLEditor->IsContainer(child)) {
- aSelection->Collapse(child,0);
- } else {
- int32_t offset;
- nsCOMPtr<nsIDOMNode> parent = EditorBase::GetNodeLocation(child, &offset);
- aSelection->Collapse(parent,offset);
- }
- return NS_OK;
-}
-
-/**
- * ReturnInListItem: do the right thing for returns pressed in list items
- */
-nsresult
-HTMLEditRules::ReturnInListItem(Selection& aSelection,
- Element& aListItem,
- nsINode& aNode,
- int32_t aOffset)
-{
- MOZ_ASSERT(HTMLEditUtils::IsListItem(&aListItem));
-
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- // Get the item parent and the active editing host.
- nsCOMPtr<Element> root = htmlEditor->GetActiveEditingHost();
-
- nsCOMPtr<Element> list = aListItem.GetParentElement();
- int32_t itemOffset = list ? list->IndexOf(&aListItem) : -1;
-
- // If we are in an empty item, then we want to pop up out of the list, but
- // only if prefs say it's okay and if the parent isn't the active editing
- // host.
- bool isEmpty;
- nsresult rv = IsEmptyBlock(aListItem, &isEmpty, MozBRCounts::no);
- NS_ENSURE_SUCCESS(rv, rv);
- if (isEmpty && root != list && mReturnInEmptyLIKillsList) {
- // Get the list offset now -- before we might eventually split the list
- nsCOMPtr<nsINode> listParent = list->GetParentNode();
- int32_t offset = listParent ? listParent->IndexOf(list) : -1;
-
- // Are we the last list item in the list?
- bool isLast;
- rv = htmlEditor->IsLastEditableChild(aListItem.AsDOMNode(), &isLast);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!isLast) {
- // We need to split the list!
- ErrorResult rv;
- htmlEditor->SplitNode(*list, itemOffset, rv);
- NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult());
- }
-
- // Are we in a sublist?
- if (HTMLEditUtils::IsList(listParent)) {
- // If so, move item out of this list and into the grandparent list
- rv = htmlEditor->MoveNode(&aListItem, listParent, offset + 1);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = aSelection.Collapse(&aListItem, 0);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // Otherwise kill this item
- rv = htmlEditor->DeleteNode(&aListItem);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Time to insert a paragraph
- nsCOMPtr<Element> pNode =
- htmlEditor->CreateNode(nsGkAtoms::p, listParent, offset + 1);
- NS_ENSURE_STATE(pNode);
-
- // Append a <br> to it
- nsCOMPtr<Element> brNode = htmlEditor->CreateBR(pNode, 0);
- NS_ENSURE_STATE(brNode);
-
- // Set selection to before the break
- rv = aSelection.Collapse(pNode, 0);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
- }
-
- // Else we want a new list item at the same list level. Get ws code to
- // adjust any ws.
- nsCOMPtr<nsINode> selNode = &aNode;
- rv = WSRunObject::PrepareToSplitAcrossBlocks(htmlEditor,
- address_of(selNode), &aOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- // Now split list item
- NS_ENSURE_STATE(selNode->IsContent());
- htmlEditor->SplitNodeDeep(aListItem, *selNode->AsContent(), aOffset);
-
- // Hack: until I can change the damaged doc range code back to being
- // extra-inclusive, I have to manually detect certain list items that may be
- // left empty.
- nsCOMPtr<nsIContent> prevItem = htmlEditor->GetPriorHTMLSibling(&aListItem);
- if (prevItem && HTMLEditUtils::IsListItem(prevItem)) {
- bool isEmptyNode;
- rv = htmlEditor->IsEmptyNode(prevItem, &isEmptyNode);
- NS_ENSURE_SUCCESS(rv, rv);
- if (isEmptyNode) {
- rv = CreateMozBR(prevItem->AsDOMNode(), 0);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- rv = htmlEditor->IsEmptyNode(&aListItem, &isEmptyNode, true);
- NS_ENSURE_SUCCESS(rv, rv);
- if (isEmptyNode) {
- nsCOMPtr<nsIAtom> nodeAtom = aListItem.NodeInfo()->NameAtom();
- if (nodeAtom == nsGkAtoms::dd || nodeAtom == nsGkAtoms::dt) {
- nsCOMPtr<nsINode> list = aListItem.GetParentNode();
- int32_t itemOffset = list ? list->IndexOf(&aListItem) : -1;
-
- nsIAtom* listAtom = nodeAtom == nsGkAtoms::dt ? nsGkAtoms::dd
- : nsGkAtoms::dt;
- nsCOMPtr<Element> newListItem =
- htmlEditor->CreateNode(listAtom, list, itemOffset + 1);
- NS_ENSURE_STATE(newListItem);
- rv = mTextEditor->DeleteNode(&aListItem);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = aSelection.Collapse(newListItem, 0);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
- }
-
- nsCOMPtr<Element> brNode;
- rv = htmlEditor->CopyLastEditableChildStyles(GetAsDOMNode(prevItem),
- GetAsDOMNode(&aListItem),
- getter_AddRefs(brNode));
- NS_ENSURE_SUCCESS(rv, rv);
- if (brNode) {
- nsCOMPtr<nsINode> brParent = brNode->GetParentNode();
- int32_t offset = brParent ? brParent->IndexOf(brNode) : -1;
- rv = aSelection.Collapse(brParent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
- }
- } else {
- WSRunObject wsObj(htmlEditor, &aListItem, 0);
- nsCOMPtr<nsINode> visNode;
- int32_t visOffset = 0;
- WSType wsType;
- wsObj.NextVisibleNode(&aListItem, 0, address_of(visNode),
- &visOffset, &wsType);
- if (wsType == WSType::special || wsType == WSType::br ||
- visNode->IsHTMLElement(nsGkAtoms::hr)) {
- nsCOMPtr<nsINode> parent = visNode->GetParentNode();
- int32_t offset = parent ? parent->IndexOf(visNode) : -1;
- rv = aSelection.Collapse(parent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
- } else {
- rv = aSelection.Collapse(visNode, visOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
- }
- }
- }
- }
- rv = aSelection.Collapse(&aListItem, 0);
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
-}
-
-/**
- * MakeBlockquote() puts the list of nodes into one or more blockquotes.
- */
-nsresult
-HTMLEditRules::MakeBlockquote(nsTArray<OwningNonNull<nsINode>>& aNodeArray)
-{
- // The idea here is to put the nodes into a minimal number of blockquotes.
- // When the user blockquotes something, they expect one blockquote. That may
- // not be possible (for instance, if they have two table cells selected, you
- // need two blockquotes inside the cells).
- nsCOMPtr<Element> curBlock;
- nsCOMPtr<nsINode> prevParent;
-
- for (auto& curNode : aNodeArray) {
- // Get the node to act on, and its location
- NS_ENSURE_STATE(curNode->IsContent());
-
- // If the node is a table element or list item, dive inside
- if (HTMLEditUtils::IsTableElementButNotTable(curNode) ||
- HTMLEditUtils::IsListItem(curNode)) {
- // Forget any previous block
- curBlock = nullptr;
- // Recursion time
- nsTArray<OwningNonNull<nsINode>> childArray;
- GetChildNodesForOperation(*curNode, childArray);
- nsresult rv = MakeBlockquote(childArray);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // If the node has different parent than previous node, further nodes in a
- // new parent
- if (prevParent) {
- if (prevParent != curNode->GetParentNode()) {
- // Forget any previous blockquote node we were using
- curBlock = nullptr;
- prevParent = curNode->GetParentNode();
- }
- } else {
- prevParent = curNode->GetParentNode();
- }
-
- // If no curBlock, make one
- if (!curBlock) {
- nsCOMPtr<nsINode> curParent = curNode->GetParentNode();
- int32_t offset = curParent ? curParent->IndexOf(curNode) : -1;
- nsresult rv = SplitAsNeeded(*nsGkAtoms::blockquote, curParent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_STATE(mHTMLEditor);
- curBlock = mHTMLEditor->CreateNode(nsGkAtoms::blockquote, curParent,
- offset);
- NS_ENSURE_STATE(curBlock);
- // remember our new block for postprocessing
- mNewBlock = curBlock;
- // note: doesn't matter if we set mNewBlock multiple times.
- }
-
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv = mHTMLEditor->MoveNode(curNode->AsContent(), curBlock, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
-}
-
-/**
- * RemoveBlockStyle() makes the nodes have no special block type.
- */
-nsresult
-HTMLEditRules::RemoveBlockStyle(nsTArray<OwningNonNull<nsINode>>& aNodeArray)
-{
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- // Intent of this routine is to be used for converting to/from headers,
- // paragraphs, pre, and address. Those blocks that pretty much just contain
- // inline things...
- nsCOMPtr<Element> curBlock;
- nsCOMPtr<nsIContent> firstNode, lastNode;
- for (auto& curNode : aNodeArray) {
- // If curNode is a address, p, header, address, or pre, remove it
- if (HTMLEditUtils::IsFormatNode(curNode)) {
- // Process any partial progress saved
- if (curBlock) {
- nsresult rv = RemovePartOfBlock(*curBlock, *firstNode, *lastNode);
- NS_ENSURE_SUCCESS(rv, rv);
- firstNode = lastNode = curBlock = nullptr;
- }
- // Remove current block
- nsresult rv = htmlEditor->RemoveBlockContainer(*curNode->AsContent());
- NS_ENSURE_SUCCESS(rv, rv);
- } else if (curNode->IsAnyOfHTMLElements(nsGkAtoms::table,
- nsGkAtoms::tr,
- nsGkAtoms::tbody,
- nsGkAtoms::td,
- nsGkAtoms::li,
- nsGkAtoms::blockquote,
- nsGkAtoms::div) ||
- HTMLEditUtils::IsList(curNode)) {
- // Process any partial progress saved
- if (curBlock) {
- nsresult rv = RemovePartOfBlock(*curBlock, *firstNode, *lastNode);
- NS_ENSURE_SUCCESS(rv, rv);
- firstNode = lastNode = curBlock = nullptr;
- }
- // Recursion time
- nsTArray<OwningNonNull<nsINode>> childArray;
- GetChildNodesForOperation(*curNode, childArray);
- nsresult rv = RemoveBlockStyle(childArray);
- NS_ENSURE_SUCCESS(rv, rv);
- } else if (IsInlineNode(curNode)) {
- if (curBlock) {
- // If so, is this node a descendant?
- if (EditorUtils::IsDescendantOf(curNode, curBlock)) {
- // Then we don't need to do anything different for this node
- lastNode = curNode->AsContent();
- continue;
- }
- // Otherwise, we have progressed beyond end of curBlock, so let's
- // handle it now. We need to remove the portion of curBlock that
- // contains [firstNode - lastNode].
- nsresult rv = RemovePartOfBlock(*curBlock, *firstNode, *lastNode);
- NS_ENSURE_SUCCESS(rv, rv);
- firstNode = lastNode = curBlock = nullptr;
- // Fall out and handle curNode
- }
- curBlock = htmlEditor->GetBlockNodeParent(curNode);
- if (curBlock && HTMLEditUtils::IsFormatNode(curBlock)) {
- firstNode = lastNode = curNode->AsContent();
- } else {
- // Not a block kind that we care about.
- curBlock = nullptr;
- }
- } else if (curBlock) {
- // Some node that is already sans block style. Skip over it and process
- // any partial progress saved.
- nsresult rv = RemovePartOfBlock(*curBlock, *firstNode, *lastNode);
- NS_ENSURE_SUCCESS(rv, rv);
- firstNode = lastNode = curBlock = nullptr;
- }
- }
- // Process any partial progress saved
- if (curBlock) {
- nsresult rv = RemovePartOfBlock(*curBlock, *firstNode, *lastNode);
- NS_ENSURE_SUCCESS(rv, rv);
- firstNode = lastNode = curBlock = nullptr;
- }
- return NS_OK;
-}
-
-/**
- * ApplyBlockStyle() does whatever it takes to make the list of nodes into one
- * or more blocks of type aBlockTag.
- */
-nsresult
-HTMLEditRules::ApplyBlockStyle(nsTArray<OwningNonNull<nsINode>>& aNodeArray,
- nsIAtom& aBlockTag)
-{
- // Intent of this routine is to be used for converting to/from headers,
- // paragraphs, pre, and address. Those blocks that pretty much just contain
- // inline things...
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- // Remove all non-editable nodes. Leave them be.
- for (int32_t i = aNodeArray.Length() - 1; i >= 0; i--) {
- if (!htmlEditor->IsEditable(aNodeArray[i])) {
- aNodeArray.RemoveElementAt(i);
- }
- }
-
- nsCOMPtr<Element> newBlock;
-
- nsCOMPtr<Element> curBlock;
- for (auto& curNode : aNodeArray) {
- nsCOMPtr<nsINode> curParent = curNode->GetParentNode();
- int32_t offset = curParent ? curParent->IndexOf(curNode) : -1;
-
- // Is it already the right kind of block?
- if (curNode->IsHTMLElement(&aBlockTag)) {
- // Forget any previous block used for previous inline nodes
- curBlock = nullptr;
- // Do nothing to this block
- continue;
- }
-
- // If curNode is a address, p, header, address, or pre, replace it with a
- // new block of correct type.
- // XXX: pre can't hold everything the others can
- if (HTMLEditUtils::IsMozDiv(curNode) ||
- HTMLEditUtils::IsFormatNode(curNode)) {
- // Forget any previous block used for previous inline nodes
- curBlock = nullptr;
- newBlock = htmlEditor->ReplaceContainer(curNode->AsElement(),
- &aBlockTag, nullptr, nullptr,
- EditorBase::eCloneAttributes);
- NS_ENSURE_STATE(newBlock);
- } else if (HTMLEditUtils::IsTable(curNode) ||
- HTMLEditUtils::IsList(curNode) ||
- curNode->IsAnyOfHTMLElements(nsGkAtoms::tbody,
- nsGkAtoms::tr,
- nsGkAtoms::td,
- nsGkAtoms::li,
- nsGkAtoms::blockquote,
- nsGkAtoms::div)) {
- // Forget any previous block used for previous inline nodes
- curBlock = nullptr;
- // Recursion time
- nsTArray<OwningNonNull<nsINode>> childArray;
- GetChildNodesForOperation(*curNode, childArray);
- if (!childArray.IsEmpty()) {
- nsresult rv = ApplyBlockStyle(childArray, aBlockTag);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // Make sure we can put a block here
- nsresult rv = SplitAsNeeded(aBlockTag, curParent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<Element> theBlock =
- htmlEditor->CreateNode(&aBlockTag, curParent, offset);
- NS_ENSURE_STATE(theBlock);
- // Remember our new block for postprocessing
- mNewBlock = theBlock;
- }
- } else if (curNode->IsHTMLElement(nsGkAtoms::br)) {
- // If the node is a break, we honor it by putting further nodes in a new
- // parent
- if (curBlock) {
- // Forget any previous block used for previous inline nodes
- curBlock = nullptr;
- nsresult rv = htmlEditor->DeleteNode(curNode);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // The break is the first (or even only) node we encountered. Create a
- // block for it.
- nsresult rv = SplitAsNeeded(aBlockTag, curParent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- curBlock = htmlEditor->CreateNode(&aBlockTag, curParent, offset);
- NS_ENSURE_STATE(curBlock);
- // Remember our new block for postprocessing
- mNewBlock = curBlock;
- // Note: doesn't matter if we set mNewBlock multiple times.
- rv = htmlEditor->MoveNode(curNode->AsContent(), curBlock, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- } else if (IsInlineNode(curNode)) {
- // If curNode is inline, pull it into curBlock. Note: it's assumed that
- // consecutive inline nodes in aNodeArray are actually members of the
- // same block parent. This happens to be true now as a side effect of
- // how aNodeArray is contructed, but some additional logic should be
- // added here if that should change
- //
- // If curNode is a non editable, drop it if we are going to <pre>.
- if (&aBlockTag == nsGkAtoms::pre && !htmlEditor->IsEditable(curNode)) {
- // Do nothing to this block
- continue;
- }
-
- // If no curBlock, make one
- if (!curBlock) {
- nsresult rv = SplitAsNeeded(aBlockTag, curParent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- curBlock = htmlEditor->CreateNode(&aBlockTag, curParent, offset);
- NS_ENSURE_STATE(curBlock);
- // Remember our new block for postprocessing
- mNewBlock = curBlock;
- // Note: doesn't matter if we set mNewBlock multiple times.
- }
-
- // XXX If curNode is a br, replace it with a return if going to <pre>
-
- // This is a continuation of some inline nodes that belong together in
- // the same block item. Use curBlock.
- nsresult rv = htmlEditor->MoveNode(curNode->AsContent(), curBlock, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- return NS_OK;
-}
-
-/**
- * Given a tag name, split inOutParent up to the point where we can insert the
- * tag. Adjust inOutParent and inOutOffset to point to new location for tag.
- */
-nsresult
-HTMLEditRules::SplitAsNeeded(nsIAtom& aTag,
- OwningNonNull<nsINode>& aInOutParent,
- int32_t& aInOutOffset)
-{
- // XXX Is there a better way to do this?
- nsCOMPtr<nsINode> parent = aInOutParent.forget();
- nsresult rv = SplitAsNeeded(aTag, parent, aInOutOffset);
- aInOutParent = parent.forget();
- return rv;
-}
-
-nsresult
-HTMLEditRules::SplitAsNeeded(nsIAtom& aTag,
- nsCOMPtr<nsINode>& inOutParent,
- int32_t& inOutOffset)
-{
- NS_ENSURE_TRUE(inOutParent, NS_ERROR_NULL_POINTER);
-
- // Check that we have a place that can legally contain the tag
- nsCOMPtr<nsINode> tagParent, splitNode;
- for (nsCOMPtr<nsINode> parent = inOutParent; parent;
- parent = parent->GetParentNode()) {
- // Sniffing up the parent tree until we find a legal place for the block
-
- // Don't leave the active editing host
- NS_ENSURE_STATE(mHTMLEditor);
- if (!mHTMLEditor->IsDescendantOfEditorRoot(parent)) {
- // XXX Why do we need to check mHTMLEditor again here?
- NS_ENSURE_STATE(mHTMLEditor);
- if (parent != mHTMLEditor->GetActiveEditingHost()) {
- return NS_ERROR_FAILURE;
- }
- }
-
- NS_ENSURE_STATE(mHTMLEditor);
- if (mHTMLEditor->CanContainTag(*parent, aTag)) {
- // Success
- tagParent = parent;
- break;
- }
-
- splitNode = parent;
- }
- if (!tagParent) {
- // Could not find a place to build tag!
- return NS_ERROR_FAILURE;
- }
- if (splitNode && splitNode->IsContent() && inOutParent->IsContent()) {
- // We found a place for block, but above inOutParent. We need to split.
- NS_ENSURE_STATE(mHTMLEditor);
- int32_t offset = mHTMLEditor->SplitNodeDeep(*splitNode->AsContent(),
- *inOutParent->AsContent(),
- inOutOffset);
- NS_ENSURE_STATE(offset != -1);
- inOutParent = tagParent;
- inOutOffset = offset;
- }
- return NS_OK;
-}
-
-/**
- * JoinNodesSmart: Join two nodes, doing whatever makes sense for their
- * children (which often means joining them, too). aNodeLeft & aNodeRight must
- * be same type of node.
- *
- * Returns the point where they're merged, or (nullptr, -1) on failure.
- */
-EditorDOMPoint
-HTMLEditRules::JoinNodesSmart(nsIContent& aNodeLeft,
- nsIContent& aNodeRight)
-{
- // Caller responsible for left and right node being the same type
- nsCOMPtr<nsINode> parent = aNodeLeft.GetParentNode();
- NS_ENSURE_TRUE(parent, EditorDOMPoint());
- int32_t parOffset = parent->IndexOf(&aNodeLeft);
- nsCOMPtr<nsINode> rightParent = aNodeRight.GetParentNode();
-
- // If they don't have the same parent, first move the right node to after the
- // left one
- if (parent != rightParent) {
- NS_ENSURE_TRUE(mHTMLEditor, EditorDOMPoint());
- nsresult rv = mHTMLEditor->MoveNode(&aNodeRight, parent, parOffset);
- NS_ENSURE_SUCCESS(rv, EditorDOMPoint());
- }
-
- EditorDOMPoint ret(&aNodeRight, aNodeLeft.Length());
-
- // Separate join rules for differing blocks
- if (HTMLEditUtils::IsList(&aNodeLeft) || aNodeLeft.GetAsText()) {
- // For lists, merge shallow (wouldn't want to combine list items)
- nsresult rv = mHTMLEditor->JoinNodes(aNodeLeft, aNodeRight);
- NS_ENSURE_SUCCESS(rv, EditorDOMPoint());
- return ret;
- }
-
- // Remember the last left child, and first right child
- NS_ENSURE_TRUE(mHTMLEditor, EditorDOMPoint());
- nsCOMPtr<nsIContent> lastLeft = mHTMLEditor->GetLastEditableChild(aNodeLeft);
- NS_ENSURE_TRUE(lastLeft, EditorDOMPoint());
-
- NS_ENSURE_TRUE(mHTMLEditor, EditorDOMPoint());
- nsCOMPtr<nsIContent> firstRight = mHTMLEditor->GetFirstEditableChild(aNodeRight);
- NS_ENSURE_TRUE(firstRight, EditorDOMPoint());
-
- // For list items, divs, etc., merge smart
- NS_ENSURE_TRUE(mHTMLEditor, EditorDOMPoint());
- nsresult rv = mHTMLEditor->JoinNodes(aNodeLeft, aNodeRight);
- NS_ENSURE_SUCCESS(rv, EditorDOMPoint());
-
- if (lastLeft && firstRight && mHTMLEditor &&
- mHTMLEditor->AreNodesSameType(lastLeft, firstRight) &&
- (lastLeft->GetAsText() || !mHTMLEditor ||
- (lastLeft->IsElement() && firstRight->IsElement() &&
- mHTMLEditor->mCSSEditUtils->ElementsSameStyle(lastLeft->AsElement(),
- firstRight->AsElement())))) {
- NS_ENSURE_TRUE(mHTMLEditor, EditorDOMPoint());
- return JoinNodesSmart(*lastLeft, *firstRight);
- }
- return ret;
-}
-
-Element*
-HTMLEditRules::GetTopEnclosingMailCite(nsINode& aNode)
-{
- nsCOMPtr<Element> ret;
-
- for (nsCOMPtr<nsINode> node = &aNode; node; node = node->GetParentNode()) {
- if ((IsPlaintextEditor() && node->IsHTMLElement(nsGkAtoms::pre)) ||
- HTMLEditUtils::IsMailCite(node)) {
- ret = node->AsElement();
- }
- if (node->IsHTMLElement(nsGkAtoms::body)) {
- break;
- }
- }
-
- return ret;
-}
-
-nsresult
-HTMLEditRules::CacheInlineStyles(nsIDOMNode* aNode)
-{
- NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
-
- NS_ENSURE_STATE(mHTMLEditor);
- bool useCSS = mHTMLEditor->IsCSSEnabled();
-
- for (int32_t j = 0; j < SIZE_STYLE_TABLE; ++j) {
- // If type-in state is set, don't intervene
- bool typeInSet, unused;
- if (NS_WARN_IF(!mHTMLEditor)) {
- return NS_ERROR_UNEXPECTED;
- }
- mHTMLEditor->mTypeInState->GetTypingState(typeInSet, unused,
- mCachedStyles[j].tag, mCachedStyles[j].attr, nullptr);
- if (typeInSet) {
- continue;
- }
-
- bool isSet = false;
- nsAutoString outValue;
- // Don't use CSS for <font size>, we don't support it usefully (bug 780035)
- if (!useCSS || (mCachedStyles[j].tag == nsGkAtoms::font &&
- mCachedStyles[j].attr.EqualsLiteral("size"))) {
- NS_ENSURE_STATE(mHTMLEditor);
- mHTMLEditor->IsTextPropertySetByContent(aNode, mCachedStyles[j].tag,
- &(mCachedStyles[j].attr), nullptr,
- isSet, &outValue);
- } else {
- NS_ENSURE_STATE(mHTMLEditor);
- isSet = mHTMLEditor->mCSSEditUtils->IsCSSEquivalentToHTMLInlineStyleSet(
- aNode, mCachedStyles[j].tag, &(mCachedStyles[j].attr), outValue,
- CSSEditUtils::eComputed);
- }
- if (isSet) {
- mCachedStyles[j].mPresent = true;
- mCachedStyles[j].value.Assign(outValue);
- }
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::ReapplyCachedStyles()
-{
- // The idea here is to examine our cached list of styles and see if any have
- // been removed. If so, add typeinstate for them, so that they will be
- // reinserted when new content is added.
-
- // remember if we are in css mode
- NS_ENSURE_STATE(mHTMLEditor);
- bool useCSS = mHTMLEditor->IsCSSEnabled();
-
- // get selection point; if it doesn't exist, we have nothing to do
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<Selection> selection = mHTMLEditor->GetSelection();
- if (!selection) {
- // If the document is removed from its parent document during executing an
- // editor operation with DOMMutationEvent or something, there may be no
- // selection.
- return NS_OK;
- }
- if (!selection->RangeCount()) {
- // Nothing to do
- return NS_OK;
- }
- nsCOMPtr<nsIContent> selNode =
- do_QueryInterface(selection->GetRangeAt(0)->GetStartParent());
- if (!selNode) {
- // Nothing to do
- return NS_OK;
- }
-
- for (int32_t i = 0; i < SIZE_STYLE_TABLE; ++i) {
- if (mCachedStyles[i].mPresent) {
- bool bFirst, bAny, bAll;
- bFirst = bAny = bAll = false;
-
- nsAutoString curValue;
- if (useCSS) {
- // check computed style first in css case
- NS_ENSURE_STATE(mHTMLEditor);
- bAny = mHTMLEditor->mCSSEditUtils->IsCSSEquivalentToHTMLInlineStyleSet(
- selNode, mCachedStyles[i].tag, &(mCachedStyles[i].attr), curValue,
- CSSEditUtils::eComputed);
- }
- if (!bAny) {
- // then check typeinstate and html style
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->GetInlinePropertyBase(*mCachedStyles[i].tag,
- &(mCachedStyles[i].attr),
- &(mCachedStyles[i].value),
- &bFirst, &bAny, &bAll,
- &curValue, false);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // this style has disappeared through deletion. Add to our typeinstate:
- if (!bAny || IsStyleCachePreservingAction(mTheAction)) {
- NS_ENSURE_STATE(mHTMLEditor);
- mHTMLEditor->mTypeInState->SetProp(mCachedStyles[i].tag,
- mCachedStyles[i].attr,
- mCachedStyles[i].value);
- }
- }
- }
-
- return NS_OK;
-}
-
-void
-HTMLEditRules::ClearCachedStyles()
-{
- // clear the mPresent bits in mCachedStyles array
- for (uint32_t j = 0; j < SIZE_STYLE_TABLE; j++) {
- mCachedStyles[j].mPresent = false;
- mCachedStyles[j].value.Truncate();
- }
-}
-
-void
-HTMLEditRules::AdjustSpecialBreaks()
-{
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
-
- // Gather list of empty nodes
- nsTArray<OwningNonNull<nsINode>> nodeArray;
- EmptyEditableFunctor functor(mHTMLEditor);
- DOMIterator iter;
- if (NS_WARN_IF(NS_FAILED(iter.Init(*mDocChangeRange)))) {
- return;
- }
- iter.AppendList(functor, nodeArray);
-
- // Put moz-br's into these empty li's and td's
- for (auto& node : nodeArray) {
- // Need to put br at END of node. It may have empty containers in it and
- // still pass the "IsEmptyNode" test, and we want the br's to be after
- // them. Also, we want the br to be after the selection if the selection
- // is in this node.
- nsresult rv = CreateMozBR(node->AsDOMNode(), (int32_t)node->Length());
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return;
- }
- }
-}
-
-nsresult
-HTMLEditRules::AdjustWhitespace(Selection* aSelection)
-{
- // get selection point
- nsCOMPtr<nsIDOMNode> selNode;
- int32_t selOffset;
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->GetStartNodeAndOffset(aSelection,
- getter_AddRefs(selNode), &selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // ask whitespace object to tweak nbsp's
- NS_ENSURE_STATE(mHTMLEditor);
- return WSRunObject(mHTMLEditor, selNode, selOffset).AdjustWhitespace();
-}
-
-nsresult
-HTMLEditRules::PinSelectionToNewBlock(Selection* aSelection)
-{
- NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
- if (!aSelection->Collapsed()) {
- return NS_OK;
- }
-
- if (NS_WARN_IF(!mNewBlock)) {
- return NS_ERROR_NULL_POINTER;
- }
-
- // get the (collapsed) selection location
- nsCOMPtr<nsIDOMNode> selNode;
- int32_t selOffset;
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->GetStartNodeAndOffset(aSelection,
- getter_AddRefs(selNode), &selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // use ranges and sRangeHelper to compare sel point to new block
- nsCOMPtr<nsINode> node = do_QueryInterface(selNode);
- NS_ENSURE_STATE(node);
- RefPtr<nsRange> range = new nsRange(node);
- rv = range->CollapseTo(node, selOffset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- bool nodeBefore, nodeAfter;
- rv = nsRange::CompareNodeToRange(mNewBlock, range, &nodeBefore, &nodeAfter);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (nodeBefore && nodeAfter) {
- return NS_OK; // selection is inside block
- } else if (nodeBefore) {
- // selection is after block. put at end of block.
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<nsINode> tmp = mHTMLEditor->GetLastEditableChild(*mNewBlock);
- if (!tmp) {
- tmp = mNewBlock;
- }
- uint32_t endPoint;
- if (mHTMLEditor->IsTextNode(tmp) ||
- mHTMLEditor->IsContainer(tmp)) {
- endPoint = tmp->Length();
- } else {
- tmp = EditorBase::GetNodeLocation(tmp, (int32_t*)&endPoint);
- endPoint++; // want to be after this node
- }
- return aSelection->Collapse(tmp, (int32_t)endPoint);
- } else {
- // selection is before block. put at start of block.
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<nsINode> tmp = mHTMLEditor->GetFirstEditableChild(*mNewBlock);
- if (!tmp) {
- tmp = mNewBlock;
- }
- int32_t offset;
- if (mHTMLEditor->IsTextNode(tmp) ||
- mHTMLEditor->IsContainer(tmp)) {
- tmp = EditorBase::GetNodeLocation(tmp, &offset);
- }
- return aSelection->Collapse(tmp, 0);
- }
-}
-
-void
-HTMLEditRules::CheckInterlinePosition(Selection& aSelection)
-{
- // If the selection isn't collapsed, do nothing.
- if (!aSelection.Collapsed()) {
- return;
- }
-
- NS_ENSURE_TRUE_VOID(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- // Get the (collapsed) selection location
- NS_ENSURE_TRUE_VOID(aSelection.GetRangeAt(0) &&
- aSelection.GetRangeAt(0)->GetStartParent());
- OwningNonNull<nsINode> selNode = *aSelection.GetRangeAt(0)->GetStartParent();
- int32_t selOffset = aSelection.GetRangeAt(0)->StartOffset();
-
- // First, let's check to see if we are after a <br>. We take care of this
- // special-case first so that we don't accidentally fall through into one of
- // the other conditionals.
- nsCOMPtr<nsIContent> node =
- htmlEditor->GetPriorHTMLNode(selNode, selOffset, true);
- if (node && node->IsHTMLElement(nsGkAtoms::br)) {
- aSelection.SetInterlinePosition(true);
- return;
- }
-
- // Are we after a block? If so try set caret to following content
- node = htmlEditor->GetPriorHTMLSibling(selNode, selOffset);
- if (node && IsBlockNode(*node)) {
- aSelection.SetInterlinePosition(true);
- return;
- }
-
- // Are we before a block? If so try set caret to prior content
- node = htmlEditor->GetNextHTMLSibling(selNode, selOffset);
- if (node && IsBlockNode(*node)) {
- aSelection.SetInterlinePosition(false);
- }
-}
-
-nsresult
-HTMLEditRules::AdjustSelection(Selection* aSelection,
- nsIEditor::EDirection aAction)
-{
- NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
-
- // if the selection isn't collapsed, do nothing.
- // moose: one thing to do instead is check for the case of
- // only a single break selected, and collapse it. Good thing? Beats me.
- if (!aSelection->Collapsed()) {
- return NS_OK;
- }
-
- // get the (collapsed) selection location
- nsCOMPtr<nsINode> selNode, temp;
- int32_t selOffset;
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->GetStartNodeAndOffset(aSelection,
- getter_AddRefs(selNode), &selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- temp = selNode;
-
- // are we in an editable node?
- NS_ENSURE_STATE(mHTMLEditor);
- while (!mHTMLEditor->IsEditable(selNode)) {
- // scan up the tree until we find an editable place to be
- selNode = EditorBase::GetNodeLocation(temp, &selOffset);
- NS_ENSURE_TRUE(selNode, NS_ERROR_FAILURE);
- temp = selNode;
- NS_ENSURE_STATE(mHTMLEditor);
- }
-
- // make sure we aren't in an empty block - user will see no cursor. If this
- // is happening, put a <br> in the block if allowed.
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<Element> theblock = mHTMLEditor->GetBlock(*selNode);
-
- if (theblock && mHTMLEditor->IsEditable(theblock)) {
- bool bIsEmptyNode;
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->IsEmptyNode(theblock, &bIsEmptyNode, false, false);
- NS_ENSURE_SUCCESS(rv, rv);
- // check if br can go into the destination node
- NS_ENSURE_STATE(mHTMLEditor);
- if (bIsEmptyNode && mHTMLEditor->CanContainTag(*selNode, *nsGkAtoms::br)) {
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<Element> rootNode = mHTMLEditor->GetRoot();
- NS_ENSURE_TRUE(rootNode, NS_ERROR_FAILURE);
- if (selNode == rootNode) {
- // Our root node is completely empty. Don't add a <br> here.
- // AfterEditInner() will add one for us when it calls
- // CreateBogusNodeIfNeeded()!
- return NS_OK;
- }
-
- // we know we can skip the rest of this routine given the cirumstance
- return CreateMozBR(GetAsDOMNode(selNode), selOffset);
- }
- }
-
- // are we in a text node?
- nsCOMPtr<nsIDOMCharacterData> textNode = do_QueryInterface(selNode);
- if (textNode)
- return NS_OK; // we LIKE it when we are in a text node. that RULZ
-
- // do we need to insert a special mozBR? We do if we are:
- // 1) prior node is in same block where selection is AND
- // 2) prior node is a br AND
- // 3) that br is not visible
-
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<nsIContent> nearNode =
- mHTMLEditor->GetPriorHTMLNode(selNode, selOffset);
- if (nearNode) {
- // is nearNode also a descendant of same block?
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<Element> block = mHTMLEditor->GetBlock(*selNode);
- nsCOMPtr<Element> nearBlock = mHTMLEditor->GetBlockNodeParent(nearNode);
- if (block && block == nearBlock) {
- if (nearNode && TextEditUtils::IsBreak(nearNode)) {
- NS_ENSURE_STATE(mHTMLEditor);
- if (!mHTMLEditor->IsVisBreak(nearNode)) {
- // need to insert special moz BR. Why? Because if we don't
- // the user will see no new line for the break. Also, things
- // like table cells won't grow in height.
- nsCOMPtr<nsIDOMNode> brNode;
- rv = CreateMozBR(GetAsDOMNode(selNode), selOffset,
- getter_AddRefs(brNode));
- NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsIDOMNode> brParent =
- EditorBase::GetNodeLocation(brNode, &selOffset);
- // selection stays *before* moz-br, sticking to it
- aSelection->SetInterlinePosition(true);
- rv = aSelection->Collapse(brParent, selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<nsIContent> nextNode =
- mHTMLEditor->GetNextHTMLNode(nearNode, true);
- if (nextNode && TextEditUtils::IsMozBR(nextNode)) {
- // selection between br and mozbr. make it stick to mozbr
- // so that it will be on blank line.
- aSelection->SetInterlinePosition(true);
- }
- }
- }
- }
- }
-
- // we aren't in a textnode: are we adjacent to text or a break or an image?
- NS_ENSURE_STATE(mHTMLEditor);
- nearNode = mHTMLEditor->GetPriorHTMLNode(selNode, selOffset, true);
- if (nearNode && (TextEditUtils::IsBreak(nearNode) ||
- EditorBase::IsTextNode(nearNode) ||
- HTMLEditUtils::IsImage(nearNode) ||
- nearNode->IsHTMLElement(nsGkAtoms::hr))) {
- // this is a good place for the caret to be
- return NS_OK;
- }
- NS_ENSURE_STATE(mHTMLEditor);
- nearNode = mHTMLEditor->GetNextHTMLNode(selNode, selOffset, true);
- if (nearNode && (TextEditUtils::IsBreak(nearNode) ||
- EditorBase::IsTextNode(nearNode) ||
- nearNode->IsAnyOfHTMLElements(nsGkAtoms::img,
- nsGkAtoms::hr))) {
- return NS_OK; // this is a good place for the caret to be
- }
-
- // look for a nearby text node.
- // prefer the correct direction.
- nsCOMPtr<nsIDOMNode> nearNodeDOM = GetAsDOMNode(nearNode);
- rv = FindNearSelectableNode(GetAsDOMNode(selNode), selOffset, aAction,
- address_of(nearNodeDOM));
- NS_ENSURE_SUCCESS(rv, rv);
- nearNode = do_QueryInterface(nearNodeDOM);
-
- if (!nearNode) {
- return NS_OK;
- }
- EditorDOMPoint pt = GetGoodSelPointForNode(*nearNode, aAction);
- rv = aSelection->Collapse(pt.node, pt.offset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- return NS_OK;
-}
-
-
-nsresult
-HTMLEditRules::FindNearSelectableNode(nsIDOMNode* aSelNode,
- int32_t aSelOffset,
- nsIEditor::EDirection& aDirection,
- nsCOMPtr<nsIDOMNode>* outSelectableNode)
-{
- NS_ENSURE_TRUE(aSelNode && outSelectableNode, NS_ERROR_NULL_POINTER);
- *outSelectableNode = nullptr;
-
- nsCOMPtr<nsIDOMNode> nearNode, curNode;
- if (aDirection == nsIEditor::ePrevious) {
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->GetPriorHTMLNode(aSelNode, aSelOffset, address_of(nearNode));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->GetNextHTMLNode(aSelNode, aSelOffset, address_of(nearNode));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
-
- // Try the other direction then.
- if (!nearNode) {
- if (aDirection == nsIEditor::ePrevious) {
- aDirection = nsIEditor::eNext;
- } else {
- aDirection = nsIEditor::ePrevious;
- }
-
- if (aDirection == nsIEditor::ePrevious) {
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv = mHTMLEditor->GetPriorHTMLNode(aSelNode, aSelOffset,
- address_of(nearNode));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv = mHTMLEditor->GetNextHTMLNode(aSelNode, aSelOffset,
- address_of(nearNode));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- }
-
- // scan in the right direction until we find an eligible text node,
- // but don't cross any breaks, images, or table elements.
- NS_ENSURE_STATE(mHTMLEditor);
- while (nearNode && !(mHTMLEditor->IsTextNode(nearNode) ||
- TextEditUtils::IsBreak(nearNode) ||
- HTMLEditUtils::IsImage(nearNode))) {
- curNode = nearNode;
- if (aDirection == nsIEditor::ePrevious) {
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->GetPriorHTMLNode(curNode, address_of(nearNode));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv = mHTMLEditor->GetNextHTMLNode(curNode, address_of(nearNode));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- NS_ENSURE_STATE(mHTMLEditor);
- }
-
- if (nearNode) {
- // don't cross any table elements
- if (InDifferentTableElements(nearNode, aSelNode)) {
- return NS_OK;
- }
-
- // otherwise, ok, we have found a good spot to put the selection
- *outSelectableNode = do_QueryInterface(nearNode);
- }
- return NS_OK;
-}
-
-bool
-HTMLEditRules::InDifferentTableElements(nsIDOMNode* aNode1,
- nsIDOMNode* aNode2)
-{
- nsCOMPtr<nsINode> node1 = do_QueryInterface(aNode1);
- nsCOMPtr<nsINode> node2 = do_QueryInterface(aNode2);
- return InDifferentTableElements(node1, node2);
-}
-
-bool
-HTMLEditRules::InDifferentTableElements(nsINode* aNode1,
- nsINode* aNode2)
-{
- MOZ_ASSERT(aNode1 && aNode2);
-
- while (aNode1 && !HTMLEditUtils::IsTableElement(aNode1)) {
- aNode1 = aNode1->GetParentNode();
- }
-
- while (aNode2 && !HTMLEditUtils::IsTableElement(aNode2)) {
- aNode2 = aNode2->GetParentNode();
- }
-
- return aNode1 != aNode2;
-}
-
-
-nsresult
-HTMLEditRules::RemoveEmptyNodes()
-{
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- // Some general notes on the algorithm used here: the goal is to examine all
- // the nodes in mDocChangeRange, and remove the empty ones. We do this by
- // using a content iterator to traverse all the nodes in the range, and
- // placing the empty nodes into an array. After finishing the iteration, we
- // delete the empty nodes in the array. (They cannot be deleted as we find
- // them because that would invalidate the iterator.)
- //
- // Since checking to see if a node is empty can be costly for nodes with many
- // descendants, there are some optimizations made. I rely on the fact that
- // the iterator is post-order: it will visit children of a node before
- // visiting the parent node. So if I find that a child node is not empty, I
- // know that its parent is not empty without even checking. So I put the
- // parent on a "skipList" which is just a voidArray of nodes I can skip the
- // empty check on. If I encounter a node on the skiplist, i skip the
- // processing for that node and replace its slot in the skiplist with that
- // node's parent.
- //
- // An interesting idea is to go ahead and regard parent nodes that are NOT on
- // the skiplist as being empty (without even doing the IsEmptyNode check) on
- // the theory that if they weren't empty, we would have encountered a
- // non-empty child earlier and thus put this parent node on the skiplist.
- //
- // Unfortunately I can't use that strategy here, because the range may
- // include some children of a node while excluding others. Thus I could find
- // all the _examined_ children empty, but still not have an empty parent.
-
- // need an iterator
- nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
-
- nsresult rv = iter->Init(mDocChangeRange);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsTArray<OwningNonNull<nsINode>> arrayOfEmptyNodes, arrayOfEmptyCites, skipList;
-
- // Check for empty nodes
- while (!iter->IsDone()) {
- OwningNonNull<nsINode> node = *iter->GetCurrentNode();
-
- nsCOMPtr<nsINode> parent = node->GetParentNode();
-
- size_t idx = skipList.IndexOf(node);
- if (idx != skipList.NoIndex) {
- // This node is on our skip list. Skip processing for this node, and
- // replace its value in the skip list with the value of its parent
- if (parent) {
- skipList[idx] = parent;
- }
- } else {
- bool bIsCandidate = false;
- bool bIsEmptyNode = false;
- bool bIsMailCite = false;
-
- if (node->IsElement()) {
- if (node->IsHTMLElement(nsGkAtoms::body)) {
- // Don't delete the body
- } else if ((bIsMailCite = HTMLEditUtils::IsMailCite(node)) ||
- node->IsHTMLElement(nsGkAtoms::a) ||
- HTMLEditUtils::IsInlineStyle(node) ||
- HTMLEditUtils::IsList(node) ||
- node->IsHTMLElement(nsGkAtoms::div)) {
- // Only consider certain nodes to be empty for purposes of removal
- bIsCandidate = true;
- } else if (HTMLEditUtils::IsFormatNode(node) ||
- HTMLEditUtils::IsListItem(node) ||
- node->IsHTMLElement(nsGkAtoms::blockquote)) {
- // These node types are candidates if selection is not in them. If
- // it is one of these, don't delete if selection inside. This is so
- // we can create empty headings, etc., for the user to type into.
- bool bIsSelInNode;
- rv = SelectionEndpointInNode(node, &bIsSelInNode);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!bIsSelInNode) {
- bIsCandidate = true;
- }
- }
- }
-
- if (bIsCandidate) {
- // We delete mailcites even if they have a solo br in them. Other
- // nodes we require to be empty.
- rv = htmlEditor->IsEmptyNode(node->AsDOMNode(), &bIsEmptyNode,
- bIsMailCite, true);
- NS_ENSURE_SUCCESS(rv, rv);
- if (bIsEmptyNode) {
- if (bIsMailCite) {
- // mailcites go on a separate list from other empty nodes
- arrayOfEmptyCites.AppendElement(*node);
- } else {
- arrayOfEmptyNodes.AppendElement(*node);
- }
- }
- }
-
- if (!bIsEmptyNode && parent) {
- // put parent on skip list
- skipList.AppendElement(*parent);
- }
- }
-
- iter->Next();
- }
-
- // now delete the empty nodes
- for (auto& delNode : arrayOfEmptyNodes) {
- if (htmlEditor->IsModifiableNode(delNode)) {
- rv = htmlEditor->DeleteNode(delNode);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- // Now delete the empty mailcites. This is a separate step because we want
- // to pull out any br's and preserve them.
- for (auto& delNode : arrayOfEmptyCites) {
- bool bIsEmptyNode;
- rv = htmlEditor->IsEmptyNode(delNode, &bIsEmptyNode, false, true);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!bIsEmptyNode) {
- // We are deleting a cite that has just a br. We want to delete cite,
- // but preserve br.
- nsCOMPtr<nsINode> parent = delNode->GetParentNode();
- int32_t offset = parent ? parent->IndexOf(delNode) : -1;
- nsCOMPtr<Element> br = htmlEditor->CreateBR(parent, offset);
- NS_ENSURE_STATE(br);
- }
- rv = htmlEditor->DeleteNode(delNode);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::SelectionEndpointInNode(nsINode* aNode,
- bool* aResult)
-{
- NS_ENSURE_TRUE(aNode && aResult, NS_ERROR_NULL_POINTER);
-
- nsIDOMNode* node = aNode->AsDOMNode();
-
- *aResult = false;
-
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<Selection> selection = mHTMLEditor->GetSelection();
- NS_ENSURE_STATE(selection);
-
- uint32_t rangeCount = selection->RangeCount();
- for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
- RefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
- nsCOMPtr<nsIDOMNode> startParent, endParent;
- range->GetStartContainer(getter_AddRefs(startParent));
- if (startParent) {
- if (node == startParent) {
- *aResult = true;
- return NS_OK;
- }
- if (EditorUtils::IsDescendantOf(startParent, node)) {
- *aResult = true;
- return NS_OK;
- }
- }
- range->GetEndContainer(getter_AddRefs(endParent));
- if (startParent == endParent) {
- continue;
- }
- if (endParent) {
- if (node == endParent) {
- *aResult = true;
- return NS_OK;
- }
- if (EditorUtils::IsDescendantOf(endParent, node)) {
- *aResult = true;
- return NS_OK;
- }
- }
- }
- return NS_OK;
-}
-
-/**
- * IsEmptyInline: Return true if aNode is an empty inline container
- */
-bool
-HTMLEditRules::IsEmptyInline(nsINode& aNode)
-{
- NS_ENSURE_TRUE(mHTMLEditor, false);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- if (IsInlineNode(aNode) && htmlEditor->IsContainer(&aNode)) {
- bool isEmpty = true;
- htmlEditor->IsEmptyNode(&aNode, &isEmpty);
- return isEmpty;
- }
- return false;
-}
-
-
-bool
-HTMLEditRules::ListIsEmptyLine(nsTArray<OwningNonNull<nsINode>>& aArrayOfNodes)
-{
- // We have a list of nodes which we are candidates for being moved into a new
- // block. Determine if it's anything more than a blank line. Look for
- // editable content above and beyond one single BR.
- NS_ENSURE_TRUE(aArrayOfNodes.Length(), true);
-
- NS_ENSURE_TRUE(mHTMLEditor, false);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- int32_t brCount = 0;
-
- for (auto& node : aArrayOfNodes) {
- if (!htmlEditor->IsEditable(node)) {
- continue;
- }
- if (TextEditUtils::IsBreak(node)) {
- // First break doesn't count
- if (brCount) {
- return false;
- }
- brCount++;
- } else if (IsEmptyInline(node)) {
- // Empty inline, keep looking
- } else {
- return false;
- }
- }
- return true;
-}
-
-
-nsresult
-HTMLEditRules::PopListItem(nsIDOMNode* aListItem,
- bool* aOutOfList)
-{
- nsCOMPtr<Element> listItem = do_QueryInterface(aListItem);
- // check parms
- NS_ENSURE_TRUE(listItem && aOutOfList, NS_ERROR_NULL_POINTER);
-
- // init out params
- *aOutOfList = false;
-
- nsCOMPtr<nsINode> curParent = listItem->GetParentNode();
- int32_t offset = curParent ? curParent->IndexOf(listItem) : -1;
-
- if (!HTMLEditUtils::IsListItem(listItem)) {
- return NS_ERROR_FAILURE;
- }
-
- // if it's first or last list item, don't need to split the list
- // otherwise we do.
- nsCOMPtr<nsINode> curParPar = curParent->GetParentNode();
- int32_t parOffset = curParPar ? curParPar->IndexOf(curParent) : -1;
-
- bool bIsFirstListItem;
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->IsFirstEditableChild(aListItem, &bIsFirstListItem);
- NS_ENSURE_SUCCESS(rv, rv);
-
- bool bIsLastListItem;
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->IsLastEditableChild(aListItem, &bIsLastListItem);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!bIsFirstListItem && !bIsLastListItem) {
- // split the list
- nsCOMPtr<nsIDOMNode> newBlock;
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->SplitNode(GetAsDOMNode(curParent), offset,
- getter_AddRefs(newBlock));
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- if (!bIsFirstListItem) {
- parOffset++;
- }
-
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->MoveNode(listItem, curParPar, parOffset);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // unwrap list item contents if they are no longer in a list
- if (!HTMLEditUtils::IsList(curParPar) &&
- HTMLEditUtils::IsListItem(listItem)) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->RemoveBlockContainer(*listItem);
- NS_ENSURE_SUCCESS(rv, rv);
- *aOutOfList = true;
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::RemoveListStructure(Element& aList)
-{
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
- while (aList.GetFirstChild()) {
- OwningNonNull<nsIContent> child = *aList.GetFirstChild();
-
- if (HTMLEditUtils::IsListItem(child)) {
- bool isOutOfList;
- // Keep popping it out until it's not in a list anymore
- do {
- nsresult rv = PopListItem(child->AsDOMNode(), &isOutOfList);
- NS_ENSURE_SUCCESS(rv, rv);
- } while (!isOutOfList);
- } else if (HTMLEditUtils::IsList(child)) {
- nsresult rv = RemoveListStructure(*child->AsElement());
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // Delete any non-list items for now
- nsresult rv = htmlEditor->DeleteNode(child);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- // Delete the now-empty list
- nsresult rv = htmlEditor->RemoveBlockContainer(aList);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::ConfirmSelectionInBody()
-{
- // get the body
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(mHTMLEditor->GetRoot());
- NS_ENSURE_TRUE(rootElement, NS_ERROR_UNEXPECTED);
-
- // get the selection
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<Selection> selection = mHTMLEditor->GetSelection();
- NS_ENSURE_STATE(selection);
-
- // get the selection start location
- nsCOMPtr<nsIDOMNode> selNode, temp, parent;
- int32_t selOffset;
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->GetStartNodeAndOffset(selection,
- getter_AddRefs(selNode), &selOffset);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- temp = selNode;
-
- // check that selNode is inside body
- while (temp && !TextEditUtils::IsBody(temp)) {
- temp->GetParentNode(getter_AddRefs(parent));
- temp = parent;
- }
-
- // if we aren't in the body, force the issue
- if (!temp) {
-// uncomment this to see when we get bad selections
-// NS_NOTREACHED("selection not in body");
- selection->Collapse(rootElement, 0);
- }
-
- // get the selection end location
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->GetEndNodeAndOffset(selection,
- getter_AddRefs(selNode), &selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- temp = selNode;
-
- // check that selNode is inside body
- while (temp && !TextEditUtils::IsBody(temp)) {
- rv = temp->GetParentNode(getter_AddRefs(parent));
- temp = parent;
- }
-
- // if we aren't in the body, force the issue
- if (!temp) {
-// uncomment this to see when we get bad selections
-// NS_NOTREACHED("selection not in body");
- selection->Collapse(rootElement, 0);
- }
-
- // XXX This is the result of the last call of GetParentNode(), it doesn't
- // make sense...
- return rv;
-}
-
-nsresult
-HTMLEditRules::UpdateDocChangeRange(nsRange* aRange)
-{
- // first make sure aRange is in the document. It might not be if
- // portions of our editting action involved manipulating nodes
- // prior to placing them in the document (e.g., populating a list item
- // before placing it in its list)
- nsCOMPtr<nsIDOMNode> startNode;
- nsresult rv = aRange->GetStartContainer(getter_AddRefs(startNode));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_STATE(mHTMLEditor);
- if (!mHTMLEditor->IsDescendantOfRoot(startNode)) {
- // just return - we don't need to adjust mDocChangeRange in this case
- return NS_OK;
- }
-
- if (!mDocChangeRange) {
- // clone aRange.
- mDocChangeRange = aRange->CloneRange();
- } else {
- int16_t result;
-
- // compare starts of ranges
- rv = mDocChangeRange->CompareBoundaryPoints(nsIDOMRange::START_TO_START,
- aRange, &result);
- if (rv == NS_ERROR_NOT_INITIALIZED) {
- // This will happen is mDocChangeRange is non-null, but the range is
- // uninitialized. In this case we'll set the start to aRange start.
- // The same test won't be needed further down since after we've set
- // the start the range will be collapsed to that point.
- result = 1;
- rv = NS_OK;
- }
- NS_ENSURE_SUCCESS(rv, rv);
- // Positive result means mDocChangeRange start is after aRange start.
- if (result > 0) {
- uint32_t startOffset;
- rv = aRange->GetStartOffset(&startOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = mDocChangeRange->SetStart(startNode, startOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // compare ends of ranges
- rv = mDocChangeRange->CompareBoundaryPoints(nsIDOMRange::END_TO_END,
- aRange, &result);
- NS_ENSURE_SUCCESS(rv, rv);
- // Negative result means mDocChangeRange end is before aRange end.
- if (result < 0) {
- nsCOMPtr<nsIDOMNode> endNode;
- rv = aRange->GetEndContainer(getter_AddRefs(endNode));
- NS_ENSURE_SUCCESS(rv, rv);
- uint32_t endOffset;
- rv = aRange->GetEndOffset(&endOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = mDocChangeRange->SetEnd(endNode, endOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::InsertMozBRIfNeeded(nsINode& aNode)
-{
- if (!IsBlockNode(aNode)) {
- return NS_OK;
- }
-
- bool isEmpty;
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv = mHTMLEditor->IsEmptyNode(&aNode, &isEmpty);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!isEmpty) {
- return NS_OK;
- }
-
- return CreateMozBR(aNode.AsDOMNode(), 0);
-}
-
-NS_IMETHODIMP
-HTMLEditRules::WillCreateNode(const nsAString& aTag,
- nsIDOMNode* aParent,
- int32_t aPosition)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditRules::DidCreateNode(const nsAString& aTag,
- nsIDOMNode* aNode,
- nsIDOMNode* aParent,
- int32_t aPosition,
- nsresult aResult)
-{
- if (!mListenerEnabled) {
- return NS_OK;
- }
- // assumption that Join keeps the righthand node
- nsresult rv = mUtilRange->SelectNode(aNode);
- NS_ENSURE_SUCCESS(rv, rv);
- return UpdateDocChangeRange(mUtilRange);
-}
-
-NS_IMETHODIMP
-HTMLEditRules::WillInsertNode(nsIDOMNode* aNode,
- nsIDOMNode* aParent,
- int32_t aPosition)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditRules::DidInsertNode(nsIDOMNode* aNode,
- nsIDOMNode* aParent,
- int32_t aPosition,
- nsresult aResult)
-{
- if (!mListenerEnabled) {
- return NS_OK;
- }
- nsresult rv = mUtilRange->SelectNode(aNode);
- NS_ENSURE_SUCCESS(rv, rv);
- return UpdateDocChangeRange(mUtilRange);
-}
-
-NS_IMETHODIMP
-HTMLEditRules::WillDeleteNode(nsIDOMNode* aChild)
-{
- if (!mListenerEnabled) {
- return NS_OK;
- }
- nsresult rv = mUtilRange->SelectNode(aChild);
- NS_ENSURE_SUCCESS(rv, rv);
- return UpdateDocChangeRange(mUtilRange);
-}
-
-NS_IMETHODIMP
-HTMLEditRules::DidDeleteNode(nsIDOMNode* aChild,
- nsresult aResult)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditRules::WillSplitNode(nsIDOMNode* aExistingRightNode,
- int32_t aOffset)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditRules::DidSplitNode(nsIDOMNode* aExistingRightNode,
- int32_t aOffset,
- nsIDOMNode* aNewLeftNode,
- nsresult aResult)
-{
- if (!mListenerEnabled) {
- return NS_OK;
- }
- nsCOMPtr<nsINode> newLeftNode = do_QueryInterface(aNewLeftNode);
- nsCOMPtr<nsINode> existingRightNode = do_QueryInterface(aExistingRightNode);
- nsresult rv = mUtilRange->SetStartAndEnd(newLeftNode, 0,
- existingRightNode, 0);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- return UpdateDocChangeRange(mUtilRange);
-}
-
-NS_IMETHODIMP
-HTMLEditRules::WillJoinNodes(nsIDOMNode* aLeftNode,
- nsIDOMNode* aRightNode,
- nsIDOMNode* aParent)
-{
- if (!mListenerEnabled) {
- return NS_OK;
- }
- // remember split point
- return EditorBase::GetLengthOfDOMNode(aLeftNode, mJoinOffset);
-}
-
-NS_IMETHODIMP
-HTMLEditRules::DidJoinNodes(nsIDOMNode* aLeftNode,
- nsIDOMNode* aRightNode,
- nsIDOMNode* aParent,
- nsresult aResult)
-{
- if (!mListenerEnabled) {
- return NS_OK;
- }
- nsCOMPtr<nsINode> rightNode = do_QueryInterface(aRightNode);
- // assumption that Join keeps the righthand node
- nsresult rv = mUtilRange->CollapseTo(rightNode, mJoinOffset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- return UpdateDocChangeRange(mUtilRange);
-}
-
-NS_IMETHODIMP
-HTMLEditRules::WillInsertText(nsIDOMCharacterData* aTextNode,
- int32_t aOffset,
- const nsAString& aString)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditRules::DidInsertText(nsIDOMCharacterData* aTextNode,
- int32_t aOffset,
- const nsAString& aString,
- nsresult aResult)
-{
- if (!mListenerEnabled) {
- return NS_OK;
- }
- int32_t length = aString.Length();
- nsCOMPtr<nsINode> theNode = do_QueryInterface(aTextNode);
- nsresult rv = mUtilRange->SetStartAndEnd(theNode, aOffset,
- theNode, aOffset + length);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- return UpdateDocChangeRange(mUtilRange);
-}
-
-NS_IMETHODIMP
-HTMLEditRules::WillDeleteText(nsIDOMCharacterData* aTextNode,
- int32_t aOffset,
- int32_t aLength)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditRules::DidDeleteText(nsIDOMCharacterData* aTextNode,
- int32_t aOffset,
- int32_t aLength,
- nsresult aResult)
-{
- if (!mListenerEnabled) {
- return NS_OK;
- }
- nsCOMPtr<nsINode> theNode = do_QueryInterface(aTextNode);
- nsresult rv = mUtilRange->CollapseTo(theNode, aOffset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- return UpdateDocChangeRange(mUtilRange);
-}
-
-NS_IMETHODIMP
-HTMLEditRules::WillDeleteSelection(nsISelection* aSelection)
-{
- if (!mListenerEnabled) {
- return NS_OK;
- }
- if (NS_WARN_IF(!aSelection)) {
- return NS_ERROR_INVALID_ARG;
- }
- RefPtr<Selection> selection = aSelection->AsSelection();
- // get the (collapsed) selection location
- nsCOMPtr<nsINode> startNode;
- int32_t startOffset;
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->GetStartNodeAndOffset(selection,
- getter_AddRefs(startNode), &startOffset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- nsCOMPtr<nsINode> endNode;
- int32_t endOffset;
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->GetEndNodeAndOffset(selection,
- getter_AddRefs(endNode), &endOffset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- rv = mUtilRange->SetStartAndEnd(startNode, startOffset, endNode, endOffset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- return UpdateDocChangeRange(mUtilRange);
-}
-
-NS_IMETHODIMP
-HTMLEditRules::DidDeleteSelection(nsISelection *aSelection)
-{
- return NS_OK;
-}
-
-// Let's remove all alignment hints in the children of aNode; it can
-// be an ALIGN attribute (in case we just remove it) or a CENTER
-// element (here we have to remove the container and keep its
-// children). We break on tables and don't look at their children.
-nsresult
-HTMLEditRules::RemoveAlignment(nsIDOMNode* aNode,
- const nsAString& aAlignType,
- bool aChildrenOnly)
-{
- NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
-
- NS_ENSURE_STATE(mHTMLEditor);
- if (mHTMLEditor->IsTextNode(aNode) || HTMLEditUtils::IsTable(aNode)) {
- return NS_OK;
- }
-
- nsCOMPtr<nsIDOMNode> child = aNode,tmp;
- if (aChildrenOnly) {
- aNode->GetFirstChild(getter_AddRefs(child));
- }
- NS_ENSURE_STATE(mHTMLEditor);
- bool useCSS = mHTMLEditor->IsCSSEnabled();
-
- while (child) {
- if (aChildrenOnly) {
- // get the next sibling right now because we could have to remove child
- child->GetNextSibling(getter_AddRefs(tmp));
- } else {
- tmp = nullptr;
- }
- bool isBlock;
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv = mHTMLEditor->NodeIsBlockStatic(child, &isBlock);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (EditorBase::NodeIsType(child, nsGkAtoms::center)) {
- // the current node is a CENTER element
- // first remove children's alignment
- rv = RemoveAlignment(child, aAlignType, true);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // we may have to insert BRs in first and last position of element's children
- // if the nodes before/after are not blocks and not BRs
- rv = MakeSureElemStartsOrEndsOnCR(child);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // now remove the CENTER container
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<Element> childAsElement = do_QueryInterface(child);
- NS_ENSURE_STATE(childAsElement);
- rv = mHTMLEditor->RemoveContainer(childAsElement);
- NS_ENSURE_SUCCESS(rv, rv);
- } else if (isBlock || HTMLEditUtils::IsHR(child)) {
- // the current node is a block element
- nsCOMPtr<Element> curElem = do_QueryInterface(child);
- if (HTMLEditUtils::SupportsAlignAttr(child)) {
- // remove the ALIGN attribute if this element can have it
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->RemoveAttribute(curElem, nsGkAtoms::align);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- if (useCSS) {
- if (HTMLEditUtils::IsTable(child) || HTMLEditUtils::IsHR(child)) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->SetAttributeOrEquivalent(curElem,
- nsGkAtoms::align,
- aAlignType, false);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- nsAutoString dummyCssValue;
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->mCSSEditUtils->RemoveCSSInlineStyle(
- child,
- nsGkAtoms::textAlign,
- dummyCssValue);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- }
- if (!HTMLEditUtils::IsTable(child)) {
- // unless this is a table, look at children
- rv = RemoveAlignment(child, aAlignType, true);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- child = tmp;
- }
- return NS_OK;
-}
-
-// Let's insert a BR as first (resp. last) child of aNode if its
-// first (resp. last) child is not a block nor a BR, and if the
-// previous (resp. next) sibling is not a block nor a BR
-nsresult
-HTMLEditRules::MakeSureElemStartsOrEndsOnCR(nsIDOMNode* aNode,
- bool aStarts)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsIDOMNode> child;
- if (aStarts) {
- NS_ENSURE_STATE(mHTMLEditor);
- child = GetAsDOMNode(mHTMLEditor->GetFirstEditableChild(*node));
- } else {
- NS_ENSURE_STATE(mHTMLEditor);
- child = GetAsDOMNode(mHTMLEditor->GetLastEditableChild(*node));
- }
- NS_ENSURE_TRUE(child, NS_OK);
- bool isChildBlock;
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv = mHTMLEditor->NodeIsBlockStatic(child, &isChildBlock);
- NS_ENSURE_SUCCESS(rv, rv);
- bool foundCR = false;
- if (isChildBlock || TextEditUtils::IsBreak(child)) {
- foundCR = true;
- } else {
- nsCOMPtr<nsIDOMNode> sibling;
- if (aStarts) {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->GetPriorHTMLSibling(aNode, address_of(sibling));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->GetNextHTMLSibling(aNode, address_of(sibling));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- if (sibling) {
- bool isBlock;
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->NodeIsBlockStatic(sibling, &isBlock);
- NS_ENSURE_SUCCESS(rv, rv);
- if (isBlock || TextEditUtils::IsBreak(sibling)) {
- foundCR = true;
- }
- } else {
- foundCR = true;
- }
- }
- if (!foundCR) {
- int32_t offset = 0;
- if (!aStarts) {
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- NS_ENSURE_STATE(node);
- offset = node->GetChildCount();
- }
- nsCOMPtr<nsIDOMNode> brNode;
- NS_ENSURE_STATE(mHTMLEditor);
- rv = mHTMLEditor->CreateBR(aNode, offset, address_of(brNode));
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::MakeSureElemStartsOrEndsOnCR(nsIDOMNode* aNode)
-{
- nsresult rv = MakeSureElemStartsOrEndsOnCR(aNode, false);
- NS_ENSURE_SUCCESS(rv, rv);
- return MakeSureElemStartsOrEndsOnCR(aNode, true);
-}
-
-nsresult
-HTMLEditRules::AlignBlock(Element& aElement,
- const nsAString& aAlignType,
- ContentsOnly aContentsOnly)
-{
- if (!IsBlockNode(aElement) && !aElement.IsHTMLElement(nsGkAtoms::hr)) {
- // We deal only with blocks; early way out
- return NS_OK;
- }
-
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- nsresult rv = RemoveAlignment(aElement.AsDOMNode(), aAlignType,
- aContentsOnly == ContentsOnly::yes);
- NS_ENSURE_SUCCESS(rv, rv);
- if (htmlEditor->IsCSSEnabled()) {
- // Let's use CSS alignment; we use margin-left and margin-right for tables
- // and text-align for other block-level elements
- rv = htmlEditor->SetAttributeOrEquivalent(
- &aElement, nsGkAtoms::align, aAlignType, false);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // HTML case; this code is supposed to be called ONLY if the element
- // supports the align attribute but we'll never know...
- if (HTMLEditUtils::SupportsAlignAttr(aElement.AsDOMNode())) {
- rv = htmlEditor->SetAttribute(&aElement, nsGkAtoms::align, aAlignType);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::ChangeIndentation(Element& aElement,
- Change aChange)
-{
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- nsIAtom& marginProperty =
- MarginPropertyAtomForIndent(*htmlEditor->mCSSEditUtils, aElement);
- nsAutoString value;
- htmlEditor->mCSSEditUtils->GetSpecifiedProperty(aElement, marginProperty,
- value);
- float f;
- nsCOMPtr<nsIAtom> unit;
- htmlEditor->mCSSEditUtils->ParseLength(value, &f, getter_AddRefs(unit));
- if (!f) {
- nsAutoString defaultLengthUnit;
- htmlEditor->mCSSEditUtils->GetDefaultLengthUnit(defaultLengthUnit);
- unit = NS_Atomize(defaultLengthUnit);
- }
- int8_t multiplier = aChange == Change::plus ? +1 : -1;
- if (nsGkAtoms::in == unit) {
- f += NS_EDITOR_INDENT_INCREMENT_IN * multiplier;
- } else if (nsGkAtoms::cm == unit) {
- f += NS_EDITOR_INDENT_INCREMENT_CM * multiplier;
- } else if (nsGkAtoms::mm == unit) {
- f += NS_EDITOR_INDENT_INCREMENT_MM * multiplier;
- } else if (nsGkAtoms::pt == unit) {
- f += NS_EDITOR_INDENT_INCREMENT_PT * multiplier;
- } else if (nsGkAtoms::pc == unit) {
- f += NS_EDITOR_INDENT_INCREMENT_PC * multiplier;
- } else if (nsGkAtoms::em == unit) {
- f += NS_EDITOR_INDENT_INCREMENT_EM * multiplier;
- } else if (nsGkAtoms::ex == unit) {
- f += NS_EDITOR_INDENT_INCREMENT_EX * multiplier;
- } else if (nsGkAtoms::px == unit) {
- f += NS_EDITOR_INDENT_INCREMENT_PX * multiplier;
- } else if (nsGkAtoms::percentage == unit) {
- f += NS_EDITOR_INDENT_INCREMENT_PERCENT * multiplier;
- }
-
- if (0 < f) {
- nsAutoString newValue;
- newValue.AppendFloat(f);
- newValue.Append(nsDependentAtomString(unit));
- htmlEditor->mCSSEditUtils->SetCSSProperty(aElement, marginProperty,
- newValue);
- return NS_OK;
- }
-
- htmlEditor->mCSSEditUtils->RemoveCSSProperty(aElement, marginProperty,
- value);
-
- // Remove unnecessary divs
- if (!aElement.IsHTMLElement(nsGkAtoms::div) ||
- &aElement == htmlEditor->GetActiveEditingHost() ||
- !htmlEditor->IsDescendantOfEditorRoot(&aElement) ||
- HTMLEditor::HasAttributes(&aElement)) {
- return NS_OK;
- }
-
- nsresult rv = htmlEditor->RemoveContainer(&aElement);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::WillAbsolutePosition(Selection& aSelection,
- bool* aCancel,
- bool* aHandled)
-{
- MOZ_ASSERT(aCancel && aHandled);
- NS_ENSURE_STATE(mHTMLEditor);
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
- WillInsert(aSelection, aCancel);
-
- // We want to ignore result of WillInsert()
- *aCancel = false;
- *aHandled = true;
-
- nsCOMPtr<Element> focusElement = htmlEditor->GetSelectionContainer();
- if (focusElement && HTMLEditUtils::IsImage(focusElement)) {
- mNewBlock = focusElement;
- return NS_OK;
- }
-
- nsresult rv = NormalizeSelection(&aSelection);
- NS_ENSURE_SUCCESS(rv, rv);
- AutoSelectionRestorer selectionRestorer(&aSelection, htmlEditor);
-
- // Convert the selection ranges into "promoted" selection ranges: this
- // basically just expands the range to include the immediate block parent,
- // and then further expands to include any ancestors whose children are all
- // in the range.
-
- nsTArray<RefPtr<nsRange>> arrayOfRanges;
- GetPromotedRanges(aSelection, arrayOfRanges,
- EditAction::setAbsolutePosition);
-
- // Use these ranges to contruct a list of nodes to act on.
- nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
- rv = GetNodesForOperation(arrayOfRanges, arrayOfNodes,
- EditAction::setAbsolutePosition);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // If nothing visible in list, make an empty block
- if (ListIsEmptyLine(arrayOfNodes)) {
- // Get selection location
- NS_ENSURE_STATE(aSelection.GetRangeAt(0) &&
- aSelection.GetRangeAt(0)->GetStartParent());
- OwningNonNull<nsINode> parent =
- *aSelection.GetRangeAt(0)->GetStartParent();
- int32_t offset = aSelection.GetRangeAt(0)->StartOffset();
-
- // Make sure we can put a block here
- rv = SplitAsNeeded(*nsGkAtoms::div, parent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<Element> positionedDiv =
- htmlEditor->CreateNode(nsGkAtoms::div, parent, offset);
- NS_ENSURE_STATE(positionedDiv);
- // Remember our new block for postprocessing
- mNewBlock = positionedDiv;
- // Delete anything that was in the list of nodes
- while (!arrayOfNodes.IsEmpty()) {
- OwningNonNull<nsINode> curNode = arrayOfNodes[0];
- rv = htmlEditor->DeleteNode(curNode);
- NS_ENSURE_SUCCESS(rv, rv);
- arrayOfNodes.RemoveElementAt(0);
- }
- // Put selection in new block
- *aHandled = true;
- rv = aSelection.Collapse(positionedDiv, 0);
- // Don't restore the selection
- selectionRestorer.Abort();
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
- }
-
- // Okay, now go through all the nodes and put them in a blockquote, or
- // whatever is appropriate. Woohoo!
- nsCOMPtr<Element> curList, curPositionedDiv, indentedLI;
- for (uint32_t i = 0; i < arrayOfNodes.Length(); i++) {
- // Here's where we actually figure out what to do
- NS_ENSURE_STATE(arrayOfNodes[i]->IsContent());
- OwningNonNull<nsIContent> curNode = *arrayOfNodes[i]->AsContent();
-
- // Ignore all non-editable nodes. Leave them be.
- if (!htmlEditor->IsEditable(curNode)) {
- continue;
- }
-
- nsCOMPtr<nsIContent> sibling;
-
- nsCOMPtr<nsINode> curParent = curNode->GetParentNode();
- int32_t offset = curParent ? curParent->IndexOf(curNode) : -1;
-
- // Some logic for putting list items into nested lists...
- if (HTMLEditUtils::IsList(curParent)) {
- // Check to see if curList is still appropriate. Which it is if curNode
- // is still right after it in the same list.
- if (curList) {
- sibling = htmlEditor->GetPriorHTMLSibling(curNode);
- }
-
- if (!curList || (sibling && sibling != curList)) {
- // Create a new nested list of correct type
- rv =
- SplitAsNeeded(*curParent->NodeInfo()->NameAtom(), curParent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!curPositionedDiv) {
- nsCOMPtr<nsINode> curParentParent = curParent->GetParentNode();
- int32_t parentOffset = curParentParent
- ? curParentParent->IndexOf(curParent) : -1;
- curPositionedDiv = htmlEditor->CreateNode(nsGkAtoms::div, curParentParent,
- parentOffset);
- mNewBlock = curPositionedDiv;
- }
- curList = htmlEditor->CreateNode(curParent->NodeInfo()->NameAtom(),
- curPositionedDiv, -1);
- NS_ENSURE_STATE(curList);
- // curList is now the correct thing to put curNode in. Remember our
- // new block for postprocessing.
- }
- // Tuck the node into the end of the active list
- rv = htmlEditor->MoveNode(curNode, curList, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // Not a list item, use blockquote? If we are inside a list item, we
- // don't want to blockquote, we want to sublist the list item. We may
- // have several nodes listed in the array of nodes to act on, that are in
- // the same list item. Since we only want to indent that li once, we
- // must keep track of the most recent indented list item, and not indent
- // it if we find another node to act on that is still inside the same li.
- nsCOMPtr<Element> listItem = IsInListItem(curNode);
- if (listItem) {
- if (indentedLI == listItem) {
- // Already indented this list item
- continue;
- }
- curParent = listItem->GetParentNode();
- offset = curParent ? curParent->IndexOf(listItem) : -1;
- // Check to see if curList is still appropriate. Which it is if
- // curNode is still right after it in the same list.
- if (curList) {
- sibling = htmlEditor->GetPriorHTMLSibling(curNode);
- }
-
- if (!curList || (sibling && sibling != curList)) {
- // Create a new nested list of correct type
- rv = SplitAsNeeded(*curParent->NodeInfo()->NameAtom(), curParent,
- offset);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!curPositionedDiv) {
- nsCOMPtr<nsINode> curParentParent = curParent->GetParentNode();
- int32_t parentOffset = curParentParent ?
- curParentParent->IndexOf(curParent) : -1;
- curPositionedDiv = htmlEditor->CreateNode(nsGkAtoms::div,
- curParentParent,
- parentOffset);
- mNewBlock = curPositionedDiv;
- }
- curList = htmlEditor->CreateNode(curParent->NodeInfo()->NameAtom(),
- curPositionedDiv, -1);
- NS_ENSURE_STATE(curList);
- }
- rv = htmlEditor->MoveNode(listItem, curList, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- // Remember we indented this li
- indentedLI = listItem;
- } else {
- // Need to make a div to put things in if we haven't already
-
- if (!curPositionedDiv) {
- if (curNode->IsHTMLElement(nsGkAtoms::div)) {
- curPositionedDiv = curNode->AsElement();
- mNewBlock = curPositionedDiv;
- curList = nullptr;
- continue;
- }
- rv = SplitAsNeeded(*nsGkAtoms::div, curParent, offset);
- NS_ENSURE_SUCCESS(rv, rv);
- curPositionedDiv = htmlEditor->CreateNode(nsGkAtoms::div, curParent,
- offset);
- NS_ENSURE_STATE(curPositionedDiv);
- // Remember our new block for postprocessing
- mNewBlock = curPositionedDiv;
- // curPositionedDiv is now the correct thing to put curNode in
- }
-
- // Tuck the node into the end of the active blockquote
- rv = htmlEditor->MoveNode(curNode, curPositionedDiv, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- // Forget curList, if any
- curList = nullptr;
- }
- }
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditRules::DidAbsolutePosition()
-{
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<nsIHTMLAbsPosEditor> absPosHTMLEditor = mHTMLEditor;
- nsCOMPtr<nsIDOMElement> elt =
- static_cast<nsIDOMElement*>(GetAsDOMNode(mNewBlock));
- return absPosHTMLEditor->AbsolutelyPositionElement(elt, true);
-}
-
-nsresult
-HTMLEditRules::WillRemoveAbsolutePosition(Selection* aSelection,
- bool* aCancel,
- bool* aHandled) {
- if (!aSelection || !aCancel || !aHandled) {
- return NS_ERROR_NULL_POINTER;
- }
- WillInsert(*aSelection, aCancel);
-
- // initialize out param
- // we want to ignore aCancel from WillInsert()
- *aCancel = false;
- *aHandled = true;
-
- nsCOMPtr<nsIDOMElement> elt;
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(elt));
- NS_ENSURE_SUCCESS(rv, rv);
-
- NS_ENSURE_STATE(mHTMLEditor);
- AutoSelectionRestorer selectionRestorer(aSelection, mHTMLEditor);
-
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<nsIHTMLAbsPosEditor> absPosHTMLEditor = mHTMLEditor;
- return absPosHTMLEditor->AbsolutelyPositionElement(elt, false);
-}
-
-nsresult
-HTMLEditRules::WillRelativeChangeZIndex(Selection* aSelection,
- int32_t aChange,
- bool* aCancel,
- bool* aHandled)
-{
- if (!aSelection || !aCancel || !aHandled) {
- return NS_ERROR_NULL_POINTER;
- }
- WillInsert(*aSelection, aCancel);
-
- // initialize out param
- // we want to ignore aCancel from WillInsert()
- *aCancel = false;
- *aHandled = true;
-
- nsCOMPtr<nsIDOMElement> elt;
- NS_ENSURE_STATE(mHTMLEditor);
- nsresult rv =
- mHTMLEditor->GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(elt));
- NS_ENSURE_SUCCESS(rv, rv);
-
- NS_ENSURE_STATE(mHTMLEditor);
- AutoSelectionRestorer selectionRestorer(aSelection, mHTMLEditor);
-
- NS_ENSURE_STATE(mHTMLEditor);
- nsCOMPtr<nsIHTMLAbsPosEditor> absPosHTMLEditor = mHTMLEditor;
- int32_t zIndex;
- return absPosHTMLEditor->RelativeChangeElementZIndex(elt, aChange, &zIndex);
-}
-
-NS_IMETHODIMP
-HTMLEditRules::DocumentModified()
-{
- nsContentUtils::AddScriptRunner(
- NewRunnableMethod(this, &HTMLEditRules::DocumentModifiedWorker));
- return NS_OK;
-}
-
-void
-HTMLEditRules::DocumentModifiedWorker()
-{
- if (!mHTMLEditor) {
- return;
- }
-
- // DeleteNode below may cause a flush, which could destroy the editor
- nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
-
- RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
- RefPtr<Selection> selection = htmlEditor->GetSelection();
- if (!selection) {
- return;
- }
-
- // Delete our bogus node, if we have one, since the document might not be
- // empty any more.
- if (mBogusNode) {
- mTextEditor->DeleteNode(mBogusNode);
- mBogusNode = nullptr;
- }
-
- // Try to recreate the bogus node if needed.
- CreateBogusNodeIfNeeded(selection);
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/HTMLEditRules.h b/editor/libeditor/HTMLEditRules.h
deleted file mode 100644
index 5525fdf24..000000000
--- a/editor/libeditor/HTMLEditRules.h
+++ /dev/null
@@ -1,427 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef HTMLEditRules_h
-#define HTMLEditRules_h
-
-#include "TypeInState.h"
-#include "mozilla/SelectionState.h"
-#include "mozilla/TextEditRules.h"
-#include "nsCOMPtr.h"
-#include "nsIEditActionListener.h"
-#include "nsIEditor.h"
-#include "nsIHTMLEditor.h"
-#include "nsISupportsImpl.h"
-#include "nsTArray.h"
-#include "nscore.h"
-
-class nsIAtom;
-class nsIDOMCharacterData;
-class nsIDOMDocument;
-class nsIDOMElement;
-class nsIDOMNode;
-class nsIEditor;
-class nsINode;
-class nsRange;
-
-namespace mozilla {
-
-class EditActionResult;
-class HTMLEditor;
-class RulesInfo;
-class TextEditor;
-struct EditorDOMPoint;
-namespace dom {
-class Element;
-class Selection;
-} // namespace dom
-
-struct StyleCache final : public PropItem
-{
- bool mPresent;
-
- StyleCache()
- : PropItem()
- , mPresent(false)
- {
- MOZ_COUNT_CTOR(StyleCache);
- }
-
- StyleCache(nsIAtom* aTag,
- const nsAString& aAttr,
- const nsAString& aValue)
- : PropItem(aTag, aAttr, aValue)
- , mPresent(false)
- {
- MOZ_COUNT_CTOR(StyleCache);
- }
-
- ~StyleCache()
- {
- MOZ_COUNT_DTOR(StyleCache);
- }
-};
-
-#define SIZE_STYLE_TABLE 19
-
-class HTMLEditRules : public TextEditRules
- , public nsIEditActionListener
-{
-public:
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLEditRules, TextEditRules)
-
- HTMLEditRules();
-
- // nsIEditRules methods
- NS_IMETHOD Init(TextEditor* aTextEditor) override;
- NS_IMETHOD DetachEditor() override;
- NS_IMETHOD BeforeEdit(EditAction action,
- nsIEditor::EDirection aDirection) override;
- NS_IMETHOD AfterEdit(EditAction action,
- nsIEditor::EDirection aDirection) override;
- NS_IMETHOD WillDoAction(Selection* aSelection, RulesInfo* aInfo,
- bool* aCancel, bool* aHandled) override;
- NS_IMETHOD DidDoAction(Selection* aSelection, RulesInfo* aInfo,
- nsresult aResult) override;
- NS_IMETHOD DocumentModified() override;
-
- nsresult GetListState(bool* aMixed, bool* aOL, bool* aUL, bool* aDL);
- nsresult GetListItemState(bool* aMixed, bool* aLI, bool* aDT, bool* aDD);
- nsresult GetIndentState(bool* aCanIndent, bool* aCanOutdent);
- nsresult GetAlignment(bool* aMixed, nsIHTMLEditor::EAlignment* aAlign);
- nsresult GetParagraphState(bool* aMixed, nsAString& outFormat);
- nsresult MakeSureElemStartsOrEndsOnCR(nsIDOMNode* aNode);
-
- // nsIEditActionListener methods
-
- NS_IMETHOD WillCreateNode(const nsAString& aTag, nsIDOMNode* aParent,
- int32_t aPosition) override;
- NS_IMETHOD DidCreateNode(const nsAString& aTag, nsIDOMNode* aNode,
- nsIDOMNode* aParent, int32_t aPosition,
- nsresult aResult) override;
- NS_IMETHOD WillInsertNode(nsIDOMNode* aNode, nsIDOMNode* aParent,
- int32_t aPosition) override;
- NS_IMETHOD DidInsertNode(nsIDOMNode* aNode, nsIDOMNode* aParent,
- int32_t aPosition, nsresult aResult) override;
- NS_IMETHOD WillDeleteNode(nsIDOMNode* aChild) override;
- NS_IMETHOD DidDeleteNode(nsIDOMNode* aChild, nsresult aResult) override;
- NS_IMETHOD WillSplitNode(nsIDOMNode* aExistingRightNode,
- int32_t aOffset) override;
- NS_IMETHOD DidSplitNode(nsIDOMNode* aExistingRightNode, int32_t aOffset,
- nsIDOMNode* aNewLeftNode, nsresult aResult) override;
- NS_IMETHOD WillJoinNodes(nsIDOMNode* aLeftNode, nsIDOMNode* aRightNode,
- nsIDOMNode* aParent) override;
- NS_IMETHOD DidJoinNodes(nsIDOMNode* aLeftNode, nsIDOMNode* aRightNode,
- nsIDOMNode* aParent, nsresult aResult) override;
- NS_IMETHOD WillInsertText(nsIDOMCharacterData* aTextNode, int32_t aOffset,
- const nsAString &aString) override;
- NS_IMETHOD DidInsertText(nsIDOMCharacterData* aTextNode, int32_t aOffset,
- const nsAString &aString, nsresult aResult) override;
- NS_IMETHOD WillDeleteText(nsIDOMCharacterData* aTextNode, int32_t aOffset,
- int32_t aLength) override;
- NS_IMETHOD DidDeleteText(nsIDOMCharacterData* aTextNode, int32_t aOffset,
- int32_t aLength, nsresult aResult) override;
- NS_IMETHOD WillDeleteSelection(nsISelection* aSelection) override;
- NS_IMETHOD DidDeleteSelection(nsISelection* aSelection) override;
- void DeleteNodeIfCollapsedText(nsINode& aNode);
-
-protected:
- virtual ~HTMLEditRules();
-
- enum RulesEndpoint
- {
- kStart,
- kEnd
- };
-
- void InitFields();
-
- void WillInsert(Selection& aSelection, bool* aCancel);
- nsresult WillInsertText(EditAction aAction,
- Selection* aSelection,
- bool* aCancel,
- bool* aHandled,
- const nsAString* inString,
- nsAString* outString,
- int32_t aMaxLength);
- nsresult WillLoadHTML(Selection* aSelection, bool* aCancel);
- nsresult WillInsertBreak(Selection& aSelection, bool* aCancel,
- bool* aHandled);
- nsresult StandardBreakImpl(nsINode& aNode, int32_t aOffset,
- Selection& aSelection);
- nsresult DidInsertBreak(Selection* aSelection, nsresult aResult);
- nsresult SplitMailCites(Selection* aSelection, bool* aHandled);
- nsresult WillDeleteSelection(Selection* aSelection,
- nsIEditor::EDirection aAction,
- nsIEditor::EStripWrappers aStripWrappers,
- bool* aCancel, bool* aHandled);
- nsresult DidDeleteSelection(Selection* aSelection,
- nsIEditor::EDirection aDir,
- nsresult aResult);
- nsresult InsertBRIfNeeded(Selection* aSelection);
- mozilla::EditorDOMPoint GetGoodSelPointForNode(nsINode& aNode,
- nsIEditor::EDirection aAction);
-
- /**
- * TryToJoinBlocks() tries to join two block elements. The right element is
- * always joined to the left element. If the elements are the same type and
- * not nested within each other, JoinNodesSmart() is called (example, joining
- * two list items together into one). If the elements are not the same type,
- * or one is a descendant of the other, we instead destroy the right block
- * placing its children into leftblock. DTD containment rules are followed
- * throughout.
- *
- * @return Sets canceled to true if the operation should do
- * nothing anymore even if this doesn't join the blocks.
- * Sets handled to true if this actually handles the
- * request. Note that this may set it to true even if this
- * does not join the block. E.g., if the blocks shouldn't
- * be joined or it's impossible to join them but it's not
- * unexpected case, this returns true with this.
- */
- EditActionResult TryToJoinBlocks(nsIContent& aLeftNode,
- nsIContent& aRightNode);
-
- /**
- * MoveBlock() moves the content from aRightBlock starting from aRightOffset
- * into aLeftBlock at aLeftOffset. Note that the "block" can be inline nodes
- * between <br>s, or between blocks, etc. DTD containment rules are followed
- * throughout.
- *
- * @return Sets handled to true if this actually joins the nodes.
- * canceled is always false.
- */
- EditActionResult MoveBlock(Element& aLeftBlock, Element& aRightBlock,
- int32_t aLeftOffset, int32_t aRightOffset);
-
- /**
- * MoveNodeSmart() moves aNode to (aDestElement, aInOutDestOffset).
- * DTD containment rules are followed throughout.
- *
- * @param aOffset returns the point after inserted content.
- * @return Sets true to handled if this actually moves
- * the nodes.
- * canceled is always false.
- */
- EditActionResult MoveNodeSmart(nsIContent& aNode, Element& aDestElement,
- int32_t* aInOutDestOffset);
-
- /**
- * MoveContents() moves the contents of aElement to (aDestElement,
- * aInOutDestOffset). DTD containment rules are followed throughout.
- *
- * @param aInOutDestOffset updated to point after inserted content.
- * @return Sets true to handled if this actually moves
- * the nodes.
- * canceled is always false.
- */
- EditActionResult MoveContents(Element& aElement, Element& aDestElement,
- int32_t* aInOutDestOffset);
-
- nsresult DeleteNonTableElements(nsINode* aNode);
- nsresult WillMakeList(Selection* aSelection,
- const nsAString* aListType,
- bool aEntireList,
- const nsAString* aBulletType,
- bool* aCancel, bool* aHandled,
- const nsAString* aItemType = nullptr);
- nsresult WillRemoveList(Selection* aSelection, bool aOrdered, bool* aCancel,
- bool* aHandled);
- nsresult WillIndent(Selection* aSelection, bool* aCancel, bool* aHandled);
- nsresult WillCSSIndent(Selection* aSelection, bool* aCancel, bool* aHandled);
- nsresult WillHTMLIndent(Selection* aSelection, bool* aCancel,
- bool* aHandled);
- nsresult WillOutdent(Selection& aSelection, bool* aCancel, bool* aHandled);
- nsresult WillAlign(Selection& aSelection, const nsAString& aAlignType,
- bool* aCancel, bool* aHandled);
- nsresult WillAbsolutePosition(Selection& aSelection, bool* aCancel,
- bool* aHandled);
- nsresult WillRemoveAbsolutePosition(Selection* aSelection, bool* aCancel,
- bool* aHandled);
- nsresult WillRelativeChangeZIndex(Selection* aSelection, int32_t aChange,
- bool* aCancel, bool* aHandled);
- nsresult WillMakeDefListItem(Selection* aSelection,
- const nsAString* aBlockType, bool aEntireList,
- bool* aCancel, bool* aHandled);
- nsresult WillMakeBasicBlock(Selection& aSelection,
- const nsAString& aBlockType,
- bool* aCancel, bool* aHandled);
- nsresult DidMakeBasicBlock(Selection* aSelection, RulesInfo* aInfo,
- nsresult aResult);
- nsresult DidAbsolutePosition();
- nsresult AlignInnerBlocks(nsINode& aNode, const nsAString* alignType);
- nsresult AlignBlockContents(nsIDOMNode* aNode, const nsAString* alignType);
- nsresult AppendInnerFormatNodes(nsTArray<OwningNonNull<nsINode>>& aArray,
- nsINode* aNode);
- nsresult GetFormatString(nsIDOMNode* aNode, nsAString &outFormat);
- enum class Lists { no, yes };
- enum class Tables { no, yes };
- void GetInnerContent(nsINode& aNode,
- nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
- int32_t* aIndex, Lists aLists = Lists::yes,
- Tables aTables = Tables::yes);
- Element* IsInListItem(nsINode* aNode);
- nsresult ReturnInHeader(Selection& aSelection, Element& aHeader,
- nsINode& aNode, int32_t aOffset);
- nsresult ReturnInParagraph(Selection* aSelection, nsIDOMNode* aHeader,
- nsIDOMNode* aTextNode, int32_t aOffset,
- bool* aCancel, bool* aHandled);
- nsresult SplitParagraph(nsIDOMNode* aPara,
- nsIContent* aBRNode,
- Selection* aSelection,
- nsCOMPtr<nsIDOMNode>* aSelNode,
- int32_t* aOffset);
- nsresult ReturnInListItem(Selection& aSelection, Element& aHeader,
- nsINode& aNode, int32_t aOffset);
- nsresult AfterEditInner(EditAction action,
- nsIEditor::EDirection aDirection);
- nsresult RemovePartOfBlock(Element& aBlock, nsIContent& aStartChild,
- nsIContent& aEndChild);
- void SplitBlock(Element& aBlock,
- nsIContent& aStartChild,
- nsIContent& aEndChild,
- nsIContent** aOutLeftNode = nullptr,
- nsIContent** aOutRightNode = nullptr,
- nsIContent** aOutMiddleNode = nullptr);
- nsresult OutdentPartOfBlock(Element& aBlock,
- nsIContent& aStartChild,
- nsIContent& aEndChild,
- bool aIsBlockIndentedWithCSS,
- nsIContent** aOutLeftNode,
- nsIContent** aOutRightNode);
-
- nsresult ConvertListType(Element* aList, Element** aOutList,
- nsIAtom* aListType, nsIAtom* aItemType);
-
- nsresult CreateStyleForInsertText(Selection& aSelection, nsIDocument& aDoc);
- enum class MozBRCounts { yes, no };
- nsresult IsEmptyBlock(Element& aNode, bool* aOutIsEmptyBlock,
- MozBRCounts aMozBRCounts = MozBRCounts::yes);
- nsresult CheckForEmptyBlock(nsINode* aStartNode, Element* aBodyNode,
- Selection* aSelection,
- nsIEditor::EDirection aAction, bool* aHandled);
- enum class BRLocation { beforeBlock, blockEnd };
- Element* CheckForInvisibleBR(Element& aBlock, BRLocation aWhere,
- int32_t aOffset = 0);
- nsresult ExpandSelectionForDeletion(Selection& aSelection);
- bool IsFirstNode(nsIDOMNode* aNode);
- bool IsLastNode(nsIDOMNode* aNode);
- nsresult NormalizeSelection(Selection* aSelection);
- void GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode* aNode,
- int32_t aOffset, EditAction actionID,
- nsCOMPtr<nsIDOMNode>* outNode, int32_t* outOffset);
- void GetPromotedRanges(Selection& aSelection,
- nsTArray<RefPtr<nsRange>>& outArrayOfRanges,
- EditAction inOperationType);
- void PromoteRange(nsRange& aRange, EditAction inOperationType);
- enum class TouchContent { no, yes };
- nsresult GetNodesForOperation(
- nsTArray<RefPtr<nsRange>>& aArrayOfRanges,
- nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
- EditAction aOperationType,
- TouchContent aTouchContent = TouchContent::yes);
- void GetChildNodesForOperation(
- nsINode& aNode,
- nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes);
- nsresult GetNodesFromPoint(EditorDOMPoint aPoint,
- EditAction aOperation,
- nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
- TouchContent aTouchContent);
- nsresult GetNodesFromSelection(
- Selection& aSelection,
- EditAction aOperation,
- nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
- TouchContent aTouchContent = TouchContent::yes);
- enum class EntireList { no, yes };
- nsresult GetListActionNodes(
- nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
- EntireList aEntireList,
- TouchContent aTouchContent = TouchContent::yes);
- void GetDefinitionListItemTypes(Element* aElement, bool* aDT, bool* aDD);
- nsresult GetParagraphFormatNodes(
- nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
- TouchContent aTouchContent = TouchContent::yes);
- void LookInsideDivBQandList(nsTArray<OwningNonNull<nsINode>>& aNodeArray);
- nsresult BustUpInlinesAtRangeEndpoints(RangeItem& inRange);
- nsresult BustUpInlinesAtBRs(
- nsIContent& aNode,
- nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes);
- nsIContent* GetHighestInlineParent(nsINode& aNode);
- void MakeTransitionList(nsTArray<OwningNonNull<nsINode>>& aNodeArray,
- nsTArray<bool>& aTransitionArray);
- nsresult RemoveBlockStyle(nsTArray<OwningNonNull<nsINode>>& aNodeArray);
- nsresult ApplyBlockStyle(nsTArray<OwningNonNull<nsINode>>& aNodeArray,
- nsIAtom& aBlockTag);
- nsresult MakeBlockquote(nsTArray<OwningNonNull<nsINode>>& aNodeArray);
- nsresult SplitAsNeeded(nsIAtom& aTag, OwningNonNull<nsINode>& inOutParent,
- int32_t& inOutOffset);
- nsresult SplitAsNeeded(nsIAtom& aTag, nsCOMPtr<nsINode>& inOutParent,
- int32_t& inOutOffset);
- nsresult AddTerminatingBR(nsIDOMNode *aBlock);
- EditorDOMPoint JoinNodesSmart(nsIContent& aNodeLeft,
- nsIContent& aNodeRight);
- Element* GetTopEnclosingMailCite(nsINode& aNode);
- nsresult PopListItem(nsIDOMNode* aListItem, bool* aOutOfList);
- nsresult RemoveListStructure(Element& aList);
- nsresult CacheInlineStyles(nsIDOMNode* aNode);
- nsresult ReapplyCachedStyles();
- void ClearCachedStyles();
- void AdjustSpecialBreaks();
- nsresult AdjustWhitespace(Selection* aSelection);
- nsresult PinSelectionToNewBlock(Selection* aSelection);
- void CheckInterlinePosition(Selection& aSelection);
- nsresult AdjustSelection(Selection* aSelection,
- nsIEditor::EDirection aAction);
- nsresult FindNearSelectableNode(nsIDOMNode* aSelNode,
- int32_t aSelOffset,
- nsIEditor::EDirection& aDirection,
- nsCOMPtr<nsIDOMNode>* outSelectableNode);
- /**
- * Returns true if aNode1 or aNode2 or both is the descendant of some type of
- * table element, but their nearest table element ancestors differ. "Table
- * element" here includes not just <table> but also <td>, <tbody>, <tr>, etc.
- * The nodes count as being their own descendants for this purpose, so a
- * table element is its own nearest table element ancestor.
- */
- bool InDifferentTableElements(nsIDOMNode* aNode1, nsIDOMNode* aNode2);
- bool InDifferentTableElements(nsINode* aNode1, nsINode* aNode2);
- nsresult RemoveEmptyNodes();
- nsresult SelectionEndpointInNode(nsINode* aNode, bool* aResult);
- nsresult UpdateDocChangeRange(nsRange* aRange);
- nsresult ConfirmSelectionInBody();
- nsresult InsertMozBRIfNeeded(nsINode& aNode);
- bool IsEmptyInline(nsINode& aNode);
- bool ListIsEmptyLine(nsTArray<OwningNonNull<nsINode>>& arrayOfNodes);
- nsresult RemoveAlignment(nsIDOMNode* aNode, const nsAString& aAlignType,
- bool aChildrenOnly);
- nsresult MakeSureElemStartsOrEndsOnCR(nsIDOMNode* aNode, bool aStarts);
- enum class ContentsOnly { no, yes };
- nsresult AlignBlock(Element& aElement,
- const nsAString& aAlignType, ContentsOnly aContentsOnly);
- enum class Change { minus, plus };
- nsresult ChangeIndentation(Element& aElement, Change aChange);
- void DocumentModifiedWorker();
-
-protected:
- HTMLEditor* mHTMLEditor;
- RefPtr<nsRange> mDocChangeRange;
- bool mListenerEnabled;
- bool mReturnInEmptyLIKillsList;
- bool mDidDeleteSelection;
- bool mDidRangedDelete;
- bool mRestoreContentEditableCount;
- RefPtr<nsRange> mUtilRange;
- // Need to remember an int across willJoin/didJoin...
- uint32_t mJoinOffset;
- nsCOMPtr<Element> mNewBlock;
- RefPtr<RangeItem> mRangeItem;
- StyleCache mCachedStyles[SIZE_STYLE_TABLE];
-};
-
-} // namespace mozilla
-
-#endif // #ifndef HTMLEditRules_h
-
diff --git a/editor/libeditor/HTMLEditUtils.cpp b/editor/libeditor/HTMLEditUtils.cpp
deleted file mode 100644
index 0e95b7ce9..000000000
--- a/editor/libeditor/HTMLEditUtils.cpp
+++ /dev/null
@@ -1,838 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "HTMLEditUtils.h"
-
-#include "TextEditUtils.h" // for TextEditUtils
-#include "mozilla/ArrayUtils.h" // for ArrayLength
-#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc.
-#include "mozilla/EditorBase.h" // for EditorBase
-#include "mozilla/dom/Element.h" // for Element, nsINode
-#include "nsAString.h" // for nsAString_internal::IsEmpty
-#include "nsCOMPtr.h" // for nsCOMPtr, operator==, etc.
-#include "nsCaseTreatment.h"
-#include "nsDebug.h" // for NS_PRECONDITION, etc.
-#include "nsError.h" // for NS_SUCCEEDED
-#include "nsGkAtoms.h" // for nsGkAtoms, nsGkAtoms::a, etc.
-#include "nsHTMLTags.h"
-#include "nsIAtom.h" // for nsIAtom
-#include "nsIDOMHTMLAnchorElement.h" // for nsIDOMHTMLAnchorElement
-#include "nsIDOMNode.h" // for nsIDOMNode
-#include "nsNameSpaceManager.h" // for kNameSpaceID_None
-#include "nsLiteralString.h" // for NS_LITERAL_STRING
-#include "nsString.h" // for nsAutoString
-
-namespace mozilla {
-
-/**
- * IsInlineStyle() returns true if aNode is an inline style.
- */
-bool
-HTMLEditUtils::IsInlineStyle(nsIDOMNode* aNode)
-{
- MOZ_ASSERT(aNode);
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- return node && IsInlineStyle(node);
-}
-
-bool
-HTMLEditUtils::IsInlineStyle(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
- return aNode->IsAnyOfHTMLElements(nsGkAtoms::b,
- nsGkAtoms::i,
- nsGkAtoms::u,
- nsGkAtoms::tt,
- nsGkAtoms::s,
- nsGkAtoms::strike,
- nsGkAtoms::big,
- nsGkAtoms::small,
- nsGkAtoms::sub,
- nsGkAtoms::sup,
- nsGkAtoms::font);
-}
-
-/**
- * IsFormatNode() returns true if aNode is a format node.
- */
-bool
-HTMLEditUtils::IsFormatNode(nsIDOMNode* aNode)
-{
- MOZ_ASSERT(aNode);
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- return node && IsFormatNode(node);
-}
-
-bool
-HTMLEditUtils::IsFormatNode(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
- return aNode->IsAnyOfHTMLElements(nsGkAtoms::p,
- nsGkAtoms::pre,
- nsGkAtoms::h1,
- nsGkAtoms::h2,
- nsGkAtoms::h3,
- nsGkAtoms::h4,
- nsGkAtoms::h5,
- nsGkAtoms::h6,
- nsGkAtoms::address);
-}
-
-/**
- * IsNodeThatCanOutdent() returns true if aNode is a list, list item or
- * blockquote.
- */
-bool
-HTMLEditUtils::IsNodeThatCanOutdent(nsIDOMNode* aNode)
-{
- MOZ_ASSERT(aNode);
- nsCOMPtr<nsIAtom> nodeAtom = EditorBase::GetTag(aNode);
- return (nodeAtom == nsGkAtoms::ul)
- || (nodeAtom == nsGkAtoms::ol)
- || (nodeAtom == nsGkAtoms::dl)
- || (nodeAtom == nsGkAtoms::li)
- || (nodeAtom == nsGkAtoms::dd)
- || (nodeAtom == nsGkAtoms::dt)
- || (nodeAtom == nsGkAtoms::blockquote);
-}
-
-/**
- * IsHeader() returns true if aNode is an html header.
- */
-bool
-HTMLEditUtils::IsHeader(nsINode& aNode)
-{
- return aNode.IsAnyOfHTMLElements(nsGkAtoms::h1,
- nsGkAtoms::h2,
- nsGkAtoms::h3,
- nsGkAtoms::h4,
- nsGkAtoms::h5,
- nsGkAtoms::h6);
-}
-
-bool
-HTMLEditUtils::IsHeader(nsIDOMNode* aNode)
-{
- MOZ_ASSERT(aNode);
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- MOZ_ASSERT(node);
- return IsHeader(*node);
-}
-
-/**
- * IsParagraph() returns true if aNode is an html paragraph.
- */
-bool
-HTMLEditUtils::IsParagraph(nsIDOMNode* aNode)
-{
- return EditorBase::NodeIsType(aNode, nsGkAtoms::p);
-}
-
-/**
- * IsHR() returns true if aNode is an horizontal rule.
- */
-bool
-HTMLEditUtils::IsHR(nsIDOMNode* aNode)
-{
- return EditorBase::NodeIsType(aNode, nsGkAtoms::hr);
-}
-
-/**
- * IsListItem() returns true if aNode is an html list item.
- */
-bool
-HTMLEditUtils::IsListItem(nsIDOMNode* aNode)
-{
- MOZ_ASSERT(aNode);
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- return node && IsListItem(node);
-}
-
-bool
-HTMLEditUtils::IsListItem(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
- return aNode->IsAnyOfHTMLElements(nsGkAtoms::li,
- nsGkAtoms::dd,
- nsGkAtoms::dt);
-}
-
-/**
- * IsTableElement() returns true if aNode is an html table, td, tr, ...
- */
-bool
-HTMLEditUtils::IsTableElement(nsIDOMNode* aNode)
-{
- MOZ_ASSERT(aNode);
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- return node && IsTableElement(node);
-}
-
-bool
-HTMLEditUtils::IsTableElement(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
- return aNode->IsAnyOfHTMLElements(nsGkAtoms::table,
- nsGkAtoms::tr,
- nsGkAtoms::td,
- nsGkAtoms::th,
- nsGkAtoms::thead,
- nsGkAtoms::tfoot,
- nsGkAtoms::tbody,
- nsGkAtoms::caption);
-}
-
-/**
- * IsTableElementButNotTable() returns true if aNode is an html td, tr, ...
- * (doesn't include table)
- */
-bool
-HTMLEditUtils::IsTableElementButNotTable(nsIDOMNode* aNode)
-{
- MOZ_ASSERT(aNode);
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- return node && IsTableElementButNotTable(node);
-}
-
-bool
-HTMLEditUtils::IsTableElementButNotTable(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
- return aNode->IsAnyOfHTMLElements(nsGkAtoms::tr,
- nsGkAtoms::td,
- nsGkAtoms::th,
- nsGkAtoms::thead,
- nsGkAtoms::tfoot,
- nsGkAtoms::tbody,
- nsGkAtoms::caption);
-}
-
-/**
- * IsTable() returns true if aNode is an html table.
- */
-bool
-HTMLEditUtils::IsTable(nsIDOMNode* aNode)
-{
- return EditorBase::NodeIsType(aNode, nsGkAtoms::table);
-}
-
-bool
-HTMLEditUtils::IsTable(nsINode* aNode)
-{
- return aNode && aNode->IsHTMLElement(nsGkAtoms::table);
-}
-
-/**
- * IsTableRow() returns true if aNode is an html tr.
- */
-bool
-HTMLEditUtils::IsTableRow(nsIDOMNode* aNode)
-{
- return EditorBase::NodeIsType(aNode, nsGkAtoms::tr);
-}
-
-/**
- * IsTableCell() returns true if aNode is an html td or th.
- */
-bool
-HTMLEditUtils::IsTableCell(nsIDOMNode* aNode)
-{
- MOZ_ASSERT(aNode);
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- return node && IsTableCell(node);
-}
-
-bool
-HTMLEditUtils::IsTableCell(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
- return aNode->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th);
-}
-
-/**
- * IsTableCellOrCaption() returns true if aNode is an html td or th or caption.
- */
-bool
-HTMLEditUtils::IsTableCellOrCaption(nsINode& aNode)
-{
- return aNode.IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th,
- nsGkAtoms::caption);
-}
-
-/**
- * IsList() returns true if aNode is an html list.
- */
-bool
-HTMLEditUtils::IsList(nsIDOMNode* aNode)
-{
- MOZ_ASSERT(aNode);
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- return node && IsList(node);
-}
-
-bool
-HTMLEditUtils::IsList(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
- return aNode->IsAnyOfHTMLElements(nsGkAtoms::ul,
- nsGkAtoms::ol,
- nsGkAtoms::dl);
-}
-
-/**
- * IsOrderedList() returns true if aNode is an html ordered list.
- */
-bool
-HTMLEditUtils::IsOrderedList(nsIDOMNode* aNode)
-{
- return EditorBase::NodeIsType(aNode, nsGkAtoms::ol);
-}
-
-
-/**
- * IsUnorderedList() returns true if aNode is an html unordered list.
- */
-bool
-HTMLEditUtils::IsUnorderedList(nsIDOMNode* aNode)
-{
- return EditorBase::NodeIsType(aNode, nsGkAtoms::ul);
-}
-
-/**
- * IsBlockquote() returns true if aNode is an html blockquote node.
- */
-bool
-HTMLEditUtils::IsBlockquote(nsIDOMNode* aNode)
-{
- return EditorBase::NodeIsType(aNode, nsGkAtoms::blockquote);
-}
-
-/**
- * IsPre() returns true if aNode is an html pre node.
- */
-bool
-HTMLEditUtils::IsPre(nsIDOMNode* aNode)
-{
- return EditorBase::NodeIsType(aNode, nsGkAtoms::pre);
-}
-
-/**
- * IsImage() returns true if aNode is an html image node.
- */
-bool
-HTMLEditUtils::IsImage(nsINode* aNode)
-{
- return aNode && aNode->IsHTMLElement(nsGkAtoms::img);
-}
-
-bool
-HTMLEditUtils::IsImage(nsIDOMNode* aNode)
-{
- return EditorBase::NodeIsType(aNode, nsGkAtoms::img);
-}
-
-bool
-HTMLEditUtils::IsLink(nsIDOMNode *aNode)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- return node && IsLink(node);
-}
-
-bool
-HTMLEditUtils::IsLink(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
-
- nsCOMPtr<nsIDOMHTMLAnchorElement> anchor = do_QueryInterface(aNode);
- if (anchor) {
- nsAutoString tmpText;
- if (NS_SUCCEEDED(anchor->GetHref(tmpText)) && !tmpText.IsEmpty()) {
- return true;
- }
- }
- return false;
-}
-
-bool
-HTMLEditUtils::IsNamedAnchor(nsIDOMNode *aNode)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- return node && IsNamedAnchor(node);
-}
-
-bool
-HTMLEditUtils::IsNamedAnchor(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
- if (!aNode->IsHTMLElement(nsGkAtoms::a)) {
- return false;
- }
-
- nsAutoString text;
- return aNode->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::name,
- text) && !text.IsEmpty();
-}
-
-/**
- * IsDiv() returns true if aNode is an html div node.
- */
-bool
-HTMLEditUtils::IsDiv(nsIDOMNode* aNode)
-{
- return EditorBase::NodeIsType(aNode, nsGkAtoms::div);
-}
-
-/**
- * IsMozDiv() returns true if aNode is an html div node with |type = _moz|.
- */
-bool
-HTMLEditUtils::IsMozDiv(nsIDOMNode* aNode)
-{
- return IsDiv(aNode) && TextEditUtils::HasMozAttr(aNode);
-}
-
-bool
-HTMLEditUtils::IsMozDiv(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
- return aNode->IsHTMLElement(nsGkAtoms::div) &&
- TextEditUtils::HasMozAttr(GetAsDOMNode(aNode));
-}
-
-/**
- * IsMailCite() returns true if aNode is an html blockquote with |type=cite|.
- */
-bool
-HTMLEditUtils::IsMailCite(nsIDOMNode* aNode)
-{
- MOZ_ASSERT(aNode);
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- return node && IsMailCite(node);
-}
-
-bool
-HTMLEditUtils::IsMailCite(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
-
- // don't ask me why, but our html mailcites are id'd by "type=cite"...
- if (aNode->IsElement() &&
- aNode->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
- NS_LITERAL_STRING("cite"),
- eIgnoreCase)) {
- return true;
- }
-
- // ... but our plaintext mailcites by "_moz_quote=true". go figure.
- if (aNode->IsElement() &&
- aNode->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mozquote,
- NS_LITERAL_STRING("true"),
- eIgnoreCase)) {
- return true;
- }
-
- return false;
-}
-
-/**
- * IsFormWidget() returns true if aNode is a form widget of some kind.
- */
-bool
-HTMLEditUtils::IsFormWidget(nsIDOMNode* aNode)
-{
- MOZ_ASSERT(aNode);
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- return node && IsFormWidget(node);
-}
-
-bool
-HTMLEditUtils::IsFormWidget(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
- return aNode->IsAnyOfHTMLElements(nsGkAtoms::textarea,
- nsGkAtoms::select,
- nsGkAtoms::button,
- nsGkAtoms::output,
- nsGkAtoms::keygen,
- nsGkAtoms::progress,
- nsGkAtoms::meter,
- nsGkAtoms::input);
-}
-
-bool
-HTMLEditUtils::SupportsAlignAttr(nsIDOMNode* aNode)
-{
- MOZ_ASSERT(aNode);
- nsCOMPtr<nsIAtom> nodeAtom = EditorBase::GetTag(aNode);
- return (nodeAtom == nsGkAtoms::hr)
- || (nodeAtom == nsGkAtoms::table)
- || (nodeAtom == nsGkAtoms::tbody)
- || (nodeAtom == nsGkAtoms::tfoot)
- || (nodeAtom == nsGkAtoms::thead)
- || (nodeAtom == nsGkAtoms::tr)
- || (nodeAtom == nsGkAtoms::td)
- || (nodeAtom == nsGkAtoms::th)
- || (nodeAtom == nsGkAtoms::div)
- || (nodeAtom == nsGkAtoms::p)
- || (nodeAtom == nsGkAtoms::h1)
- || (nodeAtom == nsGkAtoms::h2)
- || (nodeAtom == nsGkAtoms::h3)
- || (nodeAtom == nsGkAtoms::h4)
- || (nodeAtom == nsGkAtoms::h5)
- || (nodeAtom == nsGkAtoms::h6);
-}
-
-// We use bitmasks to test containment of elements. Elements are marked to be
-// in certain groups by setting the mGroup member of the nsElementInfo struct
-// to the corresponding GROUP_ values (OR'ed together). Similarly, elements are
-// marked to allow containment of certain groups by setting the
-// mCanContainGroups member of the nsElementInfo struct to the corresponding
-// GROUP_ values (OR'ed together).
-// Testing containment then simply consists of checking whether the
-// mCanContainGroups bitmask of an element and the mGroup bitmask of a
-// potential child overlap.
-
-#define GROUP_NONE 0
-
-// body, head, html
-#define GROUP_TOPLEVEL (1 << 1)
-
-// base, link, meta, script, style, title
-#define GROUP_HEAD_CONTENT (1 << 2)
-
-// b, big, i, s, small, strike, tt, u
-#define GROUP_FONTSTYLE (1 << 3)
-
-// abbr, acronym, cite, code, datalist, del, dfn, em, ins, kbd, mark, rb, rp
-// rt, rtc, ruby, samp, strong, var
-#define GROUP_PHRASE (1 << 4)
-
-// a, applet, basefont, bdo, br, font, iframe, img, map, meter, object, output,
-// picture, progress, q, script, span, sub, sup
-#define GROUP_SPECIAL (1 << 5)
-
-// button, form, input, label, select, textarea
-#define GROUP_FORMCONTROL (1 << 6)
-
-// address, applet, article, aside, blockquote, button, center, del, details,
-// dialog, dir, div, dl, fieldset, figure, footer, form, h1, h2, h3, h4, h5,
-// h6, header, hgroup, hr, iframe, ins, main, map, menu, nav, noframes,
-// noscript, object, ol, p, pre, table, section, summary, ul
-#define GROUP_BLOCK (1 << 7)
-
-// frame, frameset
-#define GROUP_FRAME (1 << 8)
-
-// col, tbody
-#define GROUP_TABLE_CONTENT (1 << 9)
-
-// tr
-#define GROUP_TBODY_CONTENT (1 << 10)
-
-// td, th
-#define GROUP_TR_CONTENT (1 << 11)
-
-// col
-#define GROUP_COLGROUP_CONTENT (1 << 12)
-
-// param
-#define GROUP_OBJECT_CONTENT (1 << 13)
-
-// li
-#define GROUP_LI (1 << 14)
-
-// area
-#define GROUP_MAP_CONTENT (1 << 15)
-
-// optgroup, option
-#define GROUP_SELECT_CONTENT (1 << 16)
-
-// option
-#define GROUP_OPTIONS (1 << 17)
-
-// dd, dt
-#define GROUP_DL_CONTENT (1 << 18)
-
-// p
-#define GROUP_P (1 << 19)
-
-// text, whitespace, newline, comment
-#define GROUP_LEAF (1 << 20)
-
-// XXX This is because the editor does sublists illegally.
-// ol, ul
-#define GROUP_OL_UL (1 << 21)
-
-// h1, h2, h3, h4, h5, h6
-#define GROUP_HEADING (1 << 22)
-
-// figcaption
-#define GROUP_FIGCAPTION (1 << 23)
-
-// picture members (img, source)
-#define GROUP_PICTURE_CONTENT (1 << 24)
-
-#define GROUP_INLINE_ELEMENT \
- (GROUP_FONTSTYLE | GROUP_PHRASE | GROUP_SPECIAL | GROUP_FORMCONTROL | \
- GROUP_LEAF)
-
-#define GROUP_FLOW_ELEMENT (GROUP_INLINE_ELEMENT | GROUP_BLOCK)
-
-struct ElementInfo final
-{
-#ifdef DEBUG
- nsHTMLTag mTag;
-#endif
- uint32_t mGroup;
- uint32_t mCanContainGroups;
- bool mIsContainer;
- bool mCanContainSelf;
-};
-
-#ifdef DEBUG
-#define ELEM(_tag, _isContainer, _canContainSelf, _group, _canContainGroups) \
- { eHTMLTag_##_tag, _group, _canContainGroups, _isContainer, _canContainSelf }
-#else
-#define ELEM(_tag, _isContainer, _canContainSelf, _group, _canContainGroups) \
- { _group, _canContainGroups, _isContainer, _canContainSelf }
-#endif
-
-static const ElementInfo kElements[eHTMLTag_userdefined] = {
- ELEM(a, true, false, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
- ELEM(abbr, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(acronym, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(address, true, true, GROUP_BLOCK, GROUP_INLINE_ELEMENT | GROUP_P),
- ELEM(applet,
- true,
- true,
- GROUP_SPECIAL | GROUP_BLOCK,
- GROUP_FLOW_ELEMENT | GROUP_OBJECT_CONTENT),
- ELEM(area, false, false, GROUP_MAP_CONTENT, GROUP_NONE),
- ELEM(article, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(aside, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(audio, false, false, GROUP_NONE, GROUP_NONE),
- ELEM(b, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
- ELEM(base, false, false, GROUP_HEAD_CONTENT, GROUP_NONE),
- ELEM(basefont, false, false, GROUP_SPECIAL, GROUP_NONE),
- ELEM(bdo, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
- ELEM(bgsound, false, false, GROUP_NONE, GROUP_NONE),
- ELEM(big, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
- ELEM(blockquote, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(body, true, true, GROUP_TOPLEVEL, GROUP_FLOW_ELEMENT),
- ELEM(br, false, false, GROUP_SPECIAL, GROUP_NONE),
- ELEM(button, true, true, GROUP_FORMCONTROL | GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(canvas, false, false, GROUP_NONE, GROUP_NONE),
- ELEM(caption, true, true, GROUP_NONE, GROUP_INLINE_ELEMENT),
- ELEM(center, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(cite, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(code, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(col,
- false,
- false,
- GROUP_TABLE_CONTENT | GROUP_COLGROUP_CONTENT,
- GROUP_NONE),
- ELEM(colgroup, true, false, GROUP_NONE, GROUP_COLGROUP_CONTENT),
- ELEM(data, true, false, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(datalist,
- true,
- false,
- GROUP_PHRASE,
- GROUP_OPTIONS | GROUP_INLINE_ELEMENT),
- ELEM(dd, true, false, GROUP_DL_CONTENT, GROUP_FLOW_ELEMENT),
- ELEM(del, true, true, GROUP_PHRASE | GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(details, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(dfn, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(dialog, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(dir, true, false, GROUP_BLOCK, GROUP_LI),
- ELEM(div, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(dl, true, false, GROUP_BLOCK, GROUP_DL_CONTENT),
- ELEM(dt, true, true, GROUP_DL_CONTENT, GROUP_INLINE_ELEMENT),
- ELEM(em, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(embed, false, false, GROUP_NONE, GROUP_NONE),
- ELEM(fieldset, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(figcaption, true, false, GROUP_FIGCAPTION, GROUP_FLOW_ELEMENT),
- ELEM(figure, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT | GROUP_FIGCAPTION),
- ELEM(font, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
- ELEM(footer, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(form, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(frame, false, false, GROUP_FRAME, GROUP_NONE),
- ELEM(frameset, true, true, GROUP_FRAME, GROUP_FRAME),
- ELEM(h1, true, false, GROUP_BLOCK | GROUP_HEADING, GROUP_INLINE_ELEMENT),
- ELEM(h2, true, false, GROUP_BLOCK | GROUP_HEADING, GROUP_INLINE_ELEMENT),
- ELEM(h3, true, false, GROUP_BLOCK | GROUP_HEADING, GROUP_INLINE_ELEMENT),
- ELEM(h4, true, false, GROUP_BLOCK | GROUP_HEADING, GROUP_INLINE_ELEMENT),
- ELEM(h5, true, false, GROUP_BLOCK | GROUP_HEADING, GROUP_INLINE_ELEMENT),
- ELEM(h6, true, false, GROUP_BLOCK | GROUP_HEADING, GROUP_INLINE_ELEMENT),
- ELEM(head, true, false, GROUP_TOPLEVEL, GROUP_HEAD_CONTENT),
- ELEM(header, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(hgroup, true, false, GROUP_BLOCK, GROUP_HEADING),
- ELEM(hr, false, false, GROUP_BLOCK, GROUP_NONE),
- ELEM(html, true, false, GROUP_TOPLEVEL, GROUP_TOPLEVEL),
- ELEM(i, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
- ELEM(iframe, true, true, GROUP_SPECIAL | GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(image, false, false, GROUP_NONE, GROUP_NONE),
- ELEM(img, false, false, GROUP_SPECIAL | GROUP_PICTURE_CONTENT, GROUP_NONE),
- ELEM(input, false, false, GROUP_FORMCONTROL, GROUP_NONE),
- ELEM(ins, true, true, GROUP_PHRASE | GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(kbd, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(keygen, false, false, GROUP_FORMCONTROL, GROUP_NONE),
- ELEM(label, true, false, GROUP_FORMCONTROL, GROUP_INLINE_ELEMENT),
- ELEM(legend, true, true, GROUP_NONE, GROUP_INLINE_ELEMENT),
- ELEM(li, true, false, GROUP_LI, GROUP_FLOW_ELEMENT),
- ELEM(link, false, false, GROUP_HEAD_CONTENT, GROUP_NONE),
- ELEM(listing, false, false, GROUP_NONE, GROUP_NONE),
- ELEM(main, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(map, true, true, GROUP_SPECIAL, GROUP_BLOCK | GROUP_MAP_CONTENT),
- ELEM(mark, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(menu, true, true, GROUP_BLOCK, GROUP_LI | GROUP_FLOW_ELEMENT),
- ELEM(menuitem, false, false, GROUP_NONE, GROUP_NONE),
- ELEM(meta, false, false, GROUP_HEAD_CONTENT, GROUP_NONE),
- ELEM(meter, true, false, GROUP_SPECIAL, GROUP_FLOW_ELEMENT),
- ELEM(multicol, false, false, GROUP_NONE, GROUP_NONE),
- ELEM(nav, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(nobr, false, false, GROUP_NONE, GROUP_NONE),
- ELEM(noembed, false, false, GROUP_NONE, GROUP_NONE),
- ELEM(noframes, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(noscript, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(object,
- true,
- true,
- GROUP_SPECIAL | GROUP_BLOCK,
- GROUP_FLOW_ELEMENT | GROUP_OBJECT_CONTENT),
- // XXX Can contain self and ul because editor does sublists illegally.
- ELEM(ol, true, true, GROUP_BLOCK | GROUP_OL_UL, GROUP_LI | GROUP_OL_UL),
- ELEM(optgroup, true, false, GROUP_SELECT_CONTENT, GROUP_OPTIONS),
- ELEM(option, true, false, GROUP_SELECT_CONTENT | GROUP_OPTIONS, GROUP_LEAF),
- ELEM(output, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
- ELEM(p, true, false, GROUP_BLOCK | GROUP_P, GROUP_INLINE_ELEMENT),
- ELEM(param, false, false, GROUP_OBJECT_CONTENT, GROUP_NONE),
- ELEM(picture, true, false, GROUP_SPECIAL, GROUP_PICTURE_CONTENT),
- ELEM(plaintext, false, false, GROUP_NONE, GROUP_NONE),
- ELEM(pre, true, true, GROUP_BLOCK, GROUP_INLINE_ELEMENT),
- ELEM(progress, true, false, GROUP_SPECIAL, GROUP_FLOW_ELEMENT),
- ELEM(q, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
- ELEM(rb, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(rp, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(rt, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(rtc, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(ruby, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(s, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
- ELEM(samp, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(script, true, false, GROUP_HEAD_CONTENT | GROUP_SPECIAL, GROUP_LEAF),
- ELEM(section, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(select, true, false, GROUP_FORMCONTROL, GROUP_SELECT_CONTENT),
- ELEM(small, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
- ELEM(slot, true, false, GROUP_NONE, GROUP_FLOW_ELEMENT),
- ELEM(source, false, false, GROUP_PICTURE_CONTENT, GROUP_NONE),
- ELEM(span, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
- ELEM(strike, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
- ELEM(strong, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(style, true, false, GROUP_HEAD_CONTENT, GROUP_LEAF),
- ELEM(sub, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
- ELEM(summary, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(sup, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
- ELEM(table, true, false, GROUP_BLOCK, GROUP_TABLE_CONTENT),
- ELEM(tbody, true, false, GROUP_TABLE_CONTENT, GROUP_TBODY_CONTENT),
- ELEM(td, true, false, GROUP_TR_CONTENT, GROUP_FLOW_ELEMENT),
- ELEM(textarea, true, false, GROUP_FORMCONTROL, GROUP_LEAF),
- ELEM(tfoot, true, false, GROUP_NONE, GROUP_TBODY_CONTENT),
- ELEM(th, true, false, GROUP_TR_CONTENT, GROUP_FLOW_ELEMENT),
- ELEM(thead, true, false, GROUP_NONE, GROUP_TBODY_CONTENT),
- ELEM(template, false, false, GROUP_NONE, GROUP_NONE),
- ELEM(time, true, false, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(title, true, false, GROUP_HEAD_CONTENT, GROUP_LEAF),
- ELEM(tr, true, false, GROUP_TBODY_CONTENT, GROUP_TR_CONTENT),
- ELEM(track, false, false, GROUP_NONE, GROUP_NONE),
- ELEM(tt, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
- ELEM(u, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
- // XXX Can contain self and ol because editor does sublists illegally.
- ELEM(ul, true, true, GROUP_BLOCK | GROUP_OL_UL, GROUP_LI | GROUP_OL_UL),
- ELEM(var, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(video, false, false, GROUP_NONE, GROUP_NONE),
- ELEM(wbr, false, false, GROUP_NONE, GROUP_NONE),
- ELEM(xmp, false, false, GROUP_NONE, GROUP_NONE),
-
- // These aren't elements.
- ELEM(text, false, false, GROUP_LEAF, GROUP_NONE),
- ELEM(whitespace, false, false, GROUP_LEAF, GROUP_NONE),
- ELEM(newline, false, false, GROUP_LEAF, GROUP_NONE),
- ELEM(comment, false, false, GROUP_LEAF, GROUP_NONE),
- ELEM(entity, false, false, GROUP_NONE, GROUP_NONE),
- ELEM(doctypeDecl, false, false, GROUP_NONE, GROUP_NONE),
- ELEM(markupDecl, false, false, GROUP_NONE, GROUP_NONE),
- ELEM(instruction, false, false, GROUP_NONE, GROUP_NONE),
-
- ELEM(userdefined, true, false, GROUP_NONE, GROUP_FLOW_ELEMENT)
-};
-
-bool
-HTMLEditUtils::CanContain(int32_t aParent, int32_t aChild)
-{
- NS_ASSERTION(aParent > eHTMLTag_unknown && aParent <= eHTMLTag_userdefined,
- "aParent out of range!");
- NS_ASSERTION(aChild > eHTMLTag_unknown && aChild <= eHTMLTag_userdefined,
- "aChild out of range!");
-
-#ifdef DEBUG
- static bool checked = false;
- if (!checked) {
- checked = true;
- int32_t i;
- for (i = 1; i <= eHTMLTag_userdefined; ++i) {
- NS_ASSERTION(kElements[i - 1].mTag == i,
- "You need to update kElements (missing tags).");
- }
- }
-#endif
-
- // Special-case button.
- if (aParent == eHTMLTag_button) {
- static const nsHTMLTag kButtonExcludeKids[] = {
- eHTMLTag_a,
- eHTMLTag_fieldset,
- eHTMLTag_form,
- eHTMLTag_iframe,
- eHTMLTag_input,
- eHTMLTag_select,
- eHTMLTag_textarea
- };
-
- uint32_t j;
- for (j = 0; j < ArrayLength(kButtonExcludeKids); ++j) {
- if (kButtonExcludeKids[j] == aChild) {
- return false;
- }
- }
- }
-
- // Deprecated elements.
- if (aChild == eHTMLTag_bgsound) {
- return false;
- }
-
- // Bug #67007, dont strip userdefined tags.
- if (aChild == eHTMLTag_userdefined) {
- return true;
- }
-
- const ElementInfo& parent = kElements[aParent - 1];
- if (aParent == aChild) {
- return parent.mCanContainSelf;
- }
-
- const ElementInfo& child = kElements[aChild - 1];
- return (parent.mCanContainGroups & child.mGroup) != 0;
-}
-
-bool
-HTMLEditUtils::IsContainer(int32_t aTag)
-{
- NS_ASSERTION(aTag > eHTMLTag_unknown && aTag <= eHTMLTag_userdefined,
- "aTag out of range!");
-
- return kElements[aTag - 1].mIsContainer;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/HTMLEditUtils.h b/editor/libeditor/HTMLEditUtils.h
deleted file mode 100644
index 95d3c0375..000000000
--- a/editor/libeditor/HTMLEditUtils.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef HTMLEditUtils_h
-#define HTMLEditUtils_h
-
-#include <stdint.h>
-#ifdef DEBUG
-// Used by various files for debug logging; included here to reduce duplication
-#include "nsDocument.h"
-#endif
-
-class nsIDOMNode;
-class nsINode;
-
-namespace mozilla {
-
-class HTMLEditUtils final
-{
-public:
- // from nsHTMLEditRules:
- static bool IsInlineStyle(nsINode* aNode);
- static bool IsInlineStyle(nsIDOMNode *aNode);
- static bool IsFormatNode(nsINode* aNode);
- static bool IsFormatNode(nsIDOMNode* aNode);
- static bool IsNodeThatCanOutdent(nsIDOMNode* aNode);
- static bool IsHeader(nsINode& aNode);
- static bool IsHeader(nsIDOMNode* aNode);
- static bool IsParagraph(nsIDOMNode* aNode);
- static bool IsHR(nsIDOMNode* aNode);
- static bool IsListItem(nsINode* aNode);
- static bool IsListItem(nsIDOMNode* aNode);
- static bool IsTable(nsIDOMNode* aNode);
- static bool IsTable(nsINode* aNode);
- static bool IsTableRow(nsIDOMNode* aNode);
- static bool IsTableElement(nsINode* aNode);
- static bool IsTableElement(nsIDOMNode* aNode);
- static bool IsTableElementButNotTable(nsINode* aNode);
- static bool IsTableElementButNotTable(nsIDOMNode* aNode);
- static bool IsTableCell(nsINode* node);
- static bool IsTableCell(nsIDOMNode* aNode);
- static bool IsTableCellOrCaption(nsINode& aNode);
- static bool IsList(nsINode* aNode);
- static bool IsList(nsIDOMNode* aNode);
- static bool IsOrderedList(nsIDOMNode* aNode);
- static bool IsUnorderedList(nsIDOMNode* aNode);
- static bool IsBlockquote(nsIDOMNode* aNode);
- static bool IsPre(nsIDOMNode* aNode);
- static bool IsAnchor(nsIDOMNode* aNode);
- static bool IsImage(nsINode* aNode);
- static bool IsImage(nsIDOMNode* aNode);
- static bool IsLink(nsIDOMNode* aNode);
- static bool IsLink(nsINode* aNode);
- static bool IsNamedAnchor(nsINode* aNode);
- static bool IsNamedAnchor(nsIDOMNode* aNode);
- static bool IsDiv(nsIDOMNode* aNode);
- static bool IsMozDiv(nsINode* aNode);
- static bool IsMozDiv(nsIDOMNode* aNode);
- static bool IsMailCite(nsINode* aNode);
- static bool IsMailCite(nsIDOMNode* aNode);
- static bool IsFormWidget(nsINode* aNode);
- static bool IsFormWidget(nsIDOMNode* aNode);
- static bool SupportsAlignAttr(nsIDOMNode* aNode);
- static bool CanContain(int32_t aParent, int32_t aChild);
- static bool IsContainer(int32_t aTag);
-};
-
-} // namespace mozilla
-
-#endif // #ifndef HTMLEditUtils_h
-
diff --git a/editor/libeditor/HTMLEditor.cpp b/editor/libeditor/HTMLEditor.cpp
deleted file mode 100644
index 6a630cb1c..000000000
--- a/editor/libeditor/HTMLEditor.cpp
+++ /dev/null
@@ -1,5255 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/HTMLEditor.h"
-
-#include "mozilla/DebugOnly.h"
-#include "mozilla/EventStates.h"
-#include "mozilla/TextEvents.h"
-
-#include "nsCRT.h"
-
-#include "nsUnicharUtils.h"
-
-#include "HTMLEditorEventListener.h"
-#include "HTMLEditRules.h"
-#include "HTMLEditUtils.h"
-#include "HTMLURIRefObject.h"
-#include "SetDocumentTitleTransaction.h"
-#include "StyleSheetTransactions.h"
-#include "TextEditUtils.h"
-#include "TypeInState.h"
-
-#include "nsIDOMText.h"
-#include "nsIDOMMozNamedAttrMap.h"
-#include "nsIDOMNodeList.h"
-#include "nsIDOMDocument.h"
-#include "nsIDOMAttr.h"
-#include "nsIDocumentInlines.h"
-#include "nsIDOMEventTarget.h"
-#include "nsIDOMKeyEvent.h"
-#include "nsIDOMMouseEvent.h"
-#include "nsIDOMHTMLAnchorElement.h"
-#include "nsISelectionController.h"
-#include "nsIDOMHTMLDocument.h"
-#include "nsILinkHandler.h"
-#include "nsIInlineSpellChecker.h"
-
-#include "mozilla/css/Loader.h"
-#include "nsIDOMStyleSheet.h"
-
-#include "nsIContent.h"
-#include "nsIContentIterator.h"
-#include "nsIMutableArray.h"
-#include "nsContentUtils.h"
-#include "nsIDocumentEncoder.h"
-#include "nsIPresShell.h"
-#include "nsPresContext.h"
-#include "nsFocusManager.h"
-#include "nsPIDOMWindow.h"
-
-// netwerk
-#include "nsIURI.h"
-#include "nsNetUtil.h"
-
-// Misc
-#include "mozilla/EditorUtils.h"
-#include "HTMLEditorObjectResizerUtils.h"
-#include "TextEditorTest.h"
-#include "WSRunObject.h"
-#include "nsGkAtoms.h"
-#include "nsIWidget.h"
-
-#include "nsIFrame.h"
-#include "mozilla/dom/Selection.h"
-#include "mozilla/dom/DocumentFragment.h"
-#include "mozilla/dom/Element.h"
-#include "mozilla/dom/Event.h"
-#include "mozilla/dom/EventTarget.h"
-#include "mozilla/dom/HTMLBodyElement.h"
-#include "nsElementTable.h"
-#include "nsTextFragment.h"
-#include "nsContentList.h"
-#include "mozilla/StyleSheet.h"
-#include "mozilla/StyleSheetInlines.h"
-
-namespace mozilla {
-
-using namespace dom;
-using namespace widget;
-
-// Some utilities to handle overloading of "A" tag for link and named anchor.
-static bool
-IsLinkTag(const nsString& s)
-{
- return s.EqualsIgnoreCase("href");
-}
-
-static bool
-IsNamedAnchorTag(const nsString& s)
-{
- return s.EqualsIgnoreCase("anchor") || s.EqualsIgnoreCase("namedanchor");
-}
-
-HTMLEditor::HTMLEditor()
- : mCRInParagraphCreatesParagraph(false)
- , mCSSAware(false)
- , mSelectedCellIndex(0)
- , mIsObjectResizingEnabled(true)
- , mIsResizing(false)
- , mPreserveRatio(false)
- , mResizedObjectIsAnImage(false)
- , mIsAbsolutelyPositioningEnabled(true)
- , mResizedObjectIsAbsolutelyPositioned(false)
- , mGrabberClicked(false)
- , mIsMoving(false)
- , mSnapToGridEnabled(false)
- , mIsInlineTableEditingEnabled(true)
- , mOriginalX(0)
- , mOriginalY(0)
- , mResizedObjectX(0)
- , mResizedObjectY(0)
- , mResizedObjectWidth(0)
- , mResizedObjectHeight(0)
- , mResizedObjectMarginLeft(0)
- , mResizedObjectMarginTop(0)
- , mResizedObjectBorderLeft(0)
- , mResizedObjectBorderTop(0)
- , mXIncrementFactor(0)
- , mYIncrementFactor(0)
- , mWidthIncrementFactor(0)
- , mHeightIncrementFactor(0)
- , mInfoXIncrement(20)
- , mInfoYIncrement(20)
- , mPositionedObjectX(0)
- , mPositionedObjectY(0)
- , mPositionedObjectWidth(0)
- , mPositionedObjectHeight(0)
- , mPositionedObjectMarginLeft(0)
- , mPositionedObjectMarginTop(0)
- , mPositionedObjectBorderLeft(0)
- , mPositionedObjectBorderTop(0)
- , mGridSize(0)
-{
-}
-
-HTMLEditor::~HTMLEditor()
-{
- // remove the rules as an action listener. Else we get a bad
- // ownership loop later on. it's ok if the rules aren't a listener;
- // we ignore the error.
- nsCOMPtr<nsIEditActionListener> mListener = do_QueryInterface(mRules);
- RemoveEditActionListener(mListener);
-
- //the autopointers will clear themselves up.
- //but we need to also remove the listeners or we have a leak
- RefPtr<Selection> selection = GetSelection();
- // if we don't get the selection, just skip this
- if (selection) {
- nsCOMPtr<nsISelectionListener>listener;
- listener = do_QueryInterface(mTypeInState);
- if (listener) {
- selection->RemoveSelectionListener(listener);
- }
- listener = do_QueryInterface(mSelectionListenerP);
- if (listener) {
- selection->RemoveSelectionListener(listener);
- }
- }
-
- mTypeInState = nullptr;
- mSelectionListenerP = nullptr;
-
- // free any default style propItems
- RemoveAllDefaultProperties();
-
- if (mLinkHandler && IsInitialized()) {
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
-
- if (ps && ps->GetPresContext()) {
- ps->GetPresContext()->SetLinkHandler(mLinkHandler);
- }
- }
-
- RemoveEventListeners();
-
- HideAnonymousEditingUIs();
-}
-
-void
-HTMLEditor::HideAnonymousEditingUIs()
-{
- if (mAbsolutelyPositionedObject) {
- HideGrabber();
- }
- if (mInlineEditedCell) {
- HideInlineTableEditingUI();
- }
- if (mResizedObject) {
- HideResizers();
- }
-}
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLEditor)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLEditor, TextEditor)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mTypeInState)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mStyleSheets)
-
- tmp->HideAnonymousEditingUIs();
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLEditor, TextEditor)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTypeInState)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleSheets)
-
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTopLeftHandle)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTopHandle)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTopRightHandle)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLeftHandle)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRightHandle)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBottomLeftHandle)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBottomHandle)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBottomRightHandle)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mActivatedHandle)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResizingShadow)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResizingInfo)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResizedObject)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMouseMotionListenerP)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelectionListenerP)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResizeEventListenerP)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObjectResizeEventListeners)
-
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAbsolutelyPositionedObject)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGrabber)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPositioningShadow)
-
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInlineEditedCell)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAddColumnBeforeButton)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRemoveColumnButton)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAddColumnAfterButton)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAddRowBeforeButton)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRemoveRowButton)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAddRowAfterButton)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_ADDREF_INHERITED(HTMLEditor, EditorBase)
-NS_IMPL_RELEASE_INHERITED(HTMLEditor, EditorBase)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLEditor)
- NS_INTERFACE_MAP_ENTRY(nsIHTMLEditor)
- NS_INTERFACE_MAP_ENTRY(nsIHTMLObjectResizer)
- NS_INTERFACE_MAP_ENTRY(nsIHTMLAbsPosEditor)
- NS_INTERFACE_MAP_ENTRY(nsIHTMLInlineTableEditor)
- NS_INTERFACE_MAP_ENTRY(nsITableEditor)
- NS_INTERFACE_MAP_ENTRY(nsIEditorStyleSheets)
- NS_INTERFACE_MAP_ENTRY(nsICSSLoaderObserver)
- NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
-NS_INTERFACE_MAP_END_INHERITING(TextEditor)
-
-NS_IMETHODIMP
-HTMLEditor::Init(nsIDOMDocument* aDoc,
- nsIContent* aRoot,
- nsISelectionController* aSelCon,
- uint32_t aFlags,
- const nsAString& aInitialValue)
-{
- NS_PRECONDITION(aDoc && !aSelCon, "bad arg");
- NS_ENSURE_TRUE(aDoc, NS_ERROR_NULL_POINTER);
- MOZ_ASSERT(aInitialValue.IsEmpty(), "Non-empty initial values not supported");
-
- nsresult rulesRv = NS_OK;
-
- {
- // block to scope AutoEditInitRulesTrigger
- AutoEditInitRulesTrigger rulesTrigger(this, rulesRv);
-
- // Init the plaintext editor
- nsresult rv = TextEditor::Init(aDoc, aRoot, nullptr, aFlags, aInitialValue);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- // Init mutation observer
- nsCOMPtr<nsINode> document = do_QueryInterface(aDoc);
- document->AddMutationObserverUnlessExists(this);
-
- if (!mRootElement) {
- UpdateRootElement();
- }
-
- // disable Composer-only features
- if (IsMailEditor()) {
- SetAbsolutePositioningEnabled(false);
- SetSnapToGridEnabled(false);
- }
-
- // Init the HTML-CSS utils
- mCSSEditUtils = MakeUnique<CSSEditUtils>(this);
-
- // disable links
- nsCOMPtr<nsIPresShell> presShell = GetPresShell();
- NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
- nsPresContext *context = presShell->GetPresContext();
- NS_ENSURE_TRUE(context, NS_ERROR_NULL_POINTER);
- if (!IsPlaintextEditor() && !IsInteractionAllowed()) {
- mLinkHandler = context->GetLinkHandler();
- context->SetLinkHandler(nullptr);
- }
-
- // init the type-in state
- mTypeInState = new TypeInState();
-
- // init the selection listener for image resizing
- mSelectionListenerP = new ResizerSelectionListener(this);
-
- if (!IsInteractionAllowed()) {
- // ignore any errors from this in case the file is missing
- AddOverrideStyleSheet(NS_LITERAL_STRING("resource://gre/res/EditorOverride.css"));
- }
-
- RefPtr<Selection> selection = GetSelection();
- if (selection) {
- nsCOMPtr<nsISelectionListener>listener;
- listener = do_QueryInterface(mTypeInState);
- if (listener) {
- selection->AddSelectionListener(listener);
- }
- listener = do_QueryInterface(mSelectionListenerP);
- if (listener) {
- selection->AddSelectionListener(listener);
- }
- }
- }
- NS_ENSURE_SUCCESS(rulesRv, rulesRv);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::PreDestroy(bool aDestroyingFrames)
-{
- if (mDidPreDestroy) {
- return NS_OK;
- }
-
- nsCOMPtr<nsIDocument> document = GetDocument();
- if (document) {
- document->RemoveMutationObserver(this);
- }
-
- while (!mStyleSheetURLs.IsEmpty()) {
- RemoveOverrideStyleSheet(mStyleSheetURLs[0]);
- }
-
- // Clean up after our anonymous content -- we don't want these nodes to
- // stay around (which they would, since the frames have an owning reference).
- HideAnonymousEditingUIs();
-
- return TextEditor::PreDestroy(aDestroyingFrames);
-}
-
-void
-HTMLEditor::UpdateRootElement()
-{
- // Use the HTML documents body element as the editor root if we didn't
- // get a root element during initialization.
-
- nsCOMPtr<nsIDOMElement> rootElement;
- nsCOMPtr<nsIDOMHTMLElement> bodyElement;
- GetBodyElement(getter_AddRefs(bodyElement));
- if (bodyElement) {
- rootElement = bodyElement;
- } else {
- // If there is no HTML body element,
- // we should use the document root element instead.
- nsCOMPtr<nsIDOMDocument> doc = GetDOMDocument();
- if (doc) {
- doc->GetDocumentElement(getter_AddRefs(rootElement));
- }
- }
-
- mRootElement = do_QueryInterface(rootElement);
-}
-
-already_AddRefed<nsIContent>
-HTMLEditor::FindSelectionRoot(nsINode* aNode)
-{
- NS_PRECONDITION(aNode->IsNodeOfType(nsINode::eDOCUMENT) ||
- aNode->IsNodeOfType(nsINode::eCONTENT),
- "aNode must be content or document node");
-
- nsCOMPtr<nsIDocument> doc = aNode->GetUncomposedDoc();
- if (!doc) {
- return nullptr;
- }
-
- nsCOMPtr<nsIContent> content;
- if (doc->HasFlag(NODE_IS_EDITABLE) || !aNode->IsContent()) {
- content = doc->GetRootElement();
- return content.forget();
- }
- content = aNode->AsContent();
-
- // XXX If we have readonly flag, shouldn't return the element which has
- // contenteditable="true"? However, such case isn't there without chrome
- // permission script.
- if (IsReadonly()) {
- // We still want to allow selection in a readonly editor.
- content = do_QueryInterface(GetRoot());
- return content.forget();
- }
-
- if (!content->HasFlag(NODE_IS_EDITABLE)) {
- // If the content is in read-write state but is not editable itself,
- // return it as the selection root.
- if (content->IsElement() &&
- content->AsElement()->State().HasState(NS_EVENT_STATE_MOZ_READWRITE)) {
- return content.forget();
- }
- return nullptr;
- }
-
- // For non-readonly editors we want to find the root of the editable subtree
- // containing aContent.
- content = content->GetEditingHost();
- return content.forget();
-}
-
-void
-HTMLEditor::CreateEventListeners()
-{
- // Don't create the handler twice
- if (!mEventListener) {
- mEventListener = new HTMLEditorEventListener();
- }
-}
-
-nsresult
-HTMLEditor::InstallEventListeners()
-{
- if (NS_WARN_IF(!IsInitialized()) || NS_WARN_IF(!mEventListener)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // NOTE: HTMLEditor doesn't need to initialize mEventTarget here because
- // the target must be document node and it must be referenced as weak pointer.
-
- HTMLEditorEventListener* listener =
- reinterpret_cast<HTMLEditorEventListener*>(mEventListener.get());
- return listener->Connect(this);
-}
-
-void
-HTMLEditor::RemoveEventListeners()
-{
- if (!IsInitialized()) {
- return;
- }
-
- nsCOMPtr<nsIDOMEventTarget> target = GetDOMEventTarget();
-
- if (target) {
- // Both mMouseMotionListenerP and mResizeEventListenerP can be
- // registerd with other targets than the DOM event receiver that
- // we can reach from here. But nonetheless, unregister the event
- // listeners with the DOM event reveiver (if it's registerd with
- // other targets, it'll get unregisterd once the target goes
- // away).
-
- if (mMouseMotionListenerP) {
- // mMouseMotionListenerP might be registerd either as bubbling or
- // capturing, unregister by both.
- target->RemoveEventListener(NS_LITERAL_STRING("mousemove"),
- mMouseMotionListenerP, false);
- target->RemoveEventListener(NS_LITERAL_STRING("mousemove"),
- mMouseMotionListenerP, true);
- }
-
- if (mResizeEventListenerP) {
- target->RemoveEventListener(NS_LITERAL_STRING("resize"),
- mResizeEventListenerP, false);
- }
- }
-
- mMouseMotionListenerP = nullptr;
- mResizeEventListenerP = nullptr;
-
- TextEditor::RemoveEventListeners();
-}
-
-NS_IMETHODIMP
-HTMLEditor::SetFlags(uint32_t aFlags)
-{
- nsresult rv = TextEditor::SetFlags(aFlags);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Sets mCSSAware to correspond to aFlags. This toggles whether CSS is
- // used to style elements in the editor. Note that the editor is only CSS
- // aware by default in Composer and in the mail editor.
- mCSSAware = !NoCSS() && !IsMailEditor();
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::InitRules()
-{
- if (!mRules) {
- // instantiate the rules for the html editor
- mRules = new HTMLEditRules();
- }
- return mRules->Init(static_cast<TextEditor*>(this));
-}
-
-NS_IMETHODIMP
-HTMLEditor::BeginningOfDocument()
-{
- // XXX Why doesn't this check if the document is alive?
- if (!IsInitialized()) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // Get the selection
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
-
- // Get the root element.
- nsCOMPtr<Element> rootElement = GetRoot();
- if (!rootElement) {
- NS_WARNING("GetRoot() returned a null pointer (mRootElement is null)");
- return NS_OK;
- }
-
- // Find first editable thingy
- bool done = false;
- nsCOMPtr<nsINode> curNode = rootElement.get(), selNode;
- int32_t curOffset = 0, selOffset = 0;
- while (!done) {
- WSRunObject wsObj(this, curNode, curOffset);
- int32_t visOffset = 0;
- WSType visType;
- nsCOMPtr<nsINode> visNode;
- wsObj.NextVisibleNode(curNode, curOffset, address_of(visNode), &visOffset,
- &visType);
- if (visType == WSType::normalWS || visType == WSType::text) {
- selNode = visNode;
- selOffset = visOffset;
- done = true;
- } else if (visType == WSType::br || visType == WSType::special) {
- selNode = visNode->GetParentNode();
- selOffset = selNode ? selNode->IndexOf(visNode) : -1;
- done = true;
- } else if (visType == WSType::otherBlock) {
- // By definition of WSRunObject, a block element terminates a
- // whitespace run. That is, although we are calling a method that is
- // named "NextVisibleNode", the node returned might not be
- // visible/editable!
- //
- // If the given block does not contain any visible/editable items, we
- // want to skip it and continue our search.
-
- if (!IsContainer(visNode)) {
- // However, we were given a block that is not a container. Since the
- // block can not contain anything that's visible, such a block only
- // makes sense if it is visible by itself, like a <hr>. We want to
- // place the caret in front of that block.
- selNode = visNode->GetParentNode();
- selOffset = selNode ? selNode->IndexOf(visNode) : -1;
- done = true;
- } else {
- bool isEmptyBlock;
- if (NS_SUCCEEDED(IsEmptyNode(visNode, &isEmptyBlock)) &&
- isEmptyBlock) {
- // Skip the empty block
- curNode = visNode->GetParentNode();
- curOffset = curNode ? curNode->IndexOf(visNode) : -1;
- curOffset++;
- } else {
- curNode = visNode;
- curOffset = 0;
- }
- // Keep looping
- }
- } else {
- // Else we found nothing useful
- selNode = curNode;
- selOffset = curOffset;
- done = true;
- }
- }
- return selection->Collapse(selNode, selOffset);
-}
-
-nsresult
-HTMLEditor::HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent)
-{
- // NOTE: When you change this method, you should also change:
- // * editor/libeditor/tests/test_htmleditor_keyevent_handling.html
-
- if (IsReadonly() || IsDisabled()) {
- // When we're not editable, the events are handled on EditorBase, so, we can
- // bypass TextEditor.
- return EditorBase::HandleKeyPressEvent(aKeyEvent);
- }
-
- WidgetKeyboardEvent* nativeKeyEvent =
- aKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
- NS_ENSURE_TRUE(nativeKeyEvent, NS_ERROR_UNEXPECTED);
- NS_ASSERTION(nativeKeyEvent->mMessage == eKeyPress,
- "HandleKeyPressEvent gets non-keypress event");
-
- switch (nativeKeyEvent->mKeyCode) {
- case NS_VK_META:
- case NS_VK_WIN:
- case NS_VK_SHIFT:
- case NS_VK_CONTROL:
- case NS_VK_ALT:
- case NS_VK_BACK:
- case NS_VK_DELETE:
- // These keys are handled on EditorBase, so, we can bypass
- // TextEditor.
- return EditorBase::HandleKeyPressEvent(aKeyEvent);
- case NS_VK_TAB: {
- if (IsPlaintextEditor()) {
- // If this works as plain text editor, e.g., mail editor for plain
- // text, should be handled on TextEditor.
- return TextEditor::HandleKeyPressEvent(aKeyEvent);
- }
-
- if (IsTabbable()) {
- return NS_OK; // let it be used for focus switching
- }
-
- if (nativeKeyEvent->IsControl() || nativeKeyEvent->IsAlt() ||
- nativeKeyEvent->IsMeta() || nativeKeyEvent->IsOS()) {
- return NS_OK;
- }
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection && selection->RangeCount(), NS_ERROR_FAILURE);
-
- nsCOMPtr<nsINode> node = selection->GetRangeAt(0)->GetStartParent();
- MOZ_ASSERT(node);
-
- nsCOMPtr<Element> blockParent = GetBlock(*node);
-
- if (!blockParent) {
- break;
- }
-
- bool handled = false;
- nsresult rv = NS_OK;
- if (HTMLEditUtils::IsTableElement(blockParent)) {
- rv = TabInTable(nativeKeyEvent->IsShift(), &handled);
- if (handled) {
- ScrollSelectionIntoView(false);
- }
- } else if (HTMLEditUtils::IsListItem(blockParent)) {
- rv = Indent(nativeKeyEvent->IsShift()
- ? NS_LITERAL_STRING("outdent")
- : NS_LITERAL_STRING("indent"));
- handled = true;
- }
- NS_ENSURE_SUCCESS(rv, rv);
- if (handled) {
- return aKeyEvent->AsEvent()->PreventDefault(); // consumed
- }
- if (nativeKeyEvent->IsShift()) {
- return NS_OK; // don't type text for shift tabs
- }
- aKeyEvent->AsEvent()->PreventDefault();
- return TypedText(NS_LITERAL_STRING("\t"), eTypedText);
- }
- case NS_VK_RETURN:
- if (nativeKeyEvent->IsControl() || nativeKeyEvent->IsAlt() ||
- nativeKeyEvent->IsMeta() || nativeKeyEvent->IsOS()) {
- return NS_OK;
- }
- aKeyEvent->AsEvent()->PreventDefault(); // consumed
- if (nativeKeyEvent->IsShift() && !IsPlaintextEditor()) {
- // only inserts a br node
- return TypedText(EmptyString(), eTypedBR);
- }
- // uses rules to figure out what to insert
- return TypedText(EmptyString(), eTypedBreak);
- }
-
- // NOTE: On some keyboard layout, some characters are inputted with Control
- // key or Alt key, but at that time, widget sets FALSE to these keys.
- if (!nativeKeyEvent->mCharCode || nativeKeyEvent->IsControl() ||
- nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta() ||
- nativeKeyEvent->IsOS()) {
- // we don't PreventDefault() here or keybindings like control-x won't work
- return NS_OK;
- }
- aKeyEvent->AsEvent()->PreventDefault();
- nsAutoString str(nativeKeyEvent->mCharCode);
- return TypedText(str, eTypedText);
-}
-
-/**
- * Returns true if the id represents an element of block type.
- * Can be used to determine if a new paragraph should be started.
- */
-bool
-HTMLEditor::NodeIsBlockStatic(const nsINode* aElement)
-{
- MOZ_ASSERT(aElement);
-
- // We want to treat these as block nodes even though nsHTMLElement says
- // they're not.
- if (aElement->IsAnyOfHTMLElements(nsGkAtoms::body,
- nsGkAtoms::head,
- nsGkAtoms::tbody,
- nsGkAtoms::thead,
- nsGkAtoms::tfoot,
- nsGkAtoms::tr,
- nsGkAtoms::th,
- nsGkAtoms::td,
- nsGkAtoms::dt,
- nsGkAtoms::dd)) {
- return true;
- }
-
- return nsHTMLElement::IsBlock(
- nsHTMLTags::AtomTagToId(aElement->NodeInfo()->NameAtom()));
-}
-
-nsresult
-HTMLEditor::NodeIsBlockStatic(nsIDOMNode* aNode,
- bool* aIsBlock)
-{
- if (!aNode || !aIsBlock) {
- return NS_ERROR_NULL_POINTER;
- }
-
- nsCOMPtr<dom::Element> element = do_QueryInterface(aNode);
- *aIsBlock = element && NodeIsBlockStatic(element);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::NodeIsBlock(nsIDOMNode* aNode,
- bool* aIsBlock)
-{
- return NodeIsBlockStatic(aNode, aIsBlock);
-}
-
-bool
-HTMLEditor::IsBlockNode(nsINode* aNode)
-{
- return aNode && NodeIsBlockStatic(aNode);
-}
-
-// Non-static version for the nsIEditor interface and JavaScript
-NS_IMETHODIMP
-HTMLEditor::SetDocumentTitle(const nsAString& aTitle)
-{
- RefPtr<SetDocumentTitleTransaction> transaction =
- new SetDocumentTitleTransaction();
- NS_ENSURE_TRUE(transaction, NS_ERROR_OUT_OF_MEMORY);
-
- nsresult rv = transaction->Init(this, &aTitle);
- NS_ENSURE_SUCCESS(rv, rv);
-
- //Don't let Rules System change the selection
- AutoTransactionsConserveSelection dontChangeSelection(this);
- return EditorBase::DoTransaction(transaction);
-}
-
-/**
- * GetBlockNodeParent returns enclosing block level ancestor, if any.
- */
-Element*
-HTMLEditor::GetBlockNodeParent(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
-
- nsCOMPtr<nsINode> p = aNode->GetParentNode();
-
- while (p) {
- if (NodeIsBlockStatic(p)) {
- return p->AsElement();
- }
- p = p->GetParentNode();
- }
-
- return nullptr;
-}
-
-nsIDOMNode*
-HTMLEditor::GetBlockNodeParent(nsIDOMNode* aNode)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
-
- if (!node) {
- NS_NOTREACHED("null node passed to GetBlockNodeParent()");
- return nullptr;
- }
-
- return GetAsDOMNode(GetBlockNodeParent(node));
-}
-
-/**
- * Returns the node if it's a block, otherwise GetBlockNodeParent
- */
-Element*
-HTMLEditor::GetBlock(nsINode& aNode)
-{
- if (NodeIsBlockStatic(&aNode)) {
- return aNode.AsElement();
- }
- return GetBlockNodeParent(&aNode);
-}
-
-/**
- * IsNextCharInNodeWhitespace() checks the adjacent content in the same node to
- * see if following selection is whitespace or nbsp.
- */
-void
-HTMLEditor::IsNextCharInNodeWhitespace(nsIContent* aContent,
- int32_t aOffset,
- bool* outIsSpace,
- bool* outIsNBSP,
- nsIContent** outNode,
- int32_t* outOffset)
-{
- MOZ_ASSERT(aContent && outIsSpace && outIsNBSP);
- MOZ_ASSERT((outNode && outOffset) || (!outNode && !outOffset));
- *outIsSpace = false;
- *outIsNBSP = false;
- if (outNode && outOffset) {
- *outNode = nullptr;
- *outOffset = -1;
- }
-
- if (aContent->IsNodeOfType(nsINode::eTEXT) &&
- (uint32_t)aOffset < aContent->Length()) {
- char16_t ch = aContent->GetText()->CharAt(aOffset);
- *outIsSpace = nsCRT::IsAsciiSpace(ch);
- *outIsNBSP = (ch == kNBSP);
- if (outNode && outOffset) {
- NS_IF_ADDREF(*outNode = aContent);
- // yes, this is _past_ the character
- *outOffset = aOffset + 1;
- }
- }
-}
-
-
-/**
- * IsPrevCharInNodeWhitespace() checks the adjacent content in the same node to
- * see if following selection is whitespace.
- */
-void
-HTMLEditor::IsPrevCharInNodeWhitespace(nsIContent* aContent,
- int32_t aOffset,
- bool* outIsSpace,
- bool* outIsNBSP,
- nsIContent** outNode,
- int32_t* outOffset)
-{
- MOZ_ASSERT(aContent && outIsSpace && outIsNBSP);
- MOZ_ASSERT((outNode && outOffset) || (!outNode && !outOffset));
- *outIsSpace = false;
- *outIsNBSP = false;
- if (outNode && outOffset) {
- *outNode = nullptr;
- *outOffset = -1;
- }
-
- if (aContent->IsNodeOfType(nsINode::eTEXT) && aOffset > 0) {
- char16_t ch = aContent->GetText()->CharAt(aOffset - 1);
- *outIsSpace = nsCRT::IsAsciiSpace(ch);
- *outIsNBSP = (ch == kNBSP);
- if (outNode && outOffset) {
- NS_IF_ADDREF(*outNode = aContent);
- *outOffset = aOffset - 1;
- }
- }
-}
-
-bool
-HTMLEditor::IsVisBreak(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
- if (!TextEditUtils::IsBreak(aNode)) {
- return false;
- }
- // Check if there is a later node in block after br
- nsCOMPtr<nsINode> nextNode = GetNextHTMLNode(aNode, true);
- if (nextNode && TextEditUtils::IsBreak(nextNode)) {
- return true;
- }
-
- // A single line break before a block boundary is not displayed, so e.g.
- // foo<p>bar<br></p> and foo<br><p>bar</p> display the same as foo<p>bar</p>.
- // But if there are multiple <br>s in a row, all but the last are visible.
- if (!nextNode) {
- // This break is trailer in block, it's not visible
- return false;
- }
- if (IsBlockNode(nextNode)) {
- // Break is right before a block, it's not visible
- return false;
- }
-
- // If there's an inline node after this one that's not a break, and also a
- // prior break, this break must be visible.
- nsCOMPtr<nsINode> priorNode = GetPriorHTMLNode(aNode, true);
- if (priorNode && TextEditUtils::IsBreak(priorNode)) {
- return true;
- }
-
- // Sigh. We have to use expensive whitespace calculation code to
- // determine what is going on
- int32_t selOffset;
- nsCOMPtr<nsINode> selNode = GetNodeLocation(aNode, &selOffset);
- // Let's look after the break
- selOffset++;
- WSRunObject wsObj(this, selNode, selOffset);
- nsCOMPtr<nsINode> unused;
- int32_t visOffset = 0;
- WSType visType;
- wsObj.NextVisibleNode(selNode, selOffset, address_of(unused),
- &visOffset, &visType);
- if (visType & WSType::block) {
- return false;
- }
-
- return true;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetIsDocumentEditable(bool* aIsDocumentEditable)
-{
- NS_ENSURE_ARG_POINTER(aIsDocumentEditable);
-
- nsCOMPtr<nsIDOMDocument> doc = GetDOMDocument();
- *aIsDocumentEditable = doc && IsModifiable();
-
- return NS_OK;
-}
-
-bool
-HTMLEditor::IsModifiable()
-{
- return !IsReadonly();
-}
-
-NS_IMETHODIMP
-HTMLEditor::UpdateBaseURL()
-{
- nsCOMPtr<nsIDocument> doc = GetDocument();
- NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
-
- // Look for an HTML <base> tag
- RefPtr<nsContentList> nodeList =
- doc->GetElementsByTagName(NS_LITERAL_STRING("base"));
-
- // If no base tag, then set baseURL to the document's URL. This is very
- // important, else relative URLs for links and images are wrong
- if (!nodeList || !nodeList->Item(0)) {
- doc->SetBaseURI(doc->GetDocumentURI());
- }
- return NS_OK;
-}
-
-/**
- * This routine is needed to provide a bottleneck for typing for logging
- * purposes. Can't use HandleKeyPress() (above) for that since it takes
- * a nsIDOMKeyEvent* parameter. So instead we pass enough info through
- * to TypedText() to determine what action to take, but without passing
- * an event.
- */
-NS_IMETHODIMP
-HTMLEditor::TypedText(const nsAString& aString,
- ETypingAction aAction)
-{
- AutoPlaceHolderBatch batch(this, nsGkAtoms::TypingTxnName);
-
- if (aAction == eTypedBR) {
- // only inserts a br node
- nsCOMPtr<nsIDOMNode> brNode;
- return InsertBR(address_of(brNode));
- }
-
- return TextEditor::TypedText(aString, aAction);
-}
-
-NS_IMETHODIMP
-HTMLEditor::TabInTable(bool inIsShift,
- bool* outHandled)
-{
- NS_ENSURE_TRUE(outHandled, NS_ERROR_NULL_POINTER);
- *outHandled = false;
-
- // Find enclosing table cell from selection (cell may be selected element)
- nsCOMPtr<Element> cellElement =
- GetElementOrParentByTagName(NS_LITERAL_STRING("td"), nullptr);
- // Do nothing -- we didn't find a table cell
- NS_ENSURE_TRUE(cellElement, NS_OK);
-
- // find enclosing table
- nsCOMPtr<Element> table = GetEnclosingTable(cellElement);
- NS_ENSURE_TRUE(table, NS_OK);
-
- // advance to next cell
- // first create an iterator over the table
- nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
- nsresult rv = iter->Init(table);
- NS_ENSURE_SUCCESS(rv, rv);
- // position iter at block
- rv = iter->PositionAt(cellElement);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsINode> node;
- do {
- if (inIsShift) {
- iter->Prev();
- } else {
- iter->Next();
- }
-
- node = iter->GetCurrentNode();
-
- if (node && HTMLEditUtils::IsTableCell(node) &&
- GetEnclosingTable(node) == table) {
- CollapseSelectionToDeepestNonTableFirstChild(nullptr, node);
- *outHandled = true;
- return NS_OK;
- }
- } while (!iter->IsDone());
-
- if (!(*outHandled) && !inIsShift) {
- // If we haven't handled it yet, then we must have run off the end of the
- // table. Insert a new row.
- rv = InsertTableRow(1, true);
- NS_ENSURE_SUCCESS(rv, rv);
- *outHandled = true;
- // Put selection in right place. Use table code to get selection and index
- // to new row...
- RefPtr<Selection> selection;
- nsCOMPtr<nsIDOMElement> tblElement, cell;
- int32_t row;
- rv = GetCellContext(getter_AddRefs(selection),
- getter_AddRefs(tblElement),
- getter_AddRefs(cell),
- nullptr, nullptr,
- &row, nullptr);
- NS_ENSURE_SUCCESS(rv, rv);
- // ...so that we can ask for first cell in that row...
- rv = GetCellAt(tblElement, row, 0, getter_AddRefs(cell));
- NS_ENSURE_SUCCESS(rv, rv);
- // ...and then set selection there. (Note that normally you should use
- // CollapseSelectionToDeepestNonTableFirstChild(), but we know cell is an
- // empty new cell, so this works fine)
- if (cell) {
- selection->Collapse(cell, 0);
- }
- }
-
- return NS_OK;
-}
-
-already_AddRefed<Element>
-HTMLEditor::CreateBR(nsINode* aNode,
- int32_t aOffset,
- EDirection aSelect)
-{
- nsCOMPtr<nsIDOMNode> parent = GetAsDOMNode(aNode);
- int32_t offset = aOffset;
- nsCOMPtr<nsIDOMNode> outBRNode;
- // We assume everything is fine if the br is not null, irrespective of retval
- CreateBRImpl(address_of(parent), &offset, address_of(outBRNode), aSelect);
- nsCOMPtr<Element> ret = do_QueryInterface(outBRNode);
- return ret.forget();
-}
-
-NS_IMETHODIMP
-HTMLEditor::CreateBR(nsIDOMNode* aNode,
- int32_t aOffset,
- nsCOMPtr<nsIDOMNode>* outBRNode,
- EDirection aSelect)
-{
- nsCOMPtr<nsIDOMNode> parent = aNode;
- int32_t offset = aOffset;
- return CreateBRImpl(address_of(parent), &offset, outBRNode, aSelect);
-}
-
-void
-HTMLEditor::CollapseSelectionToDeepestNonTableFirstChild(Selection* aSelection,
- nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
-
- RefPtr<Selection> selection = aSelection;
- if (!selection) {
- selection = GetSelection();
- }
- if (!selection) {
- // Nothing to do
- return;
- }
-
- nsCOMPtr<nsINode> node = aNode;
-
- for (nsCOMPtr<nsIContent> child = node->GetFirstChild();
- child;
- child = child->GetFirstChild()) {
- // Stop if we find a table, don't want to go into nested tables
- if (HTMLEditUtils::IsTable(child) || !IsContainer(child)) {
- break;
- }
- node = child;
- }
-
- selection->Collapse(node, 0);
-}
-
-
-/**
- * This is mostly like InsertHTMLWithCharsetAndContext, but we can't use that
- * because it is selection-based and the rules code won't let us edit under the
- * <head> node
- */
-NS_IMETHODIMP
-HTMLEditor::ReplaceHeadContentsWithHTML(const nsAString& aSourceToInsert)
-{
- // don't do any post processing, rules get confused
- AutoRules beginRulesSniffing(this, EditAction::ignore, nsIEditor::eNone);
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- ForceCompositionEnd();
-
- // Do not use AutoRules -- rules code won't let us insert in <head>. Use
- // the head node as a parent and delete/insert directly.
- nsCOMPtr<nsIDocument> document = GetDocument();
- if (NS_WARN_IF(!document)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- RefPtr<nsContentList> nodeList =
- document->GetElementsByTagName(NS_LITERAL_STRING("head"));
- NS_ENSURE_TRUE(nodeList, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsIContent> headNode = nodeList->Item(0);
- NS_ENSURE_TRUE(headNode, NS_ERROR_NULL_POINTER);
-
- // First, make sure there are no return chars in the source. Bad things
- // happen if you insert returns (instead of dom newlines, \n) into an editor
- // document.
- nsAutoString inputString (aSourceToInsert); // hope this does copy-on-write
-
- // Windows linebreaks: Map CRLF to LF:
- inputString.ReplaceSubstring(u"\r\n", u"\n");
-
- // Mac linebreaks: Map any remaining CR to LF:
- inputString.ReplaceSubstring(u"\r", u"\n");
-
- AutoEditBatch beginBatching(this);
-
- // Get the first range in the selection, for context:
- RefPtr<nsRange> range = selection->GetRangeAt(0);
- NS_ENSURE_TRUE(range, NS_ERROR_NULL_POINTER);
-
- ErrorResult err;
- RefPtr<DocumentFragment> docfrag =
- range->CreateContextualFragment(inputString, err);
-
- // XXXX BUG 50965: This is not returning the text between <title>...</title>
- // Special code is needed in JS to handle title anyway, so it doesn't matter!
-
- if (err.Failed()) {
-#ifdef DEBUG
- printf("Couldn't create contextual fragment: error was %X\n",
- err.ErrorCodeAsInt());
-#endif
- return err.StealNSResult();
- }
- NS_ENSURE_TRUE(docfrag, NS_ERROR_NULL_POINTER);
-
- // First delete all children in head
- while (nsCOMPtr<nsIContent> child = headNode->GetFirstChild()) {
- nsresult rv = DeleteNode(child);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // Now insert the new nodes
- int32_t offsetOfNewNode = 0;
-
- // Loop over the contents of the fragment and move into the document
- while (nsCOMPtr<nsIContent> child = docfrag->GetFirstChild()) {
- nsresult rv = InsertNode(*child, *headNode, offsetOfNewNode++);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::RebuildDocumentFromSource(const nsAString& aSourceString)
-{
- ForceCompositionEnd();
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<Element> bodyElement = GetRoot();
- NS_ENSURE_TRUE(bodyElement, NS_ERROR_NULL_POINTER);
-
- // Find where the <body> tag starts.
- nsReadingIterator<char16_t> beginbody;
- nsReadingIterator<char16_t> endbody;
- aSourceString.BeginReading(beginbody);
- aSourceString.EndReading(endbody);
- bool foundbody = CaseInsensitiveFindInReadable(NS_LITERAL_STRING("<body"),
- beginbody, endbody);
-
- nsReadingIterator<char16_t> beginhead;
- nsReadingIterator<char16_t> endhead;
- aSourceString.BeginReading(beginhead);
- aSourceString.EndReading(endhead);
- bool foundhead = CaseInsensitiveFindInReadable(NS_LITERAL_STRING("<head"),
- beginhead, endhead);
- // a valid head appears before the body
- if (foundbody && beginhead.get() > beginbody.get()) {
- foundhead = false;
- }
-
- nsReadingIterator<char16_t> beginclosehead;
- nsReadingIterator<char16_t> endclosehead;
- aSourceString.BeginReading(beginclosehead);
- aSourceString.EndReading(endclosehead);
-
- // Find the index after "<head>"
- bool foundclosehead = CaseInsensitiveFindInReadable(
- NS_LITERAL_STRING("</head>"), beginclosehead, endclosehead);
- // a valid close head appears after a found head
- if (foundhead && beginhead.get() > beginclosehead.get()) {
- foundclosehead = false;
- }
- // a valid close head appears before a found body
- if (foundbody && beginclosehead.get() > beginbody.get()) {
- foundclosehead = false;
- }
-
- // Time to change the document
- AutoEditBatch beginBatching(this);
-
- nsReadingIterator<char16_t> endtotal;
- aSourceString.EndReading(endtotal);
-
- if (foundhead) {
- if (foundclosehead) {
- nsresult rv =
- ReplaceHeadContentsWithHTML(Substring(beginhead, beginclosehead));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else if (foundbody) {
- nsresult rv =
- ReplaceHeadContentsWithHTML(Substring(beginhead, beginbody));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- // XXX Without recourse to some parser/content sink/docshell hackery we
- // don't really know where the head ends and the body begins so we assume
- // that there is no body
- nsresult rv = ReplaceHeadContentsWithHTML(Substring(beginhead, endtotal));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- } else {
- nsReadingIterator<char16_t> begintotal;
- aSourceString.BeginReading(begintotal);
- NS_NAMED_LITERAL_STRING(head, "<head>");
- if (foundclosehead) {
- nsresult rv =
- ReplaceHeadContentsWithHTML(head + Substring(begintotal,
- beginclosehead));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else if (foundbody) {
- nsresult rv = ReplaceHeadContentsWithHTML(head + Substring(begintotal,
- beginbody));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- // XXX Without recourse to some parser/content sink/docshell hackery we
- // don't really know where the head ends and the body begins so we assume
- // that there is no head
- nsresult rv = ReplaceHeadContentsWithHTML(head);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- }
-
- nsresult rv = SelectAll();
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!foundbody) {
- NS_NAMED_LITERAL_STRING(body, "<body>");
- // XXX Without recourse to some parser/content sink/docshell hackery we
- // don't really know where the head ends and the body begins
- if (foundclosehead) {
- // assume body starts after the head ends
- nsresult rv = LoadHTML(body + Substring(endclosehead, endtotal));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else if (foundhead) {
- // assume there is no body
- nsresult rv = LoadHTML(body);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- // assume there is no head, the entire source is body
- nsresult rv = LoadHTML(body + aSourceString);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
-
- nsCOMPtr<Element> divElement =
- CreateElementWithDefaults(NS_LITERAL_STRING("div"));
- NS_ENSURE_TRUE(divElement, NS_ERROR_FAILURE);
-
- CloneAttributes(bodyElement, divElement);
-
- return BeginningOfDocument();
- }
-
- rv = LoadHTML(Substring(beginbody, endtotal));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Now we must copy attributes user might have edited on the <body> tag
- // because InsertHTML (actually, CreateContextualFragment()) will never
- // return a body node in the DOM fragment
-
- // We already know where "<body" begins
- nsReadingIterator<char16_t> beginclosebody = beginbody;
- nsReadingIterator<char16_t> endclosebody;
- aSourceString.EndReading(endclosebody);
- if (!FindInReadable(NS_LITERAL_STRING(">"), beginclosebody, endclosebody)) {
- return NS_ERROR_FAILURE;
- }
-
- // Truncate at the end of the body tag. Kludge of the year: fool the parser
- // by replacing "body" with "div" so we get a node
- nsAutoString bodyTag;
- bodyTag.AssignLiteral("<div ");
- bodyTag.Append(Substring(endbody, endclosebody));
-
- RefPtr<nsRange> range = selection->GetRangeAt(0);
- NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
-
- ErrorResult erv;
- RefPtr<DocumentFragment> docfrag =
- range->CreateContextualFragment(bodyTag, erv);
- NS_ENSURE_TRUE(!erv.Failed(), erv.StealNSResult());
- NS_ENSURE_TRUE(docfrag, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsIContent> child = docfrag->GetFirstChild();
- NS_ENSURE_TRUE(child && child->IsElement(), NS_ERROR_NULL_POINTER);
-
- // Copy all attributes from the div child to current body element
- CloneAttributes(bodyElement, child->AsElement());
-
- // place selection at first editable content
- return BeginningOfDocument();
-}
-
-void
-HTMLEditor::NormalizeEOLInsertPosition(nsINode* firstNodeToInsert,
- nsCOMPtr<nsIDOMNode>* insertParentNode,
- int32_t* insertOffset)
-{
- /*
- This function will either correct the position passed in,
- or leave the position unchanged.
-
- When the (first) item to insert is a block level element,
- and our insertion position is after the last visible item in a line,
- i.e. the insertion position is just before a visible line break <br>,
- we want to skip to the position just after the line break (see bug 68767)
-
- However, our logic to detect whether we should skip or not
- needs to be more clever.
- We must not skip when the caret appears to be positioned at the beginning
- of a block, in that case skipping the <br> would not insert the <br>
- at the caret position, but after the current empty line.
-
- So we have several cases to test:
-
- 1) We only ever want to skip, if the next visible thing after the current position is a break
-
- 2) We do not want to skip if there is no previous visible thing at all
- That is detected if the call to PriorVisibleNode gives us an offset of zero.
- Because PriorVisibleNode always positions after the prior node, we would
- see an offset > 0, if there were a prior node.
-
- 3) We do not want to skip, if both the next and the previous visible things are breaks.
-
- 4) We do not want to skip if the previous visible thing is in a different block
- than the insertion position.
- */
-
- if (!IsBlockNode(firstNodeToInsert)) {
- return;
- }
-
- WSRunObject wsObj(this, *insertParentNode, *insertOffset);
- nsCOMPtr<nsINode> nextVisNode, prevVisNode;
- int32_t nextVisOffset=0;
- WSType nextVisType;
- int32_t prevVisOffset=0;
- WSType prevVisType;
-
- nsCOMPtr<nsINode> parent(do_QueryInterface(*insertParentNode));
- wsObj.NextVisibleNode(parent, *insertOffset, address_of(nextVisNode), &nextVisOffset, &nextVisType);
- if (!nextVisNode) {
- return;
- }
-
- if (!(nextVisType & WSType::br)) {
- return;
- }
-
- wsObj.PriorVisibleNode(parent, *insertOffset, address_of(prevVisNode), &prevVisOffset, &prevVisType);
- if (!prevVisNode) {
- return;
- }
-
- if (prevVisType & WSType::br) {
- return;
- }
-
- if (prevVisType & WSType::thisBlock) {
- return;
- }
-
- int32_t brOffset=0;
- nsCOMPtr<nsIDOMNode> brNode = GetNodeLocation(GetAsDOMNode(nextVisNode), &brOffset);
-
- *insertParentNode = brNode;
- *insertOffset = brOffset + 1;
-}
-
-NS_IMETHODIMP
-HTMLEditor::InsertElementAtSelection(nsIDOMElement* aElement,
- bool aDeleteSelection)
-{
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- nsCOMPtr<Element> element = do_QueryInterface(aElement);
- NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
-
- ForceCompositionEnd();
- AutoEditBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::insertElement,
- nsIEditor::eNext);
-
- RefPtr<Selection> selection = GetSelection();
- if (!selection) {
- return NS_ERROR_FAILURE;
- }
-
- // hand off to the rules system, see if it has anything to say about this
- bool cancel, handled;
- TextRulesInfo ruleInfo(EditAction::insertElement);
- ruleInfo.insertElement = aElement;
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- if (cancel || NS_FAILED(rv)) {
- return rv;
- }
-
- if (!handled) {
- if (aDeleteSelection) {
- if (!IsBlockNode(element)) {
- // E.g., inserting an image. In this case we don't need to delete any
- // inline wrappers before we do the insertion. Otherwise we let
- // DeleteSelectionAndPrepareToCreateNode do the deletion for us, which
- // calls DeleteSelection with aStripWrappers = eStrip.
- rv = DeleteSelection(nsIEditor::eNone, nsIEditor::eNoStrip);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- nsresult rv = DeleteSelectionAndPrepareToCreateNode();
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // If deleting, selection will be collapsed.
- // so if not, we collapse it
- if (!aDeleteSelection) {
- // Named Anchor is a special case,
- // We collapse to insert element BEFORE the selection
- // For all other tags, we insert AFTER the selection
- if (HTMLEditUtils::IsNamedAnchor(node)) {
- selection->CollapseToStart();
- } else {
- selection->CollapseToEnd();
- }
- }
-
- nsCOMPtr<nsIDOMNode> parentSelectedNode;
- int32_t offsetForInsert;
- rv = selection->GetAnchorNode(getter_AddRefs(parentSelectedNode));
- // XXX: ERROR_HANDLING bad XPCOM usage
- if (NS_SUCCEEDED(rv) &&
- NS_SUCCEEDED(selection->GetAnchorOffset(&offsetForInsert)) &&
- parentSelectedNode) {
- // Adjust position based on the node we are going to insert.
- NormalizeEOLInsertPosition(element, address_of(parentSelectedNode),
- &offsetForInsert);
-
- rv = InsertNodeAtPoint(node, address_of(parentSelectedNode),
- &offsetForInsert, false);
- NS_ENSURE_SUCCESS(rv, rv);
- // Set caret after element, but check for special case
- // of inserting table-related elements: set in first cell instead
- if (!SetCaretInTableCell(aElement)) {
- rv = SetCaretAfterElement(aElement);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // check for inserting a whole table at the end of a block. If so insert a br after it.
- if (HTMLEditUtils::IsTable(node)) {
- bool isLast;
- rv = IsLastEditableChild(node, &isLast);
- NS_ENSURE_SUCCESS(rv, rv);
- if (isLast) {
- nsCOMPtr<nsIDOMNode> brNode;
- rv = CreateBR(parentSelectedNode, offsetForInsert + 1,
- address_of(brNode));
- NS_ENSURE_SUCCESS(rv, rv);
- selection->Collapse(parentSelectedNode, offsetForInsert+1);
- }
- }
- }
- }
- rv = rules->DidDoAction(selection, &ruleInfo, rv);
- return rv;
-}
-
-
-/**
- * InsertNodeAtPoint() attempts to insert aNode into the document, at a point
- * specified by {*ioParent,*ioOffset}. Checks with strict dtd to see if
- * containment is allowed. If not allowed, will attempt to find a parent in
- * the parent hierarchy of *ioParent that will accept aNode as a child. If
- * such a parent is found, will split the document tree from
- * {*ioParent,*ioOffset} up to parent, and then insert aNode.
- * ioParent & ioOffset are then adjusted to point to the actual location that
- * aNode was inserted at. aNoEmptyNodes specifies if the splitting process
- * is allowed to reslt in empty nodes.
- *
- * @param aNode Node to insert.
- * @param ioParent Insertion parent.
- * @param ioOffset Insertion offset.
- * @param aNoEmptyNodes Splitting can result in empty nodes?
- */
-nsresult
-HTMLEditor::InsertNodeAtPoint(nsIDOMNode* aNode,
- nsCOMPtr<nsIDOMNode>* ioParent,
- int32_t* ioOffset,
- bool aNoEmptyNodes)
-{
- nsCOMPtr<nsIContent> node = do_QueryInterface(aNode);
- NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
- NS_ENSURE_TRUE(ioParent, NS_ERROR_NULL_POINTER);
- NS_ENSURE_TRUE(*ioParent, NS_ERROR_NULL_POINTER);
- NS_ENSURE_TRUE(ioOffset, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsIContent> parent = do_QueryInterface(*ioParent);
- NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
- nsCOMPtr<nsIContent> topChild = parent;
- nsCOMPtr<nsIContent> origParent = parent;
-
- // Search up the parent chain to find a suitable container
- while (!CanContain(*parent, *node)) {
- // If the current parent is a root (body or table element)
- // then go no further - we can't insert
- if (parent->IsHTMLElement(nsGkAtoms::body) ||
- HTMLEditUtils::IsTableElement(parent)) {
- return NS_ERROR_FAILURE;
- }
- // Get the next parent
- NS_ENSURE_TRUE(parent->GetParentNode(), NS_ERROR_FAILURE);
- if (!IsEditable(parent->GetParentNode())) {
- // There's no suitable place to put the node in this editing host. Maybe
- // someone is trying to put block content in a span. So just put it
- // where we were originally asked.
- parent = topChild = origParent;
- break;
- }
- topChild = parent;
- parent = parent->GetParent();
- }
- if (parent != topChild) {
- // we need to split some levels above the original selection parent
- int32_t offset = SplitNodeDeep(*topChild, *origParent, *ioOffset,
- aNoEmptyNodes ? EmptyContainers::no
- : EmptyContainers::yes);
- NS_ENSURE_STATE(offset != -1);
- *ioParent = GetAsDOMNode(parent);
- *ioOffset = offset;
- }
- // Now we can insert the new node
- return InsertNode(*node, *parent, *ioOffset);
-}
-
-NS_IMETHODIMP
-HTMLEditor::SelectElement(nsIDOMElement* aElement)
-{
- nsCOMPtr<Element> element = do_QueryInterface(aElement);
- NS_ENSURE_STATE(element || !aElement);
-
- // Must be sure that element is contained in the document body
- if (!IsDescendantOfEditorRoot(element)) {
- return NS_ERROR_NULL_POINTER;
- }
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- nsCOMPtr<nsIDOMNode>parent;
- nsresult rv = aElement->GetParentNode(getter_AddRefs(parent));
- if (NS_SUCCEEDED(rv) && parent) {
- int32_t offsetInParent = GetChildOffset(aElement, parent);
-
- // Collapse selection to just before desired element,
- rv = selection->Collapse(parent, offsetInParent);
- if (NS_SUCCEEDED(rv)) {
- // then extend it to just after
- rv = selection->Extend(parent, offsetInParent + 1);
- }
- }
- return rv;
-}
-
-NS_IMETHODIMP
-HTMLEditor::SetCaretAfterElement(nsIDOMElement* aElement)
-{
- nsCOMPtr<Element> element = do_QueryInterface(aElement);
- NS_ENSURE_STATE(element || !aElement);
-
- // Be sure the element is contained in the document body
- if (!aElement || !IsDescendantOfEditorRoot(element)) {
- return NS_ERROR_NULL_POINTER;
- }
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- nsCOMPtr<nsIDOMNode>parent;
- nsresult rv = aElement->GetParentNode(getter_AddRefs(parent));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
- int32_t offsetInParent = GetChildOffset(aElement, parent);
- // Collapse selection to just after desired element,
- return selection->Collapse(parent, offsetInParent + 1);
-}
-
-NS_IMETHODIMP
-HTMLEditor::SetParagraphFormat(const nsAString& aParagraphFormat)
-{
- nsAutoString tag; tag.Assign(aParagraphFormat);
- ToLowerCase(tag);
- if (tag.EqualsLiteral("dd") || tag.EqualsLiteral("dt")) {
- return MakeDefinitionItem(tag);
- }
- return InsertBasicBlock(tag);
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetParagraphState(bool* aMixed,
- nsAString& outFormat)
-{
- if (!mRules) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- NS_ENSURE_TRUE(aMixed, NS_ERROR_NULL_POINTER);
- RefPtr<HTMLEditRules> htmlRules =
- static_cast<HTMLEditRules*>(mRules.get());
-
- return htmlRules->GetParagraphState(aMixed, outFormat);
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetBackgroundColorState(bool* aMixed,
- nsAString& aOutColor)
-{
- if (IsCSSEnabled()) {
- // if we are in CSS mode, we have to check if the containing block defines
- // a background color
- return GetCSSBackgroundColorState(aMixed, aOutColor, true);
- }
- // in HTML mode, we look only at page's background
- return GetHTMLBackgroundColorState(aMixed, aOutColor);
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetHighlightColorState(bool* aMixed,
- nsAString& aOutColor)
-{
- *aMixed = false;
- aOutColor.AssignLiteral("transparent");
- if (!IsCSSEnabled()) {
- return NS_OK;
- }
-
- // in CSS mode, text background can be added by the Text Highlight button
- // we need to query the background of the selection without looking for
- // the block container of the ranges in the selection
- return GetCSSBackgroundColorState(aMixed, aOutColor, false);
-}
-
-nsresult
-HTMLEditor::GetCSSBackgroundColorState(bool* aMixed,
- nsAString& aOutColor,
- bool aBlockLevel)
-{
- NS_ENSURE_TRUE(aMixed, NS_ERROR_NULL_POINTER);
- *aMixed = false;
- // the default background color is transparent
- aOutColor.AssignLiteral("transparent");
-
- // get selection
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_STATE(selection && selection->GetRangeAt(0));
-
- // get selection location
- nsCOMPtr<nsINode> parent = selection->GetRangeAt(0)->GetStartParent();
- int32_t offset = selection->GetRangeAt(0)->StartOffset();
- NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
-
- // is the selection collapsed?
- nsCOMPtr<nsINode> nodeToExamine;
- if (selection->Collapsed() || IsTextNode(parent)) {
- // we want to look at the parent and ancestors
- nodeToExamine = parent;
- } else {
- // otherwise we want to look at the first editable node after
- // {parent,offset} and its ancestors for divs with alignment on them
- nodeToExamine = parent->GetChildAt(offset);
- //GetNextNode(parent, offset, true, address_of(nodeToExamine));
- }
-
- NS_ENSURE_TRUE(nodeToExamine, NS_ERROR_NULL_POINTER);
-
- if (aBlockLevel) {
- // we are querying the block background (and not the text background), let's
- // climb to the block container
- nsCOMPtr<Element> blockParent = GetBlock(*nodeToExamine);
- NS_ENSURE_TRUE(blockParent, NS_OK);
-
- // Make sure to not walk off onto the Document node
- do {
- // retrieve the computed style of background-color for blockParent
- mCSSEditUtils->GetComputedProperty(*blockParent,
- *nsGkAtoms::backgroundColor,
- aOutColor);
- blockParent = blockParent->GetParentElement();
- // look at parent if the queried color is transparent and if the node to
- // examine is not the root of the document
- } while (aOutColor.EqualsLiteral("transparent") && blockParent);
- if (aOutColor.EqualsLiteral("transparent")) {
- // we have hit the root of the document and the color is still transparent !
- // Grumble... Let's look at the default background color because that's the
- // color we are looking for
- mCSSEditUtils->GetDefaultBackgroundColor(aOutColor);
- }
- }
- else {
- // no, we are querying the text background for the Text Highlight button
- if (IsTextNode(nodeToExamine)) {
- // if the node of interest is a text node, let's climb a level
- nodeToExamine = nodeToExamine->GetParentNode();
- }
- do {
- // is the node to examine a block ?
- if (NodeIsBlockStatic(nodeToExamine)) {
- // yes it is a block; in that case, the text background color is transparent
- aOutColor.AssignLiteral("transparent");
- break;
- } else {
- // no, it's not; let's retrieve the computed style of background-color for the
- // node to examine
- mCSSEditUtils->GetComputedProperty(*nodeToExamine,
- *nsGkAtoms::backgroundColor,
- aOutColor);
- if (!aOutColor.EqualsLiteral("transparent")) {
- break;
- }
- }
- nodeToExamine = nodeToExamine->GetParentNode();
- } while ( aOutColor.EqualsLiteral("transparent") && nodeToExamine );
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetHTMLBackgroundColorState(bool* aMixed,
- nsAString& aOutColor)
-{
- //TODO: We don't handle "mixed" correctly!
- NS_ENSURE_TRUE(aMixed, NS_ERROR_NULL_POINTER);
- *aMixed = false;
- aOutColor.Truncate();
-
- nsCOMPtr<nsIDOMElement> domElement;
- int32_t selectedCount;
- nsAutoString tagName;
- nsresult rv = GetSelectedOrParentTableElement(tagName,
- &selectedCount,
- getter_AddRefs(domElement));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<dom::Element> element = do_QueryInterface(domElement);
-
- while (element) {
- // We are in a cell or selected table
- element->GetAttr(kNameSpaceID_None, nsGkAtoms::bgcolor, aOutColor);
-
- // Done if we have a color explicitly set
- if (!aOutColor.IsEmpty()) {
- return NS_OK;
- }
-
- // Once we hit the body, we're done
- if (element->IsHTMLElement(nsGkAtoms::body)) {
- return NS_OK;
- }
-
- // No color is set, but we need to report visible color inherited
- // from nested cells/tables, so search up parent chain
- element = element->GetParentElement();
- }
-
- // If no table or cell found, get page body
- dom::Element* bodyElement = GetRoot();
- NS_ENSURE_TRUE(bodyElement, NS_ERROR_NULL_POINTER);
-
- bodyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::bgcolor, aOutColor);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetListState(bool* aMixed,
- bool* aOL,
- bool* aUL,
- bool* aDL)
-{
- if (!mRules) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- NS_ENSURE_TRUE(aMixed && aOL && aUL && aDL, NS_ERROR_NULL_POINTER);
- RefPtr<HTMLEditRules> htmlRules =
- static_cast<HTMLEditRules*>(mRules.get());
-
- return htmlRules->GetListState(aMixed, aOL, aUL, aDL);
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetListItemState(bool* aMixed,
- bool* aLI,
- bool* aDT,
- bool* aDD)
-{
- if (!mRules) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- NS_ENSURE_TRUE(aMixed && aLI && aDT && aDD, NS_ERROR_NULL_POINTER);
-
- RefPtr<HTMLEditRules> htmlRules =
- static_cast<HTMLEditRules*>(mRules.get());
-
- return htmlRules->GetListItemState(aMixed, aLI, aDT, aDD);
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetAlignment(bool* aMixed,
- nsIHTMLEditor::EAlignment* aAlign)
-{
- if (!mRules) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- NS_ENSURE_TRUE(aMixed && aAlign, NS_ERROR_NULL_POINTER);
- RefPtr<HTMLEditRules> htmlRules =
- static_cast<HTMLEditRules*>(mRules.get());
-
- return htmlRules->GetAlignment(aMixed, aAlign);
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetIndentState(bool* aCanIndent,
- bool* aCanOutdent)
-{
- if (!mRules) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- NS_ENSURE_TRUE(aCanIndent && aCanOutdent, NS_ERROR_NULL_POINTER);
-
- RefPtr<HTMLEditRules> htmlRules =
- static_cast<HTMLEditRules*>(mRules.get());
-
- return htmlRules->GetIndentState(aCanIndent, aCanOutdent);
-}
-
-NS_IMETHODIMP
-HTMLEditor::MakeOrChangeList(const nsAString& aListType,
- bool entireList,
- const nsAString& aBulletType)
-{
- if (!mRules) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- bool cancel, handled;
-
- AutoEditBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::makeList, nsIEditor::eNext);
-
- // pre-process
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- TextRulesInfo ruleInfo(EditAction::makeList);
- ruleInfo.blockType = &aListType;
- ruleInfo.entireList = entireList;
- ruleInfo.bulletType = &aBulletType;
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- if (cancel || NS_FAILED(rv)) {
- return rv;
- }
-
- if (!handled) {
- // Find out if the selection is collapsed:
- bool isCollapsed = selection->Collapsed();
-
- NS_ENSURE_TRUE(selection->GetRangeAt(0) &&
- selection->GetRangeAt(0)->GetStartParent() &&
- selection->GetRangeAt(0)->GetStartParent()->IsContent(),
- NS_ERROR_FAILURE);
- OwningNonNull<nsIContent> node =
- *selection->GetRangeAt(0)->GetStartParent()->AsContent();
- int32_t offset = selection->GetRangeAt(0)->StartOffset();
-
- if (isCollapsed) {
- // have to find a place to put the list
- nsCOMPtr<nsIContent> parent = node;
- nsCOMPtr<nsIContent> topChild = node;
-
- nsCOMPtr<nsIAtom> listAtom = NS_Atomize(aListType);
- while (!CanContainTag(*parent, *listAtom)) {
- topChild = parent;
- parent = parent->GetParent();
- }
-
- if (parent != node) {
- // we need to split up to the child of parent
- offset = SplitNodeDeep(*topChild, *node, offset);
- NS_ENSURE_STATE(offset != -1);
- }
-
- // make a list
- nsCOMPtr<Element> newList = CreateNode(listAtom, parent, offset);
- NS_ENSURE_STATE(newList);
- // make a list item
- nsCOMPtr<Element> newItem = CreateNode(nsGkAtoms::li, newList, 0);
- NS_ENSURE_STATE(newItem);
- rv = selection->Collapse(newItem, 0);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- return rules->DidDoAction(selection, &ruleInfo, rv);
-}
-
-NS_IMETHODIMP
-HTMLEditor::RemoveList(const nsAString& aListType)
-{
- if (!mRules) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- bool cancel, handled;
-
- AutoEditBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::removeList, nsIEditor::eNext);
-
- // pre-process
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- TextRulesInfo ruleInfo(EditAction::removeList);
- if (aListType.LowerCaseEqualsLiteral("ol")) {
- ruleInfo.bOrdered = true;
- } else {
- ruleInfo.bOrdered = false;
- }
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- if (cancel || NS_FAILED(rv)) {
- return rv;
- }
-
- // no default behavior for this yet. what would it mean?
-
- return rules->DidDoAction(selection, &ruleInfo, rv);
-}
-
-nsresult
-HTMLEditor::MakeDefinitionItem(const nsAString& aItemType)
-{
- if (!mRules) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- bool cancel, handled;
-
- AutoEditBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::makeDefListItem,
- nsIEditor::eNext);
-
- // pre-process
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- TextRulesInfo ruleInfo(EditAction::makeDefListItem);
- ruleInfo.blockType = &aItemType;
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- if (cancel || NS_FAILED(rv)) {
- return rv;
- }
-
- if (!handled) {
- // todo: no default for now. we count on rules to handle it.
- }
-
- return rules->DidDoAction(selection, &ruleInfo, rv);
-}
-
-nsresult
-HTMLEditor::InsertBasicBlock(const nsAString& aBlockType)
-{
- if (!mRules) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- bool cancel, handled;
-
- AutoEditBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::makeBasicBlock,
- nsIEditor::eNext);
-
- // pre-process
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- TextRulesInfo ruleInfo(EditAction::makeBasicBlock);
- ruleInfo.blockType = &aBlockType;
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- if (cancel || NS_FAILED(rv)) {
- return rv;
- }
-
- if (!handled) {
- // Find out if the selection is collapsed:
- bool isCollapsed = selection->Collapsed();
-
- NS_ENSURE_TRUE(selection->GetRangeAt(0) &&
- selection->GetRangeAt(0)->GetStartParent() &&
- selection->GetRangeAt(0)->GetStartParent()->IsContent(),
- NS_ERROR_FAILURE);
- OwningNonNull<nsIContent> node =
- *selection->GetRangeAt(0)->GetStartParent()->AsContent();
- int32_t offset = selection->GetRangeAt(0)->StartOffset();
-
- if (isCollapsed) {
- // have to find a place to put the block
- nsCOMPtr<nsIContent> parent = node;
- nsCOMPtr<nsIContent> topChild = node;
-
- nsCOMPtr<nsIAtom> blockAtom = NS_Atomize(aBlockType);
- while (!CanContainTag(*parent, *blockAtom)) {
- NS_ENSURE_TRUE(parent->GetParent(), NS_ERROR_FAILURE);
- topChild = parent;
- parent = parent->GetParent();
- }
-
- if (parent != node) {
- // we need to split up to the child of parent
- offset = SplitNodeDeep(*topChild, *node, offset);
- NS_ENSURE_STATE(offset != -1);
- }
-
- // make a block
- nsCOMPtr<Element> newBlock = CreateNode(blockAtom, parent, offset);
- NS_ENSURE_STATE(newBlock);
-
- // reposition selection to inside the block
- rv = selection->Collapse(newBlock, 0);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- return rules->DidDoAction(selection, &ruleInfo, rv);
-}
-
-NS_IMETHODIMP
-HTMLEditor::Indent(const nsAString& aIndent)
-{
- if (!mRules) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- bool cancel, handled;
- EditAction opID = EditAction::indent;
- if (aIndent.LowerCaseEqualsLiteral("outdent")) {
- opID = EditAction::outdent;
- }
- AutoEditBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, opID, nsIEditor::eNext);
-
- // pre-process
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- TextRulesInfo ruleInfo(opID);
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- if (cancel || NS_FAILED(rv)) {
- return rv;
- }
-
- if (!handled) {
- // Do default - insert a blockquote node if selection collapsed
- bool isCollapsed = selection->Collapsed();
-
- NS_ENSURE_TRUE(selection->GetRangeAt(0) &&
- selection->GetRangeAt(0)->GetStartParent() &&
- selection->GetRangeAt(0)->GetStartParent()->IsContent(),
- NS_ERROR_FAILURE);
- OwningNonNull<nsIContent> node =
- *selection->GetRangeAt(0)->GetStartParent()->AsContent();
- int32_t offset = selection->GetRangeAt(0)->StartOffset();
-
- if (aIndent.EqualsLiteral("indent")) {
- if (isCollapsed) {
- // have to find a place to put the blockquote
- nsCOMPtr<nsIContent> parent = node;
- nsCOMPtr<nsIContent> topChild = node;
- while (!CanContainTag(*parent, *nsGkAtoms::blockquote)) {
- NS_ENSURE_TRUE(parent->GetParent(), NS_ERROR_FAILURE);
- topChild = parent;
- parent = parent->GetParent();
- }
-
- if (parent != node) {
- // we need to split up to the child of parent
- offset = SplitNodeDeep(*topChild, *node, offset);
- NS_ENSURE_STATE(offset != -1);
- }
-
- // make a blockquote
- nsCOMPtr<Element> newBQ = CreateNode(nsGkAtoms::blockquote, parent, offset);
- NS_ENSURE_STATE(newBQ);
- // put a space in it so layout will draw the list item
- rv = selection->Collapse(newBQ, 0);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = InsertText(NS_LITERAL_STRING(" "));
- NS_ENSURE_SUCCESS(rv, rv);
- // reposition selection to before the space character
- NS_ENSURE_STATE(selection->GetRangeAt(0));
- rv = selection->Collapse(selection->GetRangeAt(0)->GetStartParent(), 0);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- }
- return rules->DidDoAction(selection, &ruleInfo, rv);
-}
-
-//TODO: IMPLEMENT ALIGNMENT!
-
-NS_IMETHODIMP
-HTMLEditor::Align(const nsAString& aAlignType)
-{
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- AutoEditBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::align, nsIEditor::eNext);
-
- bool cancel, handled;
-
- // Find out if the selection is collapsed:
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- TextRulesInfo ruleInfo(EditAction::align);
- ruleInfo.alignType = &aAlignType;
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- if (cancel || NS_FAILED(rv)) {
- return rv;
- }
-
- return rules->DidDoAction(selection, &ruleInfo, rv);
-}
-
-already_AddRefed<Element>
-HTMLEditor::GetElementOrParentByTagName(const nsAString& aTagName,
- nsINode* aNode)
-{
- MOZ_ASSERT(!aTagName.IsEmpty());
-
- nsCOMPtr<nsINode> node = aNode;
- if (!node) {
- // If no node supplied, get it from anchor node of current selection
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, nullptr);
-
- nsCOMPtr<nsINode> anchorNode = selection->GetAnchorNode();
- NS_ENSURE_TRUE(anchorNode, nullptr);
-
- // Try to get the actual selected node
- if (anchorNode->HasChildNodes() && anchorNode->IsContent()) {
- node = anchorNode->GetChildAt(selection->AnchorOffset());
- }
- // Anchor node is probably a text node - just use that
- if (!node) {
- node = anchorNode;
- }
- }
-
- nsCOMPtr<Element> current;
- if (node->IsElement()) {
- current = node->AsElement();
- } else if (node->GetParentElement()) {
- current = node->GetParentElement();
- } else {
- // Neither aNode nor its parent is an element, so no ancestor is
- MOZ_ASSERT(!node->GetParentNode() ||
- !node->GetParentNode()->GetParentNode());
- return nullptr;
- }
-
- nsAutoString tagName(aTagName);
- ToLowerCase(tagName);
- bool getLink = IsLinkTag(tagName);
- bool getNamedAnchor = IsNamedAnchorTag(tagName);
- if (getLink || getNamedAnchor) {
- tagName.Assign('a');
- }
- bool findTableCell = tagName.EqualsLiteral("td");
- bool findList = tagName.EqualsLiteral("list");
-
- for (; current; current = current->GetParentElement()) {
- // Test if we have a link (an anchor with href set)
- if ((getLink && HTMLEditUtils::IsLink(current)) ||
- (getNamedAnchor && HTMLEditUtils::IsNamedAnchor(current))) {
- return current.forget();
- }
- if (findList) {
- // Match "ol", "ul", or "dl" for lists
- if (HTMLEditUtils::IsList(current)) {
- return current.forget();
- }
- } else if (findTableCell) {
- // Table cells are another special case: match either "td" or "th"
- if (HTMLEditUtils::IsTableCell(current)) {
- return current.forget();
- }
- } else if (current->NodeName().Equals(tagName,
- nsCaseInsensitiveStringComparator())) {
- return current.forget();
- }
-
- // Stop searching if parent is a body tag. Note: Originally used IsRoot to
- // stop at table cells, but that's too messy when you are trying to find
- // the parent table
- if (current->GetParentElement() &&
- current->GetParentElement()->IsHTMLElement(nsGkAtoms::body)) {
- break;
- }
- }
-
- return nullptr;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetElementOrParentByTagName(const nsAString& aTagName,
- nsIDOMNode* aNode,
- nsIDOMElement** aReturn)
-{
- NS_ENSURE_TRUE(!aTagName.IsEmpty(), NS_ERROR_NULL_POINTER);
- NS_ENSURE_TRUE(aReturn, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- nsCOMPtr<Element> parent =
- GetElementOrParentByTagName(aTagName, node);
- nsCOMPtr<nsIDOMElement> ret = do_QueryInterface(parent);
-
- if (!ret) {
- return NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND;
- }
-
- ret.forget(aReturn);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetSelectedElement(const nsAString& aTagName,
- nsIDOMElement** aReturn)
-{
- NS_ENSURE_TRUE(aReturn , NS_ERROR_NULL_POINTER);
-
- // default is null - no element found
- *aReturn = nullptr;
-
- // First look for a single element in selection
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- bool bNodeFound = false;
- bool isCollapsed = selection->Collapsed();
-
- nsAutoString domTagName;
- nsAutoString TagName(aTagName);
- ToLowerCase(TagName);
- // Empty string indicates we should match any element tag
- bool anyTag = (TagName.IsEmpty());
- bool isLinkTag = IsLinkTag(TagName);
- bool isNamedAnchorTag = IsNamedAnchorTag(TagName);
-
- nsCOMPtr<nsIDOMElement> selectedElement;
- RefPtr<nsRange> range = selection->GetRangeAt(0);
- NS_ENSURE_STATE(range);
-
- nsCOMPtr<nsIDOMNode> startParent;
- nsresult rv = range->GetStartContainer(getter_AddRefs(startParent));
- NS_ENSURE_SUCCESS(rv, rv);
- uint32_t startOffset = range->StartOffset();
-
- nsCOMPtr<nsIDOMNode> endParent;
- rv = range->GetEndContainer(getter_AddRefs(endParent));
- NS_ENSURE_SUCCESS(rv, rv);
- uint32_t endOffset = range->EndOffset();
-
- // Optimization for a single selected element
- if (startParent && startParent == endParent && endOffset - startOffset == 1) {
- nsCOMPtr<nsIDOMNode> selectedNode =
- GetChildAt(startParent, static_cast<int32_t>(startOffset));
- NS_ENSURE_SUCCESS(rv, NS_OK);
- if (selectedNode) {
- selectedNode->GetNodeName(domTagName);
- ToLowerCase(domTagName);
-
- // Test for appropriate node type requested
- if (anyTag || (TagName == domTagName) ||
- (isLinkTag && HTMLEditUtils::IsLink(selectedNode)) ||
- (isNamedAnchorTag && HTMLEditUtils::IsNamedAnchor(selectedNode))) {
- bNodeFound = true;
- selectedElement = do_QueryInterface(selectedNode);
- }
- }
- }
-
- if (!bNodeFound) {
- if (isLinkTag) {
- // Link tag is a special case - we return the anchor node
- // found for any selection that is totally within a link,
- // included a collapsed selection (just a caret in a link)
- nsCOMPtr<nsIDOMNode> anchorNode;
- rv = selection->GetAnchorNode(getter_AddRefs(anchorNode));
- NS_ENSURE_SUCCESS(rv, rv);
- int32_t anchorOffset = -1;
- if (anchorNode) {
- selection->GetAnchorOffset(&anchorOffset);
- }
-
- nsCOMPtr<nsIDOMNode> focusNode;
- rv = selection->GetFocusNode(getter_AddRefs(focusNode));
- NS_ENSURE_SUCCESS(rv, rv);
- int32_t focusOffset = -1;
- if (focusNode) {
- selection->GetFocusOffset(&focusOffset);
- }
-
- // Link node must be the same for both ends of selection
- if (NS_SUCCEEDED(rv) && anchorNode) {
- nsCOMPtr<nsIDOMElement> parentLinkOfAnchor;
- rv = GetElementOrParentByTagName(NS_LITERAL_STRING("href"),
- anchorNode,
- getter_AddRefs(parentLinkOfAnchor));
- // XXX: ERROR_HANDLING can parentLinkOfAnchor be null?
- if (NS_SUCCEEDED(rv) && parentLinkOfAnchor) {
- if (isCollapsed) {
- // We have just a caret in the link
- bNodeFound = true;
- } else if (focusNode) {
- // Link node must be the same for both ends of selection.
- nsCOMPtr<nsIDOMElement> parentLinkOfFocus;
- rv = GetElementOrParentByTagName(NS_LITERAL_STRING("href"),
- focusNode,
- getter_AddRefs(parentLinkOfFocus));
- if (NS_SUCCEEDED(rv) && parentLinkOfFocus == parentLinkOfAnchor) {
- bNodeFound = true;
- }
- }
-
- // We found a link node parent
- if (bNodeFound) {
- // GetElementOrParentByTagName addref'd this, so we don't need to do it here
- *aReturn = parentLinkOfAnchor;
- NS_IF_ADDREF(*aReturn);
- return NS_OK;
- }
- } else if (anchorOffset >= 0) {
- // Check if link node is the only thing selected
- nsCOMPtr<nsIDOMNode> anchorChild;
- anchorChild = GetChildAt(anchorNode,anchorOffset);
- if (anchorChild && HTMLEditUtils::IsLink(anchorChild) &&
- anchorNode == focusNode && focusOffset == anchorOffset + 1) {
- selectedElement = do_QueryInterface(anchorChild);
- bNodeFound = true;
- }
- }
- }
- }
-
- if (!isCollapsed) {
- RefPtr<nsRange> currange = selection->GetRangeAt(0);
- if (currange) {
- nsCOMPtr<nsIContentIterator> iter =
- do_CreateInstance("@mozilla.org/content/post-content-iterator;1",
- &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- iter->Init(currange);
- // loop through the content iterator for each content node
- while (!iter->IsDone()) {
- // Query interface to cast nsIContent to nsIDOMNode
- // then get tagType to compare to aTagName
- // Clone node of each desired type and append it to the aDomFrag
- selectedElement = do_QueryInterface(iter->GetCurrentNode());
- if (selectedElement) {
- // If we already found a node, then we have another element,
- // thus there's not just one element selected
- if (bNodeFound) {
- bNodeFound = false;
- break;
- }
-
- selectedElement->GetNodeName(domTagName);
- ToLowerCase(domTagName);
-
- if (anyTag) {
- // Get name of first selected element
- selectedElement->GetTagName(TagName);
- ToLowerCase(TagName);
- anyTag = false;
- }
-
- // The "A" tag is a pain,
- // used for both link(href is set) and "Named Anchor"
- nsCOMPtr<nsIDOMNode> selectedNode = do_QueryInterface(selectedElement);
- if ((isLinkTag &&
- HTMLEditUtils::IsLink(selectedNode)) ||
- (isNamedAnchorTag &&
- HTMLEditUtils::IsNamedAnchor(selectedNode))) {
- bNodeFound = true;
- } else if (TagName == domTagName) { // All other tag names are handled here
- bNodeFound = true;
- }
- if (!bNodeFound) {
- // Check if node we have is really part of the selection???
- break;
- }
- }
- iter->Next();
- }
- } else {
- // Should never get here?
- isCollapsed = true;
- NS_WARNING("isCollapsed was FALSE, but no elements found in selection\n");
- }
- }
- }
-
- if (!bNodeFound) {
- return NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND;
- }
-
- *aReturn = selectedElement;
- if (selectedElement) {
- // Getters must addref
- NS_ADDREF(*aReturn);
- }
- return rv;
-}
-
-already_AddRefed<Element>
-HTMLEditor::CreateElementWithDefaults(const nsAString& aTagName)
-{
- MOZ_ASSERT(!aTagName.IsEmpty());
-
- nsAutoString tagName(aTagName);
- ToLowerCase(tagName);
- nsAutoString realTagName;
-
- if (IsLinkTag(tagName) || IsNamedAnchorTag(tagName)) {
- realTagName.Assign('a');
- } else {
- realTagName = tagName;
- }
- // We don't use editor's CreateElement because we don't want to go through
- // the transaction system
-
- // New call to use instead to get proper HTML element, bug 39919
- nsCOMPtr<nsIAtom> realTagAtom = NS_Atomize(realTagName);
- RefPtr<Element> newElement = CreateHTMLContent(realTagAtom);
- if (!newElement) {
- return nullptr;
- }
-
- // Mark the new element dirty, so it will be formatted
- ErrorResult rv;
- newElement->SetAttribute(NS_LITERAL_STRING("_moz_dirty"), EmptyString(), rv);
-
- // Set default values for new elements
- if (tagName.EqualsLiteral("table")) {
- newElement->SetAttribute(NS_LITERAL_STRING("cellpadding"),
- NS_LITERAL_STRING("2"), rv);
- if (NS_WARN_IF(rv.Failed())) {
- rv.SuppressException();
- return nullptr;
- }
- newElement->SetAttribute(NS_LITERAL_STRING("cellspacing"),
- NS_LITERAL_STRING("2"), rv);
- if (NS_WARN_IF(rv.Failed())) {
- rv.SuppressException();
- return nullptr;
- }
- newElement->SetAttribute(NS_LITERAL_STRING("border"),
- NS_LITERAL_STRING("1"), rv);
- if (NS_WARN_IF(rv.Failed())) {
- rv.SuppressException();
- return nullptr;
- }
- } else if (tagName.EqualsLiteral("td")) {
- nsresult rv =
- SetAttributeOrEquivalent(
- newElement, nsGkAtoms::valign, NS_LITERAL_STRING("top"), true);
- NS_ENSURE_SUCCESS(rv, nullptr);
- }
- // ADD OTHER TAGS HERE
-
- return newElement.forget();
-}
-
-NS_IMETHODIMP
-HTMLEditor::CreateElementWithDefaults(const nsAString& aTagName,
- nsIDOMElement** aReturn)
-{
- NS_ENSURE_TRUE(!aTagName.IsEmpty() && aReturn, NS_ERROR_NULL_POINTER);
- *aReturn = nullptr;
-
- nsCOMPtr<Element> newElement = CreateElementWithDefaults(aTagName);
- nsCOMPtr<nsIDOMElement> ret = do_QueryInterface(newElement);
- NS_ENSURE_TRUE(ret, NS_ERROR_FAILURE);
-
- ret.forget(aReturn);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::InsertLinkAroundSelection(nsIDOMElement* aAnchorElement)
-{
- NS_ENSURE_TRUE(aAnchorElement, NS_ERROR_NULL_POINTER);
-
- // We must have a real selection
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- if (selection->Collapsed()) {
- NS_WARNING("InsertLinkAroundSelection called but there is no selection!!!");
- return NS_OK;
- }
-
- // Be sure we were given an anchor element
- nsCOMPtr<nsIDOMHTMLAnchorElement> anchor = do_QueryInterface(aAnchorElement);
- if (!anchor) {
- return NS_OK;
- }
-
- nsAutoString href;
- nsresult rv = anchor->GetHref(href);
- NS_ENSURE_SUCCESS(rv, rv);
- if (href.IsEmpty()) {
- return NS_OK;
- }
-
- AutoEditBatch beginBatching(this);
-
- // Set all attributes found on the supplied anchor element
- nsCOMPtr<nsIDOMMozNamedAttrMap> attrMap;
- aAnchorElement->GetAttributes(getter_AddRefs(attrMap));
- NS_ENSURE_TRUE(attrMap, NS_ERROR_FAILURE);
-
- uint32_t count;
- attrMap->GetLength(&count);
- nsAutoString name, value;
-
- for (uint32_t i = 0; i < count; ++i) {
- nsCOMPtr<nsIDOMAttr> attribute;
- rv = attrMap->Item(i, getter_AddRefs(attribute));
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (attribute) {
- // We must clear the string buffers
- // because GetName, GetValue appends to previous string!
- name.Truncate();
- value.Truncate();
-
- rv = attribute->GetName(name);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = attribute->GetValue(value);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = SetInlineProperty(nsGkAtoms::a, name, value);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::SetHTMLBackgroundColor(const nsAString& aColor)
-{
- MOZ_ASSERT(IsInitialized(), "The HTMLEditor hasn't been initialized yet");
-
- // Find a selected or enclosing table element to set background on
- nsCOMPtr<nsIDOMElement> element;
- int32_t selectedCount;
- nsAutoString tagName;
- nsresult rv = GetSelectedOrParentTableElement(tagName, &selectedCount,
- getter_AddRefs(element));
- NS_ENSURE_SUCCESS(rv, rv);
-
- bool setColor = !aColor.IsEmpty();
-
- NS_NAMED_LITERAL_STRING(bgcolor, "bgcolor");
- if (element) {
- if (selectedCount > 0) {
- // Traverse all selected cells
- nsCOMPtr<nsIDOMElement> cell;
- rv = GetFirstSelectedCell(nullptr, getter_AddRefs(cell));
- if (NS_SUCCEEDED(rv) && cell) {
- while (cell) {
- rv = setColor ? SetAttribute(cell, bgcolor, aColor) :
- RemoveAttribute(cell, bgcolor);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- GetNextSelectedCell(nullptr, getter_AddRefs(cell));
- }
- return NS_OK;
- }
- }
- // If we failed to find a cell, fall through to use originally-found element
- } else {
- // No table element -- set the background color on the body tag
- element = do_QueryInterface(GetRoot());
- NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
- }
- // Use the editor method that goes through the transaction system
- return setColor ? SetAttribute(element, bgcolor, aColor) :
- RemoveAttribute(element, bgcolor);
-}
-
-NS_IMETHODIMP
-HTMLEditor::SetBodyAttribute(const nsAString& aAttribute,
- const nsAString& aValue)
-{
- // TODO: Check selection for Cell, Row, Column or table and do color on appropriate level
-
- MOZ_ASSERT(IsInitialized(), "The HTMLEditor hasn't been initialized yet");
-
- // Set the background color attribute on the body tag
- nsCOMPtr<nsIDOMElement> bodyElement = do_QueryInterface(GetRoot());
- NS_ENSURE_TRUE(bodyElement, NS_ERROR_NULL_POINTER);
-
- // Use the editor method that goes through the transaction system
- return SetAttribute(bodyElement, aAttribute, aValue);
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetLinkedObjects(nsIArray** aNodeList)
-{
- NS_ENSURE_TRUE(aNodeList, NS_ERROR_NULL_POINTER);
-
- nsresult rv;
- nsCOMPtr<nsIMutableArray> nodes = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- nsCOMPtr<nsIContentIterator> iter =
- do_CreateInstance("@mozilla.org/content/post-content-iterator;1", &rv);
- NS_ENSURE_TRUE(iter, NS_ERROR_NULL_POINTER);
- if (NS_SUCCEEDED(rv)) {
- nsCOMPtr<nsIDocument> doc = GetDocument();
- NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
-
- iter->Init(doc->GetRootElement());
-
- // loop through the content iterator for each content node
- while (!iter->IsDone()) {
- nsCOMPtr<nsIDOMNode> node (do_QueryInterface(iter->GetCurrentNode()));
- if (node) {
- // Let nsURIRefObject make the hard decisions:
- nsCOMPtr<nsIURIRefObject> refObject;
- rv = NS_NewHTMLURIRefObject(getter_AddRefs(refObject), node);
- if (NS_SUCCEEDED(rv)) {
- nodes->AppendElement(refObject, false);
- }
- }
- iter->Next();
- }
- }
-
- nodes.forget(aNodeList);
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-HTMLEditor::AddStyleSheet(const nsAString& aURL)
-{
- // Enable existing sheet if already loaded.
- if (EnableExistingStyleSheet(aURL)) {
- return NS_OK;
- }
-
- // Lose the previously-loaded sheet so there's nothing to replace
- // This pattern is different from Override methods because
- // we must wait to remove mLastStyleSheetURL and add new sheet
- // at the same time (in StyleSheetLoaded callback) so they are undoable together
- mLastStyleSheetURL.Truncate();
- return ReplaceStyleSheet(aURL);
-}
-
-NS_IMETHODIMP
-HTMLEditor::ReplaceStyleSheet(const nsAString& aURL)
-{
- // Enable existing sheet if already loaded.
- if (EnableExistingStyleSheet(aURL)) {
- // Disable last sheet if not the same as new one
- if (!mLastStyleSheetURL.IsEmpty() && !mLastStyleSheetURL.Equals(aURL)) {
- return EnableStyleSheet(mLastStyleSheetURL, false);
- }
- return NS_OK;
- }
-
- // Make sure the pres shell doesn't disappear during the load.
- if (NS_WARN_IF(!IsInitialized())) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
- NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
-
- nsCOMPtr<nsIURI> uaURI;
- nsresult rv = NS_NewURI(getter_AddRefs(uaURI), aURL);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return ps->GetDocument()->CSSLoader()->
- LoadSheet(uaURI, false, nullptr, EmptyCString(), this);
-}
-
-NS_IMETHODIMP
-HTMLEditor::RemoveStyleSheet(const nsAString& aURL)
-{
- RefPtr<StyleSheet> sheet = GetStyleSheetForURL(aURL);
- NS_ENSURE_TRUE(sheet, NS_ERROR_UNEXPECTED);
-
- RefPtr<RemoveStyleSheetTransaction> transaction;
- nsresult rv =
- CreateTxnForRemoveStyleSheet(sheet, getter_AddRefs(transaction));
- if (!transaction) {
- rv = NS_ERROR_NULL_POINTER;
- }
- if (NS_SUCCEEDED(rv)) {
- rv = DoTransaction(transaction);
- if (NS_SUCCEEDED(rv)) {
- mLastStyleSheetURL.Truncate(); // forget it
- }
- // Remove it from our internal list
- rv = RemoveStyleSheetFromList(aURL);
- }
-
- return rv;
-}
-
-
-NS_IMETHODIMP
-HTMLEditor::AddOverrideStyleSheet(const nsAString& aURL)
-{
- // Enable existing sheet if already loaded.
- if (EnableExistingStyleSheet(aURL)) {
- return NS_OK;
- }
-
- // Make sure the pres shell doesn't disappear during the load.
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
- NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
-
- nsCOMPtr<nsIURI> uaURI;
- nsresult rv = NS_NewURI(getter_AddRefs(uaURI), aURL);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // We MUST ONLY load synchronous local files (no @import)
- // XXXbz Except this will actually try to load remote files
- // synchronously, of course..
- RefPtr<StyleSheet> sheet;
- // Editor override style sheets may want to style Gecko anonymous boxes
- rv = ps->GetDocument()->CSSLoader()->
- LoadSheetSync(uaURI, mozilla::css::eAgentSheetFeatures, true,
- &sheet);
-
- // Synchronous loads should ALWAYS return completed
- NS_ENSURE_TRUE(sheet, NS_ERROR_NULL_POINTER);
-
- // Add the override style sheet
- // (This checks if already exists)
- ps->AddOverrideStyleSheet(sheet);
-
- ps->RestyleForCSSRuleChanges();
-
- // Save as the last-loaded sheet
- mLastOverrideStyleSheetURL = aURL;
-
- //Add URL and style sheet to our lists
- return AddNewStyleSheetToList(aURL, sheet);
-}
-
-NS_IMETHODIMP
-HTMLEditor::ReplaceOverrideStyleSheet(const nsAString& aURL)
-{
- // Enable existing sheet if already loaded.
- if (EnableExistingStyleSheet(aURL)) {
- // Disable last sheet if not the same as new one
- if (!mLastOverrideStyleSheetURL.IsEmpty() &&
- !mLastOverrideStyleSheetURL.Equals(aURL)) {
- return EnableStyleSheet(mLastOverrideStyleSheetURL, false);
- }
- return NS_OK;
- }
- // Remove the previous sheet
- if (!mLastOverrideStyleSheetURL.IsEmpty()) {
- RemoveOverrideStyleSheet(mLastOverrideStyleSheetURL);
- }
- return AddOverrideStyleSheet(aURL);
-}
-
-// Do NOT use transaction system for override style sheets
-NS_IMETHODIMP
-HTMLEditor::RemoveOverrideStyleSheet(const nsAString& aURL)
-{
- RefPtr<StyleSheet> sheet = GetStyleSheetForURL(aURL);
-
- // Make sure we remove the stylesheet from our internal list in all
- // cases.
- nsresult rv = RemoveStyleSheetFromList(aURL);
-
- NS_ENSURE_TRUE(sheet, NS_OK); /// Don't fail if sheet not found
-
- if (NS_WARN_IF(!IsInitialized())) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
- NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
-
- ps->RemoveOverrideStyleSheet(sheet);
- ps->RestyleForCSSRuleChanges();
-
- // Remove it from our internal list
- return rv;
-}
-
-NS_IMETHODIMP
-HTMLEditor::EnableStyleSheet(const nsAString& aURL,
- bool aEnable)
-{
- RefPtr<StyleSheet> sheet = GetStyleSheetForURL(aURL);
- NS_ENSURE_TRUE(sheet, NS_OK); // Don't fail if sheet not found
-
- // Ensure the style sheet is owned by our document.
- nsCOMPtr<nsIDocument> document = GetDocument();
- sheet->SetAssociatedDocument(document, StyleSheet::NotOwnedByDocument);
-
- if (sheet->IsServo()) {
- // XXXheycam ServoStyleSheets don't support being enabled/disabled yet.
- NS_ERROR("stylo: ServoStyleSheets can't be disabled yet");
- return NS_ERROR_FAILURE;
- }
- return sheet->AsGecko()->SetDisabled(!aEnable);
-}
-
-bool
-HTMLEditor::EnableExistingStyleSheet(const nsAString& aURL)
-{
- RefPtr<StyleSheet> sheet = GetStyleSheetForURL(aURL);
-
- // Enable sheet if already loaded.
- if (!sheet) {
- return false;
- }
-
- // Ensure the style sheet is owned by our document.
- nsCOMPtr<nsIDocument> document = GetDocument();
- sheet->SetAssociatedDocument(document, StyleSheet::NotOwnedByDocument);
-
- if (sheet->IsServo()) {
- // XXXheycam ServoStyleSheets don't support being enabled/disabled yet.
- NS_ERROR("stylo: ServoStyleSheets can't be disabled yet");
- return true;
- }
- sheet->AsGecko()->SetDisabled(false);
- return true;
-}
-
-nsresult
-HTMLEditor::AddNewStyleSheetToList(const nsAString& aURL,
- StyleSheet* aStyleSheet)
-{
- uint32_t countSS = mStyleSheets.Length();
- uint32_t countU = mStyleSheetURLs.Length();
-
- if (countSS != countU) {
- return NS_ERROR_UNEXPECTED;
- }
-
- if (!mStyleSheetURLs.AppendElement(aURL)) {
- return NS_ERROR_UNEXPECTED;
- }
-
- return mStyleSheets.AppendElement(aStyleSheet) ? NS_OK : NS_ERROR_UNEXPECTED;
-}
-
-nsresult
-HTMLEditor::RemoveStyleSheetFromList(const nsAString& aURL)
-{
- // is it already in the list?
- size_t foundIndex;
- foundIndex = mStyleSheetURLs.IndexOf(aURL);
- if (foundIndex == mStyleSheetURLs.NoIndex) {
- return NS_ERROR_FAILURE;
- }
-
- // Attempt both removals; if one fails there's not much we can do.
- mStyleSheets.RemoveElementAt(foundIndex);
- mStyleSheetURLs.RemoveElementAt(foundIndex);
-
- return NS_OK;
-}
-
-StyleSheet*
-HTMLEditor::GetStyleSheetForURL(const nsAString& aURL)
-{
- // is it already in the list?
- size_t foundIndex;
- foundIndex = mStyleSheetURLs.IndexOf(aURL);
- if (foundIndex == mStyleSheetURLs.NoIndex) {
- return nullptr;
- }
-
- MOZ_ASSERT(mStyleSheets[foundIndex]);
- return mStyleSheets[foundIndex];
-}
-
-void
-HTMLEditor::GetURLForStyleSheet(StyleSheet* aStyleSheet,
- nsAString& aURL)
-{
- // is it already in the list?
- int32_t foundIndex = mStyleSheets.IndexOf(aStyleSheet);
-
- // Don't fail if we don't find it in our list
- if (foundIndex == -1) {
- return;
- }
-
- // Found it in the list!
- aURL = mStyleSheetURLs[foundIndex];
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetEmbeddedObjects(nsIArray** aNodeList)
-{
- NS_ENSURE_TRUE(aNodeList, NS_ERROR_NULL_POINTER);
-
- nsresult rv;
- nsCOMPtr<nsIMutableArray> nodes = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIContentIterator> iter =
- do_CreateInstance("@mozilla.org/content/post-content-iterator;1", &rv);
- NS_ENSURE_TRUE(iter, NS_ERROR_NULL_POINTER);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIDocument> doc = GetDocument();
- NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
-
- iter->Init(doc->GetRootElement());
-
- // Loop through the content iterator for each content node.
- while (!iter->IsDone()) {
- nsINode* node = iter->GetCurrentNode();
- if (node->IsElement()) {
- dom::Element* element = node->AsElement();
-
- // See if it's an image or an embed and also include all links.
- // Let mail decide which link to send or not
- if (element->IsAnyOfHTMLElements(nsGkAtoms::img, nsGkAtoms::embed,
- nsGkAtoms::a) ||
- (element->IsHTMLElement(nsGkAtoms::body) &&
- element->HasAttr(kNameSpaceID_None, nsGkAtoms::background))) {
- nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(node);
- nodes->AppendElement(domNode, false);
- }
- }
- iter->Next();
- }
-
- nodes.forget(aNodeList);
- return rv;
-}
-
-NS_IMETHODIMP
-HTMLEditor::DeleteSelectionImpl(EDirection aAction,
- EStripWrappers aStripWrappers)
-{
- MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
-
- nsresult rv = EditorBase::DeleteSelectionImpl(aAction, aStripWrappers);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // If we weren't asked to strip any wrappers, we're done.
- if (aStripWrappers == eNoStrip) {
- return NS_OK;
- }
-
- RefPtr<Selection> selection = GetSelection();
- // Just checking that the selection itself is collapsed doesn't seem to work
- // right in the multi-range case
- NS_ENSURE_STATE(selection);
- NS_ENSURE_STATE(selection->GetAnchorFocusRange());
- NS_ENSURE_STATE(selection->GetAnchorFocusRange()->Collapsed());
-
- NS_ENSURE_STATE(selection->GetAnchorNode()->IsContent());
- nsCOMPtr<nsIContent> content = selection->GetAnchorNode()->AsContent();
-
- // Don't strip wrappers if this is the only wrapper in the block. Then we'll
- // add a <br> later, so it won't be an empty wrapper in the end.
- nsCOMPtr<nsIContent> blockParent = content;
- while (blockParent && !IsBlockNode(blockParent)) {
- blockParent = blockParent->GetParent();
- }
- if (!blockParent) {
- return NS_OK;
- }
- bool emptyBlockParent;
- rv = IsEmptyNode(blockParent, &emptyBlockParent);
- NS_ENSURE_SUCCESS(rv, rv);
- if (emptyBlockParent) {
- return NS_OK;
- }
-
- if (content && !IsBlockNode(content) && !content->Length() &&
- content->IsEditable() && content != content->GetEditingHost()) {
- while (content->GetParent() && !IsBlockNode(content->GetParent()) &&
- content->GetParent()->Length() == 1 &&
- content->GetParent()->IsEditable() &&
- content->GetParent() != content->GetEditingHost()) {
- content = content->GetParent();
- }
- rv = DeleteNode(content);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::DeleteNode(nsINode* aNode)
-{
- nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode);
- return DeleteNode(node);
-}
-
-NS_IMETHODIMP
-HTMLEditor::DeleteNode(nsIDOMNode* aNode)
-{
- // do nothing if the node is read-only
- nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
- if (!IsModifiableNode(aNode) && !IsMozEditorBogusNode(content)) {
- return NS_ERROR_FAILURE;
- }
-
- return EditorBase::DeleteNode(aNode);
-}
-
-nsresult
-HTMLEditor::DeleteText(nsGenericDOMDataNode& aCharData,
- uint32_t aOffset,
- uint32_t aLength)
-{
- // Do nothing if the node is read-only
- if (!IsModifiableNode(&aCharData)) {
- return NS_ERROR_FAILURE;
- }
-
- return EditorBase::DeleteText(aCharData, aOffset, aLength);
-}
-
-nsresult
-HTMLEditor::InsertTextImpl(const nsAString& aStringToInsert,
- nsCOMPtr<nsINode>* aInOutNode,
- int32_t* aInOutOffset,
- nsIDocument* aDoc)
-{
- // Do nothing if the node is read-only
- if (!IsModifiableNode(*aInOutNode)) {
- return NS_ERROR_FAILURE;
- }
-
- return EditorBase::InsertTextImpl(aStringToInsert, aInOutNode, aInOutOffset,
- aDoc);
-}
-
-void
-HTMLEditor::ContentAppended(nsIDocument* aDocument,
- nsIContent* aContainer,
- nsIContent* aFirstNewContent,
- int32_t aIndexInContainer)
-{
- DoContentInserted(aDocument, aContainer, aFirstNewContent, aIndexInContainer,
- eAppended);
-}
-
-void
-HTMLEditor::ContentInserted(nsIDocument* aDocument,
- nsIContent* aContainer,
- nsIContent* aChild,
- int32_t aIndexInContainer)
-{
- DoContentInserted(aDocument, aContainer, aChild, aIndexInContainer,
- eInserted);
-}
-
-bool
-HTMLEditor::IsInObservedSubtree(nsIDocument* aDocument,
- nsIContent* aContainer,
- nsIContent* aChild)
-{
- if (!aChild) {
- return false;
- }
-
- Element* root = GetRoot();
- // To be super safe here, check both ChromeOnlyAccess and GetBindingParent.
- // That catches (also unbound) native anonymous content, XBL and ShadowDOM.
- if (root &&
- (root->ChromeOnlyAccess() != aChild->ChromeOnlyAccess() ||
- root->GetBindingParent() != aChild->GetBindingParent())) {
- return false;
- }
-
- return !aChild->ChromeOnlyAccess() && !aChild->GetBindingParent();
-}
-
-void
-HTMLEditor::DoContentInserted(nsIDocument* aDocument,
- nsIContent* aContainer,
- nsIContent* aChild,
- int32_t aIndexInContainer,
- InsertedOrAppended aInsertedOrAppended)
-{
- if (!IsInObservedSubtree(aDocument, aContainer, aChild)) {
- return;
- }
-
- nsCOMPtr<nsIHTMLEditor> kungFuDeathGrip(this);
-
- if (ShouldReplaceRootElement()) {
- UpdateRootElement();
- nsContentUtils::AddScriptRunner(NewRunnableMethod(
- this, &HTMLEditor::NotifyRootChanged));
- }
- // We don't need to handle our own modifications
- else if (!mAction && (aContainer ? aContainer->IsEditable() : aDocument->IsEditable())) {
- if (IsMozEditorBogusNode(aChild)) {
- // Ignore insertion of the bogus node
- return;
- }
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
- rules->DocumentModified();
-
- // Update spellcheck for only the newly-inserted node (bug 743819)
- if (mInlineSpellChecker) {
- RefPtr<nsRange> range = new nsRange(aChild);
- int32_t endIndex = aIndexInContainer + 1;
- if (aInsertedOrAppended == eAppended) {
- // Count all the appended nodes
- nsIContent* sibling = aChild->GetNextSibling();
- while (sibling) {
- endIndex++;
- sibling = sibling->GetNextSibling();
- }
- }
- nsresult rv = range->SetStartAndEnd(aContainer, aIndexInContainer,
- aContainer, endIndex);
- if (NS_SUCCEEDED(rv)) {
- mInlineSpellChecker->SpellCheckRange(range);
- }
- }
- }
-}
-
-void
-HTMLEditor::ContentRemoved(nsIDocument* aDocument,
- nsIContent* aContainer,
- nsIContent* aChild,
- int32_t aIndexInContainer,
- nsIContent* aPreviousSibling)
-{
- if (!IsInObservedSubtree(aDocument, aContainer, aChild)) {
- return;
- }
-
- nsCOMPtr<nsIHTMLEditor> kungFuDeathGrip(this);
-
- if (SameCOMIdentity(aChild, mRootElement)) {
- mRootElement = nullptr;
- nsContentUtils::AddScriptRunner(NewRunnableMethod(
- this, &HTMLEditor::NotifyRootChanged));
- }
- // We don't need to handle our own modifications
- else if (!mAction && (aContainer ? aContainer->IsEditable() : aDocument->IsEditable())) {
- if (aChild && IsMozEditorBogusNode(aChild)) {
- // Ignore removal of the bogus node
- return;
- }
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
- rules->DocumentModified();
- }
-}
-
-NS_IMETHODIMP_(bool)
-HTMLEditor::IsModifiableNode(nsIDOMNode* aNode)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- return IsModifiableNode(node);
-}
-
-bool
-HTMLEditor::IsModifiableNode(nsINode* aNode)
-{
- return !aNode || aNode->IsEditable();
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetIsSelectionEditable(bool* aIsSelectionEditable)
-{
- MOZ_ASSERT(aIsSelectionEditable);
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- nsINode* anchorNode = selection->GetAnchorNode();
- nsINode* focusNode = selection->GetFocusNode();
- if (!anchorNode || !focusNode) {
- return NS_ERROR_FAILURE;
- }
-
- // Per the editing spec as of June 2012: we have to have a selection whose
- // start and end nodes are editable, and which share an ancestor editing
- // host. (Bug 766387.)
- *aIsSelectionEditable = selection->RangeCount() &&
- anchorNode->IsEditable() &&
- focusNode->IsEditable();
-
- if (*aIsSelectionEditable) {
- nsINode* commonAncestor =
- selection->GetAnchorFocusRange()->GetCommonAncestor();
- while (commonAncestor && !commonAncestor->IsEditable()) {
- commonAncestor = commonAncestor->GetParentNode();
- }
- if (!commonAncestor) {
- // No editable common ancestor
- *aIsSelectionEditable = false;
- }
- }
-
- return NS_OK;
-}
-
-static nsresult
-SetSelectionAroundHeadChildren(Selection* aSelection,
- nsCOMPtr<nsIDocument>& aDocument)
-{
- MOZ_ASSERT(aDocument);
-
- // Set selection around <head> node
- dom::Element* headNode = aDocument->GetHeadElement();
- NS_ENSURE_STATE(headNode);
-
- // Collapse selection to before first child of the head,
- nsresult rv = aSelection->CollapseNative(headNode, 0);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Then extend it to just after.
- uint32_t childCount = headNode->GetChildCount();
- return aSelection->ExtendNative(headNode, childCount + 1);
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetHeadContentsAsHTML(nsAString& aOutputString)
-{
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- // Save current selection
- AutoSelectionRestorer selectionRestorer(selection, this);
-
- nsCOMPtr<nsIDocument> document = GetDocument();
- if (NS_WARN_IF(!document)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- nsresult rv = SetSelectionAroundHeadChildren(selection, document);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = OutputToString(NS_LITERAL_STRING("text/html"),
- nsIDocumentEncoder::OutputSelectionOnly,
- aOutputString);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- // Selection always includes <body></body>,
- // so terminate there
- nsReadingIterator<char16_t> findIter,endFindIter;
- aOutputString.BeginReading(findIter);
- aOutputString.EndReading(endFindIter);
- //counting on our parser to always lower case!!!
- if (CaseInsensitiveFindInReadable(NS_LITERAL_STRING("<body"),
- findIter, endFindIter)) {
- nsReadingIterator<char16_t> beginIter;
- aOutputString.BeginReading(beginIter);
- int32_t offset = Distance(beginIter, findIter);//get the distance
-
- nsWritingIterator<char16_t> writeIter;
- aOutputString.BeginWriting(writeIter);
- // Ensure the string ends in a newline
- char16_t newline ('\n');
- findIter.advance(-1);
- if (!offset || (offset > 0 && (*findIter) != newline)) {
- writeIter.advance(offset);
- *writeIter = newline;
- aOutputString.Truncate(offset+1);
- }
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::DebugUnitTests(int32_t* outNumTests,
- int32_t* outNumTestsFailed)
-{
-#ifdef DEBUG
- NS_ENSURE_TRUE(outNumTests && outNumTestsFailed, NS_ERROR_NULL_POINTER);
-
- TextEditorTest *tester = new TextEditorTest();
- NS_ENSURE_TRUE(tester, NS_ERROR_OUT_OF_MEMORY);
-
- tester->Run(this, outNumTests, outNumTestsFailed);
- delete tester;
- return NS_OK;
-#else
- return NS_ERROR_NOT_IMPLEMENTED;
-#endif
-}
-
-NS_IMETHODIMP
-HTMLEditor::StyleSheetLoaded(StyleSheet* aSheet,
- bool aWasAlternate,
- nsresult aStatus)
-{
- nsresult rv = NS_OK;
- AutoEditBatch batchIt(this);
-
- if (!mLastStyleSheetURL.IsEmpty())
- RemoveStyleSheet(mLastStyleSheetURL);
-
- RefPtr<AddStyleSheetTransaction> transaction;
- rv = CreateTxnForAddStyleSheet(aSheet, getter_AddRefs(transaction));
- if (!transaction) {
- rv = NS_ERROR_NULL_POINTER;
- }
- if (NS_SUCCEEDED(rv)) {
- rv = DoTransaction(transaction);
- if (NS_SUCCEEDED(rv)) {
- // Get the URI, then url spec from the sheet
- nsAutoCString spec;
- rv = aSheet->GetSheetURI()->GetSpec(spec);
-
- if (NS_SUCCEEDED(rv)) {
- // Save it so we can remove before applying the next one
- mLastStyleSheetURL.AssignWithConversion(spec.get());
-
- // Also save in our arrays of urls and sheets
- AddNewStyleSheetToList(mLastStyleSheetURL, aSheet);
- }
- }
- }
-
- return NS_OK;
-}
-
-/**
- * All editor operations which alter the doc should be prefaced
- * with a call to StartOperation, naming the action and direction.
- */
-NS_IMETHODIMP
-HTMLEditor::StartOperation(EditAction opID,
- nsIEditor::EDirection aDirection)
-{
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- EditorBase::StartOperation(opID, aDirection); // will set mAction, mDirection
- if (rules) {
- return rules->BeforeEdit(mAction, mDirection);
- }
- return NS_OK;
-}
-
-/**
- * All editor operations which alter the doc should be followed
- * with a call to EndOperation.
- */
-NS_IMETHODIMP
-HTMLEditor::EndOperation()
-{
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- // post processing
- nsresult rv = rules ? rules->AfterEdit(mAction, mDirection) : NS_OK;
- EditorBase::EndOperation(); // will clear mAction, mDirection
- return rv;
-}
-
-bool
-HTMLEditor::TagCanContainTag(nsIAtom& aParentTag,
- nsIAtom& aChildTag)
-{
- int32_t childTagEnum;
- // XXX Should this handle #cdata-section too?
- if (&aChildTag == nsGkAtoms::textTagName) {
- childTagEnum = eHTMLTag_text;
- } else {
- childTagEnum = nsHTMLTags::AtomTagToId(&aChildTag);
- }
-
- int32_t parentTagEnum = nsHTMLTags::AtomTagToId(&aParentTag);
- return HTMLEditUtils::CanContain(parentTagEnum, childTagEnum);
-}
-
-bool
-HTMLEditor::IsContainer(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
-
- int32_t tagEnum;
- // XXX Should this handle #cdata-section too?
- if (aNode->IsNodeOfType(nsINode::eTEXT)) {
- tagEnum = eHTMLTag_text;
- } else {
- tagEnum = nsHTMLTags::StringTagToId(aNode->NodeName());
- }
-
- return HTMLEditUtils::IsContainer(tagEnum);
-}
-
-bool
-HTMLEditor::IsContainer(nsIDOMNode* aNode)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- if (!node) {
- return false;
- }
- return IsContainer(node);
-}
-
-
-nsresult
-HTMLEditor::SelectEntireDocument(Selection* aSelection)
-{
- if (!aSelection || !mRules) {
- return NS_ERROR_NULL_POINTER;
- }
-
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- // is doc empty?
- if (rules->DocumentIsEmpty()) {
- // get editor root node
- Element* rootElement = GetRoot();
-
- // if its empty dont select entire doc - that would select the bogus node
- return aSelection->Collapse(rootElement, 0);
- }
-
- return EditorBase::SelectEntireDocument(aSelection);
-}
-
-NS_IMETHODIMP
-HTMLEditor::SelectAll()
-{
- ForceCompositionEnd();
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_STATE(selection);
-
- nsCOMPtr<nsIDOMNode> anchorNode;
- nsresult rv = selection->GetAnchorNode(getter_AddRefs(anchorNode));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIContent> anchorContent = do_QueryInterface(anchorNode, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsIContent *rootContent;
- if (anchorContent->HasIndependentSelection()) {
- rv = selection->SetAncestorLimiter(nullptr);
- NS_ENSURE_SUCCESS(rv, rv);
- rootContent = mRootElement;
- } else {
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
- rootContent = anchorContent->GetSelectionRootContent(ps);
- }
-
- NS_ENSURE_TRUE(rootContent, NS_ERROR_UNEXPECTED);
-
- nsCOMPtr<nsIDOMNode> rootElement = do_QueryInterface(rootContent, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- Maybe<mozilla::dom::Selection::AutoUserInitiated> userSelection;
- if (!rootContent->IsEditable()) {
- userSelection.emplace(selection);
- }
- return selection->SelectAllChildren(rootElement);
-}
-
-// this will NOT find aAttribute unless aAttribute has a non-null value
-// so singleton attributes like <Table border> will not be matched!
-bool
-HTMLEditor::IsTextPropertySetByContent(nsINode* aNode,
- nsIAtom* aProperty,
- const nsAString* aAttribute,
- const nsAString* aValue,
- nsAString* outValue)
-{
- MOZ_ASSERT(aNode && aProperty);
- bool isSet;
- IsTextPropertySetByContent(aNode->AsDOMNode(), aProperty, aAttribute, aValue,
- isSet, outValue);
- return isSet;
-}
-
-void
-HTMLEditor::IsTextPropertySetByContent(nsIDOMNode* aNode,
- nsIAtom* aProperty,
- const nsAString* aAttribute,
- const nsAString* aValue,
- bool& aIsSet,
- nsAString* outValue)
-{
- aIsSet = false; // must be initialized to false for code below to work
- nsAutoString propName;
- aProperty->ToString(propName);
- nsCOMPtr<nsIDOMNode>node = aNode;
-
- while (node) {
- nsCOMPtr<nsIDOMElement>element;
- element = do_QueryInterface(node);
- if (element) {
- nsAutoString tag, value;
- element->GetTagName(tag);
- if (propName.Equals(tag, nsCaseInsensitiveStringComparator())) {
- bool found = false;
- if (aAttribute && !aAttribute->IsEmpty()) {
- element->GetAttribute(*aAttribute, value);
- if (outValue) {
- *outValue = value;
- }
- if (!value.IsEmpty()) {
- if (!aValue) {
- found = true;
- } else {
- nsString tString(*aValue);
- if (tString.Equals(value, nsCaseInsensitiveStringComparator())) {
- found = true;
- } else {
- // We found the prop with the attribute, but the value doesn't
- // match.
- break;
- }
- }
- }
- } else {
- found = true;
- }
- if (found) {
- aIsSet = true;
- break;
- }
- }
- }
- nsCOMPtr<nsIDOMNode>temp;
- if (NS_SUCCEEDED(node->GetParentNode(getter_AddRefs(temp))) && temp) {
- node = temp;
- } else {
- node = nullptr;
- }
- }
-}
-
-bool
-HTMLEditor::SetCaretInTableCell(nsIDOMElement* aElement)
-{
- nsCOMPtr<dom::Element> element = do_QueryInterface(aElement);
- if (!element || !element->IsHTMLElement() ||
- !HTMLEditUtils::IsTableElement(element) ||
- !IsDescendantOfEditorRoot(element)) {
- return false;
- }
-
- nsIContent* node = element;
- while (node->HasChildren()) {
- node = node->GetFirstChild();
- }
-
- // Set selection at beginning of the found node
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, false);
-
- return NS_SUCCEEDED(selection->CollapseNative(node, 0));
-}
-
-/**
- * GetEnclosingTable() finds ancestor who is a table, if any.
- */
-Element*
-HTMLEditor::GetEnclosingTable(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
-
- for (nsCOMPtr<Element> block = GetBlockNodeParent(aNode);
- block;
- block = GetBlockNodeParent(block)) {
- if (HTMLEditUtils::IsTable(block)) {
- return block;
- }
- }
- return nullptr;
-}
-
-nsIDOMNode*
-HTMLEditor::GetEnclosingTable(nsIDOMNode* aNode)
-{
- NS_PRECONDITION(aNode, "null node passed to HTMLEditor::GetEnclosingTable");
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- NS_ENSURE_TRUE(node, nullptr);
- nsCOMPtr<Element> table = GetEnclosingTable(node);
- nsCOMPtr<nsIDOMNode> ret = do_QueryInterface(table);
- return ret;
-}
-
-
-/**
- * This method scans the selection for adjacent text nodes
- * and collapses them into a single text node.
- * "adjacent" means literally adjacent siblings of the same parent.
- * Uses EditorBase::JoinNodes so action is undoable.
- * Should be called within the context of a batch transaction.
- */
-nsresult
-HTMLEditor::CollapseAdjacentTextNodes(nsRange* aInRange)
-{
- NS_ENSURE_TRUE(aInRange, NS_ERROR_NULL_POINTER);
- AutoTransactionsConserveSelection dontSpazMySelection(this);
- nsTArray<nsCOMPtr<nsIDOMNode> > textNodes;
- // we can't actually do anything during iteration, so store the text nodes in an array
- // don't bother ref counting them because we know we can hold them for the
- // lifetime of this method
-
-
- // build a list of editable text nodes
- nsresult rv = NS_ERROR_UNEXPECTED;
- nsCOMPtr<nsIContentIterator> iter =
- do_CreateInstance("@mozilla.org/content/subtree-content-iterator;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- iter->Init(aInRange);
-
- while (!iter->IsDone()) {
- nsINode* node = iter->GetCurrentNode();
- if (node->NodeType() == nsIDOMNode::TEXT_NODE &&
- IsEditable(static_cast<nsIContent*>(node))) {
- nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(node);
- textNodes.AppendElement(domNode);
- }
-
- iter->Next();
- }
-
- // now that I have a list of text nodes, collapse adjacent text nodes
- // NOTE: assumption that JoinNodes keeps the righthand node
- while (textNodes.Length() > 1) {
- // we assume a textNodes entry can't be nullptr
- nsIDOMNode *leftTextNode = textNodes[0];
- nsIDOMNode *rightTextNode = textNodes[1];
- NS_ASSERTION(leftTextNode && rightTextNode,"left or rightTextNode null in CollapseAdjacentTextNodes");
-
- // get the prev sibling of the right node, and see if its leftTextNode
- nsCOMPtr<nsIDOMNode> prevSibOfRightNode;
- rv = rightTextNode->GetPreviousSibling(getter_AddRefs(prevSibOfRightNode));
- NS_ENSURE_SUCCESS(rv, rv);
- if (prevSibOfRightNode && prevSibOfRightNode == leftTextNode) {
- nsCOMPtr<nsIDOMNode> parent;
- rv = rightTextNode->GetParentNode(getter_AddRefs(parent));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
- rv = JoinNodes(leftTextNode, rightTextNode, parent);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- textNodes.RemoveElementAt(0); // remove the leftmost text node from the list
- }
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::SetSelectionAtDocumentStart(Selection* aSelection)
-{
- dom::Element* rootElement = GetRoot();
- NS_ENSURE_TRUE(rootElement, NS_ERROR_NULL_POINTER);
-
- return aSelection->CollapseNative(rootElement, 0);
-}
-
-/**
- * Remove aNode, reparenting any children into the parent of aNode. In
- * addition, insert any br's needed to preserve identity of removed block.
- */
-nsresult
-HTMLEditor::RemoveBlockContainer(nsIContent& aNode)
-{
- // Two possibilities: the container could be empty of editable content. If
- // that is the case, we need to compare what is before and after aNode to
- // determine if we need a br.
- //
- // Or it could be not empty, in which case we have to compare previous
- // sibling and first child to determine if we need a leading br, and compare
- // following sibling and last child to determine if we need a trailing br.
-
- nsCOMPtr<nsIContent> child = GetFirstEditableChild(aNode);
-
- if (child) {
- // The case of aNode not being empty. We need a br at start unless:
- // 1) previous sibling of aNode is a block, OR
- // 2) previous sibling of aNode is a br, OR
- // 3) first child of aNode is a block OR
- // 4) either is null
-
- nsCOMPtr<nsIContent> sibling = GetPriorHTMLSibling(&aNode);
- if (sibling && !IsBlockNode(sibling) &&
- !sibling->IsHTMLElement(nsGkAtoms::br) && !IsBlockNode(child)) {
- // Insert br node
- nsCOMPtr<Element> br = CreateBR(&aNode, 0);
- NS_ENSURE_STATE(br);
- }
-
- // We need a br at end unless:
- // 1) following sibling of aNode is a block, OR
- // 2) last child of aNode is a block, OR
- // 3) last child of aNode is a br OR
- // 4) either is null
-
- sibling = GetNextHTMLSibling(&aNode);
- if (sibling && !IsBlockNode(sibling)) {
- child = GetLastEditableChild(aNode);
- MOZ_ASSERT(child, "aNode has first editable child but not last?");
- if (!IsBlockNode(child) && !child->IsHTMLElement(nsGkAtoms::br)) {
- // Insert br node
- nsCOMPtr<Element> br = CreateBR(&aNode, aNode.Length());
- NS_ENSURE_STATE(br);
- }
- }
- } else {
- // The case of aNode being empty. We need a br at start unless:
- // 1) previous sibling of aNode is a block, OR
- // 2) previous sibling of aNode is a br, OR
- // 3) following sibling of aNode is a block, OR
- // 4) following sibling of aNode is a br OR
- // 5) either is null
- nsCOMPtr<nsIContent> sibling = GetPriorHTMLSibling(&aNode);
- if (sibling && !IsBlockNode(sibling) &&
- !sibling->IsHTMLElement(nsGkAtoms::br)) {
- sibling = GetNextHTMLSibling(&aNode);
- if (sibling && !IsBlockNode(sibling) &&
- !sibling->IsHTMLElement(nsGkAtoms::br)) {
- // Insert br node
- nsCOMPtr<Element> br = CreateBR(&aNode, 0);
- NS_ENSURE_STATE(br);
- }
- }
- }
-
- // Now remove container
- nsresult rv = RemoveContainer(&aNode);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-/**
- * GetPriorHTMLSibling() returns the previous editable sibling, if there is
- * one within the parent.
- */
-nsIContent*
-HTMLEditor::GetPriorHTMLSibling(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
-
- nsIContent* node = aNode->GetPreviousSibling();
- while (node && !IsEditable(node)) {
- node = node->GetPreviousSibling();
- }
-
- return node;
-}
-
-nsresult
-HTMLEditor::GetPriorHTMLSibling(nsIDOMNode* inNode,
- nsCOMPtr<nsIDOMNode>* outNode)
-{
- NS_ENSURE_TRUE(outNode, NS_ERROR_NULL_POINTER);
- *outNode = nullptr;
-
- nsCOMPtr<nsINode> node = do_QueryInterface(inNode);
- NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
-
- *outNode = do_QueryInterface(GetPriorHTMLSibling(node));
- return NS_OK;
-}
-
-/**
- * GetPriorHTMLSibling() returns the previous editable sibling, if there is
- * one within the parent. just like above routine but takes a parent/offset
- * instead of a node.
- */
-nsIContent*
-HTMLEditor::GetPriorHTMLSibling(nsINode* aParent,
- int32_t aOffset)
-{
- MOZ_ASSERT(aParent);
-
- nsIContent* node = aParent->GetChildAt(aOffset - 1);
- if (!node || IsEditable(node)) {
- return node;
- }
-
- return GetPriorHTMLSibling(node);
-}
-
-nsresult
-HTMLEditor::GetPriorHTMLSibling(nsIDOMNode* inParent,
- int32_t inOffset,
- nsCOMPtr<nsIDOMNode>* outNode)
-{
- NS_ENSURE_TRUE(outNode, NS_ERROR_NULL_POINTER);
- *outNode = nullptr;
-
- nsCOMPtr<nsINode> parent = do_QueryInterface(inParent);
- NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
-
- *outNode = do_QueryInterface(GetPriorHTMLSibling(parent, inOffset));
- return NS_OK;
-}
-
-/**
- * GetNextHTMLSibling() returns the next editable sibling, if there is
- * one within the parent.
- */
-nsIContent*
-HTMLEditor::GetNextHTMLSibling(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
-
- nsIContent* node = aNode->GetNextSibling();
- while (node && !IsEditable(node)) {
- node = node->GetNextSibling();
- }
-
- return node;
-}
-
-nsresult
-HTMLEditor::GetNextHTMLSibling(nsIDOMNode* inNode,
- nsCOMPtr<nsIDOMNode>* outNode)
-{
- NS_ENSURE_TRUE(outNode, NS_ERROR_NULL_POINTER);
- *outNode = nullptr;
-
- nsCOMPtr<nsINode> node = do_QueryInterface(inNode);
- NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
-
- *outNode = do_QueryInterface(GetNextHTMLSibling(node));
- return NS_OK;
-}
-
-/**
- * GetNextHTMLSibling() returns the next editable sibling, if there is
- * one within the parent. just like above routine but takes a parent/offset
- * instead of a node.
- */
-nsIContent*
-HTMLEditor::GetNextHTMLSibling(nsINode* aParent,
- int32_t aOffset)
-{
- MOZ_ASSERT(aParent);
-
- nsIContent* node = aParent->GetChildAt(aOffset + 1);
- if (!node || IsEditable(node)) {
- return node;
- }
-
- return GetNextHTMLSibling(node);
-}
-
-nsresult
-HTMLEditor::GetNextHTMLSibling(nsIDOMNode* inParent,
- int32_t inOffset,
- nsCOMPtr<nsIDOMNode>* outNode)
-{
- NS_ENSURE_TRUE(outNode, NS_ERROR_NULL_POINTER);
- *outNode = nullptr;
-
- nsCOMPtr<nsINode> parent = do_QueryInterface(inParent);
- NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
-
- *outNode = do_QueryInterface(GetNextHTMLSibling(parent, inOffset));
- return NS_OK;
-}
-
-/**
- * GetPriorHTMLNode() returns the previous editable leaf node, if there is
- * one within the <body>.
- */
-nsIContent*
-HTMLEditor::GetPriorHTMLNode(nsINode* aNode,
- bool aNoBlockCrossing)
-{
- MOZ_ASSERT(aNode);
-
- if (!GetActiveEditingHost()) {
- return nullptr;
- }
-
- return GetPriorNode(aNode, true, aNoBlockCrossing);
-}
-
-nsresult
-HTMLEditor::GetPriorHTMLNode(nsIDOMNode* aNode,
- nsCOMPtr<nsIDOMNode>* aResultNode,
- bool aNoBlockCrossing)
-{
- NS_ENSURE_TRUE(aResultNode, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
-
- *aResultNode = do_QueryInterface(GetPriorHTMLNode(node, aNoBlockCrossing));
- return NS_OK;
-}
-
-/**
- * GetPriorHTMLNode() is same as above but takes {parent,offset} instead of
- * node.
- */
-nsIContent*
-HTMLEditor::GetPriorHTMLNode(nsINode* aParent,
- int32_t aOffset,
- bool aNoBlockCrossing)
-{
- MOZ_ASSERT(aParent);
-
- if (!GetActiveEditingHost()) {
- return nullptr;
- }
-
- return GetPriorNode(aParent, aOffset, true, aNoBlockCrossing);
-}
-
-nsresult
-HTMLEditor::GetPriorHTMLNode(nsIDOMNode* aNode,
- int32_t aOffset,
- nsCOMPtr<nsIDOMNode>* aResultNode,
- bool aNoBlockCrossing)
-{
- NS_ENSURE_TRUE(aResultNode, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
-
- *aResultNode = do_QueryInterface(GetPriorHTMLNode(node, aOffset,
- aNoBlockCrossing));
- return NS_OK;
-}
-
-/**
- * GetNextHTMLNode() returns the next editable leaf node, if there is
- * one within the <body>.
- */
-nsIContent*
-HTMLEditor::GetNextHTMLNode(nsINode* aNode,
- bool aNoBlockCrossing)
-{
- MOZ_ASSERT(aNode);
-
- nsIContent* result = GetNextNode(aNode, true, aNoBlockCrossing);
-
- if (result && !IsDescendantOfEditorRoot(result)) {
- return nullptr;
- }
-
- return result;
-}
-
-nsresult
-HTMLEditor::GetNextHTMLNode(nsIDOMNode* aNode,
- nsCOMPtr<nsIDOMNode>* aResultNode,
- bool aNoBlockCrossing)
-{
- NS_ENSURE_TRUE(aResultNode, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
-
- *aResultNode = do_QueryInterface(GetNextHTMLNode(node, aNoBlockCrossing));
- return NS_OK;
-}
-
-/**
- * GetNextHTMLNode() is same as above but takes {parent,offset} instead of node.
- */
-nsIContent*
-HTMLEditor::GetNextHTMLNode(nsINode* aParent,
- int32_t aOffset,
- bool aNoBlockCrossing)
-{
- nsIContent* content = GetNextNode(aParent, aOffset, true, aNoBlockCrossing);
- if (content && !IsDescendantOfEditorRoot(content)) {
- return nullptr;
- }
- return content;
-}
-
-nsresult
-HTMLEditor::GetNextHTMLNode(nsIDOMNode* aNode,
- int32_t aOffset,
- nsCOMPtr<nsIDOMNode>* aResultNode,
- bool aNoBlockCrossing)
-{
- NS_ENSURE_TRUE(aResultNode, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
-
- *aResultNode = do_QueryInterface(GetNextHTMLNode(node, aOffset,
- aNoBlockCrossing));
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::IsFirstEditableChild(nsIDOMNode* aNode,
- bool* aOutIsFirst)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- NS_ENSURE_TRUE(aOutIsFirst && node, NS_ERROR_NULL_POINTER);
-
- // init out parms
- *aOutIsFirst = false;
-
- // find first editable child and compare it to aNode
- nsCOMPtr<nsINode> parent = node->GetParentNode();
- NS_ENSURE_TRUE(parent, NS_ERROR_FAILURE);
-
- *aOutIsFirst = (GetFirstEditableChild(*parent) == node);
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::IsLastEditableChild(nsIDOMNode* aNode,
- bool* aOutIsLast)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- NS_ENSURE_TRUE(aOutIsLast && node, NS_ERROR_NULL_POINTER);
-
- // init out parms
- *aOutIsLast = false;
-
- // find last editable child and compare it to aNode
- nsCOMPtr<nsINode> parent = node->GetParentNode();
- NS_ENSURE_TRUE(parent, NS_ERROR_FAILURE);
-
- *aOutIsLast = (GetLastEditableChild(*parent) == node);
- return NS_OK;
-}
-
-nsIContent*
-HTMLEditor::GetFirstEditableChild(nsINode& aNode)
-{
- nsCOMPtr<nsIContent> child = aNode.GetFirstChild();
-
- while (child && !IsEditable(child)) {
- child = child->GetNextSibling();
- }
-
- return child;
-}
-
-nsIContent*
-HTMLEditor::GetLastEditableChild(nsINode& aNode)
-{
- nsCOMPtr<nsIContent> child = aNode.GetLastChild();
-
- while (child && !IsEditable(child)) {
- child = child->GetPreviousSibling();
- }
-
- return child;
-}
-
-nsIContent*
-HTMLEditor::GetFirstEditableLeaf(nsINode& aNode)
-{
- nsCOMPtr<nsIContent> child = GetLeftmostChild(&aNode);
- while (child && (!IsEditable(child) || child->HasChildren())) {
- child = GetNextHTMLNode(child);
-
- // Only accept nodes that are descendants of aNode
- if (!aNode.Contains(child)) {
- return nullptr;
- }
- }
-
- return child;
-}
-
-nsIContent*
-HTMLEditor::GetLastEditableLeaf(nsINode& aNode)
-{
- nsCOMPtr<nsIContent> child = GetRightmostChild(&aNode, false);
- while (child && (!IsEditable(child) || child->HasChildren())) {
- child = GetPriorHTMLNode(child);
-
- // Only accept nodes that are descendants of aNode
- if (!aNode.Contains(child)) {
- return nullptr;
- }
- }
-
- return child;
-}
-
-/**
- * IsVisTextNode() figures out if textnode aTextNode has any visible content.
- */
-nsresult
-HTMLEditor::IsVisTextNode(nsIContent* aNode,
- bool* outIsEmptyNode,
- bool aSafeToAskFrames)
-{
- MOZ_ASSERT(aNode);
- MOZ_ASSERT(aNode->NodeType() == nsIDOMNode::TEXT_NODE);
- MOZ_ASSERT(outIsEmptyNode);
-
- *outIsEmptyNode = true;
-
- uint32_t length = aNode->TextLength();
- if (aSafeToAskFrames) {
- nsCOMPtr<nsISelectionController> selectionController =
- GetSelectionController();
- if (NS_WARN_IF(!selectionController)) {
- return NS_ERROR_FAILURE;
- }
- bool isVisible = false;
- // ask the selection controller for information about whether any
- // of the data in the node is really rendered. This is really
- // something that frames know about, but we aren't supposed to talk to frames.
- // So we put a call in the selection controller interface, since it's already
- // in bed with frames anyway. (this is a fix for bug 22227, and a
- // partial fix for bug 46209)
- nsresult rv = selectionController->CheckVisibilityContent(aNode, 0, length,
- &isVisible);
- NS_ENSURE_SUCCESS(rv, rv);
- if (isVisible) {
- *outIsEmptyNode = false;
- }
- } else if (length) {
- if (aNode->TextIsOnlyWhitespace()) {
- WSRunObject wsRunObj(this, aNode, 0);
- nsCOMPtr<nsINode> visNode;
- int32_t outVisOffset=0;
- WSType visType;
- wsRunObj.NextVisibleNode(aNode, 0, address_of(visNode),
- &outVisOffset, &visType);
- if (visType == WSType::normalWS || visType == WSType::text) {
- *outIsEmptyNode = (aNode != visNode);
- }
- } else {
- *outIsEmptyNode = false;
- }
- }
- return NS_OK;
-}
-
-/**
- * IsEmptyNode() figures out if aNode is an empty node. A block can have
- * children and still be considered empty, if the children are empty or
- * non-editable.
- */
-nsresult
-HTMLEditor::IsEmptyNode(nsIDOMNode*aNode,
- bool* outIsEmptyNode,
- bool aSingleBRDoesntCount,
- bool aListOrCellNotEmpty,
- bool aSafeToAskFrames)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- return IsEmptyNode(node, outIsEmptyNode, aSingleBRDoesntCount,
- aListOrCellNotEmpty, aSafeToAskFrames);
-}
-
-nsresult
-HTMLEditor::IsEmptyNode(nsINode* aNode,
- bool* outIsEmptyNode,
- bool aSingleBRDoesntCount,
- bool aListOrCellNotEmpty,
- bool aSafeToAskFrames)
-{
- NS_ENSURE_TRUE(aNode && outIsEmptyNode, NS_ERROR_NULL_POINTER);
- *outIsEmptyNode = true;
- bool seenBR = false;
- return IsEmptyNodeImpl(aNode, outIsEmptyNode, aSingleBRDoesntCount,
- aListOrCellNotEmpty, aSafeToAskFrames, &seenBR);
-}
-
-/**
- * IsEmptyNodeImpl() is workhorse for IsEmptyNode().
- */
-nsresult
-HTMLEditor::IsEmptyNodeImpl(nsINode* aNode,
- bool* outIsEmptyNode,
- bool aSingleBRDoesntCount,
- bool aListOrCellNotEmpty,
- bool aSafeToAskFrames,
- bool* aSeenBR)
-{
- NS_ENSURE_TRUE(aNode && outIsEmptyNode && aSeenBR, NS_ERROR_NULL_POINTER);
-
- if (aNode->NodeType() == nsIDOMNode::TEXT_NODE) {
- return IsVisTextNode(static_cast<nsIContent*>(aNode), outIsEmptyNode, aSafeToAskFrames);
- }
-
- // if it's not a text node (handled above) and it's not a container,
- // then we don't call it empty (it's an <hr>, or <br>, etc.).
- // Also, if it's an anchor then don't treat it as empty - even though
- // anchors are containers, named anchors are "empty" but we don't
- // want to treat them as such. Also, don't call ListItems or table
- // cells empty if caller desires. Form Widgets not empty.
- if (!IsContainer(aNode->AsDOMNode()) ||
- (HTMLEditUtils::IsNamedAnchor(aNode) ||
- HTMLEditUtils::IsFormWidget(aNode) ||
- (aListOrCellNotEmpty &&
- (HTMLEditUtils::IsListItem(aNode) ||
- HTMLEditUtils::IsTableCell(aNode))))) {
- *outIsEmptyNode = false;
- return NS_OK;
- }
-
- // need this for later
- bool isListItemOrCell = HTMLEditUtils::IsListItem(aNode) ||
- HTMLEditUtils::IsTableCell(aNode);
-
- // loop over children of node. if no children, or all children are either
- // empty text nodes or non-editable, then node qualifies as empty
- for (nsCOMPtr<nsIContent> child = aNode->GetFirstChild();
- child;
- child = child->GetNextSibling()) {
- // Is the child editable and non-empty? if so, return false
- if (EditorBase::IsEditable(child)) {
- if (child->NodeType() == nsIDOMNode::TEXT_NODE) {
- nsresult rv = IsVisTextNode(child, outIsEmptyNode, aSafeToAskFrames);
- NS_ENSURE_SUCCESS(rv, rv);
- // break out if we find we aren't emtpy
- if (!*outIsEmptyNode) {
- return NS_OK;
- }
- } else {
- // An editable, non-text node. We need to check its content.
- // Is it the node we are iterating over?
- if (child == aNode) {
- break;
- }
-
- if (aSingleBRDoesntCount && !*aSeenBR && child->IsHTMLElement(nsGkAtoms::br)) {
- // the first br in a block doesn't count if the caller so indicated
- *aSeenBR = true;
- } else {
- // is it an empty node of some sort?
- // note: list items or table cells are not considered empty
- // if they contain other lists or tables
- if (child->IsElement()) {
- if (isListItemOrCell) {
- if (HTMLEditUtils::IsList(child) ||
- child->IsHTMLElement(nsGkAtoms::table)) {
- // break out if we find we aren't empty
- *outIsEmptyNode = false;
- return NS_OK;
- }
- } else if (HTMLEditUtils::IsFormWidget(child)) {
- // is it a form widget?
- // break out if we find we aren't empty
- *outIsEmptyNode = false;
- return NS_OK;
- }
- }
-
- bool isEmptyNode = true;
- nsresult rv = IsEmptyNodeImpl(child, &isEmptyNode,
- aSingleBRDoesntCount,
- aListOrCellNotEmpty, aSafeToAskFrames,
- aSeenBR);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!isEmptyNode) {
- // otherwise it ain't empty
- *outIsEmptyNode = false;
- return NS_OK;
- }
- }
- }
- }
- }
-
- return NS_OK;
-}
-
-// add to aElement the CSS inline styles corresponding to the HTML attribute
-// aAttribute with its value aValue
-nsresult
-HTMLEditor::SetAttributeOrEquivalent(Element* aElement,
- nsIAtom* aAttribute,
- const nsAString& aValue,
- bool aSuppressTransaction)
-{
- MOZ_ASSERT(aElement);
- MOZ_ASSERT(aAttribute);
-
- nsAutoScriptBlocker scriptBlocker;
-
- if (!IsCSSEnabled() || !mCSSEditUtils) {
- // we are not in an HTML+CSS editor; let's set the attribute the HTML way
- return aSuppressTransaction ?
- aElement->SetAttr(kNameSpaceID_None, aAttribute, aValue, true) :
- SetAttribute(aElement, aAttribute, aValue);
- }
-
- int32_t count =
- mCSSEditUtils->SetCSSEquivalentToHTMLStyle(aElement, nullptr,
- aAttribute, &aValue,
- aSuppressTransaction);
- if (count) {
- // we found an equivalence ; let's remove the HTML attribute itself if it
- // is set
- nsAutoString existingValue;
- if (!aElement->GetAttr(kNameSpaceID_None, aAttribute, existingValue)) {
- return NS_OK;
- }
-
- return aSuppressTransaction ?
- aElement->UnsetAttr(kNameSpaceID_None, aAttribute, true) :
- RemoveAttribute(aElement, aAttribute);
- }
-
- // count is an integer that represents the number of CSS declarations applied
- // to the element. If it is zero, we found no equivalence in this
- // implementation for the attribute
- if (aAttribute == nsGkAtoms::style) {
- // if it is the style attribute, just add the new value to the existing
- // style attribute's value
- nsAutoString existingValue;
- aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::style, existingValue);
- existingValue.Append(' ');
- existingValue.Append(aValue);
- return aSuppressTransaction ?
- aElement->SetAttr(kNameSpaceID_None, aAttribute, existingValue, true) :
- SetAttribute(aElement, aAttribute, existingValue);
- }
-
- // we have no CSS equivalence for this attribute and it is not the style
- // attribute; let's set it the good'n'old HTML way
- return aSuppressTransaction ?
- aElement->SetAttr(kNameSpaceID_None, aAttribute, aValue, true) :
- SetAttribute(aElement, aAttribute, aValue);
-}
-
-nsresult
-HTMLEditor::RemoveAttributeOrEquivalent(Element* aElement,
- nsIAtom* aAttribute,
- bool aSuppressTransaction)
-{
- MOZ_ASSERT(aElement);
- MOZ_ASSERT(aAttribute);
-
- if (IsCSSEnabled() && mCSSEditUtils) {
- nsresult rv =
- mCSSEditUtils->RemoveCSSEquivalentToHTMLStyle(
- aElement, nullptr, aAttribute, nullptr, aSuppressTransaction);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- if (!aElement->HasAttr(kNameSpaceID_None, aAttribute)) {
- return NS_OK;
- }
-
- return aSuppressTransaction ?
- aElement->UnsetAttr(kNameSpaceID_None, aAttribute, /* aNotify = */ true) :
- RemoveAttribute(aElement, aAttribute);
-}
-
-nsresult
-HTMLEditor::SetIsCSSEnabled(bool aIsCSSPrefChecked)
-{
- if (!mCSSEditUtils) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- mCSSEditUtils->SetCSSEnabled(aIsCSSPrefChecked);
-
- // Disable the eEditorNoCSSMask flag if we're enabling StyleWithCSS.
- uint32_t flags = mFlags;
- if (aIsCSSPrefChecked) {
- // Turn off NoCSS as we're enabling CSS
- flags &= ~eEditorNoCSSMask;
- } else {
- // Turn on NoCSS, as we're disabling CSS.
- flags |= eEditorNoCSSMask;
- }
-
- return SetFlags(flags);
-}
-
-// Set the block background color
-nsresult
-HTMLEditor::SetCSSBackgroundColor(const nsAString& aColor)
-{
- NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
- ForceCompositionEnd();
-
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_STATE(selection);
-
- bool isCollapsed = selection->Collapsed();
-
- AutoEditBatch batchIt(this);
- AutoRules beginRulesSniffing(this, EditAction::insertElement,
- nsIEditor::eNext);
- AutoSelectionRestorer selectionRestorer(selection, this);
- AutoTransactionsConserveSelection dontSpazMySelection(this);
-
- bool cancel, handled;
- TextRulesInfo ruleInfo(EditAction::setTextProperty);
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!cancel && !handled) {
- // Loop through the ranges in the selection
- for (uint32_t i = 0; i < selection->RangeCount(); i++) {
- RefPtr<nsRange> range = selection->GetRangeAt(i);
- NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
-
- nsCOMPtr<Element> cachedBlockParent;
-
- // Check for easy case: both range endpoints in same text node
- nsCOMPtr<nsINode> startNode = range->GetStartParent();
- int32_t startOffset = range->StartOffset();
- nsCOMPtr<nsINode> endNode = range->GetEndParent();
- int32_t endOffset = range->EndOffset();
- if (startNode == endNode && IsTextNode(startNode)) {
- // Let's find the block container of the text node
- nsCOMPtr<Element> blockParent = GetBlockNodeParent(startNode);
- // And apply the background color to that block container
- if (blockParent && cachedBlockParent != blockParent) {
- cachedBlockParent = blockParent;
- mCSSEditUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
- nsGkAtoms::bgcolor,
- &aColor, false);
- }
- } else if (startNode == endNode &&
- startNode->IsHTMLElement(nsGkAtoms::body) && isCollapsed) {
- // No block in the document, let's apply the background to the body
- mCSSEditUtils->SetCSSEquivalentToHTMLStyle(startNode->AsElement(),
- nullptr, nsGkAtoms::bgcolor,
- &aColor,
- false);
- } else if (startNode == endNode && (endOffset - startOffset == 1 ||
- (!startOffset && !endOffset))) {
- // A unique node is selected, let's also apply the background color to
- // the containing block, possibly the node itself
- nsCOMPtr<nsIContent> selectedNode = startNode->GetChildAt(startOffset);
- nsCOMPtr<Element> blockParent = GetBlock(*selectedNode);
- if (blockParent && cachedBlockParent != blockParent) {
- cachedBlockParent = blockParent;
- mCSSEditUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
- nsGkAtoms::bgcolor,
- &aColor, false);
- }
- } else {
- // Not the easy case. Range not contained in single text node. There
- // are up to three phases here. There are all the nodes reported by
- // the subtree iterator to be processed. And there are potentially a
- // starting textnode and an ending textnode which are only partially
- // contained by the range.
-
- // Let's handle the nodes reported by the iterator. These nodes are
- // entirely contained in the selection range. We build up a list of
- // them (since doing operations on the document during iteration would
- // perturb the iterator).
-
- OwningNonNull<nsIContentIterator> iter =
- NS_NewContentSubtreeIterator();
-
- nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
- nsCOMPtr<nsINode> node;
-
- // Iterate range and build up array
- rv = iter->Init(range);
- // Init returns an error if no nodes in range. This can easily happen
- // with the subtree iterator if the selection doesn't contain any
- // *whole* nodes.
- if (NS_SUCCEEDED(rv)) {
- for (; !iter->IsDone(); iter->Next()) {
- node = do_QueryInterface(iter->GetCurrentNode());
- NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
-
- if (IsEditable(node)) {
- arrayOfNodes.AppendElement(*node);
- }
- }
- }
- // First check the start parent of the range to see if it needs to be
- // separately handled (it does if it's a text node, due to how the
- // subtree iterator works - it will not have reported it).
- if (IsTextNode(startNode) && IsEditable(startNode)) {
- nsCOMPtr<Element> blockParent = GetBlockNodeParent(startNode);
- if (blockParent && cachedBlockParent != blockParent) {
- cachedBlockParent = blockParent;
- mCSSEditUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
- nsGkAtoms::bgcolor,
- &aColor,
- false);
- }
- }
-
- // Then loop through the list, set the property on each node
- for (auto& node : arrayOfNodes) {
- nsCOMPtr<Element> blockParent = GetBlock(node);
- if (blockParent && cachedBlockParent != blockParent) {
- cachedBlockParent = blockParent;
- mCSSEditUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
- nsGkAtoms::bgcolor,
- &aColor,
- false);
- }
- }
- arrayOfNodes.Clear();
-
- // Last, check the end parent of the range to see if it needs to be
- // separately handled (it does if it's a text node, due to how the
- // subtree iterator works - it will not have reported it).
- if (IsTextNode(endNode) && IsEditable(endNode)) {
- nsCOMPtr<Element> blockParent = GetBlockNodeParent(endNode);
- if (blockParent && cachedBlockParent != blockParent) {
- cachedBlockParent = blockParent;
- mCSSEditUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
- nsGkAtoms::bgcolor,
- &aColor,
- false);
- }
- }
- }
- }
- }
- if (!cancel) {
- // Post-process
- rv = rules->DidDoAction(selection, &ruleInfo, rv);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::SetBackgroundColor(const nsAString& aColor)
-{
- if (IsCSSEnabled()) {
- // if we are in CSS mode, we have to apply the background color to the
- // containing block (or the body if we have no block-level element in
- // the document)
- return SetCSSBackgroundColor(aColor);
- }
-
- // but in HTML mode, we can only set the document's background color
- return SetHTMLBackgroundColor(aColor);
-}
-
-/**
- * NodesSameType() does these nodes have the same tag?
- */
-bool
-HTMLEditor::AreNodesSameType(nsIContent* aNode1,
- nsIContent* aNode2)
-{
- MOZ_ASSERT(aNode1);
- MOZ_ASSERT(aNode2);
-
- if (aNode1->NodeInfo()->NameAtom() != aNode2->NodeInfo()->NameAtom()) {
- return false;
- }
-
- if (!IsCSSEnabled() || !aNode1->IsHTMLElement(nsGkAtoms::span)) {
- return true;
- }
-
- // If CSS is enabled, we are stricter about span nodes.
- return mCSSEditUtils->ElementsSameStyle(aNode1->AsDOMNode(),
- aNode2->AsDOMNode());
-}
-
-nsresult
-HTMLEditor::CopyLastEditableChildStyles(nsIDOMNode* aPreviousBlock,
- nsIDOMNode* aNewBlock,
- Element** aOutBrNode)
-{
- nsCOMPtr<nsINode> newBlock = do_QueryInterface(aNewBlock);
- NS_ENSURE_STATE(newBlock || !aNewBlock);
- *aOutBrNode = nullptr;
- nsCOMPtr<nsIDOMNode> child, tmp;
- // first, clear out aNewBlock. Contract is that we want only the styles from previousBlock.
- nsresult rv = aNewBlock->GetFirstChild(getter_AddRefs(child));
- while (NS_SUCCEEDED(rv) && child) {
- rv = DeleteNode(child);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = aNewBlock->GetFirstChild(getter_AddRefs(child));
- }
- // now find and clone the styles
- child = aPreviousBlock;
- tmp = aPreviousBlock;
- while (tmp) {
- child = tmp;
- nsCOMPtr<nsINode> child_ = do_QueryInterface(child);
- NS_ENSURE_STATE(child_ || !child);
- tmp = GetAsDOMNode(GetLastEditableChild(*child_));
- }
- while (child && TextEditUtils::IsBreak(child)) {
- nsCOMPtr<nsIDOMNode> priorNode;
- rv = GetPriorHTMLNode(child, address_of(priorNode));
- NS_ENSURE_SUCCESS(rv, rv);
- child = priorNode;
- }
- nsCOMPtr<Element> newStyles, deepestStyle;
- nsCOMPtr<nsINode> childNode = do_QueryInterface(child);
- nsCOMPtr<Element> childElement;
- if (childNode) {
- childElement = childNode->IsElement() ? childNode->AsElement()
- : childNode->GetParentElement();
- }
- while (childElement && (childElement->AsDOMNode() != aPreviousBlock)) {
- if (HTMLEditUtils::IsInlineStyle(childElement) ||
- childElement->IsHTMLElement(nsGkAtoms::span)) {
- if (newStyles) {
- newStyles = InsertContainerAbove(newStyles,
- childElement->NodeInfo()->NameAtom());
- NS_ENSURE_STATE(newStyles);
- } else {
- deepestStyle = newStyles =
- CreateNode(childElement->NodeInfo()->NameAtom(), newBlock, 0);
- NS_ENSURE_STATE(newStyles);
- }
- CloneAttributes(newStyles, childElement);
- }
- childElement = childElement->GetParentElement();
- }
- if (deepestStyle) {
- RefPtr<Element> retVal = CreateBR(deepestStyle, 0);
- retVal.forget(aOutBrNode);
- NS_ENSURE_STATE(*aOutBrNode);
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::GetElementOrigin(nsIDOMElement* aElement,
- int32_t& aX,
- int32_t& aY)
-{
- aX = 0;
- aY = 0;
-
- if (NS_WARN_IF(!IsInitialized())) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
- NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
-
- nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
- nsIFrame *frame = content->GetPrimaryFrame();
- NS_ENSURE_TRUE(frame, NS_OK);
-
- nsIFrame *container = ps->GetAbsoluteContainingBlock(frame);
- NS_ENSURE_TRUE(container, NS_OK);
- nsPoint off = frame->GetOffsetTo(container);
- aX = nsPresContext::AppUnitsToIntCSSPixels(off.x);
- aY = nsPresContext::AppUnitsToIntCSSPixels(off.y);
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::EndUpdateViewBatch()
-{
- nsresult rv = EditorBase::EndUpdateViewBatch();
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (mUpdateCount) {
- return NS_OK;
- }
-
- // We may need to show resizing handles or update existing ones after
- // all transactions are done. This way of doing is preferred to DOM
- // mutation events listeners because all the changes the user can apply
- // to a document may result in multiple events, some of them quite hard
- // to listen too (in particular when an ancestor of the selection is
- // changed but the selection itself is not changed).
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
- return CheckSelectionStateForAnonymousButtons(selection);
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetSelectionContainer(nsIDOMElement** aReturn)
-{
- nsCOMPtr<nsIDOMElement> container =
- static_cast<nsIDOMElement*>(GetAsDOMNode(GetSelectionContainer()));
- NS_ENSURE_TRUE(container, NS_ERROR_FAILURE);
- container.forget(aReturn);
- return NS_OK;
-}
-
-Element*
-HTMLEditor::GetSelectionContainer()
-{
- // If we don't get the selection, just skip this
- NS_ENSURE_TRUE(GetSelection(), nullptr);
-
- OwningNonNull<Selection> selection = *GetSelection();
-
- nsCOMPtr<nsINode> focusNode;
-
- if (selection->Collapsed()) {
- focusNode = selection->GetFocusNode();
- } else {
- int32_t rangeCount = selection->RangeCount();
-
- if (rangeCount == 1) {
- RefPtr<nsRange> range = selection->GetRangeAt(0);
-
- nsCOMPtr<nsINode> startContainer = range->GetStartParent();
- int32_t startOffset = range->StartOffset();
- nsCOMPtr<nsINode> endContainer = range->GetEndParent();
- int32_t endOffset = range->EndOffset();
-
- if (startContainer == endContainer && startOffset + 1 == endOffset) {
- nsCOMPtr<nsIDOMElement> focusElement;
- nsresult rv = GetSelectedElement(EmptyString(),
- getter_AddRefs(focusElement));
- NS_ENSURE_SUCCESS(rv, nullptr);
- if (focusElement) {
- focusNode = do_QueryInterface(focusElement);
- }
- }
- if (!focusNode) {
- focusNode = range->GetCommonAncestor();
- }
- } else {
- for (int32_t i = 0; i < rangeCount; i++) {
- RefPtr<nsRange> range = selection->GetRangeAt(i);
-
- nsCOMPtr<nsINode> startContainer = range->GetStartParent();
- if (!focusNode) {
- focusNode = startContainer;
- } else if (focusNode != startContainer) {
- focusNode = startContainer->GetParentNode();
- break;
- }
- }
- }
- }
-
- if (focusNode && focusNode->GetAsText()) {
- focusNode = focusNode->GetParentNode();
- }
-
- if (focusNode && focusNode->IsElement()) {
- return focusNode->AsElement();
- }
-
- return nullptr;
-}
-
-NS_IMETHODIMP
-HTMLEditor::IsAnonymousElement(nsIDOMElement* aElement,
- bool* aReturn)
-{
- NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
- nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
- *aReturn = content->IsRootOfNativeAnonymousSubtree();
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::SetReturnInParagraphCreatesNewParagraph(bool aCreatesNewParagraph)
-{
- mCRInParagraphCreatesParagraph = aCreatesNewParagraph;
- return NS_OK;
-}
-
-bool
-HTMLEditor::GetReturnInParagraphCreatesNewParagraph()
-{
- return mCRInParagraphCreatesParagraph;
-}
-
-nsresult
-HTMLEditor::GetReturnInParagraphCreatesNewParagraph(bool* aCreatesNewParagraph)
-{
- *aCreatesNewParagraph = mCRInParagraphCreatesParagraph;
- return NS_OK;
-}
-
-already_AddRefed<nsIContent>
-HTMLEditor::GetFocusedContent()
-{
- nsFocusManager* fm = nsFocusManager::GetFocusManager();
- NS_ENSURE_TRUE(fm, nullptr);
-
- nsCOMPtr<nsIContent> focusedContent = fm->GetFocusedContent();
-
- nsCOMPtr<nsIDocument> document = GetDocument();
- if (NS_WARN_IF(!document)) {
- return nullptr;
- }
- bool inDesignMode = document->HasFlag(NODE_IS_EDITABLE);
- if (!focusedContent) {
- // in designMode, nobody gets focus in most cases.
- if (inDesignMode && OurWindowHasFocus()) {
- nsCOMPtr<nsIContent> rootContent = document->GetRootElement();
- return rootContent.forget();
- }
- return nullptr;
- }
-
- if (inDesignMode) {
- return OurWindowHasFocus() &&
- nsContentUtils::ContentIsDescendantOf(focusedContent, document) ?
- focusedContent.forget() : nullptr;
- }
-
- // We're HTML editor for contenteditable
-
- // If the focused content isn't editable, or it has independent selection,
- // we don't have focus.
- if (!focusedContent->HasFlag(NODE_IS_EDITABLE) ||
- focusedContent->HasIndependentSelection()) {
- return nullptr;
- }
- // If our window is focused, we're focused.
- return OurWindowHasFocus() ? focusedContent.forget() : nullptr;
-}
-
-already_AddRefed<nsIContent>
-HTMLEditor::GetFocusedContentForIME()
-{
- nsCOMPtr<nsIContent> focusedContent = GetFocusedContent();
- if (!focusedContent) {
- return nullptr;
- }
-
- nsCOMPtr<nsIDocument> document = GetDocument();
- if (NS_WARN_IF(!document)) {
- return nullptr;
- }
- return document->HasFlag(NODE_IS_EDITABLE) ? nullptr :
- focusedContent.forget();
-}
-
-bool
-HTMLEditor::IsActiveInDOMWindow()
-{
- nsFocusManager* fm = nsFocusManager::GetFocusManager();
- NS_ENSURE_TRUE(fm, false);
-
- nsCOMPtr<nsIDocument> document = GetDocument();
- if (NS_WARN_IF(!document)) {
- return false;
- }
- bool inDesignMode = document->HasFlag(NODE_IS_EDITABLE);
-
- // If we're in designMode, we're always active in the DOM window.
- if (inDesignMode) {
- return true;
- }
-
- nsPIDOMWindowOuter* ourWindow = document->GetWindow();
- nsCOMPtr<nsPIDOMWindowOuter> win;
- nsIContent* content =
- nsFocusManager::GetFocusedDescendant(ourWindow, false,
- getter_AddRefs(win));
- if (!content) {
- return false;
- }
-
- // We're HTML editor for contenteditable
-
- // If the active content isn't editable, or it has independent selection,
- // we're not active).
- if (!content->HasFlag(NODE_IS_EDITABLE) ||
- content->HasIndependentSelection()) {
- return false;
- }
- return true;
-}
-
-Element*
-HTMLEditor::GetActiveEditingHost()
-{
- nsCOMPtr<nsIDocument> document = GetDocument();
- if (NS_WARN_IF(!document)) {
- return nullptr;
- }
- if (document->HasFlag(NODE_IS_EDITABLE)) {
- return document->GetBodyElement();
- }
-
- // We're HTML editor for contenteditable
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, nullptr);
- nsCOMPtr<nsIDOMNode> focusNode;
- nsresult rv = selection->GetFocusNode(getter_AddRefs(focusNode));
- NS_ENSURE_SUCCESS(rv, nullptr);
- nsCOMPtr<nsIContent> content = do_QueryInterface(focusNode);
- if (!content) {
- return nullptr;
- }
-
- // If the active content isn't editable, or it has independent selection,
- // we're not active.
- if (!content->HasFlag(NODE_IS_EDITABLE) ||
- content->HasIndependentSelection()) {
- return nullptr;
- }
- return content->GetEditingHost();
-}
-
-already_AddRefed<EventTarget>
-HTMLEditor::GetDOMEventTarget()
-{
- // Don't use getDocument here, because we have no way of knowing
- // whether Init() was ever called. So we need to get the document
- // ourselves, if it exists.
- MOZ_ASSERT(IsInitialized(), "The HTMLEditor has not been initialized yet");
- nsCOMPtr<mozilla::dom::EventTarget> target = GetDocument();
- return target.forget();
-}
-
-bool
-HTMLEditor::ShouldReplaceRootElement()
-{
- if (!mRootElement) {
- // If we don't know what is our root element, we should find our root.
- return true;
- }
-
- // If we temporary set document root element to mRootElement, but there is
- // body element now, we should replace the root element by the body element.
- nsCOMPtr<nsIDOMHTMLElement> docBody;
- GetBodyElement(getter_AddRefs(docBody));
- return !SameCOMIdentity(docBody, mRootElement);
-}
-
-void
-HTMLEditor::NotifyRootChanged()
-{
- nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
-
- RemoveEventListeners();
- nsresult rv = InstallEventListeners();
- if (NS_FAILED(rv)) {
- return;
- }
-
- UpdateRootElement();
- if (!mRootElement) {
- return;
- }
-
- rv = BeginningOfDocument();
- if (NS_FAILED(rv)) {
- return;
- }
-
- // When this editor has focus, we need to reset the selection limiter to
- // new root. Otherwise, that is going to be done when this gets focus.
- nsCOMPtr<nsINode> node = GetFocusedNode();
- nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(node);
- if (target) {
- InitializeSelection(target);
- }
-
- SyncRealTimeSpell();
-}
-
-nsresult
-HTMLEditor::GetBodyElement(nsIDOMHTMLElement** aBody)
-{
- MOZ_ASSERT(IsInitialized(), "The HTMLEditor hasn't been initialized yet");
- nsCOMPtr<nsIDocument> document = GetDocument();
- if (NS_WARN_IF(!document)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- nsCOMPtr<nsIDOMHTMLDocument> domHTMLDocument = do_QueryInterface(document);
- if (!domHTMLDocument) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- return domHTMLDocument->GetBody(aBody);
-}
-
-already_AddRefed<nsINode>
-HTMLEditor::GetFocusedNode()
-{
- nsCOMPtr<nsIContent> focusedContent = GetFocusedContent();
- if (!focusedContent) {
- return nullptr;
- }
-
- nsIFocusManager* fm = nsFocusManager::GetFocusManager();
- NS_ASSERTION(fm, "Focus manager is null");
- nsCOMPtr<nsIDOMElement> focusedElement;
- fm->GetFocusedElement(getter_AddRefs(focusedElement));
- if (focusedElement) {
- nsCOMPtr<nsINode> node = do_QueryInterface(focusedElement);
- return node.forget();
- }
-
- nsCOMPtr<nsIDocument> document = GetDocument();
- return document.forget();
-}
-
-bool
-HTMLEditor::OurWindowHasFocus()
-{
- nsIFocusManager* fm = nsFocusManager::GetFocusManager();
- NS_ENSURE_TRUE(fm, false);
- nsCOMPtr<mozIDOMWindowProxy> focusedWindow;
- fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
- if (!focusedWindow) {
- return false;
- }
- nsCOMPtr<nsIDocument> document = GetDocument();
- if (NS_WARN_IF(!document)) {
- return false;
- }
- nsPIDOMWindowOuter* ourWindow = document->GetWindow();
- return ourWindow == focusedWindow;
-}
-
-bool
-HTMLEditor::IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent)
-{
- if (!EditorBase::IsAcceptableInputEvent(aGUIEvent)) {
- return false;
- }
-
- // While there is composition, all composition events in its top level window
- // are always fired on the composing editor. Therefore, if this editor has
- // composition, the composition events should be handled in this editor.
- if (mComposition && aGUIEvent->AsCompositionEvent()) {
- return true;
- }
-
- nsCOMPtr<nsIDOMEventTarget> target = aGUIEvent->GetDOMEventTarget();
- NS_ENSURE_TRUE(target, false);
-
- nsCOMPtr<nsIDocument> document = GetDocument();
- if (NS_WARN_IF(!document)) {
- return false;
- }
-
- if (document->HasFlag(NODE_IS_EDITABLE)) {
- // If this editor is in designMode and the event target is the document,
- // the event is for this editor.
- nsCOMPtr<nsIDocument> targetDocument = do_QueryInterface(target);
- if (targetDocument) {
- return targetDocument == document;
- }
- // Otherwise, check whether the event target is in this document or not.
- nsCOMPtr<nsIContent> targetContent = do_QueryInterface(target);
- NS_ENSURE_TRUE(targetContent, false);
- return document == targetContent->GetUncomposedDoc();
- }
-
- // This HTML editor is for contenteditable. We need to check the validity of
- // the target.
- nsCOMPtr<nsIContent> targetContent = do_QueryInterface(target);
- NS_ENSURE_TRUE(targetContent, false);
-
- // If the event is a mouse event, we need to check if the target content is
- // the focused editing host or its descendant.
- if (aGUIEvent->AsMouseEventBase()) {
- nsIContent* editingHost = GetActiveEditingHost();
- // If there is no active editing host, we cannot handle the mouse event
- // correctly.
- if (!editingHost) {
- return false;
- }
- // If clicked on non-editable root element but the body element is the
- // active editing host, we should assume that the click event is targetted.
- if (targetContent == document->GetRootElement() &&
- !targetContent->HasFlag(NODE_IS_EDITABLE) &&
- editingHost == document->GetBodyElement()) {
- targetContent = editingHost;
- }
- // If the target element is neither the active editing host nor a descendant
- // of it, we may not be able to handle the event.
- if (!nsContentUtils::ContentIsDescendantOf(targetContent, editingHost)) {
- return false;
- }
- // If the clicked element has an independent selection, we shouldn't
- // handle this click event.
- if (targetContent->HasIndependentSelection()) {
- return false;
- }
- // If the target content is editable, we should handle this event.
- return targetContent->HasFlag(NODE_IS_EDITABLE);
- }
-
- // If the target of the other events which target focused element isn't
- // editable or has an independent selection, this editor shouldn't handle the
- // event.
- if (!targetContent->HasFlag(NODE_IS_EDITABLE) ||
- targetContent->HasIndependentSelection()) {
- return false;
- }
-
- // Finally, check whether we're actually focused or not. When we're not
- // focused, we should ignore the dispatched event by script (or something)
- // because content editable element needs selection in itself for editing.
- // However, when we're not focused, it's not guaranteed.
- return IsActiveInDOMWindow();
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetPreferredIMEState(IMEState* aState)
-{
- // HTML editor don't prefer the CSS ime-mode because IE didn't do so too.
- aState->mOpen = IMEState::DONT_CHANGE_OPEN_STATE;
- if (IsReadonly() || IsDisabled()) {
- aState->mEnabled = IMEState::DISABLED;
- } else {
- aState->mEnabled = IMEState::ENABLED;
- }
- return NS_OK;
-}
-
-already_AddRefed<nsIContent>
-HTMLEditor::GetInputEventTargetContent()
-{
- nsCOMPtr<nsIContent> target = GetActiveEditingHost();
- return target.forget();
-}
-
-bool
-HTMLEditor::IsEditable(nsINode* aNode)
-{
- if (!TextEditor::IsEditable(aNode)) {
- return false;
- }
- if (aNode->IsElement()) {
- // If we're dealing with an element, then ask it whether it's editable.
- return aNode->IsEditable();
- }
- // We might be dealing with a text node for example, which we always consider
- // to be editable.
- return true;
-}
-
-Element*
-HTMLEditor::GetEditorRoot()
-{
- return GetActiveEditingHost();
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/HTMLEditor.h b/editor/libeditor/HTMLEditor.h
deleted file mode 100644
index 494e7c383..000000000
--- a/editor/libeditor/HTMLEditor.h
+++ /dev/null
@@ -1,1111 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_HTMLEditor_h
-#define mozilla_HTMLEditor_h
-
-#include "mozilla/Attributes.h"
-#include "mozilla/CSSEditUtils.h"
-#include "mozilla/StyleSheet.h"
-#include "mozilla/TextEditor.h"
-#include "mozilla/UniquePtr.h"
-#include "mozilla/dom/Element.h"
-#include "mozilla/dom/File.h"
-
-#include "nsAttrName.h"
-#include "nsCOMPtr.h"
-#include "nsIContentFilter.h"
-#include "nsICSSLoaderObserver.h"
-#include "nsIDocumentObserver.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMEventListener.h"
-#include "nsIEditor.h"
-#include "nsIEditorMailSupport.h"
-#include "nsIEditorStyleSheets.h"
-#include "nsIEditorUtils.h"
-#include "nsIEditRules.h"
-#include "nsIHTMLAbsPosEditor.h"
-#include "nsIHTMLEditor.h"
-#include "nsIHTMLInlineTableEditor.h"
-#include "nsIHTMLObjectResizeListener.h"
-#include "nsIHTMLObjectResizer.h"
-#include "nsISelectionListener.h"
-#include "nsITableEditor.h"
-#include "nsPoint.h"
-#include "nsStubMutationObserver.h"
-#include "nsTArray.h"
-
-class nsDocumentFragment;
-class nsIDOMKeyEvent;
-class nsITransferable;
-class nsIClipboard;
-class nsILinkHandler;
-class nsTableWrapperFrame;
-class nsIDOMRange;
-class nsRange;
-
-namespace mozilla {
-
-class HTMLEditorEventListener;
-class HTMLEditRules;
-class TextEditRules;
-class TypeInState;
-class WSRunObject;
-struct PropItem;
-template<class T> class OwningNonNull;
-namespace dom {
-class DocumentFragment;
-} // namespace dom
-namespace widget {
-struct IMEState;
-} // namespace widget
-
-/**
- * The HTML editor implementation.<br>
- * Use to edit HTML document represented as a DOM tree.
- */
-class HTMLEditor final : public TextEditor
- , public nsIHTMLEditor
- , public nsIHTMLObjectResizer
- , public nsIHTMLAbsPosEditor
- , public nsITableEditor
- , public nsIHTMLInlineTableEditor
- , public nsIEditorStyleSheets
- , public nsICSSLoaderObserver
- , public nsStubMutationObserver
-{
-private:
- enum BlockTransformationType
- {
- eNoOp,
- eReplaceParent = 1,
- eInsertParent = 2
- };
-
- const char16_t kNBSP = 160;
-
-public:
- enum ResizingRequestID
- {
- kX = 0,
- kY = 1,
- kWidth = 2,
- kHeight = 3
- };
-
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLEditor, TextEditor)
-
- HTMLEditor();
-
- bool GetReturnInParagraphCreatesNewParagraph();
- Element* GetSelectionContainer();
-
- // TextEditor overrides
- NS_IMETHOD GetIsDocumentEditable(bool* aIsDocumentEditable) override;
- NS_IMETHOD BeginningOfDocument() override;
- virtual nsresult HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent) override;
- virtual already_AddRefed<nsIContent> GetFocusedContent() override;
- virtual already_AddRefed<nsIContent> GetFocusedContentForIME() override;
- virtual bool IsActiveInDOMWindow() override;
- virtual already_AddRefed<dom::EventTarget> GetDOMEventTarget() override;
- virtual Element* GetEditorRoot() override;
- virtual already_AddRefed<nsIContent> FindSelectionRoot(
- nsINode *aNode) override;
- virtual bool IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent) override;
- virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override;
- virtual bool IsEditable(nsINode* aNode) override;
- using EditorBase::IsEditable;
- virtual nsresult RemoveAttributeOrEquivalent(
- Element* aElement,
- nsIAtom* aAttribute,
- bool aSuppressTransaction) override;
- virtual nsresult SetAttributeOrEquivalent(Element* aElement,
- nsIAtom* aAttribute,
- const nsAString& aValue,
- bool aSuppressTransaction) override;
- using EditorBase::RemoveAttributeOrEquivalent;
- using EditorBase::SetAttributeOrEquivalent;
-
- // nsStubMutationObserver overrides
- NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
- NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
- NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
-
- // nsIEditorIMESupport overrides
- NS_IMETHOD GetPreferredIMEState(widget::IMEState* aState) override;
-
- // nsIHTMLEditor methods
- NS_DECL_NSIHTMLEDITOR
-
- // nsIHTMLObjectResizer methods (implemented in HTMLObjectResizer.cpp)
- NS_DECL_NSIHTMLOBJECTRESIZER
-
- // nsIHTMLAbsPosEditor methods (implemented in HTMLAbsPositionEditor.cpp)
- NS_DECL_NSIHTMLABSPOSEDITOR
-
- // nsIHTMLInlineTableEditor methods (implemented in HTMLInlineTableEditor.cpp)
- NS_DECL_NSIHTMLINLINETABLEEDITOR
-
- // XXX Following methods are not overriding but defined here...
- nsresult CopyLastEditableChildStyles(nsIDOMNode* aPreviousBlock,
- nsIDOMNode* aNewBlock,
- Element** aOutBrNode);
-
- nsresult LoadHTML(const nsAString& aInputString);
-
- nsresult GetCSSBackgroundColorState(bool* aMixed, nsAString& aOutColor,
- bool aBlockLevel);
- NS_IMETHOD GetHTMLBackgroundColorState(bool* aMixed, nsAString& outColor);
-
- // nsIEditorStyleSheets methods
- NS_IMETHOD AddStyleSheet(const nsAString& aURL) override;
- NS_IMETHOD ReplaceStyleSheet(const nsAString& aURL) override;
- NS_IMETHOD RemoveStyleSheet(const nsAString &aURL) override;
-
- NS_IMETHOD AddOverrideStyleSheet(const nsAString& aURL) override;
- NS_IMETHOD ReplaceOverrideStyleSheet(const nsAString& aURL) override;
- NS_IMETHOD RemoveOverrideStyleSheet(const nsAString &aURL) override;
-
- NS_IMETHOD EnableStyleSheet(const nsAString& aURL, bool aEnable) override;
-
- // nsIEditorMailSupport methods
- NS_DECL_NSIEDITORMAILSUPPORT
-
- // nsITableEditor methods
- NS_IMETHOD InsertTableCell(int32_t aNumber, bool aAfter) override;
- NS_IMETHOD InsertTableColumn(int32_t aNumber, bool aAfter) override;
- NS_IMETHOD InsertTableRow(int32_t aNumber, bool aAfter) override;
- NS_IMETHOD DeleteTable() override;
- NS_IMETHOD DeleteTableCell(int32_t aNumber) override;
- NS_IMETHOD DeleteTableCellContents() override;
- NS_IMETHOD DeleteTableColumn(int32_t aNumber) override;
- NS_IMETHOD DeleteTableRow(int32_t aNumber) override;
- NS_IMETHOD SelectTableCell() override;
- NS_IMETHOD SelectBlockOfCells(nsIDOMElement* aStartCell,
- nsIDOMElement* aEndCell) override;
- NS_IMETHOD SelectTableRow() override;
- NS_IMETHOD SelectTableColumn() override;
- NS_IMETHOD SelectTable() override;
- NS_IMETHOD SelectAllTableCells() override;
- NS_IMETHOD SwitchTableCellHeaderType(nsIDOMElement* aSourceCell,
- nsIDOMElement** aNewCell) override;
- NS_IMETHOD JoinTableCells(bool aMergeNonContiguousContents) override;
- NS_IMETHOD SplitTableCell() override;
- NS_IMETHOD NormalizeTable(nsIDOMElement* aTable) override;
- NS_IMETHOD GetCellIndexes(nsIDOMElement* aCell,
- int32_t* aRowIndex, int32_t* aColIndex) override;
- NS_IMETHOD GetTableSize(nsIDOMElement* aTable,
- int32_t* aRowCount, int32_t* aColCount) override;
- NS_IMETHOD GetCellAt(nsIDOMElement* aTable, int32_t aRowIndex,
- int32_t aColIndex, nsIDOMElement **aCell) override;
- NS_IMETHOD GetCellDataAt(nsIDOMElement* aTable,
- int32_t aRowIndex, int32_t aColIndex,
- nsIDOMElement** aCell,
- int32_t* aStartRowIndex, int32_t* aStartColIndex,
- int32_t* aRowSpan, int32_t* aColSpan,
- int32_t* aActualRowSpan, int32_t* aActualColSpan,
- bool* aIsSelected) override;
- NS_IMETHOD GetFirstRow(nsIDOMElement* aTableElement,
- nsIDOMNode** aRowNode) override;
- NS_IMETHOD GetNextRow(nsIDOMNode* aCurrentRowNode,
- nsIDOMNode** aRowNode) override;
- nsresult GetLastCellInRow(nsIDOMNode* aRowNode,
- nsIDOMNode** aCellNode);
-
- NS_IMETHOD SetSelectionAfterTableEdit(nsIDOMElement* aTable, int32_t aRow,
- int32_t aCol, int32_t aDirection,
- bool aSelected) override;
- NS_IMETHOD GetSelectedOrParentTableElement(
- nsAString& aTagName, int32_t* aSelectedCount,
- nsIDOMElement** aTableElement) override;
- NS_IMETHOD GetSelectedCellsType(nsIDOMElement* aElement,
- uint32_t* aSelectionType) override;
-
- nsresult GetCellFromRange(nsRange* aRange, nsIDOMElement** aCell);
-
- /**
- * Finds the first selected cell in first range of selection
- * This is in the *order of selection*, not order in the table
- * (i.e., each cell added to selection is added in another range
- * in the selection's rangelist, independent of location in table)
- * aRange is optional: returns the range around the cell.
- */
- NS_IMETHOD GetFirstSelectedCell(nsIDOMRange** aRange,
- nsIDOMElement** aCell) override;
- /**
- * Get next cell until no more are found. Always use GetFirstSelected cell
- * first aRange is optional: returns the range around the cell.
- */
- NS_IMETHOD GetNextSelectedCell(nsIDOMRange** aRange,
- nsIDOMElement** aCell) override;
-
- /**
- * Upper-left-most selected cell in table.
- */
- NS_IMETHOD GetFirstSelectedCellInTable(int32_t* aRowIndex, int32_t* aColIndex,
- nsIDOMElement** aCell) override;
-
- // Miscellaneous
-
- /**
- * This sets background on the appropriate container element (table, cell,)
- * or calls into nsTextEditor to set the page background.
- */
- nsresult SetCSSBackgroundColor(const nsAString& aColor);
- nsresult SetHTMLBackgroundColor(const nsAString& aColor);
-
- // Block methods moved from EditorBase
- static Element* GetBlockNodeParent(nsINode* aNode);
- static nsIDOMNode* GetBlockNodeParent(nsIDOMNode* aNode);
- static Element* GetBlock(nsINode& aNode);
-
- void IsNextCharInNodeWhitespace(nsIContent* aContent,
- int32_t aOffset,
- bool* outIsSpace,
- bool* outIsNBSP,
- nsIContent** outNode = nullptr,
- int32_t* outOffset = 0);
- void IsPrevCharInNodeWhitespace(nsIContent* aContent,
- int32_t aOffset,
- bool* outIsSpace,
- bool* outIsNBSP,
- nsIContent** outNode = nullptr,
- int32_t* outOffset = 0);
-
- // Overrides of EditorBase interface methods
- nsresult EndUpdateViewBatch() override;
-
- NS_IMETHOD Init(nsIDOMDocument* aDoc, nsIContent* aRoot,
- nsISelectionController* aSelCon, uint32_t aFlags,
- const nsAString& aValue) override;
- NS_IMETHOD PreDestroy(bool aDestroyingFrames) override;
-
- /**
- * @param aElement Must not be null.
- */
- static bool NodeIsBlockStatic(const nsINode* aElement);
- static nsresult NodeIsBlockStatic(nsIDOMNode *aNode, bool *aIsBlock);
-
-protected:
- virtual ~HTMLEditor();
-
- using EditorBase::IsBlockNode;
- virtual bool IsBlockNode(nsINode *aNode) override;
-
-public:
- // XXX Why don't we move following methods above for grouping by the origins?
- NS_IMETHOD SetFlags(uint32_t aFlags) override;
-
- NS_IMETHOD Paste(int32_t aSelectionType) override;
- NS_IMETHOD CanPaste(int32_t aSelectionType, bool* aCanPaste) override;
-
- NS_IMETHOD PasteTransferable(nsITransferable* aTransferable) override;
- NS_IMETHOD CanPasteTransferable(nsITransferable* aTransferable,
- bool* aCanPaste) override;
-
- NS_IMETHOD DebugUnitTests(int32_t* outNumTests,
- int32_t* outNumTestsFailed) override;
-
- /**
- * All editor operations which alter the doc should be prefaced
- * with a call to StartOperation, naming the action and direction.
- */
- NS_IMETHOD StartOperation(EditAction opID,
- nsIEditor::EDirection aDirection) override;
-
- /**
- * All editor operations which alter the doc should be followed
- * with a call to EndOperation.
- */
- NS_IMETHOD EndOperation() override;
-
- /**
- * returns true if aParentTag can contain a child of type aChildTag.
- */
- virtual bool TagCanContainTag(nsIAtom& aParentTag,
- nsIAtom& aChildTag) override;
-
- /**
- * Returns true if aNode is a container.
- */
- virtual bool IsContainer(nsINode* aNode) override;
- virtual bool IsContainer(nsIDOMNode* aNode) override;
-
- /**
- * Make the given selection span the entire document.
- */
- virtual nsresult SelectEntireDocument(Selection* aSelection) override;
-
- /**
- * Join together any adjacent editable text nodes in the range.
- */
- nsresult CollapseAdjacentTextNodes(nsRange* aRange);
-
- virtual bool AreNodesSameType(nsIContent* aNode1,
- nsIContent* aNode2) override;
-
- NS_IMETHOD DeleteSelectionImpl(EDirection aAction,
- EStripWrappers aStripWrappers) override;
- nsresult DeleteNode(nsINode* aNode);
- NS_IMETHOD DeleteNode(nsIDOMNode* aNode) override;
- nsresult DeleteText(nsGenericDOMDataNode& aTextNode, uint32_t aOffset,
- uint32_t aLength);
- virtual nsresult InsertTextImpl(const nsAString& aStringToInsert,
- nsCOMPtr<nsINode>* aInOutNode,
- int32_t* aInOutOffset,
- nsIDocument* aDoc) override;
- NS_IMETHOD_(bool) IsModifiableNode(nsIDOMNode* aNode) override;
- virtual bool IsModifiableNode(nsINode* aNode) override;
-
- NS_IMETHOD GetIsSelectionEditable(bool* aIsSelectionEditable) override;
-
- NS_IMETHOD SelectAll() override;
-
- // nsICSSLoaderObserver
- NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet,
- bool aWasAlternate, nsresult aStatus) override;
-
- // Utility Routines, not part of public API
- NS_IMETHOD TypedText(const nsAString& aString,
- ETypingAction aAction) override;
- nsresult InsertNodeAtPoint(nsIDOMNode* aNode,
- nsCOMPtr<nsIDOMNode>* ioParent,
- int32_t* ioOffset,
- bool aNoEmptyNodes);
-
- /**
- * Use this to assure that selection is set after attribute nodes when
- * trying to collapse selection at begining of a block node
- * e.g., when setting at beginning of a table cell
- * This will stop at a table, however, since we don't want to
- * "drill down" into nested tables.
- * @param aSelection Optional. If null, we get current selection.
- */
- void CollapseSelectionToDeepestNonTableFirstChild(Selection* aSelection,
- nsINode* aNode);
-
- /**
- * aNode must be a non-null text node.
- * outIsEmptyNode must be non-null.
- */
- nsresult IsVisTextNode(nsIContent* aNode,
- bool* outIsEmptyNode,
- bool aSafeToAskFrames);
- nsresult IsEmptyNode(nsIDOMNode* aNode, bool* outIsEmptyBlock,
- bool aMozBRDoesntCount = false,
- bool aListOrCellNotEmpty = false,
- bool aSafeToAskFrames = false);
- nsresult IsEmptyNode(nsINode* aNode, bool* outIsEmptyBlock,
- bool aMozBRDoesntCount = false,
- bool aListOrCellNotEmpty = false,
- bool aSafeToAskFrames = false);
- nsresult IsEmptyNodeImpl(nsINode* aNode,
- bool* outIsEmptyBlock,
- bool aMozBRDoesntCount,
- bool aListOrCellNotEmpty,
- bool aSafeToAskFrames,
- bool* aSeenBR);
-
- /**
- * Returns TRUE if sheet was loaded, false if it wasn't.
- */
- bool EnableExistingStyleSheet(const nsAString& aURL);
-
- /**
- * Dealing with the internal style sheet lists.
- */
- StyleSheet* GetStyleSheetForURL(const nsAString& aURL);
- void GetURLForStyleSheet(StyleSheet* aStyleSheet,
- nsAString& aURL);
-
- /**
- * Add a url + known style sheet to the internal lists.
- */
- nsresult AddNewStyleSheetToList(const nsAString &aURL,
- StyleSheet* aStyleSheet);
- nsresult RemoveStyleSheetFromList(const nsAString &aURL);
-
- bool IsCSSEnabled()
- {
- // TODO: removal of mCSSAware and use only the presence of mCSSEditUtils
- return mCSSAware && mCSSEditUtils && mCSSEditUtils->IsCSSPrefChecked();
- }
-
- static bool HasAttributes(Element* aElement)
- {
- MOZ_ASSERT(aElement);
- uint32_t attrCount = aElement->GetAttrCount();
- return attrCount > 1 ||
- (1 == attrCount &&
- !aElement->GetAttrNameAt(0)->Equals(nsGkAtoms::mozdirty));
- }
-
-protected:
- class BlobReader final : public nsIEditorBlobListener
- {
- public:
- BlobReader(dom::BlobImpl* aBlob, HTMLEditor* aHTMLEditor,
- bool aIsSafe, nsIDOMDocument* aSourceDoc,
- nsIDOMNode* aDestinationNode, int32_t aDestOffset,
- bool aDoDeleteSelection);
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSIEDITORBLOBLISTENER
-
- private:
- ~BlobReader()
- {
- }
-
- RefPtr<dom::BlobImpl> mBlob;
- RefPtr<HTMLEditor> mHTMLEditor;
- bool mIsSafe;
- nsCOMPtr<nsIDOMDocument> mSourceDoc;
- nsCOMPtr<nsIDOMNode> mDestinationNode;
- int32_t mDestOffset;
- bool mDoDeleteSelection;
- };
-
- NS_IMETHOD InitRules() override;
-
- virtual void CreateEventListeners() override;
- virtual nsresult InstallEventListeners() override;
- virtual void RemoveEventListeners() override;
-
- bool ShouldReplaceRootElement();
- void NotifyRootChanged();
- nsresult GetBodyElement(nsIDOMHTMLElement** aBody);
-
- /**
- * Get the focused node of this editor.
- * @return If the editor has focus, this returns the focused node.
- * Otherwise, returns null.
- */
- already_AddRefed<nsINode> GetFocusedNode();
-
- /**
- * Return TRUE if aElement is a table-related elemet and caret was set.
- */
- bool SetCaretInTableCell(nsIDOMElement* aElement);
-
- NS_IMETHOD TabInTable(bool inIsShift, bool* outHandled);
- already_AddRefed<Element> CreateBR(nsINode* aNode, int32_t aOffset,
- EDirection aSelect = eNone);
- NS_IMETHOD CreateBR(
- nsIDOMNode* aNode, int32_t aOffset,
- nsCOMPtr<nsIDOMNode>* outBRNode,
- nsIEditor::EDirection aSelect = nsIEditor::eNone) override;
-
- // Table Editing (implemented in nsTableEditor.cpp)
-
- /**
- * Insert a new cell after or before supplied aCell.
- * Optional: If aNewCell supplied, returns the newly-created cell (addref'd,
- * of course)
- * This doesn't change or use the current selection.
- */
- NS_IMETHOD InsertCell(nsIDOMElement* aCell, int32_t aRowSpan,
- int32_t aColSpan, bool aAfter, bool aIsHeader,
- nsIDOMElement** aNewCell);
-
- /**
- * Helpers that don't touch the selection or do batch transactions.
- */
- NS_IMETHOD DeleteRow(nsIDOMElement* aTable, int32_t aRowIndex);
- NS_IMETHOD DeleteColumn(nsIDOMElement* aTable, int32_t aColIndex);
- NS_IMETHOD DeleteCellContents(nsIDOMElement* aCell);
-
- /**
- * Move all contents from aCellToMerge into aTargetCell (append at end).
- */
- NS_IMETHOD MergeCells(nsCOMPtr<nsIDOMElement> aTargetCell,
- nsCOMPtr<nsIDOMElement> aCellToMerge,
- bool aDeleteCellToMerge);
-
- nsresult DeleteTable2(nsIDOMElement* aTable, Selection* aSelection);
- NS_IMETHOD SetColSpan(nsIDOMElement* aCell, int32_t aColSpan);
- NS_IMETHOD SetRowSpan(nsIDOMElement* aCell, int32_t aRowSpan);
-
- /**
- * Helper used to get nsTableWrapperFrame for a table.
- */
- nsTableWrapperFrame* GetTableFrame(nsIDOMElement* aTable);
-
- /**
- * Needed to do appropriate deleting when last cell or row is about to be
- * deleted. This doesn't count cells that don't start in the given row (are
- * spanning from row above).
- */
- int32_t GetNumberOfCellsInRow(nsIDOMElement* aTable, int32_t rowIndex);
-
- /**
- * Test if all cells in row or column at given index are selected.
- */
- bool AllCellsInRowSelected(nsIDOMElement* aTable, int32_t aRowIndex,
- int32_t aNumberOfColumns);
- bool AllCellsInColumnSelected(nsIDOMElement* aTable, int32_t aColIndex,
- int32_t aNumberOfRows);
-
- bool IsEmptyCell(Element* aCell);
-
- /**
- * Most insert methods need to get the same basic context data.
- * Any of the pointers may be null if you don't need that datum (for more
- * efficiency).
- * Input: *aCell is a known cell,
- * if null, cell is obtained from the anchor node of the selection.
- * Returns NS_EDITOR_ELEMENT_NOT_FOUND if cell is not found even if aCell is
- * null.
- */
- nsresult GetCellContext(Selection** aSelection, nsIDOMElement** aTable,
- nsIDOMElement** aCell, nsIDOMNode** aCellParent,
- int32_t* aCellOffset, int32_t* aRowIndex,
- int32_t* aColIndex);
-
- NS_IMETHOD GetCellSpansAt(nsIDOMElement* aTable, int32_t aRowIndex,
- int32_t aColIndex, int32_t& aActualRowSpan,
- int32_t& aActualColSpan);
-
- NS_IMETHOD SplitCellIntoColumns(nsIDOMElement* aTable, int32_t aRowIndex,
- int32_t aColIndex, int32_t aColSpanLeft,
- int32_t aColSpanRight,
- nsIDOMElement** aNewCell);
-
- NS_IMETHOD SplitCellIntoRows(nsIDOMElement* aTable, int32_t aRowIndex,
- int32_t aColIndex, int32_t aRowSpanAbove,
- int32_t aRowSpanBelow, nsIDOMElement** aNewCell);
-
- nsresult CopyCellBackgroundColor(nsIDOMElement* destCell,
- nsIDOMElement* sourceCell);
-
- /**
- * Reduce rowspan/colspan when cells span into nonexistent rows/columns.
- */
- NS_IMETHOD FixBadRowSpan(nsIDOMElement* aTable, int32_t aRowIndex,
- int32_t& aNewRowCount);
- NS_IMETHOD FixBadColSpan(nsIDOMElement* aTable, int32_t aColIndex,
- int32_t& aNewColCount);
-
- /**
- * Fallback method: Call this after using ClearSelection() and you
- * failed to set selection to some other content in the document.
- */
- nsresult SetSelectionAtDocumentStart(Selection* aSelection);
-
- // End of Table Editing utilities
-
- static Element* GetEnclosingTable(nsINode* aNode);
- static nsIDOMNode* GetEnclosingTable(nsIDOMNode* aNode);
-
- /**
- * Content-based query returns true if <aProperty aAttribute=aValue> effects
- * aNode. If <aProperty aAttribute=aValue> contains aNode, but
- * <aProperty aAttribute=SomeOtherValue> also contains aNode and the second is
- * more deeply nested than the first, then the first does not effect aNode.
- *
- * @param aNode The target of the query
- * @param aProperty The property that we are querying for
- * @param aAttribute The attribute of aProperty, example: color in
- * <FONT color="blue"> May be null.
- * @param aValue The value of aAttribute, example: blue in
- * <FONT color="blue"> May be null. Ignored if aAttribute
- * is null.
- * @param aIsSet [OUT] true if <aProperty aAttribute=aValue> effects
- * aNode.
- * @param outValue [OUT] the value of the attribute, if aIsSet is true
- *
- * The nsIContent variant returns aIsSet instead of using an out parameter.
- */
- bool IsTextPropertySetByContent(nsINode* aNode,
- nsIAtom* aProperty,
- const nsAString* aAttribute,
- const nsAString* aValue,
- nsAString* outValue = nullptr);
-
- void IsTextPropertySetByContent(nsIDOMNode* aNode,
- nsIAtom* aProperty,
- const nsAString* aAttribute,
- const nsAString* aValue,
- bool& aIsSet,
- nsAString* outValue = nullptr);
-
- // Methods for handling plaintext quotations
- NS_IMETHOD PasteAsPlaintextQuotation(int32_t aSelectionType);
-
- /**
- * Insert a string as quoted text, replacing the selected text (if any).
- * @param aQuotedText The string to insert.
- * @param aAddCites Whether to prepend extra ">" to each line
- * (usually true, unless those characters
- * have already been added.)
- * @return aNodeInserted The node spanning the insertion, if applicable.
- * If aAddCites is false, this will be null.
- */
- NS_IMETHOD InsertAsPlaintextQuotation(const nsAString& aQuotedText,
- bool aAddCites,
- nsIDOMNode** aNodeInserted);
-
- nsresult InsertObject(const nsACString& aType, nsISupports* aObject,
- bool aIsSafe,
- nsIDOMDocument* aSourceDoc,
- nsIDOMNode* aDestinationNode,
- int32_t aDestOffset,
- bool aDoDeleteSelection);
-
- // factored methods for handling insertion of data from transferables
- // (drag&drop or clipboard)
- NS_IMETHOD PrepareTransferable(nsITransferable** transferable) override;
- nsresult PrepareHTMLTransferable(nsITransferable** transferable);
- nsresult InsertFromTransferable(nsITransferable* transferable,
- nsIDOMDocument* aSourceDoc,
- const nsAString& aContextStr,
- const nsAString& aInfoStr,
- bool havePrivateHTMLFlavor,
- nsIDOMNode *aDestinationNode,
- int32_t aDestinationOffset,
- bool aDoDeleteSelection);
- nsresult InsertFromDataTransfer(dom::DataTransfer* aDataTransfer,
- int32_t aIndex,
- nsIDOMDocument* aSourceDoc,
- nsIDOMNode* aDestinationNode,
- int32_t aDestOffset,
- bool aDoDeleteSelection) override;
- bool HavePrivateHTMLFlavor(nsIClipboard* clipboard );
- nsresult ParseCFHTML(nsCString& aCfhtml, char16_t** aStuffToPaste,
- char16_t** aCfcontext);
- nsresult DoContentFilterCallback(const nsAString& aFlavor,
- nsIDOMDocument* aSourceDoc,
- bool aWillDeleteSelection,
- nsIDOMNode** aFragmentAsNode,
- nsIDOMNode** aFragStartNode,
- int32_t* aFragStartOffset,
- nsIDOMNode** aFragEndNode,
- int32_t* aFragEndOffset,
- nsIDOMNode** aTargetNode,
- int32_t* aTargetOffset,
- bool* aDoContinue);
-
- bool IsInLink(nsIDOMNode* aNode, nsCOMPtr<nsIDOMNode>* outLink = nullptr);
- nsresult StripFormattingNodes(nsIContent& aNode, bool aOnlyList = false);
- nsresult CreateDOMFragmentFromPaste(const nsAString& aInputString,
- const nsAString& aContextStr,
- const nsAString& aInfoStr,
- nsCOMPtr<nsIDOMNode>* outFragNode,
- nsCOMPtr<nsIDOMNode>* outStartNode,
- nsCOMPtr<nsIDOMNode>* outEndNode,
- int32_t* outStartOffset,
- int32_t* outEndOffset,
- bool aTrustedInput);
- nsresult ParseFragment(const nsAString& aStr, nsIAtom* aContextLocalName,
- nsIDocument* aTargetDoc,
- dom::DocumentFragment** aFragment, bool aTrustedInput);
- void CreateListOfNodesToPaste(dom::DocumentFragment& aFragment,
- nsTArray<OwningNonNull<nsINode>>& outNodeList,
- nsINode* aStartNode,
- int32_t aStartOffset,
- nsINode* aEndNode,
- int32_t aEndOffset);
- nsresult CreateTagStack(nsTArray<nsString>& aTagStack,
- nsIDOMNode* aNode);
- enum class StartOrEnd { start, end };
- void GetListAndTableParents(StartOrEnd aStartOrEnd,
- nsTArray<OwningNonNull<nsINode>>& aNodeList,
- nsTArray<OwningNonNull<Element>>& outArray);
- int32_t DiscoverPartialListsAndTables(
- nsTArray<OwningNonNull<nsINode>>& aPasteNodes,
- nsTArray<OwningNonNull<Element>>& aListsAndTables);
- nsINode* ScanForListAndTableStructure(
- StartOrEnd aStartOrEnd,
- nsTArray<OwningNonNull<nsINode>>& aNodes,
- Element& aListOrTable);
- void ReplaceOrphanedStructure(
- StartOrEnd aStartOrEnd,
- nsTArray<OwningNonNull<nsINode>>& aNodeArray,
- nsTArray<OwningNonNull<Element>>& aListAndTableArray,
- int32_t aHighWaterMark);
-
- /**
- * Small utility routine to test if a break node is visible to user.
- */
- bool IsVisBreak(nsINode* aNode);
-
- /**
- * Utility routine to possibly adjust the insertion position when
- * inserting a block level element.
- */
- void NormalizeEOLInsertPosition(nsINode* firstNodeToInsert,
- nsCOMPtr<nsIDOMNode>* insertParentNode,
- int32_t* insertOffset);
-
- /**
- * Small utility routine to test the eEditorReadonly bit.
- */
- bool IsModifiable();
-
- /**
- * Helpers for block transformations.
- */
- nsresult MakeDefinitionItem(const nsAString& aItemType);
- nsresult InsertBasicBlock(const nsAString& aBlockType);
-
- /**
- * Increase/decrease the font size of selection.
- */
- enum class FontSize { incr, decr };
- nsresult RelativeFontChange(FontSize aDir);
-
- /**
- * Helper routines for font size changing.
- */
- nsresult RelativeFontChangeOnTextNode(FontSize aDir,
- Text& aTextNode,
- int32_t aStartOffset,
- int32_t aEndOffset);
- nsresult RelativeFontChangeOnNode(int32_t aSizeChange, nsIContent* aNode);
- nsresult RelativeFontChangeHelper(int32_t aSizeChange, nsINode* aNode);
-
- /**
- * Helper routines for inline style.
- */
- nsresult SetInlinePropertyOnTextNode(Text& aData,
- int32_t aStartOffset,
- int32_t aEndOffset,
- nsIAtom& aProperty,
- const nsAString* aAttribute,
- const nsAString& aValue);
- nsresult SetInlinePropertyOnNode(nsIContent& aNode,
- nsIAtom& aProperty,
- const nsAString* aAttribute,
- const nsAString& aValue);
-
- nsresult PromoteInlineRange(nsRange& aRange);
- nsresult PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange& aRange);
- nsresult SplitStyleAboveRange(nsRange* aRange,
- nsIAtom* aProperty,
- const nsAString* aAttribute);
- nsresult SplitStyleAbovePoint(nsCOMPtr<nsINode>* aNode, int32_t* aOffset,
- nsIAtom* aProperty,
- const nsAString* aAttribute,
- nsIContent** aOutLeftNode = nullptr,
- nsIContent** aOutRightNode = nullptr);
- nsresult ApplyDefaultProperties();
- nsresult RemoveStyleInside(nsIContent& aNode,
- nsIAtom* aProperty,
- const nsAString* aAttribute,
- const bool aChildrenOnly = false);
- nsresult RemoveInlinePropertyImpl(nsIAtom* aProperty,
- const nsAString* aAttribute);
-
- bool NodeIsProperty(nsINode& aNode);
- bool IsAtFrontOfNode(nsINode& aNode, int32_t aOffset);
- bool IsAtEndOfNode(nsINode& aNode, int32_t aOffset);
- bool IsOnlyAttribute(const nsIContent* aElement, const nsAString& aAttribute);
-
- nsresult RemoveBlockContainer(nsIContent& aNode);
-
- nsIContent* GetPriorHTMLSibling(nsINode* aNode);
- nsresult GetPriorHTMLSibling(nsIDOMNode*inNode,
- nsCOMPtr<nsIDOMNode>* outNode);
- nsIContent* GetPriorHTMLSibling(nsINode* aParent, int32_t aOffset);
- nsresult GetPriorHTMLSibling(nsIDOMNode* inParent, int32_t inOffset,
- nsCOMPtr<nsIDOMNode>* outNode);
-
- nsIContent* GetNextHTMLSibling(nsINode* aNode);
- nsresult GetNextHTMLSibling(nsIDOMNode* inNode,
- nsCOMPtr<nsIDOMNode>* outNode);
- nsIContent* GetNextHTMLSibling(nsINode* aParent, int32_t aOffset);
- nsresult GetNextHTMLSibling(nsIDOMNode* inParent, int32_t inOffset,
- nsCOMPtr<nsIDOMNode>* outNode);
-
- nsIContent* GetPriorHTMLNode(nsINode* aNode, bool aNoBlockCrossing = false);
- nsresult GetPriorHTMLNode(nsIDOMNode* inNode, nsCOMPtr<nsIDOMNode>* outNode,
- bool bNoBlockCrossing = false);
- nsIContent* GetPriorHTMLNode(nsINode* aParent, int32_t aOffset,
- bool aNoBlockCrossing = false);
- nsresult GetPriorHTMLNode(nsIDOMNode* inParent, int32_t inOffset,
- nsCOMPtr<nsIDOMNode>* outNode,
- bool bNoBlockCrossing = false);
-
- nsIContent* GetNextHTMLNode(nsINode* aNode, bool aNoBlockCrossing = false);
- nsresult GetNextHTMLNode(nsIDOMNode* inNode, nsCOMPtr<nsIDOMNode>* outNode,
- bool bNoBlockCrossing = false);
- nsIContent* GetNextHTMLNode(nsINode* aParent, int32_t aOffset,
- bool aNoBlockCrossing = false);
- nsresult GetNextHTMLNode(nsIDOMNode* inParent, int32_t inOffset,
- nsCOMPtr<nsIDOMNode>* outNode,
- bool bNoBlockCrossing = false);
-
- nsresult IsFirstEditableChild(nsIDOMNode* aNode, bool* aOutIsFirst);
- nsresult IsLastEditableChild(nsIDOMNode* aNode, bool* aOutIsLast);
- nsIContent* GetFirstEditableChild(nsINode& aNode);
- nsIContent* GetLastEditableChild(nsINode& aNode);
-
- nsIContent* GetFirstEditableLeaf(nsINode& aNode);
- nsIContent* GetLastEditableLeaf(nsINode& aNode);
-
- nsresult GetInlinePropertyBase(nsIAtom& aProperty,
- const nsAString* aAttribute,
- const nsAString* aValue,
- bool* aFirst,
- bool* aAny,
- bool* aAll,
- nsAString* outValue,
- bool aCheckDefaults = true);
- bool HasStyleOrIdOrClass(Element* aElement);
- nsresult RemoveElementIfNoStyleOrIdOrClass(Element& aElement);
-
- /**
- * Whether the outer window of the DOM event target has focus or not.
- */
- bool OurWindowHasFocus();
-
- /**
- * This function is used to insert a string of HTML input optionally with some
- * context information into the editable field. The HTML input either comes
- * from a transferable object created as part of a drop/paste operation, or
- * from the InsertHTML method. We may want the HTML input to be sanitized
- * (for example, if it's coming from a transferable object), in which case
- * aTrustedInput should be set to false, otherwise, the caller should set it
- * to true, which means that the HTML will be inserted in the DOM verbatim.
- *
- * aClearStyle should be set to false if you want the paste to be affected by
- * local style (e.g., for the insertHTML command).
- */
- nsresult DoInsertHTMLWithContext(const nsAString& aInputString,
- const nsAString& aContextStr,
- const nsAString& aInfoStr,
- const nsAString& aFlavor,
- nsIDOMDocument* aSourceDoc,
- nsIDOMNode* aDestNode,
- int32_t aDestOffset,
- bool aDeleteSelection,
- bool aTrustedInput,
- bool aClearStyle = true);
-
- nsresult ClearStyle(nsCOMPtr<nsINode>* aNode, int32_t* aOffset,
- nsIAtom* aProperty, const nsAString* aAttribute);
-
- void SetElementPosition(Element& aElement, int32_t aX, int32_t aY);
-
-protected:
- nsTArray<OwningNonNull<nsIContentFilter>> mContentFilters;
-
- RefPtr<TypeInState> mTypeInState;
-
- bool mCRInParagraphCreatesParagraph;
-
- bool mCSSAware;
- UniquePtr<CSSEditUtils> mCSSEditUtils;
-
- // Used by GetFirstSelectedCell and GetNextSelectedCell
- int32_t mSelectedCellIndex;
-
- nsString mLastStyleSheetURL;
- nsString mLastOverrideStyleSheetURL;
-
- // Maintain a list of associated style sheets and their urls.
- nsTArray<nsString> mStyleSheetURLs;
- nsTArray<RefPtr<StyleSheet>> mStyleSheets;
-
- // an array for holding default style settings
- nsTArray<PropItem*> mDefaultStyles;
-
-protected:
- // ANONYMOUS UTILS
- void RemoveListenerAndDeleteRef(const nsAString& aEvent,
- nsIDOMEventListener* aListener,
- bool aUseCapture,
- Element* aElement,
- nsIContent* aParentContent,
- nsIPresShell* aShell);
- void DeleteRefToAnonymousNode(nsIDOMElement* aElement,
- nsIContent* aParentContent,
- nsIPresShell* aShell);
-
- nsresult ShowResizersInner(nsIDOMElement *aResizedElement);
-
- /**
- * Returns the offset of an element's frame to its absolute containing block.
- */
- nsresult GetElementOrigin(nsIDOMElement* aElement,
- int32_t& aX, int32_t& aY);
- nsresult GetPositionAndDimensions(nsIDOMElement* aElement,
- int32_t& aX, int32_t& aY,
- int32_t& aW, int32_t& aH,
- int32_t& aBorderLeft,
- int32_t& aBorderTop,
- int32_t& aMarginLeft,
- int32_t& aMarginTop);
-
- bool IsInObservedSubtree(nsIDocument* aDocument,
- nsIContent* aContainer,
- nsIContent* aChild);
-
- void UpdateRootElement();
-
- // resizing
- bool mIsObjectResizingEnabled;
- bool mIsResizing;
- bool mPreserveRatio;
- bool mResizedObjectIsAnImage;
-
- // absolute positioning
- bool mIsAbsolutelyPositioningEnabled;
- bool mResizedObjectIsAbsolutelyPositioned;
-
- bool mGrabberClicked;
- bool mIsMoving;
-
- bool mSnapToGridEnabled;
-
- // inline table editing
- bool mIsInlineTableEditingEnabled;
-
- // resizing
- nsCOMPtr<Element> mTopLeftHandle;
- nsCOMPtr<Element> mTopHandle;
- nsCOMPtr<Element> mTopRightHandle;
- nsCOMPtr<Element> mLeftHandle;
- nsCOMPtr<Element> mRightHandle;
- nsCOMPtr<Element> mBottomLeftHandle;
- nsCOMPtr<Element> mBottomHandle;
- nsCOMPtr<Element> mBottomRightHandle;
-
- nsCOMPtr<Element> mActivatedHandle;
-
- nsCOMPtr<Element> mResizingShadow;
- nsCOMPtr<Element> mResizingInfo;
-
- nsCOMPtr<Element> mResizedObject;
-
- nsCOMPtr<nsIDOMEventListener> mMouseMotionListenerP;
- nsCOMPtr<nsISelectionListener> mSelectionListenerP;
- nsCOMPtr<nsIDOMEventListener> mResizeEventListenerP;
-
- nsTArray<OwningNonNull<nsIHTMLObjectResizeListener>> mObjectResizeEventListeners;
-
- int32_t mOriginalX;
- int32_t mOriginalY;
-
- int32_t mResizedObjectX;
- int32_t mResizedObjectY;
- int32_t mResizedObjectWidth;
- int32_t mResizedObjectHeight;
-
- int32_t mResizedObjectMarginLeft;
- int32_t mResizedObjectMarginTop;
- int32_t mResizedObjectBorderLeft;
- int32_t mResizedObjectBorderTop;
-
- int32_t mXIncrementFactor;
- int32_t mYIncrementFactor;
- int32_t mWidthIncrementFactor;
- int32_t mHeightIncrementFactor;
-
- int8_t mInfoXIncrement;
- int8_t mInfoYIncrement;
-
- nsresult SetAllResizersPosition();
-
- already_AddRefed<Element> CreateResizer(int16_t aLocation,
- nsIDOMNode* aParentNode);
- void SetAnonymousElementPosition(int32_t aX, int32_t aY,
- nsIDOMElement* aResizer);
-
- already_AddRefed<Element> CreateShadow(nsIDOMNode* aParentNode,
- nsIDOMElement* aOriginalObject);
- nsresult SetShadowPosition(Element* aShadow, Element* aOriginalObject,
- int32_t aOriginalObjectX,
- int32_t aOriginalObjectY);
-
- already_AddRefed<Element> CreateResizingInfo(nsIDOMNode* aParentNode);
- nsresult SetResizingInfoPosition(int32_t aX, int32_t aY,
- int32_t aW, int32_t aH);
-
- int32_t GetNewResizingIncrement(int32_t aX, int32_t aY, int32_t aID);
- nsresult StartResizing(nsIDOMElement* aHandle);
- int32_t GetNewResizingX(int32_t aX, int32_t aY);
- int32_t GetNewResizingY(int32_t aX, int32_t aY);
- int32_t GetNewResizingWidth(int32_t aX, int32_t aY);
- int32_t GetNewResizingHeight(int32_t aX, int32_t aY);
- void HideShadowAndInfo();
- void SetFinalSize(int32_t aX, int32_t aY);
- void DeleteRefToAnonymousNode(nsIDOMNode* aNode);
- void SetResizeIncrements(int32_t aX, int32_t aY, int32_t aW, int32_t aH,
- bool aPreserveRatio);
- void HideAnonymousEditingUIs();
-
- // absolute positioning
- int32_t mPositionedObjectX;
- int32_t mPositionedObjectY;
- int32_t mPositionedObjectWidth;
- int32_t mPositionedObjectHeight;
-
- int32_t mPositionedObjectMarginLeft;
- int32_t mPositionedObjectMarginTop;
- int32_t mPositionedObjectBorderLeft;
- int32_t mPositionedObjectBorderTop;
-
- nsCOMPtr<Element> mAbsolutelyPositionedObject;
- nsCOMPtr<Element> mGrabber;
- nsCOMPtr<Element> mPositioningShadow;
-
- int32_t mGridSize;
-
- already_AddRefed<Element> CreateGrabber(nsINode* aParentNode);
- nsresult StartMoving(nsIDOMElement* aHandle);
- nsresult SetFinalPosition(int32_t aX, int32_t aY);
- void AddPositioningOffset(int32_t& aX, int32_t& aY);
- void SnapToGrid(int32_t& newX, int32_t& newY);
- nsresult GrabberClicked();
- nsresult EndMoving();
- nsresult CheckPositionedElementBGandFG(nsIDOMElement* aElement,
- nsAString& aReturn);
-
- // inline table editing
- nsCOMPtr<nsIDOMElement> mInlineEditedCell;
-
- nsCOMPtr<nsIDOMElement> mAddColumnBeforeButton;
- nsCOMPtr<nsIDOMElement> mRemoveColumnButton;
- nsCOMPtr<nsIDOMElement> mAddColumnAfterButton;
-
- nsCOMPtr<nsIDOMElement> mAddRowBeforeButton;
- nsCOMPtr<nsIDOMElement> mRemoveRowButton;
- nsCOMPtr<nsIDOMElement> mAddRowAfterButton;
-
- void AddMouseClickListener(nsIDOMElement* aElement);
- void RemoveMouseClickListener(nsIDOMElement* aElement);
-
- nsCOMPtr<nsILinkHandler> mLinkHandler;
-
-public:
- friend class HTMLEditorEventListener;
- friend class HTMLEditRules;
- friend class TextEditRules;
- friend class WSRunObject;
-
-private:
- bool IsSimpleModifiableNode(nsIContent* aContent,
- nsIAtom* aProperty,
- const nsAString* aAttribute,
- const nsAString* aValue);
- nsresult SetInlinePropertyOnNodeImpl(nsIContent& aNode,
- nsIAtom& aProperty,
- const nsAString* aAttribute,
- const nsAString& aValue);
- typedef enum { eInserted, eAppended } InsertedOrAppended;
- void DoContentInserted(nsIDocument* aDocument, nsIContent* aContainer,
- nsIContent* aChild, int32_t aIndexInContainer,
- InsertedOrAppended aInsertedOrAppended);
- already_AddRefed<Element> GetElementOrParentByTagName(
- const nsAString& aTagName, nsINode* aNode);
- already_AddRefed<Element> CreateElementWithDefaults(
- const nsAString& aTagName);
-};
-
-} // namespace mozilla
-
-#endif // #ifndef mozilla_HTMLEditor_h
diff --git a/editor/libeditor/HTMLEditorDataTransfer.cpp b/editor/libeditor/HTMLEditorDataTransfer.cpp
deleted file mode 100644
index f97c0c5e1..000000000
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ /dev/null
@@ -1,2414 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/HTMLEditor.h"
-
-#include <string.h>
-
-#include "HTMLEditUtils.h"
-#include "TextEditRules.h"
-#include "TextEditUtils.h"
-#include "WSRunObject.h"
-#include "mozilla/dom/DataTransfer.h"
-#include "mozilla/dom/DocumentFragment.h"
-#include "mozilla/dom/DOMStringList.h"
-#include "mozilla/dom/Selection.h"
-#include "mozilla/ArrayUtils.h"
-#include "mozilla/Base64.h"
-#include "mozilla/BasicEvents.h"
-#include "mozilla/EditorUtils.h"
-#include "mozilla/OwningNonNull.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/SelectionState.h"
-#include "nsAString.h"
-#include "nsCOMPtr.h"
-#include "nsCRTGlue.h" // for CRLF
-#include "nsComponentManagerUtils.h"
-#include "nsIScriptError.h"
-#include "nsContentUtils.h"
-#include "nsDebug.h"
-#include "nsDependentSubstring.h"
-#include "nsError.h"
-#include "nsGkAtoms.h"
-#include "nsIClipboard.h"
-#include "nsIContent.h"
-#include "nsIContentFilter.h"
-#include "nsIDOMComment.h"
-#include "nsIDOMDocument.h"
-#include "nsIDOMDocumentFragment.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMHTMLAnchorElement.h"
-#include "nsIDOMHTMLEmbedElement.h"
-#include "nsIDOMHTMLFrameElement.h"
-#include "nsIDOMHTMLIFrameElement.h"
-#include "nsIDOMHTMLImageElement.h"
-#include "nsIDOMHTMLInputElement.h"
-#include "nsIDOMHTMLLinkElement.h"
-#include "nsIDOMHTMLObjectElement.h"
-#include "nsIDOMHTMLScriptElement.h"
-#include "nsIDOMNode.h"
-#include "nsIDocument.h"
-#include "nsIEditor.h"
-#include "nsIEditorIMESupport.h"
-#include "nsIEditorMailSupport.h"
-#include "nsIEditRules.h"
-#include "nsIFile.h"
-#include "nsIInputStream.h"
-#include "nsIMIMEService.h"
-#include "nsNameSpaceManager.h"
-#include "nsINode.h"
-#include "nsIParserUtils.h"
-#include "nsIPlaintextEditor.h"
-#include "nsISupportsImpl.h"
-#include "nsISupportsPrimitives.h"
-#include "nsISupportsUtils.h"
-#include "nsITransferable.h"
-#include "nsIURI.h"
-#include "nsIVariant.h"
-#include "nsLinebreakConverter.h"
-#include "nsLiteralString.h"
-#include "nsNetUtil.h"
-#include "nsRange.h"
-#include "nsReadableUtils.h"
-#include "nsServiceManagerUtils.h"
-#include "nsStreamUtils.h"
-#include "nsString.h"
-#include "nsStringFwd.h"
-#include "nsStringIterator.h"
-#include "nsSubstringTuple.h"
-#include "nsTreeSanitizer.h"
-#include "nsXPCOM.h"
-#include "nscore.h"
-#include "nsContentUtils.h"
-
-class nsIAtom;
-class nsILoadContext;
-class nsISupports;
-
-namespace mozilla {
-
-using namespace dom;
-
-#define kInsertCookie "_moz_Insert Here_moz_"
-
-// some little helpers
-static bool FindIntegerAfterString(const char* aLeadingString,
- nsCString& aCStr, int32_t& foundNumber);
-static nsresult RemoveFragComments(nsCString& theStr);
-static void RemoveBodyAndHead(nsINode& aNode);
-static nsresult FindTargetNode(nsIDOMNode* aStart,
- nsCOMPtr<nsIDOMNode>& aResult);
-
-nsresult
-HTMLEditor::LoadHTML(const nsAString& aInputString)
-{
- NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
-
- // force IME commit; set up rules sniffing and batching
- ForceCompositionEnd();
- AutoEditBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::loadHTML, nsIEditor::eNext);
-
- // Get selection
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_STATE(selection);
-
- TextRulesInfo ruleInfo(EditAction::loadHTML);
- bool cancel, handled;
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
- if (cancel) {
- return NS_OK; // rules canceled the operation
- }
-
- if (!handled) {
- // Delete Selection, but only if it isn't collapsed, see bug #106269
- if (!selection->Collapsed()) {
- rv = DeleteSelection(eNone, eStrip);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // Get the first range in the selection, for context:
- RefPtr<nsRange> range = selection->GetRangeAt(0);
- NS_ENSURE_TRUE(range, NS_ERROR_NULL_POINTER);
-
- // create fragment for pasted html
- nsCOMPtr<nsIDOMDocumentFragment> docfrag;
- rv = range->CreateContextualFragment(aInputString, getter_AddRefs(docfrag));
- NS_ENSURE_SUCCESS(rv, rv);
- // put the fragment into the document
- nsCOMPtr<nsIDOMNode> parent;
- rv = range->GetStartContainer(getter_AddRefs(parent));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
- uint32_t childOffset = range->StartOffset();
-
- nsCOMPtr<nsIDOMNode> nodeToInsert;
- docfrag->GetFirstChild(getter_AddRefs(nodeToInsert));
- while (nodeToInsert) {
- rv = InsertNode(nodeToInsert, parent,
- static_cast<int32_t>(childOffset++));
- NS_ENSURE_SUCCESS(rv, rv);
- docfrag->GetFirstChild(getter_AddRefs(nodeToInsert));
- }
- }
-
- return rules->DidDoAction(selection, &ruleInfo, rv);
-}
-
-NS_IMETHODIMP
-HTMLEditor::InsertHTML(const nsAString& aInString)
-{
- const nsAFlatString& empty = EmptyString();
-
- return InsertHTMLWithContext(aInString, empty, empty, empty,
- nullptr, nullptr, 0, true);
-}
-
-nsresult
-HTMLEditor::InsertHTMLWithContext(const nsAString& aInputString,
- const nsAString& aContextStr,
- const nsAString& aInfoStr,
- const nsAString& aFlavor,
- nsIDOMDocument* aSourceDoc,
- nsIDOMNode* aDestNode,
- int32_t aDestOffset,
- bool aDeleteSelection)
-{
- return DoInsertHTMLWithContext(aInputString, aContextStr, aInfoStr,
- aFlavor, aSourceDoc, aDestNode, aDestOffset, aDeleteSelection,
- /* trusted input */ true, /* clear style */ false);
-}
-
-nsresult
-HTMLEditor::DoInsertHTMLWithContext(const nsAString& aInputString,
- const nsAString& aContextStr,
- const nsAString& aInfoStr,
- const nsAString& aFlavor,
- nsIDOMDocument* aSourceDoc,
- nsIDOMNode* aDestNode,
- int32_t aDestOffset,
- bool aDeleteSelection,
- bool aTrustedInput,
- bool aClearStyle)
-{
- NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
-
- // Prevent the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- // force IME commit; set up rules sniffing and batching
- ForceCompositionEnd();
- AutoEditBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::htmlPaste, nsIEditor::eNext);
-
- // Get selection
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_STATE(selection);
-
- // create a dom document fragment that represents the structure to paste
- nsCOMPtr<nsIDOMNode> fragmentAsNode, streamStartParent, streamEndParent;
- int32_t streamStartOffset = 0, streamEndOffset = 0;
-
- nsresult rv = CreateDOMFragmentFromPaste(aInputString, aContextStr, aInfoStr,
- address_of(fragmentAsNode),
- address_of(streamStartParent),
- address_of(streamEndParent),
- &streamStartOffset,
- &streamEndOffset,
- aTrustedInput);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIDOMNode> targetNode;
- int32_t targetOffset=0;
-
- if (!aDestNode) {
- // if caller didn't provide the destination/target node,
- // fetch the paste insertion point from our selection
- rv = GetStartNodeAndOffset(selection, getter_AddRefs(targetNode), &targetOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!targetNode || !IsEditable(targetNode)) {
- return NS_ERROR_FAILURE;
- }
- } else {
- targetNode = aDestNode;
- targetOffset = aDestOffset;
- }
-
- bool doContinue = true;
-
- rv = DoContentFilterCallback(aFlavor, aSourceDoc, aDeleteSelection,
- (nsIDOMNode **)address_of(fragmentAsNode),
- (nsIDOMNode **)address_of(streamStartParent),
- &streamStartOffset,
- (nsIDOMNode **)address_of(streamEndParent),
- &streamEndOffset,
- (nsIDOMNode **)address_of(targetNode),
- &targetOffset, &doContinue);
-
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(doContinue, NS_OK);
-
- // if we have a destination / target node, we want to insert there
- // rather than in place of the selection
- // ignore aDeleteSelection here if no aDestNode since deletion will
- // also occur later; this block is intended to cover the various
- // scenarios where we are dropping in an editor (and may want to delete
- // the selection before collapsing the selection in the new destination)
- if (aDestNode) {
- if (aDeleteSelection) {
- // Use an auto tracker so that our drop point is correctly
- // positioned after the delete.
- AutoTrackDOMPoint tracker(mRangeUpdater, &targetNode, &targetOffset);
- rv = DeleteSelection(eNone, eStrip);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- rv = selection->Collapse(targetNode, targetOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // we need to recalculate various things based on potentially new offsets
- // this is work to be completed at a later date (probably by jfrancis)
-
- // make a list of what nodes in docFrag we need to move
- nsTArray<OwningNonNull<nsINode>> nodeList;
- nsCOMPtr<nsINode> fragmentAsNodeNode = do_QueryInterface(fragmentAsNode);
- NS_ENSURE_STATE(fragmentAsNodeNode || !fragmentAsNode);
- nsCOMPtr<nsINode> streamStartParentNode =
- do_QueryInterface(streamStartParent);
- NS_ENSURE_STATE(streamStartParentNode || !streamStartParent);
- nsCOMPtr<nsINode> streamEndParentNode =
- do_QueryInterface(streamEndParent);
- NS_ENSURE_STATE(streamEndParentNode || !streamEndParent);
- CreateListOfNodesToPaste(*static_cast<DocumentFragment*>(fragmentAsNodeNode.get()),
- nodeList,
- streamStartParentNode, streamStartOffset,
- streamEndParentNode, streamEndOffset);
-
- if (nodeList.IsEmpty()) {
- // We aren't inserting anything, but if aDeleteSelection is set, we do want
- // to delete everything.
- if (aDeleteSelection) {
- return DeleteSelection(eNone, eStrip);
- }
- return NS_OK;
- }
-
- // Are there any table elements in the list?
- // node and offset for insertion
- nsCOMPtr<nsIDOMNode> parentNode;
- int32_t offsetOfNewNode;
-
- // check for table cell selection mode
- bool cellSelectionMode = false;
- nsCOMPtr<nsIDOMElement> cell;
- rv = GetFirstSelectedCell(nullptr, getter_AddRefs(cell));
- if (NS_SUCCEEDED(rv) && cell) {
- cellSelectionMode = true;
- }
-
- if (cellSelectionMode) {
- // do we have table content to paste? If so, we want to delete
- // the selected table cells and replace with new table elements;
- // but if not we want to delete _contents_ of cells and replace
- // with non-table elements. Use cellSelectionMode bool to
- // indicate results.
- if (!HTMLEditUtils::IsTableElement(nodeList[0])) {
- cellSelectionMode = false;
- }
- }
-
- if (!cellSelectionMode) {
- rv = DeleteSelectionAndPrepareToCreateNode();
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (aClearStyle) {
- // pasting does not inherit local inline styles
- nsCOMPtr<nsINode> tmpNode = selection->GetAnchorNode();
- int32_t tmpOffset = static_cast<int32_t>(selection->AnchorOffset());
- rv = ClearStyle(address_of(tmpNode), &tmpOffset, nullptr, nullptr);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- } else {
- // Delete whole cells: we will replace with new table content.
-
- // Braces for artificial block to scope AutoSelectionRestorer.
- // Save current selection since DeleteTableCell() perturbs it.
- {
- AutoSelectionRestorer selectionRestorer(selection, this);
- rv = DeleteTableCell(1);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // collapse selection to beginning of deleted table content
- selection->CollapseToStart();
- }
-
- // give rules a chance to handle or cancel
- TextRulesInfo ruleInfo(EditAction::insertElement);
- bool cancel, handled;
- rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
- if (cancel) {
- return NS_OK; // rules canceled the operation
- }
-
- if (!handled) {
- // The rules code (WillDoAction above) might have changed the selection.
- // refresh our memory...
- rv = GetStartNodeAndOffset(selection, getter_AddRefs(parentNode), &offsetOfNewNode);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(parentNode, NS_ERROR_FAILURE);
-
- // Adjust position based on the first node we are going to insert.
- NormalizeEOLInsertPosition(nodeList[0], address_of(parentNode),
- &offsetOfNewNode);
-
- // if there are any invisible br's after our insertion point, remove them.
- // this is because if there is a br at end of what we paste, it will make
- // the invisible br visible.
- WSRunObject wsObj(this, parentNode, offsetOfNewNode);
- if (wsObj.mEndReasonNode &&
- TextEditUtils::IsBreak(wsObj.mEndReasonNode) &&
- !IsVisBreak(wsObj.mEndReasonNode)) {
- rv = DeleteNode(wsObj.mEndReasonNode);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // Remember if we are in a link.
- bool bStartedInLink = IsInLink(parentNode);
-
- // Are we in a text node? If so, split it.
- if (IsTextNode(parentNode)) {
- nsCOMPtr<nsIContent> parentContent = do_QueryInterface(parentNode);
- NS_ENSURE_STATE(parentContent || !parentNode);
- offsetOfNewNode = SplitNodeDeep(*parentContent, *parentContent,
- offsetOfNewNode);
- NS_ENSURE_STATE(offsetOfNewNode != -1);
- nsCOMPtr<nsIDOMNode> temp;
- rv = parentNode->GetParentNode(getter_AddRefs(temp));
- NS_ENSURE_SUCCESS(rv, rv);
- parentNode = temp;
- }
-
- // build up list of parents of first node in list that are either
- // lists or tables. First examine front of paste node list.
- nsTArray<OwningNonNull<Element>> startListAndTableArray;
- GetListAndTableParents(StartOrEnd::start, nodeList,
- startListAndTableArray);
-
- // remember number of lists and tables above us
- int32_t highWaterMark = -1;
- if (!startListAndTableArray.IsEmpty()) {
- highWaterMark = DiscoverPartialListsAndTables(nodeList,
- startListAndTableArray);
- }
-
- // if we have pieces of tables or lists to be inserted, let's force the paste
- // to deal with table elements right away, so that it doesn't orphan some
- // table or list contents outside the table or list.
- if (highWaterMark >= 0) {
- ReplaceOrphanedStructure(StartOrEnd::start, nodeList,
- startListAndTableArray, highWaterMark);
- }
-
- // Now go through the same process again for the end of the paste node list.
- nsTArray<OwningNonNull<Element>> endListAndTableArray;
- GetListAndTableParents(StartOrEnd::end, nodeList, endListAndTableArray);
- highWaterMark = -1;
-
- // remember number of lists and tables above us
- if (!endListAndTableArray.IsEmpty()) {
- highWaterMark = DiscoverPartialListsAndTables(nodeList,
- endListAndTableArray);
- }
-
- // don't orphan partial list or table structure
- if (highWaterMark >= 0) {
- ReplaceOrphanedStructure(StartOrEnd::end, nodeList,
- endListAndTableArray, highWaterMark);
- }
-
- // Loop over the node list and paste the nodes:
- nsCOMPtr<nsIDOMNode> parentBlock, lastInsertNode, insertedContextParent;
- nsCOMPtr<nsINode> parentNodeNode = do_QueryInterface(parentNode);
- NS_ENSURE_STATE(parentNodeNode || !parentNode);
- if (IsBlockNode(parentNodeNode)) {
- parentBlock = parentNode;
- } else {
- parentBlock = GetBlockNodeParent(parentNode);
- }
-
- int32_t listCount = nodeList.Length();
- for (int32_t j = 0; j < listCount; j++) {
- bool bDidInsert = false;
- nsCOMPtr<nsIDOMNode> curNode = nodeList[j]->AsDOMNode();
-
- NS_ENSURE_TRUE(curNode, NS_ERROR_FAILURE);
- NS_ENSURE_TRUE(curNode != fragmentAsNode, NS_ERROR_FAILURE);
- NS_ENSURE_TRUE(!TextEditUtils::IsBody(curNode), NS_ERROR_FAILURE);
-
- if (insertedContextParent) {
- // if we had to insert something higher up in the paste hierarchy, we want to
- // skip any further paste nodes that descend from that. Else we will paste twice.
- if (EditorUtils::IsDescendantOf(curNode, insertedContextParent)) {
- continue;
- }
- }
-
- // give the user a hand on table element insertion. if they have
- // a table or table row on the clipboard, and are trying to insert
- // into a table or table row, insert the appropriate children instead.
- if (HTMLEditUtils::IsTableRow(curNode) &&
- HTMLEditUtils::IsTableRow(parentNode) &&
- (HTMLEditUtils::IsTable(curNode) ||
- HTMLEditUtils::IsTable(parentNode))) {
- nsCOMPtr<nsIDOMNode> child;
- curNode->GetFirstChild(getter_AddRefs(child));
- while (child) {
- rv = InsertNodeAtPoint(child, address_of(parentNode), &offsetOfNewNode, true);
- if (NS_FAILED(rv)) {
- break;
- }
-
- bDidInsert = true;
- lastInsertNode = child;
- offsetOfNewNode++;
-
- curNode->GetFirstChild(getter_AddRefs(child));
- }
- }
- // give the user a hand on list insertion. if they have
- // a list on the clipboard, and are trying to insert
- // into a list or list item, insert the appropriate children instead,
- // ie, merge the lists instead of pasting in a sublist.
- else if (HTMLEditUtils::IsList(curNode) &&
- (HTMLEditUtils::IsList(parentNode) ||
- HTMLEditUtils::IsListItem(parentNode))) {
- nsCOMPtr<nsIDOMNode> child, tmp;
- curNode->GetFirstChild(getter_AddRefs(child));
- while (child) {
- if (HTMLEditUtils::IsListItem(child) ||
- HTMLEditUtils::IsList(child)) {
- // Check if we are pasting into empty list item. If so
- // delete it and paste into parent list instead.
- if (HTMLEditUtils::IsListItem(parentNode)) {
- bool isEmpty;
- rv = IsEmptyNode(parentNode, &isEmpty, true);
- if (NS_SUCCEEDED(rv) && isEmpty) {
- int32_t newOffset;
- nsCOMPtr<nsIDOMNode> listNode = GetNodeLocation(parentNode, &newOffset);
- if (listNode) {
- DeleteNode(parentNode);
- parentNode = listNode;
- offsetOfNewNode = newOffset;
- }
- }
- }
- rv = InsertNodeAtPoint(child, address_of(parentNode), &offsetOfNewNode, true);
- if (NS_FAILED(rv)) {
- break;
- }
-
- bDidInsert = true;
- lastInsertNode = child;
- offsetOfNewNode++;
- } else {
- curNode->RemoveChild(child, getter_AddRefs(tmp));
- }
- curNode->GetFirstChild(getter_AddRefs(child));
- }
- } else if (parentBlock && HTMLEditUtils::IsPre(parentBlock) &&
- HTMLEditUtils::IsPre(curNode)) {
- // Check for pre's going into pre's.
- nsCOMPtr<nsIDOMNode> child;
- curNode->GetFirstChild(getter_AddRefs(child));
- while (child) {
- rv = InsertNodeAtPoint(child, address_of(parentNode), &offsetOfNewNode, true);
- if (NS_FAILED(rv)) {
- break;
- }
-
- bDidInsert = true;
- lastInsertNode = child;
- offsetOfNewNode++;
-
- curNode->GetFirstChild(getter_AddRefs(child));
- }
- }
-
- if (!bDidInsert || NS_FAILED(rv)) {
- // try to insert
- rv = InsertNodeAtPoint(curNode, address_of(parentNode), &offsetOfNewNode, true);
- if (NS_SUCCEEDED(rv)) {
- bDidInsert = true;
- lastInsertNode = curNode;
- }
-
- // Assume failure means no legal parent in the document hierarchy,
- // try again with the parent of curNode in the paste hierarchy.
- nsCOMPtr<nsIDOMNode> parent;
- while (NS_FAILED(rv) && curNode) {
- curNode->GetParentNode(getter_AddRefs(parent));
- if (parent && !TextEditUtils::IsBody(parent)) {
- rv = InsertNodeAtPoint(parent, address_of(parentNode), &offsetOfNewNode, true);
- if (NS_SUCCEEDED(rv)) {
- bDidInsert = true;
- insertedContextParent = parent;
- lastInsertNode = GetChildAt(parentNode, offsetOfNewNode);
- }
- }
- curNode = parent;
- }
- }
- if (lastInsertNode) {
- parentNode = GetNodeLocation(lastInsertNode, &offsetOfNewNode);
- offsetOfNewNode++;
- }
- }
-
- // Now collapse the selection to the end of what we just inserted:
- if (lastInsertNode) {
- // set selection to the end of what we just pasted.
- nsCOMPtr<nsIDOMNode> selNode, tmp, highTable;
- int32_t selOffset;
-
- // but don't cross tables
- if (!HTMLEditUtils::IsTable(lastInsertNode)) {
- nsCOMPtr<nsINode> lastInsertNode_ = do_QueryInterface(lastInsertNode);
- NS_ENSURE_STATE(lastInsertNode_ || !lastInsertNode);
- selNode = GetAsDOMNode(GetLastEditableLeaf(*lastInsertNode_));
- tmp = selNode;
- while (tmp && tmp != lastInsertNode) {
- if (HTMLEditUtils::IsTable(tmp)) {
- highTable = tmp;
- }
- nsCOMPtr<nsIDOMNode> parent = tmp;
- tmp->GetParentNode(getter_AddRefs(parent));
- tmp = parent;
- }
- if (highTable) {
- selNode = highTable;
- }
- }
- if (!selNode) {
- selNode = lastInsertNode;
- }
- if (IsTextNode(selNode) ||
- (IsContainer(selNode) && !HTMLEditUtils::IsTable(selNode))) {
- rv = GetLengthOfDOMNode(selNode, (uint32_t&)selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // We need to find a container for selection. Look up.
- tmp = selNode;
- selNode = GetNodeLocation(tmp, &selOffset);
- // selNode might be null in case a mutation listener removed
- // the stuff we just inserted from the DOM.
- NS_ENSURE_STATE(selNode);
- ++selOffset; // want to be *after* last leaf node in paste
- }
-
- // make sure we don't end up with selection collapsed after an invisible break node
- WSRunObject wsRunObj(this, selNode, selOffset);
- nsCOMPtr<nsINode> visNode;
- int32_t outVisOffset=0;
- WSType visType;
- nsCOMPtr<nsINode> selNode_(do_QueryInterface(selNode));
- wsRunObj.PriorVisibleNode(selNode_, selOffset, address_of(visNode),
- &outVisOffset, &visType);
- if (visType == WSType::br) {
- // we are after a break. Is it visible? Despite the name,
- // PriorVisibleNode does not make that determination for breaks.
- // It also may not return the break in visNode. We have to pull it
- // out of the WSRunObject's state.
- if (!IsVisBreak(wsRunObj.mStartReasonNode)) {
- // don't leave selection past an invisible break;
- // reset {selNode,selOffset} to point before break
- selNode = GetNodeLocation(GetAsDOMNode(wsRunObj.mStartReasonNode), &selOffset);
- // we want to be inside any inline style prior to break
- WSRunObject wsRunObj(this, selNode, selOffset);
- selNode_ = do_QueryInterface(selNode);
- wsRunObj.PriorVisibleNode(selNode_, selOffset, address_of(visNode),
- &outVisOffset, &visType);
- if (visType == WSType::text || visType == WSType::normalWS) {
- selNode = GetAsDOMNode(visNode);
- selOffset = outVisOffset; // PriorVisibleNode already set offset to _after_ the text or ws
- } else if (visType == WSType::special) {
- // prior visible thing is an image or some other non-text thingy.
- // We want to be right after it.
- selNode = GetNodeLocation(GetAsDOMNode(wsRunObj.mStartReasonNode), &selOffset);
- ++selOffset;
- }
- }
- }
- selection->Collapse(selNode, selOffset);
-
- // if we just pasted a link, discontinue link style
- nsCOMPtr<nsIDOMNode> link;
- if (!bStartedInLink && IsInLink(selNode, address_of(link))) {
- // so, if we just pasted a link, I split it. Why do that instead of just
- // nudging selection point beyond it? Because it might have ended in a BR
- // that is not visible. If so, the code above just placed selection
- // inside that. So I split it instead.
- nsCOMPtr<nsIContent> linkContent = do_QueryInterface(link);
- NS_ENSURE_STATE(linkContent || !link);
- nsCOMPtr<nsIContent> selContent = do_QueryInterface(selNode);
- NS_ENSURE_STATE(selContent || !selNode);
- nsCOMPtr<nsIContent> leftLink;
- SplitNodeDeep(*linkContent, *selContent, selOffset,
- EmptyContainers::no, getter_AddRefs(leftLink));
- if (leftLink) {
- selNode = GetNodeLocation(GetAsDOMNode(leftLink), &selOffset);
- selection->Collapse(selNode, selOffset+1);
- }
- }
- }
- }
-
- return rules->DidDoAction(selection, &ruleInfo, rv);
-}
-
-NS_IMETHODIMP
-HTMLEditor::AddInsertionListener(nsIContentFilter* aListener)
-{
- NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER);
-
- // don't let a listener be added more than once
- if (!mContentFilters.Contains(aListener)) {
- mContentFilters.AppendElement(*aListener);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::RemoveInsertionListener(nsIContentFilter* aListener)
-{
- NS_ENSURE_TRUE(aListener, NS_ERROR_FAILURE);
-
- mContentFilters.RemoveElement(aListener);
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::DoContentFilterCallback(const nsAString& aFlavor,
- nsIDOMDocument* sourceDoc,
- bool aWillDeleteSelection,
- nsIDOMNode** aFragmentAsNode,
- nsIDOMNode** aFragStartNode,
- int32_t* aFragStartOffset,
- nsIDOMNode** aFragEndNode,
- int32_t* aFragEndOffset,
- nsIDOMNode** aTargetNode,
- int32_t* aTargetOffset,
- bool* aDoContinue)
-{
- *aDoContinue = true;
-
- for (auto& listener : mContentFilters) {
- if (!*aDoContinue) {
- break;
- }
- listener->NotifyOfInsertion(aFlavor, nullptr, sourceDoc,
- aWillDeleteSelection, aFragmentAsNode,
- aFragStartNode, aFragStartOffset,
- aFragEndNode, aFragEndOffset, aTargetNode,
- aTargetOffset, aDoContinue);
- }
-
- return NS_OK;
-}
-
-bool
-HTMLEditor::IsInLink(nsIDOMNode* aNode,
- nsCOMPtr<nsIDOMNode>* outLink)
-{
- NS_ENSURE_TRUE(aNode, false);
- if (outLink) {
- *outLink = nullptr;
- }
- nsCOMPtr<nsIDOMNode> tmp, node = aNode;
- while (node) {
- if (HTMLEditUtils::IsLink(node)) {
- if (outLink) {
- *outLink = node;
- }
- return true;
- }
- tmp = node;
- tmp->GetParentNode(getter_AddRefs(node));
- }
- return false;
-}
-
-nsresult
-HTMLEditor::StripFormattingNodes(nsIContent& aNode,
- bool aListOnly)
-{
- if (aNode.TextIsOnlyWhitespace()) {
- nsCOMPtr<nsINode> parent = aNode.GetParentNode();
- if (parent) {
- if (!aListOnly || HTMLEditUtils::IsList(parent)) {
- ErrorResult rv;
- parent->RemoveChild(aNode, rv);
- return rv.StealNSResult();
- }
- return NS_OK;
- }
- }
-
- if (!aNode.IsHTMLElement(nsGkAtoms::pre)) {
- nsCOMPtr<nsIContent> child = aNode.GetLastChild();
- while (child) {
- nsCOMPtr<nsIContent> previous = child->GetPreviousSibling();
- nsresult rv = StripFormattingNodes(*child, aListOnly);
- NS_ENSURE_SUCCESS(rv, rv);
- child = previous.forget();
- }
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::PrepareTransferable(nsITransferable** aTransferable)
-{
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::PrepareHTMLTransferable(nsITransferable** aTransferable)
-{
- // Create generic Transferable for getting the data
- nsresult rv = CallCreateInstance("@mozilla.org/widget/transferable;1", aTransferable);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Get the nsITransferable interface for getting the data from the clipboard
- if (aTransferable) {
- nsCOMPtr<nsIDocument> destdoc = GetDocument();
- nsILoadContext* loadContext = destdoc ? destdoc->GetLoadContext() : nullptr;
- (*aTransferable)->Init(loadContext);
-
- // Create the desired DataFlavor for the type of data
- // we want to get out of the transferable
- // This should only happen in html editors, not plaintext
- if (!IsPlaintextEditor()) {
- (*aTransferable)->AddDataFlavor(kNativeHTMLMime);
- (*aTransferable)->AddDataFlavor(kHTMLMime);
- (*aTransferable)->AddDataFlavor(kFileMime);
-
- switch (Preferences::GetInt("clipboard.paste_image_type", 1)) {
- case 0: // prefer JPEG over PNG over GIF encoding
- (*aTransferable)->AddDataFlavor(kJPEGImageMime);
- (*aTransferable)->AddDataFlavor(kJPGImageMime);
- (*aTransferable)->AddDataFlavor(kPNGImageMime);
- (*aTransferable)->AddDataFlavor(kGIFImageMime);
- break;
- case 1: // prefer PNG over JPEG over GIF encoding (default)
- default:
- (*aTransferable)->AddDataFlavor(kPNGImageMime);
- (*aTransferable)->AddDataFlavor(kJPEGImageMime);
- (*aTransferable)->AddDataFlavor(kJPGImageMime);
- (*aTransferable)->AddDataFlavor(kGIFImageMime);
- break;
- case 2: // prefer GIF over JPEG over PNG encoding
- (*aTransferable)->AddDataFlavor(kGIFImageMime);
- (*aTransferable)->AddDataFlavor(kJPEGImageMime);
- (*aTransferable)->AddDataFlavor(kJPGImageMime);
- (*aTransferable)->AddDataFlavor(kPNGImageMime);
- break;
- }
- }
- (*aTransferable)->AddDataFlavor(kUnicodeMime);
- (*aTransferable)->AddDataFlavor(kMozTextInternal);
- }
-
- return NS_OK;
-}
-
-bool
-FindIntegerAfterString(const char* aLeadingString,
- nsCString& aCStr,
- int32_t& foundNumber)
-{
- // first obtain offsets from cfhtml str
- int32_t numFront = aCStr.Find(aLeadingString);
- if (numFront == -1) {
- return false;
- }
- numFront += strlen(aLeadingString);
-
- int32_t numBack = aCStr.FindCharInSet(CRLF, numFront);
- if (numBack == -1) {
- return false;
- }
-
- nsAutoCString numStr(Substring(aCStr, numFront, numBack-numFront));
- nsresult errorCode;
- foundNumber = numStr.ToInteger(&errorCode);
- return true;
-}
-
-nsresult
-RemoveFragComments(nsCString& aStr)
-{
- // remove the StartFragment/EndFragment comments from the str, if present
- int32_t startCommentIndx = aStr.Find("<!--StartFragment");
- if (startCommentIndx >= 0) {
- int32_t startCommentEnd = aStr.Find("-->", false, startCommentIndx);
- if (startCommentEnd > startCommentIndx) {
- aStr.Cut(startCommentIndx, (startCommentEnd + 3) - startCommentIndx);
- }
- }
- int32_t endCommentIndx = aStr.Find("<!--EndFragment");
- if (endCommentIndx >= 0) {
- int32_t endCommentEnd = aStr.Find("-->", false, endCommentIndx);
- if (endCommentEnd > endCommentIndx) {
- aStr.Cut(endCommentIndx, (endCommentEnd + 3) - endCommentIndx);
- }
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::ParseCFHTML(nsCString& aCfhtml,
- char16_t** aStuffToPaste,
- char16_t** aCfcontext)
-{
- // First obtain offsets from cfhtml str.
- int32_t startHTML, endHTML, startFragment, endFragment;
- if (!FindIntegerAfterString("StartHTML:", aCfhtml, startHTML) ||
- startHTML < -1) {
- return NS_ERROR_FAILURE;
- }
- if (!FindIntegerAfterString("EndHTML:", aCfhtml, endHTML) ||
- endHTML < -1) {
- return NS_ERROR_FAILURE;
- }
- if (!FindIntegerAfterString("StartFragment:", aCfhtml, startFragment) ||
- startFragment < 0) {
- return NS_ERROR_FAILURE;
- }
- if (!FindIntegerAfterString("EndFragment:", aCfhtml, endFragment) ||
- startFragment < 0) {
- return NS_ERROR_FAILURE;
- }
-
- // The StartHTML and EndHTML markers are allowed to be -1 to include everything.
- // See Reference: MSDN doc entitled "HTML Clipboard Format"
- // http://msdn.microsoft.com/en-us/library/aa767917(VS.85).aspx#unknown_854
- if (startHTML == -1) {
- startHTML = aCfhtml.Find("<!--StartFragment-->");
- if (startHTML == -1) {
- return NS_OK;
- }
- }
- if (endHTML == -1) {
- const char endFragmentMarker[] = "<!--EndFragment-->";
- endHTML = aCfhtml.Find(endFragmentMarker);
- if (endHTML == -1) {
- return NS_OK;
- }
- endHTML += ArrayLength(endFragmentMarker) - 1;
- }
-
- // create context string
- nsAutoCString contextUTF8(Substring(aCfhtml, startHTML, startFragment - startHTML) +
- NS_LITERAL_CSTRING("<!--" kInsertCookie "-->") +
- Substring(aCfhtml, endFragment, endHTML - endFragment));
-
- // validate startFragment
- // make sure it's not in the middle of a HTML tag
- // see bug #228879 for more details
- int32_t curPos = startFragment;
- while (curPos > startHTML) {
- if (aCfhtml[curPos] == '>') {
- // working backwards, the first thing we see is the end of a tag
- // so StartFragment is good, so do nothing.
- break;
- }
- if (aCfhtml[curPos] == '<') {
- // if we are at the start, then we want to see the '<'
- if (curPos != startFragment) {
- // working backwards, the first thing we see is the start of a tag
- // so StartFragment is bad, so we need to update it.
- NS_ERROR("StartFragment byte count in the clipboard looks bad, see bug #228879");
- startFragment = curPos - 1;
- }
- break;
- }
- curPos--;
- }
-
- // create fragment string
- nsAutoCString fragmentUTF8(Substring(aCfhtml, startFragment, endFragment-startFragment));
-
- // remove the StartFragment/EndFragment comments from the fragment, if present
- RemoveFragComments(fragmentUTF8);
-
- // remove the StartFragment/EndFragment comments from the context, if present
- RemoveFragComments(contextUTF8);
-
- // convert both strings to usc2
- const nsAFlatString& fragUcs2Str = NS_ConvertUTF8toUTF16(fragmentUTF8);
- const nsAFlatString& cntxtUcs2Str = NS_ConvertUTF8toUTF16(contextUTF8);
-
- // translate platform linebreaks for fragment
- int32_t oldLengthInChars = fragUcs2Str.Length() + 1; // +1 to include null terminator
- int32_t newLengthInChars = 0;
- *aStuffToPaste = nsLinebreakConverter::ConvertUnicharLineBreaks(fragUcs2Str.get(),
- nsLinebreakConverter::eLinebreakAny,
- nsLinebreakConverter::eLinebreakContent,
- oldLengthInChars, &newLengthInChars);
- NS_ENSURE_TRUE(*aStuffToPaste, NS_ERROR_FAILURE);
-
- // translate platform linebreaks for context
- oldLengthInChars = cntxtUcs2Str.Length() + 1; // +1 to include null terminator
- newLengthInChars = 0;
- *aCfcontext = nsLinebreakConverter::ConvertUnicharLineBreaks(cntxtUcs2Str.get(),
- nsLinebreakConverter::eLinebreakAny,
- nsLinebreakConverter::eLinebreakContent,
- oldLengthInChars, &newLengthInChars);
- // it's ok for context to be empty. frag might be whole doc and contain all its context.
-
- // we're done!
- return NS_OK;
-}
-
-static nsresult
-ImgFromData(const nsACString& aType, const nsACString& aData, nsString& aOutput)
-{
- nsAutoCString data64;
- nsresult rv = Base64Encode(aData, data64);
- NS_ENSURE_SUCCESS(rv, rv);
-
- aOutput.AssignLiteral("<IMG src=\"data:");
- AppendUTF8toUTF16(aType, aOutput);
- aOutput.AppendLiteral(";base64,");
- if (!AppendASCIItoUTF16(data64, aOutput, fallible_t())) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- aOutput.AppendLiteral("\" alt=\"\" >");
- return NS_OK;
-}
-
-NS_IMPL_ISUPPORTS(HTMLEditor::BlobReader, nsIEditorBlobListener)
-
-HTMLEditor::BlobReader::BlobReader(BlobImpl* aBlob,
- HTMLEditor* aHTMLEditor,
- bool aIsSafe,
- nsIDOMDocument* aSourceDoc,
- nsIDOMNode* aDestinationNode,
- int32_t aDestOffset,
- bool aDoDeleteSelection)
- : mBlob(aBlob)
- , mHTMLEditor(aHTMLEditor)
- , mIsSafe(aIsSafe)
- , mSourceDoc(aSourceDoc)
- , mDestinationNode(aDestinationNode)
- , mDestOffset(aDestOffset)
- , mDoDeleteSelection(aDoDeleteSelection)
-{
- MOZ_ASSERT(mBlob);
- MOZ_ASSERT(mHTMLEditor);
- MOZ_ASSERT(mDestinationNode);
-}
-
-NS_IMETHODIMP
-HTMLEditor::BlobReader::OnResult(const nsACString& aResult)
-{
- nsString blobType;
- mBlob->GetType(blobType);
-
- NS_ConvertUTF16toUTF8 type(blobType);
- nsAutoString stuffToPaste;
- nsresult rv = ImgFromData(type, aResult, stuffToPaste);
- NS_ENSURE_SUCCESS(rv, rv);
-
- AutoEditBatch beginBatching(mHTMLEditor);
- rv = mHTMLEditor->DoInsertHTMLWithContext(stuffToPaste, EmptyString(),
- EmptyString(),
- NS_LITERAL_STRING(kFileMime),
- mSourceDoc,
- mDestinationNode, mDestOffset,
- mDoDeleteSelection,
- mIsSafe, false);
- return rv;
-}
-
-NS_IMETHODIMP
-HTMLEditor::BlobReader::OnError(const nsAString& aError)
-{
- nsCOMPtr<nsINode> destNode = do_QueryInterface(mDestinationNode);
- const nsPromiseFlatString& flat = PromiseFlatString(aError);
- const char16_t* error = flat.get();
- nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
- NS_LITERAL_CSTRING("Editor"),
- destNode->OwnerDoc(),
- nsContentUtils::eDOM_PROPERTIES,
- "EditorFileDropFailed",
- &error, 1);
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::InsertObject(const nsACString& aType,
- nsISupports* aObject,
- bool aIsSafe,
- nsIDOMDocument* aSourceDoc,
- nsIDOMNode* aDestinationNode,
- int32_t aDestOffset,
- bool aDoDeleteSelection)
-{
- nsresult rv;
-
- if (nsCOMPtr<BlobImpl> blob = do_QueryInterface(aObject)) {
- RefPtr<BlobReader> br = new BlobReader(blob, this, aIsSafe, aSourceDoc,
- aDestinationNode, aDestOffset,
- aDoDeleteSelection);
- nsCOMPtr<nsIEditorUtils> utils =
- do_GetService("@mozilla.org/editor-utils;1");
- NS_ENSURE_TRUE(utils, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsINode> node = do_QueryInterface(aDestinationNode);
- MOZ_ASSERT(node);
-
- nsCOMPtr<nsIDOMBlob> domBlob = Blob::Create(node->GetOwnerGlobal(), blob);
- NS_ENSURE_TRUE(domBlob, NS_ERROR_FAILURE);
-
- return utils->SlurpBlob(domBlob, node->OwnerDoc()->GetWindow(), br);
- }
-
- nsAutoCString type(aType);
-
- // Check to see if we can insert an image file
- bool insertAsImage = false;
- nsCOMPtr<nsIFile> fileObj;
- if (type.EqualsLiteral(kFileMime)) {
- fileObj = do_QueryInterface(aObject);
- if (fileObj) {
- // Accept any image type fed to us
- if (nsContentUtils::IsFileImage(fileObj, type)) {
- insertAsImage = true;
- } else {
- // Reset type.
- type.AssignLiteral(kFileMime);
- }
- }
- }
-
- if (type.EqualsLiteral(kJPEGImageMime) ||
- type.EqualsLiteral(kJPGImageMime) ||
- type.EqualsLiteral(kPNGImageMime) ||
- type.EqualsLiteral(kGIFImageMime) ||
- insertAsImage) {
- nsCString imageData;
- if (insertAsImage) {
- rv = nsContentUtils::SlurpFileToString(fileObj, imageData);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- nsCOMPtr<nsIInputStream> imageStream = do_QueryInterface(aObject);
- NS_ENSURE_TRUE(imageStream, NS_ERROR_FAILURE);
-
- rv = NS_ConsumeStream(imageStream, UINT32_MAX, imageData);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = imageStream->Close();
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- nsAutoString stuffToPaste;
- rv = ImgFromData(type, imageData, stuffToPaste);
- NS_ENSURE_SUCCESS(rv, rv);
-
- AutoEditBatch beginBatching(this);
- rv = DoInsertHTMLWithContext(stuffToPaste, EmptyString(), EmptyString(),
- NS_LITERAL_STRING(kFileMime),
- aSourceDoc,
- aDestinationNode, aDestOffset,
- aDoDeleteSelection,
- aIsSafe, false);
- }
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::InsertFromTransferable(nsITransferable* transferable,
- nsIDOMDocument* aSourceDoc,
- const nsAString& aContextStr,
- const nsAString& aInfoStr,
- bool havePrivateHTMLFlavor,
- nsIDOMNode* aDestinationNode,
- int32_t aDestOffset,
- bool aDoDeleteSelection)
-{
- nsresult rv = NS_OK;
- nsAutoCString bestFlavor;
- nsCOMPtr<nsISupports> genericDataObj;
- uint32_t len = 0;
- if (NS_SUCCEEDED(
- transferable->GetAnyTransferData(bestFlavor,
- getter_AddRefs(genericDataObj),
- &len))) {
- AutoTransactionsConserveSelection dontSpazMySelection(this);
- nsAutoString flavor;
- flavor.AssignWithConversion(bestFlavor);
- nsAutoString stuffToPaste;
- bool isSafe = IsSafeToInsertData(aSourceDoc);
-
- if (bestFlavor.EqualsLiteral(kFileMime) ||
- bestFlavor.EqualsLiteral(kJPEGImageMime) ||
- bestFlavor.EqualsLiteral(kJPGImageMime) ||
- bestFlavor.EqualsLiteral(kPNGImageMime) ||
- bestFlavor.EqualsLiteral(kGIFImageMime)) {
- rv = InsertObject(bestFlavor, genericDataObj, isSafe,
- aSourceDoc, aDestinationNode, aDestOffset, aDoDeleteSelection);
- } else if (bestFlavor.EqualsLiteral(kNativeHTMLMime)) {
- // note cf_html uses utf8, hence use length = len, not len/2 as in flavors below
- nsCOMPtr<nsISupportsCString> textDataObj = do_QueryInterface(genericDataObj);
- if (textDataObj && len > 0) {
- nsAutoCString cfhtml;
- textDataObj->GetData(cfhtml);
- NS_ASSERTION(cfhtml.Length() <= (len), "Invalid length!");
- nsXPIDLString cfcontext, cffragment, cfselection; // cfselection left emtpy for now
-
- rv = ParseCFHTML(cfhtml, getter_Copies(cffragment), getter_Copies(cfcontext));
- if (NS_SUCCEEDED(rv) && !cffragment.IsEmpty()) {
- AutoEditBatch beginBatching(this);
- // If we have our private HTML flavor, we will only use the fragment
- // from the CF_HTML. The rest comes from the clipboard.
- if (havePrivateHTMLFlavor) {
- rv = DoInsertHTMLWithContext(cffragment,
- aContextStr, aInfoStr, flavor,
- aSourceDoc,
- aDestinationNode, aDestOffset,
- aDoDeleteSelection,
- isSafe);
- } else {
- rv = DoInsertHTMLWithContext(cffragment,
- cfcontext, cfselection, flavor,
- aSourceDoc,
- aDestinationNode, aDestOffset,
- aDoDeleteSelection,
- isSafe);
-
- }
- } else {
- // In some platforms (like Linux), the clipboard might return data
- // requested for unknown flavors (for example:
- // application/x-moz-nativehtml). In this case, treat the data
- // to be pasted as mere HTML to get the best chance of pasting it
- // correctly.
- bestFlavor.AssignLiteral(kHTMLMime);
- // Fall through the next case
- }
- }
- }
- if (bestFlavor.EqualsLiteral(kHTMLMime) ||
- bestFlavor.EqualsLiteral(kUnicodeMime) ||
- bestFlavor.EqualsLiteral(kMozTextInternal)) {
- nsCOMPtr<nsISupportsString> textDataObj = do_QueryInterface(genericDataObj);
- if (textDataObj && len > 0) {
- nsAutoString text;
- textDataObj->GetData(text);
- NS_ASSERTION(text.Length() <= (len/2), "Invalid length!");
- stuffToPaste.Assign(text.get(), len / 2);
- } else {
- nsCOMPtr<nsISupportsCString> textDataObj(do_QueryInterface(genericDataObj));
- if (textDataObj && len > 0) {
- nsAutoCString text;
- textDataObj->GetData(text);
- NS_ASSERTION(text.Length() <= len, "Invalid length!");
- stuffToPaste.Assign(NS_ConvertUTF8toUTF16(Substring(text, 0, len)));
- }
- }
-
- if (!stuffToPaste.IsEmpty()) {
- AutoEditBatch beginBatching(this);
- if (bestFlavor.EqualsLiteral(kHTMLMime)) {
- rv = DoInsertHTMLWithContext(stuffToPaste,
- aContextStr, aInfoStr, flavor,
- aSourceDoc,
- aDestinationNode, aDestOffset,
- aDoDeleteSelection,
- isSafe);
- } else {
- rv = InsertTextAt(stuffToPaste, aDestinationNode, aDestOffset, aDoDeleteSelection);
- }
- }
- }
- }
-
- // Try to scroll the selection into view if the paste succeeded
- if (NS_SUCCEEDED(rv)) {
- ScrollSelectionIntoView(false);
- }
- return rv;
-}
-
-static void
-GetStringFromDataTransfer(nsIDOMDataTransfer* aDataTransfer,
- const nsAString& aType,
- int32_t aIndex,
- nsAString& aOutputString)
-{
- nsCOMPtr<nsIVariant> variant;
- DataTransfer::Cast(aDataTransfer)->GetDataAtNoSecurityCheck(aType, aIndex, getter_AddRefs(variant));
- if (variant) {
- variant->GetAsAString(aOutputString);
- }
-}
-
-nsresult
-HTMLEditor::InsertFromDataTransfer(DataTransfer* aDataTransfer,
- int32_t aIndex,
- nsIDOMDocument* aSourceDoc,
- nsIDOMNode* aDestinationNode,
- int32_t aDestOffset,
- bool aDoDeleteSelection)
-{
- ErrorResult rv;
- RefPtr<DOMStringList> types = aDataTransfer->MozTypesAt(aIndex, rv);
- if (rv.Failed()) {
- return rv.StealNSResult();
- }
-
- bool hasPrivateHTMLFlavor = types->Contains(NS_LITERAL_STRING(kHTMLContext));
-
- bool isText = IsPlaintextEditor();
- bool isSafe = IsSafeToInsertData(aSourceDoc);
-
- uint32_t length = types->Length();
- for (uint32_t t = 0; t < length; t++) {
- nsAutoString type;
- types->Item(t, type);
-
- if (!isText) {
- if (type.EqualsLiteral(kFileMime) ||
- type.EqualsLiteral(kJPEGImageMime) ||
- type.EqualsLiteral(kJPGImageMime) ||
- type.EqualsLiteral(kPNGImageMime) ||
- type.EqualsLiteral(kGIFImageMime)) {
- nsCOMPtr<nsIVariant> variant;
- DataTransfer::Cast(aDataTransfer)->GetDataAtNoSecurityCheck(type, aIndex, getter_AddRefs(variant));
- if (variant) {
- nsCOMPtr<nsISupports> object;
- variant->GetAsISupports(getter_AddRefs(object));
- return InsertObject(NS_ConvertUTF16toUTF8(type), object, isSafe,
- aSourceDoc, aDestinationNode, aDestOffset, aDoDeleteSelection);
- }
- } else if (type.EqualsLiteral(kNativeHTMLMime)) {
- // Windows only clipboard parsing.
- nsAutoString text;
- GetStringFromDataTransfer(aDataTransfer, type, aIndex, text);
- NS_ConvertUTF16toUTF8 cfhtml(text);
-
- nsXPIDLString cfcontext, cffragment, cfselection; // cfselection left emtpy for now
-
- nsresult rv = ParseCFHTML(cfhtml, getter_Copies(cffragment), getter_Copies(cfcontext));
- if (NS_SUCCEEDED(rv) && !cffragment.IsEmpty()) {
- AutoEditBatch beginBatching(this);
-
- if (hasPrivateHTMLFlavor) {
- // If we have our private HTML flavor, we will only use the fragment
- // from the CF_HTML. The rest comes from the clipboard.
- nsAutoString contextString, infoString;
- GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kHTMLContext), aIndex, contextString);
- GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kHTMLInfo), aIndex, infoString);
- return DoInsertHTMLWithContext(cffragment,
- contextString, infoString, type,
- aSourceDoc,
- aDestinationNode, aDestOffset,
- aDoDeleteSelection,
- isSafe);
- } else {
- return DoInsertHTMLWithContext(cffragment,
- cfcontext, cfselection, type,
- aSourceDoc,
- aDestinationNode, aDestOffset,
- aDoDeleteSelection,
- isSafe);
- }
- }
- } else if (type.EqualsLiteral(kHTMLMime)) {
- nsAutoString text, contextString, infoString;
- GetStringFromDataTransfer(aDataTransfer, type, aIndex, text);
- GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kHTMLContext), aIndex, contextString);
- GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kHTMLInfo), aIndex, infoString);
-
- AutoEditBatch beginBatching(this);
- if (type.EqualsLiteral(kHTMLMime)) {
- return DoInsertHTMLWithContext(text,
- contextString, infoString, type,
- aSourceDoc,
- aDestinationNode, aDestOffset,
- aDoDeleteSelection,
- isSafe);
- }
- }
- }
-
- if (type.EqualsLiteral(kTextMime) ||
- type.EqualsLiteral(kMozTextInternal)) {
- nsAutoString text;
- GetStringFromDataTransfer(aDataTransfer, type, aIndex, text);
-
- AutoEditBatch beginBatching(this);
- return InsertTextAt(text, aDestinationNode, aDestOffset, aDoDeleteSelection);
- }
- }
-
- return NS_OK;
-}
-
-bool
-HTMLEditor::HavePrivateHTMLFlavor(nsIClipboard* aClipboard)
-{
- // check the clipboard for our special kHTMLContext flavor. If that is there, we know
- // we have our own internal html format on clipboard.
-
- NS_ENSURE_TRUE(aClipboard, false);
- bool bHavePrivateHTMLFlavor = false;
-
- const char* flavArray[] = { kHTMLContext };
-
- if (NS_SUCCEEDED(
- aClipboard->HasDataMatchingFlavors(flavArray,
- ArrayLength(flavArray),
- nsIClipboard::kGlobalClipboard,
- &bHavePrivateHTMLFlavor))) {
- return bHavePrivateHTMLFlavor;
- }
-
- return false;
-}
-
-
-NS_IMETHODIMP
-HTMLEditor::Paste(int32_t aSelectionType)
-{
- if (!FireClipboardEvent(ePaste, aSelectionType)) {
- return NS_OK;
- }
-
- // Get Clipboard Service
- nsresult rv;
- nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Get the nsITransferable interface for getting the data from the clipboard
- nsCOMPtr<nsITransferable> trans;
- rv = PrepareHTMLTransferable(getter_AddRefs(trans));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE);
- // Get the Data from the clipboard
- rv = clipboard->GetData(trans, aSelectionType);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!IsModifiable()) {
- return NS_OK;
- }
-
- // also get additional html copy hints, if present
- nsAutoString contextStr, infoStr;
-
- // If we have our internal html flavor on the clipboard, there is special
- // context to use instead of cfhtml context.
- bool bHavePrivateHTMLFlavor = HavePrivateHTMLFlavor(clipboard);
- if (bHavePrivateHTMLFlavor) {
- nsCOMPtr<nsISupports> contextDataObj, infoDataObj;
- uint32_t contextLen, infoLen;
- nsCOMPtr<nsISupportsString> textDataObj;
-
- nsCOMPtr<nsITransferable> contextTrans =
- do_CreateInstance("@mozilla.org/widget/transferable;1");
- NS_ENSURE_TRUE(contextTrans, NS_ERROR_NULL_POINTER);
- contextTrans->Init(nullptr);
- contextTrans->AddDataFlavor(kHTMLContext);
- clipboard->GetData(contextTrans, aSelectionType);
- contextTrans->GetTransferData(kHTMLContext, getter_AddRefs(contextDataObj), &contextLen);
-
- nsCOMPtr<nsITransferable> infoTrans =
- do_CreateInstance("@mozilla.org/widget/transferable;1");
- NS_ENSURE_TRUE(infoTrans, NS_ERROR_NULL_POINTER);
- infoTrans->Init(nullptr);
- infoTrans->AddDataFlavor(kHTMLInfo);
- clipboard->GetData(infoTrans, aSelectionType);
- infoTrans->GetTransferData(kHTMLInfo, getter_AddRefs(infoDataObj), &infoLen);
-
- if (contextDataObj) {
- nsAutoString text;
- textDataObj = do_QueryInterface(contextDataObj);
- textDataObj->GetData(text);
- NS_ASSERTION(text.Length() <= (contextLen/2), "Invalid length!");
- contextStr.Assign(text.get(), contextLen / 2);
- }
-
- if (infoDataObj) {
- nsAutoString text;
- textDataObj = do_QueryInterface(infoDataObj);
- textDataObj->GetData(text);
- NS_ASSERTION(text.Length() <= (infoLen/2), "Invalid length!");
- infoStr.Assign(text.get(), infoLen / 2);
- }
- }
-
- // handle transferable hooks
- nsCOMPtr<nsIDOMDocument> domdoc;
- GetDocument(getter_AddRefs(domdoc));
- if (!EditorHookUtils::DoInsertionHook(domdoc, nullptr, trans)) {
- return NS_OK;
- }
-
- return InsertFromTransferable(trans, nullptr, contextStr, infoStr, bHavePrivateHTMLFlavor,
- nullptr, 0, true);
-}
-
-NS_IMETHODIMP
-HTMLEditor::PasteTransferable(nsITransferable* aTransferable)
-{
- // Use an invalid value for the clipboard type as data comes from aTransferable
- // and we don't currently implement a way to put that in the data transfer yet.
- if (!FireClipboardEvent(ePaste, nsIClipboard::kGlobalClipboard)) {
- return NS_OK;
- }
-
- // handle transferable hooks
- nsCOMPtr<nsIDOMDocument> domdoc = GetDOMDocument();
- if (!EditorHookUtils::DoInsertionHook(domdoc, nullptr, aTransferable)) {
- return NS_OK;
- }
-
- nsAutoString contextStr, infoStr;
- return InsertFromTransferable(aTransferable, nullptr, contextStr, infoStr, false,
- nullptr, 0, true);
-}
-
-/**
- * HTML PasteNoFormatting. Ignore any HTML styles and formating in paste source.
- */
-NS_IMETHODIMP
-HTMLEditor::PasteNoFormatting(int32_t aSelectionType)
-{
- if (!FireClipboardEvent(ePaste, aSelectionType)) {
- return NS_OK;
- }
-
- ForceCompositionEnd();
-
- // Get Clipboard Service
- nsresult rv;
- nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Get the nsITransferable interface for getting the data from the clipboard.
- // use TextEditor::PrepareTransferable() to force unicode plaintext data.
- nsCOMPtr<nsITransferable> trans;
- rv = TextEditor::PrepareTransferable(getter_AddRefs(trans));
- if (NS_SUCCEEDED(rv) && trans) {
- // Get the Data from the clipboard
- if (NS_SUCCEEDED(clipboard->GetData(trans, aSelectionType)) &&
- IsModifiable()) {
- const nsAFlatString& empty = EmptyString();
- rv = InsertFromTransferable(trans, nullptr, empty, empty, false, nullptr, 0,
- true);
- }
- }
-
- return rv;
-}
-
-// The following arrays contain the MIME types that we can paste. The arrays
-// are used by CanPaste() and CanPasteTransferable() below.
-
-static const char* textEditorFlavors[] = { kUnicodeMime };
-static const char* textHtmlEditorFlavors[] = { kUnicodeMime, kHTMLMime,
- kJPEGImageMime, kJPGImageMime,
- kPNGImageMime, kGIFImageMime };
-
-NS_IMETHODIMP
-HTMLEditor::CanPaste(int32_t aSelectionType,
- bool* aCanPaste)
-{
- NS_ENSURE_ARG_POINTER(aCanPaste);
- *aCanPaste = false;
-
- // Always enable the paste command when inside of a HTML or XHTML document.
- nsCOMPtr<nsIDocument> doc = GetDocument();
- if (doc && doc->IsHTMLOrXHTML()) {
- *aCanPaste = true;
- return NS_OK;
- }
-
- // can't paste if readonly
- if (!IsModifiable()) {
- return NS_OK;
- }
-
- nsresult rv;
- nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
- NS_ENSURE_SUCCESS(rv, rv);
-
- bool haveFlavors;
-
- // Use the flavors depending on the current editor mask
- if (IsPlaintextEditor()) {
- rv = clipboard->HasDataMatchingFlavors(textEditorFlavors,
- ArrayLength(textEditorFlavors),
- aSelectionType, &haveFlavors);
- } else {
- rv = clipboard->HasDataMatchingFlavors(textHtmlEditorFlavors,
- ArrayLength(textHtmlEditorFlavors),
- aSelectionType, &haveFlavors);
- }
- NS_ENSURE_SUCCESS(rv, rv);
-
- *aCanPaste = haveFlavors;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::CanPasteTransferable(nsITransferable* aTransferable,
- bool* aCanPaste)
-{
- NS_ENSURE_ARG_POINTER(aCanPaste);
-
- // can't paste if readonly
- if (!IsModifiable()) {
- *aCanPaste = false;
- return NS_OK;
- }
-
- // If |aTransferable| is null, assume that a paste will succeed.
- if (!aTransferable) {
- *aCanPaste = true;
- return NS_OK;
- }
-
- // Peek in |aTransferable| to see if it contains a supported MIME type.
-
- // Use the flavors depending on the current editor mask
- const char ** flavors;
- unsigned length;
- if (IsPlaintextEditor()) {
- flavors = textEditorFlavors;
- length = ArrayLength(textEditorFlavors);
- } else {
- flavors = textHtmlEditorFlavors;
- length = ArrayLength(textHtmlEditorFlavors);
- }
-
- for (unsigned int i = 0; i < length; i++, flavors++) {
- nsCOMPtr<nsISupports> data;
- uint32_t dataLen;
- nsresult rv = aTransferable->GetTransferData(*flavors,
- getter_AddRefs(data),
- &dataLen);
- if (NS_SUCCEEDED(rv) && data) {
- *aCanPaste = true;
- return NS_OK;
- }
- }
-
- *aCanPaste = false;
- return NS_OK;
-}
-
-/**
- * HTML PasteAsQuotation: Paste in a blockquote type=cite.
- */
-NS_IMETHODIMP
-HTMLEditor::PasteAsQuotation(int32_t aSelectionType)
-{
- if (IsPlaintextEditor()) {
- return PasteAsPlaintextQuotation(aSelectionType);
- }
-
- nsAutoString citation;
- return PasteAsCitedQuotation(citation, aSelectionType);
-}
-
-NS_IMETHODIMP
-HTMLEditor::PasteAsCitedQuotation(const nsAString& aCitation,
- int32_t aSelectionType)
-{
- AutoEditBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::insertQuotation,
- nsIEditor::eNext);
-
- // get selection
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- // give rules a chance to handle or cancel
- TextRulesInfo ruleInfo(EditAction::insertElement);
- bool cancel, handled;
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
- if (cancel || handled) {
- return NS_OK; // rules canceled the operation
- }
-
- nsCOMPtr<Element> newNode =
- DeleteSelectionAndCreateElement(*nsGkAtoms::blockquote);
- NS_ENSURE_TRUE(newNode, NS_ERROR_NULL_POINTER);
-
- // Try to set type=cite. Ignore it if this fails.
- newNode->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
- NS_LITERAL_STRING("cite"), true);
-
- // Set the selection to the underneath the node we just inserted:
- rv = selection->Collapse(newNode, 0);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Ensure that the inserted <blockquote> has a frame to make it IsEditable.
- FlushFrames();
-
- return Paste(aSelectionType);
-}
-
-/**
- * Paste a plaintext quotation.
- */
-NS_IMETHODIMP
-HTMLEditor::PasteAsPlaintextQuotation(int32_t aSelectionType)
-{
- // Get Clipboard Service
- nsresult rv;
- nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Create generic Transferable for getting the data
- nsCOMPtr<nsITransferable> trans =
- do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIDocument> destdoc = GetDocument();
- nsILoadContext* loadContext = destdoc ? destdoc->GetLoadContext() : nullptr;
- trans->Init(loadContext);
-
- // We only handle plaintext pastes here
- trans->AddDataFlavor(kUnicodeMime);
-
- // Get the Data from the clipboard
- clipboard->GetData(trans, aSelectionType);
-
- // Now we ask the transferable for the data
- // it still owns the data, we just have a pointer to it.
- // If it can't support a "text" output of the data the call will fail
- nsCOMPtr<nsISupports> genericDataObj;
- uint32_t len = 0;
- nsAutoCString flav;
- rv = trans->GetAnyTransferData(flav, getter_AddRefs(genericDataObj), &len);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (flav.EqualsLiteral(kUnicodeMime)) {
- nsCOMPtr<nsISupportsString> textDataObj = do_QueryInterface(genericDataObj);
- if (textDataObj && len > 0) {
- nsAutoString stuffToPaste;
- textDataObj->GetData(stuffToPaste);
- NS_ASSERTION(stuffToPaste.Length() <= (len/2), "Invalid length!");
- AutoEditBatch beginBatching(this);
- rv = InsertAsPlaintextQuotation(stuffToPaste, true, 0);
- }
- }
-
- return rv;
-}
-
-NS_IMETHODIMP
-HTMLEditor::InsertTextWithQuotations(const nsAString& aStringToInsert)
-{
- AutoEditBatch beginBatching(this);
- // The whole operation should be undoable in one transaction:
- BeginTransaction();
-
- // We're going to loop over the string, collecting up a "hunk"
- // that's all the same type (quoted or not),
- // Whenever the quotedness changes (or we reach the string's end)
- // we will insert the hunk all at once, quoted or non.
-
- static const char16_t cite('>');
- bool curHunkIsQuoted = (aStringToInsert.First() == cite);
-
- nsAString::const_iterator hunkStart, strEnd;
- aStringToInsert.BeginReading(hunkStart);
- aStringToInsert.EndReading(strEnd);
-
- // In the loop below, we only look for DOM newlines (\n),
- // because we don't have a FindChars method that can look
- // for both \r and \n. \r is illegal in the dom anyway,
- // but in debug builds, let's take the time to verify that
- // there aren't any there:
-#ifdef DEBUG
- nsAString::const_iterator dbgStart (hunkStart);
- if (FindCharInReadable('\r', dbgStart, strEnd)) {
- NS_ASSERTION(false,
- "Return characters in DOM! InsertTextWithQuotations may be wrong");
- }
-#endif /* DEBUG */
-
- // Loop over lines:
- nsresult rv = NS_OK;
- nsAString::const_iterator lineStart (hunkStart);
- // We will break from inside when we run out of newlines.
- for (;;) {
- // Search for the end of this line (dom newlines, see above):
- bool found = FindCharInReadable('\n', lineStart, strEnd);
- bool quoted = false;
- if (found) {
- // if there's another newline, lineStart now points there.
- // Loop over any consecutive newline chars:
- nsAString::const_iterator firstNewline (lineStart);
- while (*lineStart == '\n') {
- ++lineStart;
- }
- quoted = (*lineStart == cite);
- if (quoted == curHunkIsQuoted) {
- continue;
- }
- // else we're changing state, so we need to insert
- // from curHunk to lineStart then loop around.
-
- // But if the current hunk is quoted, then we want to make sure
- // that any extra newlines on the end do not get included in
- // the quoted section: blank lines flaking a quoted section
- // should be considered unquoted, so that if the user clicks
- // there and starts typing, the new text will be outside of
- // the quoted block.
- if (curHunkIsQuoted) {
- lineStart = firstNewline;
-
- // 'firstNewline' points to the first '\n'. We want to
- // ensure that this first newline goes into the hunk
- // since quoted hunks can be displayed as blocks
- // (and the newline should become invisible in this case).
- // So the next line needs to start at the next character.
- lineStart++;
- }
- }
-
- // If no newline found, lineStart is now strEnd and we can finish up,
- // inserting from curHunk to lineStart then returning.
- const nsAString &curHunk = Substring(hunkStart, lineStart);
- nsCOMPtr<nsIDOMNode> dummyNode;
- if (curHunkIsQuoted) {
- rv = InsertAsPlaintextQuotation(curHunk, false,
- getter_AddRefs(dummyNode));
- } else {
- rv = InsertText(curHunk);
- }
- if (!found) {
- break;
- }
- curHunkIsQuoted = quoted;
- hunkStart = lineStart;
- }
-
- EndTransaction();
-
- return rv;
-}
-
-NS_IMETHODIMP
-HTMLEditor::InsertAsQuotation(const nsAString& aQuotedText,
- nsIDOMNode** aNodeInserted)
-{
- if (IsPlaintextEditor()) {
- return InsertAsPlaintextQuotation(aQuotedText, true, aNodeInserted);
- }
-
- nsAutoString citation;
- return InsertAsCitedQuotation(aQuotedText, citation, false,
- aNodeInserted);
-}
-
-// Insert plaintext as a quotation, with cite marks (e.g. "> ").
-// This differs from its corresponding method in TextEditor
-// in that here, quoted material is enclosed in a <pre> tag
-// in order to preserve the original line wrapping.
-NS_IMETHODIMP
-HTMLEditor::InsertAsPlaintextQuotation(const nsAString& aQuotedText,
- bool aAddCites,
- nsIDOMNode** aNodeInserted)
-{
- // get selection
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- AutoEditBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::insertQuotation,
- nsIEditor::eNext);
-
- // give rules a chance to handle or cancel
- TextRulesInfo ruleInfo(EditAction::insertElement);
- bool cancel, handled;
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
- if (cancel || handled) {
- return NS_OK; // rules canceled the operation
- }
-
- // Wrap the inserted quote in a <span> so we can distinguish it. If we're
- // inserting into the <body>, we use a <span> which is displayed as a block
- // and sized to the screen using 98 viewport width units.
- // We could use 100vw, but 98vw avoids a horizontal scroll bar where possible.
- // All this is done to wrap overlong lines to the screen and not to the
- // container element, the width-restricted body.
- nsCOMPtr<Element> newNode =
- DeleteSelectionAndCreateElement(*nsGkAtoms::span);
-
- // If this succeeded, then set selection inside the pre
- // so the inserted text will end up there.
- // If it failed, we don't care what the return value was,
- // but we'll fall through and try to insert the text anyway.
- if (newNode) {
- // Add an attribute on the pre node so we'll know it's a quotation.
- newNode->SetAttr(kNameSpaceID_None, nsGkAtoms::mozquote,
- NS_LITERAL_STRING("true"), true);
- // Allow wrapping on spans so long lines get wrapped to the screen.
- nsCOMPtr<nsINode> parent = newNode->GetParentNode();
- if (parent && parent->IsHTMLElement(nsGkAtoms::body)) {
- newNode->SetAttr(kNameSpaceID_None, nsGkAtoms::style,
- NS_LITERAL_STRING("white-space: pre-wrap; display: block; width: 98vw;"),
- true);
- } else {
- newNode->SetAttr(kNameSpaceID_None, nsGkAtoms::style,
- NS_LITERAL_STRING("white-space: pre-wrap;"), true);
- }
-
- // and set the selection inside it:
- selection->Collapse(newNode, 0);
- }
-
- // Ensure that the inserted <span> has a frame to make it IsEditable.
- FlushFrames();
-
- if (aAddCites) {
- rv = TextEditor::InsertAsQuotation(aQuotedText, aNodeInserted);
- } else {
- rv = TextEditor::InsertText(aQuotedText);
- }
- // Note that if !aAddCites, aNodeInserted isn't set.
- // That's okay because the routines that use aAddCites
- // don't need to know the inserted node.
-
- if (aNodeInserted && NS_SUCCEEDED(rv)) {
- *aNodeInserted = GetAsDOMNode(newNode);
- NS_IF_ADDREF(*aNodeInserted);
- }
-
- // Set the selection to just after the inserted node:
- if (NS_SUCCEEDED(rv) && newNode) {
- nsCOMPtr<nsINode> parent = newNode->GetParentNode();
- int32_t offset = parent ? parent->IndexOf(newNode) : -1;
- if (parent) {
- selection->Collapse(parent, offset + 1);
- }
- }
- return rv;
-}
-
-NS_IMETHODIMP
-HTMLEditor::StripCites()
-{
- return TextEditor::StripCites();
-}
-
-NS_IMETHODIMP
-HTMLEditor::Rewrap(bool aRespectNewlines)
-{
- return TextEditor::Rewrap(aRespectNewlines);
-}
-
-NS_IMETHODIMP
-HTMLEditor::InsertAsCitedQuotation(const nsAString& aQuotedText,
- const nsAString& aCitation,
- bool aInsertHTML,
- nsIDOMNode** aNodeInserted)
-{
- // Don't let anyone insert html into a "plaintext" editor:
- if (IsPlaintextEditor()) {
- NS_ASSERTION(!aInsertHTML, "InsertAsCitedQuotation: trying to insert html into plaintext editor");
- return InsertAsPlaintextQuotation(aQuotedText, true, aNodeInserted);
- }
-
- // get selection
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- AutoEditBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::insertQuotation,
- nsIEditor::eNext);
-
- // give rules a chance to handle or cancel
- TextRulesInfo ruleInfo(EditAction::insertElement);
- bool cancel, handled;
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
- if (cancel || handled) {
- return NS_OK; // rules canceled the operation
- }
-
- nsCOMPtr<Element> newNode =
- DeleteSelectionAndCreateElement(*nsGkAtoms::blockquote);
- NS_ENSURE_TRUE(newNode, NS_ERROR_NULL_POINTER);
-
- // Try to set type=cite. Ignore it if this fails.
- newNode->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
- NS_LITERAL_STRING("cite"), true);
-
- if (!aCitation.IsEmpty()) {
- newNode->SetAttr(kNameSpaceID_None, nsGkAtoms::cite, aCitation, true);
- }
-
- // Set the selection inside the blockquote so aQuotedText will go there:
- selection->Collapse(newNode, 0);
-
- // Ensure that the inserted <blockquote> has a frame to make it IsEditable.
- FlushFrames();
-
- if (aInsertHTML) {
- rv = LoadHTML(aQuotedText);
- } else {
- rv = InsertText(aQuotedText); // XXX ignore charset
- }
-
- if (aNodeInserted && NS_SUCCEEDED(rv)) {
- *aNodeInserted = GetAsDOMNode(newNode);
- NS_IF_ADDREF(*aNodeInserted);
- }
-
- // Set the selection to just after the inserted node:
- if (NS_SUCCEEDED(rv) && newNode) {
- nsCOMPtr<nsINode> parent = newNode->GetParentNode();
- int32_t offset = parent ? parent->IndexOf(newNode) : -1;
- if (parent) {
- selection->Collapse(parent, offset + 1);
- }
- }
- return rv;
-}
-
-
-void RemoveBodyAndHead(nsINode& aNode)
-{
- nsCOMPtr<nsIContent> body, head;
- // find the body and head nodes if any.
- // look only at immediate children of aNode.
- for (nsCOMPtr<nsIContent> child = aNode.GetFirstChild();
- child;
- child = child->GetNextSibling()) {
- if (child->IsHTMLElement(nsGkAtoms::body)) {
- body = child;
- } else if (child->IsHTMLElement(nsGkAtoms::head)) {
- head = child;
- }
- }
- if (head) {
- ErrorResult ignored;
- aNode.RemoveChild(*head, ignored);
- }
- if (body) {
- nsCOMPtr<nsIContent> child = body->GetFirstChild();
- while (child) {
- ErrorResult ignored;
- aNode.InsertBefore(*child, body, ignored);
- child = body->GetFirstChild();
- }
-
- ErrorResult ignored;
- aNode.RemoveChild(*body, ignored);
- }
-}
-
-/**
- * This function finds the target node that we will be pasting into. aStart is
- * the context that we're given and aResult will be the target. Initially,
- * *aResult must be nullptr.
- *
- * The target for a paste is found by either finding the node that contains
- * the magical comment node containing kInsertCookie or, failing that, the
- * firstChild of the firstChild (until we reach a leaf).
- */
-nsresult FindTargetNode(nsIDOMNode *aStart, nsCOMPtr<nsIDOMNode> &aResult)
-{
- NS_ENSURE_TRUE(aStart, NS_OK);
-
- nsCOMPtr<nsIDOMNode> child, tmp;
-
- nsresult rv = aStart->GetFirstChild(getter_AddRefs(child));
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!child) {
- // If the current result is nullptr, then aStart is a leaf, and is the
- // fallback result.
- if (!aResult) {
- aResult = aStart;
- }
- return NS_OK;
- }
-
- do {
- // Is this child the magical cookie?
- nsCOMPtr<nsIDOMComment> comment = do_QueryInterface(child);
- if (comment) {
- nsAutoString data;
- rv = comment->GetData(data);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (data.EqualsLiteral(kInsertCookie)) {
- // Yes it is! Return an error so we bubble out and short-circuit the
- // search.
- aResult = aStart;
-
- // Note: it doesn't matter if this fails.
- aStart->RemoveChild(child, getter_AddRefs(tmp));
-
- return NS_SUCCESS_EDITOR_FOUND_TARGET;
- }
- }
-
- rv = FindTargetNode(child, aResult);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (rv == NS_SUCCESS_EDITOR_FOUND_TARGET) {
- return NS_SUCCESS_EDITOR_FOUND_TARGET;
- }
-
- rv = child->GetNextSibling(getter_AddRefs(tmp));
- NS_ENSURE_SUCCESS(rv, rv);
-
- child = tmp;
- } while (child);
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::CreateDOMFragmentFromPaste(const nsAString& aInputString,
- const nsAString& aContextStr,
- const nsAString& aInfoStr,
- nsCOMPtr<nsIDOMNode>* outFragNode,
- nsCOMPtr<nsIDOMNode>* outStartNode,
- nsCOMPtr<nsIDOMNode>* outEndNode,
- int32_t* outStartOffset,
- int32_t* outEndOffset,
- bool aTrustedInput)
-{
- NS_ENSURE_TRUE(outFragNode && outStartNode && outEndNode, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsIDocument> doc = GetDocument();
- NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
-
- // if we have context info, create a fragment for that
- nsresult rv = NS_OK;
- nsCOMPtr<nsIDOMNode> contextLeaf;
- RefPtr<DocumentFragment> contextAsNode;
- if (!aContextStr.IsEmpty()) {
- rv = ParseFragment(aContextStr, nullptr, doc, getter_AddRefs(contextAsNode),
- aTrustedInput);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(contextAsNode, NS_ERROR_FAILURE);
-
- rv = StripFormattingNodes(*contextAsNode);
- NS_ENSURE_SUCCESS(rv, rv);
-
- RemoveBodyAndHead(*contextAsNode);
-
- rv = FindTargetNode(contextAsNode, contextLeaf);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- nsCOMPtr<nsIContent> contextLeafAsContent = do_QueryInterface(contextLeaf);
-
- // create fragment for pasted html
- nsIAtom* contextAtom;
- if (contextLeafAsContent) {
- contextAtom = contextLeafAsContent->NodeInfo()->NameAtom();
- if (contextLeafAsContent->IsHTMLElement(nsGkAtoms::html)) {
- contextAtom = nsGkAtoms::body;
- }
- } else {
- contextAtom = nsGkAtoms::body;
- }
- RefPtr<DocumentFragment> fragment;
- rv = ParseFragment(aInputString,
- contextAtom,
- doc,
- getter_AddRefs(fragment),
- aTrustedInput);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(fragment, NS_ERROR_FAILURE);
-
- RemoveBodyAndHead(*fragment);
-
- if (contextAsNode) {
- // unite the two trees
- nsCOMPtr<nsIDOMNode> junk;
- contextLeaf->AppendChild(fragment, getter_AddRefs(junk));
- fragment = contextAsNode;
- }
-
- rv = StripFormattingNodes(*fragment, true);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // If there was no context, then treat all of the data we did get as the
- // pasted data.
- if (contextLeaf) {
- *outEndNode = *outStartNode = contextLeaf;
- } else {
- *outEndNode = *outStartNode = fragment;
- }
-
- *outFragNode = fragment.forget();
- *outStartOffset = 0;
-
- // get the infoString contents
- if (!aInfoStr.IsEmpty()) {
- int32_t sep = aInfoStr.FindChar((char16_t)',');
- nsAutoString numstr1(Substring(aInfoStr, 0, sep));
- nsAutoString numstr2(Substring(aInfoStr, sep+1, aInfoStr.Length() - (sep+1)));
-
- // Move the start and end children.
- nsresult err;
- int32_t num = numstr1.ToInteger(&err);
-
- nsCOMPtr<nsIDOMNode> tmp;
- while (num--) {
- (*outStartNode)->GetFirstChild(getter_AddRefs(tmp));
- NS_ENSURE_TRUE(tmp, NS_ERROR_FAILURE);
- tmp.swap(*outStartNode);
- }
-
- num = numstr2.ToInteger(&err);
- while (num--) {
- (*outEndNode)->GetLastChild(getter_AddRefs(tmp));
- NS_ENSURE_TRUE(tmp, NS_ERROR_FAILURE);
- tmp.swap(*outEndNode);
- }
- }
-
- nsCOMPtr<nsINode> node = do_QueryInterface(*outEndNode);
- *outEndOffset = node->Length();
- return NS_OK;
-}
-
-
-nsresult
-HTMLEditor::ParseFragment(const nsAString& aFragStr,
- nsIAtom* aContextLocalName,
- nsIDocument* aTargetDocument,
- DocumentFragment** aFragment,
- bool aTrustedInput)
-{
- nsAutoScriptBlockerSuppressNodeRemoved autoBlocker;
-
- RefPtr<DocumentFragment> fragment =
- new DocumentFragment(aTargetDocument->NodeInfoManager());
- nsresult rv = nsContentUtils::ParseFragmentHTML(aFragStr,
- fragment,
- aContextLocalName ?
- aContextLocalName : nsGkAtoms::body,
- kNameSpaceID_XHTML,
- false,
- true);
- if (!aTrustedInput) {
- nsTreeSanitizer sanitizer(aContextLocalName ?
- nsIParserUtils::SanitizerAllowStyle :
- nsIParserUtils::SanitizerAllowComments);
- sanitizer.Sanitize(fragment);
- }
- fragment.forget(aFragment);
- return rv;
-}
-
-void
-HTMLEditor::CreateListOfNodesToPaste(
- DocumentFragment& aFragment,
- nsTArray<OwningNonNull<nsINode>>& outNodeList,
- nsINode* aStartNode,
- int32_t aStartOffset,
- nsINode* aEndNode,
- int32_t aEndOffset)
-{
- // If no info was provided about the boundary between context and stream,
- // then assume all is stream.
- if (!aStartNode) {
- aStartNode = &aFragment;
- aStartOffset = 0;
- aEndNode = &aFragment;
- aEndOffset = aFragment.Length();
- }
-
- RefPtr<nsRange> docFragRange;
- nsresult rv = nsRange::CreateRange(aStartNode, aStartOffset,
- aEndNode, aEndOffset,
- getter_AddRefs(docFragRange));
- MOZ_ASSERT(NS_SUCCEEDED(rv));
- NS_ENSURE_SUCCESS(rv, );
-
- // Now use a subtree iterator over the range to create a list of nodes
- TrivialFunctor functor;
- DOMSubtreeIterator iter;
- rv = iter.Init(*docFragRange);
- NS_ENSURE_SUCCESS(rv, );
- iter.AppendList(functor, outNodeList);
-}
-
-void
-HTMLEditor::GetListAndTableParents(StartOrEnd aStartOrEnd,
- nsTArray<OwningNonNull<nsINode>>& aNodeList,
- nsTArray<OwningNonNull<Element>>& outArray)
-{
- MOZ_ASSERT(aNodeList.Length());
-
- // Build up list of parents of first (or last) node in list that are either
- // lists, or tables.
- int32_t idx = aStartOrEnd == StartOrEnd::end ? aNodeList.Length() - 1 : 0;
-
- for (nsCOMPtr<nsINode> node = aNodeList[idx]; node;
- node = node->GetParentNode()) {
- if (HTMLEditUtils::IsList(node) || HTMLEditUtils::IsTable(node)) {
- outArray.AppendElement(*node->AsElement());
- }
- }
-}
-
-int32_t
-HTMLEditor::DiscoverPartialListsAndTables(
- nsTArray<OwningNonNull<nsINode>>& aPasteNodes,
- nsTArray<OwningNonNull<Element>>& aListsAndTables)
-{
- int32_t ret = -1;
- int32_t listAndTableParents = aListsAndTables.Length();
-
- // Scan insertion list for table elements (other than table).
- for (auto& curNode : aPasteNodes) {
- if (HTMLEditUtils::IsTableElement(curNode) &&
- !curNode->IsHTMLElement(nsGkAtoms::table)) {
- nsCOMPtr<Element> table = curNode->GetParentElement();
- while (table && !table->IsHTMLElement(nsGkAtoms::table)) {
- table = table->GetParentElement();
- }
- if (table) {
- int32_t idx = aListsAndTables.IndexOf(table);
- if (idx == -1) {
- return ret;
- }
- ret = idx;
- if (ret == listAndTableParents - 1) {
- return ret;
- }
- }
- }
- if (HTMLEditUtils::IsListItem(curNode)) {
- nsCOMPtr<Element> list = curNode->GetParentElement();
- while (list && !HTMLEditUtils::IsList(list)) {
- list = list->GetParentElement();
- }
- if (list) {
- int32_t idx = aListsAndTables.IndexOf(list);
- if (idx == -1) {
- return ret;
- }
- ret = idx;
- if (ret == listAndTableParents - 1) {
- return ret;
- }
- }
- }
- }
- return ret;
-}
-
-nsINode*
-HTMLEditor::ScanForListAndTableStructure(
- StartOrEnd aStartOrEnd,
- nsTArray<OwningNonNull<nsINode>>& aNodes,
- Element& aListOrTable)
-{
- // Look upward from first/last paste node for a piece of this list/table
- int32_t idx = aStartOrEnd == StartOrEnd::end ? aNodes.Length() - 1 : 0;
- bool isList = HTMLEditUtils::IsList(&aListOrTable);
-
- for (nsCOMPtr<nsINode> node = aNodes[idx]; node;
- node = node->GetParentNode()) {
- if ((isList && HTMLEditUtils::IsListItem(node)) ||
- (!isList && HTMLEditUtils::IsTableElement(node) &&
- !node->IsHTMLElement(nsGkAtoms::table))) {
- nsCOMPtr<Element> structureNode = node->GetParentElement();
- if (isList) {
- while (structureNode && !HTMLEditUtils::IsList(structureNode)) {
- structureNode = structureNode->GetParentElement();
- }
- } else {
- while (structureNode &&
- !structureNode->IsHTMLElement(nsGkAtoms::table)) {
- structureNode = structureNode->GetParentElement();
- }
- }
- if (structureNode == &aListOrTable) {
- if (isList) {
- return structureNode;
- }
- return node;
- }
- }
- }
- return nullptr;
-}
-
-void
-HTMLEditor::ReplaceOrphanedStructure(
- StartOrEnd aStartOrEnd,
- nsTArray<OwningNonNull<nsINode>>& aNodeArray,
- nsTArray<OwningNonNull<Element>>& aListAndTableArray,
- int32_t aHighWaterMark)
-{
- OwningNonNull<Element> curNode = aListAndTableArray[aHighWaterMark];
-
- // Find substructure of list or table that must be included in paste.
- nsCOMPtr<nsINode> replaceNode =
- ScanForListAndTableStructure(aStartOrEnd, aNodeArray, curNode);
-
- if (!replaceNode) {
- return;
- }
-
- // If we found substructure, paste it instead of its descendants.
- // Postprocess list to remove any descendants of this node so that we don't
- // insert them twice.
- uint32_t removedCount = 0;
- uint32_t originalLength = aNodeArray.Length();
- for (uint32_t i = 0; i < originalLength; i++) {
- uint32_t idx = aStartOrEnd == StartOrEnd::start ?
- (i - removedCount) : (originalLength - i - 1);
- OwningNonNull<nsINode> endpoint = aNodeArray[idx];
- if (endpoint == replaceNode ||
- EditorUtils::IsDescendantOf(endpoint, replaceNode)) {
- aNodeArray.RemoveElementAt(idx);
- removedCount++;
- }
- }
-
- // Now replace the removed nodes with the structural parent
- if (aStartOrEnd == StartOrEnd::end) {
- aNodeArray.AppendElement(*replaceNode);
- } else {
- aNodeArray.InsertElementAt(0, *replaceNode);
- }
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/HTMLEditorEventListener.cpp b/editor/libeditor/HTMLEditorEventListener.cpp
deleted file mode 100644
index aa767519c..000000000
--- a/editor/libeditor/HTMLEditorEventListener.cpp
+++ /dev/null
@@ -1,235 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "HTMLEditorEventListener.h"
-
-#include "HTMLEditUtils.h"
-#include "mozilla/HTMLEditor.h"
-#include "mozilla/MouseEvents.h"
-#include "mozilla/dom/Event.h"
-#include "mozilla/dom/Selection.h"
-#include "nsCOMPtr.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMEvent.h"
-#include "nsIDOMEventTarget.h"
-#include "nsIDOMMouseEvent.h"
-#include "nsIDOMNode.h"
-#include "nsIEditor.h"
-#include "nsIHTMLInlineTableEditor.h"
-#include "nsIHTMLObjectResizer.h"
-#include "nsISupportsImpl.h"
-#include "nsLiteralString.h"
-#include "nsQueryObject.h"
-#include "nsRange.h"
-
-namespace mozilla {
-
-using namespace dom;
-
-#ifdef DEBUG
-nsresult
-HTMLEditorEventListener::Connect(EditorBase* aEditorBase)
-{
- nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryObject(aEditorBase);
- nsCOMPtr<nsIHTMLInlineTableEditor> htmlInlineTableEditor =
- do_QueryObject(aEditorBase);
- NS_PRECONDITION(htmlEditor && htmlInlineTableEditor,
- "Set HTMLEditor or its sub class");
- return EditorEventListener::Connect(aEditorBase);
-}
-#endif
-
-HTMLEditor*
-HTMLEditorEventListener::GetHTMLEditor()
-{
- // mEditor must be HTMLEditor or its subclass.
- return static_cast<HTMLEditor*>(mEditorBase);
-}
-
-nsresult
-HTMLEditorEventListener::MouseUp(nsIDOMMouseEvent* aMouseEvent)
-{
- if (DetachedFromEditor()) {
- return NS_OK;
- }
-
- // FYI: We need to notify HTML editor of mouseup even if it's consumed
- // because HTML editor always needs to release grabbing resizer.
- HTMLEditor* htmlEditor = GetHTMLEditor();
-
- nsCOMPtr<nsIDOMEventTarget> target;
- nsresult rv = aMouseEvent->AsEvent()->GetTarget(getter_AddRefs(target));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(target, NS_ERROR_NULL_POINTER);
- nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
-
- int32_t clientX, clientY;
- aMouseEvent->GetClientX(&clientX);
- aMouseEvent->GetClientY(&clientY);
- htmlEditor->MouseUp(clientX, clientY, element);
-
- return EditorEventListener::MouseUp(aMouseEvent);
-}
-
-nsresult
-HTMLEditorEventListener::MouseDown(nsIDOMMouseEvent* aMouseEvent)
-{
- if (NS_WARN_IF(!aMouseEvent) || DetachedFromEditor()) {
- return NS_OK;
- }
-
- WidgetMouseEvent* mousedownEvent =
- aMouseEvent->AsEvent()->WidgetEventPtr()->AsMouseEvent();
-
- HTMLEditor* htmlEditor = GetHTMLEditor();
- // Contenteditable should disregard mousedowns outside it.
- // IsAcceptableInputEvent() checks it for a mouse event.
- if (!htmlEditor->IsAcceptableInputEvent(mousedownEvent)) {
- // If it's not acceptable mousedown event (including when mousedown event
- // is fired outside of the active editing host), we need to commit
- // composition because it will be change the selection to the clicked
- // point. Then, we won't be able to commit the composition.
- return EditorEventListener::MouseDown(aMouseEvent);
- }
-
- // XXX This method may change selection. So, we need to commit composition
- // here, first.
-
- // Detect only "context menu" click
- // XXX This should be easier to do!
- // But eDOMEvents_contextmenu and eContextMenu is not exposed in any event
- // interface :-(
- int16_t buttonNumber;
- nsresult rv = aMouseEvent->GetButton(&buttonNumber);
- NS_ENSURE_SUCCESS(rv, rv);
-
- bool isContextClick = buttonNumber == 2;
-
- int32_t clickCount;
- rv = aMouseEvent->GetDetail(&clickCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIDOMEventTarget> target;
- rv = aMouseEvent->AsEvent()->GetExplicitOriginalTarget(getter_AddRefs(target));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(target, NS_ERROR_NULL_POINTER);
- nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
-
- if (isContextClick || (buttonNumber == 0 && clickCount == 2)) {
- RefPtr<Selection> selection = htmlEditor->GetSelection();
- NS_ENSURE_TRUE(selection, NS_OK);
-
- // Get location of mouse within target node
- nsCOMPtr<nsIDOMNode> parent;
- rv = aMouseEvent->GetRangeParent(getter_AddRefs(parent));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(parent, NS_ERROR_FAILURE);
-
- int32_t offset = 0;
- rv = aMouseEvent->GetRangeOffset(&offset);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Detect if mouse point is within current selection for context click
- bool nodeIsInSelection = false;
- if (isContextClick && !selection->Collapsed()) {
- int32_t rangeCount;
- rv = selection->GetRangeCount(&rangeCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- for (int32_t i = 0; i < rangeCount; i++) {
- RefPtr<nsRange> range = selection->GetRangeAt(i);
- if (!range) {
- // Don't bail yet, iterate through them all
- continue;
- }
-
- range->IsPointInRange(parent, offset, &nodeIsInSelection);
-
- // Done when we find a range that we are in
- if (nodeIsInSelection) {
- break;
- }
- }
- }
- nsCOMPtr<nsIDOMNode> node = do_QueryInterface(target);
- if (node && !nodeIsInSelection) {
- if (!element) {
- if (isContextClick) {
- // Set the selection to the point under the mouse cursor:
- selection->Collapse(parent, offset);
- } else {
- // Get enclosing link if in text so we can select the link
- nsCOMPtr<nsIDOMElement> linkElement;
- rv = htmlEditor->GetElementOrParentByTagName(
- NS_LITERAL_STRING("href"), node,
- getter_AddRefs(linkElement));
- NS_ENSURE_SUCCESS(rv, rv);
- if (linkElement) {
- element = linkElement;
- }
- }
- }
- // Select entire element clicked on if NOT within an existing selection
- // and not the entire body, or table-related elements
- if (element) {
- nsCOMPtr<nsIDOMNode> selectAllNode =
- htmlEditor->FindUserSelectAllNode(element);
-
- if (selectAllNode) {
- nsCOMPtr<nsIDOMElement> newElement = do_QueryInterface(selectAllNode);
- if (newElement) {
- node = selectAllNode;
- element = newElement;
- }
- }
-
- if (isContextClick && !HTMLEditUtils::IsImage(node)) {
- selection->Collapse(parent, offset);
- } else {
- htmlEditor->SelectElement(element);
- }
- if (DetachedFromEditor()) {
- return NS_OK;
- }
- }
- }
- // HACK !!! Context click places the caret but the context menu consumes
- // the event; so we need to check resizing state ourselves
- htmlEditor->CheckSelectionStateForAnonymousButtons(selection);
-
- // Prevent bubbling if we changed selection or
- // for all context clicks
- if (element || isContextClick) {
- aMouseEvent->AsEvent()->PreventDefault();
- return NS_OK;
- }
- } else if (!isContextClick && buttonNumber == 0 && clickCount == 1) {
- // if the target element is an image, we have to display resizers
- int32_t clientX, clientY;
- aMouseEvent->GetClientX(&clientX);
- aMouseEvent->GetClientY(&clientY);
- htmlEditor->MouseDown(clientX, clientY, element, aMouseEvent->AsEvent());
- }
-
- return EditorEventListener::MouseDown(aMouseEvent);
-}
-
-nsresult
-HTMLEditorEventListener::MouseClick(nsIDOMMouseEvent* aMouseEvent)
-{
- nsCOMPtr<nsIDOMEventTarget> target;
- nsresult rv = aMouseEvent->AsEvent()->GetTarget(getter_AddRefs(target));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(target, NS_ERROR_NULL_POINTER);
- nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
-
- GetHTMLEditor()->DoInlineTableEditingAction(element);
-
- return EditorEventListener::MouseClick(aMouseEvent);
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/HTMLEditorEventListener.h b/editor/libeditor/HTMLEditorEventListener.h
deleted file mode 100644
index b97b675b5..000000000
--- a/editor/libeditor/HTMLEditorEventListener.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef HTMLEditorEventListener_h
-#define HTMLEditorEventListener_h
-
-#include "EditorEventListener.h"
-#include "nscore.h"
-
-namespace mozilla {
-
-class EditorBase;
-class HTMLEditor;
-
-class HTMLEditorEventListener final : public EditorEventListener
-{
-public:
- HTMLEditorEventListener()
- {
- }
-
- virtual ~HTMLEditorEventListener()
- {
- }
-
-#ifdef DEBUG
- // WARNING: You must be use HTMLEditor or its sub class for this class.
- virtual nsresult Connect(EditorBase* aEditorBase) override;
-#endif
-
-protected:
- virtual nsresult MouseDown(nsIDOMMouseEvent* aMouseEvent) override;
- virtual nsresult MouseUp(nsIDOMMouseEvent* aMouseEvent) override;
- virtual nsresult MouseClick(nsIDOMMouseEvent* aMouseEvent) override;
-
- inline HTMLEditor* GetHTMLEditor();
-};
-
-} // namespace mozilla
-
-#endif // #ifndef HTMLEditorEventListener_h
diff --git a/editor/libeditor/HTMLEditorObjectResizer.cpp b/editor/libeditor/HTMLEditorObjectResizer.cpp
deleted file mode 100644
index 8ed5b6e4d..000000000
--- a/editor/libeditor/HTMLEditorObjectResizer.cpp
+++ /dev/null
@@ -1,1054 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/HTMLEditor.h"
-#include "HTMLEditorObjectResizerUtils.h"
-
-#include "HTMLEditUtils.h"
-#include "mozilla/DebugOnly.h"
-#include "mozilla/EditorUtils.h"
-#include "mozilla/LookAndFeel.h"
-#include "mozilla/MathAlgorithms.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/mozalloc.h"
-#include "nsAString.h"
-#include "nsAlgorithm.h"
-#include "nsCOMPtr.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsGkAtoms.h"
-#include "nsIAtom.h"
-#include "nsIContent.h"
-#include "nsID.h"
-#include "nsIDOMDocument.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMEvent.h"
-#include "nsIDOMEventTarget.h"
-#include "nsIDOMMouseEvent.h"
-#include "nsIDOMNode.h"
-#include "nsIDOMText.h"
-#include "nsIDocument.h"
-#include "nsIEditor.h"
-#include "nsIHTMLObjectResizeListener.h"
-#include "nsIHTMLObjectResizer.h"
-#include "nsIPresShell.h"
-#include "nsISupportsUtils.h"
-#include "nsPIDOMWindow.h"
-#include "nsReadableUtils.h"
-#include "nsString.h"
-#include "nsStringFwd.h"
-#include "nsSubstringTuple.h"
-#include "nscore.h"
-#include <algorithm>
-
-class nsISelection;
-
-namespace mozilla {
-
-using namespace dom;
-
-/******************************************************************************
- * mozilla::DocumentResizeEventListener
- ******************************************************************************/
-
-NS_IMPL_ISUPPORTS(DocumentResizeEventListener, nsIDOMEventListener)
-
-DocumentResizeEventListener::DocumentResizeEventListener(nsIHTMLEditor* aEditor)
-{
- mEditor = do_GetWeakReference(aEditor);
-}
-
-NS_IMETHODIMP
-DocumentResizeEventListener::HandleEvent(nsIDOMEvent* aMouseEvent)
-{
- nsCOMPtr<nsIHTMLObjectResizer> objectResizer = do_QueryReferent(mEditor);
- if (objectResizer) {
- return objectResizer->RefreshResizers();
- }
- return NS_OK;
-}
-
-/******************************************************************************
- * mozilla::ResizerSelectionListener
- ******************************************************************************/
-
-NS_IMPL_ISUPPORTS(ResizerSelectionListener, nsISelectionListener)
-
-ResizerSelectionListener::ResizerSelectionListener(nsIHTMLEditor* aEditor)
-{
- mEditor = do_GetWeakReference(aEditor);
-}
-
-NS_IMETHODIMP
-ResizerSelectionListener::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
- nsISelection* aSelection,
- int16_t aReason)
-{
- if ((aReason & (nsISelectionListener::MOUSEDOWN_REASON |
- nsISelectionListener::KEYPRESS_REASON |
- nsISelectionListener::SELECTALL_REASON)) && aSelection) {
- // the selection changed and we need to check if we have to
- // hide and/or redisplay resizing handles
- nsCOMPtr<nsIHTMLEditor> editor = do_QueryReferent(mEditor);
- if (editor) {
- editor->CheckSelectionStateForAnonymousButtons(aSelection);
- }
- }
-
- return NS_OK;
-}
-
-/******************************************************************************
- * mozilla::ResizerMouseMotionListener
- ******************************************************************************/
-
-NS_IMPL_ISUPPORTS(ResizerMouseMotionListener, nsIDOMEventListener)
-
-ResizerMouseMotionListener::ResizerMouseMotionListener(nsIHTMLEditor* aEditor)
-{
- mEditor = do_GetWeakReference(aEditor);
-}
-
-NS_IMETHODIMP
-ResizerMouseMotionListener::HandleEvent(nsIDOMEvent* aMouseEvent)
-{
- nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
- if (!mouseEvent) {
- //non-ui event passed in. bad things.
- return NS_OK;
- }
-
- // Don't do anything special if not an HTML object resizer editor
- nsCOMPtr<nsIHTMLObjectResizer> objectResizer = do_QueryReferent(mEditor);
- if (objectResizer) {
- // check if we have to redisplay a resizing shadow
- objectResizer->MouseMove(aMouseEvent);
- }
-
- return NS_OK;
-}
-
-/******************************************************************************
- * mozilla::HTMLEditor
- ******************************************************************************/
-
-already_AddRefed<Element>
-HTMLEditor::CreateResizer(int16_t aLocation,
- nsIDOMNode* aParentNode)
-{
- nsCOMPtr<nsIDOMElement> retDOM;
- nsresult rv = CreateAnonymousElement(NS_LITERAL_STRING("span"),
- aParentNode,
- NS_LITERAL_STRING("mozResizer"),
- false,
- getter_AddRefs(retDOM));
-
- NS_ENSURE_SUCCESS(rv, nullptr);
- NS_ENSURE_TRUE(retDOM, nullptr);
-
- // add the mouse listener so we can detect a click on a resizer
- nsCOMPtr<nsIDOMEventTarget> evtTarget = do_QueryInterface(retDOM);
- evtTarget->AddEventListener(NS_LITERAL_STRING("mousedown"), mEventListener,
- true);
-
- nsAutoString locationStr;
- switch (aLocation) {
- case nsIHTMLObjectResizer::eTopLeft:
- locationStr = kTopLeft;
- break;
- case nsIHTMLObjectResizer::eTop:
- locationStr = kTop;
- break;
- case nsIHTMLObjectResizer::eTopRight:
- locationStr = kTopRight;
- break;
-
- case nsIHTMLObjectResizer::eLeft:
- locationStr = kLeft;
- break;
- case nsIHTMLObjectResizer::eRight:
- locationStr = kRight;
- break;
-
- case nsIHTMLObjectResizer::eBottomLeft:
- locationStr = kBottomLeft;
- break;
- case nsIHTMLObjectResizer::eBottom:
- locationStr = kBottom;
- break;
- case nsIHTMLObjectResizer::eBottomRight:
- locationStr = kBottomRight;
- break;
- }
-
- nsCOMPtr<Element> ret = do_QueryInterface(retDOM);
- rv = ret->SetAttr(kNameSpaceID_None, nsGkAtoms::anonlocation, locationStr,
- true);
- NS_ENSURE_SUCCESS(rv, nullptr);
- return ret.forget();
-}
-
-already_AddRefed<Element>
-HTMLEditor::CreateShadow(nsIDOMNode* aParentNode,
- nsIDOMElement* aOriginalObject)
-{
- // let's create an image through the element factory
- nsAutoString name;
- if (HTMLEditUtils::IsImage(aOriginalObject)) {
- name.AssignLiteral("img");
- } else {
- name.AssignLiteral("span");
- }
- nsCOMPtr<nsIDOMElement> retDOM;
- CreateAnonymousElement(name, aParentNode,
- NS_LITERAL_STRING("mozResizingShadow"), true,
- getter_AddRefs(retDOM));
-
- NS_ENSURE_TRUE(retDOM, nullptr);
-
- nsCOMPtr<Element> ret = do_QueryInterface(retDOM);
- return ret.forget();
-}
-
-already_AddRefed<Element>
-HTMLEditor::CreateResizingInfo(nsIDOMNode* aParentNode)
-{
- // let's create an info box through the element factory
- nsCOMPtr<nsIDOMElement> retDOM;
- CreateAnonymousElement(NS_LITERAL_STRING("span"), aParentNode,
- NS_LITERAL_STRING("mozResizingInfo"), true,
- getter_AddRefs(retDOM));
-
- nsCOMPtr<Element> ret = do_QueryInterface(retDOM);
- return ret.forget();
-}
-
-nsresult
-HTMLEditor::SetAllResizersPosition()
-{
- NS_ENSURE_TRUE(mTopLeftHandle, NS_ERROR_FAILURE);
-
- int32_t x = mResizedObjectX;
- int32_t y = mResizedObjectY;
- int32_t w = mResizedObjectWidth;
- int32_t h = mResizedObjectHeight;
-
- // now let's place all the resizers around the image
-
- // get the size of resizers
- nsAutoString value;
- float resizerWidth, resizerHeight;
- nsCOMPtr<nsIAtom> dummyUnit;
- mCSSEditUtils->GetComputedProperty(*mTopLeftHandle, *nsGkAtoms::width,
- value);
- mCSSEditUtils->ParseLength(value, &resizerWidth, getter_AddRefs(dummyUnit));
- mCSSEditUtils->GetComputedProperty(*mTopLeftHandle, *nsGkAtoms::height,
- value);
- mCSSEditUtils->ParseLength(value, &resizerHeight, getter_AddRefs(dummyUnit));
-
- int32_t rw = (int32_t)((resizerWidth + 1) / 2);
- int32_t rh = (int32_t)((resizerHeight+ 1) / 2);
-
- SetAnonymousElementPosition(x-rw, y-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mTopLeftHandle)));
- SetAnonymousElementPosition(x+w/2-rw, y-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mTopHandle)));
- SetAnonymousElementPosition(x+w-rw-1, y-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mTopRightHandle)));
-
- SetAnonymousElementPosition(x-rw, y+h/2-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mLeftHandle)));
- SetAnonymousElementPosition(x+w-rw-1, y+h/2-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mRightHandle)));
-
- SetAnonymousElementPosition(x-rw, y+h-rh-1, static_cast<nsIDOMElement*>(GetAsDOMNode(mBottomLeftHandle)));
- SetAnonymousElementPosition(x+w/2-rw, y+h-rh-1, static_cast<nsIDOMElement*>(GetAsDOMNode(mBottomHandle)));
- SetAnonymousElementPosition(x+w-rw-1, y+h-rh-1, static_cast<nsIDOMElement*>(GetAsDOMNode(mBottomRightHandle)));
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::RefreshResizers()
-{
- // nothing to do if resizers are not displayed...
- NS_ENSURE_TRUE(mResizedObject, NS_OK);
-
- nsresult rv =
- GetPositionAndDimensions(
- static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)),
- mResizedObjectX,
- mResizedObjectY,
- mResizedObjectWidth,
- mResizedObjectHeight,
- mResizedObjectBorderLeft,
- mResizedObjectBorderTop,
- mResizedObjectMarginLeft,
- mResizedObjectMarginTop);
-
- NS_ENSURE_SUCCESS(rv, rv);
- rv = SetAllResizersPosition();
- NS_ENSURE_SUCCESS(rv, rv);
- return SetShadowPosition(mResizingShadow, mResizedObject,
- mResizedObjectX, mResizedObjectY);
-}
-
-NS_IMETHODIMP
-HTMLEditor::ShowResizers(nsIDOMElement* aResizedElement)
-{
- nsresult rv = ShowResizersInner(aResizedElement);
- if (NS_FAILED(rv)) {
- HideResizers();
- }
- return rv;
-}
-
-nsresult
-HTMLEditor::ShowResizersInner(nsIDOMElement* aResizedElement)
-{
- NS_ENSURE_ARG_POINTER(aResizedElement);
-
- nsCOMPtr<nsIDOMNode> parentNode;
- nsresult rv = aResizedElement->GetParentNode(getter_AddRefs(parentNode));
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (mResizedObject) {
- NS_ERROR("call HideResizers first");
- return NS_ERROR_UNEXPECTED;
- }
-
- nsCOMPtr<nsINode> resizedNode = do_QueryInterface(aResizedElement);
- if (NS_WARN_IF(!IsDescendantOfEditorRoot(resizedNode))) {
- return NS_ERROR_UNEXPECTED;
- }
-
- mResizedObject = do_QueryInterface(aResizedElement);
- NS_ENSURE_STATE(mResizedObject);
-
- // The resizers and the shadow will be anonymous siblings of the element.
- mTopLeftHandle = CreateResizer(nsIHTMLObjectResizer::eTopLeft, parentNode);
- NS_ENSURE_TRUE(mTopLeftHandle, NS_ERROR_FAILURE);
- mTopHandle = CreateResizer(nsIHTMLObjectResizer::eTop, parentNode);
- NS_ENSURE_TRUE(mTopHandle, NS_ERROR_FAILURE);
- mTopRightHandle = CreateResizer(nsIHTMLObjectResizer::eTopRight, parentNode);
- NS_ENSURE_TRUE(mTopRightHandle, NS_ERROR_FAILURE);
-
- mLeftHandle = CreateResizer(nsIHTMLObjectResizer::eLeft, parentNode);
- NS_ENSURE_TRUE(mLeftHandle, NS_ERROR_FAILURE);
- mRightHandle = CreateResizer(nsIHTMLObjectResizer::eRight, parentNode);
- NS_ENSURE_TRUE(mRightHandle, NS_ERROR_FAILURE);
-
- mBottomLeftHandle = CreateResizer(nsIHTMLObjectResizer::eBottomLeft, parentNode);
- NS_ENSURE_TRUE(mBottomLeftHandle, NS_ERROR_FAILURE);
- mBottomHandle = CreateResizer(nsIHTMLObjectResizer::eBottom, parentNode);
- NS_ENSURE_TRUE(mBottomHandle, NS_ERROR_FAILURE);
- mBottomRightHandle = CreateResizer(nsIHTMLObjectResizer::eBottomRight, parentNode);
- NS_ENSURE_TRUE(mBottomRightHandle, NS_ERROR_FAILURE);
-
- rv = GetPositionAndDimensions(aResizedElement,
- mResizedObjectX,
- mResizedObjectY,
- mResizedObjectWidth,
- mResizedObjectHeight,
- mResizedObjectBorderLeft,
- mResizedObjectBorderTop,
- mResizedObjectMarginLeft,
- mResizedObjectMarginTop);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // and let's set their absolute positions in the document
- rv = SetAllResizersPosition();
- NS_ENSURE_SUCCESS(rv, rv);
-
- // now, let's create the resizing shadow
- mResizingShadow = CreateShadow(parentNode, aResizedElement);
- NS_ENSURE_TRUE(mResizingShadow, NS_ERROR_FAILURE);
- // and set its position
- rv = SetShadowPosition(mResizingShadow, mResizedObject,
- mResizedObjectX, mResizedObjectY);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // and then the resizing info tooltip
- mResizingInfo = CreateResizingInfo(parentNode);
- NS_ENSURE_TRUE(mResizingInfo, NS_ERROR_FAILURE);
-
- // and listen to the "resize" event on the window first, get the
- // window from the document...
- nsCOMPtr<nsIDocument> doc = GetDocument();
- NS_ENSURE_TRUE(doc, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(doc->GetWindow());
- if (!target) {
- return NS_ERROR_NULL_POINTER;
- }
-
- mResizeEventListenerP = new DocumentResizeEventListener(this);
- if (!mResizeEventListenerP) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- rv = target->AddEventListener(NS_LITERAL_STRING("resize"),
- mResizeEventListenerP, false);
- // XXX Even when it failed to add event listener, should we need to set
- // _moz_resizing attribute?
- aResizedElement->SetAttribute(NS_LITERAL_STRING("_moz_resizing"), NS_LITERAL_STRING("true"));
- return rv;
-}
-
-NS_IMETHODIMP
-HTMLEditor::HideResizers()
-{
- NS_ENSURE_TRUE(mResizedObject, NS_OK);
-
- // get the presshell's document observer interface.
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
- // We allow the pres shell to be null; when it is, we presume there
- // are no document observers to notify, but we still want to
- // UnbindFromTree.
-
- nsCOMPtr<nsIContent> parentContent;
-
- if (mTopLeftHandle) {
- parentContent = mTopLeftHandle->GetParent();
- }
-
- NS_NAMED_LITERAL_STRING(mousedown, "mousedown");
-
- RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
- mTopLeftHandle, parentContent, ps);
- mTopLeftHandle = nullptr;
-
- RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
- mTopHandle, parentContent, ps);
- mTopHandle = nullptr;
-
- RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
- mTopRightHandle, parentContent, ps);
- mTopRightHandle = nullptr;
-
- RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
- mLeftHandle, parentContent, ps);
- mLeftHandle = nullptr;
-
- RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
- mRightHandle, parentContent, ps);
- mRightHandle = nullptr;
-
- RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
- mBottomLeftHandle, parentContent, ps);
- mBottomLeftHandle = nullptr;
-
- RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
- mBottomHandle, parentContent, ps);
- mBottomHandle = nullptr;
-
- RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
- mBottomRightHandle, parentContent, ps);
- mBottomRightHandle = nullptr;
-
- RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
- mResizingShadow, parentContent, ps);
- mResizingShadow = nullptr;
-
- RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
- mResizingInfo, parentContent, ps);
- mResizingInfo = nullptr;
-
- if (mActivatedHandle) {
- mActivatedHandle->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_moz_activated,
- true);
- mActivatedHandle = nullptr;
- }
-
- // don't forget to remove the listeners !
-
- nsCOMPtr<nsIDOMEventTarget> target = GetDOMEventTarget();
-
- if (target && mMouseMotionListenerP) {
- DebugOnly<nsresult> rv =
- target->RemoveEventListener(NS_LITERAL_STRING("mousemove"),
- mMouseMotionListenerP, true);
- NS_ASSERTION(NS_SUCCEEDED(rv), "failed to remove mouse motion listener");
- }
- mMouseMotionListenerP = nullptr;
-
- nsCOMPtr<nsIDocument> doc = GetDocument();
- if (!doc) {
- return NS_ERROR_NULL_POINTER;
- }
- target = do_QueryInterface(doc->GetWindow());
- if (!target) {
- return NS_ERROR_NULL_POINTER;
- }
-
- if (mResizeEventListenerP) {
- DebugOnly<nsresult> rv =
- target->RemoveEventListener(NS_LITERAL_STRING("resize"),
- mResizeEventListenerP, false);
- NS_ASSERTION(NS_SUCCEEDED(rv), "failed to remove resize event listener");
- }
- mResizeEventListenerP = nullptr;
-
- mResizedObject->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_moz_resizing, true);
- mResizedObject = nullptr;
-
- return NS_OK;
-}
-
-void
-HTMLEditor::HideShadowAndInfo()
-{
- if (mResizingShadow) {
- mResizingShadow->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
- NS_LITERAL_STRING("hidden"), true);
- }
- if (mResizingInfo) {
- mResizingInfo->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
- NS_LITERAL_STRING("hidden"), true);
- }
-}
-
-nsresult
-HTMLEditor::StartResizing(nsIDOMElement* aHandle)
-{
- // First notify the listeners if any
- for (auto& listener : mObjectResizeEventListeners) {
- listener->OnStartResizing(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)));
- }
-
- mIsResizing = true;
- mActivatedHandle = do_QueryInterface(aHandle);
- NS_ENSURE_STATE(mActivatedHandle || !aHandle);
- mActivatedHandle->SetAttr(kNameSpaceID_None, nsGkAtoms::_moz_activated,
- NS_LITERAL_STRING("true"), true);
-
- // do we want to preserve ratio or not?
- bool preserveRatio = HTMLEditUtils::IsImage(mResizedObject) &&
- Preferences::GetBool("editor.resizing.preserve_ratio", true);
-
- // the way we change the position/size of the shadow depends on
- // the handle
- nsAutoString locationStr;
- aHandle->GetAttribute(NS_LITERAL_STRING("anonlocation"), locationStr);
- if (locationStr.Equals(kTopLeft)) {
- SetResizeIncrements(1, 1, -1, -1, preserveRatio);
- } else if (locationStr.Equals(kTop)) {
- SetResizeIncrements(0, 1, 0, -1, false);
- } else if (locationStr.Equals(kTopRight)) {
- SetResizeIncrements(0, 1, 1, -1, preserveRatio);
- } else if (locationStr.Equals(kLeft)) {
- SetResizeIncrements(1, 0, -1, 0, false);
- } else if (locationStr.Equals(kRight)) {
- SetResizeIncrements(0, 0, 1, 0, false);
- } else if (locationStr.Equals(kBottomLeft)) {
- SetResizeIncrements(1, 0, -1, 1, preserveRatio);
- } else if (locationStr.Equals(kBottom)) {
- SetResizeIncrements(0, 0, 0, 1, false);
- } else if (locationStr.Equals(kBottomRight)) {
- SetResizeIncrements(0, 0, 1, 1, preserveRatio);
- }
-
- // make the shadow appear
- mResizingShadow->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_class, true);
-
- // position it
- mCSSEditUtils->SetCSSPropertyPixels(*mResizingShadow, *nsGkAtoms::width,
- mResizedObjectWidth);
- mCSSEditUtils->SetCSSPropertyPixels(*mResizingShadow, *nsGkAtoms::height,
- mResizedObjectHeight);
-
- // add a mouse move listener to the editor
- nsresult result = NS_OK;
- if (!mMouseMotionListenerP) {
- mMouseMotionListenerP = new ResizerMouseMotionListener(this);
- if (!mMouseMotionListenerP) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- nsCOMPtr<nsIDOMEventTarget> target = GetDOMEventTarget();
- NS_ENSURE_TRUE(target, NS_ERROR_FAILURE);
-
- result = target->AddEventListener(NS_LITERAL_STRING("mousemove"),
- mMouseMotionListenerP, true);
- NS_ASSERTION(NS_SUCCEEDED(result),
- "failed to register mouse motion listener");
- }
- return result;
-}
-
-NS_IMETHODIMP
-HTMLEditor::MouseDown(int32_t aClientX,
- int32_t aClientY,
- nsIDOMElement* aTarget,
- nsIDOMEvent* aEvent)
-{
- bool anonElement = false;
- if (aTarget && NS_SUCCEEDED(aTarget->HasAttribute(NS_LITERAL_STRING("_moz_anonclass"), &anonElement)))
- // we caught a click on an anonymous element
- if (anonElement) {
- nsAutoString anonclass;
- nsresult rv =
- aTarget->GetAttribute(NS_LITERAL_STRING("_moz_anonclass"), anonclass);
- NS_ENSURE_SUCCESS(rv, rv);
- if (anonclass.EqualsLiteral("mozResizer")) {
- // and that element is a resizer, let's start resizing!
- aEvent->PreventDefault();
-
- mOriginalX = aClientX;
- mOriginalY = aClientY;
- return StartResizing(aTarget);
- }
- if (anonclass.EqualsLiteral("mozGrabber")) {
- // and that element is a grabber, let's start moving the element!
- mOriginalX = aClientX;
- mOriginalY = aClientY;
- return GrabberClicked();
- }
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::MouseUp(int32_t aClientX,
- int32_t aClientY,
- nsIDOMElement* aTarget)
-{
- if (mIsResizing) {
- // we are resizing and release the mouse button, so let's
- // end the resizing process
- mIsResizing = false;
- HideShadowAndInfo();
- SetFinalSize(aClientX, aClientY);
- } else if (mIsMoving || mGrabberClicked) {
- if (mIsMoving) {
- mPositioningShadow->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
- NS_LITERAL_STRING("hidden"), true);
- SetFinalPosition(aClientX, aClientY);
- }
- if (mGrabberClicked) {
- EndMoving();
- }
- }
- return NS_OK;
-}
-
-void
-HTMLEditor::SetResizeIncrements(int32_t aX,
- int32_t aY,
- int32_t aW,
- int32_t aH,
- bool aPreserveRatio)
-{
- mXIncrementFactor = aX;
- mYIncrementFactor = aY;
- mWidthIncrementFactor = aW;
- mHeightIncrementFactor = aH;
- mPreserveRatio = aPreserveRatio;
-}
-
-nsresult
-HTMLEditor::SetResizingInfoPosition(int32_t aX,
- int32_t aY,
- int32_t aW,
- int32_t aH)
-{
- nsCOMPtr<nsIDOMDocument> domdoc = GetDOMDocument();
-
- // Determine the position of the resizing info box based upon the new
- // position and size of the element (aX, aY, aW, aH), and which
- // resizer is the "activated handle". For example, place the resizing
- // info box at the bottom-right corner of the new element, if the element
- // is being resized by the bottom-right resizer.
- int32_t infoXPosition;
- int32_t infoYPosition;
-
- if (mActivatedHandle == mTopLeftHandle ||
- mActivatedHandle == mLeftHandle ||
- mActivatedHandle == mBottomLeftHandle) {
- infoXPosition = aX;
- } else if (mActivatedHandle == mTopHandle ||
- mActivatedHandle == mBottomHandle) {
- infoXPosition = aX + (aW / 2);
- } else {
- // should only occur when mActivatedHandle is one of the 3 right-side
- // handles, but this is a reasonable default if it isn't any of them (?)
- infoXPosition = aX + aW;
- }
-
- if (mActivatedHandle == mTopLeftHandle ||
- mActivatedHandle == mTopHandle ||
- mActivatedHandle == mTopRightHandle) {
- infoYPosition = aY;
- } else if (mActivatedHandle == mLeftHandle ||
- mActivatedHandle == mRightHandle) {
- infoYPosition = aY + (aH / 2);
- } else {
- // should only occur when mActivatedHandle is one of the 3 bottom-side
- // handles, but this is a reasonable default if it isn't any of them (?)
- infoYPosition = aY + aH;
- }
-
- // Offset info box by 20 so it's not directly under the mouse cursor.
- const int mouseCursorOffset = 20;
- mCSSEditUtils->SetCSSPropertyPixels(*mResizingInfo, *nsGkAtoms::left,
- infoXPosition + mouseCursorOffset);
- mCSSEditUtils->SetCSSPropertyPixels(*mResizingInfo, *nsGkAtoms::top,
- infoYPosition + mouseCursorOffset);
-
- nsCOMPtr<nsIContent> textInfo = mResizingInfo->GetFirstChild();
- ErrorResult erv;
- if (textInfo) {
- mResizingInfo->RemoveChild(*textInfo, erv);
- NS_ENSURE_TRUE(!erv.Failed(), erv.StealNSResult());
- textInfo = nullptr;
- }
-
- nsAutoString widthStr, heightStr, diffWidthStr, diffHeightStr;
- widthStr.AppendInt(aW);
- heightStr.AppendInt(aH);
- int32_t diffWidth = aW - mResizedObjectWidth;
- int32_t diffHeight = aH - mResizedObjectHeight;
- if (diffWidth > 0) {
- diffWidthStr.Assign('+');
- }
- if (diffHeight > 0) {
- diffHeightStr.Assign('+');
- }
- diffWidthStr.AppendInt(diffWidth);
- diffHeightStr.AppendInt(diffHeight);
-
- nsAutoString info(widthStr + NS_LITERAL_STRING(" x ") + heightStr +
- NS_LITERAL_STRING(" (") + diffWidthStr +
- NS_LITERAL_STRING(", ") + diffHeightStr +
- NS_LITERAL_STRING(")"));
-
- nsCOMPtr<nsIDOMText> nodeAsText;
- nsresult rv = domdoc->CreateTextNode(info, getter_AddRefs(nodeAsText));
- NS_ENSURE_SUCCESS(rv, rv);
- textInfo = do_QueryInterface(nodeAsText);
- mResizingInfo->AppendChild(*textInfo, erv);
- NS_ENSURE_TRUE(!erv.Failed(), erv.StealNSResult());
-
- return mResizingInfo->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_class, true);
-}
-
-nsresult
-HTMLEditor::SetShadowPosition(Element* aShadow,
- Element* aOriginalObject,
- int32_t aOriginalObjectX,
- int32_t aOriginalObjectY)
-{
- SetAnonymousElementPosition(aOriginalObjectX, aOriginalObjectY, static_cast<nsIDOMElement*>(GetAsDOMNode(aShadow)));
-
- if (HTMLEditUtils::IsImage(aOriginalObject)) {
- nsAutoString imageSource;
- aOriginalObject->GetAttr(kNameSpaceID_None, nsGkAtoms::src, imageSource);
- nsresult rv = aShadow->SetAttr(kNameSpaceID_None, nsGkAtoms::src,
- imageSource, true);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
-}
-
-int32_t
-HTMLEditor::GetNewResizingIncrement(int32_t aX,
- int32_t aY,
- int32_t aID)
-{
- int32_t result = 0;
- if (!mPreserveRatio) {
- switch (aID) {
- case kX:
- case kWidth:
- result = aX - mOriginalX;
- break;
- case kY:
- case kHeight:
- result = aY - mOriginalY;
- break;
- }
- return result;
- }
-
- int32_t xi = (aX - mOriginalX) * mWidthIncrementFactor;
- int32_t yi = (aY - mOriginalY) * mHeightIncrementFactor;
- float objectSizeRatio =
- ((float)mResizedObjectWidth) / ((float)mResizedObjectHeight);
- result = (xi > yi) ? xi : yi;
- switch (aID) {
- case kX:
- case kWidth:
- if (result == yi)
- result = (int32_t) (((float) result) * objectSizeRatio);
- result = (int32_t) (((float) result) * mWidthIncrementFactor);
- break;
- case kY:
- case kHeight:
- if (result == xi)
- result = (int32_t) (((float) result) / objectSizeRatio);
- result = (int32_t) (((float) result) * mHeightIncrementFactor);
- break;
- }
- return result;
-}
-
-int32_t
-HTMLEditor::GetNewResizingX(int32_t aX,
- int32_t aY)
-{
- int32_t resized = mResizedObjectX +
- GetNewResizingIncrement(aX, aY, kX) * mXIncrementFactor;
- int32_t max = mResizedObjectX + mResizedObjectWidth;
- return std::min(resized, max);
-}
-
-int32_t
-HTMLEditor::GetNewResizingY(int32_t aX,
- int32_t aY)
-{
- int32_t resized = mResizedObjectY +
- GetNewResizingIncrement(aX, aY, kY) * mYIncrementFactor;
- int32_t max = mResizedObjectY + mResizedObjectHeight;
- return std::min(resized, max);
-}
-
-int32_t
-HTMLEditor::GetNewResizingWidth(int32_t aX,
- int32_t aY)
-{
- int32_t resized = mResizedObjectWidth +
- GetNewResizingIncrement(aX, aY, kWidth) *
- mWidthIncrementFactor;
- return std::max(resized, 1);
-}
-
-int32_t
-HTMLEditor::GetNewResizingHeight(int32_t aX,
- int32_t aY)
-{
- int32_t resized = mResizedObjectHeight +
- GetNewResizingIncrement(aX, aY, kHeight) *
- mHeightIncrementFactor;
- return std::max(resized, 1);
-}
-
-NS_IMETHODIMP
-HTMLEditor::MouseMove(nsIDOMEvent* aMouseEvent)
-{
- NS_NAMED_LITERAL_STRING(leftStr, "left");
- NS_NAMED_LITERAL_STRING(topStr, "top");
-
- if (mIsResizing) {
- // we are resizing and the mouse pointer's position has changed
- // we have to resdisplay the shadow
- nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
- int32_t clientX, clientY;
- mouseEvent->GetClientX(&clientX);
- mouseEvent->GetClientY(&clientY);
-
- int32_t newX = GetNewResizingX(clientX, clientY);
- int32_t newY = GetNewResizingY(clientX, clientY);
- int32_t newWidth = GetNewResizingWidth(clientX, clientY);
- int32_t newHeight = GetNewResizingHeight(clientX, clientY);
-
- mCSSEditUtils->SetCSSPropertyPixels(*mResizingShadow, *nsGkAtoms::left,
- newX);
- mCSSEditUtils->SetCSSPropertyPixels(*mResizingShadow, *nsGkAtoms::top,
- newY);
- mCSSEditUtils->SetCSSPropertyPixels(*mResizingShadow, *nsGkAtoms::width,
- newWidth);
- mCSSEditUtils->SetCSSPropertyPixels(*mResizingShadow, *nsGkAtoms::height,
- newHeight);
-
- return SetResizingInfoPosition(newX, newY, newWidth, newHeight);
- }
-
- if (mGrabberClicked) {
- nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
- int32_t clientX, clientY;
- mouseEvent->GetClientX(&clientX);
- mouseEvent->GetClientY(&clientY);
-
- int32_t xThreshold =
- LookAndFeel::GetInt(LookAndFeel::eIntID_DragThresholdX, 1);
- int32_t yThreshold =
- LookAndFeel::GetInt(LookAndFeel::eIntID_DragThresholdY, 1);
-
- if (DeprecatedAbs(clientX - mOriginalX) * 2 >= xThreshold ||
- DeprecatedAbs(clientY - mOriginalY) * 2 >= yThreshold) {
- mGrabberClicked = false;
- StartMoving(nullptr);
- }
- }
- if (mIsMoving) {
- nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aMouseEvent) );
- int32_t clientX, clientY;
- mouseEvent->GetClientX(&clientX);
- mouseEvent->GetClientY(&clientY);
-
- int32_t newX = mPositionedObjectX + clientX - mOriginalX;
- int32_t newY = mPositionedObjectY + clientY - mOriginalY;
-
- SnapToGrid(newX, newY);
-
- mCSSEditUtils->SetCSSPropertyPixels(*mPositioningShadow, *nsGkAtoms::left,
- newX);
- mCSSEditUtils->SetCSSPropertyPixels(*mPositioningShadow, *nsGkAtoms::top,
- newY);
- }
- return NS_OK;
-}
-
-void
-HTMLEditor::SetFinalSize(int32_t aX,
- int32_t aY)
-{
- if (!mResizedObject) {
- // paranoia
- return;
- }
-
- if (mActivatedHandle) {
- mActivatedHandle->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_moz_activated, true);
- mActivatedHandle = nullptr;
- }
-
- // we have now to set the new width and height of the resized object
- // we don't set the x and y position because we don't control that in
- // a normal HTML layout
- int32_t left = GetNewResizingX(aX, aY);
- int32_t top = GetNewResizingY(aX, aY);
- int32_t width = GetNewResizingWidth(aX, aY);
- int32_t height = GetNewResizingHeight(aX, aY);
- bool setWidth = !mResizedObjectIsAbsolutelyPositioned || (width != mResizedObjectWidth);
- bool setHeight = !mResizedObjectIsAbsolutelyPositioned || (height != mResizedObjectHeight);
-
- int32_t x, y;
- x = left - ((mResizedObjectIsAbsolutelyPositioned) ? mResizedObjectBorderLeft+mResizedObjectMarginLeft : 0);
- y = top - ((mResizedObjectIsAbsolutelyPositioned) ? mResizedObjectBorderTop+mResizedObjectMarginTop : 0);
-
- // we want one transaction only from a user's point of view
- AutoEditBatch batchIt(this);
-
- if (mResizedObjectIsAbsolutelyPositioned) {
- if (setHeight) {
- mCSSEditUtils->SetCSSPropertyPixels(*mResizedObject, *nsGkAtoms::top, y);
- }
- if (setWidth) {
- mCSSEditUtils->SetCSSPropertyPixels(*mResizedObject, *nsGkAtoms::left, x);
- }
- }
- if (IsCSSEnabled() || mResizedObjectIsAbsolutelyPositioned) {
- if (setWidth && mResizedObject->HasAttr(kNameSpaceID_None, nsGkAtoms::width)) {
- RemoveAttribute(mResizedObject, nsGkAtoms::width);
- }
-
- if (setHeight && mResizedObject->HasAttr(kNameSpaceID_None,
- nsGkAtoms::height)) {
- RemoveAttribute(mResizedObject, nsGkAtoms::height);
- }
-
- if (setWidth) {
- mCSSEditUtils->SetCSSPropertyPixels(*mResizedObject, *nsGkAtoms::width,
- width);
- }
- if (setHeight) {
- mCSSEditUtils->SetCSSPropertyPixels(*mResizedObject, *nsGkAtoms::height,
- height);
- }
- } else {
- // we use HTML size and remove all equivalent CSS properties
-
- // we set the CSS width and height to remove it later,
- // triggering an immediate reflow; otherwise, we have problems
- // with asynchronous reflow
- if (setWidth) {
- mCSSEditUtils->SetCSSPropertyPixels(*mResizedObject, *nsGkAtoms::width,
- width);
- }
- if (setHeight) {
- mCSSEditUtils->SetCSSPropertyPixels(*mResizedObject, *nsGkAtoms::height,
- height);
- }
- if (setWidth) {
- nsAutoString w;
- w.AppendInt(width);
- SetAttribute(mResizedObject, nsGkAtoms::width, w);
- }
- if (setHeight) {
- nsAutoString h;
- h.AppendInt(height);
- SetAttribute(mResizedObject, nsGkAtoms::height, h);
- }
-
- if (setWidth) {
- mCSSEditUtils->RemoveCSSProperty(*mResizedObject, *nsGkAtoms::width,
- EmptyString());
- }
- if (setHeight) {
- mCSSEditUtils->RemoveCSSProperty(*mResizedObject, *nsGkAtoms::height,
- EmptyString());
- }
- }
- // finally notify the listeners if any
- for (auto& listener : mObjectResizeEventListeners) {
- listener->OnEndResizing(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)),
- mResizedObjectWidth, mResizedObjectHeight, width,
- height);
- }
-
- // keep track of that size
- mResizedObjectWidth = width;
- mResizedObjectHeight = height;
-
- RefreshResizers();
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetResizedObject(nsIDOMElement** aResizedObject)
-{
- nsCOMPtr<nsIDOMElement> ret = static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject));
- ret.forget(aResizedObject);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetObjectResizingEnabled(bool* aIsObjectResizingEnabled)
-{
- *aIsObjectResizingEnabled = mIsObjectResizingEnabled;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::SetObjectResizingEnabled(bool aObjectResizingEnabled)
-{
- mIsObjectResizingEnabled = aObjectResizingEnabled;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::AddObjectResizeEventListener(nsIHTMLObjectResizeListener* aListener)
-{
- NS_ENSURE_ARG_POINTER(aListener);
- if (mObjectResizeEventListeners.Contains(aListener)) {
- /* listener already registered */
- NS_ASSERTION(false,
- "trying to register an already registered object resize event listener");
- return NS_OK;
- }
- mObjectResizeEventListeners.AppendElement(*aListener);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::RemoveObjectResizeEventListener(
- nsIHTMLObjectResizeListener* aListener)
-{
- NS_ENSURE_ARG_POINTER(aListener);
- if (!mObjectResizeEventListeners.Contains(aListener)) {
- /* listener was not registered */
- NS_ASSERTION(false,
- "trying to remove an object resize event listener that was not already registered");
- return NS_OK;
- }
- mObjectResizeEventListeners.RemoveElement(aListener);
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/HTMLEditorObjectResizerUtils.h b/editor/libeditor/HTMLEditorObjectResizerUtils.h
deleted file mode 100644
index 2bebbe76b..000000000
--- a/editor/libeditor/HTMLEditorObjectResizerUtils.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef HTMLEditorObjectResizerUtils_h
-#define HTMLEditorObjectResizerUtils_h
-
-#include "nsIDOMEventListener.h"
-#include "nsISelectionListener.h"
-#include "nsISupportsImpl.h"
-#include "nsIWeakReferenceUtils.h"
-#include "nsLiteralString.h"
-
-class nsIHTMLEditor;
-
-namespace mozilla {
-
-#define kTopLeft NS_LITERAL_STRING("nw")
-#define kTop NS_LITERAL_STRING("n")
-#define kTopRight NS_LITERAL_STRING("ne")
-#define kLeft NS_LITERAL_STRING("w")
-#define kRight NS_LITERAL_STRING("e")
-#define kBottomLeft NS_LITERAL_STRING("sw")
-#define kBottom NS_LITERAL_STRING("s")
-#define kBottomRight NS_LITERAL_STRING("se")
-
-/******************************************************************************
- * mozilla::ResizerSelectionListener
- ******************************************************************************/
-
-class ResizerSelectionListener final : public nsISelectionListener
-{
-public:
- explicit ResizerSelectionListener(nsIHTMLEditor* aEditor);
- void Reset();
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSISELECTIONLISTENER
-
-protected:
- virtual ~ResizerSelectionListener() {}
- nsWeakPtr mEditor;
-};
-
-/******************************************************************************
- * mozilla::ResizerMouseMotionListener
- ******************************************************************************/
-
-class ResizerMouseMotionListener final : public nsIDOMEventListener
-{
-public:
- explicit ResizerMouseMotionListener(nsIHTMLEditor* aEditor);
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSIDOMEVENTLISTENER
-
-protected:
- virtual ~ResizerMouseMotionListener() {}
- nsWeakPtr mEditor;
-};
-
-/******************************************************************************
- * mozilla::DocumentResizeEventListener
- ******************************************************************************/
-
-class DocumentResizeEventListener final : public nsIDOMEventListener
-{
-public:
- explicit DocumentResizeEventListener(nsIHTMLEditor* aEditor);
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSIDOMEVENTLISTENER
-
-protected:
- virtual ~DocumentResizeEventListener() {}
- nsWeakPtr mEditor;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef HTMLEditorObjectResizerUtils_h
diff --git a/editor/libeditor/HTMLInlineTableEditor.cpp b/editor/libeditor/HTMLInlineTableEditor.cpp
deleted file mode 100644
index 3da1876ec..000000000
--- a/editor/libeditor/HTMLInlineTableEditor.cpp
+++ /dev/null
@@ -1,283 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/HTMLEditor.h"
-
-#include "HTMLEditUtils.h"
-#include "mozilla/dom/Element.h"
-#include "nsAString.h"
-#include "nsCOMPtr.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsIContent.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMEventTarget.h"
-#include "nsIDOMHTMLElement.h"
-#include "nsIDOMNode.h"
-#include "nsIHTMLObjectResizer.h"
-#include "nsIPresShell.h"
-#include "nsLiteralString.h"
-#include "nsReadableUtils.h"
-#include "nsString.h"
-#include "nscore.h"
-
-namespace mozilla {
-
-// Uncomment the following line if you want to disable
-// table deletion when the only column/row is removed
-// #define DISABLE_TABLE_DELETION 1
-
-NS_IMETHODIMP
-HTMLEditor::SetInlineTableEditingEnabled(bool aIsEnabled)
-{
- mIsInlineTableEditingEnabled = aIsEnabled;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetInlineTableEditingEnabled(bool* aIsEnabled)
-{
- *aIsEnabled = mIsInlineTableEditingEnabled;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::ShowInlineTableEditingUI(nsIDOMElement* aCell)
-{
- NS_ENSURE_ARG_POINTER(aCell);
-
- // do nothing if aCell is not a table cell...
- nsCOMPtr<Element> cell = do_QueryInterface(aCell);
- if (!cell || !HTMLEditUtils::IsTableCell(cell)) {
- return NS_OK;
- }
-
- if (NS_WARN_IF(!IsDescendantOfEditorRoot(cell))) {
- return NS_ERROR_UNEXPECTED;
- }
-
- if (mInlineEditedCell) {
- NS_ERROR("call HideInlineTableEditingUI first");
- return NS_ERROR_UNEXPECTED;
- }
-
- // the resizers and the shadow will be anonymous children of the body
- nsCOMPtr<nsIDOMElement> bodyElement = do_QueryInterface(GetRoot());
- NS_ENSURE_TRUE(bodyElement, NS_ERROR_NULL_POINTER);
-
- CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
- NS_LITERAL_STRING("mozTableAddColumnBefore"),
- false, getter_AddRefs(mAddColumnBeforeButton));
- CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
- NS_LITERAL_STRING("mozTableRemoveColumn"),
- false, getter_AddRefs(mRemoveColumnButton));
- CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
- NS_LITERAL_STRING("mozTableAddColumnAfter"),
- false, getter_AddRefs(mAddColumnAfterButton));
-
- CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
- NS_LITERAL_STRING("mozTableAddRowBefore"),
- false, getter_AddRefs(mAddRowBeforeButton));
- CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
- NS_LITERAL_STRING("mozTableRemoveRow"),
- false, getter_AddRefs(mRemoveRowButton));
- CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
- NS_LITERAL_STRING("mozTableAddRowAfter"),
- false, getter_AddRefs(mAddRowAfterButton));
-
- AddMouseClickListener(mAddColumnBeforeButton);
- AddMouseClickListener(mRemoveColumnButton);
- AddMouseClickListener(mAddColumnAfterButton);
- AddMouseClickListener(mAddRowBeforeButton);
- AddMouseClickListener(mRemoveRowButton);
- AddMouseClickListener(mAddRowAfterButton);
-
- mInlineEditedCell = aCell;
- return RefreshInlineTableEditingUI();
-}
-
-NS_IMETHODIMP
-HTMLEditor::HideInlineTableEditingUI()
-{
- mInlineEditedCell = nullptr;
-
- RemoveMouseClickListener(mAddColumnBeforeButton);
- RemoveMouseClickListener(mRemoveColumnButton);
- RemoveMouseClickListener(mAddColumnAfterButton);
- RemoveMouseClickListener(mAddRowBeforeButton);
- RemoveMouseClickListener(mRemoveRowButton);
- RemoveMouseClickListener(mAddRowAfterButton);
-
- // get the presshell's document observer interface.
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
- // We allow the pres shell to be null; when it is, we presume there
- // are no document observers to notify, but we still want to
- // UnbindFromTree.
-
- // get the root content node.
- nsCOMPtr<nsIContent> bodyContent = GetRoot();
-
- DeleteRefToAnonymousNode(mAddColumnBeforeButton, bodyContent, ps);
- mAddColumnBeforeButton = nullptr;
- DeleteRefToAnonymousNode(mRemoveColumnButton, bodyContent, ps);
- mRemoveColumnButton = nullptr;
- DeleteRefToAnonymousNode(mAddColumnAfterButton, bodyContent, ps);
- mAddColumnAfterButton = nullptr;
- DeleteRefToAnonymousNode(mAddRowBeforeButton, bodyContent, ps);
- mAddRowBeforeButton = nullptr;
- DeleteRefToAnonymousNode(mRemoveRowButton, bodyContent, ps);
- mRemoveRowButton = nullptr;
- DeleteRefToAnonymousNode(mAddRowAfterButton, bodyContent, ps);
- mAddRowAfterButton = nullptr;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::DoInlineTableEditingAction(nsIDOMElement* aElement)
-{
- NS_ENSURE_ARG_POINTER(aElement);
- bool anonElement = false;
- if (aElement &&
- NS_SUCCEEDED(aElement->HasAttribute(NS_LITERAL_STRING("_moz_anonclass"), &anonElement)) &&
- anonElement) {
- nsAutoString anonclass;
- nsresult rv =
- aElement->GetAttribute(NS_LITERAL_STRING("_moz_anonclass"), anonclass);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!StringBeginsWith(anonclass, NS_LITERAL_STRING("mozTable")))
- return NS_OK;
-
- nsCOMPtr<nsIDOMNode> tableNode = GetEnclosingTable(mInlineEditedCell);
- nsCOMPtr<nsIDOMElement> tableElement = do_QueryInterface(tableNode);
- int32_t rowCount, colCount;
- rv = GetTableSize(tableElement, &rowCount, &colCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- bool hideUI = false;
- bool hideResizersWithInlineTableUI = (GetAsDOMNode(mResizedObject) == tableElement);
-
- if (anonclass.EqualsLiteral("mozTableAddColumnBefore"))
- InsertTableColumn(1, false);
- else if (anonclass.EqualsLiteral("mozTableAddColumnAfter"))
- InsertTableColumn(1, true);
- else if (anonclass.EqualsLiteral("mozTableAddRowBefore"))
- InsertTableRow(1, false);
- else if (anonclass.EqualsLiteral("mozTableAddRowAfter"))
- InsertTableRow(1, true);
- else if (anonclass.EqualsLiteral("mozTableRemoveColumn")) {
- DeleteTableColumn(1);
-#ifndef DISABLE_TABLE_DELETION
- hideUI = (colCount == 1);
-#endif
- }
- else if (anonclass.EqualsLiteral("mozTableRemoveRow")) {
- DeleteTableRow(1);
-#ifndef DISABLE_TABLE_DELETION
- hideUI = (rowCount == 1);
-#endif
- }
- else
- return NS_OK;
-
- if (hideUI) {
- HideInlineTableEditingUI();
- if (hideResizersWithInlineTableUI)
- HideResizers();
- }
- }
-
- return NS_OK;
-}
-
-void
-HTMLEditor::AddMouseClickListener(nsIDOMElement* aElement)
-{
- nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aElement));
- if (evtTarget) {
- evtTarget->AddEventListener(NS_LITERAL_STRING("click"),
- mEventListener, true);
- }
-}
-
-void
-HTMLEditor::RemoveMouseClickListener(nsIDOMElement* aElement)
-{
- nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aElement));
- if (evtTarget) {
- evtTarget->RemoveEventListener(NS_LITERAL_STRING("click"),
- mEventListener, true);
- }
-}
-
-NS_IMETHODIMP
-HTMLEditor::RefreshInlineTableEditingUI()
-{
- nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(mInlineEditedCell);
- if (!htmlElement) {
- return NS_ERROR_NULL_POINTER;
- }
-
- int32_t xCell, yCell, wCell, hCell;
- GetElementOrigin(mInlineEditedCell, xCell, yCell);
-
- nsresult rv = htmlElement->GetOffsetWidth(&wCell);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = htmlElement->GetOffsetHeight(&hCell);
- NS_ENSURE_SUCCESS(rv, rv);
-
- int32_t xHoriz = xCell + wCell/2;
- int32_t yVert = yCell + hCell/2;
-
- nsCOMPtr<nsIDOMNode> tableNode = GetEnclosingTable(mInlineEditedCell);
- nsCOMPtr<nsIDOMElement> tableElement = do_QueryInterface(tableNode);
- int32_t rowCount, colCount;
- rv = GetTableSize(tableElement, &rowCount, &colCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- SetAnonymousElementPosition(xHoriz-10, yCell-7, mAddColumnBeforeButton);
-#ifdef DISABLE_TABLE_DELETION
- NS_NAMED_LITERAL_STRING(classStr, "class");
-
- if (colCount== 1) {
- mRemoveColumnButton->SetAttribute(classStr,
- NS_LITERAL_STRING("hidden"));
- }
- else {
- bool hasClass = false;
- rv = mRemoveColumnButton->HasAttribute(classStr, &hasClass);
- if (NS_SUCCEEDED(rv) && hasClass) {
- mRemoveColumnButton->RemoveAttribute(classStr);
- }
-#endif
- SetAnonymousElementPosition(xHoriz-4, yCell-7, mRemoveColumnButton);
-#ifdef DISABLE_TABLE_DELETION
- }
-#endif
- SetAnonymousElementPosition(xHoriz+6, yCell-7, mAddColumnAfterButton);
-
- SetAnonymousElementPosition(xCell-7, yVert-10, mAddRowBeforeButton);
-#ifdef DISABLE_TABLE_DELETION
- if (rowCount== 1) {
- mRemoveRowButton->SetAttribute(classStr,
- NS_LITERAL_STRING("hidden"));
- }
- else {
- bool hasClass = false;
- rv = mRemoveRowButton->HasAttribute(classStr, &hasClass);
- if (NS_SUCCEEDED(rv) && hasClass) {
- mRemoveRowButton->RemoveAttribute(classStr);
- }
-#endif
- SetAnonymousElementPosition(xCell-7, yVert-4, mRemoveRowButton);
-#ifdef DISABLE_TABLE_DELETION
- }
-#endif
- SetAnonymousElementPosition(xCell-7, yVert+6, mAddRowAfterButton);
-
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/HTMLStyleEditor.cpp b/editor/libeditor/HTMLStyleEditor.cpp
deleted file mode 100644
index c41f0a05c..000000000
--- a/editor/libeditor/HTMLStyleEditor.cpp
+++ /dev/null
@@ -1,1756 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/HTMLEditor.h"
-
-#include "HTMLEditUtils.h"
-#include "TextEditRules.h"
-#include "TextEditUtils.h"
-#include "TypeInState.h"
-#include "mozilla/Assertions.h"
-#include "mozilla/EditorUtils.h"
-#include "mozilla/SelectionState.h"
-#include "mozilla/dom/Selection.h"
-#include "mozilla/dom/Element.h"
-#include "mozilla/mozalloc.h"
-#include "nsAString.h"
-#include "nsAttrName.h"
-#include "nsCOMPtr.h"
-#include "nsCaseTreatment.h"
-#include "nsComponentManagerUtils.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsGkAtoms.h"
-#include "nsIAtom.h"
-#include "nsIContent.h"
-#include "nsIContentIterator.h"
-#include "nsIDOMElement.h"
-#include "nsIEditor.h"
-#include "nsIEditorIMESupport.h"
-#include "nsIEditRules.h"
-#include "nsNameSpaceManager.h"
-#include "nsINode.h"
-#include "nsISupportsImpl.h"
-#include "nsLiteralString.h"
-#include "nsRange.h"
-#include "nsReadableUtils.h"
-#include "nsString.h"
-#include "nsStringFwd.h"
-#include "nsTArray.h"
-#include "nsUnicharUtils.h"
-#include "nscore.h"
-
-class nsISupports;
-
-namespace mozilla {
-
-using namespace dom;
-
-static bool
-IsEmptyTextNode(HTMLEditor* aThis, nsINode* aNode)
-{
- bool isEmptyTextNode = false;
- return EditorBase::IsTextNode(aNode) &&
- NS_SUCCEEDED(aThis->IsEmptyNode(aNode, &isEmptyTextNode)) &&
- isEmptyTextNode;
-}
-
-NS_IMETHODIMP
-HTMLEditor::AddDefaultProperty(nsIAtom* aProperty,
- const nsAString& aAttribute,
- const nsAString& aValue)
-{
- nsString outValue;
- int32_t index;
- nsString attr(aAttribute);
- if (TypeInState::FindPropInList(aProperty, attr, &outValue,
- mDefaultStyles, index)) {
- PropItem *item = mDefaultStyles[index];
- item->value = aValue;
- } else {
- nsString value(aValue);
- PropItem *propItem = new PropItem(aProperty, attr, value);
- mDefaultStyles.AppendElement(propItem);
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::RemoveDefaultProperty(nsIAtom* aProperty,
- const nsAString& aAttribute,
- const nsAString& aValue)
-{
- nsString outValue;
- int32_t index;
- nsString attr(aAttribute);
- if (TypeInState::FindPropInList(aProperty, attr, &outValue,
- mDefaultStyles, index)) {
- delete mDefaultStyles[index];
- mDefaultStyles.RemoveElementAt(index);
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::RemoveAllDefaultProperties()
-{
- size_t defcon = mDefaultStyles.Length();
- for (size_t j = 0; j < defcon; j++) {
- delete mDefaultStyles[j];
- }
- mDefaultStyles.Clear();
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-HTMLEditor::SetInlineProperty(nsIAtom* aProperty,
- const nsAString& aAttribute,
- const nsAString& aValue)
-{
- NS_ENSURE_TRUE(aProperty, NS_ERROR_NULL_POINTER);
- NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
- nsCOMPtr<nsIEditRules> rules(mRules);
- ForceCompositionEnd();
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- if (selection->Collapsed()) {
- // Manipulating text attributes on a collapsed selection only sets state
- // for the next text insertion
- mTypeInState->SetProp(aProperty, aAttribute, aValue);
- return NS_OK;
- }
-
- AutoEditBatch batchIt(this);
- AutoRules beginRulesSniffing(this, EditAction::insertElement,
- nsIEditor::eNext);
- AutoSelectionRestorer selectionRestorer(selection, this);
- AutoTransactionsConserveSelection dontSpazMySelection(this);
-
- bool cancel, handled;
- TextRulesInfo ruleInfo(EditAction::setTextProperty);
- // Protect the edit rules object from dying
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!cancel && !handled) {
- // Loop through the ranges in the selection
- uint32_t rangeCount = selection->RangeCount();
- for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; rangeIdx++) {
- RefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
-
- // Adjust range to include any ancestors whose children are entirely
- // selected
- rv = PromoteInlineRange(*range);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Check for easy case: both range endpoints in same text node
- nsCOMPtr<nsINode> startNode = range->GetStartParent();
- nsCOMPtr<nsINode> endNode = range->GetEndParent();
- if (startNode && startNode == endNode && startNode->GetAsText()) {
- rv = SetInlinePropertyOnTextNode(*startNode->GetAsText(),
- range->StartOffset(),
- range->EndOffset(),
- *aProperty, &aAttribute, aValue);
- NS_ENSURE_SUCCESS(rv, rv);
- continue;
- }
-
- // Not the easy case. Range not contained in single text node. There
- // are up to three phases here. There are all the nodes reported by the
- // subtree iterator to be processed. And there are potentially a
- // starting textnode and an ending textnode which are only partially
- // contained by the range.
-
- // Let's handle the nodes reported by the iterator. These nodes are
- // entirely contained in the selection range. We build up a list of them
- // (since doing operations on the document during iteration would perturb
- // the iterator).
-
- OwningNonNull<nsIContentIterator> iter = NS_NewContentSubtreeIterator();
-
- nsTArray<OwningNonNull<nsIContent>> arrayOfNodes;
-
- // Iterate range and build up array
- rv = iter->Init(range);
- // Init returns an error if there are no nodes in range. This can easily
- // happen with the subtree iterator if the selection doesn't contain any
- // *whole* nodes.
- if (NS_SUCCEEDED(rv)) {
- for (; !iter->IsDone(); iter->Next()) {
- OwningNonNull<nsINode> node = *iter->GetCurrentNode();
-
- if (node->IsContent() && IsEditable(node)) {
- arrayOfNodes.AppendElement(*node->AsContent());
- }
- }
- }
- // First check the start parent of the range to see if it needs to be
- // separately handled (it does if it's a text node, due to how the
- // subtree iterator works - it will not have reported it).
- if (startNode && startNode->GetAsText() && IsEditable(startNode)) {
- rv = SetInlinePropertyOnTextNode(*startNode->GetAsText(),
- range->StartOffset(),
- startNode->Length(), *aProperty,
- &aAttribute, aValue);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // Then loop through the list, set the property on each node
- for (auto& node : arrayOfNodes) {
- rv = SetInlinePropertyOnNode(*node, *aProperty, &aAttribute, aValue);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // Last check the end parent of the range to see if it needs to be
- // separately handled (it does if it's a text node, due to how the
- // subtree iterator works - it will not have reported it).
- if (endNode && endNode->GetAsText() && IsEditable(endNode)) {
- rv = SetInlinePropertyOnTextNode(*endNode->GetAsText(), 0,
- range->EndOffset(), *aProperty,
- &aAttribute, aValue);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- }
- if (!cancel) {
- // Post-process
- return rules->DidDoAction(selection, &ruleInfo, rv);
- }
- return NS_OK;
-}
-
-// Helper function for SetInlinePropertyOn*: is aNode a simple old <b>, <font>,
-// <span style="">, etc. that we can reuse instead of creating a new one?
-bool
-HTMLEditor::IsSimpleModifiableNode(nsIContent* aContent,
- nsIAtom* aProperty,
- const nsAString* aAttribute,
- const nsAString* aValue)
-{
- // aContent can be null, in which case we'll return false in a few lines
- MOZ_ASSERT(aProperty);
- MOZ_ASSERT_IF(aAttribute, aValue);
-
- nsCOMPtr<dom::Element> element = do_QueryInterface(aContent);
- if (!element) {
- return false;
- }
-
- // First check for <b>, <i>, etc.
- if (element->IsHTMLElement(aProperty) && !element->GetAttrCount() &&
- (!aAttribute || aAttribute->IsEmpty())) {
- return true;
- }
-
- // Special cases for various equivalencies: <strong>, <em>, <s>
- if (!element->GetAttrCount() &&
- ((aProperty == nsGkAtoms::b &&
- element->IsHTMLElement(nsGkAtoms::strong)) ||
- (aProperty == nsGkAtoms::i &&
- element->IsHTMLElement(nsGkAtoms::em)) ||
- (aProperty == nsGkAtoms::strike &&
- element->IsHTMLElement(nsGkAtoms::s)))) {
- return true;
- }
-
- // Now look for things like <font>
- if (aAttribute && !aAttribute->IsEmpty()) {
- nsCOMPtr<nsIAtom> atom = NS_Atomize(*aAttribute);
- MOZ_ASSERT(atom);
-
- nsString attrValue;
- if (element->IsHTMLElement(aProperty) &&
- IsOnlyAttribute(element, *aAttribute) &&
- element->GetAttr(kNameSpaceID_None, atom, attrValue) &&
- attrValue.Equals(*aValue, nsCaseInsensitiveStringComparator())) {
- // This is not quite correct, because it excludes cases like
- // <font face=000> being the same as <font face=#000000>.
- // Property-specific handling is needed (bug 760211).
- return true;
- }
- }
-
- // No luck so far. Now we check for a <span> with a single style=""
- // attribute that sets only the style we're looking for, if this type of
- // style supports it
- if (!mCSSEditUtils->IsCSSEditableProperty(element, aProperty, aAttribute) ||
- !element->IsHTMLElement(nsGkAtoms::span) ||
- element->GetAttrCount() != 1 ||
- !element->HasAttr(kNameSpaceID_None, nsGkAtoms::style)) {
- return false;
- }
-
- // Some CSS styles are not so simple. For instance, underline is
- // "text-decoration: underline", which decomposes into four different text-*
- // properties. So for now, we just create a span, add the desired style, and
- // see if it matches.
- nsCOMPtr<Element> newSpan = CreateHTMLContent(nsGkAtoms::span);
- NS_ASSERTION(newSpan, "CreateHTMLContent failed");
- NS_ENSURE_TRUE(newSpan, false);
- mCSSEditUtils->SetCSSEquivalentToHTMLStyle(newSpan, aProperty,
- aAttribute, aValue,
- /*suppress transaction*/ true);
-
- return mCSSEditUtils->ElementsSameStyle(newSpan, element);
-}
-
-nsresult
-HTMLEditor::SetInlinePropertyOnTextNode(Text& aText,
- int32_t aStartOffset,
- int32_t aEndOffset,
- nsIAtom& aProperty,
- const nsAString* aAttribute,
- const nsAString& aValue)
-{
- if (!aText.GetParentNode() ||
- !CanContainTag(*aText.GetParentNode(), aProperty)) {
- return NS_OK;
- }
-
- // Don't need to do anything if no characters actually selected
- if (aStartOffset == aEndOffset) {
- return NS_OK;
- }
-
- // Don't need to do anything if property already set on node
- if (mCSSEditUtils->IsCSSEditableProperty(&aText, &aProperty, aAttribute)) {
- // The HTML styles defined by aProperty/aAttribute have a CSS equivalence
- // for node; let's check if it carries those CSS styles
- if (mCSSEditUtils->IsCSSEquivalentToHTMLInlineStyleSet(&aText, &aProperty,
- aAttribute, aValue, CSSEditUtils::eComputed)) {
- return NS_OK;
- }
- } else if (IsTextPropertySetByContent(&aText, &aProperty, aAttribute,
- &aValue)) {
- return NS_OK;
- }
-
- // Do we need to split the text node?
- ErrorResult rv;
- RefPtr<Text> text = &aText;
- if (uint32_t(aEndOffset) != aText.Length()) {
- // We need to split off back of text node
- nsIContent* textNode = SplitNode(aText, aEndOffset, rv);
- NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult());
- text = textNode->GetAsText();
- }
-
- if (aStartOffset) {
- // We need to split off front of text node
- SplitNode(*text, aStartOffset, rv);
- NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult());
- }
-
- if (aAttribute) {
- // Look for siblings that are correct type of node
- nsIContent* sibling = GetPriorHTMLSibling(text);
- if (IsSimpleModifiableNode(sibling, &aProperty, aAttribute, &aValue)) {
- // Previous sib is already right kind of inline node; slide this over
- return MoveNode(text, sibling, -1);
- }
- sibling = GetNextHTMLSibling(text);
- if (IsSimpleModifiableNode(sibling, &aProperty, aAttribute, &aValue)) {
- // Following sib is already right kind of inline node; slide this over
- return MoveNode(text, sibling, 0);
- }
- }
-
- // Reparent the node inside inline node with appropriate {attribute,value}
- return SetInlinePropertyOnNode(*text, aProperty, aAttribute, aValue);
-}
-
-nsresult
-HTMLEditor::SetInlinePropertyOnNodeImpl(nsIContent& aNode,
- nsIAtom& aProperty,
- const nsAString* aAttribute,
- const nsAString& aValue)
-{
- nsCOMPtr<nsIAtom> attrAtom = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
-
- // If this is an element that can't be contained in a span, we have to
- // recurse to its children.
- if (!TagCanContain(*nsGkAtoms::span, aNode)) {
- if (aNode.HasChildren()) {
- nsTArray<OwningNonNull<nsIContent>> arrayOfNodes;
-
- // Populate the list.
- for (nsCOMPtr<nsIContent> child = aNode.GetFirstChild();
- child;
- child = child->GetNextSibling()) {
- if (IsEditable(child) && !IsEmptyTextNode(this, child)) {
- arrayOfNodes.AppendElement(*child);
- }
- }
-
- // Then loop through the list, set the property on each node.
- for (auto& node : arrayOfNodes) {
- nsresult rv = SetInlinePropertyOnNode(node, aProperty, aAttribute,
- aValue);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- return NS_OK;
- }
-
- // First check if there's an adjacent sibling we can put our node into.
- nsCOMPtr<nsIContent> previousSibling = GetPriorHTMLSibling(&aNode);
- nsCOMPtr<nsIContent> nextSibling = GetNextHTMLSibling(&aNode);
- if (IsSimpleModifiableNode(previousSibling, &aProperty, aAttribute, &aValue)) {
- nsresult rv = MoveNode(&aNode, previousSibling, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- if (IsSimpleModifiableNode(nextSibling, &aProperty, aAttribute, &aValue)) {
- rv = JoinNodes(*previousSibling, *nextSibling);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
- }
- if (IsSimpleModifiableNode(nextSibling, &aProperty, aAttribute, &aValue)) {
- nsresult rv = MoveNode(&aNode, nextSibling, 0);
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
- }
-
- // Don't need to do anything if property already set on node
- if (mCSSEditUtils->IsCSSEditableProperty(&aNode, &aProperty, aAttribute)) {
- if (mCSSEditUtils->IsCSSEquivalentToHTMLInlineStyleSet(
- &aNode, &aProperty, aAttribute, aValue, CSSEditUtils::eComputed)) {
- return NS_OK;
- }
- } else if (IsTextPropertySetByContent(&aNode, &aProperty,
- aAttribute, &aValue)) {
- return NS_OK;
- }
-
- bool useCSS = (IsCSSEnabled() &&
- mCSSEditUtils->IsCSSEditableProperty(&aNode, &aProperty,
- aAttribute)) ||
- // bgcolor is always done using CSS
- attrAtom == nsGkAtoms::bgcolor;
-
- if (useCSS) {
- nsCOMPtr<dom::Element> tmp;
- // We only add style="" to <span>s with no attributes (bug 746515). If we
- // don't have one, we need to make one.
- if (aNode.IsHTMLElement(nsGkAtoms::span) &&
- !aNode.AsElement()->GetAttrCount()) {
- tmp = aNode.AsElement();
- } else {
- tmp = InsertContainerAbove(&aNode, nsGkAtoms::span);
- NS_ENSURE_STATE(tmp);
- }
-
- // Add the CSS styles corresponding to the HTML style request
- mCSSEditUtils->SetCSSEquivalentToHTMLStyle(tmp,
- &aProperty, attrAtom,
- &aValue, false);
- return NS_OK;
- }
-
- // is it already the right kind of node, but with wrong attribute?
- if (aNode.IsHTMLElement(&aProperty)) {
- // Just set the attribute on it.
- nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(&aNode);
- return SetAttribute(elem, *aAttribute, aValue);
- }
-
- // ok, chuck it in its very own container
- nsCOMPtr<Element> tmp = InsertContainerAbove(&aNode, &aProperty, attrAtom,
- &aValue);
- NS_ENSURE_STATE(tmp);
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::SetInlinePropertyOnNode(nsIContent& aNode,
- nsIAtom& aProperty,
- const nsAString* aAttribute,
- const nsAString& aValue)
-{
- nsCOMPtr<nsIContent> previousSibling = aNode.GetPreviousSibling(),
- nextSibling = aNode.GetNextSibling();
- NS_ENSURE_STATE(aNode.GetParentNode());
- OwningNonNull<nsINode> parent = *aNode.GetParentNode();
-
- nsresult rv = RemoveStyleInside(aNode, &aProperty, aAttribute);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (aNode.GetParentNode()) {
- // The node is still where it was
- return SetInlinePropertyOnNodeImpl(aNode, aProperty,
- aAttribute, aValue);
- }
-
- // It's vanished. Use the old siblings for reference to construct a
- // list. But first, verify that the previous/next siblings are still
- // where we expect them; otherwise we have to give up.
- if ((previousSibling && previousSibling->GetParentNode() != parent) ||
- (nextSibling && nextSibling->GetParentNode() != parent)) {
- return NS_ERROR_UNEXPECTED;
- }
- nsTArray<OwningNonNull<nsIContent>> nodesToSet;
- nsCOMPtr<nsIContent> cur = previousSibling
- ? previousSibling->GetNextSibling() : parent->GetFirstChild();
- for (; cur && cur != nextSibling; cur = cur->GetNextSibling()) {
- if (IsEditable(cur)) {
- nodesToSet.AppendElement(*cur);
- }
- }
-
- for (auto& node : nodesToSet) {
- rv = SetInlinePropertyOnNodeImpl(node, aProperty, aAttribute, aValue);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::SplitStyleAboveRange(nsRange* inRange,
- nsIAtom* aProperty,
- const nsAString* aAttribute)
-{
- NS_ENSURE_TRUE(inRange, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsINode> startNode = inRange->GetStartParent();
- int32_t startOffset = inRange->StartOffset();
- nsCOMPtr<nsINode> endNode = inRange->GetEndParent();
- int32_t endOffset = inRange->EndOffset();
-
- nsCOMPtr<nsINode> origStartNode = startNode;
-
- // split any matching style nodes above the start of range
- {
- AutoTrackDOMPoint tracker(mRangeUpdater, address_of(endNode), &endOffset);
- nsresult rv =
- SplitStyleAbovePoint(address_of(startNode), &startOffset, aProperty,
- aAttribute);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // second verse, same as the first...
- nsresult rv =
- SplitStyleAbovePoint(address_of(endNode), &endOffset, aProperty,
- aAttribute);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // reset the range
- rv = inRange->SetStartAndEnd(startNode, startOffset, endNode, endOffset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::SplitStyleAbovePoint(nsCOMPtr<nsINode>* aNode,
- int32_t* aOffset,
- // null here means we split all properties
- nsIAtom* aProperty,
- const nsAString* aAttribute,
- nsIContent** aOutLeftNode,
- nsIContent** aOutRightNode)
-{
- NS_ENSURE_TRUE(aNode && *aNode && aOffset, NS_ERROR_NULL_POINTER);
- NS_ENSURE_TRUE((*aNode)->IsContent(), NS_OK);
-
- // Split any matching style nodes above the node/offset
- OwningNonNull<nsIContent> node = *(*aNode)->AsContent();
-
- bool useCSS = IsCSSEnabled();
-
- bool isSet;
- while (!IsBlockNode(node) && node->GetParent() &&
- IsEditable(node->GetParent())) {
- isSet = false;
- if (useCSS && mCSSEditUtils->IsCSSEditableProperty(node, aProperty,
- aAttribute)) {
- // The HTML style defined by aProperty/aAttribute has a CSS equivalence
- // in this implementation for the node; let's check if it carries those
- // CSS styles
- nsAutoString firstValue;
- isSet = mCSSEditUtils->IsCSSEquivalentToHTMLInlineStyleSet(
- node, aProperty, aAttribute, firstValue,
- CSSEditUtils::eSpecified);
- }
- if (// node is the correct inline prop
- (aProperty && node->IsHTMLElement(aProperty)) ||
- // node is href - test if really <a href=...
- (aProperty == nsGkAtoms::href && HTMLEditUtils::IsLink(node)) ||
- // or node is any prop, and we asked to split them all
- (!aProperty && NodeIsProperty(node)) ||
- // or the style is specified in the style attribute
- isSet) {
- // Found a style node we need to split
- int32_t offset = SplitNodeDeep(*node, *(*aNode)->AsContent(), *aOffset,
- EmptyContainers::yes, aOutLeftNode,
- aOutRightNode);
- NS_ENSURE_TRUE(offset != -1, NS_ERROR_FAILURE);
- // reset startNode/startOffset
- *aNode = node->GetParent();
- *aOffset = offset;
- }
- node = node->GetParent();
- }
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::ClearStyle(nsCOMPtr<nsINode>* aNode,
- int32_t* aOffset,
- nsIAtom* aProperty,
- const nsAString* aAttribute)
-{
- nsCOMPtr<nsIContent> leftNode, rightNode;
- nsresult rv = SplitStyleAbovePoint(aNode, aOffset, aProperty,
- aAttribute, getter_AddRefs(leftNode),
- getter_AddRefs(rightNode));
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (leftNode) {
- bool bIsEmptyNode;
- IsEmptyNode(leftNode, &bIsEmptyNode, false, true);
- if (bIsEmptyNode) {
- // delete leftNode if it became empty
- rv = DeleteNode(leftNode);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- if (rightNode) {
- nsCOMPtr<nsINode> secondSplitParent = GetLeftmostChild(rightNode);
- // don't try to split non-containers (br's, images, hr's, etc.)
- if (!secondSplitParent) {
- secondSplitParent = rightNode;
- }
- nsCOMPtr<Element> savedBR;
- if (!IsContainer(secondSplitParent)) {
- if (TextEditUtils::IsBreak(secondSplitParent)) {
- savedBR = do_QueryInterface(secondSplitParent);
- NS_ENSURE_STATE(savedBR);
- }
-
- secondSplitParent = secondSplitParent->GetParentNode();
- }
- *aOffset = 0;
- rv = SplitStyleAbovePoint(address_of(secondSplitParent),
- aOffset, aProperty, aAttribute,
- getter_AddRefs(leftNode),
- getter_AddRefs(rightNode));
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (rightNode) {
- bool bIsEmptyNode;
- IsEmptyNode(rightNode, &bIsEmptyNode, false, true);
- if (bIsEmptyNode) {
- // delete rightNode if it became empty
- rv = DeleteNode(rightNode);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- if (!leftNode) {
- return NS_OK;
- }
-
- // should be impossible to not get a new leftnode here
- nsCOMPtr<nsINode> newSelParent = GetLeftmostChild(leftNode);
- if (!newSelParent) {
- newSelParent = leftNode;
- }
- // If rightNode starts with a br, suck it out of right node and into
- // leftNode. This is so we you don't revert back to the previous style
- // if you happen to click at the end of a line.
- if (savedBR) {
- rv = MoveNode(savedBR, newSelParent, 0);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // remove the style on this new hierarchy
- int32_t newSelOffset = 0;
- {
- // Track the point at the new hierarchy. This is so we can know where
- // to put the selection after we call RemoveStyleInside().
- // RemoveStyleInside() could remove any and all of those nodes, so I
- // have to use the range tracking system to find the right spot to put
- // selection.
- AutoTrackDOMPoint tracker(mRangeUpdater,
- address_of(newSelParent), &newSelOffset);
- rv = RemoveStyleInside(*leftNode, aProperty, aAttribute);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // reset our node offset values to the resulting new sel point
- *aNode = newSelParent;
- *aOffset = newSelOffset;
- }
-
- return NS_OK;
-}
-
-bool
-HTMLEditor::NodeIsProperty(nsINode& aNode)
-{
- return IsContainer(&aNode) && IsEditable(&aNode) && !IsBlockNode(&aNode) &&
- !aNode.IsHTMLElement(nsGkAtoms::a);
-}
-
-nsresult
-HTMLEditor::ApplyDefaultProperties()
-{
- size_t defcon = mDefaultStyles.Length();
- for (size_t j = 0; j < defcon; j++) {
- PropItem *propItem = mDefaultStyles[j];
- NS_ENSURE_TRUE(propItem, NS_ERROR_NULL_POINTER);
- nsresult rv =
- SetInlineProperty(propItem->tag, propItem->attr, propItem->value);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::RemoveStyleInside(nsIContent& aNode,
- nsIAtom* aProperty,
- const nsAString* aAttribute,
- const bool aChildrenOnly /* = false */)
-{
- if (aNode.GetAsText()) {
- return NS_OK;
- }
-
- // first process the children
- RefPtr<nsIContent> child = aNode.GetFirstChild();
- while (child) {
- // cache next sibling since we might remove child
- nsCOMPtr<nsIContent> next = child->GetNextSibling();
- nsresult rv = RemoveStyleInside(*child, aProperty, aAttribute);
- NS_ENSURE_SUCCESS(rv, rv);
- child = next.forget();
- }
-
- // then process the node itself
- if (!aChildrenOnly &&
- // node is prop we asked for
- ((aProperty && aNode.NodeInfo()->NameAtom() == aProperty) ||
- // but check for link (<a href=...)
- (aProperty == nsGkAtoms::href && HTMLEditUtils::IsLink(&aNode)) ||
- // and for named anchors
- (aProperty == nsGkAtoms::name && HTMLEditUtils::IsNamedAnchor(&aNode)) ||
- // or node is any prop and we asked for that
- (!aProperty && NodeIsProperty(aNode)))) {
- // if we weren't passed an attribute, then we want to
- // remove any matching inlinestyles entirely
- if (!aAttribute || aAttribute->IsEmpty()) {
-
- bool hasStyleAttr = aNode.HasAttr(kNameSpaceID_None, nsGkAtoms::style);
- bool hasClassAttr = aNode.HasAttr(kNameSpaceID_None, nsGkAtoms::_class);
- if (aProperty && (hasStyleAttr || hasClassAttr)) {
- // aNode carries inline styles or a class attribute so we can't
- // just remove the element... We need to create above the element
- // a span that will carry those styles or class, then we can delete
- // the node.
- RefPtr<Element> spanNode =
- InsertContainerAbove(&aNode, nsGkAtoms::span);
- NS_ENSURE_STATE(spanNode);
- nsresult rv =
- CloneAttribute(nsGkAtoms::style, spanNode, aNode.AsElement());
- NS_ENSURE_SUCCESS(rv, rv);
- rv =
- CloneAttribute(nsGkAtoms::_class, spanNode, aNode.AsElement());
- NS_ENSURE_SUCCESS(rv, rv);
- }
- nsresult rv = RemoveContainer(&aNode);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // otherwise we just want to eliminate the attribute
- nsCOMPtr<nsIAtom> attribute = NS_Atomize(*aAttribute);
- if (aNode.HasAttr(kNameSpaceID_None, attribute)) {
- // if this matching attribute is the ONLY one on the node,
- // then remove the whole node. Otherwise just nix the attribute.
- if (IsOnlyAttribute(&aNode, *aAttribute)) {
- nsresult rv = RemoveContainer(&aNode);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(&aNode);
- NS_ENSURE_TRUE(elem, NS_ERROR_NULL_POINTER);
- nsresult rv = RemoveAttribute(elem, *aAttribute);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- }
- }
- }
-
- if (!aChildrenOnly &&
- mCSSEditUtils->IsCSSEditableProperty(&aNode, aProperty, aAttribute)) {
- // the HTML style defined by aProperty/aAttribute has a CSS equivalence in
- // this implementation for the node aNode; let's check if it carries those
- // css styles
- nsCOMPtr<nsIAtom> attribute =
- aAttribute ? NS_Atomize(*aAttribute) : nullptr;
- nsAutoString propertyValue;
- bool isSet = mCSSEditUtils->IsCSSEquivalentToHTMLInlineStyleSet(&aNode,
- aProperty, attribute, propertyValue, CSSEditUtils::eSpecified);
- if (isSet && aNode.IsElement()) {
- // yes, tmp has the corresponding css declarations in its style attribute
- // let's remove them
- mCSSEditUtils->RemoveCSSEquivalentToHTMLStyle(aNode.AsElement(),
- aProperty,
- attribute,
- &propertyValue,
- false);
- // remove the node if it is a span or font, if its style attribute is
- // empty or absent, and if it does not have a class nor an id
- RemoveElementIfNoStyleOrIdOrClass(*aNode.AsElement());
- }
- }
-
- // Or node is big or small and we are setting font size
- if (aChildrenOnly) {
- return NS_OK;
- }
- if (aProperty == nsGkAtoms::font &&
- (aNode.IsHTMLElement(nsGkAtoms::big) ||
- aNode.IsHTMLElement(nsGkAtoms::small)) &&
- aAttribute && aAttribute->LowerCaseEqualsLiteral("size")) {
- // if we are setting font size, remove any nested bigs and smalls
- return RemoveContainer(&aNode);
- }
- return NS_OK;
-}
-
-bool
-HTMLEditor::IsOnlyAttribute(const nsIContent* aContent,
- const nsAString& aAttribute)
-{
- MOZ_ASSERT(aContent);
-
- uint32_t attrCount = aContent->GetAttrCount();
- for (uint32_t i = 0; i < attrCount; ++i) {
- const nsAttrName* name = aContent->GetAttrNameAt(i);
- if (!name->NamespaceEquals(kNameSpaceID_None)) {
- return false;
- }
-
- nsAutoString attrString;
- name->LocalName()->ToString(attrString);
- // if it's the attribute we know about, or a special _moz attribute,
- // keep looking
- if (!attrString.Equals(aAttribute, nsCaseInsensitiveStringComparator()) &&
- !StringBeginsWith(attrString, NS_LITERAL_STRING("_moz"))) {
- return false;
- }
- }
- // if we made it through all of them without finding a real attribute
- // other than aAttribute, then return true
- return true;
-}
-
-nsresult
-HTMLEditor::PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange& aRange)
-{
- // We assume that <a> is not nested.
- nsCOMPtr<nsINode> startNode = aRange.GetStartParent();
- int32_t startOffset = aRange.StartOffset();
- nsCOMPtr<nsINode> endNode = aRange.GetEndParent();
- int32_t endOffset = aRange.EndOffset();
-
- nsCOMPtr<nsINode> parent = startNode;
-
- while (parent && !parent->IsHTMLElement(nsGkAtoms::body) &&
- !HTMLEditUtils::IsNamedAnchor(parent)) {
- parent = parent->GetParentNode();
- }
- NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
-
- if (HTMLEditUtils::IsNamedAnchor(parent)) {
- startNode = parent->GetParentNode();
- startOffset = startNode ? startNode->IndexOf(parent) : -1;
- }
-
- parent = endNode;
- while (parent && !parent->IsHTMLElement(nsGkAtoms::body) &&
- !HTMLEditUtils::IsNamedAnchor(parent)) {
- parent = parent->GetParentNode();
- }
- NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
-
- if (HTMLEditUtils::IsNamedAnchor(parent)) {
- endNode = parent->GetParentNode();
- endOffset = endNode ? endNode->IndexOf(parent) + 1 : 0;
- }
-
- nsresult rv = aRange.SetStartAndEnd(startNode, startOffset,
- endNode, endOffset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::PromoteInlineRange(nsRange& aRange)
-{
- nsCOMPtr<nsINode> startNode = aRange.GetStartParent();
- int32_t startOffset = aRange.StartOffset();
- nsCOMPtr<nsINode> endNode = aRange.GetEndParent();
- int32_t endOffset = aRange.EndOffset();
-
- while (startNode && !startNode->IsHTMLElement(nsGkAtoms::body) &&
- IsEditable(startNode) && IsAtFrontOfNode(*startNode, startOffset)) {
- nsCOMPtr<nsINode> parent = startNode->GetParentNode();
- NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
- startOffset = parent->IndexOf(startNode);
- startNode = parent;
- }
-
- while (endNode && !endNode->IsHTMLElement(nsGkAtoms::body) &&
- IsEditable(endNode) && IsAtEndOfNode(*endNode, endOffset)) {
- nsCOMPtr<nsINode> parent = endNode->GetParentNode();
- NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
- // We are AFTER this node
- endOffset = 1 + parent->IndexOf(endNode);
- endNode = parent;
- }
-
- nsresult rv = aRange.SetStartAndEnd(startNode, startOffset,
- endNode, endOffset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- return NS_OK;
-}
-
-bool
-HTMLEditor::IsAtFrontOfNode(nsINode& aNode,
- int32_t aOffset)
-{
- if (!aOffset) {
- return true;
- }
-
- if (IsTextNode(&aNode)) {
- return false;
- }
-
- nsCOMPtr<nsIContent> firstNode = GetFirstEditableChild(aNode);
- NS_ENSURE_TRUE(firstNode, true);
- if (aNode.IndexOf(firstNode) < aOffset) {
- return false;
- }
- return true;
-}
-
-bool
-HTMLEditor::IsAtEndOfNode(nsINode& aNode,
- int32_t aOffset)
-{
- if (aOffset == (int32_t)aNode.Length()) {
- return true;
- }
-
- if (IsTextNode(&aNode)) {
- return false;
- }
-
- nsCOMPtr<nsIContent> lastNode = GetLastEditableChild(aNode);
- NS_ENSURE_TRUE(lastNode, true);
- if (aNode.IndexOf(lastNode) < aOffset) {
- return true;
- }
- return false;
-}
-
-
-nsresult
-HTMLEditor::GetInlinePropertyBase(nsIAtom& aProperty,
- const nsAString* aAttribute,
- const nsAString* aValue,
- bool* aFirst,
- bool* aAny,
- bool* aAll,
- nsAString* outValue,
- bool aCheckDefaults)
-{
- *aAny = false;
- *aAll = true;
- *aFirst = false;
- bool first = true;
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- bool isCollapsed = selection->Collapsed();
- RefPtr<nsRange> range = selection->GetRangeAt(0);
- // XXX: Should be a while loop, to get each separate range
- // XXX: ERROR_HANDLING can currentItem be null?
- if (range) {
- // For each range, set a flag
- bool firstNodeInRange = true;
-
- if (isCollapsed) {
- nsCOMPtr<nsINode> collapsedNode = range->GetStartParent();
- NS_ENSURE_TRUE(collapsedNode, NS_ERROR_FAILURE);
- bool isSet, theSetting;
- nsString tOutString;
- if (aAttribute) {
- nsString tString(*aAttribute);
- mTypeInState->GetTypingState(isSet, theSetting, &aProperty, tString,
- &tOutString);
- if (outValue) {
- outValue->Assign(tOutString);
- }
- } else {
- mTypeInState->GetTypingState(isSet, theSetting, &aProperty);
- }
- if (isSet) {
- *aFirst = *aAny = *aAll = theSetting;
- return NS_OK;
- }
-
- if (mCSSEditUtils->IsCSSEditableProperty(collapsedNode, &aProperty,
- aAttribute)) {
- if (aValue) {
- tOutString.Assign(*aValue);
- }
- *aFirst = *aAny = *aAll =
- mCSSEditUtils->IsCSSEquivalentToHTMLInlineStyleSet(collapsedNode,
- &aProperty, aAttribute, tOutString, CSSEditUtils::eComputed);
- if (outValue) {
- outValue->Assign(tOutString);
- }
- return NS_OK;
- }
-
- isSet = IsTextPropertySetByContent(collapsedNode, &aProperty,
- aAttribute, aValue, outValue);
- *aFirst = *aAny = *aAll = isSet;
-
- if (!isSet && aCheckDefaults) {
- // Style not set, but if it is a default then it will appear if content
- // is inserted, so we should report it as set (analogous to
- // TypeInState).
- int32_t index;
- if (aAttribute && TypeInState::FindPropInList(&aProperty, *aAttribute,
- outValue, mDefaultStyles,
- index)) {
- *aFirst = *aAny = *aAll = true;
- if (outValue) {
- outValue->Assign(mDefaultStyles[index]->value);
- }
- }
- }
- return NS_OK;
- }
-
- // Non-collapsed selection
- nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
-
- nsAutoString firstValue, theValue;
-
- nsCOMPtr<nsINode> endNode = range->GetEndParent();
- int32_t endOffset = range->EndOffset();
-
- for (iter->Init(range); !iter->IsDone(); iter->Next()) {
- if (!iter->GetCurrentNode()->IsContent()) {
- continue;
- }
- nsCOMPtr<nsIContent> content = iter->GetCurrentNode()->AsContent();
-
- if (content->IsHTMLElement(nsGkAtoms::body)) {
- break;
- }
-
- // just ignore any non-editable nodes
- if (content->GetAsText() && (!IsEditable(content) ||
- IsEmptyTextNode(this, content))) {
- continue;
- }
- if (content->GetAsText()) {
- if (!isCollapsed && first && firstNodeInRange) {
- firstNodeInRange = false;
- if (range->StartOffset() == content->Length()) {
- continue;
- }
- } else if (content == endNode && !endOffset) {
- continue;
- }
- } else if (content->IsElement()) {
- // handle non-text leaf nodes here
- continue;
- }
-
- bool isSet = false;
- if (first) {
- if (mCSSEditUtils->IsCSSEditableProperty(content, &aProperty,
- aAttribute)) {
- // The HTML styles defined by aProperty/aAttribute have a CSS
- // equivalence in this implementation for node; let's check if it
- // carries those CSS styles
- if (aValue) {
- firstValue.Assign(*aValue);
- }
- isSet = mCSSEditUtils->IsCSSEquivalentToHTMLInlineStyleSet(content,
- &aProperty, aAttribute, firstValue, CSSEditUtils::eComputed);
- } else {
- isSet = IsTextPropertySetByContent(content, &aProperty, aAttribute,
- aValue, &firstValue);
- }
- *aFirst = isSet;
- first = false;
- if (outValue) {
- *outValue = firstValue;
- }
- } else {
- if (mCSSEditUtils->IsCSSEditableProperty(content, &aProperty,
- aAttribute)) {
- // The HTML styles defined by aProperty/aAttribute have a CSS
- // equivalence in this implementation for node; let's check if it
- // carries those CSS styles
- if (aValue) {
- theValue.Assign(*aValue);
- }
- isSet = mCSSEditUtils->IsCSSEquivalentToHTMLInlineStyleSet(content,
- &aProperty, aAttribute, theValue, CSSEditUtils::eComputed);
- } else {
- isSet = IsTextPropertySetByContent(content, &aProperty, aAttribute,
- aValue, &theValue);
- }
- if (firstValue != theValue) {
- *aAll = false;
- }
- }
-
- if (isSet) {
- *aAny = true;
- } else {
- *aAll = false;
- }
- }
- }
- if (!*aAny) {
- // make sure that if none of the selection is set, we don't report all is
- // set
- *aAll = false;
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetInlineProperty(nsIAtom* aProperty,
- const nsAString& aAttribute,
- const nsAString& aValue,
- bool* aFirst,
- bool* aAny,
- bool* aAll)
-{
- NS_ENSURE_TRUE(aProperty && aFirst && aAny && aAll, NS_ERROR_NULL_POINTER);
- const nsAString *att = nullptr;
- if (!aAttribute.IsEmpty())
- att = &aAttribute;
- const nsAString *val = nullptr;
- if (!aValue.IsEmpty())
- val = &aValue;
- return GetInlinePropertyBase(*aProperty, att, val, aFirst, aAny, aAll, nullptr);
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetInlinePropertyWithAttrValue(nsIAtom* aProperty,
- const nsAString& aAttribute,
- const nsAString& aValue,
- bool* aFirst,
- bool* aAny,
- bool* aAll,
- nsAString& outValue)
-{
- NS_ENSURE_TRUE(aProperty && aFirst && aAny && aAll, NS_ERROR_NULL_POINTER);
- const nsAString *att = nullptr;
- if (!aAttribute.IsEmpty())
- att = &aAttribute;
- const nsAString *val = nullptr;
- if (!aValue.IsEmpty())
- val = &aValue;
- return GetInlinePropertyBase(*aProperty, att, val, aFirst, aAny, aAll, &outValue);
-}
-
-NS_IMETHODIMP
-HTMLEditor::RemoveAllInlineProperties()
-{
- AutoEditBatch batchIt(this);
- AutoRules beginRulesSniffing(this, EditAction::resetTextProperties,
- nsIEditor::eNext);
-
- nsresult rv = RemoveInlinePropertyImpl(nullptr, nullptr);
- NS_ENSURE_SUCCESS(rv, rv);
- return ApplyDefaultProperties();
-}
-
-NS_IMETHODIMP
-HTMLEditor::RemoveInlineProperty(nsIAtom* aProperty,
- const nsAString& aAttribute)
-{
- return RemoveInlinePropertyImpl(aProperty, &aAttribute);
-}
-
-nsresult
-HTMLEditor::RemoveInlinePropertyImpl(nsIAtom* aProperty,
- const nsAString* aAttribute)
-{
- MOZ_ASSERT_IF(aProperty, aAttribute);
- NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
- ForceCompositionEnd();
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- if (selection->Collapsed()) {
- // Manipulating text attributes on a collapsed selection only sets state
- // for the next text insertion
-
- // For links, aProperty uses "href", use "a" instead
- if (aProperty == nsGkAtoms::href || aProperty == nsGkAtoms::name) {
- aProperty = nsGkAtoms::a;
- }
-
- if (aProperty) {
- mTypeInState->ClearProp(aProperty, *aAttribute);
- } else {
- mTypeInState->ClearAllProps();
- }
- return NS_OK;
- }
-
- AutoEditBatch batchIt(this);
- AutoRules beginRulesSniffing(this, EditAction::removeTextProperty,
- nsIEditor::eNext);
- AutoSelectionRestorer selectionRestorer(selection, this);
- AutoTransactionsConserveSelection dontSpazMySelection(this);
-
- bool cancel, handled;
- TextRulesInfo ruleInfo(EditAction::removeTextProperty);
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!cancel && !handled) {
- // Loop through the ranges in the selection
- uint32_t rangeCount = selection->RangeCount();
- // Since ranges might be modified by SplitStyleAboveRange, we need hold
- // current ranges
- AutoTArray<OwningNonNull<nsRange>, 8> arrayOfRanges;
- for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
- arrayOfRanges.AppendElement(*selection->GetRangeAt(rangeIdx));
- }
- for (auto& range : arrayOfRanges) {
- if (aProperty == nsGkAtoms::name) {
- // Promote range if it starts or end in a named anchor and we want to
- // remove named anchors
- rv = PromoteRangeIfStartsOrEndsInNamedAnchor(range);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- // Adjust range to include any ancestors whose children are entirely
- // selected
- rv = PromoteInlineRange(range);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
-
- // Remove this style from ancestors of our range endpoints, splitting
- // them as appropriate
- rv = SplitStyleAboveRange(range, aProperty, aAttribute);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Check for easy case: both range endpoints in same text node
- nsCOMPtr<nsINode> startNode = range->GetStartParent();
- nsCOMPtr<nsINode> endNode = range->GetEndParent();
- if (startNode && startNode == endNode && startNode->GetAsText()) {
- // We're done with this range!
- if (IsCSSEnabled() &&
- mCSSEditUtils->IsCSSEditableProperty(startNode, aProperty,
- aAttribute)) {
- // The HTML style defined by aProperty/aAttribute has a CSS
- // equivalence in this implementation for startNode
- if (mCSSEditUtils->IsCSSEquivalentToHTMLInlineStyleSet(startNode,
- aProperty, aAttribute, EmptyString(),
- CSSEditUtils::eComputed)) {
- // startNode's computed style indicates the CSS equivalence to the
- // HTML style to remove is applied; but we found no element in the
- // ancestors of startNode carrying specified styles; assume it
- // comes from a rule and try to insert a span "inverting" the style
- if (mCSSEditUtils->IsCSSInvertible(*aProperty, aAttribute)) {
- NS_NAMED_LITERAL_STRING(value, "-moz-editor-invert-value");
- SetInlinePropertyOnTextNode(*startNode->GetAsText(),
- range->StartOffset(),
- range->EndOffset(), *aProperty,
- aAttribute, value);
- }
- }
- }
- } else {
- // Not the easy case. Range not contained in single text node.
- nsCOMPtr<nsIContentIterator> iter = NS_NewContentSubtreeIterator();
-
- nsTArray<OwningNonNull<nsIContent>> arrayOfNodes;
-
- // Iterate range and build up array
- for (iter->Init(range); !iter->IsDone(); iter->Next()) {
- nsCOMPtr<nsINode> node = iter->GetCurrentNode();
- NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
-
- if (IsEditable(node) && node->IsContent()) {
- arrayOfNodes.AppendElement(*node->AsContent());
- }
- }
-
- // Loop through the list, remove the property on each node
- for (auto& node : arrayOfNodes) {
- rv = RemoveStyleInside(node, aProperty, aAttribute);
- NS_ENSURE_SUCCESS(rv, rv);
- if (IsCSSEnabled() &&
- mCSSEditUtils->IsCSSEditableProperty(node, aProperty,
- aAttribute) &&
- mCSSEditUtils->IsCSSEquivalentToHTMLInlineStyleSet(node,
- aProperty, aAttribute, EmptyString(),
- CSSEditUtils::eComputed) &&
- // startNode's computed style indicates the CSS equivalence to
- // the HTML style to remove is applied; but we found no element
- // in the ancestors of startNode carrying specified styles;
- // assume it comes from a rule and let's try to insert a span
- // "inverting" the style
- mCSSEditUtils->IsCSSInvertible(*aProperty, aAttribute)) {
- NS_NAMED_LITERAL_STRING(value, "-moz-editor-invert-value");
- SetInlinePropertyOnNode(node, *aProperty, aAttribute, value);
- }
- }
- }
- }
- }
- if (!cancel) {
- // Post-process
- rv = rules->DidDoAction(selection, &ruleInfo, rv);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::IncreaseFontSize()
-{
- return RelativeFontChange(FontSize::incr);
-}
-
-NS_IMETHODIMP
-HTMLEditor::DecreaseFontSize()
-{
- return RelativeFontChange(FontSize::decr);
-}
-
-nsresult
-HTMLEditor::RelativeFontChange(FontSize aDir)
-{
- ForceCompositionEnd();
-
- // Get the selection
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
- // If selection is collapsed, set typing state
- if (selection->Collapsed()) {
- nsIAtom& atom = aDir == FontSize::incr ? *nsGkAtoms::big :
- *nsGkAtoms::small;
-
- // Let's see in what kind of element the selection is
- NS_ENSURE_TRUE(selection->RangeCount() &&
- selection->GetRangeAt(0)->GetStartParent(), NS_OK);
- OwningNonNull<nsINode> selectedNode =
- *selection->GetRangeAt(0)->GetStartParent();
- if (IsTextNode(selectedNode)) {
- NS_ENSURE_TRUE(selectedNode->GetParentNode(), NS_OK);
- selectedNode = *selectedNode->GetParentNode();
- }
- if (!CanContainTag(selectedNode, atom)) {
- return NS_OK;
- }
-
- // Manipulating text attributes on a collapsed selection only sets state
- // for the next text insertion
- mTypeInState->SetProp(&atom, EmptyString(), EmptyString());
- return NS_OK;
- }
-
- // Wrap with txn batching, rules sniffing, and selection preservation code
- AutoEditBatch batchIt(this);
- AutoRules beginRulesSniffing(this, EditAction::setTextProperty,
- nsIEditor::eNext);
- AutoSelectionRestorer selectionRestorer(selection, this);
- AutoTransactionsConserveSelection dontSpazMySelection(this);
-
- // Loop through the ranges in the selection
- uint32_t rangeCount = selection->RangeCount();
- for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
- RefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
-
- // Adjust range to include any ancestors with entirely selected children
- nsresult rv = PromoteInlineRange(*range);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Check for easy case: both range endpoints in same text node
- nsCOMPtr<nsINode> startNode = range->GetStartParent();
- nsCOMPtr<nsINode> endNode = range->GetEndParent();
- if (startNode == endNode && IsTextNode(startNode)) {
- rv = RelativeFontChangeOnTextNode(aDir, *startNode->GetAsText(),
- range->StartOffset(),
- range->EndOffset());
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // Not the easy case. Range not contained in single text node. There
- // are up to three phases here. There are all the nodes reported by the
- // subtree iterator to be processed. And there are potentially a
- // starting textnode and an ending textnode which are only partially
- // contained by the range.
-
- // Let's handle the nodes reported by the iterator. These nodes are
- // entirely contained in the selection range. We build up a list of them
- // (since doing operations on the document during iteration would perturb
- // the iterator).
-
- OwningNonNull<nsIContentIterator> iter = NS_NewContentSubtreeIterator();
-
- // Iterate range and build up array
- rv = iter->Init(range);
- if (NS_SUCCEEDED(rv)) {
- nsTArray<OwningNonNull<nsIContent>> arrayOfNodes;
- for (; !iter->IsDone(); iter->Next()) {
- NS_ENSURE_TRUE(iter->GetCurrentNode()->IsContent(), NS_ERROR_FAILURE);
- OwningNonNull<nsIContent> node = *iter->GetCurrentNode()->AsContent();
-
- if (IsEditable(node)) {
- arrayOfNodes.AppendElement(node);
- }
- }
-
- // Now that we have the list, do the font size change on each node
- for (auto& node : arrayOfNodes) {
- rv = RelativeFontChangeOnNode(aDir == FontSize::incr ? +1 : -1, node);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- // Now check the start and end parents of the range to see if they need
- // to be separately handled (they do if they are text nodes, due to how
- // the subtree iterator works - it will not have reported them).
- if (IsTextNode(startNode) && IsEditable(startNode)) {
- rv = RelativeFontChangeOnTextNode(aDir, *startNode->GetAsText(),
- range->StartOffset(),
- startNode->Length());
- NS_ENSURE_SUCCESS(rv, rv);
- }
- if (IsTextNode(endNode) && IsEditable(endNode)) {
- rv = RelativeFontChangeOnTextNode(aDir, *endNode->GetAsText(), 0,
- range->EndOffset());
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- }
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::RelativeFontChangeOnTextNode(FontSize aDir,
- Text& aTextNode,
- int32_t aStartOffset,
- int32_t aEndOffset)
-{
- // Don't need to do anything if no characters actually selected
- if (aStartOffset == aEndOffset) {
- return NS_OK;
- }
-
- if (!aTextNode.GetParentNode() ||
- !CanContainTag(*aTextNode.GetParentNode(), *nsGkAtoms::big)) {
- return NS_OK;
- }
-
- OwningNonNull<nsIContent> node = aTextNode;
-
- // Do we need to split the text node?
-
- // -1 is a magic value meaning to the end of node
- if (aEndOffset == -1) {
- aEndOffset = aTextNode.Length();
- }
-
- ErrorResult rv;
- if ((uint32_t)aEndOffset != aTextNode.Length()) {
- // We need to split off back of text node
- node = SplitNode(node, aEndOffset, rv);
- NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult());
- }
- if (aStartOffset) {
- // We need to split off front of text node
- SplitNode(node, aStartOffset, rv);
- NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult());
- }
-
- // Look for siblings that are correct type of node
- nsIAtom* nodeType = aDir == FontSize::incr ? nsGkAtoms::big
- : nsGkAtoms::small;
- nsCOMPtr<nsIContent> sibling = GetPriorHTMLSibling(node);
- if (sibling && sibling->IsHTMLElement(nodeType)) {
- // Previous sib is already right kind of inline node; slide this over
- nsresult rv = MoveNode(node, sibling, -1);
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
- }
- sibling = GetNextHTMLSibling(node);
- if (sibling && sibling->IsHTMLElement(nodeType)) {
- // Following sib is already right kind of inline node; slide this over
- nsresult rv = MoveNode(node, sibling, 0);
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
- }
-
- // Else reparent the node inside font node with appropriate relative size
- nsCOMPtr<Element> newElement = InsertContainerAbove(node, nodeType);
- NS_ENSURE_STATE(newElement);
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::RelativeFontChangeHelper(int32_t aSizeChange,
- nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
-
- /* This routine looks for all the font nodes in the tree rooted by aNode,
- including aNode itself, looking for font nodes that have the size attr
- set. Any such nodes need to have big or small put inside them, since
- they override any big/small that are above them.
- */
-
- // Can only change font size by + or - 1
- if (aSizeChange != 1 && aSizeChange != -1) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
-
- // If this is a font node with size, put big/small inside it.
- if (aNode->IsHTMLElement(nsGkAtoms::font) &&
- aNode->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::size)) {
- // Cycle through children and adjust relative font size.
- for (uint32_t i = aNode->GetChildCount(); i--; ) {
- nsresult rv = RelativeFontChangeOnNode(aSizeChange, aNode->GetChildAt(i));
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // RelativeFontChangeOnNode already calls us recursively,
- // so we don't need to check our children again.
- return NS_OK;
- }
-
- // Otherwise cycle through the children.
- for (uint32_t i = aNode->GetChildCount(); i--; ) {
- nsresult rv = RelativeFontChangeHelper(aSizeChange, aNode->GetChildAt(i));
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::RelativeFontChangeOnNode(int32_t aSizeChange,
- nsIContent* aNode)
-{
- MOZ_ASSERT(aNode);
- // Can only change font size by + or - 1
- if (aSizeChange != 1 && aSizeChange != -1) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
-
- nsIAtom* atom;
- if (aSizeChange == 1) {
- atom = nsGkAtoms::big;
- } else {
- atom = nsGkAtoms::small;
- }
-
- // Is it the opposite of what we want?
- if ((aSizeChange == 1 && aNode->IsHTMLElement(nsGkAtoms::small)) ||
- (aSizeChange == -1 && aNode->IsHTMLElement(nsGkAtoms::big))) {
- // first populate any nested font tags that have the size attr set
- nsresult rv = RelativeFontChangeHelper(aSizeChange, aNode);
- NS_ENSURE_SUCCESS(rv, rv);
- // in that case, just remove this node and pull up the children
- return RemoveContainer(aNode);
- }
-
- // can it be put inside a "big" or "small"?
- if (TagCanContain(*atom, *aNode)) {
- // first populate any nested font tags that have the size attr set
- nsresult rv = RelativeFontChangeHelper(aSizeChange, aNode);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // ok, chuck it in.
- // first look at siblings of aNode for matching bigs or smalls.
- // if we find one, move aNode into it.
- nsIContent* sibling = GetPriorHTMLSibling(aNode);
- if (sibling && sibling->IsHTMLElement(atom)) {
- // previous sib is already right kind of inline node; slide this over into it
- return MoveNode(aNode, sibling, -1);
- }
-
- sibling = GetNextHTMLSibling(aNode);
- if (sibling && sibling->IsHTMLElement(atom)) {
- // following sib is already right kind of inline node; slide this over into it
- return MoveNode(aNode, sibling, 0);
- }
-
- // else insert it above aNode
- nsCOMPtr<Element> newElement = InsertContainerAbove(aNode, atom);
- NS_ENSURE_STATE(newElement);
-
- return NS_OK;
- }
-
- // none of the above? then cycle through the children.
- // MOOSE: we should group the children together if possible
- // into a single "big" or "small". For the moment they are
- // each getting their own.
- for (uint32_t i = aNode->GetChildCount(); i--; ) {
- nsresult rv = RelativeFontChangeOnNode(aSizeChange, aNode->GetChildAt(i));
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetFontFaceState(bool* aMixed,
- nsAString& outFace)
-{
- NS_ENSURE_TRUE(aMixed, NS_ERROR_FAILURE);
- *aMixed = true;
- outFace.Truncate();
-
- bool first, any, all;
-
- NS_NAMED_LITERAL_STRING(attr, "face");
- nsresult rv =
- GetInlinePropertyBase(*nsGkAtoms::font, &attr, nullptr, &first, &any,
- &all, &outFace);
- NS_ENSURE_SUCCESS(rv, rv);
- if (any && !all) {
- return NS_OK; // mixed
- }
- if (all) {
- *aMixed = false;
- return NS_OK;
- }
-
- // if there is no font face, check for tt
- rv = GetInlinePropertyBase(*nsGkAtoms::tt, nullptr, nullptr, &first, &any,
- &all,nullptr);
- NS_ENSURE_SUCCESS(rv, rv);
- if (any && !all) {
- return rv; // mixed
- }
- if (all) {
- *aMixed = false;
- outFace.AssignLiteral("tt");
- }
-
- if (!any) {
- // there was no font face attrs of any kind. We are in normal font.
- outFace.Truncate();
- *aMixed = false;
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetFontColorState(bool* aMixed,
- nsAString& aOutColor)
-{
- NS_ENSURE_TRUE(aMixed, NS_ERROR_NULL_POINTER);
- *aMixed = true;
- aOutColor.Truncate();
-
- NS_NAMED_LITERAL_STRING(colorStr, "color");
- bool first, any, all;
-
- nsresult rv =
- GetInlinePropertyBase(*nsGkAtoms::font, &colorStr, nullptr, &first,
- &any, &all, &aOutColor);
- NS_ENSURE_SUCCESS(rv, rv);
- if (any && !all) {
- return NS_OK; // mixed
- }
- if (all) {
- *aMixed = false;
- return NS_OK;
- }
-
- if (!any) {
- // there was no font color attrs of any kind..
- aOutColor.Truncate();
- *aMixed = false;
- }
- return NS_OK;
-}
-
-// the return value is true only if the instance of the HTML editor we created
-// can handle CSS styles (for instance, Composer can, Messenger can't) and if
-// the CSS preference is checked
-nsresult
-HTMLEditor::GetIsCSSEnabled(bool* aIsCSSEnabled)
-{
- *aIsCSSEnabled = IsCSSEnabled();
- return NS_OK;
-}
-
-static bool
-HasNonEmptyAttribute(Element* aElement,
- nsIAtom* aName)
-{
- MOZ_ASSERT(aElement);
-
- nsAutoString value;
- return aElement->GetAttr(kNameSpaceID_None, aName, value) && !value.IsEmpty();
-}
-
-bool
-HTMLEditor::HasStyleOrIdOrClass(Element* aElement)
-{
- MOZ_ASSERT(aElement);
-
- // remove the node if its style attribute is empty or absent,
- // and if it does not have a class nor an id
- return HasNonEmptyAttribute(aElement, nsGkAtoms::style) ||
- HasNonEmptyAttribute(aElement, nsGkAtoms::_class) ||
- HasNonEmptyAttribute(aElement, nsGkAtoms::id);
-}
-
-nsresult
-HTMLEditor::RemoveElementIfNoStyleOrIdOrClass(Element& aElement)
-{
- // early way out if node is not the right kind of element
- if ((!aElement.IsHTMLElement(nsGkAtoms::span) &&
- !aElement.IsHTMLElement(nsGkAtoms::font)) ||
- HasStyleOrIdOrClass(&aElement)) {
- return NS_OK;
- }
-
- return RemoveContainer(&aElement);
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/HTMLTableEditor.cpp b/editor/libeditor/HTMLTableEditor.cpp
deleted file mode 100644
index b26466179..000000000
--- a/editor/libeditor/HTMLTableEditor.cpp
+++ /dev/null
@@ -1,3452 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <stdio.h>
-
-#include "mozilla/HTMLEditor.h"
-
-#include "HTMLEditUtils.h"
-#include "mozilla/Assertions.h"
-#include "mozilla/EditorUtils.h"
-#include "mozilla/dom/Selection.h"
-#include "mozilla/dom/Element.h"
-#include "nsAString.h"
-#include "nsAlgorithm.h"
-#include "nsCOMPtr.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsGkAtoms.h"
-#include "nsIAtom.h"
-#include "nsIContent.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMNode.h"
-#include "nsIEditor.h"
-#include "nsIFrame.h"
-#include "nsINode.h"
-#include "nsIPresShell.h"
-#include "nsISupportsUtils.h"
-#include "nsITableCellLayout.h" // For efficient access to table cell
-#include "nsITableEditor.h"
-#include "nsLiteralString.h"
-#include "nsQueryFrame.h"
-#include "nsRange.h"
-#include "nsString.h"
-#include "nsTArray.h"
-#include "nsTableCellFrame.h"
-#include "nsTableWrapperFrame.h"
-#include "nscore.h"
-#include <algorithm>
-
-namespace mozilla {
-
-using namespace dom;
-
-/**
- * Stack based helper class for restoring selection after table edit.
- */
-class MOZ_STACK_CLASS AutoSelectionSetterAfterTableEdit final
-{
-private:
- nsCOMPtr<nsITableEditor> mTableEditor;
- nsCOMPtr<nsIDOMElement> mTable;
- int32_t mCol, mRow, mDirection, mSelected;
-
-public:
- AutoSelectionSetterAfterTableEdit(nsITableEditor* aTableEditor,
- nsIDOMElement* aTable,
- int32_t aRow,
- int32_t aCol,
- int32_t aDirection,
- bool aSelected)
- : mTableEditor(aTableEditor)
- , mTable(aTable)
- , mCol(aCol)
- , mRow(aRow)
- , mDirection(aDirection)
- , mSelected(aSelected)
- {
- }
-
- ~AutoSelectionSetterAfterTableEdit()
- {
- if (mTableEditor) {
- mTableEditor->SetSelectionAfterTableEdit(mTable, mRow, mCol, mDirection,
- mSelected);
- }
- }
-
- // This is needed to abort the caret reset in the destructor
- // when one method yields control to another
- void CancelSetCaret()
- {
- mTableEditor = nullptr;
- mTable = nullptr;
- }
-};
-
-NS_IMETHODIMP
-HTMLEditor::InsertCell(nsIDOMElement* aCell,
- int32_t aRowSpan,
- int32_t aColSpan,
- bool aAfter,
- bool aIsHeader,
- nsIDOMElement** aNewCell)
-{
- NS_ENSURE_TRUE(aCell, NS_ERROR_NULL_POINTER);
- if (aNewCell) {
- *aNewCell = nullptr;
- }
-
- // And the parent and offsets needed to do an insert
- nsCOMPtr<nsIDOMNode> cellParent;
- nsresult rv = aCell->GetParentNode(getter_AddRefs(cellParent));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(cellParent, NS_ERROR_NULL_POINTER);
-
- int32_t cellOffset = GetChildOffset(aCell, cellParent);
-
- nsCOMPtr<nsIDOMElement> newCell;
- rv = CreateElementWithDefaults(aIsHeader ? NS_LITERAL_STRING("th") :
- NS_LITERAL_STRING("tb"),
- getter_AddRefs(newCell));
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (!newCell) {
- return NS_ERROR_FAILURE;
- }
-
- //Optional: return new cell created
- if (aNewCell) {
- *aNewCell = newCell.get();
- NS_ADDREF(*aNewCell);
- }
-
- if (aRowSpan > 1) {
- // Note: Do NOT use editor transaction for this
- nsAutoString newRowSpan;
- newRowSpan.AppendInt(aRowSpan, 10);
- newCell->SetAttribute(NS_LITERAL_STRING("rowspan"), newRowSpan);
- }
- if (aColSpan > 1) {
- // Note: Do NOT use editor transaction for this
- nsAutoString newColSpan;
- newColSpan.AppendInt(aColSpan, 10);
- newCell->SetAttribute(NS_LITERAL_STRING("colspan"), newColSpan);
- }
- if (aAfter) {
- cellOffset++;
- }
-
- //Don't let Rules System change the selection
- AutoTransactionsConserveSelection dontChangeSelection(this);
- return InsertNode(newCell, cellParent, cellOffset);
-}
-
-NS_IMETHODIMP
-HTMLEditor::SetColSpan(nsIDOMElement* aCell,
- int32_t aColSpan)
-{
- NS_ENSURE_TRUE(aCell, NS_ERROR_NULL_POINTER);
- nsAutoString newSpan;
- newSpan.AppendInt(aColSpan, 10);
- return SetAttribute(aCell, NS_LITERAL_STRING("colspan"), newSpan);
-}
-
-NS_IMETHODIMP
-HTMLEditor::SetRowSpan(nsIDOMElement* aCell,
- int32_t aRowSpan)
-{
- NS_ENSURE_TRUE(aCell, NS_ERROR_NULL_POINTER);
- nsAutoString newSpan;
- newSpan.AppendInt(aRowSpan, 10);
- return SetAttribute(aCell, NS_LITERAL_STRING("rowspan"), newSpan);
-}
-
-NS_IMETHODIMP
-HTMLEditor::InsertTableCell(int32_t aNumber,
- bool aAfter)
-{
- nsCOMPtr<nsIDOMElement> table;
- nsCOMPtr<nsIDOMElement> curCell;
- nsCOMPtr<nsIDOMNode> cellParent;
- int32_t cellOffset, startRowIndex, startColIndex;
- nsresult rv = GetCellContext(nullptr,
- getter_AddRefs(table),
- getter_AddRefs(curCell),
- getter_AddRefs(cellParent), &cellOffset,
- &startRowIndex, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- // Don't fail if no cell found
- NS_ENSURE_TRUE(curCell, NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND);
-
- // Get more data for current cell in row we are inserting at (we need COLSPAN)
- int32_t curStartRowIndex, curStartColIndex, rowSpan, colSpan, actualRowSpan, actualColSpan;
- bool isSelected;
- rv = GetCellDataAt(table, startRowIndex, startColIndex,
- getter_AddRefs(curCell),
- &curStartRowIndex, &curStartColIndex, &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(curCell, NS_ERROR_FAILURE);
- int32_t newCellIndex = aAfter ? (startColIndex+colSpan) : startColIndex;
- //We control selection resetting after the insert...
- AutoSelectionSetterAfterTableEdit setCaret(this, table, startRowIndex,
- newCellIndex, ePreviousColumn,
- false);
- //...so suppress Rules System selection munging
- AutoTransactionsConserveSelection dontChangeSelection(this);
-
- for (int32_t i = 0; i < aNumber; i++) {
- nsCOMPtr<nsIDOMElement> newCell;
- rv = CreateElementWithDefaults(NS_LITERAL_STRING("td"),
- getter_AddRefs(newCell));
- if (NS_SUCCEEDED(rv) && newCell) {
- if (aAfter) {
- cellOffset++;
- }
- rv = InsertNode(newCell, cellParent, cellOffset);
- if (NS_FAILED(rv)) {
- break;
- }
- }
- }
- // XXX This is perhaps the result of the last call of InsertNode() or
- // CreateElementWithDefaults().
- return rv;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetFirstRow(nsIDOMElement* aTableElement,
- nsIDOMNode** aRowNode)
-{
- NS_ENSURE_TRUE(aRowNode, NS_ERROR_NULL_POINTER);
-
- *aRowNode = nullptr;
-
- NS_ENSURE_TRUE(aTableElement, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsIDOMElement> tableElement;
- nsresult rv = GetElementOrParentByTagName(NS_LITERAL_STRING("table"),
- aTableElement,
- getter_AddRefs(tableElement));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(tableElement, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsIDOMNode> tableChild;
- rv = tableElement->GetFirstChild(getter_AddRefs(tableChild));
- NS_ENSURE_SUCCESS(rv, rv);
-
- while (tableChild) {
- nsCOMPtr<nsIContent> content = do_QueryInterface(tableChild);
- if (content) {
- if (content->IsHTMLElement(nsGkAtoms::tr)) {
- // Found a row directly under <table>
- *aRowNode = tableChild;
- NS_ADDREF(*aRowNode);
- return NS_OK;
- }
- // Look for row in one of the row container elements
- if (content->IsAnyOfHTMLElements(nsGkAtoms::tbody,
- nsGkAtoms::thead,
- nsGkAtoms::tfoot)) {
- nsCOMPtr<nsIDOMNode> rowNode;
- rv = tableChild->GetFirstChild(getter_AddRefs(rowNode));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // We can encounter textnodes here -- must find a row
- while (rowNode && !HTMLEditUtils::IsTableRow(rowNode)) {
- nsCOMPtr<nsIDOMNode> nextNode;
- rv = rowNode->GetNextSibling(getter_AddRefs(nextNode));
- NS_ENSURE_SUCCESS(rv, rv);
-
- rowNode = nextNode;
- }
- if (rowNode) {
- *aRowNode = rowNode.get();
- NS_ADDREF(*aRowNode);
- return NS_OK;
- }
- }
- }
- // Here if table child was a CAPTION or COLGROUP
- // or child of a row parent wasn't a row (bad HTML?),
- // or first child was a textnode
- // Look in next table child
- nsCOMPtr<nsIDOMNode> nextChild;
- rv = tableChild->GetNextSibling(getter_AddRefs(nextChild));
- NS_ENSURE_SUCCESS(rv, rv);
-
- tableChild = nextChild;
- }
- // If here, row was not found
- return NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetNextRow(nsIDOMNode* aCurrentRowNode,
- nsIDOMNode** aRowNode)
-{
- NS_ENSURE_TRUE(aRowNode, NS_ERROR_NULL_POINTER);
-
- *aRowNode = nullptr;
-
- NS_ENSURE_TRUE(aCurrentRowNode, NS_ERROR_NULL_POINTER);
-
- if (!HTMLEditUtils::IsTableRow(aCurrentRowNode)) {
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsIDOMNode> nextRow;
- nsresult rv = aCurrentRowNode->GetNextSibling(getter_AddRefs(nextRow));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIDOMNode> nextNode;
-
- // Skip over any textnodes here
- while (nextRow && !HTMLEditUtils::IsTableRow(nextRow)) {
- rv = nextRow->GetNextSibling(getter_AddRefs(nextNode));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nextRow = nextNode;
- }
- if (nextRow) {
- *aRowNode = nextRow.get();
- NS_ADDREF(*aRowNode);
- return NS_OK;
- }
-
- // No row found, search for rows in other table sections
- nsCOMPtr<nsIDOMNode> rowParent;
- rv = aCurrentRowNode->GetParentNode(getter_AddRefs(rowParent));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(rowParent, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsIDOMNode> parentSibling;
- rv = rowParent->GetNextSibling(getter_AddRefs(parentSibling));
- NS_ENSURE_SUCCESS(rv, rv);
-
- while (parentSibling) {
- rv = parentSibling->GetFirstChild(getter_AddRefs(nextRow));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // We can encounter textnodes here -- must find a row
- while (nextRow && !HTMLEditUtils::IsTableRow(nextRow)) {
- rv = nextRow->GetNextSibling(getter_AddRefs(nextNode));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nextRow = nextNode;
- }
- if (nextRow) {
- *aRowNode = nextRow.get();
- NS_ADDREF(*aRowNode);
- return NS_OK;
- }
-
- // We arrive here only if a table section has no children
- // or first child of section is not a row (bad HTML or more "_moz_text" nodes!)
- // So look for another section sibling
- rv = parentSibling->GetNextSibling(getter_AddRefs(nextNode));
- NS_ENSURE_SUCCESS(rv, rv);
-
- parentSibling = nextNode;
- }
- // If here, row was not found
- return NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND;
-}
-
-nsresult
-HTMLEditor::GetLastCellInRow(nsIDOMNode* aRowNode,
- nsIDOMNode** aCellNode)
-{
- NS_ENSURE_TRUE(aCellNode, NS_ERROR_NULL_POINTER);
-
- *aCellNode = nullptr;
-
- NS_ENSURE_TRUE(aRowNode, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsIDOMNode> rowChild;
- nsresult rv = aRowNode->GetLastChild(getter_AddRefs(rowChild));
- NS_ENSURE_SUCCESS(rv, rv);
-
- while (rowChild && !HTMLEditUtils::IsTableCell(rowChild)) {
- // Skip over textnodes
- nsCOMPtr<nsIDOMNode> previousChild;
- rv = rowChild->GetPreviousSibling(getter_AddRefs(previousChild));
- NS_ENSURE_SUCCESS(rv, rv);
-
- rowChild = previousChild;
- }
- if (rowChild) {
- *aCellNode = rowChild.get();
- NS_ADDREF(*aCellNode);
- return NS_OK;
- }
- // If here, cell was not found
- return NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND;
-}
-
-NS_IMETHODIMP
-HTMLEditor::InsertTableColumn(int32_t aNumber,
- bool aAfter)
-{
- RefPtr<Selection> selection;
- nsCOMPtr<nsIDOMElement> table;
- nsCOMPtr<nsIDOMElement> curCell;
- int32_t startRowIndex, startColIndex;
- nsresult rv = GetCellContext(getter_AddRefs(selection),
- getter_AddRefs(table),
- getter_AddRefs(curCell),
- nullptr, nullptr,
- &startRowIndex, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- // Don't fail if no cell found
- NS_ENSURE_TRUE(curCell, NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND);
-
- // Get more data for current cell (we need ROWSPAN)
- int32_t curStartRowIndex, curStartColIndex, rowSpan, colSpan, actualRowSpan, actualColSpan;
- bool isSelected;
- rv = GetCellDataAt(table, startRowIndex, startColIndex,
- getter_AddRefs(curCell),
- &curStartRowIndex, &curStartColIndex,
- &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(curCell, NS_ERROR_FAILURE);
-
- AutoEditBatch beginBatching(this);
- // Prevent auto insertion of BR in new cell until we're done
- AutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext);
-
- // Use column after current cell if requested
- if (aAfter) {
- startColIndex += actualColSpan;
- //Detect when user is adding after a COLSPAN=0 case
- // Assume they want to stop the "0" behavior and
- // really add a new column. Thus we set the
- // colspan to its true value
- if (!colSpan) {
- SetColSpan(curCell, actualColSpan);
- }
- }
-
- int32_t rowCount, colCount, rowIndex;
- rv = GetTableSize(table, &rowCount, &colCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- //We reset caret in destructor...
- AutoSelectionSetterAfterTableEdit setCaret(this, table, startRowIndex,
- startColIndex, ePreviousRow,
- false);
- //.. so suppress Rules System selection munging
- AutoTransactionsConserveSelection dontChangeSelection(this);
-
- // If we are inserting after all existing columns
- // Make sure table is "well formed"
- // before appending new column
- if (startColIndex >= colCount) {
- NormalizeTable(table);
- }
-
- nsCOMPtr<nsIDOMNode> rowNode;
- for (rowIndex = 0; rowIndex < rowCount; rowIndex++) {
- if (startColIndex < colCount) {
- // We are inserting before an existing column
- rv = GetCellDataAt(table, rowIndex, startColIndex,
- getter_AddRefs(curCell),
- &curStartRowIndex, &curStartColIndex,
- &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Don't fail entire process if we fail to find a cell
- // (may fail just in particular rows with < adequate cells per row)
- if (curCell) {
- if (curStartColIndex < startColIndex) {
- // We have a cell spanning this location
- // Simply increase its colspan to keep table rectangular
- // Note: we do nothing if colsSpan=0,
- // since it should automatically span the new column
- if (colSpan > 0) {
- SetColSpan(curCell, colSpan+aNumber);
- }
- } else {
- // Simply set selection to the current cell
- // so we can let InsertTableCell() do the work
- // Insert a new cell before current one
- selection->Collapse(curCell, 0);
- rv = InsertTableCell(aNumber, false);
- }
- }
- } else {
- // Get current row and append new cells after last cell in row
- if (!rowIndex) {
- rv = GetFirstRow(table.get(), getter_AddRefs(rowNode));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- nsCOMPtr<nsIDOMNode> nextRow;
- rv = GetNextRow(rowNode.get(), getter_AddRefs(nextRow));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- rowNode = nextRow;
- }
-
- if (rowNode) {
- nsCOMPtr<nsIDOMNode> lastCell;
- rv = GetLastCellInRow(rowNode, getter_AddRefs(lastCell));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(lastCell, NS_ERROR_FAILURE);
-
- curCell = do_QueryInterface(lastCell);
- if (curCell) {
- // Simply add same number of cells to each row
- // Although tempted to check cell indexes for curCell,
- // the effects of COLSPAN>1 in some cells makes this futile!
- // We must use NormalizeTable first to assure
- // that there are cells in each cellmap location
- selection->Collapse(curCell, 0);
- rv = InsertTableCell(aNumber, true);
- }
- }
- }
- }
- // XXX This is perhaps the result of the last call of InsertTableCell().
- return rv;
-}
-
-NS_IMETHODIMP
-HTMLEditor::InsertTableRow(int32_t aNumber,
- bool aAfter)
-{
- nsCOMPtr<nsIDOMElement> table;
- nsCOMPtr<nsIDOMElement> curCell;
-
- int32_t startRowIndex, startColIndex;
- nsresult rv = GetCellContext(nullptr,
- getter_AddRefs(table),
- getter_AddRefs(curCell),
- nullptr, nullptr,
- &startRowIndex, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- // Don't fail if no cell found
- NS_ENSURE_TRUE(curCell, NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND);
-
- // Get more data for current cell in row we are inserting at (we need COLSPAN)
- int32_t curStartRowIndex, curStartColIndex, rowSpan, colSpan, actualRowSpan, actualColSpan;
- bool isSelected;
- rv = GetCellDataAt(table, startRowIndex, startColIndex,
- getter_AddRefs(curCell),
- &curStartRowIndex, &curStartColIndex,
- &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(curCell, NS_ERROR_FAILURE);
-
- int32_t rowCount, colCount;
- rv = GetTableSize(table, &rowCount, &colCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- AutoEditBatch beginBatching(this);
- // Prevent auto insertion of BR in new cell until we're done
- AutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext);
-
- if (aAfter) {
- // Use row after current cell
- startRowIndex += actualRowSpan;
-
- //Detect when user is adding after a ROWSPAN=0 case
- // Assume they want to stop the "0" behavior and
- // really add a new row. Thus we set the
- // rowspan to its true value
- if (!rowSpan) {
- SetRowSpan(curCell, actualRowSpan);
- }
- }
-
- //We control selection resetting after the insert...
- AutoSelectionSetterAfterTableEdit setCaret(this, table, startRowIndex,
- startColIndex, ePreviousColumn,
- false);
- //...so suppress Rules System selection munging
- AutoTransactionsConserveSelection dontChangeSelection(this);
-
- nsCOMPtr<nsIDOMElement> cellForRowParent;
- int32_t cellsInRow = 0;
- if (startRowIndex < rowCount) {
- // We are inserting above an existing row
- // Get each cell in the insert row to adjust for COLSPAN effects while we
- // count how many cells are needed
- int32_t colIndex = 0;
- while (NS_SUCCEEDED(GetCellDataAt(table, startRowIndex, colIndex,
- getter_AddRefs(curCell),
- &curStartRowIndex, &curStartColIndex,
- &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan,
- &isSelected))) {
- if (curCell) {
- if (curStartRowIndex < startRowIndex) {
- // We have a cell spanning this location
- // Simply increase its rowspan
- //Note that if rowSpan == 0, we do nothing,
- // since that cell should automatically extend into the new row
- if (rowSpan > 0) {
- SetRowSpan(curCell, rowSpan+aNumber);
- }
- } else {
- // We have a cell in the insert row
-
- // Count the number of cells we need to add to the new row
- cellsInRow += actualColSpan;
-
- // Save cell we will use below
- if (!cellForRowParent) {
- cellForRowParent = curCell;
- }
- }
- // Next cell in row
- colIndex += actualColSpan;
- } else {
- colIndex++;
- }
- }
- } else {
- // We are adding a new row after all others
- // If it weren't for colspan=0 effect,
- // we could simply use colCount for number of new cells...
- // XXX colspan=0 support has now been removed in table layout so maybe this can be cleaned up now? (bug 1243183)
- cellsInRow = colCount;
-
- // ...but we must compensate for all cells with rowSpan = 0 in the last row
- int32_t lastRow = rowCount-1;
- int32_t tempColIndex = 0;
- while (NS_SUCCEEDED(GetCellDataAt(table, lastRow, tempColIndex,
- getter_AddRefs(curCell),
- &curStartRowIndex, &curStartColIndex,
- &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan,
- &isSelected))) {
- if (!rowSpan) {
- cellsInRow -= actualColSpan;
- }
-
- tempColIndex += actualColSpan;
-
- // Save cell from the last row that we will use below
- if (!cellForRowParent && curStartRowIndex == lastRow) {
- cellForRowParent = curCell;
- }
- }
- }
-
- if (cellsInRow > 0) {
- // The row parent and offset where we will insert new row
- nsCOMPtr<nsIDOMNode> parentOfRow;
- int32_t newRowOffset;
-
- NS_NAMED_LITERAL_STRING(trStr, "tr");
- if (!cellForRowParent) {
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsIDOMElement> parentRow;
- rv = GetElementOrParentByTagName(trStr, cellForRowParent,
- getter_AddRefs(parentRow));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(parentRow, NS_ERROR_NULL_POINTER);
-
- parentRow->GetParentNode(getter_AddRefs(parentOfRow));
- NS_ENSURE_TRUE(parentOfRow, NS_ERROR_NULL_POINTER);
-
- newRowOffset = GetChildOffset(parentRow, parentOfRow);
-
- // Adjust for when adding past the end
- if (aAfter && startRowIndex >= rowCount) {
- newRowOffset++;
- }
-
- for (int32_t row = 0; row < aNumber; row++) {
- // Create a new row
- nsCOMPtr<nsIDOMElement> newRow;
- rv = CreateElementWithDefaults(trStr, getter_AddRefs(newRow));
- if (NS_SUCCEEDED(rv)) {
- NS_ENSURE_TRUE(newRow, NS_ERROR_FAILURE);
-
- for (int32_t i = 0; i < cellsInRow; i++) {
- nsCOMPtr<nsIDOMElement> newCell;
- rv = CreateElementWithDefaults(NS_LITERAL_STRING("td"),
- getter_AddRefs(newCell));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(newCell, NS_ERROR_FAILURE);
-
- // Don't use transaction system yet! (not until entire row is inserted)
- nsCOMPtr<nsIDOMNode>resultNode;
- rv = newRow->AppendChild(newCell, getter_AddRefs(resultNode));
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // Use transaction system to insert the entire row+cells
- // (Note that rows are inserted at same childoffset each time)
- rv = InsertNode(newRow, parentOfRow, newRowOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- }
- // XXX This might be the result of the last call of
- // CreateElementWithDefaults(), otherwise, NS_OK.
- return rv;
-}
-
-// Editor helper only
-// XXX Code changed for bug 217717 and now we don't need aSelection param
-// TODO: Remove aSelection param
-nsresult
-HTMLEditor::DeleteTable2(nsIDOMElement* aTable,
- Selection* aSelection)
-{
- NS_ENSURE_TRUE(aTable, NS_ERROR_NULL_POINTER);
-
- // Select the table
- nsresult rv = ClearSelection();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- rv = AppendNodeToSelectionAsRange(aTable);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return DeleteSelection(nsIEditor::eNext, nsIEditor::eStrip);
-}
-
-NS_IMETHODIMP
-HTMLEditor::DeleteTable()
-{
- RefPtr<Selection> selection;
- nsCOMPtr<nsIDOMElement> table;
- nsresult rv = GetCellContext(getter_AddRefs(selection),
- getter_AddRefs(table),
- nullptr, nullptr, nullptr, nullptr, nullptr);
- NS_ENSURE_SUCCESS(rv, rv);
-
- AutoEditBatch beginBatching(this);
- return DeleteTable2(table, selection);
-}
-
-NS_IMETHODIMP
-HTMLEditor::DeleteTableCell(int32_t aNumber)
-{
- RefPtr<Selection> selection;
- nsCOMPtr<nsIDOMElement> table;
- nsCOMPtr<nsIDOMElement> cell;
- int32_t startRowIndex, startColIndex;
-
-
- nsresult rv = GetCellContext(getter_AddRefs(selection),
- getter_AddRefs(table),
- getter_AddRefs(cell),
- nullptr, nullptr,
- &startRowIndex, &startColIndex);
-
- NS_ENSURE_SUCCESS(rv, rv);
- // Don't fail if we didn't find a table or cell
- NS_ENSURE_TRUE(table && cell, NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND);
-
- AutoEditBatch beginBatching(this);
- // Prevent rules testing until we're done
- AutoRules beginRulesSniffing(this, EditAction::deleteNode, nsIEditor::eNext);
-
- nsCOMPtr<nsIDOMElement> firstCell;
- nsCOMPtr<nsIDOMRange> range;
- rv = GetFirstSelectedCell(getter_AddRefs(range), getter_AddRefs(firstCell));
- NS_ENSURE_SUCCESS(rv, rv);
-
- int32_t rangeCount;
- rv = selection->GetRangeCount(&rangeCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (firstCell && rangeCount > 1) {
- // When > 1 selected cell,
- // ignore aNumber and use selected cells
- cell = firstCell;
-
- int32_t rowCount, colCount;
- rv = GetTableSize(table, &rowCount, &colCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Get indexes -- may be different than original cell
- rv = GetCellIndexes(cell, &startRowIndex, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // The setCaret object will call AutoSelectionSetterAfterTableEdit in its
- // destructor
- AutoSelectionSetterAfterTableEdit setCaret(this, table, startRowIndex,
- startColIndex, ePreviousColumn,
- false);
- AutoTransactionsConserveSelection dontChangeSelection(this);
-
- bool checkToDeleteRow = true;
- bool checkToDeleteColumn = true;
- while (cell) {
- bool deleteRow = false;
- bool deleteCol = false;
-
- if (checkToDeleteRow) {
- // Optimize to delete an entire row
- // Clear so we don't repeat AllCellsInRowSelected within the same row
- checkToDeleteRow = false;
-
- deleteRow = AllCellsInRowSelected(table, startRowIndex, colCount);
- if (deleteRow) {
- // First, find the next cell in a different row
- // to continue after we delete this row
- int32_t nextRow = startRowIndex;
- while (nextRow == startRowIndex) {
- rv = GetNextSelectedCell(nullptr, getter_AddRefs(cell));
- NS_ENSURE_SUCCESS(rv, rv);
- if (!cell) {
- break;
- }
- rv = GetCellIndexes(cell, &nextRow, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // Delete entire row
- rv = DeleteRow(table, startRowIndex);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (cell) {
- // For the next cell: Subtract 1 for row we deleted
- startRowIndex = nextRow - 1;
- // Set true since we know we will look at a new row next
- checkToDeleteRow = true;
- }
- }
- }
- if (!deleteRow) {
- if (checkToDeleteColumn) {
- // Optimize to delete an entire column
- // Clear this so we don't repeat AllCellsInColSelected within the same Col
- checkToDeleteColumn = false;
-
- deleteCol = AllCellsInColumnSelected(table, startColIndex, colCount);
- if (deleteCol) {
- // First, find the next cell in a different column
- // to continue after we delete this column
- int32_t nextCol = startColIndex;
- while (nextCol == startColIndex) {
- rv = GetNextSelectedCell(nullptr, getter_AddRefs(cell));
- NS_ENSURE_SUCCESS(rv, rv);
- if (!cell) {
- break;
- }
- rv = GetCellIndexes(cell, &startRowIndex, &nextCol);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // Delete entire Col
- rv = DeleteColumn(table, startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- if (cell) {
- // For the next cell, subtract 1 for col. deleted
- startColIndex = nextCol - 1;
- // Set true since we know we will look at a new column next
- checkToDeleteColumn = true;
- }
- }
- }
- if (!deleteCol) {
- // First get the next cell to delete
- nsCOMPtr<nsIDOMElement> nextCell;
- rv = GetNextSelectedCell(getter_AddRefs(range),
- getter_AddRefs(nextCell));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Then delete the cell
- rv = DeleteNode(cell);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // The next cell to delete
- cell = nextCell;
- if (cell) {
- rv = GetCellIndexes(cell, &startRowIndex, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- }
- }
- } else {
- for (int32_t i = 0; i < aNumber; i++) {
- rv = GetCellContext(getter_AddRefs(selection),
- getter_AddRefs(table),
- getter_AddRefs(cell),
- nullptr, nullptr,
- &startRowIndex, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- // Don't fail if no cell found
- NS_ENSURE_TRUE(cell, NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND);
-
- if (GetNumberOfCellsInRow(table, startRowIndex) == 1) {
- nsCOMPtr<nsIDOMElement> parentRow;
- rv = GetElementOrParentByTagName(NS_LITERAL_STRING("tr"), cell,
- getter_AddRefs(parentRow));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(parentRow, NS_ERROR_NULL_POINTER);
-
- // We should delete the row instead,
- // but first check if its the only row left
- // so we can delete the entire table
- int32_t rowCount, colCount;
- rv = GetTableSize(table, &rowCount, &colCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (rowCount == 1) {
- return DeleteTable2(table, selection);
- }
-
- // We need to call DeleteTableRow to handle cells with rowspan
- rv = DeleteTableRow(1);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // More than 1 cell in the row
-
- // The setCaret object will call AutoSelectionSetterAfterTableEdit in its
- // destructor
- AutoSelectionSetterAfterTableEdit setCaret(this, table, startRowIndex,
- startColIndex, ePreviousColumn,
- false);
- AutoTransactionsConserveSelection dontChangeSelection(this);
-
- rv = DeleteNode(cell);
- // If we fail, don't try to delete any more cells???
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::DeleteTableCellContents()
-{
- RefPtr<Selection> selection;
- nsCOMPtr<nsIDOMElement> table;
- nsCOMPtr<nsIDOMElement> cell;
- int32_t startRowIndex, startColIndex;
- nsresult rv = GetCellContext(getter_AddRefs(selection),
- getter_AddRefs(table),
- getter_AddRefs(cell),
- nullptr, nullptr,
- &startRowIndex, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- // Don't fail if no cell found
- NS_ENSURE_TRUE(cell, NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND);
-
-
- AutoEditBatch beginBatching(this);
- // Prevent rules testing until we're done
- AutoRules beginRulesSniffing(this, EditAction::deleteNode, nsIEditor::eNext);
- //Don't let Rules System change the selection
- AutoTransactionsConserveSelection dontChangeSelection(this);
-
-
- nsCOMPtr<nsIDOMElement> firstCell;
- nsCOMPtr<nsIDOMRange> range;
- rv = GetFirstSelectedCell(getter_AddRefs(range), getter_AddRefs(firstCell));
- NS_ENSURE_SUCCESS(rv, rv);
-
-
- if (firstCell) {
- cell = firstCell;
- rv = GetCellIndexes(cell, &startRowIndex, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- AutoSelectionSetterAfterTableEdit setCaret(this, table, startRowIndex,
- startColIndex, ePreviousColumn,
- false);
-
- while (cell) {
- DeleteCellContents(cell);
- if (firstCell) {
- // We doing a selected cells, so do all of them
- rv = GetNextSelectedCell(nullptr, getter_AddRefs(cell));
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- cell = nullptr;
- }
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::DeleteCellContents(nsIDOMElement* aCell)
-{
- NS_ENSURE_TRUE(aCell, NS_ERROR_NULL_POINTER);
-
- // Prevent rules testing until we're done
- AutoRules beginRulesSniffing(this, EditAction::deleteNode, nsIEditor::eNext);
-
- nsCOMPtr<nsIDOMNode> child;
- bool hasChild;
- aCell->HasChildNodes(&hasChild);
-
- while (hasChild) {
- aCell->GetLastChild(getter_AddRefs(child));
- nsresult rv = DeleteNode(child);
- NS_ENSURE_SUCCESS(rv, rv);
- aCell->HasChildNodes(&hasChild);
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::DeleteTableColumn(int32_t aNumber)
-{
- RefPtr<Selection> selection;
- nsCOMPtr<nsIDOMElement> table;
- nsCOMPtr<nsIDOMElement> cell;
- int32_t startRowIndex, startColIndex, rowCount, colCount;
- nsresult rv = GetCellContext(getter_AddRefs(selection),
- getter_AddRefs(table),
- getter_AddRefs(cell),
- nullptr, nullptr,
- &startRowIndex, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- // Don't fail if no cell found
- NS_ENSURE_TRUE(table && cell, NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND);
-
- rv = GetTableSize(table, &rowCount, &colCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Shortcut the case of deleting all columns in table
- if (!startColIndex && aNumber >= colCount) {
- return DeleteTable2(table, selection);
- }
-
- // Check for counts too high
- aNumber = std::min(aNumber,(colCount-startColIndex));
-
- AutoEditBatch beginBatching(this);
- // Prevent rules testing until we're done
- AutoRules beginRulesSniffing(this, EditAction::deleteNode, nsIEditor::eNext);
-
- // Test if deletion is controlled by selected cells
- nsCOMPtr<nsIDOMElement> firstCell;
- nsCOMPtr<nsIDOMRange> range;
- rv = GetFirstSelectedCell(getter_AddRefs(range), getter_AddRefs(firstCell));
- NS_ENSURE_SUCCESS(rv, rv);
-
- int32_t rangeCount;
- rv = selection->GetRangeCount(&rangeCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (firstCell && rangeCount > 1) {
- // Fetch indexes again - may be different for selected cells
- rv = GetCellIndexes(firstCell, &startRowIndex, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- //We control selection resetting after the insert...
- AutoSelectionSetterAfterTableEdit setCaret(this, table, startRowIndex,
- startColIndex, ePreviousRow,
- false);
-
- if (firstCell && rangeCount > 1) {
- // Use selected cells to determine what rows to delete
- cell = firstCell;
-
- while (cell) {
- if (cell != firstCell) {
- rv = GetCellIndexes(cell, &startRowIndex, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // Find the next cell in a different column
- // to continue after we delete this column
- int32_t nextCol = startColIndex;
- while (nextCol == startColIndex) {
- rv = GetNextSelectedCell(getter_AddRefs(range), getter_AddRefs(cell));
- NS_ENSURE_SUCCESS(rv, rv);
- if (!cell) {
- break;
- }
- rv = GetCellIndexes(cell, &startRowIndex, &nextCol);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- rv = DeleteColumn(table, startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- } else {
- for (int32_t i = 0; i < aNumber; i++) {
- rv = DeleteColumn(table, startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::DeleteColumn(nsIDOMElement* aTable,
- int32_t aColIndex)
-{
- NS_ENSURE_TRUE(aTable, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsIDOMElement> cell;
- int32_t startRowIndex, startColIndex, rowSpan, colSpan, actualRowSpan, actualColSpan;
- bool isSelected;
- int32_t rowIndex = 0;
-
- do {
- nsresult rv =
- GetCellDataAt(aTable, rowIndex, aColIndex, getter_AddRefs(cell),
- &startRowIndex, &startColIndex, &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (cell) {
- // Find cells that don't start in column we are deleting
- if (startColIndex < aColIndex || colSpan > 1 || !colSpan) {
- // We have a cell spanning this location
- // Decrease its colspan to keep table rectangular,
- // but if colSpan=0, it will adjust automatically
- if (colSpan > 0) {
- NS_ASSERTION((colSpan > 1),"Bad COLSPAN in DeleteTableColumn");
- SetColSpan(cell, colSpan-1);
- }
- if (startColIndex == aColIndex) {
- // Cell is in column to be deleted, but must have colspan > 1,
- // so delete contents of cell instead of cell itself
- // (We must have reset colspan above)
- DeleteCellContents(cell);
- }
- // To next cell in column
- rowIndex += actualRowSpan;
- } else {
- // Delete the cell
- if (GetNumberOfCellsInRow(aTable, rowIndex) == 1) {
- // Only 1 cell in row - delete the row
- nsCOMPtr<nsIDOMElement> parentRow;
- rv = GetElementOrParentByTagName(NS_LITERAL_STRING("tr"), cell,
- getter_AddRefs(parentRow));
- NS_ENSURE_SUCCESS(rv, rv);
- if (!parentRow) {
- return NS_ERROR_NULL_POINTER;
- }
-
- // But first check if its the only row left
- // so we can delete the entire table
- // (This should never happen but it's the safe thing to do)
- int32_t rowCount, colCount;
- rv = GetTableSize(aTable, &rowCount, &colCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (rowCount == 1) {
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
- return DeleteTable2(aTable, selection);
- }
-
- // Delete the row by placing caret in cell we were to delete
- // We need to call DeleteTableRow to handle cells with rowspan
- rv = DeleteRow(aTable, startRowIndex);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Note that we don't incremenet rowIndex
- // since a row was deleted and "next"
- // row now has current rowIndex
- } else {
- // A more "normal" deletion
- rv = DeleteNode(cell);
- NS_ENSURE_SUCCESS(rv, rv);
-
- //Skip over any rows spanned by this cell
- rowIndex += actualRowSpan;
- }
- }
- }
- } while (cell);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::DeleteTableRow(int32_t aNumber)
-{
- RefPtr<Selection> selection;
- nsCOMPtr<nsIDOMElement> table;
- nsCOMPtr<nsIDOMElement> cell;
- int32_t startRowIndex, startColIndex;
- int32_t rowCount, colCount;
- nsresult rv = GetCellContext(getter_AddRefs(selection),
- getter_AddRefs(table),
- getter_AddRefs(cell),
- nullptr, nullptr,
- &startRowIndex, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- // Don't fail if no cell found
- NS_ENSURE_TRUE(cell, NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND);
-
- rv = GetTableSize(table, &rowCount, &colCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Shortcut the case of deleting all rows in table
- if (!startRowIndex && aNumber >= rowCount) {
- return DeleteTable2(table, selection);
- }
-
- AutoEditBatch beginBatching(this);
- // Prevent rules testing until we're done
- AutoRules beginRulesSniffing(this, EditAction::deleteNode, nsIEditor::eNext);
-
- nsCOMPtr<nsIDOMElement> firstCell;
- nsCOMPtr<nsIDOMRange> range;
- rv = GetFirstSelectedCell(getter_AddRefs(range), getter_AddRefs(firstCell));
- NS_ENSURE_SUCCESS(rv, rv);
-
- int32_t rangeCount;
- rv = selection->GetRangeCount(&rangeCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (firstCell && rangeCount > 1) {
- // Fetch indexes again - may be different for selected cells
- rv = GetCellIndexes(firstCell, &startRowIndex, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- //We control selection resetting after the insert...
- AutoSelectionSetterAfterTableEdit setCaret(this, table, startRowIndex,
- startColIndex, ePreviousRow,
- false);
- // Don't change selection during deletions
- AutoTransactionsConserveSelection dontChangeSelection(this);
-
- if (firstCell && rangeCount > 1) {
- // Use selected cells to determine what rows to delete
- cell = firstCell;
-
- while (cell) {
- if (cell != firstCell) {
- rv = GetCellIndexes(cell, &startRowIndex, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // Find the next cell in a different row
- // to continue after we delete this row
- int32_t nextRow = startRowIndex;
- while (nextRow == startRowIndex) {
- rv = GetNextSelectedCell(getter_AddRefs(range), getter_AddRefs(cell));
- NS_ENSURE_SUCCESS(rv, rv);
- if (!cell) break;
- rv = GetCellIndexes(cell, &nextRow, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // Delete entire row
- rv = DeleteRow(table, startRowIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- } else {
- // Check for counts too high
- aNumber = std::min(aNumber,(rowCount-startRowIndex));
- for (int32_t i = 0; i < aNumber; i++) {
- rv = DeleteRow(table, startRowIndex);
- // If failed in current row, try the next
- if (NS_FAILED(rv)) {
- startRowIndex++;
- }
-
- // Check if there's a cell in the "next" row
- rv = GetCellAt(table, startRowIndex, startColIndex, getter_AddRefs(cell));
- NS_ENSURE_SUCCESS(rv, rv);
- if (!cell) {
- break;
- }
- }
- }
- return NS_OK;
-}
-
-// Helper that doesn't batch or change the selection
-NS_IMETHODIMP
-HTMLEditor::DeleteRow(nsIDOMElement* aTable,
- int32_t aRowIndex)
-{
- NS_ENSURE_TRUE(aTable, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsIDOMElement> cell;
- nsCOMPtr<nsIDOMElement> cellInDeleteRow;
- int32_t startRowIndex, startColIndex, rowSpan, colSpan, actualRowSpan, actualColSpan;
- bool isSelected;
- int32_t colIndex = 0;
-
- // Prevent rules testing until we're done
- AutoRules beginRulesSniffing(this, EditAction::deleteNode, nsIEditor::eNext);
-
- // The list of cells we will change rowspan in
- // and the new rowspan values for each
- nsTArray<nsCOMPtr<nsIDOMElement> > spanCellList;
- nsTArray<int32_t> newSpanList;
-
- int32_t rowCount, colCount;
- nsresult rv = GetTableSize(aTable, &rowCount, &colCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Scan through cells in row to do rowspan adjustments
- // Note that after we delete row, startRowIndex will point to the
- // cells in the next row to be deleted
- do {
- if (aRowIndex >= rowCount || colIndex >= colCount) {
- break;
- }
-
- rv = GetCellDataAt(aTable, aRowIndex, colIndex, getter_AddRefs(cell),
- &startRowIndex, &startColIndex, &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
- // We don't fail if we don't find a cell, so this must be real bad
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- // Compensate for cells that don't start or extend below the row we are deleting
- if (cell) {
- if (startRowIndex < aRowIndex) {
- // Cell starts in row above us
- // Decrease its rowspan to keep table rectangular
- // but we don't need to do this if rowspan=0,
- // since it will automatically adjust
- if (rowSpan > 0) {
- // Build list of cells to change rowspan
- // We can't do it now since it upsets cell map,
- // so we will do it after deleting the row
- spanCellList.AppendElement(cell);
- newSpanList.AppendElement(std::max((aRowIndex - startRowIndex), actualRowSpan-1));
- }
- } else {
- if (rowSpan > 1) {
- // Cell spans below row to delete, so we must insert new cells to
- // keep rows below. Note that we test "rowSpan" so we don't do this
- // if rowSpan = 0 (automatic readjustment).
- int32_t aboveRowToInsertNewCellInto = aRowIndex - startRowIndex + 1;
- int32_t numOfRawSpanRemainingBelow = actualRowSpan - 1;
- rv = SplitCellIntoRows(aTable, startRowIndex, startColIndex,
- aboveRowToInsertNewCellInto,
- numOfRawSpanRemainingBelow, nullptr);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- if (!cellInDeleteRow) {
- cellInDeleteRow = cell; // Reference cell to find row to delete
- }
- }
- // Skip over other columns spanned by this cell
- colIndex += actualColSpan;
- }
- } while (cell);
-
- // Things are messed up if we didn't find a cell in the row!
- NS_ENSURE_TRUE(cellInDeleteRow, NS_ERROR_FAILURE);
-
- // Delete the entire row
- nsCOMPtr<nsIDOMElement> parentRow;
- rv = GetElementOrParentByTagName(NS_LITERAL_STRING("tr"), cellInDeleteRow,
- getter_AddRefs(parentRow));
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (parentRow) {
- rv = DeleteNode(parentRow);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // Now we can set new rowspans for cells stored above
- for (uint32_t i = 0, n = spanCellList.Length(); i < n; i++) {
- nsIDOMElement *cellPtr = spanCellList[i];
- if (cellPtr) {
- rv = SetRowSpan(cellPtr, newSpanList[i]);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-HTMLEditor::SelectTable()
-{
- nsCOMPtr<nsIDOMElement> table;
- nsresult rv = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), nullptr,
- getter_AddRefs(table));
- NS_ENSURE_SUCCESS(rv, rv);
- // Don't fail if we didn't find a table
- NS_ENSURE_TRUE(table, NS_OK);
-
- rv = ClearSelection();
- if (NS_FAILED(rv)) {
- return rv;
- }
- return AppendNodeToSelectionAsRange(table);
-}
-
-NS_IMETHODIMP
-HTMLEditor::SelectTableCell()
-{
- nsCOMPtr<nsIDOMElement> cell;
- nsresult rv = GetElementOrParentByTagName(NS_LITERAL_STRING("td"), nullptr,
- getter_AddRefs(cell));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(cell, NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND);
-
- rv = ClearSelection();
- if (NS_FAILED(rv)) {
- return rv;
- }
- return AppendNodeToSelectionAsRange(cell);
-}
-
-NS_IMETHODIMP
-HTMLEditor::SelectBlockOfCells(nsIDOMElement* aStartCell,
- nsIDOMElement* aEndCell)
-{
- NS_ENSURE_TRUE(aStartCell && aEndCell, NS_ERROR_NULL_POINTER);
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
-
- NS_NAMED_LITERAL_STRING(tableStr, "table");
- nsCOMPtr<nsIDOMElement> table;
- nsresult rv = GetElementOrParentByTagName(tableStr, aStartCell,
- getter_AddRefs(table));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(table, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIDOMElement> endTable;
- rv = GetElementOrParentByTagName(tableStr, aEndCell,
- getter_AddRefs(endTable));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(endTable, NS_ERROR_FAILURE);
-
- // We can only select a block if within the same table,
- // so do nothing if not within one table
- if (table != endTable) {
- return NS_OK;
- }
-
- int32_t startRowIndex, startColIndex, endRowIndex, endColIndex;
-
- // Get starting and ending cells' location in the cellmap
- rv = GetCellIndexes(aStartCell, &startRowIndex, &startColIndex);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- rv = GetCellIndexes(aEndCell, &endRowIndex, &endColIndex);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- // Suppress nsISelectionListener notification
- // until all selection changes are finished
- SelectionBatcher selectionBatcher(selection);
-
- // Examine all cell nodes in current selection and
- // remove those outside the new block cell region
- int32_t minColumn = std::min(startColIndex, endColIndex);
- int32_t minRow = std::min(startRowIndex, endRowIndex);
- int32_t maxColumn = std::max(startColIndex, endColIndex);
- int32_t maxRow = std::max(startRowIndex, endRowIndex);
-
- nsCOMPtr<nsIDOMElement> cell;
- int32_t currentRowIndex, currentColIndex;
- nsCOMPtr<nsIDOMRange> range;
- rv = GetFirstSelectedCell(getter_AddRefs(range), getter_AddRefs(cell));
- NS_ENSURE_SUCCESS(rv, rv);
- if (rv == NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND) {
- return NS_OK;
- }
-
- while (cell) {
- rv = GetCellIndexes(cell, &currentRowIndex, &currentColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (currentRowIndex < maxRow || currentRowIndex > maxRow ||
- currentColIndex < maxColumn || currentColIndex > maxColumn) {
- selection->RemoveRange(range);
- // Since we've removed the range, decrement pointer to next range
- mSelectedCellIndex--;
- }
- rv = GetNextSelectedCell(getter_AddRefs(range), getter_AddRefs(cell));
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- int32_t rowSpan, colSpan, actualRowSpan, actualColSpan;
- bool isSelected;
- for (int32_t row = minRow; row <= maxRow; row++) {
- for (int32_t col = minColumn; col <= maxColumn;
- col += std::max(actualColSpan, 1)) {
- rv = GetCellDataAt(table, row, col, getter_AddRefs(cell),
- &currentRowIndex, &currentColIndex,
- &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
- if (NS_FAILED(rv)) {
- break;
- }
- // Skip cells that already selected or are spanned from previous locations
- if (!isSelected && cell &&
- row == currentRowIndex && col == currentColIndex) {
- rv = AppendNodeToSelectionAsRange(cell);
- if (NS_FAILED(rv)) {
- break;
- }
- }
- }
- }
- // NS_OK, otherwise, the last failure of GetCellDataAt() or
- // AppendNodeToSelectionAsRange().
- return rv;
-}
-
-NS_IMETHODIMP
-HTMLEditor::SelectAllTableCells()
-{
- nsCOMPtr<nsIDOMElement> cell;
- nsresult rv = GetElementOrParentByTagName(NS_LITERAL_STRING("td"), nullptr,
- getter_AddRefs(cell));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Don't fail if we didn't find a cell
- NS_ENSURE_TRUE(cell, NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND);
-
- nsCOMPtr<nsIDOMElement> startCell = cell;
-
- // Get parent table
- nsCOMPtr<nsIDOMElement> table;
- rv = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), cell,
- getter_AddRefs(table));
- NS_ENSURE_SUCCESS(rv, rv);
- if (!table) {
- return NS_ERROR_NULL_POINTER;
- }
-
- int32_t rowCount, colCount;
- rv = GetTableSize(table, &rowCount, &colCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
-
- // Suppress nsISelectionListener notification
- // until all selection changes are finished
- SelectionBatcher selectionBatcher(selection);
-
- // It is now safe to clear the selection
- // BE SURE TO RESET IT BEFORE LEAVING!
- rv = ClearSelection();
-
- // Select all cells in the same column as current cell
- bool cellSelected = false;
- int32_t rowSpan, colSpan, actualRowSpan, actualColSpan, currentRowIndex, currentColIndex;
- bool isSelected;
- for (int32_t row = 0; row < rowCount; row++) {
- for (int32_t col = 0; col < colCount; col += std::max(actualColSpan, 1)) {
- rv = GetCellDataAt(table, row, col, getter_AddRefs(cell),
- &currentRowIndex, &currentColIndex,
- &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
- if (NS_FAILED(rv)) {
- break;
- }
- // Skip cells that are spanned from previous rows or columns
- if (cell && row == currentRowIndex && col == currentColIndex) {
- rv = AppendNodeToSelectionAsRange(cell);
- if (NS_FAILED(rv)) {
- break;
- }
- cellSelected = true;
- }
- }
- }
- // Safety code to select starting cell if nothing else was selected
- if (!cellSelected) {
- return AppendNodeToSelectionAsRange(startCell);
- }
- // NS_OK, otherwise, the error of ClearSelection() when there is no column or
- // the last failure of GetCellDataAt() or AppendNodeToSelectionAsRange().
- return rv;
-}
-
-NS_IMETHODIMP
-HTMLEditor::SelectTableRow()
-{
- nsCOMPtr<nsIDOMElement> cell;
- nsresult rv = GetElementOrParentByTagName(NS_LITERAL_STRING("td"), nullptr,
- getter_AddRefs(cell));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Don't fail if we didn't find a cell
- NS_ENSURE_TRUE(cell, NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND);
- nsCOMPtr<nsIDOMElement> startCell = cell;
-
- // Get table and location of cell:
- RefPtr<Selection> selection;
- nsCOMPtr<nsIDOMElement> table;
- int32_t startRowIndex, startColIndex;
-
- rv = GetCellContext(getter_AddRefs(selection),
- getter_AddRefs(table),
- getter_AddRefs(cell),
- nullptr, nullptr,
- &startRowIndex, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(table, NS_ERROR_FAILURE);
-
- int32_t rowCount, colCount;
- rv = GetTableSize(table, &rowCount, &colCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- //Note: At this point, we could get first and last cells in row,
- // then call SelectBlockOfCells, but that would take just
- // a little less code, so the following is more efficient
-
- // Suppress nsISelectionListener notification
- // until all selection changes are finished
- SelectionBatcher selectionBatcher(selection);
-
- // It is now safe to clear the selection
- // BE SURE TO RESET IT BEFORE LEAVING!
- rv = ClearSelection();
-
- // Select all cells in the same row as current cell
- bool cellSelected = false;
- int32_t rowSpan, colSpan, actualRowSpan, actualColSpan, currentRowIndex, currentColIndex;
- bool isSelected;
- for (int32_t col = 0; col < colCount; col += std::max(actualColSpan, 1)) {
- rv = GetCellDataAt(table, startRowIndex, col, getter_AddRefs(cell),
- &currentRowIndex, &currentColIndex, &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
- if (NS_FAILED(rv)) {
- break;
- }
- // Skip cells that are spanned from previous rows or columns
- if (cell && currentRowIndex == startRowIndex && currentColIndex == col) {
- rv = AppendNodeToSelectionAsRange(cell);
- if (NS_FAILED(rv)) {
- break;
- }
- cellSelected = true;
- }
- }
- // Safety code to select starting cell if nothing else was selected
- if (!cellSelected) {
- return AppendNodeToSelectionAsRange(startCell);
- }
- // NS_OK, otherwise, the error of ClearSelection() when there is no column or
- // the last failure of GetCellDataAt() or AppendNodeToSelectionAsRange().
- return rv;
-}
-
-NS_IMETHODIMP
-HTMLEditor::SelectTableColumn()
-{
- nsCOMPtr<nsIDOMElement> cell;
- nsresult rv = GetElementOrParentByTagName(NS_LITERAL_STRING("td"), nullptr,
- getter_AddRefs(cell));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Don't fail if we didn't find a cell
- NS_ENSURE_TRUE(cell, NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND);
-
- nsCOMPtr<nsIDOMElement> startCell = cell;
-
- // Get location of cell:
- RefPtr<Selection> selection;
- nsCOMPtr<nsIDOMElement> table;
- int32_t startRowIndex, startColIndex;
-
- rv = GetCellContext(getter_AddRefs(selection),
- getter_AddRefs(table),
- getter_AddRefs(cell),
- nullptr, nullptr,
- &startRowIndex, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(table, NS_ERROR_FAILURE);
-
- int32_t rowCount, colCount;
- rv = GetTableSize(table, &rowCount, &colCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Suppress nsISelectionListener notification
- // until all selection changes are finished
- SelectionBatcher selectionBatcher(selection);
-
- // It is now safe to clear the selection
- // BE SURE TO RESET IT BEFORE LEAVING!
- rv = ClearSelection();
-
- // Select all cells in the same column as current cell
- bool cellSelected = false;
- int32_t rowSpan, colSpan, actualRowSpan, actualColSpan, currentRowIndex, currentColIndex;
- bool isSelected;
- for (int32_t row = 0; row < rowCount; row += std::max(actualRowSpan, 1)) {
- rv = GetCellDataAt(table, row, startColIndex, getter_AddRefs(cell),
- &currentRowIndex, &currentColIndex, &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
- if (NS_FAILED(rv)) {
- break;
- }
- // Skip cells that are spanned from previous rows or columns
- if (cell && currentRowIndex == row && currentColIndex == startColIndex) {
- rv = AppendNodeToSelectionAsRange(cell);
- if (NS_FAILED(rv)) {
- break;
- }
- cellSelected = true;
- }
- }
- // Safety code to select starting cell if nothing else was selected
- if (!cellSelected) {
- return AppendNodeToSelectionAsRange(startCell);
- }
- // NS_OK, otherwise, the error of ClearSelection() when there is no row or
- // the last failure of GetCellDataAt() or AppendNodeToSelectionAsRange().
- return rv;
-}
-
-NS_IMETHODIMP
-HTMLEditor::SplitTableCell()
-{
- nsCOMPtr<nsIDOMElement> table;
- nsCOMPtr<nsIDOMElement> cell;
- int32_t startRowIndex, startColIndex, actualRowSpan, actualColSpan;
- // Get cell, table, etc. at selection anchor node
- nsresult rv = GetCellContext(nullptr,
- getter_AddRefs(table),
- getter_AddRefs(cell),
- nullptr, nullptr,
- &startRowIndex, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!table || !cell) {
- return NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND;
- }
-
- // We need rowspan and colspan data
- rv = GetCellSpansAt(table, startRowIndex, startColIndex,
- actualRowSpan, actualColSpan);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Must have some span to split
- if (actualRowSpan <= 1 && actualColSpan <= 1) {
- return NS_OK;
- }
-
- AutoEditBatch beginBatching(this);
- // Prevent auto insertion of BR in new cell until we're done
- AutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext);
-
- // We reset selection
- AutoSelectionSetterAfterTableEdit setCaret(this, table, startRowIndex,
- startColIndex, ePreviousColumn,
- false);
- //...so suppress Rules System selection munging
- AutoTransactionsConserveSelection dontChangeSelection(this);
-
- nsCOMPtr<nsIDOMElement> newCell;
- int32_t rowIndex = startRowIndex;
- int32_t rowSpanBelow, colSpanAfter;
-
- // Split up cell row-wise first into rowspan=1 above, and the rest below,
- // whittling away at the cell below until no more extra span
- for (rowSpanBelow = actualRowSpan-1; rowSpanBelow >= 0; rowSpanBelow--) {
- // We really split row-wise only if we had rowspan > 1
- if (rowSpanBelow > 0) {
- rv = SplitCellIntoRows(table, rowIndex, startColIndex, 1, rowSpanBelow,
- getter_AddRefs(newCell));
- NS_ENSURE_SUCCESS(rv, rv);
- CopyCellBackgroundColor(newCell, cell);
- }
- int32_t colIndex = startColIndex;
- // Now split the cell with rowspan = 1 into cells if it has colSpan > 1
- for (colSpanAfter = actualColSpan-1; colSpanAfter > 0; colSpanAfter--) {
- rv = SplitCellIntoColumns(table, rowIndex, colIndex, 1, colSpanAfter,
- getter_AddRefs(newCell));
- NS_ENSURE_SUCCESS(rv, rv);
- CopyCellBackgroundColor(newCell, cell);
- colIndex++;
- }
- // Point to the new cell and repeat
- rowIndex++;
- }
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::CopyCellBackgroundColor(nsIDOMElement* destCell,
- nsIDOMElement* sourceCell)
-{
- NS_ENSURE_TRUE(destCell && sourceCell, NS_ERROR_NULL_POINTER);
-
- // Copy backgournd color to new cell
- NS_NAMED_LITERAL_STRING(bgcolor, "bgcolor");
- nsAutoString color;
- bool isSet;
- nsresult rv = GetAttributeValue(sourceCell, bgcolor, color, &isSet);
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (!isSet) {
- return NS_OK;
- }
- return SetAttribute(destCell, bgcolor, color);
-}
-
-NS_IMETHODIMP
-HTMLEditor::SplitCellIntoColumns(nsIDOMElement* aTable,
- int32_t aRowIndex,
- int32_t aColIndex,
- int32_t aColSpanLeft,
- int32_t aColSpanRight,
- nsIDOMElement** aNewCell)
-{
- NS_ENSURE_TRUE(aTable, NS_ERROR_NULL_POINTER);
- if (aNewCell) {
- *aNewCell = nullptr;
- }
-
- nsCOMPtr<nsIDOMElement> cell;
- int32_t startRowIndex, startColIndex, rowSpan, colSpan, actualRowSpan, actualColSpan;
- bool isSelected;
- nsresult rv =
- GetCellDataAt(aTable, aRowIndex, aColIndex, getter_AddRefs(cell),
- &startRowIndex, &startColIndex,
- &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(cell, NS_ERROR_NULL_POINTER);
-
- // We can't split!
- if (actualColSpan <= 1 || (aColSpanLeft + aColSpanRight) > actualColSpan) {
- return NS_OK;
- }
-
- // Reduce colspan of cell to split
- rv = SetColSpan(cell, aColSpanLeft);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Insert new cell after using the remaining span
- // and always get the new cell so we can copy the background color;
- nsCOMPtr<nsIDOMElement> newCell;
- rv = InsertCell(cell, actualRowSpan, aColSpanRight, true, false,
- getter_AddRefs(newCell));
- NS_ENSURE_SUCCESS(rv, rv);
- if (!newCell) {
- return NS_OK;
- }
- if (aNewCell) {
- NS_ADDREF(*aNewCell = newCell.get());
- }
- return CopyCellBackgroundColor(newCell, cell);
-}
-
-NS_IMETHODIMP
-HTMLEditor::SplitCellIntoRows(nsIDOMElement* aTable,
- int32_t aRowIndex,
- int32_t aColIndex,
- int32_t aRowSpanAbove,
- int32_t aRowSpanBelow,
- nsIDOMElement** aNewCell)
-{
- NS_ENSURE_TRUE(aTable, NS_ERROR_NULL_POINTER);
- if (aNewCell) *aNewCell = nullptr;
-
- nsCOMPtr<nsIDOMElement> cell;
- int32_t startRowIndex, startColIndex, rowSpan, colSpan, actualRowSpan, actualColSpan;
- bool isSelected;
- nsresult rv =
- GetCellDataAt(aTable, aRowIndex, aColIndex, getter_AddRefs(cell),
- &startRowIndex, &startColIndex,
- &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(cell, NS_ERROR_NULL_POINTER);
-
- // We can't split!
- if (actualRowSpan <= 1 || (aRowSpanAbove + aRowSpanBelow) > actualRowSpan) {
- return NS_OK;
- }
-
- int32_t rowCount, colCount;
- rv = GetTableSize(aTable, &rowCount, &colCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIDOMElement> cell2;
- nsCOMPtr<nsIDOMElement> lastCellFound;
- int32_t startRowIndex2, startColIndex2, rowSpan2, colSpan2, actualRowSpan2, actualColSpan2;
- bool isSelected2;
- int32_t colIndex = 0;
- bool insertAfter = (startColIndex > 0);
- // This is the row we will insert new cell into
- int32_t rowBelowIndex = startRowIndex+aRowSpanAbove;
-
- // Find a cell to insert before or after
- for (;;) {
- // Search for a cell to insert before
- rv = GetCellDataAt(aTable, rowBelowIndex,
- colIndex, getter_AddRefs(cell2),
- &startRowIndex2, &startColIndex2, &rowSpan2, &colSpan2,
- &actualRowSpan2, &actualColSpan2, &isSelected2);
- // If we fail here, it could be because row has bad rowspan values,
- // such as all cells having rowspan > 1 (Call FixRowSpan first!)
- if (NS_FAILED(rv) || !cell) {
- return NS_ERROR_FAILURE;
- }
-
- // Skip over cells spanned from above (like the one we are splitting!)
- if (cell2 && startRowIndex2 == rowBelowIndex) {
- if (!insertAfter) {
- // Inserting before, so stop at first cell in row we want to insert
- // into.
- break;
- }
- // New cell isn't first in row,
- // so stop after we find the cell just before new cell's column
- if (startColIndex2 + actualColSpan2 == startColIndex) {
- break;
- }
- // If cell found is AFTER desired new cell colum,
- // we have multiple cells with rowspan > 1 that
- // prevented us from finding a cell to insert after...
- if (startColIndex2 > startColIndex) {
- // ... so instead insert before the cell we found
- insertAfter = false;
- break;
- }
- lastCellFound = cell2;
- }
- // Skip to next available cellmap location
- colIndex += std::max(actualColSpan2, 1);
-
- // Done when past end of total number of columns
- if (colIndex > colCount) {
- break;
- }
- }
-
- if (!cell2 && lastCellFound) {
- // Edge case where we didn't find a cell to insert after
- // or before because column(s) before desired column
- // and all columns after it are spanned from above.
- // We can insert after the last cell we found
- cell2 = lastCellFound;
- insertAfter = true; // Should always be true, but let's be sure
- }
-
- // Reduce rowspan of cell to split
- rv = SetRowSpan(cell, aRowSpanAbove);
- NS_ENSURE_SUCCESS(rv, rv);
-
-
- // Insert new cell after using the remaining span
- // and always get the new cell so we can copy the background color;
- nsCOMPtr<nsIDOMElement> newCell;
- rv = InsertCell(cell2, aRowSpanBelow, actualColSpan, insertAfter, false,
- getter_AddRefs(newCell));
- NS_ENSURE_SUCCESS(rv, rv);
- if (!newCell) {
- return NS_OK;
- }
- if (aNewCell) {
- NS_ADDREF(*aNewCell = newCell.get());
- }
- return CopyCellBackgroundColor(newCell, cell2);
-}
-
-NS_IMETHODIMP
-HTMLEditor::SwitchTableCellHeaderType(nsIDOMElement* aSourceCell,
- nsIDOMElement** aNewCell)
-{
- nsCOMPtr<Element> sourceCell = do_QueryInterface(aSourceCell);
- NS_ENSURE_TRUE(sourceCell, NS_ERROR_NULL_POINTER);
-
- AutoEditBatch beginBatching(this);
- // Prevent auto insertion of BR in new cell created by ReplaceContainer
- AutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext);
-
- // Save current selection to restore when done
- // This is needed so ReplaceContainer can monitor selection
- // when replacing nodes
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
- AutoSelectionRestorer selectionRestorer(selection, this);
-
- // Set to the opposite of current type
- nsCOMPtr<nsIAtom> atom = EditorBase::GetTag(aSourceCell);
- nsIAtom* newCellType = atom == nsGkAtoms::td ? nsGkAtoms::th : nsGkAtoms::td;
-
- // This creates new node, moves children, copies attributes (true)
- // and manages the selection!
- nsCOMPtr<Element> newNode = ReplaceContainer(sourceCell, newCellType,
- nullptr, nullptr, EditorBase::eCloneAttributes);
- NS_ENSURE_TRUE(newNode, NS_ERROR_FAILURE);
-
- // Return the new cell
- if (aNewCell) {
- nsCOMPtr<nsIDOMElement> newElement = do_QueryInterface(newNode);
- *aNewCell = newElement.get();
- NS_ADDREF(*aNewCell);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::JoinTableCells(bool aMergeNonContiguousContents)
-{
- nsCOMPtr<nsIDOMElement> table;
- nsCOMPtr<nsIDOMElement> targetCell;
- int32_t startRowIndex, startColIndex, rowSpan, colSpan, actualRowSpan, actualColSpan;
- bool isSelected;
- nsCOMPtr<nsIDOMElement> cell2;
- int32_t startRowIndex2, startColIndex2, rowSpan2, colSpan2, actualRowSpan2, actualColSpan2;
- bool isSelected2;
-
- // Get cell, table, etc. at selection anchor node
- nsresult rv = GetCellContext(nullptr,
- getter_AddRefs(table),
- getter_AddRefs(targetCell),
- nullptr, nullptr,
- &startRowIndex, &startColIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!table || !targetCell) {
- return NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND;
- }
-
- AutoEditBatch beginBatching(this);
- //Don't let Rules System change the selection
- AutoTransactionsConserveSelection dontChangeSelection(this);
-
- // Note: We dont' use AutoSelectionSetterAfterTableEdit here so the selection
- // is retained after joining. This leaves the target cell selected
- // as well as the "non-contiguous" cells, so user can see what happened.
-
- nsCOMPtr<nsIDOMElement> firstCell;
- int32_t firstRowIndex, firstColIndex;
- rv = GetFirstSelectedCellInTable(&firstRowIndex, &firstColIndex,
- getter_AddRefs(firstCell));
- NS_ENSURE_SUCCESS(rv, rv);
-
- bool joinSelectedCells = false;
- if (firstCell) {
- nsCOMPtr<nsIDOMElement> secondCell;
- rv = GetNextSelectedCell(nullptr, getter_AddRefs(secondCell));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // If only one cell is selected, join with cell to the right
- joinSelectedCells = (secondCell != nullptr);
- }
-
- if (joinSelectedCells) {
- // We have selected cells: Join just contiguous cells
- // and just merge contents if not contiguous
-
- int32_t rowCount, colCount;
- rv = GetTableSize(table, &rowCount, &colCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Get spans for cell we will merge into
- int32_t firstRowSpan, firstColSpan;
- rv = GetCellSpansAt(table, firstRowIndex, firstColIndex,
- firstRowSpan, firstColSpan);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // This defines the last indexes along the "edges"
- // of the contiguous block of cells, telling us
- // that we can join adjacent cells to the block
- // Start with same as the first values,
- // then expand as we find adjacent selected cells
- int32_t lastRowIndex = firstRowIndex;
- int32_t lastColIndex = firstColIndex;
- int32_t rowIndex, colIndex;
-
- // First pass: Determine boundaries of contiguous rectangular block
- // that we will join into one cell,
- // favoring adjacent cells in the same row
- for (rowIndex = firstRowIndex; rowIndex <= lastRowIndex; rowIndex++) {
- int32_t currentRowCount = rowCount;
- // Be sure each row doesn't have rowspan errors
- rv = FixBadRowSpan(table, rowIndex, rowCount);
- NS_ENSURE_SUCCESS(rv, rv);
- // Adjust rowcount by number of rows we removed
- lastRowIndex -= (currentRowCount-rowCount);
-
- bool cellFoundInRow = false;
- bool lastRowIsSet = false;
- int32_t lastColInRow = 0;
- int32_t firstColInRow = firstColIndex;
- for (colIndex = firstColIndex; colIndex < colCount;
- colIndex += std::max(actualColSpan2, 1)) {
- rv = GetCellDataAt(table, rowIndex, colIndex, getter_AddRefs(cell2),
- &startRowIndex2, &startColIndex2,
- &rowSpan2, &colSpan2,
- &actualRowSpan2, &actualColSpan2, &isSelected2);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (isSelected2) {
- if (!cellFoundInRow) {
- // We've just found the first selected cell in this row
- firstColInRow = colIndex;
- }
- if (rowIndex > firstRowIndex && firstColInRow != firstColIndex) {
- // We're in at least the second row,
- // but left boundary is "ragged" (not the same as 1st row's start)
- //Let's just end block on previous row
- // and keep previous lastColIndex
- //TODO: We could try to find the Maximum firstColInRow
- // so our block can still extend down more rows?
- lastRowIndex = std::max(0,rowIndex - 1);
- lastRowIsSet = true;
- break;
- }
- // Save max selected column in this row, including extra colspan
- lastColInRow = colIndex + (actualColSpan2-1);
- cellFoundInRow = true;
- } else if (cellFoundInRow) {
- // No cell or not selected, but at least one cell in row was found
- if (rowIndex > (firstRowIndex + 1) && colIndex <= lastColIndex) {
- // Cell is in a column less than current right border in
- // the third or higher selected row, so stop block at the previous row
- lastRowIndex = std::max(0,rowIndex - 1);
- lastRowIsSet = true;
- }
- // We're done with this row
- break;
- }
- } // End of column loop
-
- // Done with this row
- if (cellFoundInRow) {
- if (rowIndex == firstRowIndex) {
- // First row always initializes the right boundary
- lastColIndex = lastColInRow;
- }
-
- // If we didn't determine last row above...
- if (!lastRowIsSet) {
- if (colIndex < lastColIndex) {
- // (don't think we ever get here?)
- // Cell is in a column less than current right boundary,
- // so stop block at the previous row
- lastRowIndex = std::max(0,rowIndex - 1);
- } else {
- // Go on to examine next row
- lastRowIndex = rowIndex+1;
- }
- }
- // Use the minimum col we found so far for right boundary
- lastColIndex = std::min(lastColIndex, lastColInRow);
- } else {
- // No selected cells in this row -- stop at row above
- // and leave last column at its previous value
- lastRowIndex = std::max(0,rowIndex - 1);
- }
- }
-
- // The list of cells we will delete after joining
- nsTArray<nsCOMPtr<nsIDOMElement> > deleteList;
-
- // 2nd pass: Do the joining and merging
- for (rowIndex = 0; rowIndex < rowCount; rowIndex++) {
- for (colIndex = 0; colIndex < colCount;
- colIndex += std::max(actualColSpan2, 1)) {
- rv = GetCellDataAt(table, rowIndex, colIndex, getter_AddRefs(cell2),
- &startRowIndex2, &startColIndex2,
- &rowSpan2, &colSpan2,
- &actualRowSpan2, &actualColSpan2, &isSelected2);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // If this is 0, we are past last cell in row, so exit the loop
- if (!actualColSpan2) {
- break;
- }
-
- // Merge only selected cells (skip cell we're merging into, of course)
- if (isSelected2 && cell2 != firstCell) {
- if (rowIndex >= firstRowIndex && rowIndex <= lastRowIndex &&
- colIndex >= firstColIndex && colIndex <= lastColIndex) {
- // We are within the join region
- // Problem: It is very tricky to delete cells as we merge,
- // since that will upset the cellmap
- // Instead, build a list of cells to delete and do it later
- NS_ASSERTION(startRowIndex2 == rowIndex, "JoinTableCells: StartRowIndex is in row above");
-
- if (actualColSpan2 > 1) {
- //Check if cell "hangs" off the boundary because of colspan > 1
- // Use split methods to chop off excess
- int32_t extraColSpan = (startColIndex2 + actualColSpan2) - (lastColIndex+1);
- if ( extraColSpan > 0) {
- rv = SplitCellIntoColumns(table, startRowIndex2, startColIndex2,
- actualColSpan2 - extraColSpan,
- extraColSpan, nullptr);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- rv = MergeCells(firstCell, cell2, false);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Add cell to list to delete
- deleteList.AppendElement(cell2.get());
- } else if (aMergeNonContiguousContents) {
- // Cell is outside join region -- just merge the contents
- rv = MergeCells(firstCell, cell2, false);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- }
- }
-
- // All cell contents are merged. Delete the empty cells we accumulated
- // Prevent rules testing until we're done
- AutoRules beginRulesSniffing(this, EditAction::deleteNode,
- nsIEditor::eNext);
-
- for (uint32_t i = 0, n = deleteList.Length(); i < n; i++) {
- nsIDOMElement *elementPtr = deleteList[i];
- if (elementPtr) {
- nsCOMPtr<nsIDOMNode> node = do_QueryInterface(elementPtr);
- rv = DeleteNode(node);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- // Cleanup selection: remove ranges where cells were deleted
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
-
- int32_t rangeCount;
- rv = selection->GetRangeCount(&rangeCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- RefPtr<nsRange> range;
- for (int32_t i = 0; i < rangeCount; i++) {
- range = selection->GetRangeAt(i);
- NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIDOMElement> deletedCell;
- GetCellFromRange(range, getter_AddRefs(deletedCell));
- if (!deletedCell) {
- selection->RemoveRange(range);
- rangeCount--;
- i--;
- }
- }
-
- // Set spans for the cell everthing merged into
- rv = SetRowSpan(firstCell, lastRowIndex-firstRowIndex+1);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = SetColSpan(firstCell, lastColIndex-firstColIndex+1);
- NS_ENSURE_SUCCESS(rv, rv);
-
-
- // Fixup disturbances in table layout
- NormalizeTable(table);
- } else {
- // Joining with cell to the right -- get rowspan and colspan data of target cell
- rv = GetCellDataAt(table, startRowIndex, startColIndex,
- getter_AddRefs(targetCell),
- &startRowIndex, &startColIndex, &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(targetCell, NS_ERROR_NULL_POINTER);
-
- // Get data for cell to the right
- rv = GetCellDataAt(table, startRowIndex, startColIndex + actualColSpan,
- getter_AddRefs(cell2),
- &startRowIndex2, &startColIndex2, &rowSpan2, &colSpan2,
- &actualRowSpan2, &actualColSpan2, &isSelected2);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!cell2) {
- return NS_OK; // Don't fail if there's no cell
- }
-
- // sanity check
- NS_ASSERTION((startRowIndex >= startRowIndex2),"JoinCells: startRowIndex < startRowIndex2");
-
- // Figure out span of merged cell starting from target's starting row
- // to handle case of merged cell starting in a row above
- int32_t spanAboveMergedCell = startRowIndex - startRowIndex2;
- int32_t effectiveRowSpan2 = actualRowSpan2 - spanAboveMergedCell;
-
- if (effectiveRowSpan2 > actualRowSpan) {
- // Cell to the right spans into row below target
- // Split off portion below target cell's bottom-most row
- rv = SplitCellIntoRows(table, startRowIndex2, startColIndex2,
- spanAboveMergedCell+actualRowSpan,
- effectiveRowSpan2-actualRowSpan, nullptr);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // Move contents from cell to the right
- // Delete the cell now only if it starts in the same row
- // and has enough row "height"
- rv = MergeCells(targetCell, cell2,
- (startRowIndex2 == startRowIndex) &&
- (effectiveRowSpan2 >= actualRowSpan));
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (effectiveRowSpan2 < actualRowSpan) {
- // Merged cell is "shorter"
- // (there are cells(s) below it that are row-spanned by target cell)
- // We could try splitting those cells, but that's REAL messy,
- // so the safest thing to do is NOT really join the cells
- return NS_OK;
- }
-
- if (spanAboveMergedCell > 0) {
- // Cell we merged started in a row above the target cell
- // Reduce rowspan to give room where target cell will extend its colspan
- rv = SetRowSpan(cell2, spanAboveMergedCell);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // Reset target cell's colspan to encompass cell to the right
- rv = SetColSpan(targetCell, actualColSpan+actualColSpan2);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::MergeCells(nsCOMPtr<nsIDOMElement> aTargetCell,
- nsCOMPtr<nsIDOMElement> aCellToMerge,
- bool aDeleteCellToMerge)
-{
- nsCOMPtr<dom::Element> targetCell = do_QueryInterface(aTargetCell);
- nsCOMPtr<dom::Element> cellToMerge = do_QueryInterface(aCellToMerge);
- NS_ENSURE_TRUE(targetCell && cellToMerge, NS_ERROR_NULL_POINTER);
-
- // Prevent rules testing until we're done
- AutoRules beginRulesSniffing(this, EditAction::deleteNode, nsIEditor::eNext);
-
- // Don't need to merge if cell is empty
- if (!IsEmptyCell(cellToMerge)) {
- // Get index of last child in target cell
- // If we fail or don't have children,
- // we insert at index 0
- int32_t insertIndex = 0;
-
- // Start inserting just after last child
- uint32_t len = targetCell->GetChildCount();
- if (len == 1 && IsEmptyCell(targetCell)) {
- // Delete the empty node
- nsIContent* cellChild = targetCell->GetFirstChild();
- nsresult rv = DeleteNode(cellChild->AsDOMNode());
- NS_ENSURE_SUCCESS(rv, rv);
- insertIndex = 0;
- } else {
- insertIndex = (int32_t)len;
- }
-
- // Move the contents
- while (cellToMerge->HasChildren()) {
- nsCOMPtr<nsIDOMNode> cellChild = cellToMerge->GetLastChild()->AsDOMNode();
- nsresult rv = DeleteNode(cellChild);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = InsertNode(cellChild, aTargetCell, insertIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- // Delete cells whose contents were moved
- if (aDeleteCellToMerge) {
- return DeleteNode(aCellToMerge);
- }
-
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-HTMLEditor::FixBadRowSpan(nsIDOMElement* aTable,
- int32_t aRowIndex,
- int32_t& aNewRowCount)
-{
- NS_ENSURE_TRUE(aTable, NS_ERROR_NULL_POINTER);
-
- int32_t rowCount, colCount;
- nsresult rv = GetTableSize(aTable, &rowCount, &colCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIDOMElement>cell;
- int32_t startRowIndex, startColIndex, rowSpan, colSpan, actualRowSpan, actualColSpan;
- bool isSelected;
-
- int32_t minRowSpan = -1;
- int32_t colIndex;
-
- for (colIndex = 0; colIndex < colCount;
- colIndex += std::max(actualColSpan, 1)) {
- rv = GetCellDataAt(aTable, aRowIndex, colIndex, getter_AddRefs(cell),
- &startRowIndex, &startColIndex, &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
- // NOTE: This is a *real* failure.
- // GetCellDataAt passes if cell is missing from cellmap
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (!cell) {
- break;
- }
- if (rowSpan > 0 &&
- startRowIndex == aRowIndex &&
- (rowSpan < minRowSpan || minRowSpan == -1)) {
- minRowSpan = rowSpan;
- }
- NS_ASSERTION((actualColSpan > 0),"ActualColSpan = 0 in FixBadRowSpan");
- }
- if (minRowSpan > 1) {
- // The amount to reduce everyone's rowspan
- // so at least one cell has rowspan = 1
- int32_t rowsReduced = minRowSpan - 1;
- for (colIndex = 0; colIndex < colCount;
- colIndex += std::max(actualColSpan, 1)) {
- rv = GetCellDataAt(aTable, aRowIndex, colIndex, getter_AddRefs(cell),
- &startRowIndex, &startColIndex, &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
- if (NS_FAILED(rv)) {
- return rv;
- }
- // Fixup rowspans only for cells starting in current row
- if (cell && rowSpan > 0 &&
- startRowIndex == aRowIndex &&
- startColIndex == colIndex ) {
- rv = SetRowSpan(cell, rowSpan-rowsReduced);
- if (NS_FAILED(rv)) {
- return rv;
- }
- }
- NS_ASSERTION((actualColSpan > 0),"ActualColSpan = 0 in FixBadRowSpan");
- }
- }
- return GetTableSize(aTable, &aNewRowCount, &colCount);
-}
-
-NS_IMETHODIMP
-HTMLEditor::FixBadColSpan(nsIDOMElement* aTable,
- int32_t aColIndex,
- int32_t& aNewColCount)
-{
- NS_ENSURE_TRUE(aTable, NS_ERROR_NULL_POINTER);
-
- int32_t rowCount, colCount;
- nsresult rv = GetTableSize(aTable, &rowCount, &colCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIDOMElement> cell;
- int32_t startRowIndex, startColIndex, rowSpan, colSpan, actualRowSpan, actualColSpan;
- bool isSelected;
-
- int32_t minColSpan = -1;
- int32_t rowIndex;
-
- for (rowIndex = 0; rowIndex < rowCount;
- rowIndex += std::max(actualRowSpan, 1)) {
- rv = GetCellDataAt(aTable, rowIndex, aColIndex, getter_AddRefs(cell),
- &startRowIndex, &startColIndex, &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
- // NOTE: This is a *real* failure.
- // GetCellDataAt passes if cell is missing from cellmap
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (!cell) {
- break;
- }
- if (colSpan > 0 &&
- startColIndex == aColIndex &&
- (colSpan < minColSpan || minColSpan == -1)) {
- minColSpan = colSpan;
- }
- NS_ASSERTION((actualRowSpan > 0),"ActualRowSpan = 0 in FixBadColSpan");
- }
- if (minColSpan > 1) {
- // The amount to reduce everyone's colspan
- // so at least one cell has colspan = 1
- int32_t colsReduced = minColSpan - 1;
- for (rowIndex = 0; rowIndex < rowCount;
- rowIndex += std::max(actualRowSpan, 1)) {
- rv = GetCellDataAt(aTable, rowIndex, aColIndex, getter_AddRefs(cell),
- &startRowIndex, &startColIndex, &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
- if (NS_FAILED(rv)) {
- return rv;
- }
- // Fixup colspans only for cells starting in current column
- if (cell && colSpan > 0 &&
- startColIndex == aColIndex &&
- startRowIndex == rowIndex) {
- rv = SetColSpan(cell, colSpan-colsReduced);
- if (NS_FAILED(rv)) {
- return rv;
- }
- }
- NS_ASSERTION((actualRowSpan > 0),"ActualRowSpan = 0 in FixBadColSpan");
- }
- }
- return GetTableSize(aTable, &rowCount, &aNewColCount);
-}
-
-NS_IMETHODIMP
-HTMLEditor::NormalizeTable(nsIDOMElement* aTable)
-{
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIDOMElement> table;
- nsresult rv = GetElementOrParentByTagName(NS_LITERAL_STRING("table"),
- aTable, getter_AddRefs(table));
- NS_ENSURE_SUCCESS(rv, rv);
- // Don't fail if we didn't find a table
- NS_ENSURE_TRUE(table, NS_OK);
-
- int32_t rowCount, colCount, rowIndex, colIndex;
- rv = GetTableSize(table, &rowCount, &colCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Save current selection
- AutoSelectionRestorer selectionRestorer(selection, this);
-
- AutoEditBatch beginBatching(this);
- // Prevent auto insertion of BR in new cell until we're done
- AutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext);
-
- nsCOMPtr<nsIDOMElement> cell;
- int32_t startRowIndex, startColIndex, rowSpan, colSpan, actualRowSpan, actualColSpan;
- bool isSelected;
-
- // Scan all cells in each row to detect bad rowspan values
- for (rowIndex = 0; rowIndex < rowCount; rowIndex++) {
- rv = FixBadRowSpan(table, rowIndex, rowCount);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // and same for colspans
- for (colIndex = 0; colIndex < colCount; colIndex++) {
- rv = FixBadColSpan(table, colIndex, colCount);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // Fill in missing cellmap locations with empty cells
- for (rowIndex = 0; rowIndex < rowCount; rowIndex++) {
- nsCOMPtr<nsIDOMElement> previousCellInRow;
- for (colIndex = 0; colIndex < colCount; colIndex++) {
- rv = GetCellDataAt(table, rowIndex, colIndex, getter_AddRefs(cell),
- &startRowIndex, &startColIndex, &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
- // NOTE: This is a *real* failure.
- // GetCellDataAt passes if cell is missing from cellmap
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (!cell) {
- //We are missing a cell at a cellmap location
-#ifdef DEBUG
- printf("NormalizeTable found missing cell at row=%d, col=%d\n",
- rowIndex, colIndex);
-#endif
- // Add a cell after the previous Cell in the current row
- if (!previousCellInRow) {
- // We don't have any cells in this row -- We are really messed up!
-#ifdef DEBUG
- printf("NormalizeTable found no cells in row=%d, col=%d\n",
- rowIndex, colIndex);
-#endif
- return NS_ERROR_FAILURE;
- }
-
- // Insert a new cell after (true), and return the new cell to us
- rv = InsertCell(previousCellInRow, 1, 1, true, false,
- getter_AddRefs(cell));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Set this so we use returned new "cell" to set previousCellInRow below
- if (cell) {
- startRowIndex = rowIndex;
- }
- }
- // Save the last cell found in the same row we are scanning
- if (startRowIndex == rowIndex) {
- previousCellInRow = cell;
- }
- }
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetCellIndexes(nsIDOMElement* aCell,
- int32_t* aRowIndex,
- int32_t* aColIndex)
-{
- NS_ENSURE_ARG_POINTER(aRowIndex);
- *aColIndex=0; // initialize out params
- NS_ENSURE_ARG_POINTER(aColIndex);
- *aRowIndex=0;
- if (!aCell) {
- // Get the selected cell or the cell enclosing the selection anchor
- nsCOMPtr<nsIDOMElement> cell;
- nsresult rv = GetElementOrParentByTagName(NS_LITERAL_STRING("td"), nullptr,
- getter_AddRefs(cell));
- if (NS_FAILED(rv) || !cell) {
- return NS_ERROR_FAILURE;
- }
- aCell = cell;
- }
-
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
- NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
-
- nsCOMPtr<nsIContent> nodeAsContent( do_QueryInterface(aCell) );
- NS_ENSURE_TRUE(nodeAsContent, NS_ERROR_FAILURE);
- // frames are not ref counted, so don't use an nsCOMPtr
- nsIFrame *layoutObject = nodeAsContent->GetPrimaryFrame();
- NS_ENSURE_TRUE(layoutObject, NS_ERROR_FAILURE);
-
- nsITableCellLayout *cellLayoutObject = do_QueryFrame(layoutObject);
- NS_ENSURE_TRUE(cellLayoutObject, NS_ERROR_FAILURE);
- return cellLayoutObject->GetCellIndexes(*aRowIndex, *aColIndex);
-}
-
-nsTableWrapperFrame*
-HTMLEditor::GetTableFrame(nsIDOMElement* aTable)
-{
- NS_ENSURE_TRUE(aTable, nullptr);
-
- nsCOMPtr<nsIContent> nodeAsContent( do_QueryInterface(aTable) );
- NS_ENSURE_TRUE(nodeAsContent, nullptr);
- return do_QueryFrame(nodeAsContent->GetPrimaryFrame());
-}
-
-//Return actual number of cells (a cell with colspan > 1 counts as just 1)
-int32_t
-HTMLEditor::GetNumberOfCellsInRow(nsIDOMElement* aTable,
- int32_t rowIndex)
-{
- int32_t cellCount = 0;
- nsCOMPtr<nsIDOMElement> cell;
- int32_t colIndex = 0;
- do {
- int32_t startRowIndex, startColIndex, rowSpan, colSpan, actualRowSpan, actualColSpan;
- bool isSelected;
- nsresult rv =
- GetCellDataAt(aTable, rowIndex, colIndex, getter_AddRefs(cell),
- &startRowIndex, &startColIndex, &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
- NS_ENSURE_SUCCESS(rv, 0);
- if (cell) {
- // Only count cells that start in row we are working with
- if (startRowIndex == rowIndex) {
- cellCount++;
- }
- //Next possible location for a cell
- colIndex += actualColSpan;
- } else {
- colIndex++;
- }
- } while (cell);
-
- return cellCount;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetTableSize(nsIDOMElement* aTable,
- int32_t* aRowCount,
- int32_t* aColCount)
-{
- NS_ENSURE_ARG_POINTER(aRowCount);
- NS_ENSURE_ARG_POINTER(aColCount);
- *aRowCount = 0;
- *aColCount = 0;
- nsCOMPtr<nsIDOMElement> table;
- // Get the selected talbe or the table enclosing the selection anchor
- nsresult rv = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), aTable,
- getter_AddRefs(table));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(table, NS_ERROR_FAILURE);
-
- nsTableWrapperFrame* tableFrame = GetTableFrame(table.get());
- NS_ENSURE_TRUE(tableFrame, NS_ERROR_FAILURE);
-
- *aRowCount = tableFrame->GetRowCount();
- *aColCount = tableFrame->GetColCount();
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetCellDataAt(nsIDOMElement* aTable,
- int32_t aRowIndex,
- int32_t aColIndex,
- nsIDOMElement** aCell,
- int32_t* aStartRowIndex,
- int32_t* aStartColIndex,
- int32_t* aRowSpan,
- int32_t* aColSpan,
- int32_t* aActualRowSpan,
- int32_t* aActualColSpan,
- bool* aIsSelected)
-{
- NS_ENSURE_ARG_POINTER(aStartRowIndex);
- NS_ENSURE_ARG_POINTER(aStartColIndex);
- NS_ENSURE_ARG_POINTER(aRowSpan);
- NS_ENSURE_ARG_POINTER(aColSpan);
- NS_ENSURE_ARG_POINTER(aActualRowSpan);
- NS_ENSURE_ARG_POINTER(aActualColSpan);
- NS_ENSURE_ARG_POINTER(aIsSelected);
- NS_ENSURE_TRUE(aCell, NS_ERROR_NULL_POINTER);
-
- *aStartRowIndex = 0;
- *aStartColIndex = 0;
- *aRowSpan = 0;
- *aColSpan = 0;
- *aActualRowSpan = 0;
- *aActualColSpan = 0;
- *aIsSelected = false;
-
- *aCell = nullptr;
-
- if (!aTable) {
- // Get the selected table or the table enclosing the selection anchor
- nsCOMPtr<nsIDOMElement> table;
- nsresult rv =
- GetElementOrParentByTagName(NS_LITERAL_STRING("table"), nullptr,
- getter_AddRefs(table));
- NS_ENSURE_SUCCESS(rv, rv);
- if (!table) {
- return NS_ERROR_FAILURE;
- }
- aTable = table;
- }
-
- nsTableWrapperFrame* tableFrame = GetTableFrame(aTable);
- NS_ENSURE_TRUE(tableFrame, NS_ERROR_FAILURE);
-
- nsTableCellFrame* cellFrame =
- tableFrame->GetCellFrameAt(aRowIndex, aColIndex);
- if (!cellFrame) {
- return NS_ERROR_FAILURE;
- }
-
- *aIsSelected = cellFrame->IsSelected();
- *aStartRowIndex = cellFrame->RowIndex();
- *aStartColIndex = cellFrame->ColIndex();
- *aRowSpan = cellFrame->GetRowSpan();
- *aColSpan = cellFrame->GetColSpan();
- *aActualRowSpan = tableFrame->GetEffectiveRowSpanAt(aRowIndex, aColIndex);
- *aActualColSpan = tableFrame->GetEffectiveColSpanAt(aRowIndex, aColIndex);
- nsCOMPtr<nsIDOMElement> domCell = do_QueryInterface(cellFrame->GetContent());
- domCell.forget(aCell);
-
- return NS_OK;
-}
-
-// When all you want is the cell
-NS_IMETHODIMP
-HTMLEditor::GetCellAt(nsIDOMElement* aTable,
- int32_t aRowIndex,
- int32_t aColIndex,
- nsIDOMElement** aCell)
-{
- NS_ENSURE_ARG_POINTER(aCell);
- *aCell = nullptr;
-
- if (!aTable) {
- // Get the selected table or the table enclosing the selection anchor
- nsCOMPtr<nsIDOMElement> table;
- nsresult rv =
- GetElementOrParentByTagName(NS_LITERAL_STRING("table"), nullptr,
- getter_AddRefs(table));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(table, NS_ERROR_FAILURE);
- aTable = table;
- }
-
- nsTableWrapperFrame* tableFrame = GetTableFrame(aTable);
- if (!tableFrame) {
- *aCell = nullptr;
- return NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND;
- }
-
- nsCOMPtr<nsIDOMElement> domCell =
- do_QueryInterface(tableFrame->GetCellAt(aRowIndex, aColIndex));
- domCell.forget(aCell);
-
- return NS_OK;
-}
-
-// When all you want are the rowspan and colspan (not exposed in nsITableEditor)
-NS_IMETHODIMP
-HTMLEditor::GetCellSpansAt(nsIDOMElement* aTable,
- int32_t aRowIndex,
- int32_t aColIndex,
- int32_t& aActualRowSpan,
- int32_t& aActualColSpan)
-{
- nsTableWrapperFrame* tableFrame = GetTableFrame(aTable);
- if (!tableFrame) {
- return NS_ERROR_FAILURE;
- }
- aActualRowSpan = tableFrame->GetEffectiveRowSpanAt(aRowIndex, aColIndex);
- aActualColSpan = tableFrame->GetEffectiveColSpanAt(aRowIndex, aColIndex);
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::GetCellContext(Selection** aSelection,
- nsIDOMElement** aTable,
- nsIDOMElement** aCell,
- nsIDOMNode** aCellParent,
- int32_t* aCellOffset,
- int32_t* aRowIndex,
- int32_t* aColIndex)
-{
- // Initialize return pointers
- if (aSelection) {
- *aSelection = nullptr;
- }
- if (aTable) {
- *aTable = nullptr;
- }
- if (aCell) {
- *aCell = nullptr;
- }
- if (aCellParent) {
- *aCellParent = nullptr;
- }
- if (aCellOffset) {
- *aCellOffset = 0;
- }
- if (aRowIndex) {
- *aRowIndex = 0;
- }
- if (aColIndex) {
- *aColIndex = 0;
- }
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
-
- if (aSelection) {
- *aSelection = selection.get();
- NS_ADDREF(*aSelection);
- }
- nsCOMPtr <nsIDOMElement> table;
- nsCOMPtr <nsIDOMElement> cell;
-
- // Caller may supply the cell...
- if (aCell && *aCell) {
- cell = *aCell;
- }
-
- // ...but if not supplied,
- // get cell if it's the child of selection anchor node,
- // or get the enclosing by a cell
- if (!cell) {
- // Find a selected or enclosing table element
- nsCOMPtr<nsIDOMElement> cellOrTableElement;
- int32_t selectedCount;
- nsAutoString tagName;
- nsresult rv =
- GetSelectedOrParentTableElement(tagName, &selectedCount,
- getter_AddRefs(cellOrTableElement));
- NS_ENSURE_SUCCESS(rv, rv);
- if (tagName.EqualsLiteral("table")) {
- // We have a selected table, not a cell
- if (aTable) {
- *aTable = cellOrTableElement.get();
- NS_ADDREF(*aTable);
- }
- return NS_OK;
- }
- if (!tagName.EqualsLiteral("td")) {
- return NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND;
- }
-
- // We found a cell
- cell = cellOrTableElement;
- }
- if (aCell) {
- *aCell = cell.get();
- NS_ADDREF(*aCell);
- }
-
- // Get containing table
- nsresult rv = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), cell,
- getter_AddRefs(table));
- NS_ENSURE_SUCCESS(rv, rv);
- // Cell must be in a table, so fail if not found
- NS_ENSURE_TRUE(table, NS_ERROR_FAILURE);
- if (aTable) {
- *aTable = table.get();
- NS_ADDREF(*aTable);
- }
-
- // Get the rest of the related data only if requested
- if (aRowIndex || aColIndex) {
- int32_t rowIndex, colIndex;
- // Get current cell location so we can put caret back there when done
- rv = GetCellIndexes(cell, &rowIndex, &colIndex);
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (aRowIndex) {
- *aRowIndex = rowIndex;
- }
- if (aColIndex) {
- *aColIndex = colIndex;
- }
- }
- if (aCellParent) {
- nsCOMPtr <nsIDOMNode> cellParent;
- // Get the immediate parent of the cell
- rv = cell->GetParentNode(getter_AddRefs(cellParent));
- NS_ENSURE_SUCCESS(rv, rv);
- // Cell has to have a parent, so fail if not found
- NS_ENSURE_TRUE(cellParent, NS_ERROR_FAILURE);
-
- *aCellParent = cellParent.get();
- NS_ADDREF(*aCellParent);
-
- if (aCellOffset) {
- *aCellOffset = GetChildOffset(cell, cellParent);
- }
- }
-
- return NS_OK;
-}
-
-nsresult
-HTMLEditor::GetCellFromRange(nsRange* aRange,
- nsIDOMElement** aCell)
-{
- // Note: this might return a node that is outside of the range.
- // Use carefully.
- NS_ENSURE_TRUE(aRange && aCell, NS_ERROR_NULL_POINTER);
-
- *aCell = nullptr;
-
- nsCOMPtr<nsIDOMNode> startParent;
- nsresult rv = aRange->GetStartContainer(getter_AddRefs(startParent));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(startParent, NS_ERROR_FAILURE);
-
- uint32_t startOffset = aRange->StartOffset();
-
- nsCOMPtr<nsIDOMNode> childNode =
- GetChildAt(startParent, static_cast<int32_t>(startOffset));
- // This means selection is probably at a text node (or end of doc?)
- if (!childNode) {
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsIDOMNode> endParent;
- rv = aRange->GetEndContainer(getter_AddRefs(endParent));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(startParent, NS_ERROR_FAILURE);
-
- // If a cell is deleted, the range is collapse
- // (startOffset == aRange->EndOffset())
- // so tell caller the cell wasn't found
- if (startParent == endParent &&
- aRange->EndOffset() == startOffset+1 &&
- HTMLEditUtils::IsTableCell(childNode)) {
- // Should we also test if frame is selected? (Use GetCellDataAt())
- // (Let's not for now -- more efficient)
- nsCOMPtr<nsIDOMElement> cellElement = do_QueryInterface(childNode);
- *aCell = cellElement.get();
- NS_ADDREF(*aCell);
- return NS_OK;
- }
- return NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetFirstSelectedCell(nsIDOMRange** aRange,
- nsIDOMElement** aCell)
-{
- NS_ENSURE_TRUE(aCell, NS_ERROR_NULL_POINTER);
- *aCell = nullptr;
- if (aRange) {
- *aRange = nullptr;
- }
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
-
- RefPtr<nsRange> range = selection->GetRangeAt(0);
- NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
-
- mSelectedCellIndex = 0;
-
- nsresult rv = GetCellFromRange(range, aCell);
- // Failure here probably means selection is in a text node,
- // so there's no selected cell
- if (NS_FAILED(rv)) {
- return NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND;
- }
- // No cell means range was collapsed (cell was deleted)
- if (!*aCell) {
- return NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND;
- }
-
- if (aRange) {
- *aRange = range.get();
- NS_ADDREF(*aRange);
- }
-
- // Setup for next cell
- mSelectedCellIndex = 1;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetNextSelectedCell(nsIDOMRange** aRange,
- nsIDOMElement** aCell)
-{
- NS_ENSURE_TRUE(aCell, NS_ERROR_NULL_POINTER);
- *aCell = nullptr;
- if (aRange) {
- *aRange = nullptr;
- }
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
-
- int32_t rangeCount = selection->RangeCount();
-
- // Don't even try if index exceeds range count
- if (mSelectedCellIndex >= rangeCount) {
- return NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND;
- }
-
- // Scan through ranges to find next valid selected cell
- RefPtr<nsRange> range;
- for (; mSelectedCellIndex < rangeCount; mSelectedCellIndex++) {
- range = selection->GetRangeAt(mSelectedCellIndex);
- NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
-
- nsresult rv = GetCellFromRange(range, aCell);
- // Failure here means the range doesn't contain a cell
- NS_ENSURE_SUCCESS(rv, NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND);
-
- // We found a selected cell
- if (*aCell) {
- break;
- }
-
- // If we didn't find a cell, continue to next range in selection
- }
- // No cell means all remaining ranges were collapsed (cells were deleted)
- NS_ENSURE_TRUE(*aCell, NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND);
-
- if (aRange) {
- *aRange = range.get();
- NS_ADDREF(*aRange);
- }
-
- // Setup for next cell
- mSelectedCellIndex++;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetFirstSelectedCellInTable(int32_t* aRowIndex,
- int32_t* aColIndex,
- nsIDOMElement** aCell)
-{
- NS_ENSURE_TRUE(aCell, NS_ERROR_NULL_POINTER);
- *aCell = nullptr;
- if (aRowIndex) {
- *aRowIndex = 0;
- }
- if (aColIndex) {
- *aColIndex = 0;
- }
-
- nsCOMPtr<nsIDOMElement> cell;
- nsresult rv = GetFirstSelectedCell(nullptr, getter_AddRefs(cell));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(cell, NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND);
-
- *aCell = cell.get();
- NS_ADDREF(*aCell);
-
- // Also return the row and/or column if requested
- if (aRowIndex || aColIndex) {
- int32_t startRowIndex, startColIndex;
- rv = GetCellIndexes(cell, &startRowIndex, &startColIndex);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- if (aRowIndex) {
- *aRowIndex = startRowIndex;
- }
- if (aColIndex) {
- *aColIndex = startColIndex;
- }
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::SetSelectionAfterTableEdit(nsIDOMElement* aTable,
- int32_t aRow,
- int32_t aCol,
- int32_t aDirection,
- bool aSelected)
-{
- NS_ENSURE_TRUE(aTable, NS_ERROR_NOT_INITIALIZED);
-
- RefPtr<Selection> selection = GetSelection();
-
- if (!selection) {
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsIDOMElement> cell;
- bool done = false;
- do {
- nsresult rv = GetCellAt(aTable, aRow, aCol, getter_AddRefs(cell));
- if (NS_FAILED(rv)) {
- break;
- }
-
- if (cell) {
- if (aSelected) {
- // Reselect the cell
- return SelectElement(cell);
- } else {
- // Set the caret to deepest first child
- // but don't go into nested tables
- // TODO: Should we really be placing the caret at the END
- // of the cell content?
- nsCOMPtr<nsINode> cellNode = do_QueryInterface(cell);
- if (cellNode) {
- CollapseSelectionToDeepestNonTableFirstChild(selection, cellNode);
- }
- return NS_OK;
- }
- } else {
- // Setup index to find another cell in the
- // direction requested, but move in
- // other direction if already at beginning of row or column
- switch (aDirection) {
- case ePreviousColumn:
- if (!aCol) {
- if (aRow > 0) {
- aRow--;
- } else {
- done = true;
- }
- } else {
- aCol--;
- }
- break;
- case ePreviousRow:
- if (!aRow) {
- if (aCol > 0) {
- aCol--;
- } else {
- done = true;
- }
- } else {
- aRow--;
- }
- break;
- default:
- done = true;
- }
- }
- } while (!done);
-
- // We didn't find a cell
- // Set selection to just before the table
- nsCOMPtr<nsIDOMNode> tableParent;
- nsresult rv = aTable->GetParentNode(getter_AddRefs(tableParent));
- if (NS_SUCCEEDED(rv) && tableParent) {
- int32_t tableOffset = GetChildOffset(aTable, tableParent);
- return selection->Collapse(tableParent, tableOffset);
- }
- // Last resort: Set selection to start of doc
- // (it's very bad to not have a valid selection!)
- return SetSelectionAtDocumentStart(selection);
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetSelectedOrParentTableElement(nsAString& aTagName,
- int32_t* aSelectedCount,
- nsIDOMElement** aTableElement)
-{
- NS_ENSURE_ARG_POINTER(aTableElement);
- NS_ENSURE_ARG_POINTER(aSelectedCount);
- *aTableElement = nullptr;
- aTagName.Truncate();
- *aSelectedCount = 0;
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
-
- // Try to get the first selected cell
- nsCOMPtr<nsIDOMElement> tableOrCellElement;
- nsresult rv = GetFirstSelectedCell(nullptr,
- getter_AddRefs(tableOrCellElement));
- NS_ENSURE_SUCCESS(rv, rv);
-
- NS_NAMED_LITERAL_STRING(tdName, "td");
-
- if (tableOrCellElement) {
- // Each cell is in its own selection range,
- // so count signals multiple-cell selection
- rv = selection->GetRangeCount(aSelectedCount);
- NS_ENSURE_SUCCESS(rv, rv);
- aTagName = tdName;
- } else {
- nsCOMPtr<nsIDOMNode> anchorNode;
- rv = selection->GetAnchorNode(getter_AddRefs(anchorNode));
- if (NS_FAILED(rv)) {
- return rv;
- }
- NS_ENSURE_TRUE(anchorNode, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIDOMNode> selectedNode;
-
- // Get child of anchor node, if exists
- bool hasChildren;
- anchorNode->HasChildNodes(&hasChildren);
-
- if (hasChildren) {
- int32_t anchorOffset;
- rv = selection->GetAnchorOffset(&anchorOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- selectedNode = GetChildAt(anchorNode, anchorOffset);
- if (!selectedNode) {
- selectedNode = anchorNode;
- // If anchor doesn't have a child, we can't be selecting a table element,
- // so don't do the following:
- } else {
- nsCOMPtr<nsIAtom> atom = EditorBase::GetTag(selectedNode);
-
- if (atom == nsGkAtoms::td) {
- tableOrCellElement = do_QueryInterface(selectedNode);
- aTagName = tdName;
- // Each cell is in its own selection range,
- // so count signals multiple-cell selection
- rv = selection->GetRangeCount(aSelectedCount);
- NS_ENSURE_SUCCESS(rv, rv);
- } else if (atom == nsGkAtoms::table) {
- tableOrCellElement = do_QueryInterface(selectedNode);
- aTagName.AssignLiteral("table");
- *aSelectedCount = 1;
- } else if (atom == nsGkAtoms::tr) {
- tableOrCellElement = do_QueryInterface(selectedNode);
- aTagName.AssignLiteral("tr");
- *aSelectedCount = 1;
- }
- }
- }
- if (!tableOrCellElement) {
- // Didn't find a table element -- find a cell parent
- rv = GetElementOrParentByTagName(tdName, anchorNode,
- getter_AddRefs(tableOrCellElement));
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (tableOrCellElement) {
- aTagName = tdName;
- }
- }
- }
- if (tableOrCellElement) {
- *aTableElement = tableOrCellElement.get();
- NS_ADDREF(*aTableElement);
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLEditor::GetSelectedCellsType(nsIDOMElement* aElement,
- uint32_t* aSelectionType)
-{
- NS_ENSURE_ARG_POINTER(aSelectionType);
- *aSelectionType = 0;
-
- // Be sure we have a table element
- // (if aElement is null, this uses selection's anchor node)
- nsCOMPtr<nsIDOMElement> table;
-
- nsresult rv =
- GetElementOrParentByTagName(NS_LITERAL_STRING("table"), aElement,
- getter_AddRefs(table));
- NS_ENSURE_SUCCESS(rv, rv);
-
- int32_t rowCount, colCount;
- rv = GetTableSize(table, &rowCount, &colCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Traverse all selected cells
- nsCOMPtr<nsIDOMElement> selectedCell;
- rv = GetFirstSelectedCell(nullptr, getter_AddRefs(selectedCell));
- NS_ENSURE_SUCCESS(rv, rv);
- if (rv == NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND) {
- return NS_OK;
- }
-
- // We have at least one selected cell, so set return value
- *aSelectionType = nsISelectionPrivate::TABLESELECTION_CELL;
-
- // Store indexes of each row/col to avoid duplication of searches
- nsTArray<int32_t> indexArray;
-
- bool allCellsInRowAreSelected = false;
- bool allCellsInColAreSelected = false;
- while (NS_SUCCEEDED(rv) && selectedCell) {
- // Get the cell's location in the cellmap
- int32_t startRowIndex, startColIndex;
- rv = GetCellIndexes(selectedCell, &startRowIndex, &startColIndex);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- if (!indexArray.Contains(startColIndex)) {
- indexArray.AppendElement(startColIndex);
- allCellsInRowAreSelected = AllCellsInRowSelected(table, startRowIndex, colCount);
- // We're done as soon as we fail for any row
- if (!allCellsInRowAreSelected) {
- break;
- }
- }
- rv = GetNextSelectedCell(nullptr, getter_AddRefs(selectedCell));
- }
-
- if (allCellsInRowAreSelected) {
- *aSelectionType = nsISelectionPrivate::TABLESELECTION_ROW;
- return NS_OK;
- }
- // Test for columns
-
- // Empty the indexArray
- indexArray.Clear();
-
- // Start at first cell again
- rv = GetFirstSelectedCell(nullptr, getter_AddRefs(selectedCell));
- while (NS_SUCCEEDED(rv) && selectedCell) {
- // Get the cell's location in the cellmap
- int32_t startRowIndex, startColIndex;
- rv = GetCellIndexes(selectedCell, &startRowIndex, &startColIndex);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- if (!indexArray.Contains(startRowIndex)) {
- indexArray.AppendElement(startColIndex);
- allCellsInColAreSelected = AllCellsInColumnSelected(table, startColIndex, rowCount);
- // We're done as soon as we fail for any column
- if (!allCellsInRowAreSelected) {
- break;
- }
- }
- rv = GetNextSelectedCell(nullptr, getter_AddRefs(selectedCell));
- }
- if (allCellsInColAreSelected) {
- *aSelectionType = nsISelectionPrivate::TABLESELECTION_COLUMN;
- }
-
- return NS_OK;
-}
-
-bool
-HTMLEditor::AllCellsInRowSelected(nsIDOMElement* aTable,
- int32_t aRowIndex,
- int32_t aNumberOfColumns)
-{
- NS_ENSURE_TRUE(aTable, false);
-
- int32_t curStartRowIndex, curStartColIndex, rowSpan, colSpan, actualRowSpan, actualColSpan;
- bool isSelected;
-
- for (int32_t col = 0; col < aNumberOfColumns;
- col += std::max(actualColSpan, 1)) {
- nsCOMPtr<nsIDOMElement> cell;
- nsresult rv = GetCellDataAt(aTable, aRowIndex, col, getter_AddRefs(cell),
- &curStartRowIndex, &curStartColIndex,
- &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
-
- NS_ENSURE_SUCCESS(rv, false);
- // If no cell, we may have a "ragged" right edge,
- // so return TRUE only if we already found a cell in the row
- NS_ENSURE_TRUE(cell, (col > 0) ? true : false);
-
- // Return as soon as a non-selected cell is found
- NS_ENSURE_TRUE(isSelected, false);
-
- NS_ASSERTION((actualColSpan > 0),"ActualColSpan = 0 in AllCellsInRowSelected");
- }
- return true;
-}
-
-bool
-HTMLEditor::AllCellsInColumnSelected(nsIDOMElement* aTable,
- int32_t aColIndex,
- int32_t aNumberOfRows)
-{
- NS_ENSURE_TRUE(aTable, false);
-
- int32_t curStartRowIndex, curStartColIndex, rowSpan, colSpan, actualRowSpan, actualColSpan;
- bool isSelected;
-
- for (int32_t row = 0; row < aNumberOfRows;
- row += std::max(actualRowSpan, 1)) {
- nsCOMPtr<nsIDOMElement> cell;
- nsresult rv = GetCellDataAt(aTable, row, aColIndex, getter_AddRefs(cell),
- &curStartRowIndex, &curStartColIndex,
- &rowSpan, &colSpan,
- &actualRowSpan, &actualColSpan, &isSelected);
-
- NS_ENSURE_SUCCESS(rv, false);
- // If no cell, we must have a "ragged" right edge on the last column
- // so return TRUE only if we already found a cell in the row
- NS_ENSURE_TRUE(cell, (row > 0) ? true : false);
-
- // Return as soon as a non-selected cell is found
- NS_ENSURE_TRUE(isSelected, false);
- }
- return true;
-}
-
-bool
-HTMLEditor::IsEmptyCell(dom::Element* aCell)
-{
- MOZ_ASSERT(aCell);
-
- // Check if target only contains empty text node or <br>
- nsCOMPtr<nsINode> cellChild = aCell->GetFirstChild();
- if (!cellChild) {
- return false;
- }
-
- nsCOMPtr<nsINode> nextChild = cellChild->GetNextSibling();
- if (nextChild) {
- return false;
- }
-
- // We insert a single break into a cell by default
- // to have some place to locate a cursor -- it is dispensable
- if (cellChild->IsHTMLElement(nsGkAtoms::br)) {
- return true;
- }
-
- bool isEmpty;
- // Or check if no real content
- nsresult rv = IsEmptyNode(cellChild, &isEmpty, false, false);
- NS_ENSURE_SUCCESS(rv, false);
- return isEmpty;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/HTMLURIRefObject.cpp b/editor/libeditor/HTMLURIRefObject.cpp
deleted file mode 100644
index 612451d85..000000000
--- a/editor/libeditor/HTMLURIRefObject.cpp
+++ /dev/null
@@ -1,262 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Here is the list, from beppe and glazman:
- href >> A, AREA, BASE, LINK
- src >> FRAME, IFRAME, IMG, INPUT, SCRIPT
- <META http-equiv="refresh" content="3,http://www.acme.com/intro.html">
- longdesc >> FRAME, IFRAME, IMG
- usemap >> IMG, INPUT, OBJECT
- action >> FORM
- background >> BODY
- codebase >> OBJECT, APPLET
- classid >> OBJECT
- data >> OBJECT
- cite >> BLOCKQUOTE, DEL, INS, Q
- profile >> HEAD
- ARCHIVE attribute on APPLET ; warning, it contains a list of URIs.
-
- Easier way of organizing the list:
- a: href
- area: href
- base: href
- body: background
- blockquote: cite (not normally rewritable)
- link: href
- frame: src, longdesc
- iframe: src, longdesc
- input: src, usemap
- form: action
- img: src, longdesc, usemap
- script: src
- applet: codebase, archive <list>
- object: codebase, data, classid, usemap
- head: profile
- del: cite
- ins: cite
- q: cite
- */
-
-#include "HTMLURIRefObject.h"
-
-#include "mozilla/mozalloc.h"
-#include "nsAString.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsID.h"
-#include "nsIDOMAttr.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMMozNamedAttrMap.h"
-#include "nsIDOMNode.h"
-#include "nsISupportsUtils.h"
-#include "nsString.h"
-
-namespace mozilla {
-
-// String classes change too often and I can't keep up.
-// Set this macro to this week's approved case-insensitive compare routine.
-#define MATCHES(tagName, str) tagName.EqualsIgnoreCase(str)
-
-HTMLURIRefObject::HTMLURIRefObject()
- : mCurAttrIndex(0)
- , mAttributeCnt(0)
-{
-}
-
-HTMLURIRefObject::~HTMLURIRefObject()
-{
-}
-
-//Interfaces for addref and release and queryinterface
-NS_IMPL_ISUPPORTS(HTMLURIRefObject, nsIURIRefObject)
-
-NS_IMETHODIMP
-HTMLURIRefObject::Reset()
-{
- mCurAttrIndex = 0;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLURIRefObject::GetNextURI(nsAString& aURI)
-{
- NS_ENSURE_TRUE(mNode, NS_ERROR_NOT_INITIALIZED);
-
- // XXX Why don't you use nsIAtom for comparing the tag name a lot?
- nsAutoString tagName;
- nsresult rv = mNode->GetNodeName(tagName);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Loop over attribute list:
- if (!mAttributes) {
- nsCOMPtr<nsIDOMElement> element (do_QueryInterface(mNode));
- NS_ENSURE_TRUE(element, NS_ERROR_INVALID_ARG);
-
- mCurAttrIndex = 0;
- element->GetAttributes(getter_AddRefs(mAttributes));
- NS_ENSURE_TRUE(mAttributes, NS_ERROR_NOT_INITIALIZED);
-
- rv = mAttributes->GetLength(&mAttributeCnt);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(mAttributeCnt, NS_ERROR_FAILURE);
- mCurAttrIndex = 0;
- }
-
- while (mCurAttrIndex < mAttributeCnt) {
- nsCOMPtr<nsIDOMAttr> attrNode;
- rv = mAttributes->Item(mCurAttrIndex++, getter_AddRefs(attrNode));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_ARG_POINTER(attrNode);
- nsString curAttr;
- rv = attrNode->GetName(curAttr);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // href >> A, AREA, BASE, LINK
- if (MATCHES(curAttr, "href")) {
- if (!MATCHES(tagName, "a") && !MATCHES(tagName, "area") &&
- !MATCHES(tagName, "base") && !MATCHES(tagName, "link")) {
- continue;
- }
- rv = attrNode->GetValue(aURI);
- NS_ENSURE_SUCCESS(rv, rv);
- nsString uri (aURI);
- // href pointing to a named anchor doesn't count
- if (aURI.First() != char16_t('#')) {
- return NS_OK;
- }
- aURI.Truncate();
- return NS_ERROR_INVALID_ARG;
- }
- // src >> FRAME, IFRAME, IMG, INPUT, SCRIPT
- else if (MATCHES(curAttr, "src")) {
- if (!MATCHES(tagName, "img") &&
- !MATCHES(tagName, "frame") && !MATCHES(tagName, "iframe") &&
- !MATCHES(tagName, "input") && !MATCHES(tagName, "script")) {
- continue;
- }
- return attrNode->GetValue(aURI);
- }
- //<META http-equiv="refresh" content="3,http://www.acme.com/intro.html">
- else if (MATCHES(curAttr, "content")) {
- if (!MATCHES(tagName, "meta")) {
- continue;
- }
- }
- // longdesc >> FRAME, IFRAME, IMG
- else if (MATCHES(curAttr, "longdesc")) {
- if (!MATCHES(tagName, "img") &&
- !MATCHES(tagName, "frame") && !MATCHES(tagName, "iframe")) {
- continue;
- }
- }
- // usemap >> IMG, INPUT, OBJECT
- else if (MATCHES(curAttr, "usemap")) {
- if (!MATCHES(tagName, "img") &&
- !MATCHES(tagName, "input") && !MATCHES(tagName, "object")) {
- continue;
- }
- }
- // action >> FORM
- else if (MATCHES(curAttr, "action")) {
- if (!MATCHES(tagName, "form")) {
- continue;
- }
- }
- // background >> BODY
- else if (MATCHES(curAttr, "background")) {
- if (!MATCHES(tagName, "body")) {
- continue;
- }
- }
- // codebase >> OBJECT, APPLET
- else if (MATCHES(curAttr, "codebase")) {
- if (!MATCHES(tagName, "meta")) {
- continue;
- }
- }
- // classid >> OBJECT
- else if (MATCHES(curAttr, "classid")) {
- if (!MATCHES(tagName, "object")) {
- continue;
- }
- }
- // data >> OBJECT
- else if (MATCHES(curAttr, "data")) {
- if (!MATCHES(tagName, "object")) {
- continue;
- }
- }
- // cite >> BLOCKQUOTE, DEL, INS, Q
- else if (MATCHES(curAttr, "cite")) {
- if (!MATCHES(tagName, "blockquote") && !MATCHES(tagName, "q") &&
- !MATCHES(tagName, "del") && !MATCHES(tagName, "ins")) {
- continue;
- }
- }
- // profile >> HEAD
- else if (MATCHES(curAttr, "profile")) {
- if (!MATCHES(tagName, "head")) {
- continue;
- }
- }
- // archive attribute on APPLET; warning, it contains a list of URIs.
- else if (MATCHES(curAttr, "archive")) {
- if (!MATCHES(tagName, "applet")) {
- continue;
- }
- }
- }
- // Return a code to indicate that there are no more,
- // to distinguish that case from real errors.
- return NS_ERROR_NOT_AVAILABLE;
-}
-
-NS_IMETHODIMP
-HTMLURIRefObject::RewriteAllURIs(const nsAString& aOldPat,
- const nsAString& aNewPat,
- bool aMakeRel)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-HTMLURIRefObject::GetNode(nsIDOMNode** aNode)
-{
- NS_ENSURE_TRUE(mNode, NS_ERROR_NOT_INITIALIZED);
- NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
- *aNode = mNode.get();
- NS_ADDREF(*aNode);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLURIRefObject::SetNode(nsIDOMNode* aNode)
-{
- mNode = aNode;
- nsAutoString dummyURI;
- if (NS_SUCCEEDED(GetNextURI(dummyURI))) {
- mCurAttrIndex = 0; // Reset so we'll get the first node next time
- return NS_OK;
- }
-
- // If there weren't any URIs in the attributes,
- // then don't accept this node.
- mNode = nullptr;
- return NS_ERROR_INVALID_ARG;
-}
-
-} // namespace mozilla
-
-nsresult NS_NewHTMLURIRefObject(nsIURIRefObject** aResult, nsIDOMNode* aNode)
-{
- RefPtr<mozilla::HTMLURIRefObject> refObject = new mozilla::HTMLURIRefObject();
- nsresult rv = refObject->SetNode(aNode);
- if (NS_FAILED(rv)) {
- *aResult = 0;
- return rv;
- }
- refObject.forget(aResult);
- return NS_OK;
-}
diff --git a/editor/libeditor/HTMLURIRefObject.h b/editor/libeditor/HTMLURIRefObject.h
deleted file mode 100644
index 47f7f1868..000000000
--- a/editor/libeditor/HTMLURIRefObject.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef HTMLURIRefObject_h
-#define HTMLURIRefObject_h
-
-#include "nsCOMPtr.h"
-#include "nsISupportsImpl.h"
-#include "nsIURIRefObject.h"
-#include "nscore.h"
-
-#define NS_URI_REF_OBJECT_CID \
-{ /* {bdd79df6-1dd1-11b2-b29c-c3d63a58f1d2} */ \
- 0xbdd79df6, 0x1dd1, 0x11b2, \
- { 0xb2, 0x9c, 0xc3, 0xd6, 0x3a, 0x58, 0xf1, 0xd2 } \
-}
-
-class nsIDOMMozNamedAttrMap;
-class nsIDOMNode;
-
-namespace mozilla {
-
-class HTMLURIRefObject final : public nsIURIRefObject
-{
-public:
- HTMLURIRefObject();
-
- // Interfaces for addref and release and queryinterface
- NS_DECL_ISUPPORTS
-
- NS_DECL_NSIURIREFOBJECT
-
-protected:
- virtual ~HTMLURIRefObject();
-
- nsCOMPtr<nsIDOMNode> mNode;
- nsCOMPtr<nsIDOMMozNamedAttrMap> mAttributes;
- uint32_t mCurAttrIndex;
- uint32_t mAttributeCnt;
-};
-
-} // namespace mozilla
-
-nsresult NS_NewHTMLURIRefObject(nsIURIRefObject** aResult, nsIDOMNode* aNode);
-
-#endif // #ifndef HTMLURIRefObject_h
diff --git a/editor/libeditor/InsertNodeTransaction.cpp b/editor/libeditor/InsertNodeTransaction.cpp
deleted file mode 100644
index 6317b8c15..000000000
--- a/editor/libeditor/InsertNodeTransaction.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "InsertNodeTransaction.h"
-
-#include "mozilla/EditorBase.h" // for EditorBase
-
-#include "mozilla/dom/Selection.h" // for Selection
-
-#include "nsAString.h"
-#include "nsDebug.h" // for NS_ENSURE_TRUE, etc.
-#include "nsError.h" // for NS_ERROR_NULL_POINTER, etc.
-#include "nsIContent.h" // for nsIContent
-#include "nsMemory.h" // for nsMemory
-#include "nsReadableUtils.h" // for ToNewCString
-#include "nsString.h" // for nsString
-
-namespace mozilla {
-
-using namespace dom;
-
-InsertNodeTransaction::InsertNodeTransaction(nsIContent& aNode,
- nsINode& aParent,
- int32_t aOffset,
- EditorBase& aEditorBase)
- : mNode(&aNode)
- , mParent(&aParent)
- , mOffset(aOffset)
- , mEditorBase(&aEditorBase)
-{
-}
-
-InsertNodeTransaction::~InsertNodeTransaction()
-{
-}
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(InsertNodeTransaction, EditTransactionBase,
- mEditorBase,
- mNode,
- mParent)
-
-NS_IMPL_ADDREF_INHERITED(InsertNodeTransaction, EditTransactionBase)
-NS_IMPL_RELEASE_INHERITED(InsertNodeTransaction, EditTransactionBase)
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InsertNodeTransaction)
-NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
-
-NS_IMETHODIMP
-InsertNodeTransaction::DoTransaction()
-{
- if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mNode) || NS_WARN_IF(!mParent)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- uint32_t count = mParent->GetChildCount();
- if (mOffset > static_cast<int32_t>(count) || mOffset == -1) {
- // -1 is sentinel value meaning "append at end"
- mOffset = count;
- }
-
- // Note, it's ok for ref to be null. That means append.
- nsCOMPtr<nsIContent> ref = mParent->GetChildAt(mOffset);
-
- mEditorBase->MarkNodeDirty(GetAsDOMNode(mNode));
-
- ErrorResult rv;
- mParent->InsertBefore(*mNode, ref, rv);
- NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult());
-
- // Only set selection to insertion point if editor gives permission
- if (mEditorBase->GetShouldTxnSetSelection()) {
- RefPtr<Selection> selection = mEditorBase->GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- // Place the selection just after the inserted element
- selection->Collapse(mParent, mOffset + 1);
- } else {
- // Do nothing - DOM Range gravity will adjust selection
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-InsertNodeTransaction::UndoTransaction()
-{
- if (NS_WARN_IF(!mNode) || NS_WARN_IF(!mParent)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
- ErrorResult rv;
- mParent->RemoveChild(*mNode, rv);
- return rv.StealNSResult();
-}
-
-NS_IMETHODIMP
-InsertNodeTransaction::GetTxnDescription(nsAString& aString)
-{
- aString.AssignLiteral("InsertNodeTransaction");
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/InsertNodeTransaction.h b/editor/libeditor/InsertNodeTransaction.h
deleted file mode 100644
index 1b9739d6c..000000000
--- a/editor/libeditor/InsertNodeTransaction.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef InsertNodeTransaction_h
-#define InsertNodeTransaction_h
-
-#include "mozilla/EditTransactionBase.h" // for EditTransactionBase, etc.
-#include "nsCOMPtr.h" // for nsCOMPtr
-#include "nsCycleCollectionParticipant.h"
-#include "nsIContent.h" // for nsIContent
-#include "nsISupportsImpl.h" // for NS_DECL_ISUPPORTS_INHERITED
-
-namespace mozilla {
-
-class EditorBase;
-
-/**
- * A transaction that inserts a single element
- */
-class InsertNodeTransaction final : public EditTransactionBase
-{
-public:
- /**
- * Initialize the transaction.
- * @param aNode The node to insert.
- * @param aParent The node to insert into.
- * @param aOffset The offset in aParent to insert aNode.
- */
- InsertNodeTransaction(nsIContent& aNode, nsINode& aParent, int32_t aOffset,
- EditorBase& aEditorBase);
-
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(InsertNodeTransaction,
- EditTransactionBase)
-
- NS_DECL_EDITTRANSACTIONBASE
-
-protected:
- virtual ~InsertNodeTransaction();
-
- // The element to insert.
- nsCOMPtr<nsIContent> mNode;
-
- // The node into which the new node will be inserted.
- nsCOMPtr<nsINode> mParent;
-
- // The index in mParent for the new node.
- int32_t mOffset;
-
- // The editor for this transaction.
- RefPtr<EditorBase> mEditorBase;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef InsertNodeTransaction_h
diff --git a/editor/libeditor/InsertTextTransaction.cpp b/editor/libeditor/InsertTextTransaction.cpp
deleted file mode 100644
index 0434b2dd5..000000000
--- a/editor/libeditor/InsertTextTransaction.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "InsertTextTransaction.h"
-
-#include "mozilla/EditorBase.h" // mEditorBase
-#include "mozilla/SelectionState.h" // RangeUpdater
-#include "mozilla/dom/Selection.h" // Selection local var
-#include "mozilla/dom/Text.h" // mTextNode
-#include "nsAString.h" // nsAString parameter
-#include "nsDebug.h" // for NS_ASSERTION, etc.
-#include "nsError.h" // for NS_OK, etc.
-#include "nsQueryObject.h" // for do_QueryObject
-
-namespace mozilla {
-
-using namespace dom;
-
-InsertTextTransaction::InsertTextTransaction(Text& aTextNode,
- uint32_t aOffset,
- const nsAString& aStringToInsert,
- EditorBase& aEditorBase,
- RangeUpdater* aRangeUpdater)
- : mTextNode(&aTextNode)
- , mOffset(aOffset)
- , mStringToInsert(aStringToInsert)
- , mEditorBase(&aEditorBase)
- , mRangeUpdater(aRangeUpdater)
-{
-}
-
-InsertTextTransaction::~InsertTextTransaction()
-{
-}
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(InsertTextTransaction, EditTransactionBase,
- mEditorBase,
- mTextNode)
-
-NS_IMPL_ADDREF_INHERITED(InsertTextTransaction, EditTransactionBase)
-NS_IMPL_RELEASE_INHERITED(InsertTextTransaction, EditTransactionBase)
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InsertTextTransaction)
- if (aIID.Equals(NS_GET_IID(InsertTextTransaction))) {
- foundInterface = static_cast<nsITransaction*>(this);
- } else
-NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
-
-
-NS_IMETHODIMP
-InsertTextTransaction::DoTransaction()
-{
- if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode)) {
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- nsresult rv = mTextNode->InsertData(mOffset, mStringToInsert);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Only set selection to insertion point if editor gives permission
- if (mEditorBase->GetShouldTxnSetSelection()) {
- RefPtr<Selection> selection = mEditorBase->GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- DebugOnly<nsresult> rv =
- selection->Collapse(mTextNode, mOffset + mStringToInsert.Length());
- NS_ASSERTION(NS_SUCCEEDED(rv),
- "Selection could not be collapsed after insert");
- } else {
- // Do nothing - DOM Range gravity will adjust selection
- }
- mRangeUpdater->SelAdjInsertText(*mTextNode, mOffset, mStringToInsert);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-InsertTextTransaction::UndoTransaction()
-{
- return mTextNode->DeleteData(mOffset, mStringToInsert.Length());
-}
-
-NS_IMETHODIMP
-InsertTextTransaction::Merge(nsITransaction* aTransaction,
- bool* aDidMerge)
-{
- if (!aTransaction || !aDidMerge) {
- return NS_OK;
- }
- // Set out param default value
- *aDidMerge = false;
-
- // If aTransaction is a InsertTextTransaction, and if the selection hasn't
- // changed, then absorb it.
- RefPtr<InsertTextTransaction> otherTransaction = do_QueryObject(aTransaction);
- if (otherTransaction && IsSequentialInsert(*otherTransaction)) {
- nsAutoString otherData;
- otherTransaction->GetData(otherData);
- mStringToInsert += otherData;
- *aDidMerge = true;
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-InsertTextTransaction::GetTxnDescription(nsAString& aString)
-{
- aString.AssignLiteral("InsertTextTransaction: ");
- aString += mStringToInsert;
- return NS_OK;
-}
-
-/* ============ private methods ================== */
-
-void
-InsertTextTransaction::GetData(nsString& aResult)
-{
- aResult = mStringToInsert;
-}
-
-bool
-InsertTextTransaction::IsSequentialInsert(
- InsertTextTransaction& aOtherTransaction)
-{
- return aOtherTransaction.mTextNode == mTextNode &&
- aOtherTransaction.mOffset == mOffset + mStringToInsert.Length();
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/InsertTextTransaction.h b/editor/libeditor/InsertTextTransaction.h
deleted file mode 100644
index b6867ad76..000000000
--- a/editor/libeditor/InsertTextTransaction.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef InsertTextTransaction_h
-#define InsertTextTransaction_h
-
-#include "mozilla/EditTransactionBase.h" // base class
-#include "nsCycleCollectionParticipant.h" // various macros
-#include "nsID.h" // NS_DECLARE_STATIC_IID_ACCESSOR
-#include "nsISupportsImpl.h" // NS_DECL_ISUPPORTS_INHERITED
-#include "nsString.h" // nsString members
-#include "nscore.h" // NS_IMETHOD, nsAString
-
-class nsITransaction;
-
-#define NS_INSERTTEXTTXN_IID \
-{ 0x8c9ad77f, 0x22a7, 0x4d01, \
- { 0xb1, 0x59, 0x8a, 0x0f, 0xdb, 0x1d, 0x08, 0xe9 } }
-
-namespace mozilla {
-
-class EditorBase;
-class RangeUpdater;
-
-namespace dom {
-class Text;
-} // namespace dom
-
-/**
- * A transaction that inserts text into a content node.
- */
-class InsertTextTransaction final : public EditTransactionBase
-{
-public:
- NS_DECLARE_STATIC_IID_ACCESSOR(NS_INSERTTEXTTXN_IID)
-
- /**
- * @param aElement The text content node.
- * @param aOffset The location in aElement to do the insertion.
- * @param aString The new text to insert.
- * @param aPresShell Used to get and set the selection.
- * @param aRangeUpdater The range updater
- */
- InsertTextTransaction(dom::Text& aTextNode, uint32_t aOffset,
- const nsAString& aString, EditorBase& aEditorBase,
- RangeUpdater* aRangeUpdater);
-
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(InsertTextTransaction,
- EditTransactionBase)
-
- NS_DECL_EDITTRANSACTIONBASE
-
- NS_IMETHOD Merge(nsITransaction* aTransaction, bool* aDidMerge) override;
-
- /**
- * Return the string data associated with this transaction.
- */
- void GetData(nsString& aResult);
-
-private:
- virtual ~InsertTextTransaction();
-
- // Return true if aOtherTransaction immediately follows this transaction.
- bool IsSequentialInsert(InsertTextTransaction& aOtherTrasaction);
-
- // The Text node to operate upon.
- RefPtr<dom::Text> mTextNode;
-
- // The offset into mTextNode where the insertion is to take place.
- uint32_t mOffset;
-
- // The text to insert into mTextNode at mOffset.
- nsString mStringToInsert;
-
- // The editor, which we'll need to get the selection.
- RefPtr<EditorBase> mEditorBase;
-
- RangeUpdater* mRangeUpdater;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(InsertTextTransaction, NS_INSERTTEXTTXN_IID)
-
-} // namespace mozilla
-
-#endif // #ifndef InsertTextTransaction_h
diff --git a/editor/libeditor/InternetCiter.cpp b/editor/libeditor/InternetCiter.cpp
deleted file mode 100644
index ed9fa5549..000000000
--- a/editor/libeditor/InternetCiter.cpp
+++ /dev/null
@@ -1,366 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "InternetCiter.h"
-
-#include "nsAString.h"
-#include "nsCOMPtr.h"
-#include "nsCRT.h"
-#include "nsDebug.h"
-#include "nsDependentSubstring.h"
-#include "nsError.h"
-#include "nsILineBreaker.h"
-#include "nsLWBrkCIID.h"
-#include "nsServiceManagerUtils.h"
-#include "nsString.h"
-#include "nsStringIterator.h"
-
-namespace mozilla {
-
-const char16_t gt ('>');
-const char16_t space (' ');
-const char16_t nl ('\n');
-const char16_t cr('\r');
-
-/**
- * Mail citations using the Internet style: > This is a citation.
- */
-
-nsresult
-InternetCiter::GetCiteString(const nsAString& aInString,
- nsAString& aOutString)
-{
- aOutString.Truncate();
- char16_t uch = nl;
-
- // Strip trailing new lines which will otherwise turn up
- // as ugly quoted empty lines.
- nsReadingIterator <char16_t> beginIter,endIter;
- aInString.BeginReading(beginIter);
- aInString.EndReading(endIter);
- while(beginIter!= endIter &&
- (*endIter == cr || *endIter == nl)) {
- --endIter;
- }
-
- // Loop over the string:
- while (beginIter != endIter) {
- if (uch == nl) {
- aOutString.Append(gt);
- // No space between >: this is ">>> " style quoting, for
- // compatibility with RFC 2646 and format=flowed.
- if (*beginIter != gt) {
- aOutString.Append(space);
- }
- }
-
- uch = *beginIter;
- ++beginIter;
-
- aOutString += uch;
- }
-
- if (uch != nl) {
- aOutString += nl;
- }
- return NS_OK;
-}
-
-nsresult
-InternetCiter::StripCitesAndLinebreaks(const nsAString& aInString,
- nsAString& aOutString,
- bool aLinebreaksToo,
- int32_t* aCiteLevel)
-{
- if (aCiteLevel) {
- *aCiteLevel = 0;
- }
-
- aOutString.Truncate();
- nsReadingIterator <char16_t> beginIter,endIter;
- aInString.BeginReading(beginIter);
- aInString.EndReading(endIter);
- while (beginIter!= endIter) { // loop over lines
- // Clear out cites first, at the beginning of the line:
- int32_t thisLineCiteLevel = 0;
- while (beginIter!= endIter &&
- (*beginIter == gt || nsCRT::IsAsciiSpace(*beginIter))) {
- if (*beginIter == gt) {
- ++thisLineCiteLevel;
- }
- ++beginIter;
- }
- // Now copy characters until line end:
- while (beginIter != endIter && (*beginIter != '\r' && *beginIter != '\n')) {
- aOutString.Append(*beginIter);
- ++beginIter;
- }
- if (aLinebreaksToo) {
- aOutString.Append(char16_t(' '));
- } else {
- aOutString.Append(char16_t('\n')); // DOM linebreaks, not NS_LINEBREAK
- }
- // Skip over any more consecutive linebreak-like characters:
- while (beginIter != endIter && (*beginIter == '\r' || *beginIter == '\n')) {
- ++beginIter;
- }
- // Done with this line -- update cite level
- if (aCiteLevel && (thisLineCiteLevel > *aCiteLevel)) {
- *aCiteLevel = thisLineCiteLevel;
- }
- }
- return NS_OK;
-}
-
-nsresult
-InternetCiter::StripCites(const nsAString& aInString,
- nsAString& aOutString)
-{
- return StripCitesAndLinebreaks(aInString, aOutString, false, 0);
-}
-
-static void AddCite(nsAString& aOutString, int32_t citeLevel)
-{
- for (int32_t i = 0; i < citeLevel; ++i) {
- aOutString.Append(gt);
- }
- if (citeLevel > 0) {
- aOutString.Append(space);
- }
-}
-
-static inline void
-BreakLine(nsAString& aOutString, uint32_t& outStringCol,
- uint32_t citeLevel)
-{
- aOutString.Append(nl);
- if (citeLevel > 0) {
- AddCite(aOutString, citeLevel);
- outStringCol = citeLevel + 1;
- } else {
- outStringCol = 0;
- }
-}
-
-static inline bool IsSpace(char16_t c)
-{
- const char16_t nbsp (0xa0);
- return (nsCRT::IsAsciiSpace(c) || (c == nl) || (c == cr) || (c == nbsp));
-}
-
-nsresult
-InternetCiter::Rewrap(const nsAString& aInString,
- uint32_t aWrapCol,
- uint32_t aFirstLineOffset,
- bool aRespectNewlines,
- nsAString& aOutString)
-{
- // There shouldn't be returns in this string, only dom newlines.
- // Check to make sure:
-#ifdef DEBUG
- int32_t cr = aInString.FindChar(char16_t('\r'));
- NS_ASSERTION((cr < 0), "Rewrap: CR in string gotten from DOM!\n");
-#endif /* DEBUG */
-
- aOutString.Truncate();
-
- nsresult rv;
- nsCOMPtr<nsILineBreaker> lineBreaker = do_GetService(NS_LBRK_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Loop over lines in the input string, rewrapping each one.
- uint32_t length;
- uint32_t posInString = 0;
- uint32_t outStringCol = 0;
- uint32_t citeLevel = 0;
- const nsPromiseFlatString &tString = PromiseFlatString(aInString);
- length = tString.Length();
- while (posInString < length) {
- // Get the new cite level here since we're at the beginning of a line
- uint32_t newCiteLevel = 0;
- while (posInString < length && tString[posInString] == gt) {
- ++newCiteLevel;
- ++posInString;
- while (posInString < length && tString[posInString] == space) {
- ++posInString;
- }
- }
- if (posInString >= length) {
- break;
- }
-
- // Special case: if this is a blank line, maintain a blank line
- // (retain the original paragraph breaks)
- if (tString[posInString] == nl && !aOutString.IsEmpty()) {
- if (aOutString.Last() != nl) {
- aOutString.Append(nl);
- }
- AddCite(aOutString, newCiteLevel);
- aOutString.Append(nl);
-
- ++posInString;
- outStringCol = 0;
- continue;
- }
-
- // If the cite level has changed, then start a new line with the
- // new cite level (but if we're at the beginning of the string,
- // don't bother).
- if (newCiteLevel != citeLevel && posInString > newCiteLevel+1 &&
- outStringCol) {
- BreakLine(aOutString, outStringCol, 0);
- }
- citeLevel = newCiteLevel;
-
- // Prepend the quote level to the out string if appropriate
- if (!outStringCol) {
- AddCite(aOutString, citeLevel);
- outStringCol = citeLevel + (citeLevel ? 1 : 0);
- }
- // If it's not a cite, and we're not at the beginning of a line in
- // the output string, add a space to separate new text from the
- // previous text.
- else if (outStringCol > citeLevel) {
- aOutString.Append(space);
- ++outStringCol;
- }
-
- // find the next newline -- don't want to go farther than that
- int32_t nextNewline = tString.FindChar(nl, posInString);
- if (nextNewline < 0) {
- nextNewline = length;
- }
-
- // For now, don't wrap unquoted lines at all.
- // This is because the plaintext edit window has already wrapped them
- // by the time we get them for rewrap, yet when we call the line
- // breaker, it will refuse to break backwards, and we'll end up
- // with a line that's too long and gets displayed as a lone word
- // on a line by itself. Need special logic to detect this case
- // and break it ourselves without resorting to the line breaker.
- if (!citeLevel) {
- aOutString.Append(Substring(tString, posInString,
- nextNewline-posInString));
- outStringCol += nextNewline - posInString;
- if (nextNewline != (int32_t)length) {
- aOutString.Append(nl);
- outStringCol = 0;
- }
- posInString = nextNewline+1;
- continue;
- }
-
- // Otherwise we have to use the line breaker and loop
- // over this line of the input string to get all of it:
- while ((int32_t)posInString < nextNewline) {
- // Skip over initial spaces:
- while ((int32_t)posInString < nextNewline &&
- nsCRT::IsAsciiSpace(tString[posInString])) {
- ++posInString;
- }
-
- // If this is a short line, just append it and continue:
- if (outStringCol + nextNewline - posInString <= aWrapCol-citeLevel-1) {
- // If this short line is the final one in the in string,
- // then we need to include the final newline, if any:
- if (nextNewline+1 == (int32_t)length && tString[nextNewline-1] == nl) {
- ++nextNewline;
- }
- // Trim trailing spaces:
- int32_t lastRealChar = nextNewline;
- while ((uint32_t)lastRealChar > posInString &&
- nsCRT::IsAsciiSpace(tString[lastRealChar-1])) {
- --lastRealChar;
- }
-
- aOutString += Substring(tString,
- posInString, lastRealChar - posInString);
- outStringCol += lastRealChar - posInString;
- posInString = nextNewline + 1;
- continue;
- }
-
- int32_t eol = posInString + aWrapCol - citeLevel - outStringCol;
- // eol is the prospective end of line.
- // We'll first look backwards from there for a place to break.
- // If it's already less than our current position,
- // then our line is already too long, so break now.
- if (eol <= (int32_t)posInString) {
- BreakLine(aOutString, outStringCol, citeLevel);
- continue; // continue inner loop, with outStringCol now at bol
- }
-
- int32_t breakPt = 0;
- // XXX Why this uses NS_ERROR_"BASE"?
- rv = NS_ERROR_BASE;
- if (lineBreaker) {
- breakPt = lineBreaker->Prev(tString.get() + posInString,
- length - posInString, eol + 1 - posInString);
- if (breakPt == NS_LINEBREAKER_NEED_MORE_TEXT) {
- // if we couldn't find a breakpoint looking backwards,
- // and we're not starting a new line, then end this line
- // and loop around again:
- if (outStringCol > citeLevel + 1) {
- BreakLine(aOutString, outStringCol, citeLevel);
- continue; // continue inner loop, with outStringCol now at bol
- }
-
- // Else try looking forwards:
- breakPt = lineBreaker->Next(tString.get() + posInString,
- length - posInString, eol - posInString);
-
- rv = breakPt == NS_LINEBREAKER_NEED_MORE_TEXT ? NS_ERROR_BASE :
- NS_OK;
- } else {
- rv = NS_OK;
- }
- }
- // If rv is okay, then breakPt is the place to break.
- // If we get out here and rv is set, something went wrong with line
- // breaker. Just break the line, hard.
- if (NS_FAILED(rv)) {
- breakPt = eol;
- }
-
- // Special case: maybe we should have wrapped last time.
- // If the first breakpoint here makes the current line too long,
- // then if we already have text on the current line,
- // break and loop around again.
- // If we're at the beginning of the current line, though,
- // don't force a break since the long word might be a url
- // and breaking it would make it unclickable on the other end.
- const int SLOP = 6;
- if (outStringCol + breakPt > aWrapCol + SLOP &&
- outStringCol > citeLevel+1) {
- BreakLine(aOutString, outStringCol, citeLevel);
- continue;
- }
-
- nsAutoString sub (Substring(tString, posInString, breakPt));
- // skip newlines or whitespace at the end of the string
- int32_t subend = sub.Length();
- while (subend > 0 && IsSpace(sub[subend-1])) {
- --subend;
- }
- sub.Left(sub, subend);
- aOutString += sub;
- outStringCol += sub.Length();
- // Advance past the whitespace which caused the wrap:
- posInString += breakPt;
- while (posInString < length && IsSpace(tString[posInString])) {
- ++posInString;
- }
-
- // Add a newline and the quote level to the out string
- if (posInString < length) { // not for the last line, though
- BreakLine(aOutString, outStringCol, citeLevel);
- }
- } // end inner loop within one line of aInString
- } // end outer loop over lines of aInString
-
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/InternetCiter.h b/editor/libeditor/InternetCiter.h
deleted file mode 100644
index d1a861678..000000000
--- a/editor/libeditor/InternetCiter.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef InternetCiter_h
-#define InternetCiter_h
-
-#include "nscore.h"
-#include "nsStringFwd.h"
-
-namespace mozilla {
-
-/**
- * Mail citations using standard Internet style.
- */
-class InternetCiter final
-{
-public:
- static nsresult GetCiteString(const nsAString& aInString,
- nsAString& aOutString);
-
- static nsresult StripCites(const nsAString& aInString,
- nsAString& aOutString);
-
- static nsresult Rewrap(const nsAString& aInString,
- uint32_t aWrapCol, uint32_t aFirstLineOffset,
- bool aRespectNewlines,
- nsAString& aOutString);
-
-protected:
- static nsresult StripCitesAndLinebreaks(const nsAString& aInString,
- nsAString& aOutString,
- bool aLinebreaksToo,
- int32_t* aCiteLevel);
-};
-
-} // namespace mozilla
-
-#endif // #ifndef InternetCiter_h
diff --git a/editor/libeditor/JoinNodeTransaction.cpp b/editor/libeditor/JoinNodeTransaction.cpp
deleted file mode 100644
index 50727cce1..000000000
--- a/editor/libeditor/JoinNodeTransaction.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "JoinNodeTransaction.h"
-
-#include "mozilla/EditorBase.h" // for EditorBase
-#include "nsAString.h"
-#include "nsDebug.h" // for NS_ASSERTION, etc.
-#include "nsError.h" // for NS_ERROR_NULL_POINTER, etc.
-#include "nsIContent.h" // for nsIContent
-#include "nsIDOMCharacterData.h" // for nsIDOMCharacterData
-#include "nsIEditor.h" // for EditorBase::IsModifiableNode
-#include "nsISupportsImpl.h" // for QueryInterface, etc.
-
-namespace mozilla {
-
-using namespace dom;
-
-JoinNodeTransaction::JoinNodeTransaction(EditorBase& aEditorBase,
- nsINode& aLeftNode,
- nsINode& aRightNode)
- : mEditorBase(&aEditorBase)
- , mLeftNode(&aLeftNode)
- , mRightNode(&aRightNode)
- , mOffset(0)
-{
-}
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(JoinNodeTransaction, EditTransactionBase,
- mEditorBase,
- mLeftNode,
- mRightNode,
- mParent)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(JoinNodeTransaction)
-NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
-
-nsresult
-JoinNodeTransaction::CheckValidity()
-{
- if (NS_WARN_IF(!mEditorBase) ||
- !mEditorBase->IsModifiableNode(mLeftNode->GetParentNode())) {
- return NS_ERROR_FAILURE;
- }
- return NS_OK;
-}
-
-// After DoTransaction() and RedoTransaction(), the left node is removed from
-// the content tree and right node remains.
-NS_IMETHODIMP
-JoinNodeTransaction::DoTransaction()
-{
- if (NS_WARN_IF(!mEditorBase) ||
- NS_WARN_IF(!mLeftNode) ||
- NS_WARN_IF(!mRightNode)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // Get the parent node
- nsCOMPtr<nsINode> leftParent = mLeftNode->GetParentNode();
- NS_ENSURE_TRUE(leftParent, NS_ERROR_NULL_POINTER);
-
- // Verify that mLeftNode and mRightNode have the same parent
- if (leftParent != mRightNode->GetParentNode()) {
- NS_ASSERTION(false, "Nodes do not have same parent");
- return NS_ERROR_INVALID_ARG;
- }
-
- // Set this instance's mParent. Other methods will see a non-null mParent
- // and know all is well
- mParent = leftParent;
- mOffset = mLeftNode->Length();
-
- return mEditorBase->JoinNodesImpl(mRightNode, mLeftNode, mParent);
-}
-
-//XXX: What if instead of split, we just deleted the unneeded children of
-// mRight and re-inserted mLeft?
-NS_IMETHODIMP
-JoinNodeTransaction::UndoTransaction()
-{
- if (NS_WARN_IF(!mParent) ||
- NS_WARN_IF(!mRightNode) ||
- NS_WARN_IF(!mLeftNode)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // First, massage the existing node so it is in its post-split state
- ErrorResult rv;
- if (mRightNode->GetAsText()) {
- rv = mRightNode->GetAsText()->DeleteData(0, mOffset);
- } else {
- nsCOMPtr<nsIContent> child = mRightNode->GetFirstChild();
- for (uint32_t i = 0; i < mOffset; i++) {
- if (rv.Failed()) {
- return rv.StealNSResult();
- }
- if (!child) {
- return NS_ERROR_NULL_POINTER;
- }
- nsCOMPtr<nsIContent> nextSibling = child->GetNextSibling();
- mLeftNode->AppendChild(*child, rv);
- child = nextSibling;
- }
- }
- // Second, re-insert the left node into the tree
- nsCOMPtr<nsINode> refNode = mRightNode;
- mParent->InsertBefore(*mLeftNode, refNode, rv);
- return rv.StealNSResult();
-}
-
-NS_IMETHODIMP
-JoinNodeTransaction::GetTxnDescription(nsAString& aString)
-{
- aString.AssignLiteral("JoinNodeTransaction");
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/JoinNodeTransaction.h b/editor/libeditor/JoinNodeTransaction.h
deleted file mode 100644
index 827d9dfaf..000000000
--- a/editor/libeditor/JoinNodeTransaction.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef JoinNodeTransaction_h
-#define JoinNodeTransaction_h
-
-#include "mozilla/EditTransactionBase.h" // for EditTransactionBase, etc.
-#include "nsCOMPtr.h" // for nsCOMPtr
-#include "nsCycleCollectionParticipant.h"
-#include "nsID.h" // for REFNSIID
-#include "nscore.h" // for NS_IMETHOD
-
-class nsINode;
-
-namespace mozilla {
-
-class EditorBase;
-
-/**
- * A transaction that joins two nodes E1 (left node) and E2 (right node) into a
- * single node E. The children of E are the children of E1 followed by the
- * children of E2. After DoTransaction() and RedoTransaction(), E1 is removed
- * from the content tree and E2 remains.
- */
-class JoinNodeTransaction final : public EditTransactionBase
-{
-public:
- /**
- * @param aEditorBase The provider of core editing operations.
- * @param aLeftNode The first of two nodes to join.
- * @param aRightNode The second of two nodes to join.
- */
- JoinNodeTransaction(EditorBase& aEditorBase,
- nsINode& aLeftNode, nsINode& aRightNode);
-
- /**
- * Call this after constructing to ensure the inputs are correct.
- */
- nsresult CheckValidity();
-
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(JoinNodeTransaction,
- EditTransactionBase)
- NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
-
- NS_DECL_EDITTRANSACTIONBASE
-
-protected:
- RefPtr<EditorBase> mEditorBase;
-
- // The nodes to operate upon. After the merge, mRightNode remains and
- // mLeftNode is removed from the content tree.
- nsCOMPtr<nsINode> mLeftNode;
- nsCOMPtr<nsINode> mRightNode;
-
- // The offset into mNode where the children of mElement are split (for
- // undo). mOffset is the index of the first child in the right node. -1
- // means the left node had no children.
- uint32_t mOffset;
-
- // The parent node containing mLeftNode and mRightNode.
- nsCOMPtr<nsINode> mParent;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef JoinNodeTransaction_h
diff --git a/editor/libeditor/PlaceholderTransaction.cpp b/editor/libeditor/PlaceholderTransaction.cpp
deleted file mode 100644
index 142a85075..000000000
--- a/editor/libeditor/PlaceholderTransaction.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "PlaceholderTransaction.h"
-
-#include "CompositionTransaction.h"
-#include "mozilla/EditorBase.h"
-#include "mozilla/dom/Selection.h"
-#include "mozilla/Move.h"
-#include "nsGkAtoms.h"
-#include "nsQueryObject.h"
-
-namespace mozilla {
-
-using namespace dom;
-
-PlaceholderTransaction::PlaceholderTransaction(
- EditorBase& aEditorBase,
- nsIAtom* aName,
- UniquePtr<SelectionState> aSelState)
- : mAbsorb(true)
- , mForwarding(nullptr)
- , mCompositionTransaction(nullptr)
- , mCommitted(false)
- , mStartSel(Move(aSelState))
- , mEditorBase(&aEditorBase)
-{
- mName = aName;
-}
-
-PlaceholderTransaction::~PlaceholderTransaction()
-{
-}
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(PlaceholderTransaction)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PlaceholderTransaction,
- EditAggregateTransaction)
- if (tmp->mStartSel) {
- ImplCycleCollectionUnlink(*tmp->mStartSel);
- }
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditorBase);
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mEndSel);
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PlaceholderTransaction,
- EditAggregateTransaction)
- if (tmp->mStartSel) {
- ImplCycleCollectionTraverse(cb, *tmp->mStartSel, "mStartSel", 0);
- }
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEditorBase);
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEndSel);
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PlaceholderTransaction)
- NS_INTERFACE_MAP_ENTRY(nsIAbsorbingTransaction)
-NS_INTERFACE_MAP_END_INHERITING(EditAggregateTransaction)
-
-NS_IMPL_ADDREF_INHERITED(PlaceholderTransaction, EditAggregateTransaction)
-NS_IMPL_RELEASE_INHERITED(PlaceholderTransaction, EditAggregateTransaction)
-
-NS_IMETHODIMP
-PlaceholderTransaction::DoTransaction()
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-PlaceholderTransaction::UndoTransaction()
-{
- if (NS_WARN_IF(!mEditorBase)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // Undo transactions.
- nsresult rv = EditAggregateTransaction::UndoTransaction();
- NS_ENSURE_SUCCESS(rv, rv);
-
- NS_ENSURE_TRUE(mStartSel, NS_ERROR_NULL_POINTER);
-
- // now restore selection
- RefPtr<Selection> selection = mEditorBase->GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- return mStartSel->RestoreSelection(selection);
-}
-
-NS_IMETHODIMP
-PlaceholderTransaction::RedoTransaction()
-{
- if (NS_WARN_IF(!mEditorBase)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // Redo transactions.
- nsresult rv = EditAggregateTransaction::RedoTransaction();
- NS_ENSURE_SUCCESS(rv, rv);
-
- // now restore selection
- RefPtr<Selection> selection = mEditorBase->GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- return mEndSel.RestoreSelection(selection);
-}
-
-
-NS_IMETHODIMP
-PlaceholderTransaction::Merge(nsITransaction* aTransaction,
- bool* aDidMerge)
-{
- NS_ENSURE_TRUE(aDidMerge && aTransaction, NS_ERROR_NULL_POINTER);
-
- // set out param default value
- *aDidMerge=false;
-
- if (mForwarding) {
- NS_NOTREACHED("tried to merge into a placeholder that was in forwarding mode!");
- return NS_ERROR_FAILURE;
- }
-
- // check to see if aTransaction is one of the editor's
- // private transactions. If not, we want to avoid merging
- // the foreign transaction into our placeholder since we
- // don't know what it does.
-
- nsCOMPtr<nsPIEditorTransaction> pTxn = do_QueryInterface(aTransaction);
- NS_ENSURE_TRUE(pTxn, NS_OK); // it's foreign so just bail!
-
- // XXX: hack, not safe! need nsIEditTransaction!
- EditTransactionBase* editTransactionBase = (EditTransactionBase*)aTransaction;
- // determine if this incoming txn is a placeholder txn
- nsCOMPtr<nsIAbsorbingTransaction> absorbingTransaction =
- do_QueryObject(editTransactionBase);
-
- // We are absorbing all transactions if mAbsorb is lit.
- if (mAbsorb) {
- RefPtr<CompositionTransaction> otherTransaction =
- do_QueryObject(aTransaction);
- if (otherTransaction) {
- // special handling for CompositionTransaction's: they need to merge with
- // any previous CompositionTransaction in this placeholder, if possible.
- if (!mCompositionTransaction) {
- // this is the first IME txn in the placeholder
- mCompositionTransaction = otherTransaction;
- AppendChild(editTransactionBase);
- } else {
- bool didMerge;
- mCompositionTransaction->Merge(otherTransaction, &didMerge);
- if (!didMerge) {
- // it wouldn't merge. Earlier IME txn is already committed and will
- // not absorb further IME txns. So just stack this one after it
- // and remember it as a candidate for further merges.
- mCompositionTransaction = otherTransaction;
- AppendChild(editTransactionBase);
- }
- }
- } else if (!absorbingTransaction) {
- // See bug 171243: just drop incoming placeholders on the floor.
- // Their children will be swallowed by this preexisting one.
- AppendChild(editTransactionBase);
- }
- *aDidMerge = true;
-// RememberEndingSelection();
-// efficiency hack: no need to remember selection here, as we haven't yet
-// finished the initial batch and we know we will be told when the batch ends.
-// we can remeber the selection then.
- } else {
- // merge typing or IME or deletion transactions if the selection matches
- if ((mName.get() == nsGkAtoms::TypingTxnName ||
- mName.get() == nsGkAtoms::IMETxnName ||
- mName.get() == nsGkAtoms::DeleteTxnName) && !mCommitted) {
- if (absorbingTransaction) {
- nsCOMPtr<nsIAtom> atom;
- absorbingTransaction->GetTxnName(getter_AddRefs(atom));
- if (atom && atom == mName) {
- // check if start selection of next placeholder matches
- // end selection of this placeholder
- bool isSame;
- absorbingTransaction->StartSelectionEquals(&mEndSel, &isSame);
- if (isSame) {
- mAbsorb = true; // we need to start absorbing again
- absorbingTransaction->ForwardEndBatchTo(this);
- // AppendChild(editTransactionBase);
- // see bug 171243: we don't need to merge placeholders
- // into placeholders. We just reactivate merging in the pre-existing
- // placeholder and drop the new one on the floor. The EndPlaceHolderBatch()
- // call on the new placeholder will be forwarded to this older one.
- RememberEndingSelection();
- *aDidMerge = true;
- }
- }
- }
- }
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-PlaceholderTransaction::GetTxnDescription(nsAString& aString)
-{
- aString.AssignLiteral("PlaceholderTransaction: ");
-
- if (mName) {
- nsAutoString name;
- mName->ToString(name);
- aString += name;
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-PlaceholderTransaction::GetTxnName(nsIAtom** aName)
-{
- return GetName(aName);
-}
-
-NS_IMETHODIMP
-PlaceholderTransaction::StartSelectionEquals(SelectionState* aSelState,
- bool* aResult)
-{
- // determine if starting selection matches the given selection state.
- // note that we only care about collapsed selections.
- NS_ENSURE_TRUE(aResult && aSelState, NS_ERROR_NULL_POINTER);
- if (!mStartSel->IsCollapsed() || !aSelState->IsCollapsed()) {
- *aResult = false;
- return NS_OK;
- }
- *aResult = mStartSel->IsEqual(aSelState);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-PlaceholderTransaction::EndPlaceHolderBatch()
-{
- mAbsorb = false;
-
- if (mForwarding) {
- nsCOMPtr<nsIAbsorbingTransaction> plcTxn = do_QueryReferent(mForwarding);
- if (plcTxn) {
- plcTxn->EndPlaceHolderBatch();
- }
- }
- // remember our selection state.
- return RememberEndingSelection();
-}
-
-NS_IMETHODIMP
-PlaceholderTransaction::ForwardEndBatchTo(
- nsIAbsorbingTransaction* aForwardingAddress)
-{
- mForwarding = do_GetWeakReference(aForwardingAddress);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-PlaceholderTransaction::Commit()
-{
- mCommitted = true;
- return NS_OK;
-}
-
-nsresult
-PlaceholderTransaction::RememberEndingSelection()
-{
- if (NS_WARN_IF(!mEditorBase)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- RefPtr<Selection> selection = mEditorBase->GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- mEndSel.SaveSelection(selection);
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/PlaceholderTransaction.h b/editor/libeditor/PlaceholderTransaction.h
deleted file mode 100644
index 5fa58a1e9..000000000
--- a/editor/libeditor/PlaceholderTransaction.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef PlaceholderTransaction_h
-#define PlaceholderTransaction_h
-
-#include "EditAggregateTransaction.h"
-#include "mozilla/EditorUtils.h"
-#include "mozilla/UniquePtr.h"
-#include "mozilla/WeakPtr.h"
-#include "nsIAbsorbingTransaction.h"
-#include "nsIDOMNode.h"
-#include "nsCOMPtr.h"
-#include "nsWeakPtr.h"
-#include "nsWeakReference.h"
-
-namespace mozilla {
-
-class CompositionTransaction;
-
-/**
- * An aggregate transaction that knows how to absorb all subsequent
- * transactions with the same name. This transaction does not "Do" anything.
- * But it absorbs other transactions via merge, and can undo/redo the
- * transactions it has absorbed.
- */
-
-class PlaceholderTransaction final
- : public EditAggregateTransaction
- , public nsIAbsorbingTransaction
- , public SupportsWeakPtr<PlaceholderTransaction>
-{
-public:
- MOZ_DECLARE_WEAKREFERENCE_TYPENAME(PlaceholderTransaction)
-
- NS_DECL_ISUPPORTS_INHERITED
-
- PlaceholderTransaction(EditorBase& aEditorBase, nsIAtom* aName,
- UniquePtr<SelectionState> aSelState);
-
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PlaceholderTransaction,
- EditAggregateTransaction)
-// ------------ EditAggregateTransaction -----------------------
-
- NS_DECL_EDITTRANSACTIONBASE
-
- NS_IMETHOD RedoTransaction() override;
- NS_IMETHOD Merge(nsITransaction* aTransaction, bool* aDidMerge) override;
-
-// ------------ nsIAbsorbingTransaction -----------------------
-
- NS_IMETHOD GetTxnName(nsIAtom** aName) override;
-
- NS_IMETHOD StartSelectionEquals(SelectionState* aSelState,
- bool* aResult) override;
-
- NS_IMETHOD EndPlaceHolderBatch() override;
-
- NS_IMETHOD ForwardEndBatchTo(
- nsIAbsorbingTransaction* aForwardingAddress) override;
-
- NS_IMETHOD Commit() override;
-
- NS_IMETHOD_(PlaceholderTransaction*) AsPlaceholderTransaction() override
- {
- return this;
- }
-
- nsresult RememberEndingSelection();
-
-protected:
- virtual ~PlaceholderTransaction();
-
- // Do we auto absorb any and all transaction?
- bool mAbsorb;
- nsWeakPtr mForwarding;
- // First IME txn in this placeholder - used for IME merging.
- mozilla::CompositionTransaction* mCompositionTransaction;
- // Do we stop auto absorbing any matching placeholder transactions?
- bool mCommitted;
-
- // These next two members store the state of the selection in a safe way.
- // Selection at the start of the transaction is stored, as is the selection
- // at the end. This is so that UndoTransaction() and RedoTransaction() can
- // restore the selection properly.
-
- // Use a pointer because this is constructed before we exist.
- UniquePtr<SelectionState> mStartSel;
- SelectionState mEndSel;
-
- // The editor for this transaction.
- RefPtr<EditorBase> mEditorBase;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef PlaceholderTransaction_h
diff --git a/editor/libeditor/SelectionState.cpp b/editor/libeditor/SelectionState.cpp
deleted file mode 100644
index 057e04875..000000000
--- a/editor/libeditor/SelectionState.cpp
+++ /dev/null
@@ -1,696 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/SelectionState.h"
-
-#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc.
-#include "mozilla/EditorUtils.h" // for EditorUtils
-#include "mozilla/dom/Selection.h" // for Selection
-#include "nsAString.h" // for nsAString_internal::Length
-#include "nsCycleCollectionParticipant.h"
-#include "nsDebug.h" // for NS_ENSURE_TRUE, etc.
-#include "nsError.h" // for NS_OK, etc.
-#include "nsIContent.h" // for nsIContent
-#include "nsIDOMCharacterData.h" // for nsIDOMCharacterData
-#include "nsIDOMNode.h" // for nsIDOMNode
-#include "nsISupportsImpl.h" // for nsRange::Release
-#include "nsRange.h" // for nsRange
-
-namespace mozilla {
-
-using namespace dom;
-
-/******************************************************************************
- * mozilla::SelectionState
- *
- * Class for recording selection info. Stores selection as collection of
- * { {startnode, startoffset} , {endnode, endoffset} } tuples. Can't store
- * ranges since dom gravity will possibly change the ranges.
- ******************************************************************************/
-SelectionState::SelectionState()
-{
-}
-
-SelectionState::~SelectionState()
-{
- MakeEmpty();
-}
-
-void
-SelectionState::SaveSelection(Selection* aSel)
-{
- MOZ_ASSERT(aSel);
- int32_t arrayCount = mArray.Length();
- int32_t rangeCount = aSel->RangeCount();
-
- // if we need more items in the array, new them
- if (arrayCount < rangeCount) {
- for (int32_t i = arrayCount; i < rangeCount; i++) {
- mArray.AppendElement();
- mArray[i] = new RangeItem();
- }
- } else if (arrayCount > rangeCount) {
- // else if we have too many, delete them
- for (int32_t i = arrayCount - 1; i >= rangeCount; i--) {
- mArray.RemoveElementAt(i);
- }
- }
-
- // now store the selection ranges
- for (int32_t i = 0; i < rangeCount; i++) {
- mArray[i]->StoreRange(aSel->GetRangeAt(i));
- }
-}
-
-nsresult
-SelectionState::RestoreSelection(Selection* aSel)
-{
- NS_ENSURE_TRUE(aSel, NS_ERROR_NULL_POINTER);
-
- // clear out selection
- aSel->RemoveAllRanges();
-
- // set the selection ranges anew
- size_t arrayCount = mArray.Length();
- for (size_t i = 0; i < arrayCount; i++) {
- RefPtr<nsRange> range = mArray[i]->GetRange();
- NS_ENSURE_TRUE(range, NS_ERROR_UNEXPECTED);
-
- nsresult rv = aSel->AddRange(range);
- if (NS_FAILED(rv)) {
- return rv;
- }
- }
- return NS_OK;
-}
-
-bool
-SelectionState::IsCollapsed()
-{
- if (mArray.Length() != 1) {
- return false;
- }
- RefPtr<nsRange> range = mArray[0]->GetRange();
- NS_ENSURE_TRUE(range, false);
- bool bIsCollapsed = false;
- range->GetCollapsed(&bIsCollapsed);
- return bIsCollapsed;
-}
-
-bool
-SelectionState::IsEqual(SelectionState* aSelState)
-{
- NS_ENSURE_TRUE(aSelState, false);
- size_t myCount = mArray.Length(), itsCount = aSelState->mArray.Length();
- if (myCount != itsCount) {
- return false;
- }
- if (!myCount) {
- return false;
- }
-
- for (size_t i = 0; i < myCount; i++) {
- RefPtr<nsRange> myRange = mArray[i]->GetRange();
- RefPtr<nsRange> itsRange = aSelState->mArray[i]->GetRange();
- NS_ENSURE_TRUE(myRange && itsRange, false);
-
- int16_t compResult;
- nsresult rv;
- rv = myRange->CompareBoundaryPoints(nsIDOMRange::START_TO_START, itsRange, &compResult);
- if (NS_FAILED(rv) || compResult) {
- return false;
- }
- rv = myRange->CompareBoundaryPoints(nsIDOMRange::END_TO_END, itsRange, &compResult);
- if (NS_FAILED(rv) || compResult) {
- return false;
- }
- }
- // if we got here, they are equal
- return true;
-}
-
-void
-SelectionState::MakeEmpty()
-{
- // free any items in the array
- mArray.Clear();
-}
-
-bool
-SelectionState::IsEmpty()
-{
- return mArray.IsEmpty();
-}
-
-/******************************************************************************
- * mozilla::RangeUpdater
- *
- * Class for updating nsRanges in response to editor actions.
- ******************************************************************************/
-
-RangeUpdater::RangeUpdater()
- : mLock(false)
-{
-}
-
-RangeUpdater::~RangeUpdater()
-{
- // nothing to do, we don't own the items in our array.
-}
-
-void
-RangeUpdater::RegisterRangeItem(RangeItem* aRangeItem)
-{
- if (!aRangeItem) {
- return;
- }
- if (mArray.Contains(aRangeItem)) {
- NS_ERROR("tried to register an already registered range");
- return; // don't register it again. It would get doubly adjusted.
- }
- mArray.AppendElement(aRangeItem);
-}
-
-void
-RangeUpdater::DropRangeItem(RangeItem* aRangeItem)
-{
- if (!aRangeItem) {
- return;
- }
- mArray.RemoveElement(aRangeItem);
-}
-
-nsresult
-RangeUpdater::RegisterSelectionState(SelectionState& aSelState)
-{
- size_t theCount = aSelState.mArray.Length();
- if (theCount < 1) {
- return NS_ERROR_FAILURE;
- }
-
- for (size_t i = 0; i < theCount; i++) {
- RegisterRangeItem(aSelState.mArray[i]);
- }
-
- return NS_OK;
-}
-
-nsresult
-RangeUpdater::DropSelectionState(SelectionState& aSelState)
-{
- size_t theCount = aSelState.mArray.Length();
- if (theCount < 1) {
- return NS_ERROR_FAILURE;
- }
-
- for (size_t i = 0; i < theCount; i++) {
- DropRangeItem(aSelState.mArray[i]);
- }
-
- return NS_OK;
-}
-
-// gravity methods:
-
-nsresult
-RangeUpdater::SelAdjCreateNode(nsINode* aParent,
- int32_t aPosition)
-{
- if (mLock) {
- // lock set by Will/DidReplaceParent, etc...
- return NS_OK;
- }
- NS_ENSURE_TRUE(aParent, NS_ERROR_NULL_POINTER);
- size_t count = mArray.Length();
- if (!count) {
- return NS_OK;
- }
-
- for (size_t i = 0; i < count; i++) {
- RangeItem* item = mArray[i];
- NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
-
- if (item->startNode == aParent && item->startOffset > aPosition) {
- item->startOffset++;
- }
- if (item->endNode == aParent && item->endOffset > aPosition) {
- item->endOffset++;
- }
- }
- return NS_OK;
-}
-
-nsresult
-RangeUpdater::SelAdjCreateNode(nsIDOMNode* aParent,
- int32_t aPosition)
-{
- nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
- return SelAdjCreateNode(parent, aPosition);
-}
-
-nsresult
-RangeUpdater::SelAdjInsertNode(nsINode* aParent,
- int32_t aPosition)
-{
- return SelAdjCreateNode(aParent, aPosition);
-}
-
-nsresult
-RangeUpdater::SelAdjInsertNode(nsIDOMNode* aParent,
- int32_t aPosition)
-{
- return SelAdjCreateNode(aParent, aPosition);
-}
-
-void
-RangeUpdater::SelAdjDeleteNode(nsINode* aNode)
-{
- if (mLock) {
- // lock set by Will/DidReplaceParent, etc...
- return;
- }
- MOZ_ASSERT(aNode);
- size_t count = mArray.Length();
- if (!count) {
- return;
- }
-
- nsCOMPtr<nsINode> parent = aNode->GetParentNode();
- int32_t offset = parent ? parent->IndexOf(aNode) : -1;
-
- // check for range endpoints that are after aNode and in the same parent
- for (size_t i = 0; i < count; i++) {
- RangeItem* item = mArray[i];
- MOZ_ASSERT(item);
-
- if (item->startNode == parent && item->startOffset > offset) {
- item->startOffset--;
- }
- if (item->endNode == parent && item->endOffset > offset) {
- item->endOffset--;
- }
-
- // check for range endpoints that are in aNode
- if (item->startNode == aNode) {
- item->startNode = parent;
- item->startOffset = offset;
- }
- if (item->endNode == aNode) {
- item->endNode = parent;
- item->endOffset = offset;
- }
-
- // check for range endpoints that are in descendants of aNode
- nsCOMPtr<nsINode> oldStart;
- if (EditorUtils::IsDescendantOf(item->startNode, aNode)) {
- oldStart = item->startNode; // save for efficiency hack below.
- item->startNode = parent;
- item->startOffset = offset;
- }
-
- // avoid having to call IsDescendantOf() for common case of range startnode == range endnode.
- if (item->endNode == oldStart ||
- EditorUtils::IsDescendantOf(item->endNode, aNode)) {
- item->endNode = parent;
- item->endOffset = offset;
- }
- }
-}
-
-void
-RangeUpdater::SelAdjDeleteNode(nsIDOMNode* aNode)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- NS_ENSURE_TRUE_VOID(node);
- return SelAdjDeleteNode(node);
-}
-
-nsresult
-RangeUpdater::SelAdjSplitNode(nsIContent& aOldRightNode,
- int32_t aOffset,
- nsIContent* aNewLeftNode)
-{
- if (mLock) {
- // lock set by Will/DidReplaceParent, etc...
- return NS_OK;
- }
- NS_ENSURE_TRUE(aNewLeftNode, NS_ERROR_NULL_POINTER);
- size_t count = mArray.Length();
- if (!count) {
- return NS_OK;
- }
-
- nsCOMPtr<nsINode> parent = aOldRightNode.GetParentNode();
- int32_t offset = parent ? parent->IndexOf(&aOldRightNode) : -1;
-
- // first part is same as inserting aNewLeftnode
- nsresult rv = SelAdjInsertNode(parent, offset - 1);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // next step is to check for range enpoints inside aOldRightNode
- for (size_t i = 0; i < count; i++) {
- RangeItem* item = mArray[i];
- NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
-
- if (item->startNode == &aOldRightNode) {
- if (item->startOffset > aOffset) {
- item->startOffset -= aOffset;
- } else {
- item->startNode = aNewLeftNode;
- }
- }
- if (item->endNode == &aOldRightNode) {
- if (item->endOffset > aOffset) {
- item->endOffset -= aOffset;
- } else {
- item->endNode = aNewLeftNode;
- }
- }
- }
- return NS_OK;
-}
-
-nsresult
-RangeUpdater::SelAdjJoinNodes(nsINode& aLeftNode,
- nsINode& aRightNode,
- nsINode& aParent,
- int32_t aOffset,
- int32_t aOldLeftNodeLength)
-{
- if (mLock) {
- // lock set by Will/DidReplaceParent, etc...
- return NS_OK;
- }
- size_t count = mArray.Length();
- if (!count) {
- return NS_OK;
- }
-
- for (size_t i = 0; i < count; i++) {
- RangeItem* item = mArray[i];
- NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
-
- if (item->startNode == &aParent) {
- // adjust start point in aParent
- if (item->startOffset > aOffset) {
- item->startOffset--;
- } else if (item->startOffset == aOffset) {
- // join keeps right hand node
- item->startNode = &aRightNode;
- item->startOffset = aOldLeftNodeLength;
- }
- } else if (item->startNode == &aRightNode) {
- // adjust start point in aRightNode
- item->startOffset += aOldLeftNodeLength;
- } else if (item->startNode == &aLeftNode) {
- // adjust start point in aLeftNode
- item->startNode = &aRightNode;
- }
-
- if (item->endNode == &aParent) {
- // adjust end point in aParent
- if (item->endOffset > aOffset) {
- item->endOffset--;
- } else if (item->endOffset == aOffset) {
- // join keeps right hand node
- item->endNode = &aRightNode;
- item->endOffset = aOldLeftNodeLength;
- }
- } else if (item->endNode == &aRightNode) {
- // adjust end point in aRightNode
- item->endOffset += aOldLeftNodeLength;
- } else if (item->endNode == &aLeftNode) {
- // adjust end point in aLeftNode
- item->endNode = &aRightNode;
- }
- }
-
- return NS_OK;
-}
-
-void
-RangeUpdater::SelAdjInsertText(Text& aTextNode,
- int32_t aOffset,
- const nsAString& aString)
-{
- if (mLock) {
- // lock set by Will/DidReplaceParent, etc...
- return;
- }
-
- size_t count = mArray.Length();
- if (!count) {
- return;
- }
-
- size_t len = aString.Length();
- for (size_t i = 0; i < count; i++) {
- RangeItem* item = mArray[i];
- MOZ_ASSERT(item);
-
- if (item->startNode == &aTextNode && item->startOffset > aOffset) {
- item->startOffset += len;
- }
- if (item->endNode == &aTextNode && item->endOffset > aOffset) {
- item->endOffset += len;
- }
- }
- return;
-}
-
-nsresult
-RangeUpdater::SelAdjDeleteText(nsIContent* aTextNode,
- int32_t aOffset,
- int32_t aLength)
-{
- if (mLock) {
- // lock set by Will/DidReplaceParent, etc...
- return NS_OK;
- }
-
- size_t count = mArray.Length();
- if (!count) {
- return NS_OK;
- }
- NS_ENSURE_TRUE(aTextNode, NS_ERROR_NULL_POINTER);
-
- for (size_t i = 0; i < count; i++) {
- RangeItem* item = mArray[i];
- NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
-
- if (item->startNode == aTextNode && item->startOffset > aOffset) {
- item->startOffset -= aLength;
- if (item->startOffset < 0) {
- item->startOffset = 0;
- }
- }
- if (item->endNode == aTextNode && item->endOffset > aOffset) {
- item->endOffset -= aLength;
- if (item->endOffset < 0) {
- item->endOffset = 0;
- }
- }
- }
- return NS_OK;
-}
-
-nsresult
-RangeUpdater::SelAdjDeleteText(nsIDOMCharacterData* aTextNode,
- int32_t aOffset,
- int32_t aLength)
-{
- nsCOMPtr<nsIContent> textNode = do_QueryInterface(aTextNode);
- return SelAdjDeleteText(textNode, aOffset, aLength);
-}
-
-nsresult
-RangeUpdater::WillReplaceContainer()
-{
- if (mLock) {
- return NS_ERROR_UNEXPECTED;
- }
- mLock = true;
- return NS_OK;
-}
-
-nsresult
-RangeUpdater::DidReplaceContainer(Element* aOriginalNode,
- Element* aNewNode)
-{
- NS_ENSURE_TRUE(mLock, NS_ERROR_UNEXPECTED);
- mLock = false;
-
- NS_ENSURE_TRUE(aOriginalNode && aNewNode, NS_ERROR_NULL_POINTER);
- size_t count = mArray.Length();
- if (!count) {
- return NS_OK;
- }
-
- for (size_t i = 0; i < count; i++) {
- RangeItem* item = mArray[i];
- NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
-
- if (item->startNode == aOriginalNode) {
- item->startNode = aNewNode;
- }
- if (item->endNode == aOriginalNode) {
- item->endNode = aNewNode;
- }
- }
- return NS_OK;
-}
-
-nsresult
-RangeUpdater::WillRemoveContainer()
-{
- if (mLock) {
- return NS_ERROR_UNEXPECTED;
- }
- mLock = true;
- return NS_OK;
-}
-
-nsresult
-RangeUpdater::DidRemoveContainer(nsINode* aNode,
- nsINode* aParent,
- int32_t aOffset,
- uint32_t aNodeOrigLen)
-{
- NS_ENSURE_TRUE(mLock, NS_ERROR_UNEXPECTED);
- mLock = false;
-
- NS_ENSURE_TRUE(aNode && aParent, NS_ERROR_NULL_POINTER);
- size_t count = mArray.Length();
- if (!count) {
- return NS_OK;
- }
-
- for (size_t i = 0; i < count; i++) {
- RangeItem* item = mArray[i];
- NS_ENSURE_TRUE(item, NS_ERROR_NULL_POINTER);
-
- if (item->startNode == aNode) {
- item->startNode = aParent;
- item->startOffset += aOffset;
- } else if (item->startNode == aParent && item->startOffset > aOffset) {
- item->startOffset += (int32_t)aNodeOrigLen - 1;
- }
-
- if (item->endNode == aNode) {
- item->endNode = aParent;
- item->endOffset += aOffset;
- } else if (item->endNode == aParent && item->endOffset > aOffset) {
- item->endOffset += (int32_t)aNodeOrigLen - 1;
- }
- }
- return NS_OK;
-}
-
-nsresult
-RangeUpdater::DidRemoveContainer(nsIDOMNode* aNode,
- nsIDOMNode* aParent,
- int32_t aOffset,
- uint32_t aNodeOrigLen)
-{
- nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
- nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
- return DidRemoveContainer(node, parent, aOffset, aNodeOrigLen);
-}
-
-nsresult
-RangeUpdater::WillInsertContainer()
-{
- if (mLock) {
- return NS_ERROR_UNEXPECTED;
- }
- mLock = true;
- return NS_OK;
-}
-
-nsresult
-RangeUpdater::DidInsertContainer()
-{
- NS_ENSURE_TRUE(mLock, NS_ERROR_UNEXPECTED);
- mLock = false;
- return NS_OK;
-}
-
-void
-RangeUpdater::WillMoveNode()
-{
- mLock = true;
-}
-
-void
-RangeUpdater::DidMoveNode(nsINode* aOldParent, int32_t aOldOffset,
- nsINode* aNewParent, int32_t aNewOffset)
-{
- MOZ_ASSERT(aOldParent);
- MOZ_ASSERT(aNewParent);
- NS_ENSURE_TRUE_VOID(mLock);
- mLock = false;
-
- for (size_t i = 0, count = mArray.Length(); i < count; ++i) {
- RangeItem* item = mArray[i];
- NS_ENSURE_TRUE_VOID(item);
-
- // like a delete in aOldParent
- if (item->startNode == aOldParent && item->startOffset > aOldOffset) {
- item->startOffset--;
- }
- if (item->endNode == aOldParent && item->endOffset > aOldOffset) {
- item->endOffset--;
- }
-
- // and like an insert in aNewParent
- if (item->startNode == aNewParent && item->startOffset > aNewOffset) {
- item->startOffset++;
- }
- if (item->endNode == aNewParent && item->endOffset > aNewOffset) {
- item->endOffset++;
- }
- }
-}
-
-/******************************************************************************
- * mozilla::RangeItem
- *
- * Helper struct for SelectionState. This stores range endpoints.
- ******************************************************************************/
-
-RangeItem::RangeItem()
-{
-}
-
-RangeItem::~RangeItem()
-{
-}
-
-NS_IMPL_CYCLE_COLLECTION(RangeItem, startNode, endNode)
-NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(RangeItem, AddRef)
-NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(RangeItem, Release)
-
-void
-RangeItem::StoreRange(nsRange* aRange)
-{
- MOZ_ASSERT(aRange);
- startNode = aRange->GetStartParent();
- startOffset = aRange->StartOffset();
- endNode = aRange->GetEndParent();
- endOffset = aRange->EndOffset();
-}
-
-already_AddRefed<nsRange>
-RangeItem::GetRange()
-{
- RefPtr<nsRange> range = new nsRange(startNode);
- if (NS_FAILED(range->SetStartAndEnd(startNode, startOffset,
- endNode, endOffset))) {
- return nullptr;
- }
- return range.forget();
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/SelectionState.h b/editor/libeditor/SelectionState.h
deleted file mode 100644
index 36e7b7769..000000000
--- a/editor/libeditor/SelectionState.h
+++ /dev/null
@@ -1,357 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_SelectionState_h
-#define mozilla_SelectionState_h
-
-#include "nsCOMPtr.h"
-#include "nsIDOMNode.h"
-#include "nsINode.h"
-#include "nsTArray.h"
-#include "nscore.h"
-
-class nsCycleCollectionTraversalCallback;
-class nsIDOMCharacterData;
-class nsRange;
-namespace mozilla {
-class RangeUpdater;
-namespace dom {
-class Selection;
-class Text;
-} // namespace dom
-
-/**
- * A helper struct for saving/setting ranges.
- */
-struct RangeItem final
-{
- RangeItem();
-
-private:
- // Private destructor, to discourage deletion outside of Release():
- ~RangeItem();
-
-public:
- void StoreRange(nsRange* aRange);
- already_AddRefed<nsRange> GetRange();
-
- NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(RangeItem)
- NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(RangeItem)
-
- nsCOMPtr<nsINode> startNode;
- int32_t startOffset;
- nsCOMPtr<nsINode> endNode;
- int32_t endOffset;
-};
-
-/**
- * mozilla::SelectionState
- *
- * Class for recording selection info. Stores selection as collection of
- * { {startnode, startoffset} , {endnode, endoffset} } tuples. Can't store
- * ranges since dom gravity will possibly change the ranges.
- */
-
-class SelectionState final
-{
-public:
- SelectionState();
- ~SelectionState();
-
- void SaveSelection(dom::Selection *aSel);
- nsresult RestoreSelection(dom::Selection* aSel);
- bool IsCollapsed();
- bool IsEqual(SelectionState *aSelState);
- void MakeEmpty();
- bool IsEmpty();
-private:
- nsTArray<RefPtr<RangeItem>> mArray;
-
- friend class RangeUpdater;
- friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
- SelectionState&,
- const char*,
- uint32_t);
- friend void ImplCycleCollectionUnlink(SelectionState&);
-};
-
-inline void
-ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
- SelectionState& aField,
- const char* aName,
- uint32_t aFlags = 0)
-{
- ImplCycleCollectionTraverse(aCallback, aField.mArray, aName, aFlags);
-}
-
-inline void
-ImplCycleCollectionUnlink(SelectionState& aField)
-{
- ImplCycleCollectionUnlink(aField.mArray);
-}
-
-class RangeUpdater final
-{
-public:
- RangeUpdater();
- ~RangeUpdater();
-
- void RegisterRangeItem(RangeItem* aRangeItem);
- void DropRangeItem(RangeItem* aRangeItem);
- nsresult RegisterSelectionState(SelectionState& aSelState);
- nsresult DropSelectionState(SelectionState& aSelState);
-
- // editor selection gravity routines. Note that we can't always depend on
- // DOM Range gravity to do what we want to the "real" selection. For instance,
- // if you move a node, that corresponds to deleting it and reinserting it.
- // DOM Range gravity will promote the selection out of the node on deletion,
- // which is not what you want if you know you are reinserting it.
- nsresult SelAdjCreateNode(nsINode* aParent, int32_t aPosition);
- nsresult SelAdjCreateNode(nsIDOMNode* aParent, int32_t aPosition);
- nsresult SelAdjInsertNode(nsINode* aParent, int32_t aPosition);
- nsresult SelAdjInsertNode(nsIDOMNode* aParent, int32_t aPosition);
- void SelAdjDeleteNode(nsINode* aNode);
- void SelAdjDeleteNode(nsIDOMNode* aNode);
- nsresult SelAdjSplitNode(nsIContent& aOldRightNode, int32_t aOffset,
- nsIContent* aNewLeftNode);
- nsresult SelAdjJoinNodes(nsINode& aLeftNode,
- nsINode& aRightNode,
- nsINode& aParent,
- int32_t aOffset,
- int32_t aOldLeftNodeLength);
- void SelAdjInsertText(dom::Text& aTextNode, int32_t aOffset,
- const nsAString &aString);
- nsresult SelAdjDeleteText(nsIContent* aTextNode, int32_t aOffset,
- int32_t aLength);
- nsresult SelAdjDeleteText(nsIDOMCharacterData* aTextNode,
- int32_t aOffset, int32_t aLength);
- // the following gravity routines need will/did sandwiches, because the other
- // gravity routines will be called inside of these sandwiches, but should be
- // ignored.
- nsresult WillReplaceContainer();
- nsresult DidReplaceContainer(dom::Element* aOriginalNode,
- dom::Element* aNewNode);
- nsresult WillRemoveContainer();
- nsresult DidRemoveContainer(nsINode* aNode, nsINode* aParent,
- int32_t aOffset, uint32_t aNodeOrigLen);
- nsresult DidRemoveContainer(nsIDOMNode* aNode, nsIDOMNode* aParent,
- int32_t aOffset, uint32_t aNodeOrigLen);
- nsresult WillInsertContainer();
- nsresult DidInsertContainer();
- void WillMoveNode();
- void DidMoveNode(nsINode* aOldParent, int32_t aOldOffset,
- nsINode* aNewParent, int32_t aNewOffset);
-
-private:
- friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
- RangeUpdater&,
- const char*,
- uint32_t);
- friend void ImplCycleCollectionUnlink(RangeUpdater& aField);
-
- nsTArray<RefPtr<RangeItem>> mArray;
- bool mLock;
-};
-
-inline void
-ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
- RangeUpdater& aField,
- const char* aName,
- uint32_t aFlags = 0)
-{
- ImplCycleCollectionTraverse(aCallback, aField.mArray, aName, aFlags);
-}
-
-inline void
-ImplCycleCollectionUnlink(RangeUpdater& aField)
-{
- ImplCycleCollectionUnlink(aField.mArray);
-}
-
-/**
- * Helper class for using SelectionState. Stack based class for doing
- * preservation of dom points across editor actions.
- */
-
-class MOZ_STACK_CLASS AutoTrackDOMPoint final
-{
-private:
- RangeUpdater& mRangeUpdater;
- // Allow tracking either nsIDOMNode or nsINode until nsIDOMNode is gone
- nsCOMPtr<nsINode>* mNode;
- nsCOMPtr<nsIDOMNode>* mDOMNode;
- int32_t* mOffset;
- RefPtr<RangeItem> mRangeItem;
-
-public:
- AutoTrackDOMPoint(RangeUpdater& aRangeUpdater,
- nsCOMPtr<nsINode>* aNode, int32_t* aOffset)
- : mRangeUpdater(aRangeUpdater)
- , mNode(aNode)
- , mDOMNode(nullptr)
- , mOffset(aOffset)
- {
- mRangeItem = new RangeItem();
- mRangeItem->startNode = *mNode;
- mRangeItem->endNode = *mNode;
- mRangeItem->startOffset = *mOffset;
- mRangeItem->endOffset = *mOffset;
- mRangeUpdater.RegisterRangeItem(mRangeItem);
- }
-
- AutoTrackDOMPoint(RangeUpdater& aRangeUpdater,
- nsCOMPtr<nsIDOMNode>* aNode, int32_t* aOffset)
- : mRangeUpdater(aRangeUpdater)
- , mNode(nullptr)
- , mDOMNode(aNode)
- , mOffset(aOffset)
- {
- mRangeItem = new RangeItem();
- mRangeItem->startNode = do_QueryInterface(*mDOMNode);
- mRangeItem->endNode = do_QueryInterface(*mDOMNode);
- mRangeItem->startOffset = *mOffset;
- mRangeItem->endOffset = *mOffset;
- mRangeUpdater.RegisterRangeItem(mRangeItem);
- }
-
- ~AutoTrackDOMPoint()
- {
- mRangeUpdater.DropRangeItem(mRangeItem);
- if (mNode) {
- *mNode = mRangeItem->startNode;
- } else {
- *mDOMNode = GetAsDOMNode(mRangeItem->startNode);
- }
- *mOffset = mRangeItem->startOffset;
- }
-};
-
-/**
- * Another helper class for SelectionState. Stack based class for doing
- * Will/DidReplaceContainer()
- */
-
-class MOZ_STACK_CLASS AutoReplaceContainerSelNotify final
-{
-private:
- RangeUpdater& mRangeUpdater;
- dom::Element* mOriginalElement;
- dom::Element* mNewElement;
-
-public:
- AutoReplaceContainerSelNotify(RangeUpdater& aRangeUpdater,
- dom::Element* aOriginalElement,
- dom::Element* aNewElement)
- : mRangeUpdater(aRangeUpdater)
- , mOriginalElement(aOriginalElement)
- , mNewElement(aNewElement)
- {
- mRangeUpdater.WillReplaceContainer();
- }
-
- ~AutoReplaceContainerSelNotify()
- {
- mRangeUpdater.DidReplaceContainer(mOriginalElement, mNewElement);
- }
-};
-
-/**
- * Another helper class for SelectionState. Stack based class for doing
- * Will/DidRemoveContainer()
- */
-
-class MOZ_STACK_CLASS AutoRemoveContainerSelNotify final
-{
-private:
- RangeUpdater& mRangeUpdater;
- nsIDOMNode* mNode;
- nsIDOMNode* mParent;
- int32_t mOffset;
- uint32_t mNodeOrigLen;
-
-public:
- AutoRemoveContainerSelNotify(RangeUpdater& aRangeUpdater,
- nsINode* aNode,
- nsINode* aParent,
- int32_t aOffset,
- uint32_t aNodeOrigLen)
- : mRangeUpdater(aRangeUpdater)
- , mNode(aNode->AsDOMNode())
- , mParent(aParent->AsDOMNode())
- , mOffset(aOffset)
- , mNodeOrigLen(aNodeOrigLen)
- {
- mRangeUpdater.WillRemoveContainer();
- }
-
- ~AutoRemoveContainerSelNotify()
- {
- mRangeUpdater.DidRemoveContainer(mNode, mParent, mOffset, mNodeOrigLen);
- }
-};
-
-/**
- * Another helper class for SelectionState. Stack based class for doing
- * Will/DidInsertContainer()
- */
-
-class MOZ_STACK_CLASS AutoInsertContainerSelNotify final
-{
-private:
- RangeUpdater& mRangeUpdater;
-
-public:
- explicit AutoInsertContainerSelNotify(RangeUpdater& aRangeUpdater)
- : mRangeUpdater(aRangeUpdater)
- {
- mRangeUpdater.WillInsertContainer();
- }
-
- ~AutoInsertContainerSelNotify()
- {
- mRangeUpdater.DidInsertContainer();
- }
-};
-
-/**
- * Another helper class for SelectionState. Stack based class for doing
- * Will/DidMoveNode()
- */
-
-class MOZ_STACK_CLASS AutoMoveNodeSelNotify final
-{
-private:
- RangeUpdater& mRangeUpdater;
- nsINode* mOldParent;
- nsINode* mNewParent;
- int32_t mOldOffset;
- int32_t mNewOffset;
-
-public:
- AutoMoveNodeSelNotify(RangeUpdater& aRangeUpdater,
- nsINode* aOldParent,
- int32_t aOldOffset,
- nsINode* aNewParent,
- int32_t aNewOffset)
- : mRangeUpdater(aRangeUpdater)
- , mOldParent(aOldParent)
- , mNewParent(aNewParent)
- , mOldOffset(aOldOffset)
- , mNewOffset(aNewOffset)
- {
- MOZ_ASSERT(aOldParent);
- MOZ_ASSERT(aNewParent);
- mRangeUpdater.WillMoveNode();
- }
-
- ~AutoMoveNodeSelNotify()
- {
- mRangeUpdater.DidMoveNode(mOldParent, mOldOffset, mNewParent, mNewOffset);
- }
-};
-
-} // namespace mozilla
-
-#endif // #ifndef mozilla_SelectionState_h
diff --git a/editor/libeditor/SetDocumentTitleTransaction.cpp b/editor/libeditor/SetDocumentTitleTransaction.cpp
deleted file mode 100644
index 88403c0ad..000000000
--- a/editor/libeditor/SetDocumentTitleTransaction.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "SetDocumentTitleTransaction.h"
-#include "mozilla/dom/Element.h" // for Element
-#include "nsAString.h"
-#include "nsCOMPtr.h" // for nsCOMPtr, getter_AddRefs, etc.
-#include "nsDebug.h" // for NS_ENSURE_SUCCESS, etc.
-#include "nsError.h" // for NS_OK, NS_ERROR_FAILURE, etc.
-#include "nsIDOMCharacterData.h" // for nsIDOMCharacterData
-#include "nsIDOMDocument.h" // for nsIDOMDocument
-#include "nsIDOMElement.h" // for nsIDOMElement
-#include "nsIDOMNode.h" // for nsIDOMNode
-#include "nsIDOMNodeList.h" // for nsIDOMNodeList
-#include "nsIDOMText.h" // for nsIDOMText
-#include "nsIDocument.h" // for nsIDocument
-#include "nsIEditor.h" // for nsIEditor
-#include "nsIHTMLEditor.h" // for nsIHTMLEditor
-#include "nsLiteralString.h" // for NS_LITERAL_STRING
-
-namespace mozilla {
-
-// Note that aEditor is not refcounted.
-SetDocumentTitleTransaction::SetDocumentTitleTransaction()
- : mEditor(nullptr)
- , mIsTransient(false)
-{
-}
-
-NS_IMETHODIMP
-SetDocumentTitleTransaction::Init(nsIHTMLEditor* aEditor,
- const nsAString* aValue)
-
-{
- NS_ASSERTION(aEditor && aValue, "null args");
- if (!aEditor || !aValue) {
- return NS_ERROR_NULL_POINTER;
- }
-
- mEditor = aEditor;
- mValue = *aValue;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-SetDocumentTitleTransaction::DoTransaction()
-{
- return SetDomTitle(mValue);
-}
-
-NS_IMETHODIMP
-SetDocumentTitleTransaction::UndoTransaction()
-{
- // No extra work required; the DOM changes alone are enough
- return NS_OK;
-}
-
-NS_IMETHODIMP
-SetDocumentTitleTransaction::RedoTransaction()
-{
- // No extra work required; the DOM changes alone are enough
- return NS_OK;
-}
-
-nsresult
-SetDocumentTitleTransaction::SetDomTitle(const nsAString& aTitle)
-{
- nsCOMPtr<nsIEditor> editor = do_QueryInterface(mEditor);
- if (NS_WARN_IF(!editor)) {
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsIDOMDocument> domDoc;
- nsresult rv = editor->GetDocument(getter_AddRefs(domDoc));
- if (NS_WARN_IF(!domDoc)) {
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsIDOMNodeList> titleList;
- rv = domDoc->GetElementsByTagName(NS_LITERAL_STRING("title"),
- getter_AddRefs(titleList));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- // First assume we will NOT really do anything
- // (transaction will not be pushed on stack)
- mIsTransient = true;
-
- nsCOMPtr<nsIDOMNode> titleNode;
- if(titleList) {
- rv = titleList->Item(0, getter_AddRefs(titleNode));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- if (titleNode) {
- // Delete existing child textnode of title node
- // (Note: all contents under a TITLE node are always in a single text node)
- nsCOMPtr<nsIDOMNode> child;
- rv = titleNode->GetFirstChild(getter_AddRefs(child));
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- if(child) {
- // Save current text as the undo value
- nsCOMPtr<nsIDOMCharacterData> textNode = do_QueryInterface(child);
- if(textNode) {
- textNode->GetData(mUndoValue);
-
- // If title text is identical to what already exists,
- // quit now (mIsTransient is now TRUE)
- if (mUndoValue == aTitle) {
- return NS_OK;
- }
- }
- rv = editor->DeleteNode(child);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- }
- }
-
- // We didn't return above, thus we really will be changing the title
- mIsTransient = false;
-
- // Get the <HEAD> node, create a <TITLE> and insert it under the HEAD
- nsCOMPtr<nsIDocument> document = do_QueryInterface(domDoc);
- if (NS_WARN_IF(!document)) {
- return NS_ERROR_UNEXPECTED;
- }
-
- RefPtr<dom::Element> headElement = document->GetHeadElement();
- if (NS_WARN_IF(!headElement)) {
- return NS_ERROR_UNEXPECTED;
- }
-
- bool newTitleNode = false;
- uint32_t newTitleIndex = 0;
-
- if (!titleNode) {
- // Didn't find one above: Create a new one
- nsCOMPtr<nsIDOMElement>titleElement;
- rv = domDoc->CreateElement(NS_LITERAL_STRING("title"),
- getter_AddRefs(titleElement));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- if (NS_WARN_IF(!titleElement)) {
- return NS_ERROR_FAILURE;
- }
-
- titleNode = do_QueryInterface(titleElement);
- newTitleNode = true;
-
- // Get index so we append new title node after all existing HEAD children.
- newTitleIndex = headElement->GetChildCount();
- }
-
- // Append a text node under the TITLE only if the title text isn't empty.
- if (titleNode && !aTitle.IsEmpty()) {
- nsCOMPtr<nsIDOMText> textNode;
- rv = domDoc->CreateTextNode(aTitle, getter_AddRefs(textNode));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- nsCOMPtr<nsIDOMNode> newNode = do_QueryInterface(textNode);
- if (NS_WARN_IF(!newNode)) {
- return NS_ERROR_FAILURE;
- }
-
- if (newTitleNode) {
- // Not undoable: We will insert newTitleNode below
- nsCOMPtr<nsIDOMNode> resultNode;
- rv = titleNode->AppendChild(newNode, getter_AddRefs(resultNode));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- } else {
- // This is an undoable transaction
- rv = editor->InsertNode(newNode, titleNode, 0);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- // Calling AppendChild() or InsertNode() could cause removing the head
- // element. So, let's mark it dirty.
- headElement = nullptr;
- }
-
- if (newTitleNode) {
- if (!headElement) {
- headElement = document->GetHeadElement();
- if (NS_WARN_IF(!headElement)) {
- // XXX Can we return NS_OK when there is no head element?
- return NS_ERROR_UNEXPECTED;
- }
- }
- // Undoable transaction to insert title+text together
- rv = editor->InsertNode(titleNode, headElement->AsDOMNode(), newTitleIndex);
- }
- return rv;
-}
-
-NS_IMETHODIMP
-SetDocumentTitleTransaction::GetTxnDescription(nsAString& aString)
-{
- aString.AssignLiteral("SetDocumentTitleTransaction: ");
- aString += mValue;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-SetDocumentTitleTransaction::GetIsTransient(bool* aIsTransient)
-{
- if (NS_WARN_IF(!aIsTransient)) {
- return NS_ERROR_NULL_POINTER;
- }
- *aIsTransient = mIsTransient;
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/SetDocumentTitleTransaction.h b/editor/libeditor/SetDocumentTitleTransaction.h
deleted file mode 100644
index 0f17fe8d2..000000000
--- a/editor/libeditor/SetDocumentTitleTransaction.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef SetDocumentTitleTransaction_h
-#define SetDocumentTitleTransaction_h
-
-#include "mozilla/EditTransactionBase.h" // for EditTransactionBase, etc.
-#include "nsString.h" // for nsString
-#include "nscore.h" // for NS_IMETHOD, nsAString, etc.
-
-class nsIHTMLEditor;
-
-namespace mozilla {
-
-/**
- * A transaction that changes the document's title,
- * which is a text node under the <title> tag in a page's <head> section
- * provides default concrete behavior for all nsITransaction methods.
- */
-class SetDocumentTitleTransaction final : public EditTransactionBase
-{
-public:
- /**
- * Initialize the transaction.
- * @param aEditor The object providing core editing operations.
- * @param aValue The new value for document title.
- */
- NS_IMETHOD Init(nsIHTMLEditor* aEditor,
- const nsAString* aValue);
- SetDocumentTitleTransaction();
-
-private:
- nsresult SetDomTitle(const nsAString& aTitle);
-
-public:
- NS_DECL_EDITTRANSACTIONBASE
-
- NS_IMETHOD RedoTransaction() override;
- NS_IMETHOD GetIsTransient(bool *aIsTransient) override;
-
-protected:
-
- // The editor that created this transaction.
- nsIHTMLEditor* mEditor;
-
- // The new title string.
- nsString mValue;
-
- // The previous title string to use for undo.
- nsString mUndoValue;
-
- // Set true if we dont' really change the title during Do().
- bool mIsTransient;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef SetDocumentTitleTransaction_h
diff --git a/editor/libeditor/SplitNodeTransaction.cpp b/editor/libeditor/SplitNodeTransaction.cpp
deleted file mode 100644
index 8965b5399..000000000
--- a/editor/libeditor/SplitNodeTransaction.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "SplitNodeTransaction.h"
-
-#include "mozilla/EditorBase.h" // for EditorBase
-#include "mozilla/dom/Selection.h"
-#include "nsAString.h"
-#include "nsDebug.h" // for NS_ASSERTION, etc.
-#include "nsError.h" // for NS_ERROR_NOT_INITIALIZED, etc.
-#include "nsIContent.h" // for nsIContent
-
-namespace mozilla {
-
-using namespace dom;
-
-SplitNodeTransaction::SplitNodeTransaction(EditorBase& aEditorBase,
- nsIContent& aNode,
- int32_t aOffset)
- : mEditorBase(&aEditorBase)
- , mExistingRightNode(&aNode)
- , mOffset(aOffset)
-{
-}
-
-SplitNodeTransaction::~SplitNodeTransaction()
-{
-}
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(SplitNodeTransaction, EditTransactionBase,
- mEditorBase,
- mParent,
- mNewLeftNode)
-
-NS_IMPL_ADDREF_INHERITED(SplitNodeTransaction, EditTransactionBase)
-NS_IMPL_RELEASE_INHERITED(SplitNodeTransaction, EditTransactionBase)
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SplitNodeTransaction)
-NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
-
-NS_IMETHODIMP
-SplitNodeTransaction::DoTransaction()
-{
- if (NS_WARN_IF(!mEditorBase)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // Create a new node
- ErrorResult rv;
- // Don't use .downcast directly because AsContent has an assertion we want
- nsCOMPtr<nsINode> clone = mExistingRightNode->CloneNode(false, rv);
- NS_ASSERTION(!rv.Failed() && clone, "Could not create clone");
- NS_ENSURE_TRUE(!rv.Failed() && clone, rv.StealNSResult());
- mNewLeftNode = dont_AddRef(clone.forget().take()->AsContent());
- mEditorBase->MarkNodeDirty(mExistingRightNode->AsDOMNode());
-
- // Get the parent node
- mParent = mExistingRightNode->GetParentNode();
- NS_ENSURE_TRUE(mParent, NS_ERROR_NULL_POINTER);
-
- // Insert the new node
- rv = mEditorBase->SplitNodeImpl(*mExistingRightNode, mOffset, *mNewLeftNode);
- if (mEditorBase->GetShouldTxnSetSelection()) {
- RefPtr<Selection> selection = mEditorBase->GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- rv = selection->Collapse(mNewLeftNode, mOffset);
- }
- return rv.StealNSResult();
-}
-
-NS_IMETHODIMP
-SplitNodeTransaction::UndoTransaction()
-{
- if (NS_WARN_IF(!mEditorBase) ||
- NS_WARN_IF(!mNewLeftNode) ||
- NS_WARN_IF(!mParent)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // This assumes Do inserted the new node in front of the prior existing node
- return mEditorBase->JoinNodesImpl(mExistingRightNode, mNewLeftNode, mParent);
-}
-
-/* Redo cannot simply resplit the right node, because subsequent transactions
- * on the redo stack may depend on the left node existing in its previous
- * state.
- */
-NS_IMETHODIMP
-SplitNodeTransaction::RedoTransaction()
-{
- if (NS_WARN_IF(!mNewLeftNode) ||
- NS_WARN_IF(!mParent)) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- ErrorResult rv;
- // First, massage the existing node so it is in its post-split state
- if (mExistingRightNode->GetAsText()) {
- rv = mExistingRightNode->GetAsText()->DeleteData(0, mOffset);
- NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult());
- } else {
- nsCOMPtr<nsIContent> child = mExistingRightNode->GetFirstChild();
- nsCOMPtr<nsIContent> nextSibling;
- for (int32_t i=0; i < mOffset; i++) {
- if (rv.Failed()) {
- return rv.StealNSResult();
- }
- if (!child) {
- return NS_ERROR_NULL_POINTER;
- }
- nextSibling = child->GetNextSibling();
- mExistingRightNode->RemoveChild(*child, rv);
- if (!rv.Failed()) {
- mNewLeftNode->AppendChild(*child, rv);
- }
- child = nextSibling;
- }
- }
- // Second, re-insert the left node into the tree
- nsCOMPtr<nsIContent> refNode = mExistingRightNode;
- mParent->InsertBefore(*mNewLeftNode, refNode, rv);
- return rv.StealNSResult();
-}
-
-
-NS_IMETHODIMP
-SplitNodeTransaction::GetTxnDescription(nsAString& aString)
-{
- aString.AssignLiteral("SplitNodeTransaction");
- return NS_OK;
-}
-
-nsIContent*
-SplitNodeTransaction::GetNewNode()
-{
- return mNewLeftNode;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/SplitNodeTransaction.h b/editor/libeditor/SplitNodeTransaction.h
deleted file mode 100644
index 4c50143ec..000000000
--- a/editor/libeditor/SplitNodeTransaction.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef SplitNodeTransaction_h
-#define SplitNodeTransaction_h
-
-#include "mozilla/EditTransactionBase.h" // for EditTxn, etc.
-#include "nsCOMPtr.h" // for nsCOMPtr
-#include "nsCycleCollectionParticipant.h"
-#include "nsISupportsImpl.h" // for NS_DECL_ISUPPORTS_INHERITED
-#include "nscore.h" // for NS_IMETHOD
-
-class nsIContent;
-class nsINode;
-
-namespace mozilla {
-
-class EditorBase;
-
-/**
- * A transaction that splits a node into two identical nodes, with the children
- * divided between the new nodes.
- */
-class SplitNodeTransaction final : public EditTransactionBase
-{
-public:
- /**
- * @param aEditorBase The provider of core editing operations
- * @param aNode The node to split
- * @param aOffset The location within aNode to do the split. aOffset may
- * refer to children of aNode, or content of aNode. The
- * left node will have child|content 0..aOffset-1.
- */
- SplitNodeTransaction(EditorBase& aEditorBase, nsIContent& aNode,
- int32_t aOffset);
-
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SplitNodeTransaction,
- EditTransactionBase)
-
- NS_DECL_EDITTRANSACTIONBASE
-
- NS_IMETHOD RedoTransaction() override;
-
- nsIContent* GetNewNode();
-
-protected:
- virtual ~SplitNodeTransaction();
-
- RefPtr<EditorBase> mEditorBase;
-
- // The node to operate upon.
- nsCOMPtr<nsIContent> mExistingRightNode;
-
- // The offset into mExistingRightNode where its children are split. mOffset
- // is the index of the first child in the right node. -1 means the new node
- // gets no children.
- int32_t mOffset;
-
- // The node we create when splitting mExistingRightNode.
- nsCOMPtr<nsIContent> mNewLeftNode;
-
- // The parent shared by mExistingRightNode and mNewLeftNode.
- nsCOMPtr<nsINode> mParent;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef SplitNodeTransaction_h
diff --git a/editor/libeditor/StyleSheetTransactions.cpp b/editor/libeditor/StyleSheetTransactions.cpp
deleted file mode 100644
index cf32898a9..000000000
--- a/editor/libeditor/StyleSheetTransactions.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "StyleSheetTransactions.h"
-
-#include <stddef.h> // for nullptr
-
-#include "nsAString.h"
-#include "nsCOMPtr.h" // for nsCOMPtr, do_QueryInterface, etc.
-#include "mozilla/StyleSheet.h" // for mozilla::StyleSheet
-#include "mozilla/StyleSheetInlines.h"
-#include "nsDebug.h" // for NS_ENSURE_TRUE
-#include "nsError.h" // for NS_OK, etc.
-#include "nsIDOMDocument.h" // for nsIDOMDocument
-#include "nsIDocument.h" // for nsIDocument
-#include "nsIDocumentObserver.h" // for UPDATE_STYLE
-#include "nsIEditor.h" // for nsIEditor
-
-namespace mozilla {
-
-static void
-AddStyleSheet(nsIEditor* aEditor, StyleSheet* aSheet)
-{
- nsCOMPtr<nsIDOMDocument> domDoc;
- aEditor->GetDocument(getter_AddRefs(domDoc));
- nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
- if (doc) {
- doc->BeginUpdate(UPDATE_STYLE);
- doc->AddStyleSheet(aSheet);
- doc->EndUpdate(UPDATE_STYLE);
- }
-}
-
-static void
-RemoveStyleSheet(nsIEditor* aEditor, StyleSheet* aSheet)
-{
- nsCOMPtr<nsIDOMDocument> domDoc;
- aEditor->GetDocument(getter_AddRefs(domDoc));
- nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
- if (doc) {
- doc->BeginUpdate(UPDATE_STYLE);
- doc->RemoveStyleSheet(aSheet);
- doc->EndUpdate(UPDATE_STYLE);
- }
-}
-
-/******************************************************************************
- * AddStyleSheetTransaction
- ******************************************************************************/
-
-AddStyleSheetTransaction::AddStyleSheetTransaction()
- : mEditor(nullptr)
-{
-}
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(AddStyleSheetTransaction,
- EditTransactionBase,
- mEditor,
- mSheet)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AddStyleSheetTransaction)
-NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
-
-NS_IMETHODIMP
-AddStyleSheetTransaction::Init(nsIEditor* aEditor,
- StyleSheet* aSheet)
-{
- NS_ENSURE_TRUE(aEditor && aSheet, NS_ERROR_INVALID_ARG);
-
- mEditor = aEditor;
- mSheet = aSheet;
-
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-AddStyleSheetTransaction::DoTransaction()
-{
- NS_ENSURE_TRUE(mEditor && mSheet, NS_ERROR_NOT_INITIALIZED);
-
- AddStyleSheet(mEditor, mSheet);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-AddStyleSheetTransaction::UndoTransaction()
-{
- NS_ENSURE_TRUE(mEditor && mSheet, NS_ERROR_NOT_INITIALIZED);
-
- RemoveStyleSheet(mEditor, mSheet);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-AddStyleSheetTransaction::GetTxnDescription(nsAString& aString)
-{
- aString.AssignLiteral("AddStyleSheetTransaction");
- return NS_OK;
-}
-
-/******************************************************************************
- * RemoveStyleSheetTransaction
- ******************************************************************************/
-
-RemoveStyleSheetTransaction::RemoveStyleSheetTransaction()
- : mEditor(nullptr)
-{
-}
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(RemoveStyleSheetTransaction,
- EditTransactionBase,
- mEditor,
- mSheet)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(RemoveStyleSheetTransaction)
-NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
-
-NS_IMETHODIMP
-RemoveStyleSheetTransaction::Init(nsIEditor* aEditor,
- StyleSheet* aSheet)
-{
- NS_ENSURE_TRUE(aEditor && aSheet, NS_ERROR_INVALID_ARG);
-
- mEditor = aEditor;
- mSheet = aSheet;
-
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-RemoveStyleSheetTransaction::DoTransaction()
-{
- NS_ENSURE_TRUE(mEditor && mSheet, NS_ERROR_NOT_INITIALIZED);
-
- RemoveStyleSheet(mEditor, mSheet);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-RemoveStyleSheetTransaction::UndoTransaction()
-{
- NS_ENSURE_TRUE(mEditor && mSheet, NS_ERROR_NOT_INITIALIZED);
-
- AddStyleSheet(mEditor, mSheet);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-RemoveStyleSheetTransaction::GetTxnDescription(nsAString& aString)
-{
- aString.AssignLiteral("RemoveStyleSheetTransaction");
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/StyleSheetTransactions.h b/editor/libeditor/StyleSheetTransactions.h
deleted file mode 100644
index d6855981b..000000000
--- a/editor/libeditor/StyleSheetTransactions.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef StylesheetTransactions_h
-#define StylesheetTransactions_h
-
-#include "mozilla/EditTransactionBase.h" // for EditTransactionBase, etc.
-#include "mozilla/StyleSheet.h" // for mozilla::StyleSheet
-#include "nsCycleCollectionParticipant.h"
-#include "nsID.h" // for REFNSIID
-#include "nscore.h" // for NS_IMETHOD
-
-class nsIEditor;
-
-namespace mozilla {
-
-class AddStyleSheetTransaction final : public EditTransactionBase
-{
-public:
- /**
- * Initialize the transaction.
- * @param aEditor The object providing core editing operations
- * @param aSheet The stylesheet to add
- */
- NS_IMETHOD Init(nsIEditor* aEditor, StyleSheet* aSheet);
-
- AddStyleSheetTransaction();
-
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AddStyleSheetTransaction,
- EditTransactionBase)
- NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
-
- NS_DECL_EDITTRANSACTIONBASE
-
-protected:
- // The editor that created this transaction.
- nsCOMPtr<nsIEditor> mEditor;
- // The style sheet to add.
- RefPtr<mozilla::StyleSheet> mSheet;
-};
-
-
-class RemoveStyleSheetTransaction final : public EditTransactionBase
-{
-public:
- /**
- * Initialize the transaction.
- * @param aEditor The object providing core editing operations.
- * @param aSheet The stylesheet to remove.
- */
- NS_IMETHOD Init(nsIEditor* aEditor, StyleSheet* aSheet);
-
- RemoveStyleSheetTransaction();
-
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(RemoveStyleSheetTransaction,
- EditTransactionBase)
- NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
-
- NS_DECL_EDITTRANSACTIONBASE
-
-protected:
- // The editor that created this transaction.
- nsCOMPtr<nsIEditor> mEditor;
- // The style sheet to remove.
- RefPtr<StyleSheet> mSheet;
-
-};
-
-} // namespace mozilla
-
-#endif // #ifndef StylesheetTransactions_h
diff --git a/editor/libeditor/TextEditRules.cpp b/editor/libeditor/TextEditRules.cpp
deleted file mode 100644
index e98d36dd3..000000000
--- a/editor/libeditor/TextEditRules.cpp
+++ /dev/null
@@ -1,1485 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/TextEditRules.h"
-
-#include "TextEditUtils.h"
-#include "mozilla/Assertions.h"
-#include "mozilla/EditorUtils.h"
-#include "mozilla/LookAndFeel.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/TextComposition.h"
-#include "mozilla/TextEditor.h"
-#include "mozilla/dom/Element.h"
-#include "mozilla/dom/NodeIterator.h"
-#include "mozilla/dom/Selection.h"
-#include "nsAString.h"
-#include "nsCOMPtr.h"
-#include "nsCRT.h"
-#include "nsCRTGlue.h"
-#include "nsComponentManagerUtils.h"
-#include "nsContentUtils.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsGkAtoms.h"
-#include "nsIContent.h"
-#include "nsIDOMDocument.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMNode.h"
-#include "nsIDOMNodeFilter.h"
-#include "nsIDOMNodeIterator.h"
-#include "nsIDOMNodeList.h"
-#include "nsIDOMText.h"
-#include "nsNameSpaceManager.h"
-#include "nsINode.h"
-#include "nsIPlaintextEditor.h"
-#include "nsISupportsBase.h"
-#include "nsLiteralString.h"
-#include "nsUnicharUtils.h"
-
-namespace mozilla {
-
-using namespace dom;
-
-#define CANCEL_OPERATION_IF_READONLY_OR_DISABLED \
- if (IsReadonly() || IsDisabled()) \
- { \
- *aCancel = true; \
- return NS_OK; \
- };
-
-/********************************************************
- * mozilla::TextEditRules
- ********************************************************/
-
-TextEditRules::TextEditRules()
- : mTextEditor(nullptr)
- , mPasswordIMEIndex(0)
- , mCachedSelectionOffset(0)
- , mActionNesting(0)
- , mLockRulesSniffing(false)
- , mDidExplicitlySetInterline(false)
- , mDeleteBidiImmediately(false)
- , mTheAction(EditAction::none)
- , mLastStart(0)
- , mLastLength(0)
-{
- InitFields();
-}
-
-void
-TextEditRules::InitFields()
-{
- mTextEditor = nullptr;
- mPasswordText.Truncate();
- mPasswordIMEText.Truncate();
- mPasswordIMEIndex = 0;
- mBogusNode = nullptr;
- mCachedSelectionNode = nullptr;
- mCachedSelectionOffset = 0;
- mActionNesting = 0;
- mLockRulesSniffing = false;
- mDidExplicitlySetInterline = false;
- mDeleteBidiImmediately = false;
- mTheAction = EditAction::none;
- mTimer = nullptr;
- mLastStart = 0;
- mLastLength = 0;
-}
-
-TextEditRules::~TextEditRules()
-{
- // do NOT delete mTextEditor here. We do not hold a ref count to
- // mTextEditor. mTextEditor owns our lifespan.
-
- if (mTimer) {
- mTimer->Cancel();
- }
-}
-
-NS_IMPL_CYCLE_COLLECTION(TextEditRules, mBogusNode, mCachedSelectionNode)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TextEditRules)
- NS_INTERFACE_MAP_ENTRY(nsIEditRules)
- NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
- NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIEditRules)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(TextEditRules)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(TextEditRules)
-
-NS_IMETHODIMP
-TextEditRules::Init(TextEditor* aTextEditor)
-{
- if (!aTextEditor) {
- return NS_ERROR_NULL_POINTER;
- }
-
- InitFields();
-
- // We hold a non-refcounted reference back to our editor.
- mTextEditor = aTextEditor;
- RefPtr<Selection> selection = mTextEditor->GetSelection();
- NS_WARNING_ASSERTION(selection, "editor cannot get selection");
-
- // Put in a magic br if needed. This method handles null selection,
- // which should never happen anyway
- nsresult rv = CreateBogusNodeIfNeeded(selection);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // If the selection hasn't been set up yet, set it up collapsed to the end of
- // our editable content.
- int32_t rangeCount;
- rv = selection->GetRangeCount(&rangeCount);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!rangeCount) {
- rv = mTextEditor->EndOfDocument();
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- if (IsPlaintextEditor()) {
- // ensure trailing br node
- rv = CreateTrailingBRIfNeeded();
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- mDeleteBidiImmediately =
- Preferences::GetBool("bidi.edit.delete_immediately", false);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-TextEditRules::SetInitialValue(const nsAString& aValue)
-{
- if (IsPasswordEditor()) {
- mPasswordText = aValue;
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-TextEditRules::DetachEditor()
-{
- if (mTimer) {
- mTimer->Cancel();
- }
- mTextEditor = nullptr;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-TextEditRules::BeforeEdit(EditAction action,
- nsIEditor::EDirection aDirection)
-{
- if (mLockRulesSniffing) {
- return NS_OK;
- }
-
- AutoLockRulesSniffing lockIt(this);
- mDidExplicitlySetInterline = false;
- if (!mActionNesting) {
- // let rules remember the top level action
- mTheAction = action;
- }
- mActionNesting++;
-
- // get the selection and cache the position before editing
- NS_ENSURE_STATE(mTextEditor);
- RefPtr<Selection> selection = mTextEditor->GetSelection();
- NS_ENSURE_STATE(selection);
-
- selection->GetAnchorNode(getter_AddRefs(mCachedSelectionNode));
- selection->GetAnchorOffset(&mCachedSelectionOffset);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-TextEditRules::AfterEdit(EditAction action,
- nsIEditor::EDirection aDirection)
-{
- if (mLockRulesSniffing) {
- return NS_OK;
- }
-
- AutoLockRulesSniffing lockIt(this);
-
- NS_PRECONDITION(mActionNesting>0, "bad action nesting!");
- if (!--mActionNesting) {
- NS_ENSURE_STATE(mTextEditor);
- RefPtr<Selection> selection = mTextEditor->GetSelection();
- NS_ENSURE_STATE(selection);
-
- NS_ENSURE_STATE(mTextEditor);
- nsresult rv =
- mTextEditor->HandleInlineSpellCheck(action, selection,
- mCachedSelectionNode,
- mCachedSelectionOffset,
- nullptr, 0, nullptr, 0);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // if only trailing <br> remaining remove it
- rv = RemoveRedundantTrailingBR();
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- // detect empty doc
- rv = CreateBogusNodeIfNeeded(selection);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // ensure trailing br node
- rv = CreateTrailingBRIfNeeded();
- NS_ENSURE_SUCCESS(rv, rv);
-
- // collapse the selection to the trailing BR if it's at the end of our text node
- CollapseSelectionToTrailingBRIfNeeded(selection);
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-TextEditRules::WillDoAction(Selection* aSelection,
- RulesInfo* aInfo,
- bool* aCancel,
- bool* aHandled)
-{
- // null selection is legal
- MOZ_ASSERT(aInfo && aCancel && aHandled);
-
- *aCancel = false;
- *aHandled = false;
-
- // my kingdom for dynamic cast
- TextRulesInfo* info = static_cast<TextRulesInfo*>(aInfo);
-
- switch (info->action) {
- case EditAction::insertBreak:
- UndefineCaretBidiLevel(aSelection);
- return WillInsertBreak(aSelection, aCancel, aHandled, info->maxLength);
- case EditAction::insertText:
- case EditAction::insertIMEText:
- UndefineCaretBidiLevel(aSelection);
- return WillInsertText(info->action, aSelection, aCancel, aHandled,
- info->inString, info->outString, info->maxLength);
- case EditAction::deleteSelection:
- return WillDeleteSelection(aSelection, info->collapsedAction,
- aCancel, aHandled);
- case EditAction::undo:
- return WillUndo(aSelection, aCancel, aHandled);
- case EditAction::redo:
- return WillRedo(aSelection, aCancel, aHandled);
- case EditAction::setTextProperty:
- return WillSetTextProperty(aSelection, aCancel, aHandled);
- case EditAction::removeTextProperty:
- return WillRemoveTextProperty(aSelection, aCancel, aHandled);
- case EditAction::outputText:
- return WillOutputText(aSelection, info->outputFormat, info->outString,
- aCancel, aHandled);
- case EditAction::insertElement:
- // i had thought this would be html rules only. but we put pre elements
- // into plaintext mail when doing quoting for reply! doh!
- WillInsert(*aSelection, aCancel);
- return NS_OK;
- default:
- return NS_ERROR_FAILURE;
- }
-}
-
-NS_IMETHODIMP
-TextEditRules::DidDoAction(Selection* aSelection,
- RulesInfo* aInfo,
- nsresult aResult)
-{
- NS_ENSURE_STATE(mTextEditor);
- // don't let any txns in here move the selection around behind our back.
- // Note that this won't prevent explicit selection setting from working.
- AutoTransactionsConserveSelection dontSpazMySelection(mTextEditor);
-
- NS_ENSURE_TRUE(aSelection && aInfo, NS_ERROR_NULL_POINTER);
-
- // my kingdom for dynamic cast
- TextRulesInfo* info = static_cast<TextRulesInfo*>(aInfo);
-
- switch (info->action) {
- case EditAction::insertBreak:
- return DidInsertBreak(aSelection, aResult);
- case EditAction::insertText:
- case EditAction::insertIMEText:
- return DidInsertText(aSelection, aResult);
- case EditAction::deleteSelection:
- return DidDeleteSelection(aSelection, info->collapsedAction, aResult);
- case EditAction::undo:
- return DidUndo(aSelection, aResult);
- case EditAction::redo:
- return DidRedo(aSelection, aResult);
- case EditAction::setTextProperty:
- return DidSetTextProperty(aSelection, aResult);
- case EditAction::removeTextProperty:
- return DidRemoveTextProperty(aSelection, aResult);
- case EditAction::outputText:
- return DidOutputText(aSelection, aResult);
- default:
- // Don't fail on transactions we don't handle here!
- return NS_OK;
- }
-}
-
-NS_IMETHODIMP_(bool)
-TextEditRules::DocumentIsEmpty()
-{
- return (mBogusNode != nullptr);
-}
-
-void
-TextEditRules::WillInsert(Selection& aSelection, bool* aCancel)
-{
- MOZ_ASSERT(aCancel);
-
- if (IsReadonly() || IsDisabled()) {
- *aCancel = true;
- return;
- }
-
- // initialize out param
- *aCancel = false;
-
- // check for the magic content node and delete it if it exists
- if (mBogusNode) {
- NS_ENSURE_TRUE_VOID(mTextEditor);
- mTextEditor->DeleteNode(mBogusNode);
- mBogusNode = nullptr;
- }
-}
-
-nsresult
-TextEditRules::DidInsert(Selection* aSelection,
- nsresult aResult)
-{
- return NS_OK;
-}
-
-nsresult
-TextEditRules::WillInsertBreak(Selection* aSelection,
- bool* aCancel,
- bool* aHandled,
- int32_t aMaxLength)
-{
- if (!aSelection || !aCancel || !aHandled) {
- return NS_ERROR_NULL_POINTER;
- }
- CANCEL_OPERATION_IF_READONLY_OR_DISABLED
- *aHandled = false;
- if (IsSingleLineEditor()) {
- *aCancel = true;
- } else {
- // handle docs with a max length
- // NOTE, this function copies inString into outString for us.
- NS_NAMED_LITERAL_STRING(inString, "\n");
- nsAutoString outString;
- bool didTruncate;
- nsresult rv = TruncateInsertionIfNeeded(aSelection, &inString, &outString,
- aMaxLength, &didTruncate);
- NS_ENSURE_SUCCESS(rv, rv);
- if (didTruncate) {
- *aCancel = true;
- return NS_OK;
- }
-
- *aCancel = false;
-
- // if the selection isn't collapsed, delete it.
- bool bCollapsed;
- rv = aSelection->GetIsCollapsed(&bCollapsed);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!bCollapsed) {
- NS_ENSURE_STATE(mTextEditor);
- rv = mTextEditor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- WillInsert(*aSelection, aCancel);
- // initialize out param
- // we want to ignore result of WillInsert()
- *aCancel = false;
- }
- return NS_OK;
-}
-
-nsresult
-TextEditRules::DidInsertBreak(Selection* aSelection,
- nsresult aResult)
-{
- return NS_OK;
-}
-
-nsresult
-TextEditRules::CollapseSelectionToTrailingBRIfNeeded(Selection* aSelection)
-{
- // we only need to execute the stuff below if we are a plaintext editor.
- // html editors have a different mechanism for putting in mozBR's
- // (because there are a bunch more places you have to worry about it in html)
- if (!IsPlaintextEditor()) {
- return NS_OK;
- }
-
- NS_ENSURE_STATE(mTextEditor);
-
- // If there is no selection ranges, we should set to the end of the editor.
- // This is usually performed in TextEditRules::Init(), however, if the
- // editor is reframed, this may be called by AfterEdit().
- if (!aSelection->RangeCount()) {
- mTextEditor->EndOfDocument();
- }
-
- // if we are at the end of the textarea, we need to set the
- // selection to stick to the mozBR at the end of the textarea.
- int32_t selOffset;
- nsCOMPtr<nsIDOMNode> selNode;
- nsresult rv =
- mTextEditor->GetStartNodeAndOffset(aSelection,
- getter_AddRefs(selNode), &selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIDOMText> nodeAsText = do_QueryInterface(selNode);
- if (!nodeAsText) {
- return NS_OK; // Nothing to do if we're not at a text node.
- }
-
- uint32_t length;
- rv = nodeAsText->GetLength(&length);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // nothing to do if we're not at the end of the text node
- if (selOffset != int32_t(length)) {
- return NS_OK;
- }
-
- int32_t parentOffset;
- nsCOMPtr<nsIDOMNode> parentNode =
- EditorBase::GetNodeLocation(selNode, &parentOffset);
-
- NS_ENSURE_STATE(mTextEditor);
- nsCOMPtr<nsIDOMNode> root = do_QueryInterface(mTextEditor->GetRoot());
- NS_ENSURE_TRUE(root, NS_ERROR_NULL_POINTER);
- if (parentNode != root) {
- return NS_OK;
- }
-
- nsCOMPtr<nsIDOMNode> nextNode = mTextEditor->GetChildAt(parentNode,
- parentOffset + 1);
- if (nextNode && TextEditUtils::IsMozBR(nextNode)) {
- rv = aSelection->Collapse(parentNode, parentOffset + 1);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
-}
-
-static inline already_AddRefed<nsINode>
-GetTextNode(Selection* selection)
-{
- int32_t selOffset;
- nsCOMPtr<nsINode> selNode;
- nsresult rv =
- EditorBase::GetStartNodeAndOffset(selection,
- getter_AddRefs(selNode), &selOffset);
- NS_ENSURE_SUCCESS(rv, nullptr);
- if (!EditorBase::IsTextNode(selNode)) {
- // This should be the root node, walk the tree looking for text nodes
- RefPtr<NodeIterator> iter =
- new NodeIterator(selNode, nsIDOMNodeFilter::SHOW_TEXT,
- NodeFilterHolder());
- while (!EditorBase::IsTextNode(selNode)) {
- IgnoredErrorResult rv;
- selNode = iter->NextNode(rv);
- if (!selNode) {
- return nullptr;
- }
- }
- }
- return selNode.forget();
-}
-#ifdef DEBUG
-#define ASSERT_PASSWORD_LENGTHS_EQUAL() \
- if (IsPasswordEditor() && mTextEditor->GetRoot()) { \
- int32_t txtLen; \
- mTextEditor->GetTextLength(&txtLen); \
- NS_ASSERTION(mPasswordText.Length() == uint32_t(txtLen), \
- "password length not equal to number of asterisks"); \
- }
-#else
-#define ASSERT_PASSWORD_LENGTHS_EQUAL()
-#endif
-
-// static
-void
-TextEditRules::HandleNewLines(nsString& aString,
- int32_t aNewlineHandling)
-{
- if (aNewlineHandling < 0) {
- int32_t caretStyle;
- TextEditor::GetDefaultEditorPrefs(aNewlineHandling, caretStyle);
- }
-
- switch(aNewlineHandling) {
- case nsIPlaintextEditor::eNewlinesReplaceWithSpaces:
- // Strip trailing newlines first so we don't wind up with trailing spaces
- aString.Trim(CRLF, false, true);
- aString.ReplaceChar(CRLF, ' ');
- break;
- case nsIPlaintextEditor::eNewlinesStrip:
- aString.StripChars(CRLF);
- break;
- case nsIPlaintextEditor::eNewlinesPasteToFirst:
- default: {
- int32_t firstCRLF = aString.FindCharInSet(CRLF);
-
- // we get first *non-empty* line.
- int32_t offset = 0;
- while (firstCRLF == offset) {
- offset++;
- firstCRLF = aString.FindCharInSet(CRLF, offset);
- }
- if (firstCRLF > 0) {
- aString.Truncate(firstCRLF);
- }
- if (offset > 0) {
- aString.Cut(0, offset);
- }
- break;
- }
- case nsIPlaintextEditor::eNewlinesReplaceWithCommas:
- aString.Trim(CRLF, true, true);
- aString.ReplaceChar(CRLF, ',');
- break;
- case nsIPlaintextEditor::eNewlinesStripSurroundingWhitespace: {
- nsAutoString result;
- uint32_t offset = 0;
- while (offset < aString.Length()) {
- int32_t nextCRLF = aString.FindCharInSet(CRLF, offset);
- if (nextCRLF < 0) {
- result.Append(nsDependentSubstring(aString, offset));
- break;
- }
- uint32_t wsBegin = nextCRLF;
- // look backwards for the first non-whitespace char
- while (wsBegin > offset && NS_IS_SPACE(aString[wsBegin - 1])) {
- --wsBegin;
- }
- result.Append(nsDependentSubstring(aString, offset, wsBegin - offset));
- offset = nextCRLF + 1;
- while (offset < aString.Length() && NS_IS_SPACE(aString[offset])) {
- ++offset;
- }
- }
- aString = result;
- break;
- }
- case nsIPlaintextEditor::eNewlinesPasteIntact:
- // even if we're pasting newlines, don't paste leading/trailing ones
- aString.Trim(CRLF, true, true);
- break;
- }
-}
-
-nsresult
-TextEditRules::WillInsertText(EditAction aAction,
- Selection* aSelection,
- bool* aCancel,
- bool* aHandled,
- const nsAString* inString,
- nsAString* outString,
- int32_t aMaxLength)
-{
- if (!aSelection || !aCancel || !aHandled) {
- return NS_ERROR_NULL_POINTER;
- }
-
- if (inString->IsEmpty() && aAction != EditAction::insertIMEText) {
- // HACK: this is a fix for bug 19395
- // I can't outlaw all empty insertions
- // because IME transaction depend on them
- // There is more work to do to make the
- // world safe for IME.
- *aCancel = true;
- *aHandled = false;
- return NS_OK;
- }
-
- // initialize out param
- *aCancel = false;
- *aHandled = true;
-
- // handle docs with a max length
- // NOTE, this function copies inString into outString for us.
- bool truncated = false;
- nsresult rv = TruncateInsertionIfNeeded(aSelection, inString, outString,
- aMaxLength, &truncated);
- NS_ENSURE_SUCCESS(rv, rv);
- // If we're exceeding the maxlength when composing IME, we need to clean up
- // the composing text, so we shouldn't return early.
- if (truncated && outString->IsEmpty() &&
- aAction != EditAction::insertIMEText) {
- *aCancel = true;
- return NS_OK;
- }
-
- int32_t start = 0;
- int32_t end = 0;
-
- // handle password field docs
- if (IsPasswordEditor()) {
- NS_ENSURE_STATE(mTextEditor);
- nsContentUtils::GetSelectionInTextControl(aSelection,
- mTextEditor->GetRoot(),
- start, end);
- }
-
- // if the selection isn't collapsed, delete it.
- bool bCollapsed;
- rv = aSelection->GetIsCollapsed(&bCollapsed);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!bCollapsed) {
- NS_ENSURE_STATE(mTextEditor);
- rv = mTextEditor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- WillInsert(*aSelection, aCancel);
- // initialize out param
- // we want to ignore result of WillInsert()
- *aCancel = false;
-
- // handle password field data
- // this has the side effect of changing all the characters in aOutString
- // to the replacement character
- if (IsPasswordEditor() &&
- aAction == EditAction::insertIMEText) {
- RemoveIMETextFromPWBuf(start, outString);
- }
-
- // People have lots of different ideas about what text fields
- // should do with multiline pastes. See bugs 21032, 23485, 23485, 50935.
- // The six possible options are:
- // 0. paste newlines intact
- // 1. paste up to the first newline (default)
- // 2. replace newlines with spaces
- // 3. strip newlines
- // 4. replace with commas
- // 5. strip newlines and surrounding whitespace
- // So find out what we're expected to do:
- if (IsSingleLineEditor()) {
- nsAutoString tString(*outString);
-
- NS_ENSURE_STATE(mTextEditor);
- HandleNewLines(tString, mTextEditor->mNewlineHandling);
-
- outString->Assign(tString);
- }
-
- if (IsPasswordEditor()) {
- // manage the password buffer
- mPasswordText.Insert(*outString, start);
-
- if (LookAndFeel::GetEchoPassword() && !DontEchoPassword()) {
- HideLastPWInput();
- mLastStart = start;
- mLastLength = outString->Length();
- if (mTimer) {
- mTimer->Cancel();
- } else {
- mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- mTimer->InitWithCallback(this, LookAndFeel::GetPasswordMaskDelay(),
- nsITimer::TYPE_ONE_SHOT);
- } else {
- FillBufWithPWChars(outString, outString->Length());
- }
- }
-
- // get the (collapsed) selection location
- NS_ENSURE_STATE(aSelection->GetRangeAt(0));
- nsCOMPtr<nsINode> selNode = aSelection->GetRangeAt(0)->GetStartParent();
- int32_t selOffset = aSelection->GetRangeAt(0)->StartOffset();
- NS_ENSURE_STATE(selNode);
-
- // don't put text in places that can't have it
- NS_ENSURE_STATE(mTextEditor);
- if (!mTextEditor->IsTextNode(selNode) &&
- !mTextEditor->CanContainTag(*selNode, *nsGkAtoms::textTagName)) {
- return NS_ERROR_FAILURE;
- }
-
- // we need to get the doc
- NS_ENSURE_STATE(mTextEditor);
- nsCOMPtr<nsIDocument> doc = mTextEditor->GetDocument();
- NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
-
- if (aAction == EditAction::insertIMEText) {
- NS_ENSURE_STATE(mTextEditor);
- // Find better insertion point to insert text.
- mTextEditor->FindBetterInsertionPoint(selNode, selOffset);
- // If there is one or more IME selections, its minimum offset should be
- // the insertion point.
- int32_t IMESelectionOffset =
- mTextEditor->GetIMESelectionStartOffsetIn(selNode);
- if (IMESelectionOffset >= 0) {
- selOffset = IMESelectionOffset;
- }
- rv = mTextEditor->InsertTextImpl(*outString, address_of(selNode),
- &selOffset, doc);
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // aAction == EditAction::insertText; find where we are
- nsCOMPtr<nsINode> curNode = selNode;
- int32_t curOffset = selOffset;
-
- // don't spaz my selection in subtransactions
- NS_ENSURE_STATE(mTextEditor);
- AutoTransactionsConserveSelection dontSpazMySelection(mTextEditor);
-
- rv = mTextEditor->InsertTextImpl(*outString, address_of(curNode),
- &curOffset, doc);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (curNode) {
- // Make the caret attach to the inserted text, unless this text ends with a LF,
- // in which case make the caret attach to the next line.
- bool endsWithLF =
- !outString->IsEmpty() && outString->Last() == nsCRT::LF;
- aSelection->SetInterlinePosition(endsWithLF);
-
- aSelection->Collapse(curNode, curOffset);
- }
- }
- ASSERT_PASSWORD_LENGTHS_EQUAL()
- return NS_OK;
-}
-
-nsresult
-TextEditRules::DidInsertText(Selection* aSelection,
- nsresult aResult)
-{
- return DidInsert(aSelection, aResult);
-}
-
-nsresult
-TextEditRules::WillSetTextProperty(Selection* aSelection,
- bool* aCancel,
- bool* aHandled)
-{
- if (!aSelection || !aCancel || !aHandled) {
- return NS_ERROR_NULL_POINTER;
- }
-
- // XXX: should probably return a success value other than NS_OK that means "not allowed"
- if (IsPlaintextEditor()) {
- *aCancel = true;
- }
- return NS_OK;
-}
-
-nsresult
-TextEditRules::DidSetTextProperty(Selection* aSelection,
- nsresult aResult)
-{
- return NS_OK;
-}
-
-nsresult
-TextEditRules::WillRemoveTextProperty(Selection* aSelection,
- bool* aCancel,
- bool* aHandled)
-{
- if (!aSelection || !aCancel || !aHandled) {
- return NS_ERROR_NULL_POINTER;
- }
-
- // XXX: should probably return a success value other than NS_OK that means "not allowed"
- if (IsPlaintextEditor()) {
- *aCancel = true;
- }
- return NS_OK;
-}
-
-nsresult
-TextEditRules::DidRemoveTextProperty(Selection* aSelection,
- nsresult aResult)
-{
- return NS_OK;
-}
-
-nsresult
-TextEditRules::WillDeleteSelection(Selection* aSelection,
- nsIEditor::EDirection aCollapsedAction,
- bool* aCancel,
- bool* aHandled)
-{
- if (!aSelection || !aCancel || !aHandled) {
- return NS_ERROR_NULL_POINTER;
- }
- CANCEL_OPERATION_IF_READONLY_OR_DISABLED
-
- // initialize out param
- *aCancel = false;
- *aHandled = false;
-
- // if there is only bogus content, cancel the operation
- if (mBogusNode) {
- *aCancel = true;
- return NS_OK;
- }
-
- // If the current selection is empty (e.g the user presses backspace with
- // a collapsed selection), then we want to avoid sending the selectstart
- // event to the user, so we hide selection changes. However, we still
- // want to send a single selectionchange event to the document, so we
- // batch the selectionchange events, such that a single event fires after
- // the AutoHideSelectionChanges destructor has been run.
- SelectionBatcher selectionBatcher(aSelection);
- AutoHideSelectionChanges hideSelection(aSelection);
- nsAutoScriptBlocker scriptBlocker;
-
- if (IsPasswordEditor()) {
- NS_ENSURE_STATE(mTextEditor);
- nsresult rv =
- mTextEditor->ExtendSelectionForDelete(aSelection, &aCollapsedAction);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // manage the password buffer
- int32_t start, end;
- nsContentUtils::GetSelectionInTextControl(aSelection,
- mTextEditor->GetRoot(),
- start, end);
-
- if (LookAndFeel::GetEchoPassword()) {
- HideLastPWInput();
- mLastStart = start;
- mLastLength = 0;
- if (mTimer) {
- mTimer->Cancel();
- }
- }
-
- // Collapsed selection.
- if (end == start) {
- // Deleting back.
- if (nsIEditor::ePrevious == aCollapsedAction && 0<start) {
- mPasswordText.Cut(start-1, 1);
- }
- // Deleting forward.
- else if (nsIEditor::eNext == aCollapsedAction) {
- mPasswordText.Cut(start, 1);
- }
- // Otherwise nothing to do for this collapsed selection.
- }
- // Extended selection.
- else {
- mPasswordText.Cut(start, end-start);
- }
- } else {
- nsCOMPtr<nsIDOMNode> startNode;
- int32_t startOffset;
- NS_ENSURE_STATE(mTextEditor);
- nsresult rv =
- mTextEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(startNode),
- &startOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
-
- bool bCollapsed;
- rv = aSelection->GetIsCollapsed(&bCollapsed);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!bCollapsed) {
- return NS_OK;
- }
-
- // Test for distance between caret and text that will be deleted
- rv = CheckBidiLevelForDeletion(aSelection, startNode, startOffset,
- aCollapsedAction, aCancel);
- NS_ENSURE_SUCCESS(rv, rv);
- if (*aCancel) {
- return NS_OK;
- }
-
- NS_ENSURE_STATE(mTextEditor);
- rv = mTextEditor->ExtendSelectionForDelete(aSelection, &aCollapsedAction);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- NS_ENSURE_STATE(mTextEditor);
- nsresult rv =
- mTextEditor->DeleteSelectionImpl(aCollapsedAction, nsIEditor::eStrip);
- NS_ENSURE_SUCCESS(rv, rv);
-
- *aHandled = true;
- ASSERT_PASSWORD_LENGTHS_EQUAL()
- return NS_OK;
-}
-
-nsresult
-TextEditRules::DidDeleteSelection(Selection* aSelection,
- nsIEditor::EDirection aCollapsedAction,
- nsresult aResult)
-{
- nsCOMPtr<nsIDOMNode> startNode;
- int32_t startOffset;
- NS_ENSURE_STATE(mTextEditor);
- nsresult rv =
- mTextEditor->GetStartNodeAndOffset(aSelection,
- getter_AddRefs(startNode), &startOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
-
- // delete empty text nodes at selection
- if (mTextEditor->IsTextNode(startNode)) {
- nsCOMPtr<nsIDOMText> textNode = do_QueryInterface(startNode);
- uint32_t strLength;
- rv = textNode->GetLength(&strLength);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // are we in an empty text node?
- if (!strLength) {
- rv = mTextEditor->DeleteNode(startNode);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- if (mDidExplicitlySetInterline) {
- return NS_OK;
- }
- // We prevent the caret from sticking on the left of prior BR
- // (i.e. the end of previous line) after this deletion. Bug 92124
- return aSelection->SetInterlinePosition(true);
-}
-
-nsresult
-TextEditRules::WillUndo(Selection* aSelection,
- bool* aCancel,
- bool* aHandled)
-{
- if (!aSelection || !aCancel || !aHandled) {
- return NS_ERROR_NULL_POINTER;
- }
- CANCEL_OPERATION_IF_READONLY_OR_DISABLED
- // initialize out param
- *aCancel = false;
- *aHandled = false;
- return NS_OK;
-}
-
-/**
- * The idea here is to see if the magic empty node has suddenly reappeared as
- * the result of the undo. If it has, set our state so we remember it.
- * There is a tradeoff between doing here and at redo, or doing it everywhere
- * else that might care. Since undo and redo are relatively rare, it makes
- * sense to take the (small) performance hit here.
- */
-nsresult
-TextEditRules::DidUndo(Selection* aSelection,
- nsresult aResult)
-{
- NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
- // If aResult is an error, we return it.
- NS_ENSURE_SUCCESS(aResult, aResult);
-
- NS_ENSURE_STATE(mTextEditor);
- dom::Element* theRoot = mTextEditor->GetRoot();
- NS_ENSURE_TRUE(theRoot, NS_ERROR_FAILURE);
- nsIContent* node = mTextEditor->GetLeftmostChild(theRoot);
- if (node && mTextEditor->IsMozEditorBogusNode(node)) {
- mBogusNode = do_QueryInterface(node);
- } else {
- mBogusNode = nullptr;
- }
- return aResult;
-}
-
-nsresult
-TextEditRules::WillRedo(Selection* aSelection,
- bool* aCancel,
- bool* aHandled)
-{
- if (!aSelection || !aCancel || !aHandled) {
- return NS_ERROR_NULL_POINTER;
- }
- CANCEL_OPERATION_IF_READONLY_OR_DISABLED
- // initialize out param
- *aCancel = false;
- *aHandled = false;
- return NS_OK;
-}
-
-nsresult
-TextEditRules::DidRedo(Selection* aSelection,
- nsresult aResult)
-{
- if (!aSelection) {
- return NS_ERROR_NULL_POINTER;
- }
- if (NS_FAILED(aResult)) {
- return aResult; // if aResult is an error, we return it.
- }
-
- NS_ENSURE_STATE(mTextEditor);
- nsCOMPtr<nsIDOMElement> theRoot = do_QueryInterface(mTextEditor->GetRoot());
- NS_ENSURE_TRUE(theRoot, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIDOMHTMLCollection> nodeList;
- nsresult rv = theRoot->GetElementsByTagName(NS_LITERAL_STRING("br"),
- getter_AddRefs(nodeList));
- NS_ENSURE_SUCCESS(rv, rv);
- if (nodeList) {
- uint32_t len;
- nodeList->GetLength(&len);
-
- if (len != 1) {
- // only in the case of one br could there be the bogus node
- mBogusNode = nullptr;
- return NS_OK;
- }
-
- nsCOMPtr<nsIDOMNode> node;
- nodeList->Item(0, getter_AddRefs(node));
- nsCOMPtr<nsIContent> content = do_QueryInterface(node);
- MOZ_ASSERT(content);
- if (mTextEditor->IsMozEditorBogusNode(content)) {
- mBogusNode = node;
- } else {
- mBogusNode = nullptr;
- }
- }
- return NS_OK;
-}
-
-nsresult
-TextEditRules::WillOutputText(Selection* aSelection,
- const nsAString* aOutputFormat,
- nsAString* aOutString,
- bool* aCancel,
- bool* aHandled)
-{
- // null selection ok
- if (!aOutString || !aOutputFormat || !aCancel || !aHandled) {
- return NS_ERROR_NULL_POINTER;
- }
-
- // initialize out param
- *aCancel = false;
- *aHandled = false;
-
- nsAutoString outputFormat(*aOutputFormat);
- ToLowerCase(outputFormat);
- if (outputFormat.EqualsLiteral("text/plain")) {
- // Only use these rules for plain text output.
- if (IsPasswordEditor()) {
- *aOutString = mPasswordText;
- *aHandled = true;
- } else if (mBogusNode) {
- // This means there's no content, so output null string.
- aOutString->Truncate();
- *aHandled = true;
- }
- }
- return NS_OK;
-}
-
-nsresult
-TextEditRules::DidOutputText(Selection* aSelection,
- nsresult aResult)
-{
- return NS_OK;
-}
-
-nsresult
-TextEditRules::RemoveRedundantTrailingBR()
-{
- // If the bogus node exists, we have no work to do
- if (mBogusNode) {
- return NS_OK;
- }
-
- // Likewise, nothing to be done if we could never have inserted a trailing br
- if (IsSingleLineEditor()) {
- return NS_OK;
- }
-
- NS_ENSURE_STATE(mTextEditor);
- RefPtr<dom::Element> body = mTextEditor->GetRoot();
- if (!body) {
- return NS_ERROR_NULL_POINTER;
- }
-
- uint32_t childCount = body->GetChildCount();
- if (childCount > 1) {
- // The trailing br is redundant if it is the only remaining child node
- return NS_OK;
- }
-
- RefPtr<nsIContent> child = body->GetFirstChild();
- if (!child || !child->IsElement()) {
- return NS_OK;
- }
-
- dom::Element* elem = child->AsElement();
- if (!TextEditUtils::IsMozBR(elem)) {
- return NS_OK;
- }
-
- // Rather than deleting this node from the DOM tree we should instead
- // morph this br into the bogus node
- elem->UnsetAttr(kNameSpaceID_None, nsGkAtoms::type, true);
-
- // set mBogusNode to be this <br>
- mBogusNode = do_QueryInterface(elem);
-
- // give it the bogus node attribute
- elem->SetAttr(kNameSpaceID_None, kMOZEditorBogusNodeAttrAtom,
- kMOZEditorBogusNodeValue, false);
- return NS_OK;
-}
-
-nsresult
-TextEditRules::CreateTrailingBRIfNeeded()
-{
- // but only if we aren't a single line edit field
- if (IsSingleLineEditor()) {
- return NS_OK;
- }
-
- NS_ENSURE_STATE(mTextEditor);
- dom::Element* body = mTextEditor->GetRoot();
- NS_ENSURE_TRUE(body, NS_ERROR_NULL_POINTER);
-
- nsIContent* lastChild = body->GetLastChild();
- // assuming CreateBogusNodeIfNeeded() has been called first
- NS_ENSURE_TRUE(lastChild, NS_ERROR_NULL_POINTER);
-
- if (!lastChild->IsHTMLElement(nsGkAtoms::br)) {
- AutoTransactionsConserveSelection dontSpazMySelection(mTextEditor);
- nsCOMPtr<nsIDOMNode> domBody = do_QueryInterface(body);
- return CreateMozBR(domBody, body->Length());
- }
-
- // Check to see if the trailing BR is a former bogus node - this will have
- // stuck around if we previously morphed a trailing node into a bogus node.
- if (!mTextEditor->IsMozEditorBogusNode(lastChild)) {
- return NS_OK;
- }
-
- // Morph it back to a mozBR
- lastChild->UnsetAttr(kNameSpaceID_None, kMOZEditorBogusNodeAttrAtom, false);
- lastChild->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
- NS_LITERAL_STRING("_moz"), true);
- return NS_OK;
-}
-
-nsresult
-TextEditRules::CreateBogusNodeIfNeeded(Selection* aSelection)
-{
- NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
- NS_ENSURE_TRUE(mTextEditor, NS_ERROR_NULL_POINTER);
-
- if (mBogusNode) {
- // Let's not create more than one, ok?
- return NS_OK;
- }
-
- // tell rules system to not do any post-processing
- AutoRules beginRulesSniffing(mTextEditor, EditAction::ignore,
- nsIEditor::eNone);
-
- nsCOMPtr<dom::Element> body = mTextEditor->GetRoot();
- if (!body) {
- // We don't even have a body yet, don't insert any bogus nodes at
- // this point.
- return NS_OK;
- }
-
- // Now we've got the body element. Iterate over the body element's children,
- // looking for editable content. If no editable content is found, insert the
- // bogus node.
- for (nsCOMPtr<nsIContent> bodyChild = body->GetFirstChild();
- bodyChild;
- bodyChild = bodyChild->GetNextSibling()) {
- if (mTextEditor->IsMozEditorBogusNode(bodyChild) ||
- !mTextEditor->IsEditable(body) || // XXX hoist out of the loop?
- mTextEditor->IsEditable(bodyChild) ||
- mTextEditor->IsBlockNode(bodyChild)) {
- return NS_OK;
- }
- }
-
- // Skip adding the bogus node if body is read-only.
- if (!mTextEditor->IsModifiableNode(body)) {
- return NS_OK;
- }
-
- // Create a br.
- nsCOMPtr<Element> newContent = mTextEditor->CreateHTMLContent(nsGkAtoms::br);
- NS_ENSURE_STATE(newContent);
-
- // set mBogusNode to be the newly created <br>
- mBogusNode = do_QueryInterface(newContent);
- NS_ENSURE_TRUE(mBogusNode, NS_ERROR_NULL_POINTER);
-
- // Give it a special attribute.
- newContent->SetAttr(kNameSpaceID_None, kMOZEditorBogusNodeAttrAtom,
- kMOZEditorBogusNodeValue, false);
-
- // Put the node in the document.
- nsCOMPtr<nsIDOMNode> bodyNode = do_QueryInterface(body);
- nsresult rv = mTextEditor->InsertNode(mBogusNode, bodyNode, 0);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Set selection.
- aSelection->CollapseNative(body, 0);
- return NS_OK;
-}
-
-
-nsresult
-TextEditRules::TruncateInsertionIfNeeded(Selection* aSelection,
- const nsAString* aInString,
- nsAString* aOutString,
- int32_t aMaxLength,
- bool* aTruncated)
-{
- if (!aSelection || !aInString || !aOutString) {
- return NS_ERROR_NULL_POINTER;
- }
-
- if (!aOutString->Assign(*aInString, mozilla::fallible)) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- if (aTruncated) {
- *aTruncated = false;
- }
-
- NS_ENSURE_STATE(mTextEditor);
- if (-1 != aMaxLength && IsPlaintextEditor() &&
- !mTextEditor->IsIMEComposing()) {
- // Get the current text length.
- // Get the length of inString.
- // Get the length of the selection.
- // If selection is collapsed, it is length 0.
- // Subtract the length of the selection from the len(doc)
- // since we'll delete the selection on insert.
- // This is resultingDocLength.
- // Get old length of IME composing string
- // which will be replaced by new one.
- // If (resultingDocLength) is at or over max, cancel the insert
- // If (resultingDocLength) + (length of input) > max,
- // set aOutString to subset of inString so length = max
- int32_t docLength;
- nsresult rv = mTextEditor->GetTextLength(&docLength);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- int32_t start, end;
- nsContentUtils::GetSelectionInTextControl(aSelection,
- mTextEditor->GetRoot(),
- start, end);
-
- TextComposition* composition = mTextEditor->GetComposition();
- int32_t oldCompStrLength = composition ? composition->String().Length() : 0;
-
- const int32_t selectionLength = end - start;
- const int32_t resultingDocLength = docLength - selectionLength - oldCompStrLength;
- if (resultingDocLength >= aMaxLength) {
- // This call is guaranteed to reduce the capacity of the string, so it
- // cannot cause an OOM.
- aOutString->Truncate();
- if (aTruncated) {
- *aTruncated = true;
- }
- } else {
- int32_t oldLength = aOutString->Length();
- if (oldLength + resultingDocLength > aMaxLength) {
- int32_t newLength = aMaxLength - resultingDocLength;
- MOZ_ASSERT(newLength > 0);
- char16_t newLastChar = aOutString->CharAt(newLength - 1);
- char16_t removingFirstChar = aOutString->CharAt(newLength);
- // Don't separate the string between a surrogate pair.
- if (NS_IS_HIGH_SURROGATE(newLastChar) &&
- NS_IS_LOW_SURROGATE(removingFirstChar)) {
- newLength--;
- }
- // XXX What should we do if we're removing IVS and its preceding
- // character won't be removed?
- // This call is guaranteed to reduce the capacity of the string, so it
- // cannot cause an OOM.
- aOutString->Truncate(newLength);
- if (aTruncated) {
- *aTruncated = true;
- }
- }
- }
- }
- return NS_OK;
-}
-
-void
-TextEditRules::ResetIMETextPWBuf()
-{
- mPasswordIMEText.Truncate();
-}
-
-void
-TextEditRules::RemoveIMETextFromPWBuf(int32_t& aStart,
- nsAString* aIMEString)
-{
- MOZ_ASSERT(aIMEString);
-
- // initialize PasswordIME
- if (mPasswordIMEText.IsEmpty()) {
- mPasswordIMEIndex = aStart;
- } else {
- // manage the password buffer
- mPasswordText.Cut(mPasswordIMEIndex, mPasswordIMEText.Length());
- aStart = mPasswordIMEIndex;
- }
-
- mPasswordIMEText.Assign(*aIMEString);
-}
-
-NS_IMETHODIMP
-TextEditRules::Notify(nsITimer* aTimer)
-{
- MOZ_ASSERT(mTimer);
-
- // Check whether our text editor's password flag was changed before this
- // "hide password character" timer actually fires.
- nsresult rv = IsPasswordEditor() ? HideLastPWInput() : NS_OK;
- ASSERT_PASSWORD_LENGTHS_EQUAL();
- mLastLength = 0;
- return rv;
-}
-
-nsresult
-TextEditRules::HideLastPWInput()
-{
- if (!mLastLength) {
- // Special case, we're trying to replace a range that no longer exists
- return NS_OK;
- }
-
- nsAutoString hiddenText;
- FillBufWithPWChars(&hiddenText, mLastLength);
-
- NS_ENSURE_STATE(mTextEditor);
- RefPtr<Selection> selection = mTextEditor->GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- int32_t start, end;
- nsContentUtils::GetSelectionInTextControl(selection, mTextEditor->GetRoot(),
- start, end);
-
- nsCOMPtr<nsINode> selNode = GetTextNode(selection);
- NS_ENSURE_TRUE(selNode, NS_OK);
-
- selNode->GetAsText()->ReplaceData(mLastStart, mLastLength, hiddenText);
- selection->Collapse(selNode, start);
- if (start != end) {
- selection->Extend(selNode, end);
- }
- return NS_OK;
-}
-
-// static
-void
-TextEditRules::FillBufWithPWChars(nsAString* aOutString,
- int32_t aLength)
-{
- MOZ_ASSERT(aOutString);
-
- // change the output to the platform password character
- char16_t passwordChar = LookAndFeel::GetPasswordCharacter();
-
- aOutString->Truncate();
- for (int32_t i = 0; i < aLength; i++) {
- aOutString->Append(passwordChar);
- }
-}
-
-/**
- * CreateMozBR() puts a BR node with moz attribute at {inParent, inOffset}.
- */
-nsresult
-TextEditRules::CreateMozBR(nsIDOMNode* inParent,
- int32_t inOffset,
- nsIDOMNode** outBRNode)
-{
- NS_ENSURE_TRUE(inParent, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsIDOMNode> brNode;
- NS_ENSURE_STATE(mTextEditor);
- nsresult rv = mTextEditor->CreateBR(inParent, inOffset, address_of(brNode));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // give it special moz attr
- nsCOMPtr<Element> brElem = do_QueryInterface(brNode);
- if (brElem) {
- rv = mTextEditor->SetAttribute(brElem, nsGkAtoms::type,
- NS_LITERAL_STRING("_moz"));
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- if (outBRNode) {
- brNode.forget(outBRNode);
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-TextEditRules::DocumentModified()
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-bool
-TextEditRules::IsPasswordEditor() const
-{
- return mTextEditor ? mTextEditor->IsPasswordEditor() : false;
-}
-
-bool
-TextEditRules::IsSingleLineEditor() const
-{
- return mTextEditor ? mTextEditor->IsSingleLineEditor() : false;
-}
-
-bool
-TextEditRules::IsPlaintextEditor() const
-{
- return mTextEditor ? mTextEditor->IsPlaintextEditor() : false;
-}
-
-bool
-TextEditRules::IsReadonly() const
-{
- return mTextEditor ? mTextEditor->IsReadonly() : false;
-}
-
-bool
-TextEditRules::IsDisabled() const
-{
- return mTextEditor ? mTextEditor->IsDisabled() : false;
-}
-bool
-TextEditRules::IsMailEditor() const
-{
- return mTextEditor ? mTextEditor->IsMailEditor() : false;
-}
-
-bool
-TextEditRules::DontEchoPassword() const
-{
- return mTextEditor ? mTextEditor->DontEchoPassword() : false;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/TextEditRules.h b/editor/libeditor/TextEditRules.h
deleted file mode 100644
index 208e14d23..000000000
--- a/editor/libeditor/TextEditRules.h
+++ /dev/null
@@ -1,357 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_TextEditRules_h
-#define mozilla_TextEditRules_h
-
-#include "mozilla/EditorBase.h"
-#include "nsCOMPtr.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsIEditRules.h"
-#include "nsIEditor.h"
-#include "nsISupportsImpl.h"
-#include "nsITimer.h"
-#include "nsString.h"
-#include "nscore.h"
-
-class nsIDOMElement;
-class nsIDOMNode;
-
-namespace mozilla {
-
-class AutoLockRulesSniffing;
-class TextEditor;
-namespace dom {
-class Selection;
-} // namespace dom
-
-/**
- * Object that encapsulates HTML text-specific editing rules.
- *
- * To be a good citizen, edit rules must live by these restrictions:
- * 1. All data manipulation is through the editor.
- * Content nodes in the document tree must <B>not</B> be manipulated
- * directly. Content nodes in document fragments that are not part of the
- * document itself may be manipulated at will. Operations on document
- * fragments must <B>not</B> go through the editor.
- * 2. Selection must not be explicitly set by the rule method.
- * Any manipulation of Selection must be done by the editor.
- */
-class TextEditRules : public nsIEditRules
- , public nsITimerCallback
-{
-public:
- typedef dom::Element Element;
- typedef dom::Selection Selection;
- typedef dom::Text Text;
- template<typename T> using OwningNonNull = OwningNonNull<T>;
-
- NS_DECL_NSITIMERCALLBACK
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(TextEditRules, nsIEditRules)
-
- TextEditRules();
-
- // nsIEditRules methods
- NS_IMETHOD Init(TextEditor* aTextEditor) override;
- NS_IMETHOD SetInitialValue(const nsAString& aValue) override;
- NS_IMETHOD DetachEditor() override;
- NS_IMETHOD BeforeEdit(EditAction action,
- nsIEditor::EDirection aDirection) override;
- NS_IMETHOD AfterEdit(EditAction action,
- nsIEditor::EDirection aDirection) override;
- NS_IMETHOD WillDoAction(Selection* aSelection, RulesInfo* aInfo,
- bool* aCancel, bool* aHandled) override;
- NS_IMETHOD DidDoAction(Selection* aSelection, RulesInfo* aInfo,
- nsresult aResult) override;
- NS_IMETHOD_(bool) DocumentIsEmpty() override;
- NS_IMETHOD DocumentModified() override;
-
-protected:
- virtual ~TextEditRules();
-
-public:
- void ResetIMETextPWBuf();
-
- /**
- * Handles the newline characters either according to aNewLineHandling
- * or to the default system prefs if aNewLineHandling is negative.
- *
- * @param aString the string to be modified in place.
- * @param aNewLineHandling determine the desired type of newline handling:
- * * negative values:
- * handle newlines according to platform defaults.
- * * nsIPlaintextEditor::eNewlinesReplaceWithSpaces:
- * replace newlines with spaces.
- * * nsIPlaintextEditor::eNewlinesStrip:
- * remove newlines from the string.
- * * nsIPlaintextEditor::eNewlinesReplaceWithCommas:
- * replace newlines with commas.
- * * nsIPlaintextEditor::eNewlinesStripSurroundingWhitespace:
- * collapse newlines and surrounding whitespace characters and
- * remove them from the string.
- * * nsIPlaintextEditor::eNewlinesPasteIntact:
- * only remove the leading and trailing newlines.
- * * nsIPlaintextEditor::eNewlinesPasteToFirst or any other value:
- * remove the first newline and all characters following it.
- */
- static void HandleNewLines(nsString& aString, int32_t aNewLineHandling);
-
- /**
- * Prepare a string buffer for being displayed as the contents of a password
- * field. This function uses the platform-specific character for representing
- * characters entered into password fields.
- *
- * @param aOutString the output string. When this function returns,
- * aOutString will contain aLength password characters.
- * @param aLength the number of password characters that aOutString should
- * contain.
- */
- static void FillBufWithPWChars(nsAString* aOutString, int32_t aLength);
-
-protected:
-
- void InitFields();
-
- // TextEditRules implementation methods
- nsresult WillInsertText(EditAction aAction,
- Selection* aSelection,
- bool* aCancel,
- bool* aHandled,
- const nsAString* inString,
- nsAString* outString,
- int32_t aMaxLength);
- nsresult DidInsertText(Selection* aSelection, nsresult aResult);
- nsresult GetTopEnclosingPre(nsIDOMNode* aNode, nsIDOMNode** aOutPreNode);
-
- nsresult WillInsertBreak(Selection* aSelection, bool* aCancel,
- bool* aHandled, int32_t aMaxLength);
- nsresult DidInsertBreak(Selection* aSelection, nsresult aResult);
-
- void WillInsert(Selection& aSelection, bool* aCancel);
- nsresult DidInsert(Selection* aSelection, nsresult aResult);
-
- nsresult WillDeleteSelection(Selection* aSelection,
- nsIEditor::EDirection aCollapsedAction,
- bool* aCancel,
- bool* aHandled);
- nsresult DidDeleteSelection(Selection* aSelection,
- nsIEditor::EDirection aCollapsedAction,
- nsresult aResult);
-
- nsresult WillSetTextProperty(Selection* aSelection, bool* aCancel,
- bool* aHandled);
- nsresult DidSetTextProperty(Selection* aSelection, nsresult aResult);
-
- nsresult WillRemoveTextProperty(Selection* aSelection, bool* aCancel,
- bool* aHandled);
- nsresult DidRemoveTextProperty(Selection* aSelection, nsresult aResult);
-
- nsresult WillUndo(Selection* aSelection, bool* aCancel, bool* aHandled);
- nsresult DidUndo(Selection* aSelection, nsresult aResult);
-
- nsresult WillRedo(Selection* aSelection, bool* aCancel, bool* aHandled);
- nsresult DidRedo(Selection* aSelection, nsresult aResult);
-
- /**
- * Called prior to nsIEditor::OutputToString.
- * @param aSelection
- * @param aInFormat The format requested for the output, a MIME type.
- * @param aOutText The string to use for output, if aCancel is set to true.
- * @param aOutCancel If set to true, the caller should cancel the operation
- * and use aOutText as the result.
- */
- nsresult WillOutputText(Selection* aSelection,
- const nsAString* aInFormat,
- nsAString* aOutText,
- bool* aOutCancel,
- bool* aHandled);
-
- nsresult DidOutputText(Selection* aSelection, nsresult aResult);
-
- /**
- * Check for and replace a redundant trailing break.
- */
- nsresult RemoveRedundantTrailingBR();
-
- /**
- * Creates a trailing break in the text doc if there is not one already.
- */
- nsresult CreateTrailingBRIfNeeded();
-
- /**
- * Creates a bogus text node if the document has no editable content.
- */
- nsresult CreateBogusNodeIfNeeded(Selection* aSelection);
-
- /**
- * Returns a truncated insertion string if insertion would place us over
- * aMaxLength
- */
- nsresult TruncateInsertionIfNeeded(Selection* aSelection,
- const nsAString* aInString,
- nsAString* aOutString,
- int32_t aMaxLength,
- bool* aTruncated);
-
- /**
- * Remove IME composition text from password buffer.
- */
- void RemoveIMETextFromPWBuf(int32_t& aStart, nsAString* aIMEString);
-
- nsresult CreateMozBR(nsIDOMNode* inParent, int32_t inOffset,
- nsIDOMNode** outBRNode = nullptr);
-
- void UndefineCaretBidiLevel(Selection* aSelection);
-
- nsresult CheckBidiLevelForDeletion(Selection* aSelection,
- nsIDOMNode* aSelNode,
- int32_t aSelOffset,
- nsIEditor::EDirection aAction,
- bool* aCancel);
-
- nsresult HideLastPWInput();
-
- nsresult CollapseSelectionToTrailingBRIfNeeded(Selection* aSelection);
-
- bool IsPasswordEditor() const;
- bool IsSingleLineEditor() const;
- bool IsPlaintextEditor() const;
- bool IsReadonly() const;
- bool IsDisabled() const;
- bool IsMailEditor() const;
- bool DontEchoPassword() const;
-
- // Note that we do not refcount the editor.
- TextEditor* mTextEditor;
- // A buffer we use to store the real value of password editors.
- nsString mPasswordText;
- // A buffer we use to track the IME composition string.
- nsString mPasswordIMEText;
- uint32_t mPasswordIMEIndex;
- // Magic node acts as placeholder in empty doc.
- nsCOMPtr<nsIDOMNode> mBogusNode;
- // Cached selected node.
- nsCOMPtr<nsIDOMNode> mCachedSelectionNode;
- // Cached selected offset.
- int32_t mCachedSelectionOffset;
- uint32_t mActionNesting;
- bool mLockRulesSniffing;
- bool mDidExplicitlySetInterline;
- // In bidirectional text, delete characters not visually adjacent to the
- // caret without moving the caret first.
- bool mDeleteBidiImmediately;
- // The top level editor action.
- EditAction mTheAction;
- nsCOMPtr<nsITimer> mTimer;
- uint32_t mLastStart;
- uint32_t mLastLength;
-
- // friends
- friend class AutoLockRulesSniffing;
-};
-
-class TextRulesInfo final : public RulesInfo
-{
-public:
- explicit TextRulesInfo(EditAction aAction)
- : RulesInfo(aAction)
- , inString(nullptr)
- , outString(nullptr)
- , outputFormat(nullptr)
- , maxLength(-1)
- , collapsedAction(nsIEditor::eNext)
- , stripWrappers(nsIEditor::eStrip)
- , bOrdered(false)
- , entireList(false)
- , bulletType(nullptr)
- , alignType(nullptr)
- , blockType(nullptr)
- , insertElement(nullptr)
- {}
-
- // kInsertText
- const nsAString* inString;
- nsAString* outString;
- const nsAString* outputFormat;
- int32_t maxLength;
-
- // kDeleteSelection
- nsIEditor::EDirection collapsedAction;
- nsIEditor::EStripWrappers stripWrappers;
-
- // kMakeList
- bool bOrdered;
- bool entireList;
- const nsAString* bulletType;
-
- // kAlign
- const nsAString* alignType;
-
- // kMakeBasicBlock
- const nsAString* blockType;
-
- // kInsertElement
- const nsIDOMElement* insertElement;
-};
-
-/**
- * Stack based helper class for StartOperation()/EndOperation() sandwich.
- * This class sets a bool letting us know to ignore any rules sniffing
- * that tries to occur reentrantly.
- */
-class MOZ_STACK_CLASS AutoLockRulesSniffing final
-{
-public:
- explicit AutoLockRulesSniffing(TextEditRules* aRules)
- : mRules(aRules)
- {
- if (mRules) {
- mRules->mLockRulesSniffing = true;
- }
- }
-
- ~AutoLockRulesSniffing()
- {
- if (mRules) {
- mRules->mLockRulesSniffing = false;
- }
- }
-
-protected:
- TextEditRules* mRules;
-};
-
-/**
- * Stack based helper class for turning on/off the edit listener.
- */
-class MOZ_STACK_CLASS AutoLockListener final
-{
-public:
- explicit AutoLockListener(bool* aEnabled)
- : mEnabled(aEnabled)
- , mOldState(false)
- {
- if (mEnabled) {
- mOldState = *mEnabled;
- *mEnabled = false;
- }
- }
-
- ~AutoLockListener()
- {
- if (mEnabled) {
- *mEnabled = mOldState;
- }
- }
-
-protected:
- bool* mEnabled;
- bool mOldState;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef mozilla_TextEditRules_h
diff --git a/editor/libeditor/TextEditRulesBidi.cpp b/editor/libeditor/TextEditRulesBidi.cpp
deleted file mode 100644
index f6b8b7120..000000000
--- a/editor/libeditor/TextEditRulesBidi.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/TextEditRules.h"
-
-#include "mozilla/TextEditor.h"
-#include "mozilla/dom/Selection.h"
-#include "nsCOMPtr.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsFrameSelection.h"
-#include "nsIContent.h"
-#include "nsIDOMNode.h"
-#include "nsIEditor.h"
-#include "nsIPresShell.h"
-#include "nsISupportsImpl.h"
-#include "nsPresContext.h"
-#include "nscore.h"
-
-namespace mozilla {
-
-using namespace dom;
-
-// Test for distance between caret and text that will be deleted
-nsresult
-TextEditRules::CheckBidiLevelForDeletion(Selection* aSelection,
- nsIDOMNode* aSelNode,
- int32_t aSelOffset,
- nsIEditor::EDirection aAction,
- bool* aCancel)
-{
- NS_ENSURE_ARG_POINTER(aCancel);
- *aCancel = false;
-
- nsCOMPtr<nsIPresShell> shell = mTextEditor->GetPresShell();
- NS_ENSURE_TRUE(shell, NS_ERROR_NOT_INITIALIZED);
-
- nsPresContext *context = shell->GetPresContext();
- NS_ENSURE_TRUE(context, NS_ERROR_NULL_POINTER);
-
- if (!context->BidiEnabled()) {
- return NS_OK;
- }
-
- nsCOMPtr<nsIContent> content = do_QueryInterface(aSelNode);
- NS_ENSURE_TRUE(content, NS_ERROR_NULL_POINTER);
-
- nsBidiLevel levelBefore;
- nsBidiLevel levelAfter;
- RefPtr<nsFrameSelection> frameSelection =
- aSelection->AsSelection()->GetFrameSelection();
- NS_ENSURE_TRUE(frameSelection, NS_ERROR_NULL_POINTER);
-
- nsPrevNextBidiLevels levels = frameSelection->
- GetPrevNextBidiLevels(content, aSelOffset, true);
-
- levelBefore = levels.mLevelBefore;
- levelAfter = levels.mLevelAfter;
-
- nsBidiLevel currentCaretLevel = frameSelection->GetCaretBidiLevel();
-
- nsBidiLevel levelOfDeletion;
- levelOfDeletion =
- (nsIEditor::eNext==aAction || nsIEditor::eNextWord==aAction) ?
- levelAfter : levelBefore;
-
- if (currentCaretLevel == levelOfDeletion) {
- return NS_OK; // perform the deletion
- }
-
- if (!mDeleteBidiImmediately && levelBefore != levelAfter) {
- *aCancel = true;
- }
-
- // Set the bidi level of the caret to that of the
- // character that will be (or would have been) deleted
- frameSelection->SetCaretBidiLevel(levelOfDeletion);
- return NS_OK;
-}
-
-void
-TextEditRules::UndefineCaretBidiLevel(Selection* aSelection)
-{
- /**
- * After inserting text the caret Bidi level must be set to the level of the
- * inserted text.This is difficult, because we cannot know what the level is
- * until after the Bidi algorithm is applied to the whole paragraph.
- *
- * So we set the caret Bidi level to UNDEFINED here, and the caret code will
- * set it correctly later
- */
- RefPtr<nsFrameSelection> frameSelection = aSelection->GetFrameSelection();
- if (frameSelection) {
- frameSelection->UndefineCaretBidiLevel();
- }
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/TextEditUtils.cpp b/editor/libeditor/TextEditUtils.cpp
deleted file mode 100644
index 7c4f2ec12..000000000
--- a/editor/libeditor/TextEditUtils.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "TextEditUtils.h"
-
-#include "mozilla/Assertions.h"
-#include "mozilla/TextEditor.h"
-#include "mozilla/dom/Element.h"
-#include "nsAString.h"
-#include "nsCOMPtr.h"
-#include "nsCaseTreatment.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsGkAtoms.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMNode.h"
-#include "nsNameSpaceManager.h"
-#include "nsLiteralString.h"
-#include "nsString.h"
-
-namespace mozilla {
-
-/******************************************************************************
- * TextEditUtils
- ******************************************************************************/
-
-/**
- * IsBody() returns true if aNode is an html body node.
- */
-bool
-TextEditUtils::IsBody(nsIDOMNode* aNode)
-{
- return EditorBase::NodeIsType(aNode, nsGkAtoms::body);
-}
-
-/**
- * IsBreak() returns true if aNode is an html break node.
- */
-bool
-TextEditUtils::IsBreak(nsIDOMNode* aNode)
-{
- return EditorBase::NodeIsType(aNode, nsGkAtoms::br);
-}
-
-bool
-TextEditUtils::IsBreak(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
- return aNode->IsHTMLElement(nsGkAtoms::br);
-}
-
-
-/**
- * IsMozBR() returns true if aNode is an html br node with |type = _moz|.
- */
-bool
-TextEditUtils::IsMozBR(nsIDOMNode* aNode)
-{
- MOZ_ASSERT(aNode);
- return IsBreak(aNode) && HasMozAttr(aNode);
-}
-
-bool
-TextEditUtils::IsMozBR(nsINode* aNode)
-{
- MOZ_ASSERT(aNode);
- return aNode->IsHTMLElement(nsGkAtoms::br) &&
- aNode->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
- NS_LITERAL_STRING("_moz"),
- eIgnoreCase);
-}
-
-/**
- * HasMozAttr() returns true if aNode has type attribute and its value is
- * |_moz|. (Used to indicate div's and br's we use in mail compose rules)
- */
-bool
-TextEditUtils::HasMozAttr(nsIDOMNode* aNode)
-{
- MOZ_ASSERT(aNode);
- nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
- if (!element) {
- return false;
- }
- nsAutoString typeAttrVal;
- nsresult rv = element->GetAttribute(NS_LITERAL_STRING("type"), typeAttrVal);
- return NS_SUCCEEDED(rv) && typeAttrVal.LowerCaseEqualsLiteral("_moz");
-}
-
-/******************************************************************************
- * AutoEditInitRulesTrigger
- ******************************************************************************/
-
-AutoEditInitRulesTrigger::AutoEditInitRulesTrigger(TextEditor* aTextEditor,
- nsresult& aResult)
- : mTextEditor(aTextEditor)
- , mResult(aResult)
-{
- if (mTextEditor) {
- mTextEditor->BeginEditorInit();
- }
-}
-
-AutoEditInitRulesTrigger::~AutoEditInitRulesTrigger()
-{
- if (mTextEditor) {
- mResult = mTextEditor->EndEditorInit();
- }
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/TextEditUtils.h b/editor/libeditor/TextEditUtils.h
deleted file mode 100644
index cfdbc928f..000000000
--- a/editor/libeditor/TextEditUtils.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef TextEditUtils_h
-#define TextEditUtils_h
-
-#include "nscore.h"
-
-class nsIDOMNode;
-class nsINode;
-
-namespace mozilla {
-
-class TextEditor;
-
-class TextEditUtils final
-{
-public:
- // from TextEditRules:
- static bool IsBody(nsIDOMNode* aNode);
- static bool IsBreak(nsIDOMNode* aNode);
- static bool IsBreak(nsINode* aNode);
- static bool IsMozBR(nsIDOMNode* aNode);
- static bool IsMozBR(nsINode* aNode);
- static bool HasMozAttr(nsIDOMNode* aNode);
-};
-
-/***************************************************************************
- * stack based helper class for detecting end of editor initialization, in
- * order to trigger "end of init" initialization of the edit rules.
- */
-class AutoEditInitRulesTrigger final
-{
-private:
- TextEditor* mTextEditor;
- nsresult& mResult;
-
-public:
- AutoEditInitRulesTrigger(TextEditor* aTextEditor, nsresult& aResult);
- ~AutoEditInitRulesTrigger();
-};
-
-} // naemspace mozilla
-
-#endif // #ifndef TextEditUtils_h
diff --git a/editor/libeditor/TextEditor.cpp b/editor/libeditor/TextEditor.cpp
deleted file mode 100644
index 3bee7843c..000000000
--- a/editor/libeditor/TextEditor.cpp
+++ /dev/null
@@ -1,1641 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/TextEditor.h"
-
-#include "InternetCiter.h"
-#include "TextEditUtils.h"
-#include "gfxFontUtils.h"
-#include "mozilla/Assertions.h"
-#include "mozilla/EditorUtils.h" // AutoEditBatch, AutoRules
-#include "mozilla/mozalloc.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/TextEditRules.h"
-#include "mozilla/TextComposition.h"
-#include "mozilla/TextEvents.h"
-#include "mozilla/dom/Selection.h"
-#include "mozilla/dom/Event.h"
-#include "mozilla/dom/Element.h"
-#include "nsAString.h"
-#include "nsCRT.h"
-#include "nsCaret.h"
-#include "nsCharTraits.h"
-#include "nsComponentManagerUtils.h"
-#include "nsContentCID.h"
-#include "nsContentList.h"
-#include "nsCopySupport.h"
-#include "nsDebug.h"
-#include "nsDependentSubstring.h"
-#include "nsError.h"
-#include "nsGkAtoms.h"
-#include "nsIClipboard.h"
-#include "nsIContent.h"
-#include "nsIContentIterator.h"
-#include "nsIDOMCharacterData.h"
-#include "nsIDOMDocument.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMEventTarget.h"
-#include "nsIDOMKeyEvent.h"
-#include "nsIDOMNode.h"
-#include "nsIDOMNodeList.h"
-#include "nsIDocumentEncoder.h"
-#include "nsIEditorIMESupport.h"
-#include "nsIEditRules.h"
-#include "nsINode.h"
-#include "nsIPresShell.h"
-#include "nsISelectionController.h"
-#include "nsISupportsPrimitives.h"
-#include "nsITransferable.h"
-#include "nsIWeakReferenceUtils.h"
-#include "nsNameSpaceManager.h"
-#include "nsLiteralString.h"
-#include "nsReadableUtils.h"
-#include "nsServiceManagerUtils.h"
-#include "nsString.h"
-#include "nsStringFwd.h"
-#include "nsSubstringTuple.h"
-#include "nsUnicharUtils.h"
-#include "nsXPCOM.h"
-
-class nsIOutputStream;
-class nsISupports;
-
-namespace mozilla {
-
-using namespace dom;
-
-TextEditor::TextEditor()
- : mWrapColumn(0)
- , mMaxTextLength(-1)
- , mInitTriggerCounter(0)
- , mNewlineHandling(nsIPlaintextEditor::eNewlinesPasteToFirst)
-#ifdef XP_WIN
- , mCaretStyle(1)
-#else
- , mCaretStyle(0)
-#endif
-{
- // check the "single line editor newline handling"
- // and "caret behaviour in selection" prefs
- GetDefaultEditorPrefs(mNewlineHandling, mCaretStyle);
-}
-
-TextEditor::~TextEditor()
-{
- // Remove event listeners. Note that if we had an HTML editor,
- // it installed its own instead of these
- RemoveEventListeners();
-
- if (mRules)
- mRules->DetachEditor();
-}
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(TextEditor)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TextEditor, EditorBase)
- if (tmp->mRules)
- tmp->mRules->DetachEditor();
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mRules)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TextEditor, EditorBase)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRules)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_ADDREF_INHERITED(TextEditor, EditorBase)
-NS_IMPL_RELEASE_INHERITED(TextEditor, EditorBase)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TextEditor)
- NS_INTERFACE_MAP_ENTRY(nsIPlaintextEditor)
- NS_INTERFACE_MAP_ENTRY(nsIEditorMailSupport)
-NS_INTERFACE_MAP_END_INHERITING(EditorBase)
-
-
-NS_IMETHODIMP
-TextEditor::Init(nsIDOMDocument* aDoc,
- nsIContent* aRoot,
- nsISelectionController* aSelCon,
- uint32_t aFlags,
- const nsAString& aInitialValue)
-{
- NS_PRECONDITION(aDoc, "bad arg");
- NS_ENSURE_TRUE(aDoc, NS_ERROR_NULL_POINTER);
-
- if (mRules) {
- mRules->DetachEditor();
- }
-
- nsresult rulesRv = NS_OK;
- {
- // block to scope AutoEditInitRulesTrigger
- AutoEditInitRulesTrigger rulesTrigger(this, rulesRv);
-
- // Init the base editor
- nsresult rv = EditorBase::Init(aDoc, aRoot, aSelCon, aFlags, aInitialValue);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- }
- NS_ENSURE_SUCCESS(rulesRv, rulesRv);
-
- // mRules may not have been initialized yet, when this is called via
- // HTMLEditor::Init.
- if (mRules) {
- mRules->SetInitialValue(aInitialValue);
- }
-
- return NS_OK;
-}
-
-static int32_t sNewlineHandlingPref = -1,
- sCaretStylePref = -1;
-
-static void
-EditorPrefsChangedCallback(const char* aPrefName, void *)
-{
- if (!nsCRT::strcmp(aPrefName, "editor.singleLine.pasteNewlines")) {
- sNewlineHandlingPref =
- Preferences::GetInt("editor.singleLine.pasteNewlines",
- nsIPlaintextEditor::eNewlinesPasteToFirst);
- } else if (!nsCRT::strcmp(aPrefName, "layout.selection.caret_style")) {
- sCaretStylePref = Preferences::GetInt("layout.selection.caret_style",
-#ifdef XP_WIN
- 1);
- if (!sCaretStylePref) {
- sCaretStylePref = 1;
- }
-#else
- 0);
-#endif
- }
-}
-
-// static
-void
-TextEditor::GetDefaultEditorPrefs(int32_t& aNewlineHandling,
- int32_t& aCaretStyle)
-{
- if (sNewlineHandlingPref == -1) {
- Preferences::RegisterCallback(EditorPrefsChangedCallback,
- "editor.singleLine.pasteNewlines");
- EditorPrefsChangedCallback("editor.singleLine.pasteNewlines", nullptr);
- Preferences::RegisterCallback(EditorPrefsChangedCallback,
- "layout.selection.caret_style");
- EditorPrefsChangedCallback("layout.selection.caret_style", nullptr);
- }
-
- aNewlineHandling = sNewlineHandlingPref;
- aCaretStyle = sCaretStylePref;
-}
-
-void
-TextEditor::BeginEditorInit()
-{
- mInitTriggerCounter++;
-}
-
-nsresult
-TextEditor::EndEditorInit()
-{
- NS_PRECONDITION(mInitTriggerCounter > 0, "ended editor init before we began?");
- mInitTriggerCounter--;
- if (mInitTriggerCounter) {
- return NS_OK;
- }
-
- nsresult rv = InitRules();
- if (NS_FAILED(rv)) {
- return rv;
- }
- // Throw away the old transaction manager if this is not the first time that
- // we're initializing the editor.
- EnableUndo(false);
- EnableUndo(true);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-TextEditor::SetDocumentCharacterSet(const nsACString& characterSet)
-{
- nsresult rv = EditorBase::SetDocumentCharacterSet(characterSet);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Update META charset element.
- nsCOMPtr<nsIDOMDocument> domdoc = GetDOMDocument();
- NS_ENSURE_TRUE(domdoc, NS_ERROR_NOT_INITIALIZED);
-
- if (UpdateMetaCharset(domdoc, characterSet)) {
- return NS_OK;
- }
-
- nsCOMPtr<nsIDOMNodeList> headList;
- rv = domdoc->GetElementsByTagName(NS_LITERAL_STRING("head"), getter_AddRefs(headList));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(headList, NS_OK);
-
- nsCOMPtr<nsIDOMNode> headNode;
- headList->Item(0, getter_AddRefs(headNode));
- NS_ENSURE_TRUE(headNode, NS_OK);
-
- // Create a new meta charset tag
- nsCOMPtr<nsIDOMNode> resultNode;
- rv = CreateNode(NS_LITERAL_STRING("meta"), headNode, 0, getter_AddRefs(resultNode));
- NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
- NS_ENSURE_TRUE(resultNode, NS_OK);
-
- // Set attributes to the created element
- if (characterSet.IsEmpty()) {
- return NS_OK;
- }
-
- nsCOMPtr<dom::Element> metaElement = do_QueryInterface(resultNode);
- if (!metaElement) {
- return NS_OK;
- }
-
- // not undoable, undo should undo CreateNode
- metaElement->SetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv,
- NS_LITERAL_STRING("Content-Type"), true);
- metaElement->SetAttr(kNameSpaceID_None, nsGkAtoms::content,
- NS_LITERAL_STRING("text/html;charset=") +
- NS_ConvertASCIItoUTF16(characterSet),
- true);
- return NS_OK;
-}
-
-bool
-TextEditor::UpdateMetaCharset(nsIDOMDocument* aDocument,
- const nsACString& aCharacterSet)
-{
- MOZ_ASSERT(aDocument);
- // get a list of META tags
- nsCOMPtr<nsIDOMNodeList> list;
- nsresult rv = aDocument->GetElementsByTagName(NS_LITERAL_STRING("meta"),
- getter_AddRefs(list));
- NS_ENSURE_SUCCESS(rv, false);
- NS_ENSURE_TRUE(list, false);
-
- nsCOMPtr<nsINodeList> metaList = do_QueryInterface(list);
-
- uint32_t listLength = 0;
- metaList->GetLength(&listLength);
-
- for (uint32_t i = 0; i < listLength; ++i) {
- nsCOMPtr<nsIContent> metaNode = metaList->Item(i);
- MOZ_ASSERT(metaNode);
-
- if (!metaNode->IsElement()) {
- continue;
- }
-
- nsAutoString currentValue;
- metaNode->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, currentValue);
-
- if (!FindInReadable(NS_LITERAL_STRING("content-type"),
- currentValue,
- nsCaseInsensitiveStringComparator())) {
- continue;
- }
-
- metaNode->GetAttr(kNameSpaceID_None, nsGkAtoms::content, currentValue);
-
- NS_NAMED_LITERAL_STRING(charsetEquals, "charset=");
- nsAString::const_iterator originalStart, start, end;
- originalStart = currentValue.BeginReading(start);
- currentValue.EndReading(end);
- if (!FindInReadable(charsetEquals, start, end,
- nsCaseInsensitiveStringComparator())) {
- continue;
- }
-
- // set attribute to <original prefix> charset=text/html
- RefPtr<Element> metaElement = metaNode->AsElement();
- MOZ_ASSERT(metaElement);
- rv = EditorBase::SetAttribute(metaElement, nsGkAtoms::content,
- Substring(originalStart, start) +
- charsetEquals +
- NS_ConvertASCIItoUTF16(aCharacterSet));
- return NS_SUCCEEDED(rv);
- }
- return false;
-}
-
-NS_IMETHODIMP
-TextEditor::InitRules()
-{
- if (!mRules) {
- // instantiate the rules for this text editor
- mRules = new TextEditRules();
- }
- return mRules->Init(this);
-}
-
-
-NS_IMETHODIMP
-TextEditor::GetIsDocumentEditable(bool* aIsDocumentEditable)
-{
- NS_ENSURE_ARG_POINTER(aIsDocumentEditable);
-
- nsCOMPtr<nsIDOMDocument> doc = GetDOMDocument();
- *aIsDocumentEditable = doc && IsModifiable();
-
- return NS_OK;
-}
-
-bool
-TextEditor::IsModifiable()
-{
- return !IsReadonly();
-}
-
-nsresult
-TextEditor::HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent)
-{
- // NOTE: When you change this method, you should also change:
- // * editor/libeditor/tests/test_texteditor_keyevent_handling.html
- // * editor/libeditor/tests/test_htmleditor_keyevent_handling.html
- //
- // And also when you add new key handling, you need to change the subclass's
- // HandleKeyPressEvent()'s switch statement.
-
- if (IsReadonly() || IsDisabled()) {
- // When we're not editable, the events handled on EditorBase.
- return EditorBase::HandleKeyPressEvent(aKeyEvent);
- }
-
- WidgetKeyboardEvent* nativeKeyEvent =
- aKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
- NS_ENSURE_TRUE(nativeKeyEvent, NS_ERROR_UNEXPECTED);
- NS_ASSERTION(nativeKeyEvent->mMessage == eKeyPress,
- "HandleKeyPressEvent gets non-keypress event");
-
- switch (nativeKeyEvent->mKeyCode) {
- case NS_VK_META:
- case NS_VK_WIN:
- case NS_VK_SHIFT:
- case NS_VK_CONTROL:
- case NS_VK_ALT:
- case NS_VK_BACK:
- case NS_VK_DELETE:
- // These keys are handled on EditorBase
- return EditorBase::HandleKeyPressEvent(aKeyEvent);
- case NS_VK_TAB: {
- if (IsTabbable()) {
- return NS_OK; // let it be used for focus switching
- }
-
- if (nativeKeyEvent->IsShift() || nativeKeyEvent->IsControl() ||
- nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta() ||
- nativeKeyEvent->IsOS()) {
- return NS_OK;
- }
-
- // else we insert the tab straight through
- aKeyEvent->AsEvent()->PreventDefault();
- return TypedText(NS_LITERAL_STRING("\t"), eTypedText);
- }
- case NS_VK_RETURN:
- if (IsSingleLineEditor() || nativeKeyEvent->IsControl() ||
- nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta() ||
- nativeKeyEvent->IsOS()) {
- return NS_OK;
- }
- aKeyEvent->AsEvent()->PreventDefault();
- return TypedText(EmptyString(), eTypedBreak);
- }
-
- // NOTE: On some keyboard layout, some characters are inputted with Control
- // key or Alt key, but at that time, widget sets FALSE to these keys.
- if (!nativeKeyEvent->mCharCode || nativeKeyEvent->IsControl() ||
- nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta() ||
- nativeKeyEvent->IsOS()) {
- // we don't PreventDefault() here or keybindings like control-x won't work
- return NS_OK;
- }
- aKeyEvent->AsEvent()->PreventDefault();
- nsAutoString str(nativeKeyEvent->mCharCode);
- return TypedText(str, eTypedText);
-}
-
-/* This routine is needed to provide a bottleneck for typing for logging
- purposes. Can't use HandleKeyPress() (above) for that since it takes
- a nsIDOMKeyEvent* parameter. So instead we pass enough info through
- to TypedText() to determine what action to take, but without passing
- an event.
- */
-NS_IMETHODIMP
-TextEditor::TypedText(const nsAString& aString, ETypingAction aAction)
-{
- AutoPlaceHolderBatch batch(this, nsGkAtoms::TypingTxnName);
-
- switch (aAction) {
- case eTypedText:
- return InsertText(aString);
- case eTypedBreak:
- return InsertLineBreak();
- default:
- // eTypedBR is only for HTML
- return NS_ERROR_FAILURE;
- }
-}
-
-already_AddRefed<Element>
-TextEditor::CreateBRImpl(nsCOMPtr<nsINode>* aInOutParent,
- int32_t* aInOutOffset,
- EDirection aSelect)
-{
- nsCOMPtr<nsIDOMNode> parent(GetAsDOMNode(*aInOutParent));
- nsCOMPtr<nsIDOMNode> br;
- // We ignore the retval, and assume it's fine if the br is non-null
- CreateBRImpl(address_of(parent), aInOutOffset, address_of(br), aSelect);
- *aInOutParent = do_QueryInterface(parent);
- nsCOMPtr<Element> ret(do_QueryInterface(br));
- return ret.forget();
-}
-
-nsresult
-TextEditor::CreateBRImpl(nsCOMPtr<nsIDOMNode>* aInOutParent,
- int32_t* aInOutOffset,
- nsCOMPtr<nsIDOMNode>* outBRNode,
- EDirection aSelect)
-{
- NS_ENSURE_TRUE(aInOutParent && *aInOutParent && aInOutOffset && outBRNode, NS_ERROR_NULL_POINTER);
- *outBRNode = nullptr;
-
- // we need to insert a br. unfortunately, we may have to split a text node to do it.
- nsCOMPtr<nsIDOMNode> node = *aInOutParent;
- int32_t theOffset = *aInOutOffset;
- nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(node);
- NS_NAMED_LITERAL_STRING(brType, "br");
- nsCOMPtr<nsIDOMNode> brNode;
- if (nodeAsText) {
- int32_t offset;
- uint32_t len;
- nodeAsText->GetLength(&len);
- nsCOMPtr<nsIDOMNode> tmp = GetNodeLocation(node, &offset);
- NS_ENSURE_TRUE(tmp, NS_ERROR_FAILURE);
- if (!theOffset) {
- // we are already set to go
- } else if (theOffset == (int32_t)len) {
- // update offset to point AFTER the text node
- offset++;
- } else {
- // split the text node
- nsresult rv = SplitNode(node, theOffset, getter_AddRefs(tmp));
- NS_ENSURE_SUCCESS(rv, rv);
- tmp = GetNodeLocation(node, &offset);
- }
- // create br
- nsresult rv = CreateNode(brType, tmp, offset, getter_AddRefs(brNode));
- NS_ENSURE_SUCCESS(rv, rv);
- *aInOutParent = tmp;
- *aInOutOffset = offset+1;
- } else {
- nsresult rv = CreateNode(brType, node, theOffset, getter_AddRefs(brNode));
- NS_ENSURE_SUCCESS(rv, rv);
- (*aInOutOffset)++;
- }
-
- *outBRNode = brNode;
- if (*outBRNode && (aSelect != eNone)) {
- int32_t offset;
- nsCOMPtr<nsIDOMNode> parent = GetNodeLocation(*outBRNode, &offset);
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_STATE(selection);
- if (aSelect == eNext) {
- // position selection after br
- selection->SetInterlinePosition(true);
- selection->Collapse(parent, offset + 1);
- } else if (aSelect == ePrevious) {
- // position selection before br
- selection->SetInterlinePosition(true);
- selection->Collapse(parent, offset);
- }
- }
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-TextEditor::CreateBR(nsIDOMNode* aNode,
- int32_t aOffset,
- nsCOMPtr<nsIDOMNode>* outBRNode,
- EDirection aSelect)
-{
- nsCOMPtr<nsIDOMNode> parent = aNode;
- int32_t offset = aOffset;
- return CreateBRImpl(address_of(parent), &offset, outBRNode, aSelect);
-}
-
-nsresult
-TextEditor::InsertBR(nsCOMPtr<nsIDOMNode>* outBRNode)
-{
- NS_ENSURE_TRUE(outBRNode, NS_ERROR_NULL_POINTER);
- *outBRNode = nullptr;
-
- // calling it text insertion to trigger moz br treatment by rules
- AutoRules beginRulesSniffing(this, EditAction::insertText, nsIEditor::eNext);
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_STATE(selection);
-
- if (!selection->Collapsed()) {
- nsresult rv = DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- nsCOMPtr<nsIDOMNode> selNode;
- int32_t selOffset;
- nsresult rv =
- GetStartNodeAndOffset(selection, getter_AddRefs(selNode), &selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = CreateBR(selNode, selOffset, outBRNode);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // position selection after br
- selNode = GetNodeLocation(*outBRNode, &selOffset);
- selection->SetInterlinePosition(true);
- return selection->Collapse(selNode, selOffset+1);
-}
-
-nsresult
-TextEditor::ExtendSelectionForDelete(Selection* aSelection,
- nsIEditor::EDirection* aAction)
-{
- bool bCollapsed = aSelection->Collapsed();
-
- if (*aAction == eNextWord ||
- *aAction == ePreviousWord ||
- (*aAction == eNext && bCollapsed) ||
- (*aAction == ePrevious && bCollapsed) ||
- *aAction == eToBeginningOfLine ||
- *aAction == eToEndOfLine) {
- nsCOMPtr<nsISelectionController> selCont;
- GetSelectionController(getter_AddRefs(selCont));
- NS_ENSURE_TRUE(selCont, NS_ERROR_NO_INTERFACE);
-
- nsresult rv;
- switch (*aAction) {
- case eNextWord:
- rv = selCont->WordExtendForDelete(true);
- // DeleteSelectionImpl doesn't handle these actions
- // because it's inside batching, so don't confuse it:
- *aAction = eNone;
- break;
- case ePreviousWord:
- rv = selCont->WordExtendForDelete(false);
- *aAction = eNone;
- break;
- case eNext:
- rv = selCont->CharacterExtendForDelete();
- // Don't set aAction to eNone (see Bug 502259)
- break;
- case ePrevious: {
- // Only extend the selection where the selection is after a UTF-16
- // surrogate pair or a variation selector.
- // For other cases we don't want to do that, in order
- // to make sure that pressing backspace will only delete the last
- // typed character.
- nsCOMPtr<nsIDOMNode> node;
- int32_t offset;
- rv = GetStartNodeAndOffset(aSelection, getter_AddRefs(node), &offset);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
-
- // node might be anonymous DIV, so we find better text node
- FindBetterInsertionPoint(node, offset);
-
- if (IsTextNode(node)) {
- nsCOMPtr<nsIDOMCharacterData> charData = do_QueryInterface(node);
- if (charData) {
- nsAutoString data;
- rv = charData->GetData(data);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if ((offset > 1 &&
- NS_IS_LOW_SURROGATE(data[offset - 1]) &&
- NS_IS_HIGH_SURROGATE(data[offset - 2])) ||
- (offset > 0 &&
- gfxFontUtils::IsVarSelector(data[offset - 1]))) {
- rv = selCont->CharacterExtendForBackspace();
- }
- }
- }
- break;
- }
- case eToBeginningOfLine:
- selCont->IntraLineMove(true, false); // try to move to end
- rv = selCont->IntraLineMove(false, true); // select to beginning
- *aAction = eNone;
- break;
- case eToEndOfLine:
- rv = selCont->IntraLineMove(true, true);
- *aAction = eNext;
- break;
- default: // avoid several compiler warnings
- rv = NS_OK;
- break;
- }
- return rv;
- }
- return NS_OK;
-}
-
-nsresult
-TextEditor::DeleteSelection(EDirection aAction,
- EStripWrappers aStripWrappers)
-{
- MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
-
- if (!mRules) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- // delete placeholder txns merge.
- AutoPlaceHolderBatch batch(this, nsGkAtoms::DeleteTxnName);
- AutoRules beginRulesSniffing(this, EditAction::deleteSelection, aAction);
-
- // pre-process
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- // If there is an existing selection when an extended delete is requested,
- // platforms that use "caret-style" caret positioning collapse the
- // selection to the start and then create a new selection.
- // Platforms that use "selection-style" caret positioning just delete the
- // existing selection without extending it.
- if (!selection->Collapsed() &&
- (aAction == eNextWord || aAction == ePreviousWord ||
- aAction == eToBeginningOfLine || aAction == eToEndOfLine)) {
- if (mCaretStyle == 1) {
- nsresult rv = selection->CollapseToStart();
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- aAction = eNone;
- }
- }
-
- TextRulesInfo ruleInfo(EditAction::deleteSelection);
- ruleInfo.collapsedAction = aAction;
- ruleInfo.stripWrappers = aStripWrappers;
- bool cancel, handled;
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!cancel && !handled) {
- rv = DeleteSelectionImpl(aAction, aStripWrappers);
- }
- if (!cancel) {
- // post-process
- rv = rules->DidDoAction(selection, &ruleInfo, rv);
- }
- return rv;
-}
-
-NS_IMETHODIMP
-TextEditor::InsertText(const nsAString& aStringToInsert)
-{
- if (!mRules) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- EditAction opID = EditAction::insertText;
- if (ShouldHandleIMEComposition()) {
- opID = EditAction::insertIMEText;
- }
- AutoPlaceHolderBatch batch(this, nullptr);
- AutoRules beginRulesSniffing(this, opID, nsIEditor::eNext);
-
- // pre-process
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
- nsAutoString resultString;
- // XXX can we trust instring to outlive ruleInfo,
- // XXX and ruleInfo not to refer to instring in its dtor?
- //nsAutoString instring(aStringToInsert);
- TextRulesInfo ruleInfo(opID);
- ruleInfo.inString = &aStringToInsert;
- ruleInfo.outString = &resultString;
- ruleInfo.maxLength = mMaxTextLength;
-
- bool cancel, handled;
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!cancel && !handled) {
- // we rely on rules code for now - no default implementation
- }
- if (cancel) {
- return NS_OK;
- }
- // post-process
- return rules->DidDoAction(selection, &ruleInfo, rv);
-}
-
-NS_IMETHODIMP
-TextEditor::InsertLineBreak()
-{
- if (!mRules) {
- return NS_ERROR_NOT_INITIALIZED;
- }
-
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- AutoEditBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::insertBreak, nsIEditor::eNext);
-
- // pre-process
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- TextRulesInfo ruleInfo(EditAction::insertBreak);
- ruleInfo.maxLength = mMaxTextLength;
- bool cancel, handled;
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!cancel && !handled) {
- // get the (collapsed) selection location
- NS_ENSURE_STATE(selection->GetRangeAt(0));
- nsCOMPtr<nsINode> selNode = selection->GetRangeAt(0)->GetStartParent();
- int32_t selOffset = selection->GetRangeAt(0)->StartOffset();
- NS_ENSURE_STATE(selNode);
-
- // don't put text in places that can't have it
- if (!IsTextNode(selNode) && !CanContainTag(*selNode,
- *nsGkAtoms::textTagName)) {
- return NS_ERROR_FAILURE;
- }
-
- // we need to get the doc
- nsCOMPtr<nsIDocument> doc = GetDocument();
- NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
-
- // don't spaz my selection in subtransactions
- AutoTransactionsConserveSelection dontSpazMySelection(this);
-
- // insert a linefeed character
- rv = InsertTextImpl(NS_LITERAL_STRING("\n"), address_of(selNode),
- &selOffset, doc);
- if (!selNode) {
- rv = NS_ERROR_NULL_POINTER; // don't return here, so DidDoAction is called
- }
- if (NS_SUCCEEDED(rv)) {
- // set the selection to the correct location
- rv = selection->Collapse(selNode, selOffset);
- if (NS_SUCCEEDED(rv)) {
- // see if we're at the end of the editor range
- nsCOMPtr<nsIDOMNode> endNode;
- int32_t endOffset;
- rv = GetEndNodeAndOffset(selection,
- getter_AddRefs(endNode), &endOffset);
-
- if (NS_SUCCEEDED(rv) &&
- endNode == GetAsDOMNode(selNode) && endOffset == selOffset) {
- // SetInterlinePosition(true) means we want the caret to stick to the content on the "right".
- // We want the caret to stick to whatever is past the break. This is
- // because the break is on the same line we were on, but the next content
- // will be on the following line.
- selection->SetInterlinePosition(true);
- }
- }
- }
- }
-
- if (!cancel) {
- // post-process, always called if WillInsertBreak didn't return cancel==true
- rv = rules->DidDoAction(selection, &ruleInfo, rv);
- }
- return rv;
-}
-
-nsresult
-TextEditor::BeginIMEComposition(WidgetCompositionEvent* aEvent)
-{
- NS_ENSURE_TRUE(!mComposition, NS_OK);
-
- if (IsPasswordEditor()) {
- NS_ENSURE_TRUE(mRules, NS_ERROR_NULL_POINTER);
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- TextEditRules* textEditRules = static_cast<TextEditRules*>(rules.get());
- textEditRules->ResetIMETextPWBuf();
- }
-
- return EditorBase::BeginIMEComposition(aEvent);
-}
-
-nsresult
-TextEditor::UpdateIMEComposition(WidgetCompositionEvent* aCompositionChangeEvent)
-{
- MOZ_ASSERT(aCompositionChangeEvent,
- "aCompositionChangeEvent must not be nullptr");
-
- if (NS_WARN_IF(!aCompositionChangeEvent)) {
- return NS_ERROR_INVALID_ARG;
- }
-
- MOZ_ASSERT(aCompositionChangeEvent->mMessage == eCompositionChange,
- "The event should be eCompositionChange");
-
- if (!EnsureComposition(aCompositionChangeEvent)) {
- return NS_OK;
- }
-
- nsCOMPtr<nsIPresShell> ps = GetPresShell();
- NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_STATE(selection);
-
- // NOTE: TextComposition should receive selection change notification before
- // CompositionChangeEventHandlingMarker notifies TextComposition of the
- // end of handling compositionchange event because TextComposition may
- // need to ignore selection changes caused by composition. Therefore,
- // CompositionChangeEventHandlingMarker must be destroyed after a call
- // of NotifiyEditorObservers(eNotifyEditorObserversOfEnd) or
- // NotifiyEditorObservers(eNotifyEditorObserversOfCancel) which notifies
- // TextComposition of a selection change.
- MOZ_ASSERT(!mPlaceholderBatch,
- "UpdateIMEComposition() must be called without place holder batch");
- TextComposition::CompositionChangeEventHandlingMarker
- compositionChangeEventHandlingMarker(mComposition, aCompositionChangeEvent);
-
- NotifyEditorObservers(eNotifyEditorObserversOfBefore);
-
- RefPtr<nsCaret> caretP = ps->GetCaret();
-
- nsresult rv;
- {
- AutoPlaceHolderBatch batch(this, nsGkAtoms::IMETxnName);
-
- rv = InsertText(aCompositionChangeEvent->mData);
-
- if (caretP) {
- caretP->SetSelection(selection);
- }
- }
-
- // If still composing, we should fire input event via observer.
- // Note that if the composition will be committed by the following
- // compositionend event, we don't need to notify editor observes of this
- // change.
- // NOTE: We must notify after the auto batch will be gone.
- if (!aCompositionChangeEvent->IsFollowedByCompositionEnd()) {
- NotifyEditorObservers(eNotifyEditorObserversOfEnd);
- }
-
- return rv;
-}
-
-already_AddRefed<nsIContent>
-TextEditor::GetInputEventTargetContent()
-{
- nsCOMPtr<nsIContent> target = do_QueryInterface(mEventTarget);
- return target.forget();
-}
-
-NS_IMETHODIMP
-TextEditor::GetDocumentIsEmpty(bool* aDocumentIsEmpty)
-{
- NS_ENSURE_TRUE(aDocumentIsEmpty, NS_ERROR_NULL_POINTER);
-
- NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
-
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- *aDocumentIsEmpty = rules->DocumentIsEmpty();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-TextEditor::GetTextLength(int32_t* aCount)
-{
- NS_ASSERTION(aCount, "null pointer");
-
- // initialize out params
- *aCount = 0;
-
- // special-case for empty document, to account for the bogus node
- bool docEmpty;
- nsresult rv = GetDocumentIsEmpty(&docEmpty);
- NS_ENSURE_SUCCESS(rv, rv);
- if (docEmpty) {
- return NS_OK;
- }
-
- dom::Element *rootElement = GetRoot();
- NS_ENSURE_TRUE(rootElement, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsIContentIterator> iter =
- do_CreateInstance("@mozilla.org/content/post-content-iterator;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- uint32_t totalLength = 0;
- iter->Init(rootElement);
- for (; !iter->IsDone(); iter->Next()) {
- nsCOMPtr<nsIDOMNode> currentNode = do_QueryInterface(iter->GetCurrentNode());
- nsCOMPtr<nsIDOMCharacterData> textNode = do_QueryInterface(currentNode);
- if (textNode && IsEditable(currentNode)) {
- uint32_t length;
- textNode->GetLength(&length);
- totalLength += length;
- }
- }
-
- *aCount = totalLength;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-TextEditor::SetMaxTextLength(int32_t aMaxTextLength)
-{
- mMaxTextLength = aMaxTextLength;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-TextEditor::GetMaxTextLength(int32_t* aMaxTextLength)
-{
- NS_ENSURE_TRUE(aMaxTextLength, NS_ERROR_INVALID_POINTER);
- *aMaxTextLength = mMaxTextLength;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-TextEditor::GetWrapWidth(int32_t* aWrapColumn)
-{
- NS_ENSURE_TRUE( aWrapColumn, NS_ERROR_NULL_POINTER);
-
- *aWrapColumn = mWrapColumn;
- return NS_OK;
-}
-
-//
-// See if the style value includes this attribute, and if it does,
-// cut out everything from the attribute to the next semicolon.
-//
-static void CutStyle(const char* stylename, nsString& styleValue)
-{
- // Find the current wrapping type:
- int32_t styleStart = styleValue.Find(stylename, true);
- if (styleStart >= 0) {
- int32_t styleEnd = styleValue.Find(";", false, styleStart);
- if (styleEnd > styleStart) {
- styleValue.Cut(styleStart, styleEnd - styleStart + 1);
- } else {
- styleValue.Cut(styleStart, styleValue.Length() - styleStart);
- }
- }
-}
-
-NS_IMETHODIMP
-TextEditor::SetWrapWidth(int32_t aWrapColumn)
-{
- SetWrapColumn(aWrapColumn);
-
- // Make sure we're a plaintext editor, otherwise we shouldn't
- // do the rest of this.
- if (!IsPlaintextEditor()) {
- return NS_OK;
- }
-
- // Ought to set a style sheet here ...
- // Probably should keep around an mPlaintextStyleSheet for this purpose.
- dom::Element *rootElement = GetRoot();
- NS_ENSURE_TRUE(rootElement, NS_ERROR_NULL_POINTER);
-
- // Get the current style for this root element:
- nsAutoString styleValue;
- rootElement->GetAttr(kNameSpaceID_None, nsGkAtoms::style, styleValue);
-
- // We'll replace styles for these values:
- CutStyle("white-space", styleValue);
- CutStyle("width", styleValue);
- CutStyle("font-family", styleValue);
-
- // If we have other style left, trim off any existing semicolons
- // or whitespace, then add a known semicolon-space:
- if (!styleValue.IsEmpty()) {
- styleValue.Trim("; \t", false, true);
- styleValue.AppendLiteral("; ");
- }
-
- // Make sure we have fixed-width font. This should be done for us,
- // but it isn't, see bug 22502, so we have to add "font: -moz-fixed;".
- // Only do this if we're wrapping.
- if (IsWrapHackEnabled() && aWrapColumn >= 0) {
- styleValue.AppendLiteral("font-family: -moz-fixed; ");
- }
-
- // and now we're ready to set the new whitespace/wrapping style.
- if (aWrapColumn > 0) {
- // Wrap to a fixed column.
- styleValue.AppendLiteral("white-space: pre-wrap; width: ");
- styleValue.AppendInt(aWrapColumn);
- styleValue.AppendLiteral("ch;");
- } else if (!aWrapColumn) {
- styleValue.AppendLiteral("white-space: pre-wrap;");
- } else {
- styleValue.AppendLiteral("white-space: pre;");
- }
-
- return rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::style, styleValue, true);
-}
-
-NS_IMETHODIMP
-TextEditor::SetWrapColumn(int32_t aWrapColumn)
-{
- mWrapColumn = aWrapColumn;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-TextEditor::GetNewlineHandling(int32_t* aNewlineHandling)
-{
- NS_ENSURE_ARG_POINTER(aNewlineHandling);
-
- *aNewlineHandling = mNewlineHandling;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-TextEditor::SetNewlineHandling(int32_t aNewlineHandling)
-{
- mNewlineHandling = aNewlineHandling;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-TextEditor::Undo(uint32_t aCount)
-{
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- AutoUpdateViewBatch beginViewBatching(this);
-
- ForceCompositionEnd();
-
- NotifyEditorObservers(eNotifyEditorObserversOfBefore);
-
- AutoRules beginRulesSniffing(this, EditAction::undo, nsIEditor::eNone);
-
- TextRulesInfo ruleInfo(EditAction::undo);
- RefPtr<Selection> selection = GetSelection();
- bool cancel, handled;
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
-
- if (!cancel && NS_SUCCEEDED(rv)) {
- rv = EditorBase::Undo(aCount);
- rv = rules->DidDoAction(selection, &ruleInfo, rv);
- }
-
- NotifyEditorObservers(eNotifyEditorObserversOfEnd);
- return rv;
-}
-
-NS_IMETHODIMP
-TextEditor::Redo(uint32_t aCount)
-{
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- AutoUpdateViewBatch beginViewBatching(this);
-
- ForceCompositionEnd();
-
- NotifyEditorObservers(eNotifyEditorObserversOfBefore);
-
- AutoRules beginRulesSniffing(this, EditAction::redo, nsIEditor::eNone);
-
- TextRulesInfo ruleInfo(EditAction::redo);
- RefPtr<Selection> selection = GetSelection();
- bool cancel, handled;
- nsresult rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
-
- if (!cancel && NS_SUCCEEDED(rv)) {
- rv = EditorBase::Redo(aCount);
- rv = rules->DidDoAction(selection, &ruleInfo, rv);
- }
-
- NotifyEditorObservers(eNotifyEditorObserversOfEnd);
- return rv;
-}
-
-bool
-TextEditor::CanCutOrCopy(PasswordFieldAllowed aPasswordFieldAllowed)
-{
- RefPtr<Selection> selection = GetSelection();
- if (!selection) {
- return false;
- }
-
- if (aPasswordFieldAllowed == ePasswordFieldNotAllowed &&
- IsPasswordEditor()) {
- return false;
- }
-
- return !selection->Collapsed();
-}
-
-bool
-TextEditor::FireClipboardEvent(EventMessage aEventMessage,
- int32_t aSelectionType,
- bool* aActionTaken)
-{
- if (aEventMessage == ePaste) {
- ForceCompositionEnd();
- }
-
- nsCOMPtr<nsIPresShell> presShell = GetPresShell();
- NS_ENSURE_TRUE(presShell, false);
-
- RefPtr<Selection> selection = GetSelection();
- if (!selection) {
- return false;
- }
-
- if (!nsCopySupport::FireClipboardEvent(aEventMessage, aSelectionType,
- presShell, selection, aActionTaken)) {
- return false;
- }
-
- // If the event handler caused the editor to be destroyed, return false.
- // Otherwise return true to indicate that the event was not cancelled.
- return !mDidPreDestroy;
-}
-
-NS_IMETHODIMP
-TextEditor::Cut()
-{
- bool actionTaken = false;
- if (FireClipboardEvent(eCut, nsIClipboard::kGlobalClipboard, &actionTaken)) {
- DeleteSelection(eNone, eStrip);
- }
- return actionTaken ? NS_OK : NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-TextEditor::CanCut(bool* aCanCut)
-{
- NS_ENSURE_ARG_POINTER(aCanCut);
- // Cut is always enabled in HTML documents
- nsCOMPtr<nsIDocument> doc = GetDocument();
- *aCanCut = (doc && doc->IsHTMLOrXHTML()) ||
- (IsModifiable() && CanCutOrCopy(ePasswordFieldNotAllowed));
- return NS_OK;
-}
-
-NS_IMETHODIMP
-TextEditor::Copy()
-{
- bool actionTaken = false;
- FireClipboardEvent(eCopy, nsIClipboard::kGlobalClipboard, &actionTaken);
-
- return actionTaken ? NS_OK : NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-TextEditor::CanCopy(bool* aCanCopy)
-{
- NS_ENSURE_ARG_POINTER(aCanCopy);
- // Copy is always enabled in HTML documents
- nsCOMPtr<nsIDocument> doc = GetDocument();
- *aCanCopy = (doc && doc->IsHTMLOrXHTML()) ||
- CanCutOrCopy(ePasswordFieldNotAllowed);
- return NS_OK;
-}
-
-NS_IMETHODIMP
-TextEditor::CanDelete(bool* aCanDelete)
-{
- NS_ENSURE_ARG_POINTER(aCanDelete);
- *aCanDelete = IsModifiable() && CanCutOrCopy(ePasswordFieldAllowed);
- return NS_OK;
-}
-
-// Shared between OutputToString and OutputToStream
-NS_IMETHODIMP
-TextEditor::GetAndInitDocEncoder(const nsAString& aFormatType,
- uint32_t aFlags,
- const nsACString& aCharset,
- nsIDocumentEncoder** encoder)
-{
- nsresult rv = NS_OK;
-
- nsAutoCString formatType(NS_DOC_ENCODER_CONTRACTID_BASE);
- LossyAppendUTF16toASCII(aFormatType, formatType);
- nsCOMPtr<nsIDocumentEncoder> docEncoder (do_CreateInstance(formatType.get(), &rv));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIDOMDocument> domDoc = GetDOMDocument();
- NS_ASSERTION(domDoc, "Need a document");
-
- rv = docEncoder->Init(domDoc, aFormatType, aFlags);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!aCharset.IsEmpty() && !aCharset.EqualsLiteral("null")) {
- docEncoder->SetCharset(aCharset);
- }
-
- int32_t wc;
- (void) GetWrapWidth(&wc);
- if (wc >= 0) {
- (void) docEncoder->SetWrapColumn(wc);
- }
-
- // Set the selection, if appropriate.
- // We do this either if the OutputSelectionOnly flag is set,
- // in which case we use our existing selection ...
- if (aFlags & nsIDocumentEncoder::OutputSelectionOnly) {
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_STATE(selection);
- rv = docEncoder->SetSelection(selection);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // ... or if the root element is not a body,
- // in which case we set the selection to encompass the root.
- else {
- dom::Element* rootElement = GetRoot();
- NS_ENSURE_TRUE(rootElement, NS_ERROR_FAILURE);
- if (!rootElement->IsHTMLElement(nsGkAtoms::body)) {
- rv = docEncoder->SetNativeContainerNode(rootElement);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- docEncoder.forget(encoder);
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-TextEditor::OutputToString(const nsAString& aFormatType,
- uint32_t aFlags,
- nsAString& aOutputString)
-{
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- nsString resultString;
- TextRulesInfo ruleInfo(EditAction::outputText);
- ruleInfo.outString = &resultString;
- // XXX Struct should store a nsAReadable*
- nsAutoString str(aFormatType);
- ruleInfo.outputFormat = &str;
- bool cancel, handled;
- nsresult rv = rules->WillDoAction(nullptr, &ruleInfo, &cancel, &handled);
- if (cancel || NS_FAILED(rv)) {
- return rv;
- }
- if (handled) {
- // This case will get triggered by password fields.
- aOutputString.Assign(*(ruleInfo.outString));
- return rv;
- }
-
- nsAutoCString charsetStr;
- rv = GetDocumentCharacterSet(charsetStr);
- if (NS_FAILED(rv) || charsetStr.IsEmpty()) {
- charsetStr.AssignLiteral("ISO-8859-1");
- }
-
- nsCOMPtr<nsIDocumentEncoder> encoder;
- rv = GetAndInitDocEncoder(aFormatType, aFlags, charsetStr, getter_AddRefs(encoder));
- NS_ENSURE_SUCCESS(rv, rv);
- return encoder->EncodeToString(aOutputString);
-}
-
-NS_IMETHODIMP
-TextEditor::OutputToStream(nsIOutputStream* aOutputStream,
- const nsAString& aFormatType,
- const nsACString& aCharset,
- uint32_t aFlags)
-{
- nsresult rv;
-
- // special-case for empty document when requesting plain text,
- // to account for the bogus text node.
- // XXX Should there be a similar test in OutputToString?
- if (aFormatType.EqualsLiteral("text/plain")) {
- bool docEmpty;
- rv = GetDocumentIsEmpty(&docEmpty);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (docEmpty) {
- return NS_OK; // Output nothing.
- }
- }
-
- nsCOMPtr<nsIDocumentEncoder> encoder;
- rv = GetAndInitDocEncoder(aFormatType, aFlags, aCharset,
- getter_AddRefs(encoder));
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- return encoder->EncodeToStream(aOutputStream);
-}
-
-NS_IMETHODIMP
-TextEditor::InsertTextWithQuotations(const nsAString& aStringToInsert)
-{
- return InsertText(aStringToInsert);
-}
-
-NS_IMETHODIMP
-TextEditor::PasteAsQuotation(int32_t aSelectionType)
-{
- // Get Clipboard Service
- nsresult rv;
- nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Get the nsITransferable interface for getting the data from the clipboard
- nsCOMPtr<nsITransferable> trans;
- rv = PrepareTransferable(getter_AddRefs(trans));
- if (NS_SUCCEEDED(rv) && trans) {
- // Get the Data from the clipboard
- clipboard->GetData(trans, aSelectionType);
-
- // Now we ask the transferable for the data
- // it still owns the data, we just have a pointer to it.
- // If it can't support a "text" output of the data the call will fail
- nsCOMPtr<nsISupports> genericDataObj;
- uint32_t len;
- nsAutoCString flav;
- rv = trans->GetAnyTransferData(flav, getter_AddRefs(genericDataObj),
- &len);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- if (flav.EqualsLiteral(kUnicodeMime) ||
- flav.EqualsLiteral(kMozTextInternal)) {
- nsCOMPtr<nsISupportsString> textDataObj ( do_QueryInterface(genericDataObj) );
- if (textDataObj && len > 0) {
- nsAutoString stuffToPaste;
- textDataObj->GetData ( stuffToPaste );
- AutoEditBatch beginBatching(this);
- rv = InsertAsQuotation(stuffToPaste, 0);
- }
- }
- }
-
- return rv;
-}
-
-NS_IMETHODIMP
-TextEditor::InsertAsQuotation(const nsAString& aQuotedText,
- nsIDOMNode** aNodeInserted)
-{
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- // Let the citer quote it for us:
- nsString quotedStuff;
- nsresult rv = InternetCiter::GetCiteString(aQuotedText, quotedStuff);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // It's best to put a blank line after the quoted text so that mails
- // written without thinking won't be so ugly.
- if (!aQuotedText.IsEmpty() && (aQuotedText.Last() != char16_t('\n'))) {
- quotedStuff.Append(char16_t('\n'));
- }
-
- // get selection
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
- AutoEditBatch beginBatching(this);
- AutoRules beginRulesSniffing(this, EditAction::insertText, nsIEditor::eNext);
-
- // give rules a chance to handle or cancel
- TextRulesInfo ruleInfo(EditAction::insertElement);
- bool cancel, handled;
- rv = rules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
- NS_ENSURE_SUCCESS(rv, rv);
- if (cancel) {
- return NS_OK; // Rules canceled the operation.
- }
- if (!handled) {
- rv = InsertText(quotedStuff);
-
- // XXX Should set *aNodeInserted to the first node inserted
- if (aNodeInserted && NS_SUCCEEDED(rv)) {
- *aNodeInserted = nullptr;
- }
- }
- return rv;
-}
-
-NS_IMETHODIMP
-TextEditor::PasteAsCitedQuotation(const nsAString& aCitation,
- int32_t aSelectionType)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-TextEditor::InsertAsCitedQuotation(const nsAString& aQuotedText,
- const nsAString& aCitation,
- bool aInsertHTML,
- nsIDOMNode** aNodeInserted)
-{
- return InsertAsQuotation(aQuotedText, aNodeInserted);
-}
-
-nsresult
-TextEditor::SharedOutputString(uint32_t aFlags,
- bool* aIsCollapsed,
- nsAString& aResult)
-{
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
-
- *aIsCollapsed = selection->Collapsed();
-
- if (!*aIsCollapsed) {
- aFlags |= nsIDocumentEncoder::OutputSelectionOnly;
- }
- // If the selection isn't collapsed, we'll use the whole document.
-
- return OutputToString(NS_LITERAL_STRING("text/plain"), aFlags, aResult);
-}
-
-NS_IMETHODIMP
-TextEditor::Rewrap(bool aRespectNewlines)
-{
- int32_t wrapCol;
- nsresult rv = GetWrapWidth(&wrapCol);
- NS_ENSURE_SUCCESS(rv, NS_OK);
-
- // Rewrap makes no sense if there's no wrap column; default to 72.
- if (wrapCol <= 0) {
- wrapCol = 72;
- }
-
- nsAutoString current;
- bool isCollapsed;
- rv = SharedOutputString(nsIDocumentEncoder::OutputFormatted
- | nsIDocumentEncoder::OutputLFLineBreak,
- &isCollapsed, current);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsString wrapped;
- uint32_t firstLineOffset = 0; // XXX need to reset this if there is a selection
- rv = InternetCiter::Rewrap(current, wrapCol, firstLineOffset,
- aRespectNewlines, wrapped);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (isCollapsed) {
- SelectAll();
- }
-
- return InsertTextWithQuotations(wrapped);
-}
-
-NS_IMETHODIMP
-TextEditor::StripCites()
-{
- nsAutoString current;
- bool isCollapsed;
- nsresult rv = SharedOutputString(nsIDocumentEncoder::OutputFormatted,
- &isCollapsed, current);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsString stripped;
- rv = InternetCiter::StripCites(current, stripped);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (isCollapsed) {
- rv = SelectAll();
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return InsertText(stripped);
-}
-
-NS_IMETHODIMP
-TextEditor::GetEmbeddedObjects(nsIArray** aNodeList)
-{
- if (NS_WARN_IF(!aNodeList)) {
- return NS_ERROR_INVALID_ARG;
- }
-
- *aNodeList = nullptr;
- return NS_OK;
-}
-
-/**
- * All editor operations which alter the doc should be prefaced
- * with a call to StartOperation, naming the action and direction.
- */
-NS_IMETHODIMP
-TextEditor::StartOperation(EditAction opID,
- nsIEditor::EDirection aDirection)
-{
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- EditorBase::StartOperation(opID, aDirection); // will set mAction, mDirection
- if (rules) {
- return rules->BeforeEdit(mAction, mDirection);
- }
- return NS_OK;
-}
-
-/**
- * All editor operations which alter the doc should be followed
- * with a call to EndOperation.
- */
-NS_IMETHODIMP
-TextEditor::EndOperation()
-{
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- // post processing
- nsresult rv = rules ? rules->AfterEdit(mAction, mDirection) : NS_OK;
- EditorBase::EndOperation(); // will clear mAction, mDirection
- return rv;
-}
-
-nsresult
-TextEditor::SelectEntireDocument(Selection* aSelection)
-{
- if (!aSelection || !mRules) {
- return NS_ERROR_NULL_POINTER;
- }
-
- // Protect the edit rules object from dying
- nsCOMPtr<nsIEditRules> rules(mRules);
-
- // is doc empty?
- if (rules->DocumentIsEmpty()) {
- // get root node
- nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(GetRoot());
- NS_ENSURE_TRUE(rootElement, NS_ERROR_FAILURE);
-
- // if it's empty don't select entire doc - that would select the bogus node
- return aSelection->Collapse(rootElement, 0);
- }
-
- SelectionBatcher selectionBatcher(aSelection);
- nsresult rv = EditorBase::SelectEntireDocument(aSelection);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Don't select the trailing BR node if we have one
- int32_t selOffset;
- nsCOMPtr<nsIDOMNode> selNode;
- rv = GetEndNodeAndOffset(aSelection, getter_AddRefs(selNode), &selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIDOMNode> childNode = GetChildAt(selNode, selOffset - 1);
-
- if (childNode && TextEditUtils::IsMozBR(childNode)) {
- int32_t parentOffset;
- nsCOMPtr<nsIDOMNode> parentNode = GetNodeLocation(childNode, &parentOffset);
-
- return aSelection->Extend(parentNode, parentOffset);
- }
-
- return NS_OK;
-}
-
-already_AddRefed<EventTarget>
-TextEditor::GetDOMEventTarget()
-{
- nsCOMPtr<EventTarget> copy = mEventTarget;
- return copy.forget();
-}
-
-
-nsresult
-TextEditor::SetAttributeOrEquivalent(Element* aElement,
- nsIAtom* aAttribute,
- const nsAString& aValue,
- bool aSuppressTransaction)
-{
- return EditorBase::SetAttribute(aElement, aAttribute, aValue);
-}
-
-nsresult
-TextEditor::RemoveAttributeOrEquivalent(Element* aElement,
- nsIAtom* aAttribute,
- bool aSuppressTransaction)
-{
- return EditorBase::RemoveAttribute(aElement, aAttribute);
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/TextEditor.h b/editor/libeditor/TextEditor.h
deleted file mode 100644
index 7bb594931..000000000
--- a/editor/libeditor/TextEditor.h
+++ /dev/null
@@ -1,250 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_TextEditor_h
-#define mozilla_TextEditor_h
-
-#include "mozilla/EditorBase.h"
-#include "nsCOMPtr.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsIEditor.h"
-#include "nsIEditorMailSupport.h"
-#include "nsIPlaintextEditor.h"
-#include "nsISupportsImpl.h"
-#include "nscore.h"
-
-class nsIContent;
-class nsIDOMDocument;
-class nsIDOMElement;
-class nsIDOMEvent;
-class nsIDOMKeyEvent;
-class nsIDOMNode;
-class nsIDocumentEncoder;
-class nsIEditRules;
-class nsIOutputStream;
-class nsISelectionController;
-class nsITransferable;
-
-namespace mozilla {
-
-class AutoEditInitRulesTrigger;
-class HTMLEditRules;
-class TextEditRules;
-namespace dom {
-class Selection;
-} // namespace dom
-
-/**
- * The text editor implementation.
- * Use to edit text document represented as a DOM tree.
- */
-class TextEditor : public EditorBase
- , public nsIPlaintextEditor
- , public nsIEditorMailSupport
-{
-public:
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TextEditor, EditorBase)
-
- enum ETypingAction
- {
- eTypedText, /* user typed text */
- eTypedBR, /* user typed shift-enter to get a br */
- eTypedBreak /* user typed enter */
- };
-
- TextEditor();
-
- // nsIPlaintextEditor methods
- NS_DECL_NSIPLAINTEXTEDITOR
-
- // nsIEditorMailSupport overrides
- NS_DECL_NSIEDITORMAILSUPPORT
-
- // Overrides of EditorBase
- virtual nsresult RemoveAttributeOrEquivalent(
- Element* aElement,
- nsIAtom* aAttribute,
- bool aSuppressTransaction) override;
- virtual nsresult SetAttributeOrEquivalent(Element* aElement,
- nsIAtom* aAttribute,
- const nsAString& aValue,
- bool aSuppressTransaction) override;
- using EditorBase::RemoveAttributeOrEquivalent;
- using EditorBase::SetAttributeOrEquivalent;
-
- NS_IMETHOD Init(nsIDOMDocument* aDoc, nsIContent* aRoot,
- nsISelectionController* aSelCon, uint32_t aFlags,
- const nsAString& aValue) override;
-
- NS_IMETHOD GetDocumentIsEmpty(bool* aDocumentIsEmpty) override;
- NS_IMETHOD GetIsDocumentEditable(bool* aIsDocumentEditable) override;
-
- NS_IMETHOD DeleteSelection(EDirection aAction,
- EStripWrappers aStripWrappers) override;
-
- NS_IMETHOD SetDocumentCharacterSet(const nsACString& characterSet) override;
-
- NS_IMETHOD Undo(uint32_t aCount) override;
- NS_IMETHOD Redo(uint32_t aCount) override;
-
- NS_IMETHOD Cut() override;
- NS_IMETHOD CanCut(bool* aCanCut) override;
- NS_IMETHOD Copy() override;
- NS_IMETHOD CanCopy(bool* aCanCopy) override;
- NS_IMETHOD CanDelete(bool* aCanDelete) override;
- NS_IMETHOD Paste(int32_t aSelectionType) override;
- NS_IMETHOD CanPaste(int32_t aSelectionType, bool* aCanPaste) override;
- NS_IMETHOD PasteTransferable(nsITransferable* aTransferable) override;
- NS_IMETHOD CanPasteTransferable(nsITransferable* aTransferable,
- bool* aCanPaste) override;
-
- NS_IMETHOD OutputToString(const nsAString& aFormatType,
- uint32_t aFlags,
- nsAString& aOutputString) override;
-
- NS_IMETHOD OutputToStream(nsIOutputStream* aOutputStream,
- const nsAString& aFormatType,
- const nsACString& aCharsetOverride,
- uint32_t aFlags) override;
-
- /**
- * All editor operations which alter the doc should be prefaced
- * with a call to StartOperation, naming the action and direction.
- */
- NS_IMETHOD StartOperation(EditAction opID,
- nsIEditor::EDirection aDirection) override;
-
- /**
- * All editor operations which alter the doc should be followed
- * with a call to EndOperation.
- */
- NS_IMETHOD EndOperation() override;
-
- /**
- * Make the given selection span the entire document.
- */
- virtual nsresult SelectEntireDocument(Selection* aSelection) override;
-
- virtual nsresult HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent) override;
-
- virtual already_AddRefed<dom::EventTarget> GetDOMEventTarget() override;
-
- virtual nsresult BeginIMEComposition(WidgetCompositionEvent* aEvent) override;
- virtual nsresult UpdateIMEComposition(
- WidgetCompositionEvent* aCompositionChangeEvent) override;
-
- virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override;
-
- // Utility Routines, not part of public API
- NS_IMETHOD TypedText(const nsAString& aString, ETypingAction aAction);
-
- nsresult InsertTextAt(const nsAString& aStringToInsert,
- nsIDOMNode* aDestinationNode,
- int32_t aDestOffset,
- bool aDoDeleteSelection);
-
- virtual nsresult InsertFromDataTransfer(dom::DataTransfer* aDataTransfer,
- int32_t aIndex,
- nsIDOMDocument* aSourceDoc,
- nsIDOMNode* aDestinationNode,
- int32_t aDestOffset,
- bool aDoDeleteSelection) override;
-
- virtual nsresult InsertFromDrop(nsIDOMEvent* aDropEvent) override;
-
- /**
- * Extends the selection for given deletion operation
- * If done, also update aAction to what's actually left to do after the
- * extension.
- */
- nsresult ExtendSelectionForDelete(Selection* aSelection,
- nsIEditor::EDirection* aAction);
-
- /**
- * Return true if the data is safe to insert as the source and destination
- * principals match, or we are in a editor context where this doesn't matter.
- * Otherwise, the data must be sanitized first.
- */
- bool IsSafeToInsertData(nsIDOMDocument* aSourceDoc);
-
- static void GetDefaultEditorPrefs(int32_t& aNewLineHandling,
- int32_t& aCaretStyle);
-
-protected:
- virtual ~TextEditor();
-
- NS_IMETHOD InitRules();
- void BeginEditorInit();
- nsresult EndEditorInit();
-
- NS_IMETHOD GetAndInitDocEncoder(const nsAString& aFormatType,
- uint32_t aFlags,
- const nsACString& aCharset,
- nsIDocumentEncoder** encoder);
-
- NS_IMETHOD CreateBR(nsIDOMNode* aNode, int32_t aOffset,
- nsCOMPtr<nsIDOMNode>* outBRNode,
- EDirection aSelect = eNone);
- already_AddRefed<Element> CreateBRImpl(nsCOMPtr<nsINode>* aInOutParent,
- int32_t* aInOutOffset,
- EDirection aSelect);
- nsresult CreateBRImpl(nsCOMPtr<nsIDOMNode>* aInOutParent,
- int32_t* aInOutOffset,
- nsCOMPtr<nsIDOMNode>* outBRNode,
- EDirection aSelect);
- nsresult InsertBR(nsCOMPtr<nsIDOMNode>* outBRNode);
-
- /**
- * Factored methods for handling insertion of data from transferables
- * (drag&drop or clipboard).
- */
- NS_IMETHOD PrepareTransferable(nsITransferable** transferable);
- NS_IMETHOD InsertTextFromTransferable(nsITransferable* transferable,
- nsIDOMNode* aDestinationNode,
- int32_t aDestOffset,
- bool aDoDeleteSelection);
-
- /**
- * Shared outputstring; returns whether selection is collapsed and resulting
- * string.
- */
- nsresult SharedOutputString(uint32_t aFlags, bool* aIsCollapsed,
- nsAString& aResult);
-
- /**
- * Small utility routine to test the eEditorReadonly bit.
- */
- bool IsModifiable();
-
- enum PasswordFieldAllowed
- {
- ePasswordFieldAllowed,
- ePasswordFieldNotAllowed
- };
- bool CanCutOrCopy(PasswordFieldAllowed aPasswordFieldAllowed);
- bool FireClipboardEvent(EventMessage aEventMessage,
- int32_t aSelectionType,
- bool* aActionTaken = nullptr);
-
- bool UpdateMetaCharset(nsIDOMDocument* aDocument,
- const nsACString& aCharacterSet);
-
-protected:
- nsCOMPtr<nsIEditRules> mRules;
- int32_t mWrapColumn;
- int32_t mMaxTextLength;
- int32_t mInitTriggerCounter;
- int32_t mNewlineHandling;
- int32_t mCaretStyle;
-
- friend class AutoEditInitRulesTrigger;
- friend class HTMLEditRules;
- friend class TextEditRules;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef mozilla_TextEditor_h
diff --git a/editor/libeditor/TextEditorDataTransfer.cpp b/editor/libeditor/TextEditorDataTransfer.cpp
deleted file mode 100644
index 2cc2906fa..000000000
--- a/editor/libeditor/TextEditorDataTransfer.cpp
+++ /dev/null
@@ -1,479 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/TextEditor.h"
-
-#include "mozilla/ArrayUtils.h"
-#include "mozilla/EditorUtils.h"
-#include "mozilla/MouseEvents.h"
-#include "mozilla/SelectionState.h"
-#include "mozilla/dom/Selection.h"
-#include "nsAString.h"
-#include "nsCOMPtr.h"
-#include "nsComponentManagerUtils.h"
-#include "nsContentUtils.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsIClipboard.h"
-#include "nsIContent.h"
-#include "nsIDOMDataTransfer.h"
-#include "nsIDOMDocument.h"
-#include "nsIDOMDragEvent.h"
-#include "nsIDOMEvent.h"
-#include "nsIDOMNode.h"
-#include "nsIDOMUIEvent.h"
-#include "nsIDocument.h"
-#include "nsIDragService.h"
-#include "nsIDragSession.h"
-#include "nsIEditor.h"
-#include "nsIEditorIMESupport.h"
-#include "nsIDocShell.h"
-#include "nsIDocShellTreeItem.h"
-#include "nsIPrincipal.h"
-#include "nsIFormControl.h"
-#include "nsIPlaintextEditor.h"
-#include "nsISupportsPrimitives.h"
-#include "nsITransferable.h"
-#include "nsIVariant.h"
-#include "nsLiteralString.h"
-#include "nsRange.h"
-#include "nsServiceManagerUtils.h"
-#include "nsString.h"
-#include "nsXPCOM.h"
-#include "nscore.h"
-
-class nsILoadContext;
-class nsISupports;
-
-namespace mozilla {
-
-using namespace dom;
-
-NS_IMETHODIMP
-TextEditor::PrepareTransferable(nsITransferable** transferable)
-{
- // Create generic Transferable for getting the data
- nsresult rv = CallCreateInstance("@mozilla.org/widget/transferable;1", transferable);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Get the nsITransferable interface for getting the data from the clipboard
- if (transferable) {
- nsCOMPtr<nsIDocument> destdoc = GetDocument();
- nsILoadContext* loadContext = destdoc ? destdoc->GetLoadContext() : nullptr;
- (*transferable)->Init(loadContext);
-
- (*transferable)->AddDataFlavor(kUnicodeMime);
- (*transferable)->AddDataFlavor(kMozTextInternal);
- };
- return NS_OK;
-}
-
-nsresult
-TextEditor::InsertTextAt(const nsAString& aStringToInsert,
- nsIDOMNode* aDestinationNode,
- int32_t aDestOffset,
- bool aDoDeleteSelection)
-{
- if (aDestinationNode) {
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_STATE(selection);
-
- nsCOMPtr<nsIDOMNode> targetNode = aDestinationNode;
- int32_t targetOffset = aDestOffset;
-
- if (aDoDeleteSelection) {
- // Use an auto tracker so that our drop point is correctly
- // positioned after the delete.
- AutoTrackDOMPoint tracker(mRangeUpdater, &targetNode, &targetOffset);
- nsresult rv = DeleteSelection(eNone, eStrip);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- nsresult rv = selection->Collapse(targetNode, targetOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return InsertText(aStringToInsert);
-}
-
-NS_IMETHODIMP
-TextEditor::InsertTextFromTransferable(nsITransferable* aTransferable,
- nsIDOMNode* aDestinationNode,
- int32_t aDestOffset,
- bool aDoDeleteSelection)
-{
- nsresult rv = NS_OK;
- nsAutoCString bestFlavor;
- nsCOMPtr<nsISupports> genericDataObj;
- uint32_t len = 0;
- if (NS_SUCCEEDED(
- aTransferable->GetAnyTransferData(bestFlavor,
- getter_AddRefs(genericDataObj),
- &len)) &&
- (bestFlavor.EqualsLiteral(kUnicodeMime) ||
- bestFlavor.EqualsLiteral(kMozTextInternal))) {
- AutoTransactionsConserveSelection dontSpazMySelection(this);
- nsCOMPtr<nsISupportsString> textDataObj ( do_QueryInterface(genericDataObj) );
- if (textDataObj && len > 0) {
- nsAutoString stuffToPaste;
- textDataObj->GetData(stuffToPaste);
- NS_ASSERTION(stuffToPaste.Length() <= (len/2), "Invalid length!");
-
- // Sanitize possible carriage returns in the string to be inserted
- nsContentUtils::PlatformToDOMLineBreaks(stuffToPaste);
-
- AutoEditBatch beginBatching(this);
- rv = InsertTextAt(stuffToPaste, aDestinationNode, aDestOffset, aDoDeleteSelection);
- }
- }
-
- // Try to scroll the selection into view if the paste/drop succeeded
-
- if (NS_SUCCEEDED(rv)) {
- ScrollSelectionIntoView(false);
- }
-
- return rv;
-}
-
-nsresult
-TextEditor::InsertFromDataTransfer(DataTransfer* aDataTransfer,
- int32_t aIndex,
- nsIDOMDocument* aSourceDoc,
- nsIDOMNode* aDestinationNode,
- int32_t aDestOffset,
- bool aDoDeleteSelection)
-{
- nsCOMPtr<nsIVariant> data;
- DataTransfer::Cast(aDataTransfer)->GetDataAtNoSecurityCheck(NS_LITERAL_STRING("text/plain"), aIndex,
- getter_AddRefs(data));
- if (data) {
- nsAutoString insertText;
- data->GetAsAString(insertText);
- nsContentUtils::PlatformToDOMLineBreaks(insertText);
-
- AutoEditBatch beginBatching(this);
- return InsertTextAt(insertText, aDestinationNode, aDestOffset, aDoDeleteSelection);
- }
-
- return NS_OK;
-}
-
-nsresult
-TextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
-{
- ForceCompositionEnd();
-
- nsCOMPtr<nsIDOMDragEvent> dragEvent(do_QueryInterface(aDropEvent));
- NS_ENSURE_TRUE(dragEvent, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIDOMDataTransfer> domDataTransfer;
- dragEvent->GetDataTransfer(getter_AddRefs(domDataTransfer));
- nsCOMPtr<DataTransfer> dataTransfer = do_QueryInterface(domDataTransfer);
- NS_ENSURE_TRUE(dataTransfer, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
- NS_ASSERTION(dragSession, "No drag session");
-
- nsCOMPtr<nsIDOMNode> sourceNode;
- dataTransfer->GetMozSourceNode(getter_AddRefs(sourceNode));
-
- nsCOMPtr<nsIDOMDocument> srcdomdoc;
- if (sourceNode) {
- sourceNode->GetOwnerDocument(getter_AddRefs(srcdomdoc));
- NS_ENSURE_TRUE(sourceNode, NS_ERROR_FAILURE);
- }
-
- if (nsContentUtils::CheckForSubFrameDrop(dragSession,
- aDropEvent->WidgetEventPtr()->AsDragEvent())) {
- // Don't allow drags from subframe documents with different origins than
- // the drop destination.
- if (srcdomdoc && !IsSafeToInsertData(srcdomdoc)) {
- return NS_OK;
- }
- }
-
- // Current doc is destination
- nsCOMPtr<nsIDOMDocument> destdomdoc = GetDOMDocument();
- NS_ENSURE_TRUE(destdomdoc, NS_ERROR_NOT_INITIALIZED);
-
- uint32_t numItems = 0;
- nsresult rv = dataTransfer->GetMozItemCount(&numItems);
- NS_ENSURE_SUCCESS(rv, rv);
- if (numItems < 1) {
- return NS_ERROR_FAILURE; // Nothing to drop?
- }
-
- // Combine any deletion and drop insertion into one transaction
- AutoEditBatch beginBatching(this);
-
- bool deleteSelection = false;
-
- // We have to figure out whether to delete and relocate caret only once
- // Parent and offset are under the mouse cursor
- nsCOMPtr<nsIDOMUIEvent> uiEvent = do_QueryInterface(aDropEvent);
- NS_ENSURE_TRUE(uiEvent, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIDOMNode> newSelectionParent;
- rv = uiEvent->GetRangeParent(getter_AddRefs(newSelectionParent));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(newSelectionParent, NS_ERROR_FAILURE);
-
- int32_t newSelectionOffset;
- rv = uiEvent->GetRangeOffset(&newSelectionOffset);
- NS_ENSURE_SUCCESS(rv, rv);
-
- RefPtr<Selection> selection = GetSelection();
- NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
-
- bool isCollapsed = selection->Collapsed();
-
- // Only the HTMLEditor::FindUserSelectAllNode returns a node.
- nsCOMPtr<nsIDOMNode> userSelectNode = FindUserSelectAllNode(newSelectionParent);
- if (userSelectNode) {
- // The drop is happening over a "-moz-user-select: all"
- // subtree so make sure the content we insert goes before
- // the root of the subtree.
- //
- // XXX: Note that inserting before the subtree matches the
- // current behavior when dropping on top of an image.
- // The decision for dropping before or after the
- // subtree should really be done based on coordinates.
-
- newSelectionParent = GetNodeLocation(userSelectNode, &newSelectionOffset);
-
- NS_ENSURE_TRUE(newSelectionParent, NS_ERROR_FAILURE);
- }
-
- // Check if mouse is in the selection
- // if so, jump through some hoops to determine if mouse is over selection (bail)
- // and whether user wants to copy selection or delete it
- if (!isCollapsed) {
- // We never have to delete if selection is already collapsed
- bool cursorIsInSelection = false;
-
- int32_t rangeCount;
- rv = selection->GetRangeCount(&rangeCount);
- NS_ENSURE_SUCCESS(rv, rv);
-
- for (int32_t j = 0; j < rangeCount; j++) {
- RefPtr<nsRange> range = selection->GetRangeAt(j);
- if (!range) {
- // don't bail yet, iterate through them all
- continue;
- }
-
- rv = range->IsPointInRange(newSelectionParent, newSelectionOffset, &cursorIsInSelection);
- if (cursorIsInSelection) {
- break;
- }
- }
-
- if (cursorIsInSelection) {
- // Dragging within same doc can't drop on itself -- leave!
- if (srcdomdoc == destdomdoc) {
- return NS_OK;
- }
-
- // Dragging from another window onto a selection
- // XXX Decision made to NOT do this,
- // note that 4.x does replace if dropped on
- //deleteSelection = true;
- } else {
- // We are NOT over the selection
- if (srcdomdoc == destdomdoc) {
- // Within the same doc: delete if user doesn't want to copy
- uint32_t dropEffect;
- dataTransfer->GetDropEffectInt(&dropEffect);
- deleteSelection = !(dropEffect & nsIDragService::DRAGDROP_ACTION_COPY);
- } else {
- // Different source doc: Don't delete
- deleteSelection = false;
- }
- }
- }
-
- if (IsPlaintextEditor()) {
- nsCOMPtr<nsIContent> content = do_QueryInterface(newSelectionParent);
- while (content) {
- nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(content));
- if (formControl && !formControl->AllowDrop()) {
- // Don't allow dropping into a form control that doesn't allow being
- // dropped into.
- return NS_OK;
- }
- content = content->GetParent();
- }
- }
-
- for (uint32_t i = 0; i < numItems; ++i) {
- InsertFromDataTransfer(dataTransfer, i, srcdomdoc, newSelectionParent,
- newSelectionOffset, deleteSelection);
- }
-
- if (NS_SUCCEEDED(rv)) {
- ScrollSelectionIntoView(false);
- }
-
- return rv;
-}
-
-NS_IMETHODIMP
-TextEditor::Paste(int32_t aSelectionType)
-{
- if (!FireClipboardEvent(ePaste, aSelectionType)) {
- return NS_OK;
- }
-
- // Get Clipboard Service
- nsresult rv;
- nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- // Get the nsITransferable interface for getting the data from the clipboard
- nsCOMPtr<nsITransferable> trans;
- rv = PrepareTransferable(getter_AddRefs(trans));
- if (NS_SUCCEEDED(rv) && trans) {
- // Get the Data from the clipboard
- if (NS_SUCCEEDED(clipboard->GetData(trans, aSelectionType)) &&
- IsModifiable()) {
- // handle transferable hooks
- nsCOMPtr<nsIDOMDocument> domdoc = GetDOMDocument();
- if (!EditorHookUtils::DoInsertionHook(domdoc, nullptr, trans)) {
- return NS_OK;
- }
-
- rv = InsertTextFromTransferable(trans, nullptr, 0, true);
- }
- }
-
- return rv;
-}
-
-NS_IMETHODIMP
-TextEditor::PasteTransferable(nsITransferable* aTransferable)
-{
- // Use an invalid value for the clipboard type as data comes from aTransferable
- // and we don't currently implement a way to put that in the data transfer yet.
- if (!FireClipboardEvent(ePaste, -1)) {
- return NS_OK;
- }
-
- if (!IsModifiable()) {
- return NS_OK;
- }
-
- // handle transferable hooks
- nsCOMPtr<nsIDOMDocument> domdoc = GetDOMDocument();
- if (!EditorHookUtils::DoInsertionHook(domdoc, nullptr, aTransferable)) {
- return NS_OK;
- }
-
- return InsertTextFromTransferable(aTransferable, nullptr, 0, true);
-}
-
-NS_IMETHODIMP
-TextEditor::CanPaste(int32_t aSelectionType,
- bool* aCanPaste)
-{
- NS_ENSURE_ARG_POINTER(aCanPaste);
- *aCanPaste = false;
-
- // Always enable the paste command when inside of a HTML or XHTML document.
- nsCOMPtr<nsIDocument> doc = GetDocument();
- if (doc && doc->IsHTMLOrXHTML()) {
- *aCanPaste = true;
- return NS_OK;
- }
-
- // can't paste if readonly
- if (!IsModifiable()) {
- return NS_OK;
- }
-
- nsresult rv;
- nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // the flavors that we can deal with
- const char* textEditorFlavors[] = { kUnicodeMime };
-
- bool haveFlavors;
- rv = clipboard->HasDataMatchingFlavors(textEditorFlavors,
- ArrayLength(textEditorFlavors),
- aSelectionType, &haveFlavors);
- NS_ENSURE_SUCCESS(rv, rv);
-
- *aCanPaste = haveFlavors;
- return NS_OK;
-}
-
-
-NS_IMETHODIMP
-TextEditor::CanPasteTransferable(nsITransferable* aTransferable,
- bool* aCanPaste)
-{
- NS_ENSURE_ARG_POINTER(aCanPaste);
-
- // can't paste if readonly
- if (!IsModifiable()) {
- *aCanPaste = false;
- return NS_OK;
- }
-
- // If |aTransferable| is null, assume that a paste will succeed.
- if (!aTransferable) {
- *aCanPaste = true;
- return NS_OK;
- }
-
- nsCOMPtr<nsISupports> data;
- uint32_t dataLen;
- nsresult rv = aTransferable->GetTransferData(kUnicodeMime,
- getter_AddRefs(data),
- &dataLen);
- if (NS_SUCCEEDED(rv) && data) {
- *aCanPaste = true;
- } else {
- *aCanPaste = false;
- }
-
- return NS_OK;
-}
-
-bool
-TextEditor::IsSafeToInsertData(nsIDOMDocument* aSourceDoc)
-{
- // Try to determine whether we should use a sanitizing fragment sink
- bool isSafe = false;
-
- nsCOMPtr<nsIDocument> destdoc = GetDocument();
- NS_ASSERTION(destdoc, "Where is our destination doc?");
- nsCOMPtr<nsIDocShellTreeItem> dsti = destdoc->GetDocShell();
- nsCOMPtr<nsIDocShellTreeItem> root;
- if (dsti) {
- dsti->GetRootTreeItem(getter_AddRefs(root));
- }
- nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(root);
- uint32_t appType;
- if (docShell && NS_SUCCEEDED(docShell->GetAppType(&appType))) {
- isSafe = appType == nsIDocShell::APP_TYPE_EDITOR;
- }
- if (!isSafe && aSourceDoc) {
- nsCOMPtr<nsIDocument> srcdoc = do_QueryInterface(aSourceDoc);
- NS_ASSERTION(srcdoc, "Where is our source doc?");
-
- nsIPrincipal* srcPrincipal = srcdoc->NodePrincipal();
- nsIPrincipal* destPrincipal = destdoc->NodePrincipal();
- NS_ASSERTION(srcPrincipal && destPrincipal, "How come we don't have a principal?");
- srcPrincipal->Subsumes(destPrincipal, &isSafe);
- }
-
- return isSafe;
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/TextEditorTest.cpp b/editor/libeditor/TextEditorTest.cpp
deleted file mode 100644
index 5378bc33b..000000000
--- a/editor/libeditor/TextEditorTest.cpp
+++ /dev/null
@@ -1,259 +0,0 @@
-/* -*- Mode: C++ tab-width: 2 indent-tabs-mode: nil c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifdef DEBUG
-
-#include "TextEditorTest.h"
-
-#include <stdio.h>
-
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsGkAtoms.h"
-#include "nsIDOMCharacterData.h"
-#include "nsIDOMDocument.h"
-#include "nsIDOMNode.h"
-#include "nsIDOMNodeList.h"
-#include "nsIEditor.h"
-#include "nsIHTMLEditor.h"
-#include "nsIPlaintextEditor.h"
-#include "nsISelection.h"
-#include "nsLiteralString.h"
-#include "nsReadableUtils.h"
-#include "nsString.h"
-#include "nsStringFwd.h"
-
-#define TEST_RESULT(r) { if (NS_FAILED(r)) {printf("FAILURE result=%X\n", static_cast<uint32_t>(r)); return r; } }
-#define TEST_POINTER(p) { if (!p) {printf("FAILURE null pointer\n"); return NS_ERROR_NULL_POINTER; } }
-
-TextEditorTest::TextEditorTest()
-{
- printf("constructed a TextEditorTest\n");
-}
-
-TextEditorTest::~TextEditorTest()
-{
- printf("destroyed a TextEditorTest\n");
-}
-
-void TextEditorTest::Run(nsIEditor *aEditor, int32_t *outNumTests, int32_t *outNumTestsFailed)
-{
- if (!aEditor) return;
- mTextEditor = do_QueryInterface(aEditor);
- mEditor = do_QueryInterface(aEditor);
- RunUnitTest(outNumTests, outNumTestsFailed);
-}
-
-nsresult TextEditorTest::RunUnitTest(int32_t *outNumTests, int32_t *outNumTestsFailed)
-{
- NS_ENSURE_TRUE(outNumTests && outNumTestsFailed, NS_ERROR_NULL_POINTER);
-
- *outNumTests = 0;
- *outNumTestsFailed = 0;
-
- nsresult rv = InitDoc();
- TEST_RESULT(rv);
- // shouldn't we just bail on error here?
-
- // insert some simple text
- rv = mTextEditor->InsertText(NS_LITERAL_STRING("1234567890abcdefghij1234567890"));
- TEST_RESULT(rv);
- (*outNumTests)++;
- if (NS_FAILED(rv)) {
- ++(*outNumTestsFailed);
- }
-
- // insert some more text
- rv = mTextEditor->InsertText(NS_LITERAL_STRING("Moreover, I am cognizant of the interrelatedness of all communities and states. I cannot sit idly by in Atlanta and not be concerned about what happens in Birmingham. Injustice anywhere is a threat to justice everywhere"));
- TEST_RESULT(rv);
- (*outNumTests)++;
- if (NS_FAILED(rv)) {
- ++(*outNumTestsFailed);
- }
-
- rv = TestInsertBreak();
- TEST_RESULT(rv);
- (*outNumTests)++;
- if (NS_FAILED(rv)) {
- ++(*outNumTestsFailed);
- }
-
- rv = TestTextProperties();
- TEST_RESULT(rv);
- (*outNumTests)++;
- if (NS_FAILED(rv)) {
- ++(*outNumTestsFailed);
- }
-
- // get us back to the original document
- rv = mEditor->Undo(12);
- TEST_RESULT(rv);
-
- return rv;
-}
-
-nsresult TextEditorTest::InitDoc()
-{
- nsresult rv = mEditor->SelectAll();
- TEST_RESULT(rv);
- rv = mEditor->DeleteSelection(nsIEditor::eNext, nsIEditor::eStrip);
- TEST_RESULT(rv);
- return rv;
-}
-
-nsresult TextEditorTest::TestInsertBreak()
-{
- nsCOMPtr<nsISelection>selection;
- nsresult rv = mEditor->GetSelection(getter_AddRefs(selection));
- TEST_RESULT(rv);
- TEST_POINTER(selection.get());
- nsCOMPtr<nsIDOMNode>anchor;
- rv = selection->GetAnchorNode(getter_AddRefs(anchor));
- TEST_RESULT(rv);
- TEST_POINTER(anchor.get());
- selection->Collapse(anchor, 0);
- // insert one break
- printf("inserting a break\n");
- rv = mTextEditor->InsertLineBreak();
- TEST_RESULT(rv);
- mEditor->DebugDumpContent();
-
- // insert a second break adjacent to the first
- printf("inserting a second break\n");
- rv = mTextEditor->InsertLineBreak();
- TEST_RESULT(rv);
- mEditor->DebugDumpContent();
-
- return rv;
-}
-
-nsresult TextEditorTest::TestTextProperties()
-{
- nsCOMPtr<nsIDOMDocument>doc;
- nsresult rv = mEditor->GetDocument(getter_AddRefs(doc));
- TEST_RESULT(rv);
- TEST_POINTER(doc.get());
- nsCOMPtr<nsIDOMNodeList>nodeList;
- // XXX This is broken, text nodes are not elements.
- nsAutoString textTag(NS_LITERAL_STRING("#text"));
- rv = doc->GetElementsByTagName(textTag, getter_AddRefs(nodeList));
- TEST_RESULT(rv);
- TEST_POINTER(nodeList.get());
- uint32_t count;
- nodeList->GetLength(&count);
- NS_ASSERTION(0!=count, "there are no text nodes in the document!");
- nsCOMPtr<nsIDOMNode>textNode;
- rv = nodeList->Item(count - 1, getter_AddRefs(textNode));
- TEST_RESULT(rv);
- TEST_POINTER(textNode.get());
-
- // set the whole text node to bold
- printf("set the whole first text node to bold\n");
- nsCOMPtr<nsISelection>selection;
- rv = mEditor->GetSelection(getter_AddRefs(selection));
- TEST_RESULT(rv);
- TEST_POINTER(selection.get());
- nsCOMPtr<nsIDOMCharacterData>textData;
- textData = do_QueryInterface(textNode);
- uint32_t length;
- textData->GetLength(&length);
- selection->Collapse(textNode, 0);
- selection->Extend(textNode, length);
-
- nsCOMPtr<nsIHTMLEditor> htmlEditor (do_QueryInterface(mTextEditor));
- NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
-
- bool any = false;
- bool all = false;
- bool first=false;
-
- const nsAFlatString& empty = EmptyString();
-
- rv = htmlEditor->GetInlineProperty(nsGkAtoms::b, empty, empty, &first,
- &any, &all);
- TEST_RESULT(rv);
- NS_ASSERTION(false==first, "first should be false");
- NS_ASSERTION(false==any, "any should be false");
- NS_ASSERTION(false==all, "all should be false");
- rv = htmlEditor->SetInlineProperty(nsGkAtoms::b, empty, empty);
- TEST_RESULT(rv);
- rv = htmlEditor->GetInlineProperty(nsGkAtoms::b, empty, empty, &first,
- &any, &all);
- TEST_RESULT(rv);
- NS_ASSERTION(true==first, "first should be true");
- NS_ASSERTION(true==any, "any should be true");
- NS_ASSERTION(true==all, "all should be true");
- mEditor->DebugDumpContent();
-
- // remove the bold we just set
- printf("set the whole first text node to not bold\n");
- rv = htmlEditor->RemoveInlineProperty(nsGkAtoms::b, empty);
- TEST_RESULT(rv);
- rv = htmlEditor->GetInlineProperty(nsGkAtoms::b, empty, empty, &first,
- &any, &all);
- TEST_RESULT(rv);
- NS_ASSERTION(false==first, "first should be false");
- NS_ASSERTION(false==any, "any should be false");
- NS_ASSERTION(false==all, "all should be false");
- mEditor->DebugDumpContent();
-
- // set all but the first and last character to bold
- printf("set the first text node (1, length-1) to bold and italic, and (2, length-1) to underline.\n");
- selection->Collapse(textNode, 1);
- selection->Extend(textNode, length-1);
- rv = htmlEditor->SetInlineProperty(nsGkAtoms::b, empty, empty);
- TEST_RESULT(rv);
- rv = htmlEditor->GetInlineProperty(nsGkAtoms::b, empty, empty, &first,
- &any, &all);
- TEST_RESULT(rv);
- NS_ASSERTION(true==first, "first should be true");
- NS_ASSERTION(true==any, "any should be true");
- NS_ASSERTION(true==all, "all should be true");
- mEditor->DebugDumpContent();
- // make all that same text italic
- rv = htmlEditor->SetInlineProperty(nsGkAtoms::i, empty, empty);
- TEST_RESULT(rv);
- rv = htmlEditor->GetInlineProperty(nsGkAtoms::i, empty, empty, &first,
- &any, &all);
- TEST_RESULT(rv);
- NS_ASSERTION(true==first, "first should be true");
- NS_ASSERTION(true==any, "any should be true");
- NS_ASSERTION(true==all, "all should be true");
- rv = htmlEditor->GetInlineProperty(nsGkAtoms::b, empty, empty, &first,
- &any, &all);
- TEST_RESULT(rv);
- NS_ASSERTION(true==first, "first should be true");
- NS_ASSERTION(true==any, "any should be true");
- NS_ASSERTION(true==all, "all should be true");
- mEditor->DebugDumpContent();
-
- // make all the text underlined, except for the first 2 and last 2 characters
- rv = doc->GetElementsByTagName(textTag, getter_AddRefs(nodeList));
- TEST_RESULT(rv);
- TEST_POINTER(nodeList.get());
- nodeList->GetLength(&count);
- NS_ASSERTION(0!=count, "there are no text nodes in the document!");
- rv = nodeList->Item(count-2, getter_AddRefs(textNode));
- TEST_RESULT(rv);
- TEST_POINTER(textNode.get());
- textData = do_QueryInterface(textNode);
- textData->GetLength(&length);
- NS_ASSERTION(length==915, "wrong text node");
- selection->Collapse(textNode, 1);
- selection->Extend(textNode, length-2);
- rv = htmlEditor->SetInlineProperty(nsGkAtoms::u, empty, empty);
- TEST_RESULT(rv);
- rv = htmlEditor->GetInlineProperty(nsGkAtoms::u, empty, empty, &first,
- &any, &all);
- TEST_RESULT(rv);
- NS_ASSERTION(true==first, "first should be true");
- NS_ASSERTION(true==any, "any should be true");
- NS_ASSERTION(true==all, "all should be true");
- mEditor->DebugDumpContent();
-
- return rv;
-}
-
-#endif
diff --git a/editor/libeditor/TextEditorTest.h b/editor/libeditor/TextEditorTest.h
deleted file mode 100644
index 0483da463..000000000
--- a/editor/libeditor/TextEditorTest.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef __TextEditorTest_h__
-#define __TextEditorTest_h__
-
-#include "nscore.h"
-
-class nsIEditor;
-class nsIPlaintextEditor;
-#ifdef DEBUG
-
-#include "nsCOMPtr.h"
-
-class TextEditorTest
-{
-public:
-
- void Run(nsIEditor *aEditor, int32_t *outNumTests, int32_t *outNumTestsFailed);
- TextEditorTest();
- ~TextEditorTest();
-
-protected:
-
- /** create an empty document */
- nsresult InitDoc();
-
- nsresult RunUnitTest(int32_t *outNumTests, int32_t *outNumTestsFailed);
-
- nsresult TestInsertBreak();
-
- nsresult TestTextProperties();
-
- nsCOMPtr<nsIPlaintextEditor> mTextEditor;
- nsCOMPtr<nsIEditor> mEditor;
-};
-
-#endif /* DEBUG */
-
-#endif
diff --git a/editor/libeditor/TypeInState.cpp b/editor/libeditor/TypeInState.cpp
deleted file mode 100644
index 840139fee..000000000
--- a/editor/libeditor/TypeInState.cpp
+++ /dev/null
@@ -1,397 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "TypeInState.h"
-
-#include <stddef.h>
-
-#include "nsError.h"
-#include "mozilla/EditorBase.h"
-#include "mozilla/mozalloc.h"
-#include "mozilla/dom/Selection.h"
-#include "nsAString.h"
-#include "nsDebug.h"
-#include "nsGkAtoms.h"
-#include "nsIDOMNode.h"
-#include "nsISupportsBase.h"
-#include "nsISupportsImpl.h"
-#include "nsReadableUtils.h"
-#include "nsStringFwd.h"
-
-class nsIAtom;
-class nsIDOMDocument;
-
-namespace mozilla {
-
-using namespace dom;
-
-/********************************************************************
- * mozilla::TypeInState
- *******************************************************************/
-
-NS_IMPL_CYCLE_COLLECTION(TypeInState, mLastSelectionContainer)
-NS_IMPL_CYCLE_COLLECTING_ADDREF(TypeInState)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(TypeInState)
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TypeInState)
- NS_INTERFACE_MAP_ENTRY(nsISelectionListener)
- NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-TypeInState::TypeInState()
- : mRelativeFontSize(0)
- , mLastSelectionOffset(0)
-{
- Reset();
-}
-
-TypeInState::~TypeInState()
-{
- // Call Reset() to release any data that may be in
- // mClearedArray and mSetArray.
-
- Reset();
-}
-
-nsresult
-TypeInState::UpdateSelState(Selection* aSelection)
-{
- NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
-
- if (!aSelection->Collapsed()) {
- return NS_OK;
- }
-
- return EditorBase::GetStartNodeAndOffset(
- aSelection, getter_AddRefs(mLastSelectionContainer),
- &mLastSelectionOffset);
-}
-
-
-NS_IMETHODIMP
-TypeInState::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
- nsISelection* aSelection,
- int16_t aReason)
-{
- // XXX: Selection currently generates bogus selection changed notifications
- // XXX: (bug 140303). It can notify us when the selection hasn't actually
- // XXX: changed, and it notifies us more than once for the same change.
- // XXX:
- // XXX: The following code attempts to work around the bogus notifications,
- // XXX: and should probably be removed once bug 140303 is fixed.
- // XXX:
- // XXX: This code temporarily fixes the problem where clicking the mouse in
- // XXX: the same location clears the type-in-state.
- RefPtr<Selection> selection =
- aSelection ? aSelection->AsSelection() : nullptr;
-
- if (aSelection) {
- int32_t rangeCount = selection->RangeCount();
-
- if (selection->Collapsed() && rangeCount) {
- nsCOMPtr<nsIDOMNode> selNode;
- int32_t selOffset = 0;
-
- nsresult rv =
- EditorBase::GetStartNodeAndOffset(selection, getter_AddRefs(selNode),
- &selOffset);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (selNode &&
- selNode == mLastSelectionContainer &&
- selOffset == mLastSelectionOffset) {
- // We got a bogus selection changed notification!
- return NS_OK;
- }
-
- mLastSelectionContainer = selNode;
- mLastSelectionOffset = selOffset;
- } else {
- mLastSelectionContainer = nullptr;
- mLastSelectionOffset = 0;
- }
- }
-
- Reset();
- return NS_OK;
-}
-
-void
-TypeInState::Reset()
-{
- for (size_t i = 0, n = mClearedArray.Length(); i < n; i++) {
- delete mClearedArray[i];
- }
- mClearedArray.Clear();
- for (size_t i = 0, n = mSetArray.Length(); i < n; i++) {
- delete mSetArray[i];
- }
- mSetArray.Clear();
-}
-
-
-void
-TypeInState::SetProp(nsIAtom* aProp,
- const nsAString& aAttr,
- const nsAString& aValue)
-{
- // special case for big/small, these nest
- if (nsGkAtoms::big == aProp) {
- mRelativeFontSize++;
- return;
- }
- if (nsGkAtoms::small == aProp) {
- mRelativeFontSize--;
- return;
- }
-
- int32_t index;
- if (IsPropSet(aProp, aAttr, nullptr, index)) {
- // if it's already set, update the value
- mSetArray[index]->value = aValue;
- return;
- }
-
- // Make a new propitem and add it to the list of set properties.
- mSetArray.AppendElement(new PropItem(aProp, aAttr, aValue));
-
- // remove it from the list of cleared properties, if we have a match
- RemovePropFromClearedList(aProp, aAttr);
-}
-
-
-void
-TypeInState::ClearAllProps()
-{
- // null prop means "all" props
- ClearProp(nullptr, EmptyString());
-}
-
-void
-TypeInState::ClearProp(nsIAtom* aProp,
- const nsAString& aAttr)
-{
- // if it's already cleared we are done
- if (IsPropCleared(aProp, aAttr)) {
- return;
- }
-
- // make a new propitem
- PropItem* item = new PropItem(aProp, aAttr, EmptyString());
-
- // remove it from the list of set properties, if we have a match
- RemovePropFromSetList(aProp, aAttr);
-
- // add it to the list of cleared properties
- mClearedArray.AppendElement(item);
-}
-
-
-/**
- * TakeClearProperty() hands back next property item on the clear list.
- * Caller assumes ownership of PropItem and must delete it.
- */
-UniquePtr<PropItem>
-TypeInState::TakeClearProperty()
-{
- size_t count = mClearedArray.Length();
- if (!count) {
- return nullptr;
- }
-
- --count; // indices are zero based
- PropItem* propItem = mClearedArray[count];
- mClearedArray.RemoveElementAt(count);
- return UniquePtr<PropItem>(propItem);
-}
-
-/**
- * TakeSetProperty() hands back next poroperty item on the set list.
- * Caller assumes ownership of PropItem and must delete it.
- */
-UniquePtr<PropItem>
-TypeInState::TakeSetProperty()
-{
- size_t count = mSetArray.Length();
- if (!count) {
- return nullptr;
- }
- count--; // indices are zero based
- PropItem* propItem = mSetArray[count];
- mSetArray.RemoveElementAt(count);
- return UniquePtr<PropItem>(propItem);
-}
-
-/**
- * TakeRelativeFontSize() hands back relative font value, which is then
- * cleared out.
- */
-int32_t
-TypeInState::TakeRelativeFontSize()
-{
- int32_t relSize = mRelativeFontSize;
- mRelativeFontSize = 0;
- return relSize;
-}
-
-void
-TypeInState::GetTypingState(bool& isSet,
- bool& theSetting,
- nsIAtom* aProp)
-{
- GetTypingState(isSet, theSetting, aProp, EmptyString(), nullptr);
-}
-
-void
-TypeInState::GetTypingState(bool& isSet,
- bool& theSetting,
- nsIAtom* aProp,
- const nsString& aAttr,
- nsString* aValue)
-{
- if (IsPropSet(aProp, aAttr, aValue)) {
- isSet = true;
- theSetting = true;
- } else if (IsPropCleared(aProp, aAttr)) {
- isSet = true;
- theSetting = false;
- } else {
- isSet = false;
- }
-}
-
-void
-TypeInState::RemovePropFromSetList(nsIAtom* aProp,
- const nsAString& aAttr)
-{
- int32_t index;
- if (!aProp) {
- // clear _all_ props
- for (size_t i = 0, n = mSetArray.Length(); i < n; i++) {
- delete mSetArray[i];
- }
- mSetArray.Clear();
- mRelativeFontSize=0;
- } else if (FindPropInList(aProp, aAttr, nullptr, mSetArray, index)) {
- delete mSetArray[index];
- mSetArray.RemoveElementAt(index);
- }
-}
-
-void
-TypeInState::RemovePropFromClearedList(nsIAtom* aProp,
- const nsAString& aAttr)
-{
- int32_t index;
- if (FindPropInList(aProp, aAttr, nullptr, mClearedArray, index)) {
- delete mClearedArray[index];
- mClearedArray.RemoveElementAt(index);
- }
-}
-
-bool
-TypeInState::IsPropSet(nsIAtom* aProp,
- const nsAString& aAttr,
- nsAString* outValue)
-{
- int32_t i;
- return IsPropSet(aProp, aAttr, outValue, i);
-}
-
-bool
-TypeInState::IsPropSet(nsIAtom* aProp,
- const nsAString& aAttr,
- nsAString* outValue,
- int32_t& outIndex)
-{
- // linear search. list should be short.
- size_t count = mSetArray.Length();
- for (size_t i = 0; i < count; i++) {
- PropItem *item = mSetArray[i];
- if (item->tag == aProp && item->attr == aAttr) {
- if (outValue) {
- *outValue = item->value;
- }
- outIndex = i;
- return true;
- }
- }
- return false;
-}
-
-
-bool
-TypeInState::IsPropCleared(nsIAtom* aProp,
- const nsAString& aAttr)
-{
- int32_t i;
- return IsPropCleared(aProp, aAttr, i);
-}
-
-
-bool
-TypeInState::IsPropCleared(nsIAtom* aProp,
- const nsAString& aAttr,
- int32_t& outIndex)
-{
- if (FindPropInList(aProp, aAttr, nullptr, mClearedArray, outIndex)) {
- return true;
- }
- if (FindPropInList(0, EmptyString(), nullptr, mClearedArray, outIndex)) {
- // special case for all props cleared
- outIndex = -1;
- return true;
- }
- return false;
-}
-
-bool
-TypeInState::FindPropInList(nsIAtom* aProp,
- const nsAString& aAttr,
- nsAString* outValue,
- nsTArray<PropItem*>& aList,
- int32_t& outIndex)
-{
- // linear search. list should be short.
- size_t count = aList.Length();
- for (size_t i = 0; i < count; i++) {
- PropItem *item = aList[i];
- if (item->tag == aProp && item->attr == aAttr) {
- if (outValue) {
- *outValue = item->value;
- }
- outIndex = i;
- return true;
- }
- }
- return false;
-}
-
-/********************************************************************
- * mozilla::PropItem: helper struct for mozilla::TypeInState
- *******************************************************************/
-
-PropItem::PropItem()
- : tag(nullptr)
-{
- MOZ_COUNT_CTOR(PropItem);
-}
-
-PropItem::PropItem(nsIAtom* aTag,
- const nsAString& aAttr,
- const nsAString &aValue)
- : tag(aTag)
- , attr(aAttr)
- , value(aValue)
-{
- MOZ_COUNT_CTOR(PropItem);
-}
-
-PropItem::~PropItem()
-{
- MOZ_COUNT_DTOR(PropItem);
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/TypeInState.h b/editor/libeditor/TypeInState.h
deleted file mode 100644
index e1b949508..000000000
--- a/editor/libeditor/TypeInState.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef TypeInState_h
-#define TypeInState_h
-
-#include "mozilla/UniquePtr.h"
-#include "nsCOMPtr.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsISelectionListener.h"
-#include "nsISupportsImpl.h"
-#include "nsString.h"
-#include "nsTArray.h"
-#include "nscore.h"
-
-// Workaround for windows headers
-#ifdef SetProp
-#undef SetProp
-#endif
-
-class nsIAtom;
-class nsIDOMNode;
-
-namespace mozilla {
-
-class HTMLEditRules;
-namespace dom {
-class Selection;
-} // namespace dom
-
-struct PropItem
-{
- nsIAtom* tag;
- nsString attr;
- nsString value;
-
- PropItem();
- PropItem(nsIAtom* aTag, const nsAString& aAttr, const nsAString& aValue);
- ~PropItem();
-};
-
-class TypeInState final : public nsISelectionListener
-{
-public:
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS(TypeInState)
-
- TypeInState();
- void Reset();
-
- nsresult UpdateSelState(dom::Selection* aSelection);
-
- // nsISelectionListener
- NS_DECL_NSISELECTIONLISTENER
-
- void SetProp(nsIAtom* aProp, const nsAString& aAttr, const nsAString& aValue);
-
- void ClearAllProps();
- void ClearProp(nsIAtom* aProp, const nsAString& aAttr);
-
- /**
- * TakeClearProperty() hands back next property item on the clear list.
- * Caller assumes ownership of PropItem and must delete it.
- */
- UniquePtr<PropItem> TakeClearProperty();
-
- /**
- * TakeSetProperty() hands back next property item on the set list.
- * Caller assumes ownership of PropItem and must delete it.
- */
- UniquePtr<PropItem> TakeSetProperty();
-
- /**
- * TakeRelativeFontSize() hands back relative font value, which is then
- * cleared out.
- */
- int32_t TakeRelativeFontSize();
-
- void GetTypingState(bool& isSet, bool& theSetting, nsIAtom* aProp);
- void GetTypingState(bool& isSet, bool& theSetting, nsIAtom* aProp,
- const nsString& aAttr, nsString* outValue);
-
- static bool FindPropInList(nsIAtom* aProp, const nsAString& aAttr,
- nsAString* outValue, nsTArray<PropItem*>& aList,
- int32_t& outIndex);
-
-protected:
- virtual ~TypeInState();
-
- void RemovePropFromSetList(nsIAtom* aProp, const nsAString& aAttr);
- void RemovePropFromClearedList(nsIAtom* aProp, const nsAString& aAttr);
- bool IsPropSet(nsIAtom* aProp, const nsAString& aAttr, nsAString* outValue);
- bool IsPropSet(nsIAtom* aProp, const nsAString& aAttr, nsAString* outValue,
- int32_t& outIndex);
- bool IsPropCleared(nsIAtom* aProp, const nsAString& aAttr);
- bool IsPropCleared(nsIAtom* aProp, const nsAString& aAttr, int32_t& outIndex);
-
- nsTArray<PropItem*> mSetArray;
- nsTArray<PropItem*> mClearedArray;
- int32_t mRelativeFontSize;
- nsCOMPtr<nsIDOMNode> mLastSelectionContainer;
- int32_t mLastSelectionOffset;
-
- friend class HTMLEditRules;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef TypeInState_h
-
diff --git a/editor/libeditor/WSRunObject.cpp b/editor/libeditor/WSRunObject.cpp
deleted file mode 100644
index 0748f09e5..000000000
--- a/editor/libeditor/WSRunObject.cpp
+++ /dev/null
@@ -1,1926 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "WSRunObject.h"
-
-#include "TextEditUtils.h"
-
-#include "mozilla/Assertions.h"
-#include "mozilla/Casting.h"
-#include "mozilla/EditorUtils.h"
-#include "mozilla/HTMLEditor.h"
-#include "mozilla/mozalloc.h"
-#include "mozilla/OwningNonNull.h"
-#include "mozilla/SelectionState.h"
-
-#include "nsAString.h"
-#include "nsCRT.h"
-#include "nsContentUtils.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsIContent.h"
-#include "nsIDOMDocument.h"
-#include "nsIDOMNode.h"
-#include "nsISupportsImpl.h"
-#include "nsRange.h"
-#include "nsString.h"
-#include "nsTextFragment.h"
-
-namespace mozilla {
-
-using namespace dom;
-
-const char16_t nbsp = 160;
-
-WSRunObject::WSRunObject(HTMLEditor* aHTMLEditor,
- nsINode* aNode,
- int32_t aOffset)
- : mNode(aNode)
- , mOffset(aOffset)
- , mPRE(false)
- , mStartOffset(0)
- , mEndOffset(0)
- , mFirstNBSPOffset(0)
- , mLastNBSPOffset(0)
- , mStartRun(nullptr)
- , mEndRun(nullptr)
- , mHTMLEditor(aHTMLEditor)
-{
- GetWSNodes();
- GetRuns();
-}
-
-WSRunObject::WSRunObject(HTMLEditor* aHTMLEditor,
- nsIDOMNode* aNode,
- int32_t aOffset)
- : mNode(do_QueryInterface(aNode))
- , mOffset(aOffset)
- , mPRE(false)
- , mStartOffset(0)
- , mEndOffset(0)
- , mFirstNBSPOffset(0)
- , mLastNBSPOffset(0)
- , mStartRun(nullptr)
- , mEndRun(nullptr)
- , mHTMLEditor(aHTMLEditor)
-{
- GetWSNodes();
- GetRuns();
-}
-
-WSRunObject::~WSRunObject()
-{
- ClearRuns();
-}
-
-nsresult
-WSRunObject::ScrubBlockBoundary(HTMLEditor* aHTMLEditor,
- BlockBoundary aBoundary,
- nsINode* aBlock,
- int32_t aOffset)
-{
- NS_ENSURE_TRUE(aHTMLEditor && aBlock, NS_ERROR_NULL_POINTER);
-
- int32_t offset;
- if (aBoundary == kBlockStart) {
- offset = 0;
- } else if (aBoundary == kBlockEnd) {
- offset = aBlock->Length();
- } else {
- // Else we are scrubbing an outer boundary - just before or after a block
- // element.
- NS_ENSURE_STATE(aOffset >= 0);
- offset = aOffset;
- }
-
- WSRunObject theWSObj(aHTMLEditor, aBlock, offset);
- return theWSObj.Scrub();
-}
-
-nsresult
-WSRunObject::PrepareToJoinBlocks(HTMLEditor* aHTMLEditor,
- Element* aLeftBlock,
- Element* aRightBlock)
-{
- NS_ENSURE_TRUE(aLeftBlock && aRightBlock && aHTMLEditor,
- NS_ERROR_NULL_POINTER);
-
- WSRunObject leftWSObj(aHTMLEditor, aLeftBlock, aLeftBlock->Length());
- WSRunObject rightWSObj(aHTMLEditor, aRightBlock, 0);
-
- return leftWSObj.PrepareToDeleteRangePriv(&rightWSObj);
-}
-
-nsresult
-WSRunObject::PrepareToDeleteRange(HTMLEditor* aHTMLEditor,
- nsCOMPtr<nsINode>* aStartNode,
- int32_t* aStartOffset,
- nsCOMPtr<nsINode>* aEndNode,
- int32_t* aEndOffset)
-{
- NS_ENSURE_TRUE(aHTMLEditor && aStartNode && *aStartNode && aStartOffset &&
- aEndNode && *aEndNode && aEndOffset, NS_ERROR_NULL_POINTER);
-
- AutoTrackDOMPoint trackerStart(aHTMLEditor->mRangeUpdater,
- aStartNode, aStartOffset);
- AutoTrackDOMPoint trackerEnd(aHTMLEditor->mRangeUpdater,
- aEndNode, aEndOffset);
-
- WSRunObject leftWSObj(aHTMLEditor, *aStartNode, *aStartOffset);
- WSRunObject rightWSObj(aHTMLEditor, *aEndNode, *aEndOffset);
-
- return leftWSObj.PrepareToDeleteRangePriv(&rightWSObj);
-}
-
-nsresult
-WSRunObject::PrepareToDeleteNode(HTMLEditor* aHTMLEditor,
- nsIContent* aContent)
-{
- NS_ENSURE_TRUE(aContent && aHTMLEditor, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsINode> parent = aContent->GetParentNode();
- NS_ENSURE_STATE(parent);
- int32_t offset = parent->IndexOf(aContent);
-
- WSRunObject leftWSObj(aHTMLEditor, parent, offset);
- WSRunObject rightWSObj(aHTMLEditor, parent, offset + 1);
-
- return leftWSObj.PrepareToDeleteRangePriv(&rightWSObj);
-}
-
-nsresult
-WSRunObject::PrepareToSplitAcrossBlocks(HTMLEditor* aHTMLEditor,
- nsCOMPtr<nsINode>* aSplitNode,
- int32_t* aSplitOffset)
-{
- NS_ENSURE_TRUE(aHTMLEditor && aSplitNode && *aSplitNode && aSplitOffset,
- NS_ERROR_NULL_POINTER);
-
- AutoTrackDOMPoint tracker(aHTMLEditor->mRangeUpdater,
- aSplitNode, aSplitOffset);
-
- WSRunObject wsObj(aHTMLEditor, *aSplitNode, *aSplitOffset);
-
- return wsObj.PrepareToSplitAcrossBlocksPriv();
-}
-
-already_AddRefed<Element>
-WSRunObject::InsertBreak(nsCOMPtr<nsINode>* aInOutParent,
- int32_t* aInOutOffset,
- nsIEditor::EDirection aSelect)
-{
- // MOOSE: for now, we always assume non-PRE formatting. Fix this later.
- // meanwhile, the pre case is handled in WillInsertText in
- // HTMLEditRules.cpp
- NS_ENSURE_TRUE(aInOutParent && aInOutOffset, nullptr);
-
- WSFragment *beforeRun, *afterRun;
- FindRun(*aInOutParent, *aInOutOffset, &beforeRun, false);
- FindRun(*aInOutParent, *aInOutOffset, &afterRun, true);
-
- {
- // Some scoping for AutoTrackDOMPoint. This will track our insertion
- // point while we tweak any surrounding whitespace
- AutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater, aInOutParent,
- aInOutOffset);
-
- // Handle any changes needed to ws run after inserted br
- if (!afterRun || (afterRun->mType & WSType::trailingWS)) {
- // Don't need to do anything. Just insert break. ws won't change.
- } else if (afterRun->mType & WSType::leadingWS) {
- // Delete the leading ws that is after insertion point. We don't
- // have to (it would still not be significant after br), but it's
- // just more aesthetically pleasing to.
- nsresult rv = DeleteChars(*aInOutParent, *aInOutOffset,
- afterRun->mEndNode, afterRun->mEndOffset,
- eOutsideUserSelectAll);
- NS_ENSURE_SUCCESS(rv, nullptr);
- } else if (afterRun->mType == WSType::normalWS) {
- // Need to determine if break at front of non-nbsp run. If so, convert
- // run to nbsp.
- WSPoint thePoint = GetCharAfter(*aInOutParent, *aInOutOffset);
- if (thePoint.mTextNode && nsCRT::IsAsciiSpace(thePoint.mChar)) {
- WSPoint prevPoint = GetCharBefore(thePoint);
- if (prevPoint.mTextNode && !nsCRT::IsAsciiSpace(prevPoint.mChar)) {
- // We are at start of non-nbsps. Convert to a single nbsp.
- nsresult rv = ConvertToNBSP(thePoint);
- NS_ENSURE_SUCCESS(rv, nullptr);
- }
- }
- }
-
- // Handle any changes needed to ws run before inserted br
- if (!beforeRun || (beforeRun->mType & WSType::leadingWS)) {
- // Don't need to do anything. Just insert break. ws won't change.
- } else if (beforeRun->mType & WSType::trailingWS) {
- // Need to delete the trailing ws that is before insertion point, because it
- // would become significant after break inserted.
- nsresult rv = DeleteChars(beforeRun->mStartNode, beforeRun->mStartOffset,
- *aInOutParent, *aInOutOffset,
- eOutsideUserSelectAll);
- NS_ENSURE_SUCCESS(rv, nullptr);
- } else if (beforeRun->mType == WSType::normalWS) {
- // Try to change an nbsp to a space, just to prevent nbsp proliferation
- nsresult rv = CheckTrailingNBSP(beforeRun, *aInOutParent, *aInOutOffset);
- NS_ENSURE_SUCCESS(rv, nullptr);
- }
- }
-
- // ready, aim, fire!
- return mHTMLEditor->CreateBRImpl(aInOutParent, aInOutOffset, aSelect);
-}
-
-nsresult
-WSRunObject::InsertText(const nsAString& aStringToInsert,
- nsCOMPtr<nsINode>* aInOutParent,
- int32_t* aInOutOffset,
- nsIDocument* aDoc)
-{
- // MOOSE: for now, we always assume non-PRE formatting. Fix this later.
- // meanwhile, the pre case is handled in WillInsertText in
- // HTMLEditRules.cpp
-
- // MOOSE: for now, just getting the ws logic straight. This implementation
- // is very slow. Will need to replace edit rules impl with a more efficient
- // text sink here that does the minimal amount of searching/replacing/copying
-
- NS_ENSURE_TRUE(aInOutParent && aInOutOffset && aDoc, NS_ERROR_NULL_POINTER);
-
- if (aStringToInsert.IsEmpty()) {
- return NS_OK;
- }
-
- nsAutoString theString(aStringToInsert);
-
- WSFragment *beforeRun, *afterRun;
- FindRun(*aInOutParent, *aInOutOffset, &beforeRun, false);
- FindRun(*aInOutParent, *aInOutOffset, &afterRun, true);
-
- {
- // Some scoping for AutoTrackDOMPoint. This will track our insertion
- // point while we tweak any surrounding whitespace
- AutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater, aInOutParent,
- aInOutOffset);
-
- // Handle any changes needed to ws run after inserted text
- if (!afterRun || afterRun->mType & WSType::trailingWS) {
- // Don't need to do anything. Just insert text. ws won't change.
- } else if (afterRun->mType & WSType::leadingWS) {
- // Delete the leading ws that is after insertion point, because it
- // would become significant after text inserted.
- nsresult rv =
- DeleteChars(*aInOutParent, *aInOutOffset, afterRun->mEndNode,
- afterRun->mEndOffset, eOutsideUserSelectAll);
- NS_ENSURE_SUCCESS(rv, rv);
- } else if (afterRun->mType == WSType::normalWS) {
- // Try to change an nbsp to a space, if possible, just to prevent nbsp
- // proliferation
- nsresult rv = CheckLeadingNBSP(afterRun, *aInOutParent, *aInOutOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // Handle any changes needed to ws run before inserted text
- if (!beforeRun || beforeRun->mType & WSType::leadingWS) {
- // Don't need to do anything. Just insert text. ws won't change.
- } else if (beforeRun->mType & WSType::trailingWS) {
- // Need to delete the trailing ws that is before insertion point, because
- // it would become significant after text inserted.
- nsresult rv =
- DeleteChars(beforeRun->mStartNode, beforeRun->mStartOffset,
- *aInOutParent, *aInOutOffset, eOutsideUserSelectAll);
- NS_ENSURE_SUCCESS(rv, rv);
- } else if (beforeRun->mType == WSType::normalWS) {
- // Try to change an nbsp to a space, if possible, just to prevent nbsp
- // proliferation
- nsresult rv = CheckTrailingNBSP(beforeRun, *aInOutParent, *aInOutOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- // Next up, tweak head and tail of string as needed. First the head: there
- // are a variety of circumstances that would require us to convert a leading
- // ws char into an nbsp:
-
- if (nsCRT::IsAsciiSpace(theString[0])) {
- // We have a leading space
- if (beforeRun) {
- if (beforeRun->mType & WSType::leadingWS) {
- theString.SetCharAt(nbsp, 0);
- } else if (beforeRun->mType & WSType::normalWS) {
- WSPoint wspoint = GetCharBefore(*aInOutParent, *aInOutOffset);
- if (wspoint.mTextNode && nsCRT::IsAsciiSpace(wspoint.mChar)) {
- theString.SetCharAt(nbsp, 0);
- }
- }
- } else if (mStartReason & WSType::block || mStartReason == WSType::br) {
- theString.SetCharAt(nbsp, 0);
- }
- }
-
- // Then the tail
- uint32_t lastCharIndex = theString.Length() - 1;
-
- if (nsCRT::IsAsciiSpace(theString[lastCharIndex])) {
- // We have a leading space
- if (afterRun) {
- if (afterRun->mType & WSType::trailingWS) {
- theString.SetCharAt(nbsp, lastCharIndex);
- } else if (afterRun->mType & WSType::normalWS) {
- WSPoint wspoint = GetCharAfter(*aInOutParent, *aInOutOffset);
- if (wspoint.mTextNode && nsCRT::IsAsciiSpace(wspoint.mChar)) {
- theString.SetCharAt(nbsp, lastCharIndex);
- }
- }
- } else if (mEndReason & WSType::block) {
- theString.SetCharAt(nbsp, lastCharIndex);
- }
- }
-
- // Next, scan string for adjacent ws and convert to nbsp/space combos
- // MOOSE: don't need to convert tabs here since that is done by
- // WillInsertText() before we are called. Eventually, all that logic will be
- // pushed down into here and made more efficient.
- bool prevWS = false;
- for (uint32_t i = 0; i <= lastCharIndex; i++) {
- if (nsCRT::IsAsciiSpace(theString[i])) {
- if (prevWS) {
- // i - 1 can't be negative because prevWS starts out false
- theString.SetCharAt(nbsp, i - 1);
- } else {
- prevWS = true;
- }
- } else {
- prevWS = false;
- }
- }
-
- // Ready, aim, fire!
- mHTMLEditor->InsertTextImpl(theString, aInOutParent, aInOutOffset, aDoc);
- return NS_OK;
-}
-
-nsresult
-WSRunObject::DeleteWSBackward()
-{
- WSPoint point = GetCharBefore(mNode, mOffset);
- NS_ENSURE_TRUE(point.mTextNode, NS_OK); // nothing to delete
-
- // Easy case, preformatted ws.
- if (mPRE && (nsCRT::IsAsciiSpace(point.mChar) || point.mChar == nbsp)) {
- return DeleteChars(point.mTextNode, point.mOffset,
- point.mTextNode, point.mOffset + 1);
- }
-
- // Caller's job to ensure that previous char is really ws. If it is normal
- // ws, we need to delete the whole run.
- if (nsCRT::IsAsciiSpace(point.mChar)) {
- RefPtr<Text> startNodeText, endNodeText;
- int32_t startOffset, endOffset;
- GetAsciiWSBounds(eBoth, point.mTextNode, point.mOffset + 1,
- getter_AddRefs(startNodeText), &startOffset,
- getter_AddRefs(endNodeText), &endOffset);
-
- // adjust surrounding ws
- nsCOMPtr<nsINode> startNode = startNodeText.get();
- nsCOMPtr<nsINode> endNode = endNodeText.get();
- nsresult rv =
- WSRunObject::PrepareToDeleteRange(mHTMLEditor,
- address_of(startNode), &startOffset,
- address_of(endNode), &endOffset);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // finally, delete that ws
- return DeleteChars(startNode, startOffset, endNode, endOffset);
- }
-
- if (point.mChar == nbsp) {
- nsCOMPtr<nsINode> node(point.mTextNode);
- // adjust surrounding ws
- int32_t startOffset = point.mOffset;
- int32_t endOffset = point.mOffset + 1;
- nsresult rv =
- WSRunObject::PrepareToDeleteRange(mHTMLEditor,
- address_of(node), &startOffset,
- address_of(node), &endOffset);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // finally, delete that ws
- return DeleteChars(node, startOffset, node, endOffset);
- }
-
- return NS_OK;
-}
-
-nsresult
-WSRunObject::DeleteWSForward()
-{
- WSPoint point = GetCharAfter(mNode, mOffset);
- NS_ENSURE_TRUE(point.mTextNode, NS_OK); // nothing to delete
-
- // Easy case, preformatted ws.
- if (mPRE && (nsCRT::IsAsciiSpace(point.mChar) || point.mChar == nbsp)) {
- return DeleteChars(point.mTextNode, point.mOffset,
- point.mTextNode, point.mOffset + 1);
- }
-
- // Caller's job to ensure that next char is really ws. If it is normal ws,
- // we need to delete the whole run.
- if (nsCRT::IsAsciiSpace(point.mChar)) {
- RefPtr<Text> startNodeText, endNodeText;
- int32_t startOffset, endOffset;
- GetAsciiWSBounds(eBoth, point.mTextNode, point.mOffset + 1,
- getter_AddRefs(startNodeText), &startOffset,
- getter_AddRefs(endNodeText), &endOffset);
-
- // Adjust surrounding ws
- nsCOMPtr<nsINode> startNode(startNodeText), endNode(endNodeText);
- nsresult rv =
- WSRunObject::PrepareToDeleteRange(mHTMLEditor,
- address_of(startNode), &startOffset,
- address_of(endNode), &endOffset);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Finally, delete that ws
- return DeleteChars(startNode, startOffset, endNode, endOffset);
- }
-
- if (point.mChar == nbsp) {
- nsCOMPtr<nsINode> node(point.mTextNode);
- // Adjust surrounding ws
- int32_t startOffset = point.mOffset;
- int32_t endOffset = point.mOffset+1;
- nsresult rv =
- WSRunObject::PrepareToDeleteRange(mHTMLEditor,
- address_of(node), &startOffset,
- address_of(node), &endOffset);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Finally, delete that ws
- return DeleteChars(node, startOffset, node, endOffset);
- }
-
- return NS_OK;
-}
-
-void
-WSRunObject::PriorVisibleNode(nsINode* aNode,
- int32_t aOffset,
- nsCOMPtr<nsINode>* outVisNode,
- int32_t* outVisOffset,
- WSType* outType)
-{
- // Find first visible thing before the point. Position
- // outVisNode/outVisOffset just _after_ that thing. If we don't find
- // anything return start of ws.
- MOZ_ASSERT(aNode && outVisNode && outVisOffset && outType);
-
- WSFragment* run;
- FindRun(aNode, aOffset, &run, false);
-
- // Is there a visible run there or earlier?
- for (; run; run = run->mLeft) {
- if (run->mType == WSType::normalWS) {
- WSPoint point = GetCharBefore(aNode, aOffset);
- // When it's a non-empty text node, return it.
- if (point.mTextNode && point.mTextNode->Length()) {
- *outVisNode = point.mTextNode;
- *outVisOffset = point.mOffset + 1;
- if (nsCRT::IsAsciiSpace(point.mChar) || point.mChar == nbsp) {
- *outType = WSType::normalWS;
- } else {
- *outType = WSType::text;
- }
- return;
- }
- // If no text node, keep looking. We should eventually fall out of loop
- }
- }
-
- // If we get here, then nothing in ws data to find. Return start reason.
- *outVisNode = mStartReasonNode;
- // This really isn't meaningful if mStartReasonNode != mStartNode
- *outVisOffset = mStartOffset;
- *outType = mStartReason;
-}
-
-
-void
-WSRunObject::NextVisibleNode(nsINode* aNode,
- int32_t aOffset,
- nsCOMPtr<nsINode>* outVisNode,
- int32_t* outVisOffset,
- WSType* outType)
-{
- // Find first visible thing after the point. Position
- // outVisNode/outVisOffset just _before_ that thing. If we don't find
- // anything return end of ws.
- MOZ_ASSERT(aNode && outVisNode && outVisOffset && outType);
-
- WSFragment* run;
- FindRun(aNode, aOffset, &run, true);
-
- // Is there a visible run there or later?
- for (; run; run = run->mRight) {
- if (run->mType == WSType::normalWS) {
- WSPoint point = GetCharAfter(aNode, aOffset);
- // When it's a non-empty text node, return it.
- if (point.mTextNode && point.mTextNode->Length()) {
- *outVisNode = point.mTextNode;
- *outVisOffset = point.mOffset;
- if (nsCRT::IsAsciiSpace(point.mChar) || point.mChar == nbsp) {
- *outType = WSType::normalWS;
- } else {
- *outType = WSType::text;
- }
- return;
- }
- // If no text node, keep looking. We should eventually fall out of loop
- }
- }
-
- // If we get here, then nothing in ws data to find. Return end reason
- *outVisNode = mEndReasonNode;
- // This really isn't meaningful if mEndReasonNode != mEndNode
- *outVisOffset = mEndOffset;
- *outType = mEndReason;
-}
-
-nsresult
-WSRunObject::AdjustWhitespace()
-{
- // this routine examines a run of ws and tries to get rid of some unneeded nbsp's,
- // replacing them with regualr ascii space if possible. Keeping things simple
- // for now and just trying to fix up the trailing ws in the run.
- if (!mLastNBSPNode) {
- // nothing to do!
- return NS_OK;
- }
- WSFragment *curRun = mStartRun;
- while (curRun) {
- // look for normal ws run
- if (curRun->mType == WSType::normalWS) {
- nsresult rv = CheckTrailingNBSPOfRun(curRun);
- if (NS_FAILED(rv)) {
- return rv;
- }
- }
- curRun = curRun->mRight;
- }
- return NS_OK;
-}
-
-
-//--------------------------------------------------------------------------------------------
-// protected methods
-//--------------------------------------------------------------------------------------------
-
-nsINode*
-WSRunObject::GetWSBoundingParent()
-{
- NS_ENSURE_TRUE(mNode, nullptr);
- OwningNonNull<nsINode> wsBoundingParent = *mNode;
- while (!IsBlockNode(wsBoundingParent)) {
- nsCOMPtr<nsINode> parent = wsBoundingParent->GetParentNode();
- if (!parent || !mHTMLEditor->IsEditable(parent)) {
- break;
- }
- wsBoundingParent = parent;
- }
- return wsBoundingParent;
-}
-
-nsresult
-WSRunObject::GetWSNodes()
-{
- // collect up an array of nodes that are contiguous with the insertion point
- // and which contain only whitespace. Stop if you reach non-ws text or a new
- // block boundary.
- EditorDOMPoint start(mNode, mOffset), end(mNode, mOffset);
- nsCOMPtr<nsINode> wsBoundingParent = GetWSBoundingParent();
-
- // first look backwards to find preceding ws nodes
- if (RefPtr<Text> textNode = mNode->GetAsText()) {
- const nsTextFragment* textFrag = textNode->GetText();
-
- mNodeArray.InsertElementAt(0, textNode);
- if (mOffset) {
- for (int32_t pos = mOffset - 1; pos >= 0; pos--) {
- // sanity bounds check the char position. bug 136165
- if (uint32_t(pos) >= textFrag->GetLength()) {
- NS_NOTREACHED("looking beyond end of text fragment");
- continue;
- }
- char16_t theChar = textFrag->CharAt(pos);
- if (!nsCRT::IsAsciiSpace(theChar)) {
- if (theChar != nbsp) {
- mStartNode = textNode;
- mStartOffset = pos + 1;
- mStartReason = WSType::text;
- mStartReasonNode = textNode;
- break;
- }
- // as we look backwards update our earliest found nbsp
- mFirstNBSPNode = textNode;
- mFirstNBSPOffset = pos;
- // also keep track of latest nbsp so far
- if (!mLastNBSPNode) {
- mLastNBSPNode = textNode;
- mLastNBSPOffset = pos;
- }
- }
- start.node = textNode;
- start.offset = pos;
- }
- }
- }
-
- while (!mStartNode) {
- // we haven't found the start of ws yet. Keep looking
- nsCOMPtr<nsIContent> priorNode = GetPreviousWSNode(start, wsBoundingParent);
- if (priorNode) {
- if (IsBlockNode(priorNode)) {
- mStartNode = start.node;
- mStartOffset = start.offset;
- mStartReason = WSType::otherBlock;
- mStartReasonNode = priorNode;
- } else if (RefPtr<Text> textNode = priorNode->GetAsText()) {
- mNodeArray.InsertElementAt(0, textNode);
- const nsTextFragment *textFrag;
- if (!textNode || !(textFrag = textNode->GetText())) {
- return NS_ERROR_NULL_POINTER;
- }
- uint32_t len = textNode->TextLength();
-
- if (len < 1) {
- // Zero length text node. Set start point to it
- // so we can get past it!
- start.SetPoint(priorNode, 0);
- } else {
- for (int32_t pos = len - 1; pos >= 0; pos--) {
- // sanity bounds check the char position. bug 136165
- if (uint32_t(pos) >= textFrag->GetLength()) {
- NS_NOTREACHED("looking beyond end of text fragment");
- continue;
- }
- char16_t theChar = textFrag->CharAt(pos);
- if (!nsCRT::IsAsciiSpace(theChar)) {
- if (theChar != nbsp) {
- mStartNode = textNode;
- mStartOffset = pos + 1;
- mStartReason = WSType::text;
- mStartReasonNode = textNode;
- break;
- }
- // as we look backwards update our earliest found nbsp
- mFirstNBSPNode = textNode;
- mFirstNBSPOffset = pos;
- // also keep track of latest nbsp so far
- if (!mLastNBSPNode) {
- mLastNBSPNode = textNode;
- mLastNBSPOffset = pos;
- }
- }
- start.SetPoint(textNode, pos);
- }
- }
- } else {
- // it's a break or a special node, like <img>, that is not a block and not
- // a break but still serves as a terminator to ws runs.
- mStartNode = start.node;
- mStartOffset = start.offset;
- if (TextEditUtils::IsBreak(priorNode)) {
- mStartReason = WSType::br;
- } else {
- mStartReason = WSType::special;
- }
- mStartReasonNode = priorNode;
- }
- } else {
- // no prior node means we exhausted wsBoundingParent
- mStartNode = start.node;
- mStartOffset = start.offset;
- mStartReason = WSType::thisBlock;
- mStartReasonNode = wsBoundingParent;
- }
- }
-
- // then look ahead to find following ws nodes
- if (RefPtr<Text> textNode = mNode->GetAsText()) {
- // don't need to put it on list. it already is from code above
- const nsTextFragment *textFrag = textNode->GetText();
-
- uint32_t len = textNode->TextLength();
- if (uint16_t(mOffset)<len) {
- for (uint32_t pos = mOffset; pos < len; pos++) {
- // sanity bounds check the char position. bug 136165
- if (pos >= textFrag->GetLength()) {
- NS_NOTREACHED("looking beyond end of text fragment");
- continue;
- }
- char16_t theChar = textFrag->CharAt(pos);
- if (!nsCRT::IsAsciiSpace(theChar)) {
- if (theChar != nbsp) {
- mEndNode = textNode;
- mEndOffset = pos;
- mEndReason = WSType::text;
- mEndReasonNode = textNode;
- break;
- }
- // as we look forwards update our latest found nbsp
- mLastNBSPNode = textNode;
- mLastNBSPOffset = pos;
- // also keep track of earliest nbsp so far
- if (!mFirstNBSPNode) {
- mFirstNBSPNode = textNode;
- mFirstNBSPOffset = pos;
- }
- }
- end.SetPoint(textNode, pos + 1);
- }
- }
- }
-
- while (!mEndNode) {
- // we haven't found the end of ws yet. Keep looking
- nsCOMPtr<nsIContent> nextNode = GetNextWSNode(end, wsBoundingParent);
- if (nextNode) {
- if (IsBlockNode(nextNode)) {
- // we encountered a new block. therefore no more ws.
- mEndNode = end.node;
- mEndOffset = end.offset;
- mEndReason = WSType::otherBlock;
- mEndReasonNode = nextNode;
- } else if (RefPtr<Text> textNode = nextNode->GetAsText()) {
- mNodeArray.AppendElement(textNode);
- const nsTextFragment *textFrag;
- if (!textNode || !(textFrag = textNode->GetText())) {
- return NS_ERROR_NULL_POINTER;
- }
- uint32_t len = textNode->TextLength();
-
- if (len < 1) {
- // Zero length text node. Set end point to it
- // so we can get past it!
- end.SetPoint(textNode, 0);
- } else {
- for (uint32_t pos = 0; pos < len; pos++) {
- // sanity bounds check the char position. bug 136165
- if (pos >= textFrag->GetLength()) {
- NS_NOTREACHED("looking beyond end of text fragment");
- continue;
- }
- char16_t theChar = textFrag->CharAt(pos);
- if (!nsCRT::IsAsciiSpace(theChar)) {
- if (theChar != nbsp) {
- mEndNode = textNode;
- mEndOffset = pos;
- mEndReason = WSType::text;
- mEndReasonNode = textNode;
- break;
- }
- // as we look forwards update our latest found nbsp
- mLastNBSPNode = textNode;
- mLastNBSPOffset = pos;
- // also keep track of earliest nbsp so far
- if (!mFirstNBSPNode) {
- mFirstNBSPNode = textNode;
- mFirstNBSPOffset = pos;
- }
- }
- end.SetPoint(textNode, pos + 1);
- }
- }
- } else {
- // we encountered a break or a special node, like <img>,
- // that is not a block and not a break but still
- // serves as a terminator to ws runs.
- mEndNode = end.node;
- mEndOffset = end.offset;
- if (TextEditUtils::IsBreak(nextNode)) {
- mEndReason = WSType::br;
- } else {
- mEndReason = WSType::special;
- }
- mEndReasonNode = nextNode;
- }
- } else {
- // no next node means we exhausted wsBoundingParent
- mEndNode = end.node;
- mEndOffset = end.offset;
- mEndReason = WSType::thisBlock;
- mEndReasonNode = wsBoundingParent;
- }
- }
-
- return NS_OK;
-}
-
-void
-WSRunObject::GetRuns()
-{
- ClearRuns();
-
- // handle some easy cases first
- mHTMLEditor->IsPreformatted(GetAsDOMNode(mNode), &mPRE);
- // if it's preformatedd, or if we are surrounded by text or special, it's all one
- // big normal ws run
- if (mPRE ||
- ((mStartReason == WSType::text || mStartReason == WSType::special) &&
- (mEndReason == WSType::text || mEndReason == WSType::special ||
- mEndReason == WSType::br))) {
- MakeSingleWSRun(WSType::normalWS);
- return;
- }
-
- // if we are before or after a block (or after a break), and there are no nbsp's,
- // then it's all non-rendering ws.
- if (!mFirstNBSPNode && !mLastNBSPNode &&
- ((mStartReason & WSType::block) || mStartReason == WSType::br ||
- (mEndReason & WSType::block))) {
- WSType wstype;
- if ((mStartReason & WSType::block) || mStartReason == WSType::br) {
- wstype = WSType::leadingWS;
- }
- if (mEndReason & WSType::block) {
- wstype |= WSType::trailingWS;
- }
- MakeSingleWSRun(wstype);
- return;
- }
-
- // otherwise a little trickier. shucks.
- mStartRun = new WSFragment();
- mStartRun->mStartNode = mStartNode;
- mStartRun->mStartOffset = mStartOffset;
-
- if (mStartReason & WSType::block || mStartReason == WSType::br) {
- // set up mStartRun
- mStartRun->mType = WSType::leadingWS;
- mStartRun->mEndNode = mFirstNBSPNode;
- mStartRun->mEndOffset = mFirstNBSPOffset;
- mStartRun->mLeftType = mStartReason;
- mStartRun->mRightType = WSType::normalWS;
-
- // set up next run
- WSFragment *normalRun = new WSFragment();
- mStartRun->mRight = normalRun;
- normalRun->mType = WSType::normalWS;
- normalRun->mStartNode = mFirstNBSPNode;
- normalRun->mStartOffset = mFirstNBSPOffset;
- normalRun->mLeftType = WSType::leadingWS;
- normalRun->mLeft = mStartRun;
- if (mEndReason != WSType::block) {
- // then no trailing ws. this normal run ends the overall ws run.
- normalRun->mRightType = mEndReason;
- normalRun->mEndNode = mEndNode;
- normalRun->mEndOffset = mEndOffset;
- mEndRun = normalRun;
- } else {
- // we might have trailing ws.
- // it so happens that *if* there is an nbsp at end, {mEndNode,mEndOffset-1}
- // will point to it, even though in general start/end points not
- // guaranteed to be in text nodes.
- if (mLastNBSPNode == mEndNode && mLastNBSPOffset == mEndOffset - 1) {
- // normal ws runs right up to adjacent block (nbsp next to block)
- normalRun->mRightType = mEndReason;
- normalRun->mEndNode = mEndNode;
- normalRun->mEndOffset = mEndOffset;
- mEndRun = normalRun;
- } else {
- normalRun->mEndNode = mLastNBSPNode;
- normalRun->mEndOffset = mLastNBSPOffset+1;
- normalRun->mRightType = WSType::trailingWS;
-
- // set up next run
- WSFragment *lastRun = new WSFragment();
- lastRun->mType = WSType::trailingWS;
- lastRun->mStartNode = mLastNBSPNode;
- lastRun->mStartOffset = mLastNBSPOffset+1;
- lastRun->mEndNode = mEndNode;
- lastRun->mEndOffset = mEndOffset;
- lastRun->mLeftType = WSType::normalWS;
- lastRun->mLeft = normalRun;
- lastRun->mRightType = mEndReason;
- mEndRun = lastRun;
- normalRun->mRight = lastRun;
- }
- }
- } else {
- // mStartReason is not WSType::block or WSType::br; set up mStartRun
- mStartRun->mType = WSType::normalWS;
- mStartRun->mEndNode = mLastNBSPNode;
- mStartRun->mEndOffset = mLastNBSPOffset+1;
- mStartRun->mLeftType = mStartReason;
-
- // we might have trailing ws.
- // it so happens that *if* there is an nbsp at end, {mEndNode,mEndOffset-1}
- // will point to it, even though in general start/end points not
- // guaranteed to be in text nodes.
- if (mLastNBSPNode == mEndNode && mLastNBSPOffset == (mEndOffset - 1)) {
- mStartRun->mRightType = mEndReason;
- mStartRun->mEndNode = mEndNode;
- mStartRun->mEndOffset = mEndOffset;
- mEndRun = mStartRun;
- } else {
- // set up next run
- WSFragment *lastRun = new WSFragment();
- lastRun->mType = WSType::trailingWS;
- lastRun->mStartNode = mLastNBSPNode;
- lastRun->mStartOffset = mLastNBSPOffset+1;
- lastRun->mLeftType = WSType::normalWS;
- lastRun->mLeft = mStartRun;
- lastRun->mRightType = mEndReason;
- mEndRun = lastRun;
- mStartRun->mRight = lastRun;
- mStartRun->mRightType = WSType::trailingWS;
- }
- }
-}
-
-void
-WSRunObject::ClearRuns()
-{
- WSFragment *tmp, *run;
- run = mStartRun;
- while (run) {
- tmp = run->mRight;
- delete run;
- run = tmp;
- }
- mStartRun = 0;
- mEndRun = 0;
-}
-
-void
-WSRunObject::MakeSingleWSRun(WSType aType)
-{
- mStartRun = new WSFragment();
-
- mStartRun->mStartNode = mStartNode;
- mStartRun->mStartOffset = mStartOffset;
- mStartRun->mType = aType;
- mStartRun->mEndNode = mEndNode;
- mStartRun->mEndOffset = mEndOffset;
- mStartRun->mLeftType = mStartReason;
- mStartRun->mRightType = mEndReason;
-
- mEndRun = mStartRun;
-}
-
-nsIContent*
-WSRunObject::GetPreviousWSNodeInner(nsINode* aStartNode,
- nsINode* aBlockParent)
-{
- // Can't really recycle various getnext/prior routines because we have
- // special needs here. Need to step into inline containers but not block
- // containers.
- MOZ_ASSERT(aStartNode && aBlockParent);
-
- nsCOMPtr<nsIContent> priorNode = aStartNode->GetPreviousSibling();
- OwningNonNull<nsINode> curNode = *aStartNode;
- while (!priorNode) {
- // We have exhausted nodes in parent of aStartNode.
- nsCOMPtr<nsINode> curParent = curNode->GetParentNode();
- NS_ENSURE_TRUE(curParent, nullptr);
- if (curParent == aBlockParent) {
- // We have exhausted nodes in the block parent. The convention here is
- // to return null.
- return nullptr;
- }
- // We have a parent: look for previous sibling
- priorNode = curParent->GetPreviousSibling();
- curNode = curParent;
- }
- // We have a prior node. If it's a block, return it.
- if (IsBlockNode(priorNode)) {
- return priorNode;
- }
- if (mHTMLEditor->IsContainer(priorNode)) {
- // Else if it's a container, get deep rightmost child
- nsCOMPtr<nsIContent> child = mHTMLEditor->GetRightmostChild(priorNode);
- if (child) {
- return child;
- }
- }
- // Else return the node itself
- return priorNode;
-}
-
-nsIContent*
-WSRunObject::GetPreviousWSNode(EditorDOMPoint aPoint,
- nsINode* aBlockParent)
-{
- // Can't really recycle various getnext/prior routines because we
- // have special needs here. Need to step into inline containers but
- // not block containers.
- MOZ_ASSERT(aPoint.node && aBlockParent);
-
- if (aPoint.node->NodeType() == nsIDOMNode::TEXT_NODE) {
- return GetPreviousWSNodeInner(aPoint.node, aBlockParent);
- }
- if (!mHTMLEditor->IsContainer(aPoint.node)) {
- return GetPreviousWSNodeInner(aPoint.node, aBlockParent);
- }
-
- if (!aPoint.offset) {
- if (aPoint.node == aBlockParent) {
- // We are at start of the block.
- return nullptr;
- }
-
- // We are at start of non-block container
- return GetPreviousWSNodeInner(aPoint.node, aBlockParent);
- }
-
- nsCOMPtr<nsIContent> startContent = do_QueryInterface(aPoint.node);
- NS_ENSURE_TRUE(startContent, nullptr);
- nsCOMPtr<nsIContent> priorNode = startContent->GetChildAt(aPoint.offset - 1);
- NS_ENSURE_TRUE(priorNode, nullptr);
- // We have a prior node. If it's a block, return it.
- if (IsBlockNode(priorNode)) {
- return priorNode;
- }
- if (mHTMLEditor->IsContainer(priorNode)) {
- // Else if it's a container, get deep rightmost child
- nsCOMPtr<nsIContent> child = mHTMLEditor->GetRightmostChild(priorNode);
- if (child) {
- return child;
- }
- }
- // Else return the node itself
- return priorNode;
-}
-
-nsIContent*
-WSRunObject::GetNextWSNodeInner(nsINode* aStartNode,
- nsINode* aBlockParent)
-{
- // Can't really recycle various getnext/prior routines because we have
- // special needs here. Need to step into inline containers but not block
- // containers.
- MOZ_ASSERT(aStartNode && aBlockParent);
-
- nsCOMPtr<nsIContent> nextNode = aStartNode->GetNextSibling();
- nsCOMPtr<nsINode> curNode = aStartNode;
- while (!nextNode) {
- // We have exhausted nodes in parent of aStartNode.
- nsCOMPtr<nsINode> curParent = curNode->GetParentNode();
- NS_ENSURE_TRUE(curParent, nullptr);
- if (curParent == aBlockParent) {
- // We have exhausted nodes in the block parent. The convention here is
- // to return null.
- return nullptr;
- }
- // We have a parent: look for next sibling
- nextNode = curParent->GetNextSibling();
- curNode = curParent;
- }
- // We have a next node. If it's a block, return it.
- if (IsBlockNode(nextNode)) {
- return nextNode;
- }
- if (mHTMLEditor->IsContainer(nextNode)) {
- // Else if it's a container, get deep leftmost child
- nsCOMPtr<nsIContent> child = mHTMLEditor->GetLeftmostChild(nextNode);
- if (child) {
- return child;
- }
- }
- // Else return the node itself
- return nextNode;
-}
-
-nsIContent*
-WSRunObject::GetNextWSNode(EditorDOMPoint aPoint,
- nsINode* aBlockParent)
-{
- // Can't really recycle various getnext/prior routines because we have
- // special needs here. Need to step into inline containers but not block
- // containers.
- MOZ_ASSERT(aPoint.node && aBlockParent);
-
- if (aPoint.node->NodeType() == nsIDOMNode::TEXT_NODE) {
- return GetNextWSNodeInner(aPoint.node, aBlockParent);
- }
- if (!mHTMLEditor->IsContainer(aPoint.node)) {
- return GetNextWSNodeInner(aPoint.node, aBlockParent);
- }
-
- nsCOMPtr<nsIContent> startContent = do_QueryInterface(aPoint.node);
- NS_ENSURE_TRUE(startContent, nullptr);
-
- nsCOMPtr<nsIContent> nextNode = startContent->GetChildAt(aPoint.offset);
- if (!nextNode) {
- if (aPoint.node == aBlockParent) {
- // We are at end of the block.
- return nullptr;
- }
-
- // We are at end of non-block container
- return GetNextWSNodeInner(aPoint.node, aBlockParent);
- }
-
- // We have a next node. If it's a block, return it.
- if (IsBlockNode(nextNode)) {
- return nextNode;
- }
- if (mHTMLEditor->IsContainer(nextNode)) {
- // else if it's a container, get deep leftmost child
- nsCOMPtr<nsIContent> child = mHTMLEditor->GetLeftmostChild(nextNode);
- if (child) {
- return child;
- }
- }
- // Else return the node itself
- return nextNode;
-}
-
-nsresult
-WSRunObject::PrepareToDeleteRangePriv(WSRunObject* aEndObject)
-{
- // this routine adjust whitespace before *this* and after aEndObject
- // in preperation for the two areas to become adjacent after the
- // intervening content is deleted. It's overly agressive right
- // now. There might be a block boundary remaining between them after
- // the deletion, in which case these adjstments are unneeded (though
- // I don't think they can ever be harmful?)
-
- NS_ENSURE_TRUE(aEndObject, NS_ERROR_NULL_POINTER);
-
- // get the runs before and after selection
- WSFragment *beforeRun, *afterRun;
- FindRun(mNode, mOffset, &beforeRun, false);
- aEndObject->FindRun(aEndObject->mNode, aEndObject->mOffset, &afterRun, true);
-
- // trim after run of any leading ws
- if (afterRun && (afterRun->mType & WSType::leadingWS)) {
- nsresult rv =
- aEndObject->DeleteChars(aEndObject->mNode, aEndObject->mOffset,
- afterRun->mEndNode, afterRun->mEndOffset,
- eOutsideUserSelectAll);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- // adjust normal ws in afterRun if needed
- if (afterRun && afterRun->mType == WSType::normalWS && !aEndObject->mPRE) {
- if ((beforeRun && (beforeRun->mType & WSType::leadingWS)) ||
- (!beforeRun && ((mStartReason & WSType::block) ||
- mStartReason == WSType::br))) {
- // make sure leading char of following ws is an nbsp, so that it will show up
- WSPoint point = aEndObject->GetCharAfter(aEndObject->mNode,
- aEndObject->mOffset);
- if (point.mTextNode && nsCRT::IsAsciiSpace(point.mChar)) {
- nsresult rv = aEndObject->ConvertToNBSP(point, eOutsideUserSelectAll);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- }
- // trim before run of any trailing ws
- if (beforeRun && (beforeRun->mType & WSType::trailingWS)) {
- nsresult rv = DeleteChars(beforeRun->mStartNode, beforeRun->mStartOffset,
- mNode, mOffset, eOutsideUserSelectAll);
- NS_ENSURE_SUCCESS(rv, rv);
- } else if (beforeRun && beforeRun->mType == WSType::normalWS && !mPRE) {
- if ((afterRun && (afterRun->mType & WSType::trailingWS)) ||
- (afterRun && afterRun->mType == WSType::normalWS) ||
- (!afterRun && (aEndObject->mEndReason & WSType::block))) {
- // make sure trailing char of starting ws is an nbsp, so that it will show up
- WSPoint point = GetCharBefore(mNode, mOffset);
- if (point.mTextNode && nsCRT::IsAsciiSpace(point.mChar)) {
- RefPtr<Text> wsStartNode, wsEndNode;
- int32_t wsStartOffset, wsEndOffset;
- GetAsciiWSBounds(eBoth, mNode, mOffset,
- getter_AddRefs(wsStartNode), &wsStartOffset,
- getter_AddRefs(wsEndNode), &wsEndOffset);
- point.mTextNode = wsStartNode;
- point.mOffset = wsStartOffset;
- nsresult rv = ConvertToNBSP(point, eOutsideUserSelectAll);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- }
- return NS_OK;
-}
-
-nsresult
-WSRunObject::PrepareToSplitAcrossBlocksPriv()
-{
- // used to prepare ws to be split across two blocks. The main issue
- // here is make sure normalWS doesn't end up becoming non-significant
- // leading or trailing ws after the split.
-
- // get the runs before and after selection
- WSFragment *beforeRun, *afterRun;
- FindRun(mNode, mOffset, &beforeRun, false);
- FindRun(mNode, mOffset, &afterRun, true);
-
- // adjust normal ws in afterRun if needed
- if (afterRun && afterRun->mType == WSType::normalWS) {
- // make sure leading char of following ws is an nbsp, so that it will show up
- WSPoint point = GetCharAfter(mNode, mOffset);
- if (point.mTextNode && nsCRT::IsAsciiSpace(point.mChar)) {
- nsresult rv = ConvertToNBSP(point);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
-
- // adjust normal ws in beforeRun if needed
- if (beforeRun && beforeRun->mType == WSType::normalWS) {
- // make sure trailing char of starting ws is an nbsp, so that it will show up
- WSPoint point = GetCharBefore(mNode, mOffset);
- if (point.mTextNode && nsCRT::IsAsciiSpace(point.mChar)) {
- RefPtr<Text> wsStartNode, wsEndNode;
- int32_t wsStartOffset, wsEndOffset;
- GetAsciiWSBounds(eBoth, mNode, mOffset,
- getter_AddRefs(wsStartNode), &wsStartOffset,
- getter_AddRefs(wsEndNode), &wsEndOffset);
- point.mTextNode = wsStartNode;
- point.mOffset = wsStartOffset;
- nsresult rv = ConvertToNBSP(point);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- return NS_OK;
-}
-
-nsresult
-WSRunObject::DeleteChars(nsINode* aStartNode,
- int32_t aStartOffset,
- nsINode* aEndNode,
- int32_t aEndOffset,
- AreaRestriction aAR)
-{
- // MOOSE: this routine needs to be modified to preserve the integrity of the
- // wsFragment info.
- NS_ENSURE_TRUE(aStartNode && aEndNode, NS_ERROR_NULL_POINTER);
-
- if (aAR == eOutsideUserSelectAll) {
- nsCOMPtr<nsIDOMNode> san =
- mHTMLEditor->FindUserSelectAllNode(GetAsDOMNode(aStartNode));
- if (san) {
- return NS_OK;
- }
-
- if (aStartNode != aEndNode) {
- san = mHTMLEditor->FindUserSelectAllNode(GetAsDOMNode(aEndNode));
- if (san) {
- return NS_OK;
- }
- }
- }
-
- if (aStartNode == aEndNode && aStartOffset == aEndOffset) {
- // Nothing to delete
- return NS_OK;
- }
-
- int32_t idx = mNodeArray.IndexOf(aStartNode);
- if (idx == -1) {
- // If our strarting point wasn't one of our ws text nodes, then just go
- // through them from the beginning.
- idx = 0;
- }
-
- if (aStartNode == aEndNode && aStartNode->GetAsText()) {
- return mHTMLEditor->DeleteText(*aStartNode->GetAsText(),
- static_cast<uint32_t>(aStartOffset),
- static_cast<uint32_t>(aEndOffset - aStartOffset));
- }
-
- RefPtr<nsRange> range;
- int32_t count = mNodeArray.Length();
- for (; idx < count; idx++) {
- RefPtr<Text> node = mNodeArray[idx];
- if (!node) {
- // We ran out of ws nodes; must have been deleting to end
- return NS_OK;
- }
- if (node == aStartNode) {
- uint32_t len = node->Length();
- if (uint32_t(aStartOffset) < len) {
- nsresult rv =
- mHTMLEditor->DeleteText(*node, AssertedCast<uint32_t>(aStartOffset),
- len - aStartOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- } else if (node == aEndNode) {
- if (aEndOffset) {
- nsresult rv =
- mHTMLEditor->DeleteText(*node, 0, AssertedCast<uint32_t>(aEndOffset));
- NS_ENSURE_SUCCESS(rv, rv);
- }
- break;
- } else {
- if (!range) {
- range = new nsRange(aStartNode);
- nsresult rv =
- range->SetStartAndEnd(aStartNode, aStartOffset, aEndNode, aEndOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- bool nodeBefore, nodeAfter;
- nsresult rv =
- nsRange::CompareNodeToRange(node, range, &nodeBefore, &nodeAfter);
- NS_ENSURE_SUCCESS(rv, rv);
- if (nodeAfter) {
- break;
- }
- if (!nodeBefore) {
- rv = mHTMLEditor->DeleteNode(node);
- NS_ENSURE_SUCCESS(rv, rv);
- mNodeArray.RemoveElement(node);
- --count;
- --idx;
- }
- }
- }
- return NS_OK;
-}
-
-WSRunObject::WSPoint
-WSRunObject::GetCharAfter(nsINode* aNode,
- int32_t aOffset)
-{
- MOZ_ASSERT(aNode);
-
- int32_t idx = mNodeArray.IndexOf(aNode);
- if (idx == -1) {
- // Use range comparisons to get right ws node
- return GetWSPointAfter(aNode, aOffset);
- }
- // Use WSPoint version of GetCharAfter()
- return GetCharAfter(WSPoint(mNodeArray[idx], aOffset, 0));
-}
-
-WSRunObject::WSPoint
-WSRunObject::GetCharBefore(nsINode* aNode,
- int32_t aOffset)
-{
- MOZ_ASSERT(aNode);
-
- int32_t idx = mNodeArray.IndexOf(aNode);
- if (idx == -1) {
- // Use range comparisons to get right ws node
- return GetWSPointBefore(aNode, aOffset);
- }
- // Use WSPoint version of GetCharBefore()
- return GetCharBefore(WSPoint(mNodeArray[idx], aOffset, 0));
-}
-
-WSRunObject::WSPoint
-WSRunObject::GetCharAfter(const WSPoint &aPoint)
-{
- MOZ_ASSERT(aPoint.mTextNode);
-
- WSPoint outPoint;
- outPoint.mTextNode = nullptr;
- outPoint.mOffset = 0;
- outPoint.mChar = 0;
-
- int32_t idx = mNodeArray.IndexOf(aPoint.mTextNode);
- if (idx == -1) {
- // Can't find point, but it's not an error
- return outPoint;
- }
-
- if (static_cast<uint16_t>(aPoint.mOffset) < aPoint.mTextNode->TextLength()) {
- outPoint = aPoint;
- outPoint.mChar = GetCharAt(aPoint.mTextNode, aPoint.mOffset);
- return outPoint;
- }
-
- int32_t numNodes = mNodeArray.Length();
- if (idx + 1 < numNodes) {
- outPoint.mTextNode = mNodeArray[idx + 1];
- MOZ_ASSERT(outPoint.mTextNode);
- outPoint.mOffset = 0;
- outPoint.mChar = GetCharAt(outPoint.mTextNode, 0);
- }
-
- return outPoint;
-}
-
-WSRunObject::WSPoint
-WSRunObject::GetCharBefore(const WSPoint &aPoint)
-{
- MOZ_ASSERT(aPoint.mTextNode);
-
- WSPoint outPoint;
- outPoint.mTextNode = nullptr;
- outPoint.mOffset = 0;
- outPoint.mChar = 0;
-
- int32_t idx = mNodeArray.IndexOf(aPoint.mTextNode);
- if (idx == -1) {
- // Can't find point, but it's not an error
- return outPoint;
- }
-
- if (aPoint.mOffset) {
- outPoint = aPoint;
- outPoint.mOffset--;
- outPoint.mChar = GetCharAt(aPoint.mTextNode, aPoint.mOffset - 1);
- return outPoint;
- }
-
- if (idx) {
- outPoint.mTextNode = mNodeArray[idx - 1];
-
- uint32_t len = outPoint.mTextNode->TextLength();
- if (len) {
- outPoint.mOffset = len - 1;
- outPoint.mChar = GetCharAt(outPoint.mTextNode, len - 1);
- }
- }
- return outPoint;
-}
-
-nsresult
-WSRunObject::ConvertToNBSP(WSPoint aPoint, AreaRestriction aAR)
-{
- // MOOSE: this routine needs to be modified to preserve the integrity of the
- // wsFragment info.
- NS_ENSURE_TRUE(aPoint.mTextNode, NS_ERROR_NULL_POINTER);
-
- if (aAR == eOutsideUserSelectAll) {
- nsCOMPtr<nsIDOMNode> san =
- mHTMLEditor->FindUserSelectAllNode(GetAsDOMNode(aPoint.mTextNode));
- if (san) {
- return NS_OK;
- }
- }
-
- // First, insert an nbsp
- AutoTransactionsConserveSelection dontSpazMySelection(mHTMLEditor);
- nsAutoString nbspStr(nbsp);
- nsresult rv =
- mHTMLEditor->InsertTextIntoTextNodeImpl(nbspStr, *aPoint.mTextNode,
- aPoint.mOffset, true);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Next, find range of ws it will replace
- RefPtr<Text> startNode, endNode;
- int32_t startOffset = 0, endOffset = 0;
-
- GetAsciiWSBounds(eAfter, aPoint.mTextNode, aPoint.mOffset + 1,
- getter_AddRefs(startNode), &startOffset,
- getter_AddRefs(endNode), &endOffset);
-
- // Finally, delete that replaced ws, if any
- if (startNode) {
- rv = DeleteChars(startNode, startOffset, endNode, endOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-void
-WSRunObject::GetAsciiWSBounds(int16_t aDir,
- nsINode* aNode,
- int32_t aOffset,
- Text** outStartNode,
- int32_t* outStartOffset,
- Text** outEndNode,
- int32_t* outEndOffset)
-{
- MOZ_ASSERT(aNode && outStartNode && outStartOffset && outEndNode &&
- outEndOffset);
-
- RefPtr<Text> startNode, endNode;
- int32_t startOffset = 0, endOffset = 0;
-
- if (aDir & eAfter) {
- WSPoint point = GetCharAfter(aNode, aOffset);
- if (point.mTextNode) {
- // We found a text node, at least
- startNode = endNode = point.mTextNode;
- startOffset = endOffset = point.mOffset;
-
- // Scan ahead to end of ASCII ws
- for (; nsCRT::IsAsciiSpace(point.mChar) && point.mTextNode;
- point = GetCharAfter(point)) {
- endNode = point.mTextNode;
- // endOffset is _after_ ws
- point.mOffset++;
- endOffset = point.mOffset;
- }
- }
- }
-
- if (aDir & eBefore) {
- WSPoint point = GetCharBefore(aNode, aOffset);
- if (point.mTextNode) {
- // We found a text node, at least
- startNode = point.mTextNode;
- startOffset = point.mOffset + 1;
- if (!endNode) {
- endNode = startNode;
- endOffset = startOffset;
- }
-
- // Scan back to start of ASCII ws
- for (; nsCRT::IsAsciiSpace(point.mChar) && point.mTextNode;
- point = GetCharBefore(point)) {
- startNode = point.mTextNode;
- startOffset = point.mOffset;
- }
- }
- }
-
- startNode.forget(outStartNode);
- *outStartOffset = startOffset;
- endNode.forget(outEndNode);
- *outEndOffset = endOffset;
-}
-
-/**
- * Given a dompoint, find the ws run that is before or after it, as caller
- * needs
- */
-void
-WSRunObject::FindRun(nsINode* aNode,
- int32_t aOffset,
- WSFragment** outRun,
- bool after)
-{
- MOZ_ASSERT(aNode && outRun);
- *outRun = nullptr;
-
- for (WSFragment* run = mStartRun; run; run = run->mRight) {
- int32_t comp = run->mStartNode ? nsContentUtils::ComparePoints(aNode,
- aOffset, run->mStartNode, run->mStartOffset) : -1;
- if (comp <= 0) {
- if (after) {
- *outRun = run;
- } else {
- // before
- *outRun = nullptr;
- }
- return;
- }
- comp = run->mEndNode ? nsContentUtils::ComparePoints(aNode, aOffset,
- run->mEndNode, run->mEndOffset) : -1;
- if (comp < 0) {
- *outRun = run;
- return;
- } else if (!comp) {
- if (after) {
- *outRun = run->mRight;
- } else {
- // before
- *outRun = run;
- }
- return;
- }
- if (!run->mRight) {
- if (after) {
- *outRun = nullptr;
- } else {
- // before
- *outRun = run;
- }
- return;
- }
- }
-}
-
-char16_t
-WSRunObject::GetCharAt(Text* aTextNode,
- int32_t aOffset)
-{
- // return 0 if we can't get a char, for whatever reason
- NS_ENSURE_TRUE(aTextNode, 0);
-
- int32_t len = int32_t(aTextNode->TextLength());
- if (aOffset < 0 || aOffset >= len) {
- return 0;
- }
- return aTextNode->GetText()->CharAt(aOffset);
-}
-
-WSRunObject::WSPoint
-WSRunObject::GetWSPointAfter(nsINode* aNode,
- int32_t aOffset)
-{
- // Note: only to be called if aNode is not a ws node.
-
- // Binary search on wsnodes
- uint32_t numNodes = mNodeArray.Length();
-
- if (!numNodes) {
- // Do nothing if there are no nodes to search
- WSPoint outPoint;
- return outPoint;
- }
-
- uint32_t firstNum = 0, curNum = numNodes/2, lastNum = numNodes;
- int16_t cmp = 0;
- RefPtr<Text> curNode;
-
- // Begin binary search. We do this because we need to minimize calls to
- // ComparePoints(), which is expensive.
- while (curNum != lastNum) {
- curNode = mNodeArray[curNum];
- cmp = nsContentUtils::ComparePoints(aNode, aOffset, curNode, 0);
- if (cmp < 0) {
- lastNum = curNum;
- } else {
- firstNum = curNum + 1;
- }
- curNum = (lastNum - firstNum)/2 + firstNum;
- MOZ_ASSERT(firstNum <= curNum && curNum <= lastNum, "Bad binary search");
- }
-
- // When the binary search is complete, we always know that the current node
- // is the same as the end node, which is always past our range. Therefore,
- // we've found the node immediately after the point of interest.
- if (curNum == mNodeArray.Length()) {
- // hey asked for past our range (it's after the last node). GetCharAfter
- // will do the work for us when we pass it the last index of the last node.
- RefPtr<Text> textNode(mNodeArray[curNum - 1]);
- WSPoint point(textNode, textNode->TextLength(), 0);
- return GetCharAfter(point);
- } else {
- // The char after the point is the first character of our range.
- RefPtr<Text> textNode(mNodeArray[curNum]);
- WSPoint point(textNode, 0, 0);
- return GetCharAfter(point);
- }
-}
-
-WSRunObject::WSPoint
-WSRunObject::GetWSPointBefore(nsINode* aNode,
- int32_t aOffset)
-{
- // Note: only to be called if aNode is not a ws node.
-
- // Binary search on wsnodes
- uint32_t numNodes = mNodeArray.Length();
-
- if (!numNodes) {
- // Do nothing if there are no nodes to search
- WSPoint outPoint;
- return outPoint;
- }
-
- uint32_t firstNum = 0, curNum = numNodes/2, lastNum = numNodes;
- int16_t cmp = 0;
- RefPtr<Text> curNode;
-
- // Begin binary search. We do this because we need to minimize calls to
- // ComparePoints(), which is expensive.
- while (curNum != lastNum) {
- curNode = mNodeArray[curNum];
- cmp = nsContentUtils::ComparePoints(aNode, aOffset, curNode, 0);
- if (cmp < 0) {
- lastNum = curNum;
- } else {
- firstNum = curNum + 1;
- }
- curNum = (lastNum - firstNum)/2 + firstNum;
- MOZ_ASSERT(firstNum <= curNum && curNum <= lastNum, "Bad binary search");
- }
-
- // When the binary search is complete, we always know that the current node
- // is the same as the end node, which is always past our range. Therefore,
- // we've found the node immediately after the point of interest.
- if (curNum == mNodeArray.Length()) {
- // Get the point before the end of the last node, we can pass the length of
- // the node into GetCharBefore, and it will return the last character.
- RefPtr<Text> textNode(mNodeArray[curNum - 1]);
- WSPoint point(textNode, textNode->TextLength(), 0);
- return GetCharBefore(point);
- } else {
- // We can just ask the current node for the point immediately before it,
- // it will handle moving to the previous node (if any) and returning the
- // appropriate character
- RefPtr<Text> textNode(mNodeArray[curNum]);
- WSPoint point(textNode, 0, 0);
- return GetCharBefore(point);
- }
-}
-
-nsresult
-WSRunObject::CheckTrailingNBSPOfRun(WSFragment *aRun)
-{
- // Try to change an nbsp to a space, if possible, just to prevent nbsp
- // proliferation. Examine what is before and after the trailing nbsp, if
- // any.
- NS_ENSURE_TRUE(aRun, NS_ERROR_NULL_POINTER);
- bool leftCheck = false;
- bool spaceNBSP = false;
- bool rightCheck = false;
-
- // confirm run is normalWS
- if (aRun->mType != WSType::normalWS) {
- return NS_ERROR_FAILURE;
- }
-
- // first check for trailing nbsp
- WSPoint thePoint = GetCharBefore(aRun->mEndNode, aRun->mEndOffset);
- if (thePoint.mTextNode && thePoint.mChar == nbsp) {
- // now check that what is to the left of it is compatible with replacing nbsp with space
- WSPoint prevPoint = GetCharBefore(thePoint);
- if (prevPoint.mTextNode) {
- if (!nsCRT::IsAsciiSpace(prevPoint.mChar)) {
- leftCheck = true;
- } else {
- spaceNBSP = true;
- }
- } else if (aRun->mLeftType == WSType::text ||
- aRun->mLeftType == WSType::special) {
- leftCheck = true;
- }
- if (leftCheck || spaceNBSP) {
- // now check that what is to the right of it is compatible with replacing
- // nbsp with space
- if (aRun->mRightType == WSType::text ||
- aRun->mRightType == WSType::special ||
- aRun->mRightType == WSType::br) {
- rightCheck = true;
- }
- if ((aRun->mRightType & WSType::block) &&
- IsBlockNode(GetWSBoundingParent())) {
- // We are at a block boundary. Insert a <br>. Why? Well, first note
- // that the br will have no visible effect since it is up against a
- // block boundary. |foo<br><p>bar| renders like |foo<p>bar| and
- // similarly |<p>foo<br></p>bar| renders like |<p>foo</p>bar|. What
- // this <br> addition gets us is the ability to convert a trailing nbsp
- // to a space. Consider: |<body>foo. '</body>|, where ' represents
- // selection. User types space attempting to put 2 spaces after the
- // end of their sentence. We used to do this as: |<body>foo.
- // &nbsp</body>| This caused problems with soft wrapping: the nbsp
- // would wrap to the next line, which looked attrocious. If you try to
- // do: |<body>foo.&nbsp </body>| instead, the trailing space is
- // invisible because it is against a block boundary. If you do:
- // |<body>foo.&nbsp&nbsp</body>| then you get an even uglier soft
- // wrapping problem, where foo is on one line until you type the final
- // space, and then "foo " jumps down to the next line. Ugh. The best
- // way I can find out of this is to throw in a harmless <br> here,
- // which allows us to do: |<body>foo.&nbsp <br></body>|, which doesn't
- // cause foo to jump lines, doesn't cause spaces to show up at the
- // beginning of soft wrapped lines, and lets the user see 2 spaces when
- // they type 2 spaces.
-
- nsCOMPtr<Element> brNode =
- mHTMLEditor->CreateBR(aRun->mEndNode, aRun->mEndOffset);
- NS_ENSURE_TRUE(brNode, NS_ERROR_FAILURE);
-
- // Refresh thePoint, prevPoint
- thePoint = GetCharBefore(aRun->mEndNode, aRun->mEndOffset);
- prevPoint = GetCharBefore(thePoint);
- rightCheck = true;
- }
- }
- if (leftCheck && rightCheck) {
- // Now replace nbsp with space. First, insert a space
- AutoTransactionsConserveSelection dontSpazMySelection(mHTMLEditor);
- nsAutoString spaceStr(char16_t(32));
- nsresult rv =
- mHTMLEditor->InsertTextIntoTextNodeImpl(spaceStr, *thePoint.mTextNode,
- thePoint.mOffset, true);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Finally, delete that nbsp
- rv = DeleteChars(thePoint.mTextNode, thePoint.mOffset + 1,
- thePoint.mTextNode, thePoint.mOffset + 2);
- NS_ENSURE_SUCCESS(rv, rv);
- } else if (!mPRE && spaceNBSP && rightCheck) {
- // Don't mess with this preformatted for now. We have a run of ASCII
- // whitespace (which will render as one space) followed by an nbsp (which
- // is at the end of the whitespace run). Let's switch their order. This
- // will ensure that if someone types two spaces after a sentence, and the
- // editor softwraps at this point, the spaces won't be split across lines,
- // which looks ugly and is bad for the moose.
-
- RefPtr<Text> startNode, endNode;
- int32_t startOffset, endOffset;
- GetAsciiWSBounds(eBoth, prevPoint.mTextNode, prevPoint.mOffset + 1,
- getter_AddRefs(startNode), &startOffset,
- getter_AddRefs(endNode), &endOffset);
-
- // Delete that nbsp
- nsresult rv = DeleteChars(thePoint.mTextNode, thePoint.mOffset,
- thePoint.mTextNode, thePoint.mOffset + 1);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Finally, insert that nbsp before the ASCII ws run
- AutoTransactionsConserveSelection dontSpazMySelection(mHTMLEditor);
- nsAutoString nbspStr(nbsp);
- rv = mHTMLEditor->InsertTextIntoTextNodeImpl(nbspStr, *startNode,
- startOffset, true);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- }
- return NS_OK;
-}
-
-nsresult
-WSRunObject::CheckTrailingNBSP(WSFragment* aRun,
- nsINode* aNode,
- int32_t aOffset)
-{
- // Try to change an nbsp to a space, if possible, just to prevent nbsp
- // proliferation. This routine is called when we are about to make this
- // point in the ws abut an inserted break or text, so we don't have to worry
- // about what is after it. What is after it now will end up after the
- // inserted object.
- NS_ENSURE_TRUE(aRun && aNode, NS_ERROR_NULL_POINTER);
- bool canConvert = false;
- WSPoint thePoint = GetCharBefore(aNode, aOffset);
- if (thePoint.mTextNode && thePoint.mChar == nbsp) {
- WSPoint prevPoint = GetCharBefore(thePoint);
- if (prevPoint.mTextNode) {
- if (!nsCRT::IsAsciiSpace(prevPoint.mChar)) {
- canConvert = true;
- }
- } else if (aRun->mLeftType == WSType::text ||
- aRun->mLeftType == WSType::special) {
- canConvert = true;
- }
- }
- if (canConvert) {
- // First, insert a space
- AutoTransactionsConserveSelection dontSpazMySelection(mHTMLEditor);
- nsAutoString spaceStr(char16_t(32));
- nsresult rv =
- mHTMLEditor->InsertTextIntoTextNodeImpl(spaceStr, *thePoint.mTextNode,
- thePoint.mOffset, true);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Finally, delete that nbsp
- rv = DeleteChars(thePoint.mTextNode, thePoint.mOffset + 1,
- thePoint.mTextNode, thePoint.mOffset + 2);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
-}
-
-nsresult
-WSRunObject::CheckLeadingNBSP(WSFragment* aRun,
- nsINode* aNode,
- int32_t aOffset)
-{
- // Try to change an nbsp to a space, if possible, just to prevent nbsp
- // proliferation This routine is called when we are about to make this point
- // in the ws abut an inserted text, so we don't have to worry about what is
- // before it. What is before it now will end up before the inserted text.
- bool canConvert = false;
- WSPoint thePoint = GetCharAfter(aNode, aOffset);
- if (thePoint.mChar == nbsp) {
- WSPoint tmp = thePoint;
- // we want to be after thePoint
- tmp.mOffset++;
- WSPoint nextPoint = GetCharAfter(tmp);
- if (nextPoint.mTextNode) {
- if (!nsCRT::IsAsciiSpace(nextPoint.mChar)) {
- canConvert = true;
- }
- } else if (aRun->mRightType == WSType::text ||
- aRun->mRightType == WSType::special ||
- aRun->mRightType == WSType::br) {
- canConvert = true;
- }
- }
- if (canConvert) {
- // First, insert a space
- AutoTransactionsConserveSelection dontSpazMySelection(mHTMLEditor);
- nsAutoString spaceStr(char16_t(32));
- nsresult rv =
- mHTMLEditor->InsertTextIntoTextNodeImpl(spaceStr, *thePoint.mTextNode,
- thePoint.mOffset, true);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Finally, delete that nbsp
- rv = DeleteChars(thePoint.mTextNode, thePoint.mOffset + 1,
- thePoint.mTextNode, thePoint.mOffset + 2);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
-}
-
-
-nsresult
-WSRunObject::Scrub()
-{
- WSFragment *run = mStartRun;
- while (run) {
- if (run->mType & (WSType::leadingWS | WSType::trailingWS)) {
- nsresult rv = DeleteChars(run->mStartNode, run->mStartOffset,
- run->mEndNode, run->mEndOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- run = run->mRight;
- }
- return NS_OK;
-}
-
-bool
-WSRunObject::IsBlockNode(nsINode* aNode)
-{
- return aNode && aNode->IsElement() &&
- HTMLEditor::NodeIsBlockStatic(aNode->AsElement());
-}
-
-} // namespace mozilla
diff --git a/editor/libeditor/WSRunObject.h b/editor/libeditor/WSRunObject.h
deleted file mode 100644
index 215e3eb2f..000000000
--- a/editor/libeditor/WSRunObject.h
+++ /dev/null
@@ -1,411 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef WSRunObject_h
-#define WSRunObject_h
-
-#include "nsCOMPtr.h"
-#include "nsIEditor.h" // for EDirection
-#include "nsINode.h"
-#include "nscore.h"
-#include "mozilla/Attributes.h"
-#include "mozilla/dom/Text.h"
-
-class nsIDOMNode;
-
-namespace mozilla {
-
-class HTMLEditor;
-class HTMLEditRules;
-struct EditorDOMPoint;
-
-// class WSRunObject represents the entire whitespace situation
-// around a given point. It collects up a list of nodes that contain
-// whitespace and categorizes in up to 3 different WSFragments (detailed
-// below). Each WSFragment is a collection of whitespace that is
-// either all insignificant, or that is significant. A WSFragment could
-// consist of insignificant whitespace because it is after a block
-// boundary or after a break. Or it could be insignificant because it
-// is before a block. Or it could be significant because it is
-// surrounded by text, or starts and ends with nbsps, etc.
-
-// Throughout I refer to LeadingWS, NormalWS, TrailingWS. LeadingWS & TrailingWS
-// are runs of ascii ws that are insignificant (do not render) because they
-// are adjacent to block boundaries, or after a break. NormalWS is ws that
-// does cause soem rendering. Note that not all the ws in a NormalWS run need
-// render. For example, two ascii spaces surrounded by text on both sides
-// will only render as one space (in non-preformatted stlye html), yet both
-// spaces count as NormalWS. Together, they render as the one visible space.
-
-/**
- * A type-safe bitfield indicating various types of whitespace or other things.
- * Used as a member variable in WSRunObject and WSFragment.
- *
- * XXX: If this idea is useful in other places, we should generalize it using a
- * template.
- */
-class WSType
-{
-public:
- enum Enum
- {
- none = 0,
- leadingWS = 1, // leading insignificant ws, ie, after block or br
- trailingWS = 1 << 1, // trailing insignificant ws, ie, before block
- normalWS = 1 << 2, // normal significant ws, ie, after text, image, ...
- text = 1 << 3, // indicates regular (non-ws) text
- special = 1 << 4, // indicates an inline non-container, like image
- br = 1 << 5, // indicates a br node
- otherBlock = 1 << 6, // indicates a block other than one ws run is in
- thisBlock = 1 << 7, // indicates the block ws run is in
- block = otherBlock | thisBlock // block found
- };
-
- /**
- * Implicit constructor, because the enums are logically just WSTypes
- * themselves, and are only a separate type because there's no other obvious
- * way to name specific WSType values.
- */
- MOZ_IMPLICIT WSType(const Enum& aEnum = none)
- : mEnum(aEnum)
- {}
-
- // operator==, &, and | need to access mEnum
- friend bool operator==(const WSType& aLeft, const WSType& aRight);
- friend const WSType operator&(const WSType& aLeft, const WSType& aRight);
- friend const WSType operator|(const WSType& aLeft, const WSType& aRight);
- WSType& operator=(const WSType& aOther)
- {
- // This handles self-assignment fine
- mEnum = aOther.mEnum;
- return *this;
- }
- WSType& operator&=(const WSType& aOther)
- {
- mEnum &= aOther.mEnum;
- return *this;
- }
- WSType& operator|=(const WSType& aOther)
- {
- mEnum |= aOther.mEnum;
- return *this;
- }
-
-private:
- uint16_t mEnum;
- void bool_conversion_helper() {}
-
-public:
- // Allow boolean conversion with no numeric conversion
- typedef void (WSType::*bool_type)();
- operator bool_type() const
- {
- return mEnum ? &WSType::bool_conversion_helper : nullptr;
- }
-};
-
-/**
- * These are declared as global functions so "WSType::Enum == WSType" et al.
- * will work using the implicit constructor.
- */
-inline bool operator==(const WSType& aLeft, const WSType& aRight)
-{
- return aLeft.mEnum == aRight.mEnum;
-}
-
-inline bool operator!=(const WSType& aLeft, const WSType& aRight)
-{
- return !(aLeft == aRight);
-}
-
-inline const WSType operator&(const WSType& aLeft, const WSType& aRight)
-{
- WSType ret;
- ret.mEnum = aLeft.mEnum & aRight.mEnum;
- return ret;
-}
-
-inline const WSType operator|(const WSType& aLeft, const WSType& aRight)
-{
- WSType ret;
- ret.mEnum = aLeft.mEnum | aRight.mEnum;
- return ret;
-}
-
-/**
- * Make sure that & and | of WSType::Enum creates a WSType instead of an int,
- * because operators between WSType and int shouldn't work
- */
-inline const WSType operator&(const WSType::Enum& aLeft,
- const WSType::Enum& aRight)
-{
- return WSType(aLeft) & WSType(aRight);
-}
-
-inline const WSType operator|(const WSType::Enum& aLeft,
- const WSType::Enum& aRight)
-{
- return WSType(aLeft) | WSType(aRight);
-}
-
-class MOZ_STACK_CLASS WSRunObject final
-{
-public:
- enum BlockBoundary
- {
- kBeforeBlock,
- kBlockStart,
- kBlockEnd,
- kAfterBlock
- };
-
- enum {eBefore = 1};
- enum {eAfter = 1 << 1};
- enum {eBoth = eBefore | eAfter};
-
- WSRunObject(HTMLEditor* aHTMLEditor, nsINode* aNode, int32_t aOffset);
- WSRunObject(HTMLEditor* aHTMLEditor, nsIDOMNode* aNode, int32_t aOffset);
- ~WSRunObject();
-
- // ScrubBlockBoundary removes any non-visible whitespace at the specified
- // location relative to a block node.
- static nsresult ScrubBlockBoundary(HTMLEditor* aHTMLEditor,
- BlockBoundary aBoundary,
- nsINode* aBlock,
- int32_t aOffset = -1);
-
- // PrepareToJoinBlocks fixes up ws at the end of aLeftBlock and the
- // beginning of aRightBlock in preperation for them to be joined. Example
- // of fixup: trailingws in aLeftBlock needs to be removed.
- static nsresult PrepareToJoinBlocks(HTMLEditor* aHTMLEditor,
- dom::Element* aLeftBlock,
- dom::Element* aRightBlock);
-
- // PrepareToDeleteRange fixes up ws before {aStartNode,aStartOffset}
- // and after {aEndNode,aEndOffset} in preperation for content
- // in that range to be deleted. Note that the nodes and offsets
- // are adjusted in response to any dom changes we make while
- // adjusting ws.
- // example of fixup: trailingws before {aStartNode,aStartOffset}
- // needs to be removed.
- static nsresult PrepareToDeleteRange(HTMLEditor* aHTMLEditor,
- nsCOMPtr<nsINode>* aStartNode,
- int32_t* aStartOffset,
- nsCOMPtr<nsINode>* aEndNode,
- int32_t* aEndOffset);
-
- // PrepareToDeleteNode fixes up ws before and after aContent in preparation
- // for aContent to be deleted. Example of fixup: trailingws before
- // aContent needs to be removed.
- static nsresult PrepareToDeleteNode(HTMLEditor* aHTMLEditor,
- nsIContent* aContent);
-
- // PrepareToSplitAcrossBlocks fixes up ws before and after
- // {aSplitNode,aSplitOffset} in preparation for a block parent to be split.
- // Note that the aSplitNode and aSplitOffset are adjusted in response to
- // any DOM changes we make while adjusting ws. Example of fixup: normalws
- // before {aSplitNode,aSplitOffset} needs to end with nbsp.
- static nsresult PrepareToSplitAcrossBlocks(HTMLEditor* aHTMLEditor,
- nsCOMPtr<nsINode>* aSplitNode,
- int32_t* aSplitOffset);
-
- // InsertBreak inserts a br node at {aInOutParent,aInOutOffset}
- // and makes any needed adjustments to ws around that point.
- // example of fixup: normalws after {aInOutParent,aInOutOffset}
- // needs to begin with nbsp.
- already_AddRefed<dom::Element> InsertBreak(nsCOMPtr<nsINode>* aInOutParent,
- int32_t* aInOutOffset,
- nsIEditor::EDirection aSelect);
-
- // InsertText inserts a string at {aInOutParent,aInOutOffset} and makes any
- // needed adjustments to ws around that point. Example of fixup:
- // trailingws before {aInOutParent,aInOutOffset} needs to be removed.
- nsresult InsertText(const nsAString& aStringToInsert,
- nsCOMPtr<nsINode>* aInOutNode,
- int32_t* aInOutOffset,
- nsIDocument* aDoc);
-
- // DeleteWSBackward deletes a single visible piece of ws before the ws
- // point (the point to create the wsRunObject, passed to its constructor).
- // It makes any needed conversion to adjacent ws to retain its
- // significance.
- nsresult DeleteWSBackward();
-
- // DeleteWSForward deletes a single visible piece of ws after the ws point
- // (the point to create the wsRunObject, passed to its constructor). It
- // makes any needed conversion to adjacent ws to retain its significance.
- nsresult DeleteWSForward();
-
- // PriorVisibleNode returns the first piece of visible thing before
- // {aNode,aOffset}. If there is no visible ws qualifying it returns what
- // is before the ws run. Note that {outVisNode,outVisOffset} is set to
- // just AFTER the visible object.
- void PriorVisibleNode(nsINode* aNode,
- int32_t aOffset,
- nsCOMPtr<nsINode>* outVisNode,
- int32_t* outVisOffset,
- WSType* outType);
-
- // NextVisibleNode returns the first piece of visible thing after
- // {aNode,aOffset}. If there is no visible ws qualifying it returns what
- // is after the ws run. Note that {outVisNode,outVisOffset} is set to just
- // BEFORE the visible object.
- void NextVisibleNode(nsINode* aNode,
- int32_t aOffset,
- nsCOMPtr<nsINode>* outVisNode,
- int32_t* outVisOffset,
- WSType* outType);
-
- // AdjustWhitespace examines the ws object for nbsp's that can
- // be safely converted to regular ascii space and converts them.
- nsresult AdjustWhitespace();
-
-protected:
- // WSFragment represents a single run of ws (all leadingws, or all normalws,
- // or all trailingws, or all leading+trailingws). Note that this single run
- // may still span multiple nodes.
- struct WSFragment final
- {
- nsCOMPtr<nsINode> mStartNode; // node where ws run starts
- nsCOMPtr<nsINode> mEndNode; // node where ws run ends
- int32_t mStartOffset; // offset where ws run starts
- int32_t mEndOffset; // offset where ws run ends
- // type of ws, and what is to left and right of it
- WSType mType, mLeftType, mRightType;
- // other ws runs to left or right. may be null.
- WSFragment *mLeft, *mRight;
-
- WSFragment()
- : mStartOffset(0)
- , mEndOffset(0)
- , mLeft(nullptr)
- , mRight(nullptr)
- {}
- };
-
- // A WSPoint struct represents a unique location within the ws run. It is
- // always within a textnode that is one of the nodes stored in the list
- // in the wsRunObject. For convenience, the character at that point is also
- // stored in the struct.
- struct MOZ_STACK_CLASS WSPoint final
- {
- RefPtr<dom::Text> mTextNode;
- uint32_t mOffset;
- char16_t mChar;
-
- WSPoint()
- : mTextNode(nullptr)
- , mOffset(0)
- , mChar(0)
- {}
-
- WSPoint(dom::Text* aTextNode, int32_t aOffset, char16_t aChar)
- : mTextNode(aTextNode)
- , mOffset(aOffset)
- , mChar(aChar)
- {}
- };
-
- enum AreaRestriction
- {
- eAnywhere, eOutsideUserSelectAll
- };
-
- /**
- * Return the node which we will handle white-space under. This is the
- * closest block within the DOM subtree we're editing, or if none is
- * found, the (inline) root of the editable subtree.
- */
- nsINode* GetWSBoundingParent();
-
- nsresult GetWSNodes();
- void GetRuns();
- void ClearRuns();
- void MakeSingleWSRun(WSType aType);
- nsIContent* GetPreviousWSNodeInner(nsINode* aStartNode,
- nsINode* aBlockParent);
- nsIContent* GetPreviousWSNode(EditorDOMPoint aPoint, nsINode* aBlockParent);
- nsIContent* GetNextWSNodeInner(nsINode* aStartNode, nsINode* aBlockParent);
- nsIContent* GetNextWSNode(EditorDOMPoint aPoint, nsINode* aBlockParent);
- nsresult PrepareToDeleteRangePriv(WSRunObject* aEndObject);
- nsresult PrepareToSplitAcrossBlocksPriv();
- nsresult DeleteChars(nsINode* aStartNode, int32_t aStartOffset,
- nsINode* aEndNode, int32_t aEndOffset,
- AreaRestriction aAR = eAnywhere);
- WSPoint GetCharAfter(nsINode* aNode, int32_t aOffset);
- WSPoint GetCharBefore(nsINode* aNode, int32_t aOffset);
- WSPoint GetCharAfter(const WSPoint& aPoint);
- WSPoint GetCharBefore(const WSPoint& aPoint);
- nsresult ConvertToNBSP(WSPoint aPoint,
- AreaRestriction aAR = eAnywhere);
- void GetAsciiWSBounds(int16_t aDir, nsINode* aNode, int32_t aOffset,
- dom::Text** outStartNode, int32_t* outStartOffset,
- dom::Text** outEndNode, int32_t* outEndOffset);
- void FindRun(nsINode* aNode, int32_t aOffset, WSFragment** outRun,
- bool after);
- char16_t GetCharAt(dom::Text* aTextNode, int32_t aOffset);
- WSPoint GetWSPointAfter(nsINode* aNode, int32_t aOffset);
- WSPoint GetWSPointBefore(nsINode* aNode, int32_t aOffset);
- nsresult CheckTrailingNBSPOfRun(WSFragment *aRun);
- nsresult CheckTrailingNBSP(WSFragment* aRun, nsINode* aNode,
- int32_t aOffset);
- nsresult CheckLeadingNBSP(WSFragment* aRun, nsINode* aNode,
- int32_t aOffset);
-
- nsresult Scrub();
- bool IsBlockNode(nsINode* aNode);
-
- // The node passed to our constructor.
- nsCOMPtr<nsINode> mNode;
- // The offset passed to our contructor.
- int32_t mOffset;
- // Together, the above represent the point at which we are building up ws info.
-
- // true if we are in preformatted whitespace context.
- bool mPRE;
- // Node/offset where ws starts.
- nsCOMPtr<nsINode> mStartNode;
- int32_t mStartOffset;
- // Reason why ws starts (eText, eOtherBlock, etc.).
- WSType mStartReason;
- // The node that implicated by start reason.
- nsCOMPtr<nsINode> mStartReasonNode;
-
- // Node/offset where ws ends.
- nsCOMPtr<nsINode> mEndNode;
- int32_t mEndOffset;
- // Reason why ws ends (eText, eOtherBlock, etc.).
- WSType mEndReason;
- // The node that implicated by end reason.
- nsCOMPtr<nsINode> mEndReasonNode;
-
- // Location of first nbsp in ws run, if any.
- RefPtr<dom::Text> mFirstNBSPNode;
- int32_t mFirstNBSPOffset;
-
- // Location of last nbsp in ws run, if any.
- RefPtr<dom::Text> mLastNBSPNode;
- int32_t mLastNBSPOffset;
-
- // The list of nodes containing ws in this run.
- nsTArray<RefPtr<dom::Text>> mNodeArray;
-
- // The first WSFragment in the run.
- WSFragment* mStartRun;
- // The last WSFragment in the run, may be same as first.
- WSFragment* mEndRun;
-
- // Non-owning.
- HTMLEditor* mHTMLEditor;
-
- // Opening this class up for pillaging.
- friend class HTMLEditRules;
- // Opening this class up for more pillaging.
- friend class HTMLEditor;
-};
-
-} // namespace mozilla
-
-#endif // #ifndef WSRunObject_h
diff --git a/editor/libeditor/crashtests/1057677.html b/editor/libeditor/crashtests/1057677.html
deleted file mode 100644
index d0b9497a5..000000000
--- a/editor/libeditor/crashtests/1057677.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<html><body></body><script>
-document.designMode = "on";
-var hrElem = document.createElement("HR");
-var select = window.getSelection();
-document.body.appendChild(hrElem);
-select.collapse(hrElem,0);
-document.execCommand("InsertHTML", false, "<div>foo</div><div>bar</div>");
-</script>
-</html>
diff --git a/editor/libeditor/crashtests/1128787.html b/editor/libeditor/crashtests/1128787.html
deleted file mode 100644
index fc6bff097..000000000
--- a/editor/libeditor/crashtests/1128787.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<title>Bug 1128787</title>
-</head>
-<body>
- <input type="button"/>
- <script>
- window.onload = function () {
- document.designMode = "on";
- }
- var input = document.getElementsByTagName("input")[0];
- input.focus();
- input.type = "text";
- </script>
-</body>
-</html>
diff --git a/editor/libeditor/crashtests/1134545.html b/editor/libeditor/crashtests/1134545.html
deleted file mode 100644
index 4e871804f..000000000
--- a/editor/libeditor/crashtests/1134545.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<!-- saved from url=(0065)https://bug1134545.bugzilla.mozilla.org/attachment.cgi?id=8566418 -->
-<html><head><meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
-<script>
-
-function boom()
-{
- textNode = document.createTextNode(" ");
- x.appendChild(textNode);
- x.setAttribute('contenteditable', "true");
- textNode.remove();
- window.getSelection().selectAllChildren(textNode);
- document.execCommand("increasefontsize", false, null);
-}
-
-</script>
-</head>
-<body onload="boom();">
-<div id="x" contenteditable="true"></div>
-
-
-</body></html> \ No newline at end of file
diff --git a/editor/libeditor/crashtests/1158452.html b/editor/libeditor/crashtests/1158452.html
deleted file mode 100644
index 56c74abd6..000000000
--- a/editor/libeditor/crashtests/1158452.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-<div>
-<div>
-aaaaaaa
-</script>
-<script type="text/javascript">
-document.designMode = "on"
-window.getSelection().modify("extend", "backward", "line")
-document.execCommand("increasefontsize","",null);
-</script>
diff --git a/editor/libeditor/crashtests/1158651.html b/editor/libeditor/crashtests/1158651.html
deleted file mode 100644
index 27278b523..000000000
--- a/editor/libeditor/crashtests/1158651.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<script>
-onload = function() {
- var testContainer = document.createElement("span");
- testContainer.contentEditable = true;
- document.body.appendChild(testContainer);
-
- function queryFormatBlock(content)
- {
- testContainer.innerHTML = content;
- while (testContainer.firstChild)
- testContainer = testContainer.firstChild;
- window.getSelection().collapse(testContainer, 0);
- document.queryCommandValue('formatBlock');
- }
-
- queryFormatBlock('<ol>hello</ol>');
-};
-</script>
diff --git a/editor/libeditor/crashtests/1244894.xhtml b/editor/libeditor/crashtests/1244894.xhtml
deleted file mode 100644
index 89a24751e..000000000
--- a/editor/libeditor/crashtests/1244894.xhtml
+++ /dev/null
@@ -1,21 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<script>
-
-function boom()
-{
- document.designMode = 'on';
- document.execCommand("indent", false, null);
- document.execCommand("insertText", false, "a");
- document.execCommand("forwardDelete", false, null);
- document.execCommand("justifyfull", false, null);
-}
-
-window.addEventListener("load", boom, false);
-
-</script>
-</head>
-
-<body> <span class="v"></span></body><body><input type="file" /></body>
-
-</html>
diff --git a/editor/libeditor/crashtests/1272490.html b/editor/libeditor/crashtests/1272490.html
deleted file mode 100644
index a3c8ecd81..000000000
--- a/editor/libeditor/crashtests/1272490.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8">
-<script>
-window.onload = function () {
- var childDocument = document.getElementsByTagName("iframe")[0].contentDocument;
- childDocument.designMode = "on";
- function onAttrModified(aEvent) {
- childDocument.removeEventListener("DOMAttrModified", onAttrModified, false);
- // Remove the editor from document during executing "insertOrderedList".
- document.body.innerHTML = "";
- }
- childDocument.addEventListener("DOMAttrModified", onAttrModified, false);
- childDocument.execCommand("insertOrderedList", false, "1");
-}
-</script>
-</head>
-<body><iframe></iframe></body>
-</html>
diff --git a/editor/libeditor/crashtests/1317704.html b/editor/libeditor/crashtests/1317704.html
deleted file mode 100644
index 64359c796..000000000
--- a/editor/libeditor/crashtests/1317704.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8">
-<script>
-addEventListener('DOMContentLoaded', function(){
- document.documentElement.className = 'lizard';
- setTimeout(function(){
- document.execCommand('selectAll', false, null);
- document.designMode = 'on';
- document.execCommand('removeformat', false, null);
- }, 0);
-});
-</script>
-<style>
-.lizard{
- -webkit-user-select:all;
-}
-*{
- position:fixed;
- display:table-column;
-}
-</style>
-</head>
-<body>
-<span>
-<span contenteditable>
-<span class=lizard></span>
-<span class=lizard></span>
-<span />
-</span>
-</span>
-</span>
-</span>
-</body>
-</html>
diff --git a/editor/libeditor/crashtests/1348851.html b/editor/libeditor/crashtests/1348851.html
deleted file mode 100644
index d618f049e..000000000
--- a/editor/libeditor/crashtests/1348851.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE>
-<html>
-<head>
-<meta charset="UTF-8">
-<script>
-function boom(){
- document.designMode = "on";
- document.execCommand("insertlinebreak");
- document.designMode = "off";
- document.designMode = "on";
- document.execCommand("insertunorderedlist");
-}
-addEventListener("DOMContentLoaded", boom);
-</script>
-</head>
-<body style="display:flex;">
-<!--comment-->
-</body>
-</html>
diff --git a/editor/libeditor/crashtests/336081-1.xhtml b/editor/libeditor/crashtests/336081-1.xhtml
deleted file mode 100644
index da653c601..000000000
--- a/editor/libeditor/crashtests/336081-1.xhtml
+++ /dev/null
@@ -1,52 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
-<head>
-<script>
-<![CDATA[
-
-function foop(targetWindow)
-{
- var targetDocument = targetWindow.document;
-
- var r1 = targetDocument.createRange();
- r1.setStart(targetDocument.getElementById("out1"), 0);
- r1.setEnd (targetDocument.getElementById("out2"), 0);
- targetWindow.getSelection().addRange(r1);
-
- var r2 = targetDocument.createRange();
- r2.setStart(targetDocument.getElementById("in1"), 0);
- r2.setEnd (targetDocument.getElementById("in2"), 0);
- targetWindow.getSelection().addRange(r2);
-
- targetDocument.execCommand('removeformat', false, null);
- targetDocument.execCommand('outdent', false, null);
-}
-
-function init()
-{
- setTimeout(function()
- {
- var fd = window.frames[0].document;
- fd.body.appendChild(fd.importNode(document.getElementById('rootish'), true));
- fd.designMode = 'on';
- foop(window.frames[0]);
- document.documentElement.removeAttribute("class");
- }, 100);
-}
-
-]]>
-</script>
-</head>
-
-<body onload="init()">
-
-<iframe src="data:text/html," style="width: 95%; height: 500px;"/>
-
-<div id="rootish">
-<div id="out1"/>
-<div id="in1"/>
-<div id="in2"/>
-<div id="out2"/>
-</div>
-
-</body>
-</html> \ No newline at end of file
diff --git a/editor/libeditor/crashtests/336104.html b/editor/libeditor/crashtests/336104.html
deleted file mode 100644
index 32f11b745..000000000
--- a/editor/libeditor/crashtests/336104.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<script>
-function init()
-{
- var targetWindow = window.frames[0];
- var targetDocument = targetWindow.document;
- var rootish = document.getElementById('rootish');
-
- targetDocument.body.appendChild(targetDocument.adoptNode(rootish));
- targetDocument.designMode = 'on';
-
- targetWindow.getSelection().removeAllRanges();
-
- var r = targetDocument.createRange();
- r.setStart(targetDocument.getElementById("start"), 0);
- r.setEnd (targetDocument.getElementById("endparent").firstChild, 0);
- targetWindow.getSelection().addRange(r);
-
- targetDocument.execCommand('outdent', false, null);
-}
-</script>
-
-</head>
-
-<body onload="setTimeout(init, 300);">
-
-<iframe src="data:text/html," style="width: 95%; height: 500px;"></iframe>
-
-<div id="rootish">
- <div id="start"></div>
- <p>Huh</p>
- <svg xmlns="http://www.w3.org/2000/svg" id="endparent"> </svg>
-</div>
-
-</body>
-</html>
diff --git a/editor/libeditor/crashtests/382527-1.html b/editor/libeditor/crashtests/382527-1.html
deleted file mode 100644
index 2441dcd87..000000000
--- a/editor/libeditor/crashtests/382527-1.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-<head>
-<script>
-
-
-function init1()
-{
- targetIframe = document.createElementNS('http://www.w3.org/1999/xhtml', 'iframe');
- targetIframe.src = "data:text/html,";
- targetIframe.setAttribute("style", "width: 300px; height: 200px; border: 1px dotted green;");
- targetIframe.addEventListener("load", init2, false);
- document.body.appendChild(targetIframe);
-}
-
-
-function init2()
-{
- targetWindow = targetIframe.contentWindow;
- targetDocument = targetWindow.document;
-
- var div = document.getElementById("div");
- textNode = div.firstChild;
-
- targetDocument.body.appendChild(targetDocument.adoptNode(div, true));
-
- targetDocument.designMode = 'on';
- setTimeout(init3, 0);
-}
-
-
-function init3()
-{
- var rng = targetDocument.createRange();
- rng.setStart(textNode, 1);
- rng.setEnd(textNode, 1);
- targetWindow.getSelection().addRange(rng);
-
- try {
- targetDocument.execCommand("inserthtml", false, "<p>");
- } catch(e) {}
-
- document.documentElement.removeAttribute("class");
-}
-
-
-</script>
-
-</head>
-
-<body onload="init1();">
-
-<div id="div"> </div>
-
-<script>
-</script>
-</body>
-</html>
diff --git a/editor/libeditor/crashtests/382778-1.html b/editor/libeditor/crashtests/382778-1.html
deleted file mode 100644
index 960b16630..000000000
--- a/editor/libeditor/crashtests/382778-1.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-<head>
-<script>
-
-function init1()
-{
- // Create an html:iframe in HTML mode (so designMode can be used 320092)
- targetIframe = document.createElementNS('http://www.w3.org/1999/xhtml', 'iframe');
- targetIframe.src = "data:text/html,";
- targetIframe.setAttribute("style", "width: 700px; height: 500px; border: 1px dotted green;");
- targetIframe.addEventListener("load", init2, false);
- document.body.appendChild(targetIframe);
-}
-
-
-function init2()
-{
- targetWindow = targetIframe.contentWindow;
- targetDocument = targetWindow.document;
-
- p = document.getElementById("p");
- pText = p.firstChild;
-
- targetDocument.body.appendChild(targetDocument.adoptNode(p, true));
-
- targetDocument.designMode = 'on';
-
- setTimeout(boom, 0);
-}
-
-
-function boom()
-{
- var rng = targetDocument.createRange();
- rng.setStart(pText, 3);
- rng.setEnd(pText, 3);
-
- targetWindow.getSelection().addRange(rng);
-
- targetDocument.execCommand("insertorderedlist", false, null);
-
- document.documentElement.removeAttribute("class")
-}
-
-</script>
-</head>
-
-<body onload="init1();">
-<p id="p">word word</p>
-</body>
-
-</html>
diff --git a/editor/libeditor/crashtests/402172-1.html b/editor/libeditor/crashtests/402172-1.html
deleted file mode 100644
index 4022523fa..000000000
--- a/editor/libeditor/crashtests/402172-1.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<html>
-<head>
-<script>
-
-function boom()
-{
- document.getElementById("div").contentEditable = "true";
- document.getElementById("div").focus();
- document.getElementById("div").contentEditable = "false";
-
- document.getElementById("table").contentEditable = "true";
-}
-
-</script>
-</head>
-
-<body onload="boom();">
-
-<table id="table"><td></td></table><div id="div"></div>
-
-</body>
-
-</html>
diff --git a/editor/libeditor/crashtests/403965-1.xhtml b/editor/libeditor/crashtests/403965-1.xhtml
deleted file mode 100644
index 02993914d..000000000
--- a/editor/libeditor/crashtests/403965-1.xhtml
+++ /dev/null
@@ -1,7 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-<tbody contenteditable="true"/>
-<frameset/>
-<xul:box onbeforecopy="event.explicitOriginalTarget.parentNode.parentNode.removeChild(event.explicitOriginalTarget.parentNode)">
-<xul:box/>
-</xul:box>
-</html> \ No newline at end of file
diff --git a/editor/libeditor/crashtests/407074-1.html b/editor/libeditor/crashtests/407074-1.html
deleted file mode 100644
index 22f172856..000000000
--- a/editor/libeditor/crashtests/407074-1.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<html>
-<head>
-</head>
-
-<body onload="try { document.execCommand('inserthtml', false, '0'); } catch(e) { }"><span id="textarea" contenteditable="true">is</span></body>
-
-</html>
diff --git a/editor/libeditor/crashtests/407079-1.html b/editor/libeditor/crashtests/407079-1.html
deleted file mode 100644
index 8b0e36cd6..000000000
--- a/editor/libeditor/crashtests/407079-1.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<html>
-<head>
-<script type="text/javascript">
-
-function boom()
-{
- document.execCommand("selectAll", false, null);
- document.execCommand("inserthtml", false, "<p>");
-}
-
-</script>
-</head>
-
-<body onload="boom();"><textarea contenteditable="true"></textarea></body>
-</html>
diff --git a/editor/libeditor/crashtests/407256-1.html b/editor/libeditor/crashtests/407256-1.html
deleted file mode 100644
index 824162ac5..000000000
--- a/editor/libeditor/crashtests/407256-1.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<html>
-<head>
-<script type="text/javascript">
-
-function boom()
-{
- document.addEventListener("DOMNodeInserted", x, false);
-
- function x()
- {
- document.removeEventListener("DOMNodeInserted", x, false);
- document.execCommand("insertParagraph", false, "");
- }
-
- document.execCommand("insertorderedlist", false, "");
-}
-
-</script>
-</head>
-
-<body contenteditable="true" onload="boom()"></body>
-
-</html>
diff --git a/editor/libeditor/crashtests/407277-1.html b/editor/libeditor/crashtests/407277-1.html
deleted file mode 100644
index 41c6bf280..000000000
--- a/editor/libeditor/crashtests/407277-1.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<html>
-<head>
-</head>
-<body style="margin: initial;"
- contenteditable="true"
- onload="document.execCommand('outdent', false, null);"></body>
-</html>
diff --git a/editor/libeditor/crashtests/414178-1.html b/editor/libeditor/crashtests/414178-1.html
deleted file mode 100644
index 19cc205b9..000000000
--- a/editor/libeditor/crashtests/414178-1.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script type="text/javascript">
-
-function boom()
-{
- var table = document.createElement("table");
- document.body.appendChild(table);
- table.contentEditable = "true";
- table.focus();
- try {
- // This will throw, since it's attempting to inject a list inside a table
- document.execCommand("insertunorderedlist", false, null);
- } catch (e) {}
-}
-
-</script>
-</head>
-
-<body onload="boom();"></body>
-</html>
diff --git a/editor/libeditor/crashtests/418923-1.html b/editor/libeditor/crashtests/418923-1.html
deleted file mode 100644
index 786ea25d9..000000000
--- a/editor/libeditor/crashtests/418923-1.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<html><head><script type="text/javascript">
-
-function boom()
-{
- var dE = document.documentElement;
- var head = document.getElementsByTagName("head")[0];
- dE.removeChild(document.body);
- dE.contentEditable = "true";
- dE.focus();
- dE.contentEditable = "false";
- head.focus();
- head.contentEditable = "true";
- try {
- document.execCommand("selectAll", false, "");
- } catch(e) {
- }
-}
-
-</script></head><body onload="boom();"></body></html> \ No newline at end of file
diff --git a/editor/libeditor/crashtests/420439.html b/editor/libeditor/crashtests/420439.html
deleted file mode 100644
index e1303307d..000000000
--- a/editor/libeditor/crashtests/420439.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<html>
-<head>
-<script type="text/javascript">
-
-function boom()
-{
- function x()
- {
- document.removeEventListener("DOMAttrModified", x, false);
- document.execCommand("backcolor", false, "green");
- }
-
- document.getElementById("td").focus();
-
- document.addEventListener("DOMAttrModified", x, false);
- try {
- document.execCommand("subscript", false, null);
- } catch(e) {
- }
- document.removeEventListener("DOMAttrModified", x, false);
-}
-
-</script>
-</head>
-
-<body contenteditable="true" onload="setTimeout(boom, 30);">
-<table><tbody contenteditable="false"><tr><td contenteditable="true" id="td"></td></tr></tbody></table>
-</body>
-
-</html>
diff --git a/editor/libeditor/crashtests/428489-1.html b/editor/libeditor/crashtests/428489-1.html
deleted file mode 100644
index 8eec1268b..000000000
--- a/editor/libeditor/crashtests/428489-1.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<html>
-<head>
-<title>Crash [@ nsHTMLEditor::GetPositionAndDimensions] when window gets removed during click on contenteditable absolute positioned element</title>
-</head>
-<body>
-<iframe id="content" src="data:text/html;charset=utf-8,%3Chtml%3E%3Chead%3E%0A%3Cscript%3E%0Awindow.addEventListener%28%27DOMAttrModified%27%2C%20function%28e%29%20%7Bdump%28%27DOMAttrModified\n%27%29%3Bwindow.frameElement.parentNode.removeChild%28window.frameElement%29%3B%7D%2C%20true%29%3B%0A%3C/script%3E%0A%3C/head%3E%0A%3Cbody%3E%0A%3Cdiv%20style%3D%22position%3A%20absolute%3B%22%20contenteditable%3D%22true%22%3EClicking%20on%20this%20should%20not%20crash%20Mozilla%0A%3C/body%3E%0A%3C/html%3E" style="width:1000px;height: 300px;"></iframe>
-</body>
-</html>
diff --git a/editor/libeditor/crashtests/429586-1.html b/editor/libeditor/crashtests/429586-1.html
deleted file mode 100644
index a32df3b72..000000000
--- a/editor/libeditor/crashtests/429586-1.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<html>
-<head>
-<title>Bug 429586 - Crash [@ nsEditor::EndUpdateViewBatch] with pasting and domattrmodified removing iframe</title>
-</head>
-<body>
-<iframe id="content" src="data:text/html;charset=utf-8,%3Chtml%3E%0A%3Chead%3E%0A%3C/head%3E%0A%3Cbody%20contenteditable%3D%22true%22%3E%0A%0A%3Cscript%3E%0Afunction%20dokey%28%29%7B%0Adocument.body.focus%28%29%3B%0Adocument.execCommand%28%27insertParagraph%27%2C%20false%2C%20%27%27%29%3B%0A%7D%0AsetTimeout%28dokey%2C200%29%3B%0A%0Adocument.addEventListener%28%27DOMAttrModified%27%2C%20function%28%29%20%7Bwindow.frameElement.parentNode.removeChild%28window.frameElement%29%7D%2C%20true%29%3B%0A%3C/script%3E%0A%3C/body%3E%0A%3C/html%3E"></iframe>
-</body>
-</html>
diff --git a/editor/libeditor/crashtests/430624-1.html b/editor/libeditor/crashtests/430624-1.html
deleted file mode 100644
index bfa95c662..000000000
--- a/editor/libeditor/crashtests/430624-1.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<html>
-<head>
-<script>
-function crash() {
- window.frames[0].onload = null;
- window.frames[0].location = 'data:text/html;charset=utf-8,2nd%20page';
-}
-</script>
-</head>
-<body onload="crash()">
- <!-- iframe contents: <html><body onload="document.body.setAttribute('spellcheck', true);"></body></html> -->
- <iframe src="data:text/html;charset=utf-8;base64,PGh0bWw%2BPGJvZHkgb25sb2FkPSJkb2N1bWVudC5ib2R5LnNldEF0dHJpYnV0ZSgnc3BlbGxjaGVjaycsIHRydWUpOyI%2BPC9ib2R5PjwvaHRtbD4%3D"></iframe>
-</body>
-</html> \ No newline at end of file
diff --git a/editor/libeditor/crashtests/431086-1.xhtml b/editor/libeditor/crashtests/431086-1.xhtml
deleted file mode 100644
index c6c5d8d99..000000000
--- a/editor/libeditor/crashtests/431086-1.xhtml
+++ /dev/null
@@ -1,22 +0,0 @@
-<div xmlns="http://www.w3.org/1999/xhtml">
-
-<script type="text/javascript">
-
-function boom()
-{
- var r = document.documentElement;
- r.style.position = "absolute";
- r.contentEditable = "true";
- r.focus();
- r.contentEditable = "false";
- r.focus();
- r.contentEditable = "true";
- document.execCommand("subscript", false, null);
- r.contentEditable = "false";
-}
-
-window.addEventListener("load", boom, false);
-
-</script>
-
-</div>
diff --git a/editor/libeditor/crashtests/448329-1.html b/editor/libeditor/crashtests/448329-1.html
deleted file mode 100644
index 99d0f63b3..000000000
--- a/editor/libeditor/crashtests/448329-1.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!DOCTYPE HTML>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <title>Testcase for bug 448329</title>
-</head>
-<body>
-
-<iframe id="frame448329"></iframe>
-
-<script>
-
-function test448329(id,cmd) {
-
- var elm = document.getElementById(id);
- var doc = elm.contentDocument;
- doc.designMode = "On";
-
- // Work around getSelection depending on a presshell but not flushing to get
- // one.
- doc.body.offsetWidth;
- var s = doc.defaultView.getSelection();
-
- // Test document node
- if (s.rangeCount > 0)
- s.removeAllRanges();
- var range = doc.createRange();
- range.setStart(doc, 0);
- range.setEnd(doc, 0);
- s.addRange(range);
- doc.queryCommandIndeterm(cmd);
-
- // Test HTML node
- if (s.rangeCount > 0)
- s.removeAllRanges();
- range = doc.createRange();
- range.setStart(doc.documentElement, 0);
- range.setEnd(doc.documentElement, 0);
- s.addRange(range);
- doc.queryCommandIndeterm(cmd);
-
- // Test BODY node
- if (s.rangeCount > 0)
- s.removeAllRanges();
- range = doc.createRange();
- var body = doc.documentElement.childNodes[1];
- range.setStart(body, 0);
- range.setEnd(body, 0);
- s.addRange(range);
- doc.queryCommandIndeterm(cmd);
-
- var text = doc.createTextNode("Hello Kitty");
- body.insertBefore(text, null)
-
- // Test TEXT node
- if (s.rangeCount > 0)
- s.removeAllRanges();
- range = doc.createRange();
- range.setStart(text, 0);
- range.setEnd(text, 1);
- s.addRange(range);
- doc.queryCommandIndeterm(cmd);
-
-}
-
-test448329("frame448329", "backcolor")
-test448329("frame448329", "hilitecolor")
-
-</script>
-
-
-</body>
-</html>
diff --git a/editor/libeditor/crashtests/448329-2.html b/editor/libeditor/crashtests/448329-2.html
deleted file mode 100644
index fd4707b54..000000000
--- a/editor/libeditor/crashtests/448329-2.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<html>
-<head>
- <title>Testcase for bug 448329</title>
-<script>
-function go() {
- test("myFrame", "backcolor");
-}
-function test(id,cmd) {
- var doc = document.getElementById(id).contentDocument;
- doc.designMode = "On";
-
- var s = doc.defaultView.getSelection();
- s.removeAllRanges();
- s.addRange(doc.createRange());
-
- doc.queryCommandIndeterm(cmd);
-}
-</script>
-</head>
-<body onload="go()"><iframe id="myFrame"></iframe></body>
-</html>
diff --git a/editor/libeditor/crashtests/448329-3.html b/editor/libeditor/crashtests/448329-3.html
deleted file mode 100644
index 0a48c1818..000000000
--- a/editor/libeditor/crashtests/448329-3.html
+++ /dev/null
@@ -1,112 +0,0 @@
-<!DOCTYPE HTML>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <title>Testcase #3 for bug 448329</title>
-</head>
-<body>
-
-<iframe id="frame448329"></iframe>
-
-<script>
-
-function test448329(id,cmd,val) {
-
- var elm = document.getElementById(id);
- var doc = elm.contentDocument;
- doc.designMode = "On";
-
- // Work around getSelection depending on a presshell but not flushing to get
- // one.
- doc.body.offsetWidth;
- var s = doc.defaultView.getSelection();
-
- // Test document node
- if (s.rangeCount > 0)
- s.removeAllRanges();
- var range = doc.createRange();
- range.setStart(doc, 0);
- range.setEnd(doc, 0);
- s.addRange(range);
- doc.execCommand(cmd,false,val);
-
- // Test HTML node
- if (s.rangeCount > 0)
- s.removeAllRanges();
- range = doc.createRange();
- range.setStart(doc.documentElement, 0);
- range.setEnd(doc.documentElement, 0);
- s.addRange(range);
- doc.execCommand(cmd,false,val);
-
- // Test BODY node
- if (s.rangeCount > 0)
- s.removeAllRanges();
- range = doc.createRange();
- var body = doc.documentElement.childNodes[1];
- range.setStart(body, 0);
- range.setEnd(body, 0);
- s.addRange(range);
- doc.execCommand(cmd,false,val);
-
- var text = doc.createTextNode("Hello Kitty");
- body.insertBefore(text, null)
-
- // Test TEXT node
- if (s.rangeCount > 0)
- s.removeAllRanges();
- range = doc.createRange();
- range.setStart(text, 0);
- range.setEnd(text, 1);
- s.addRange(range);
- doc.execCommand(cmd,false,val);
-
- // Test BODY[0,0] + TEXT node
- if (s.rangeCount > 0)
- s.removeAllRanges();
- range = doc.createRange();
- range.setStart(body, 0);
- range.setEnd(body, 0);
- s.addRange(range);
- range = doc.createRange();
- range.setStart(text, 0);
- range.setEnd(text, 1);
- s.addRange(range);
- doc.execCommand(cmd,false,val);
-
- // Test BODY[0,1] + TEXT node
- if (s.rangeCount > 0)
- s.removeAllRanges();
- range = doc.createRange();
- range.setStart(body, 0);
- range.setEnd(body, 1);
- s.addRange(range);
- range = doc.createRange();
- range.setStart(text, 0);
- range.setEnd(text, 1);
- s.addRange(range);
- doc.execCommand(cmd,false,val);
-
- // Test BODY[0,1] + TEXT node without a parent
- if (s.rangeCount > 0)
- s.removeAllRanges();
- range = doc.createRange();
- range.setStart(body, 0);
- range.setEnd(body, 1);
- s.addRange(range);
- range = doc.createRange();
- text = doc.createTextNode("Hello Kitty"); // not in doc
- range.setStart(text, 0);
- range.setEnd(text, 1);
- s.addRange(range);
- doc.execCommand(cmd,false,val);
-
-}
-
-test448329("frame448329", "backcolor", "green")
-test448329("frame448329", "hilitecolor", "green")
-
-</script>
-
-
-</body>
-</html>
diff --git a/editor/libeditor/crashtests/456727-1.html b/editor/libeditor/crashtests/456727-1.html
deleted file mode 100644
index d14422c93..000000000
--- a/editor/libeditor/crashtests/456727-1.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<html>
-<BODY onload="
-document.designMode='on';
-document.replaceChild(document.createElement('HTML'), document.firstChild);
-document.queryCommandValue('backcolor');
-">
-</body>
-</html> \ No newline at end of file
diff --git a/editor/libeditor/crashtests/456727-2.html b/editor/libeditor/crashtests/456727-2.html
deleted file mode 100644
index 1c8fe5db9..000000000
--- a/editor/libeditor/crashtests/456727-2.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<html>
-<BODY onload="
-document.designMode='on';
-document.removeChild(document.firstChild);
-document.queryCommandState('BackColor');
-">
-</body>
-</html>
diff --git a/editor/libeditor/crashtests/459613-iframe.html b/editor/libeditor/crashtests/459613-iframe.html
deleted file mode 100644
index 9f6e558d0..000000000
--- a/editor/libeditor/crashtests/459613-iframe.html
+++ /dev/null
@@ -1 +0,0 @@
-<html><body><textarea>notaword</textarea></body></html>
diff --git a/editor/libeditor/crashtests/459613.html b/editor/libeditor/crashtests/459613.html
deleted file mode 100644
index 7a335f22e..000000000
--- a/editor/libeditor/crashtests/459613.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<html class="reftest-wait">
-<head>
-<script type="text/javascript">
-
-function finish() {
- document.documentElement.removeAttribute("class");
-}
-
-</script>
-</head>
-
-<body>
-
-<iframe src="459613-iframe.html" onload="finish();"></iframe>
-
-</body>
-</html>
diff --git a/editor/libeditor/crashtests/467647-1.html b/editor/libeditor/crashtests/467647-1.html
deleted file mode 100644
index 7bb4271d7..000000000
--- a/editor/libeditor/crashtests/467647-1.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script type="text/javascript">
-
-function boom()
-{
- document.getElementById("s").focus();
- try {
- document.execCommand("insertorderedlist", false, null);
- } catch(e) { }
-}
-
-</script>
-</head>
-
-<body onload="boom();"><span id="s" contenteditable="true">One<div></div></span><marquee></marquee></body>
-
-</html>
diff --git a/editor/libeditor/crashtests/475132-1.xhtml b/editor/libeditor/crashtests/475132-1.xhtml
deleted file mode 100644
index 8b4dd688c..000000000
--- a/editor/libeditor/crashtests/475132-1.xhtml
+++ /dev/null
@@ -1,20 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<script type="text/javascript">
-
-function boom()
-{
- document.getElementsByTagName("td")[0].contentEditable = "true";
- document.getElementsByTagName("td")[0].focus();
- document.documentElement.contentEditable = "true";
- document.documentElement.focus();
- document.execCommand("indent", false, null);
- document.execCommand("insertParagraph", false, null);
-}
-
-</script>
-</head>
-
-<body onload="boom();" contenteditable="false"><td></td></body>
-
-</html>
diff --git a/editor/libeditor/crashtests/499844-1.html b/editor/libeditor/crashtests/499844-1.html
deleted file mode 100644
index 4fa509c4a..000000000
--- a/editor/libeditor/crashtests/499844-1.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<html>
-<head>
-<script type="text/javascript">
-
-function boom()
-{
- document.body.contentEditable = "true";
- document.execCommand("outdent", false, null);
-}
-
-</script>
-</head>
-
-<body style="word-spacing: 3px;" onload="boom();"> &#x0301;</body>
-</html>
diff --git a/editor/libeditor/crashtests/503709-1.xhtml b/editor/libeditor/crashtests/503709-1.xhtml
deleted file mode 100644
index 867bebf1a..000000000
--- a/editor/libeditor/crashtests/503709-1.xhtml
+++ /dev/null
@@ -1,11 +0,0 @@
-<html contenteditable="true" xmlns="http://www.w3.org/1999/xhtml"><head><script>
-
-function boom()
-{
- document.execCommand("selectAll", false, "");
- try { document.execCommand("justifyfull", false, null); } catch(e) { }
- try { document.execCommand("inserthorizontalrule", false, "false"); } catch(e) { }
- document.execCommand("delete", false, null);
-}
-
-</script></head>x y z<body onload="boom();"><div/></body></html>
diff --git a/editor/libeditor/crashtests/513375-1.xhtml b/editor/libeditor/crashtests/513375-1.xhtml
deleted file mode 100644
index 25e5e1c34..000000000
--- a/editor/libeditor/crashtests/513375-1.xhtml
+++ /dev/null
@@ -1,19 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head contenteditable="true">
-<script type="text/javascript">
-<![CDATA[
-
-function boom()
-{
- var r = document.createRange();
- r.selectNode(document.body);
- r.deleteContents();
- try { document.execCommand("selectAll", false, null); } catch(e) { }
-}
-
-]]>
-</script>
-</head>
-
-<body onload="boom();" contenteditable="true"></body>
-</html>
diff --git a/editor/libeditor/crashtests/535632-1.xhtml b/editor/libeditor/crashtests/535632-1.xhtml
deleted file mode 100644
index 92470b825..000000000
--- a/editor/libeditor/crashtests/535632-1.xhtml
+++ /dev/null
@@ -1 +0,0 @@
-<body xmlns="http://www.w3.org/1999/xhtml" style="margin: 200px;" contenteditable="true" onload="document.execCommand('outdent', false, null);" /> \ No newline at end of file
diff --git a/editor/libeditor/crashtests/574558-1.xhtml b/editor/libeditor/crashtests/574558-1.xhtml
deleted file mode 100644
index 6aac47072..000000000
--- a/editor/libeditor/crashtests/574558-1.xhtml
+++ /dev/null
@@ -1,15 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml"><head><script>
-<![CDATA[
-
-function boom()
-{
- document.execCommand("selectAll", false, null);
- document.execCommand("selectAll", false, null);
- document.execCommand("inserthtml", false, "<span><div>");
- var textarea = document.getElementById("textarea");
- var span = document.createElementNS("http://www.w3.org/1999/xhtml", "span");
- textarea.appendChild(span);
-}
-
-]]>
-</script></head><div contenteditable="true"></div><body onload="boom();"><textarea id="textarea">f</textarea></body></html>
diff --git a/editor/libeditor/crashtests/580151-1.xhtml b/editor/libeditor/crashtests/580151-1.xhtml
deleted file mode 100644
index 379941111..000000000
--- a/editor/libeditor/crashtests/580151-1.xhtml
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
-
-var t;
-
-function boom()
-{
- var b = document.createElementNS("http://www.w3.org/1999/xhtml", "body");
- t = document.createElementNS("http://www.w3.org/1999/xhtml", "textarea");
- b.appendChild(t);
- document.removeChild(document.documentElement)
- document.appendChild(b)
- document.removeChild(document.documentElement)
- var ns = document.createElementNS("http://www.w3.org/1999/xhtml", "script");
- var nt = document.createTextNode("t.appendChild(document.createTextNode(' '));");
- ns.appendChild(nt);
- b.appendChild(ns);
- document.appendChild(b);
-}
-
-</script>
-</head>
-<body onload="boom();"></body>
-</html>
diff --git a/editor/libeditor/crashtests/582138-1.xhtml b/editor/libeditor/crashtests/582138-1.xhtml
deleted file mode 100644
index afcec2eba..000000000
--- a/editor/libeditor/crashtests/582138-1.xhtml
+++ /dev/null
@@ -1,10 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml"><mtr xmlns="http://www.w3.org/1998/Math/MathML"><td id="cell" xmlns="http://www.w3.org/1999/xhtml"></td></mtr><script>
-function boom()
-{
- document.getElementById("cell").contentEditable = true;
- document.getElementById("cell").focus();
- document.execCommand("inserthtml", false, "x");
-}
-
-window.addEventListener("load", boom, false);
-</script></html>
diff --git a/editor/libeditor/crashtests/612565-1.html b/editor/libeditor/crashtests/612565-1.html
deleted file mode 100644
index 1b059aa66..000000000
--- a/editor/libeditor/crashtests/612565-1.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <iframe></iframe>
- </body>
- <script>
- onload = function() {
- var i = document.querySelector("iframe");
- var doc = i.contentDocument;
- doc.body.appendChild(doc.createTextNode("foo"));
- doc.designMode = "on";
- while (doc.body.firstChild) {
- doc.body.removeChild(doc.body.firstChild);
- }
- };
- </script>
-</html>
diff --git a/editor/libeditor/crashtests/615015-1.html b/editor/libeditor/crashtests/615015-1.html
deleted file mode 100644
index a383f9e75..000000000
--- a/editor/libeditor/crashtests/615015-1.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
-
-function boom()
-{
- document.getElementById("j").focus();
- try {
- document.execCommand("insertunorderedlist", false, null);
- } catch(e) { }
-}
-
-</script>
-</head>
-<body onload="boom();"><span><span contenteditable id="j"></span>T</span></body>
-</html>
diff --git a/editor/libeditor/crashtests/615450-1.html b/editor/libeditor/crashtests/615450-1.html
deleted file mode 100644
index fb36bddc9..000000000
--- a/editor/libeditor/crashtests/615450-1.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<html contenteditable="true">
-<head>
-<script>
-
-function boom()
-{
- document.documentElement.appendChild(document.body);
- document.documentElement.contentEditable = "false";
- try { document.execCommand("outdent", false, null); } catch(e) { }
- document.body.contentEditable = "true";
- try { document.execCommand("inserthtml", false, "x"); } catch(e) { }
-}
-
-</script>
-</head>
-<body onload="boom();"><div style="margin-left: 40px;"><span contenteditable="true">p q r s</span> T</div></body></html>
diff --git a/editor/libeditor/crashtests/633709.xhtml b/editor/libeditor/crashtests/633709.xhtml
deleted file mode 100644
index 139389001..000000000
--- a/editor/libeditor/crashtests/633709.xhtml
+++ /dev/null
@@ -1,36 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
-
-<body><div contenteditable="true"></div><div><input id="i"><div></div></input></div></body>
-
-<script id="s">
-<![CDATA[
-
-function boom()
-{
- document.getElementById("i").focus();
-
- try { document.execCommand("stylewithcss", false, "true") } catch(e) { }
- try { document.execCommand("inserthtml", false, "<x>X</x>"); } catch(e) { }
- try { document.execCommand("underline", false, null); } catch(e) { }
- try { document.execCommand("justifyfull", false, null); } catch(e) { }
- try { document.execCommand("underline", false, null); } catch(e) { }
- try { document.execCommand("insertParagraph", false, null); } catch(e) { }
- try { document.execCommand("delete", false, null); } catch(e) { }
-
- try { document.execCommand("stylewithcss", false, "false") } catch(e) { }
- try { document.execCommand("inserthtml", false, "<x>X</x>"); } catch(e) { }
- try { document.execCommand("underline", false, null); } catch(e) { }
- try { document.execCommand("justifyfull", false, null); } catch(e) { }
- try { document.execCommand("underline", false, null); } catch(e) { }
- try { document.execCommand("insertParagraph", false, null); } catch(e) { }
- try { document.execCommand("delete", false, null); } catch(e) { }
-
- document.documentElement.removeAttribute("class");
-}
-
-setTimeout(boom, 10);
-
-]]>
-</script>
-
-</html>
diff --git a/editor/libeditor/crashtests/636074-1.html b/editor/libeditor/crashtests/636074-1.html
deleted file mode 100644
index e99c42ea6..000000000
--- a/editor/libeditor/crashtests/636074-1.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
-
-function boom()
-{
- document.getElementById("i").focus();
- document.documentElement.contentEditable = "true";
- document.execCommand("inserthtml", false, "<table>");
- document.execCommand("indent", false, null);
- document.execCommand("delete", false, null);
-}
-
-</script>
-</head>
-<body onload="boom();"><input id="i"></body>
-</html>
diff --git a/editor/libeditor/crashtests/639736-1.xhtml b/editor/libeditor/crashtests/639736-1.xhtml
deleted file mode 100644
index 4692daee7..000000000
--- a/editor/libeditor/crashtests/639736-1.xhtml
+++ /dev/null
@@ -1,14 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<script>
-
-function boom()
-{
- try { document.execCommand("removeformat", false, null); } catch(e) { }
- document.adoptNode(document.documentElement);
-}
-
-</script>
-</head>
-<body onload="boom();"><td contenteditable="true" /></body>
-</html>
diff --git a/editor/libeditor/crashtests/643786-1.html b/editor/libeditor/crashtests/643786-1.html
deleted file mode 100644
index 3f0b27a54..000000000
--- a/editor/libeditor/crashtests/643786-1.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
-
-function boom()
-{
- var f = document.getElementById("f");
- var fw = f.contentWindow;
- fw.document.designMode = 'on';
- f.style.content = "'m'";
- fw.document.removeChild(fw.document.documentElement)
-}
-
-</script>
-</head>
-<body onload="boom();"><iframe id="f" src="data:text/html,"></iframe></body>
-</html>
diff --git a/editor/libeditor/crashtests/650572-1.html b/editor/libeditor/crashtests/650572-1.html
deleted file mode 100644
index a86f6e618..000000000
--- a/editor/libeditor/crashtests/650572-1.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
-
-function boom()
-{
- document.documentElement.offsetHeight;
- document.getElementById("d").focus();
- document.getElementById("b").style.display = "inline";
- document.getElementById("c").contentEditable = "false";
-}
-
-</script>
-</head>
-<body contenteditable="true" id="b" onload="setTimeout(boom, 200);"><div id="c"><input id="d"></div></body>
-</html>
-
diff --git a/editor/libeditor/crashtests/667321-1.html b/editor/libeditor/crashtests/667321-1.html
deleted file mode 100644
index 275269522..000000000
--- a/editor/libeditor/crashtests/667321-1.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
-
-function boom()
-{
- document.body.style.cssFloat = "left";
- document.createElement("div").appendChild(document.querySelector("legend"));
-}
-
-</script>
-</head>
-<body onload="boom();"><fieldset><legend></legend><textarea></textarea></fieldset></body>
-</html>
diff --git a/editor/libeditor/crashtests/682650-1.html b/editor/libeditor/crashtests/682650-1.html
deleted file mode 100644
index 66ebc2f62..000000000
--- a/editor/libeditor/crashtests/682650-1.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
-
-function repeatChar(s, n)
-{
- while (s.length < n)
- s += s;
- return s.substr(0, n);
-}
-
-function boom()
-{
- document.documentElement.contentEditable = "true";
- document.execCommand("inserthtml", false, "<button><\/button>");
- document.execCommand("inserthtml", false, repeatChar("i", 34646));
- document.execCommand("contentReadOnly", false, null);
- document.execCommand("removeformat", false, null);
- document.execCommand("hilitecolor", false, "red");
- document.execCommand("inserthtml", false, "a");
- document.execCommand("delete", false, null);
-}
-
-</script>
-</head>
-
-<body onload="boom();"></body>
-
-</html>
diff --git a/editor/libeditor/crashtests/713427-1.html b/editor/libeditor/crashtests/713427-1.html
deleted file mode 100644
index 21da24693..000000000
--- a/editor/libeditor/crashtests/713427-1.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<span>
-<script contenteditable="true"></script>
-<blockquote>
-<input>
-<code style="display: table-row;">
-<html contenteditable="true">
-</blockquote>
-
-
diff --git a/editor/libeditor/crashtests/713427-2.xhtml b/editor/libeditor/crashtests/713427-2.xhtml
deleted file mode 100644
index b04a5d773..000000000
--- a/editor/libeditor/crashtests/713427-2.xhtml
+++ /dev/null
@@ -1,28 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<script>
-<![CDATA[
-
-function boom()
-{
- while (document.documentElement.firstChild) {
- document.documentElement.removeChild(document.documentElement.firstChild);
- }
-
- var td = document.createElementNS("http://www.w3.org/1999/xhtml", "td");
- td.setAttributeNS(null, "contenteditable", "true");
- (document.documentElement).appendChild(td);
- var head = document.createElementNS("http://www.w3.org/1999/xhtml", "head");
- (document.documentElement).appendChild(head);
-
- head.appendChild(td);
-}
-
-window.addEventListener("load", boom, false);
-
-]]>
-</script>
-</head>
-
-<body></body>
-</html>
diff --git a/editor/libeditor/crashtests/716456-1.html b/editor/libeditor/crashtests/716456-1.html
deleted file mode 100644
index a5ef5a2cc..000000000
--- a/editor/libeditor/crashtests/716456-1.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-<head>
-<script>
-
-function boom()
-{
- var div = document.querySelector("div");
- div.contentEditable = "true";
- div.focus();
-
- var r = document.documentElement;
- document["removeChild"](r);
- document["appendChild"](r);
-
- setTimeout(function() {
- getSelection().collapse(div, 0);
- document.execCommand("inserthtml", false, "a");
- setTimeout(function() {
- document.documentElement.removeAttribute("class");
- }, 0);
- }, 0);
-}
-
-</script>
-</head>
-
-<body onload="boom();"><div></div></body>
-</html>
diff --git a/editor/libeditor/crashtests/759748.html b/editor/libeditor/crashtests/759748.html
deleted file mode 100644
index 1e85a3877..000000000
--- a/editor/libeditor/crashtests/759748.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!doctype html>
-<body>
-<script>
-var cmds = {
- bold: "",
- italic: "",
- underline: "",
- strikethrough: "",
- subscript: "",
- superscript: "",
- cut: "",
- copy: "",
- paste: "",
- delete: "",
- forwarddelete: "",
- selectall: "",
- undo: "",
- redo: "",
- indent: "",
- outdent: "",
- backcolor: "#888888",
- forecolor: "#888888",
- hilitecolor: "#888888",
- fontname: "Courier",
- fontsize: "6",
- increasefontsize: "",
- decreasefontsize: "",
- inserthorizontalrule: "",
- createlink: "foo",
- insertimage: "foo",
- inserthtml: "foo",
- inserttext: "foo",
- insertparagraph: "",
- gethtml: "",
- justifyleft: "",
- justifyright: "",
- justifycenter: "",
- justifyfull: "",
- removeformat: "",
- unlink: "",
- insertorderedlist: "",
- insertunorderedlist: "",
- formatblock: "h1",
- heading: "h1",
- stylewithcss: "true",
- usecss: "true",
- contentreadonly: "true",
- readonly: "true",
- insertbronreturn: "true",
- enableobjectresizing: "true",
- enableinlinetableediting: "true",
-};
-for (var k in cmds) {
- document.body.innerHTML = "<div contenteditable>abc</div>";
- getSelection().removeAllRanges();
- try { document.execCommand(k, false, cmds[k]) } catch(e) {}
-}
-</script>
diff --git a/editor/libeditor/crashtests/761861.html b/editor/libeditor/crashtests/761861.html
deleted file mode 100644
index 0c1f3f521..000000000
--- a/editor/libeditor/crashtests/761861.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!doctype html>
-<script>
-function boom() {
- var r = document.documentElement;
- while (r.firstChild) {
- r.removeChild(r.firstChild);
- }
-
- document.documentElement.contentEditable = "true";
- document.documentElement.appendChild(document.createElement("span"));
- document.documentElement.firstChild.appendChild(document.createTextNode("_"));
- document.execCommand("forwarddelete");
-}
-</script>
-<body onload="boom()">
diff --git a/editor/libeditor/crashtests/762183.html b/editor/libeditor/crashtests/762183.html
deleted file mode 100644
index 1916ac6fb..000000000
--- a/editor/libeditor/crashtests/762183.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<body contenteditable=true>x y
-<script>
-document.body.firstChild.splitText(2).splitText(1).splitText(1);
-getSelection().collapse(document.body, 1);
-document.execCommand("forwardDelete", false, null);
-</script>
diff --git a/editor/libeditor/crashtests/766305.html b/editor/libeditor/crashtests/766305.html
deleted file mode 100644
index a5000fe73..000000000
--- a/editor/libeditor/crashtests/766305.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
-
-function boom()
-{
- var s = "x";
- for (var i = 0; i < 15; ++i)
- s = s + s;
- var t = document.createTextNode(s);
- document.body.appendChild(t);
- window.getSelection().collapse(t, s.length);
- document.execCommand("insertText", false, "a");
-}
-
-</script>
-</head>
-
-<body contenteditable="true" onload="boom();"></body>
-</html>
diff --git a/editor/libeditor/crashtests/766360.html b/editor/libeditor/crashtests/766360.html
deleted file mode 100644
index 76c30456d..000000000
--- a/editor/libeditor/crashtests/766360.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
-
-function boom()
-{
- var r = document.createRange();
- r.setEnd(document.createTextNode("x"), 0);
- window.getSelection().addRange(r);
- document.execCommand("inserthtml", false, "y");
-}
-
-</script>
-</head>
-
-<body contenteditable="true" onload="boom();"></body>
-</html>
diff --git a/editor/libeditor/crashtests/766387.html b/editor/libeditor/crashtests/766387.html
deleted file mode 100644
index 20ccc60d4..000000000
--- a/editor/libeditor/crashtests/766387.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
-
-function boom()
-{
- window.getSelection().removeAllRanges();
- var r = document.createRange();
- r.setStart(document.getElementById("x"), 1);
- r.setEnd(document.getElementById("y"), 0);
- window.getSelection().addRange(r);
- document.execCommand("insertorderedlist", false, null);
-}
-
-</script>
-</head>
-
-<body onload="boom();"><div id="x" contenteditable="true">a</div><div id="y" contenteditable="true"></div></body>
-</html>
diff --git a/editor/libeditor/crashtests/766413.html b/editor/libeditor/crashtests/766413.html
deleted file mode 100644
index c5d9835e3..000000000
--- a/editor/libeditor/crashtests/766413.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
-
-function boom()
-{
- var root = document.documentElement;
- while (root.firstChild) {
- root.removeChild(root.firstChild);
- }
-
- var space = document.createTextNode(" ");
- var body = document.createElementNS("http://www.w3.org/1999/xhtml", "body");
- root.contentEditable = "true";
- root.focus();
- document.execCommand("contentReadOnly", false, null);
- root.appendChild(body);
- root.contentEditable = "false";
- root.appendChild(space);
- root.removeChild(body);
- root.contentEditable = "true";
-
- window.getSelection().removeAllRanges();
- var r1 = document.createRange();
- r1.setStart(root, 0);
- r1.setEnd(root, 0);
- window.getSelection().addRange(r1);
- looseText = document.createTextNode("c");
- var r2 = document.createRange();
- r2.setStart(looseText, 0);
- r2.setEnd(looseText, 0);
- window.getSelection().addRange(r2);
-
- document.execCommand("forwardDelete", false, null);
-}
-
-</script>
-</head>
-
-<body onload="boom();"></body>
-</html>
diff --git a/editor/libeditor/crashtests/766795.html b/editor/libeditor/crashtests/766795.html
deleted file mode 100644
index b4ade3020..000000000
--- a/editor/libeditor/crashtests/766795.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<html>
-<head>
-<script>
-
-function boom()
-{
- var fragEl = document.createElement("span");
- fragEl.setAttribute("contenteditable", "true");
- fragEl.setAttribute("style", "position: absolute;");
-
- var frag = document.createDocumentFragment();
- frag.appendChild(fragEl);
-
- window.getSelection().selectAllChildren(fragEl);
-}
-
-</script>
-</head>
-
-<body contenteditable="true" onload="boom();"></body>
-</html>
diff --git a/editor/libeditor/crashtests/766845.xhtml b/editor/libeditor/crashtests/766845.xhtml
deleted file mode 100644
index 409e21010..000000000
--- a/editor/libeditor/crashtests/766845.xhtml
+++ /dev/null
@@ -1,27 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<script>
-<![CDATA[
-
-function boom()
-{
- window.getSelection().removeAllRanges();
- var r1 = document.createRange();
- r1.setStart(document.body, 0);
- r1.setEnd (document.body, 1);
- window.getSelection().addRange(r1);
- var r2 = document.createRange();
- r2.setStart(document.body, 1);
- r2.setEnd (document.body, 2);
- window.getSelection().addRange(r2);
- if (document.queryCommandEnabled("inserthtml"))
- document.execCommand("inserthtml", false, "1");
-}
-
-]]>
-</script>
-</head>
-
-<body contenteditable="true" onload="boom();"><div></div><div></div></body>
-
-</html>
diff --git a/editor/libeditor/crashtests/767169.html b/editor/libeditor/crashtests/767169.html
deleted file mode 100644
index 3dfad160c..000000000
--- a/editor/libeditor/crashtests/767169.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<html>
-<head>
-<script>
-
-// Document must not have a doctype to trigger the bug
-
-function boom()
-{
- var root = document.documentElement;
- while (root.firstChild) { root.removeChild(root.firstChild); }
- root.contentEditable = "true";
- document.removeChild(root);
- document.appendChild(root);
- window.getSelection().collapse(root, 0);
- window.getSelection().extend(document, 1);
- document.removeChild(root);
-}
-
-</script>
-</head>
-
-<body onload="boom();"></body>
-</html>
diff --git a/editor/libeditor/crashtests/768748.html b/editor/libeditor/crashtests/768748.html
deleted file mode 100644
index 09206dce3..000000000
--- a/editor/libeditor/crashtests/768748.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!DOCTYPE html>
-<html contenteditable="true">
-<head>
-<script>
-
-function boom()
-{
- var looseText = document.createTextNode("x");
- window.getSelection().collapse(looseText, 0);
- document.queryCommandState("insertorderedlist");
-}
-
-</script>
-</head>
-<body onload="setTimeout(boom, 0)"></body>
-</html>
diff --git a/editor/libeditor/crashtests/768765.html b/editor/libeditor/crashtests/768765.html
deleted file mode 100644
index 060e5161b..000000000
--- a/editor/libeditor/crashtests/768765.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
-
-function boom()
-{
- var root = document.documentElement;
-
- while (root.firstChild) { root.removeChild(root.firstChild); }
-
- var body = document.createElementNS("http://www.w3.org/1999/xhtml", "body");
- var div = document.createElementNS("http://www.w3.org/1999/xhtml", "div");
- root.contentEditable = "true";
- root.appendChild(div);
- root.removeChild(div);
- root.insertBefore(body, root.firstChild);
-
- window.getSelection().removeAllRanges();
- var r0 = document.createRange();
- r0.setStart(body, 0);
- r0.setEnd(body, 0);
- window.getSelection().addRange(r0);
- var r1 = document.createRange();
- r1.setStart(div, 0);
- r1.setEnd(div, 0);
- window.getSelection().addRange(r1);
-
- document.execCommand("inserthtml", false, "1");
-}
-
-</script>
-</head>
-
-<body onload="boom();"></body>
-</html>
diff --git a/editor/libeditor/crashtests/769008-1.html b/editor/libeditor/crashtests/769008-1.html
deleted file mode 100644
index 8ea8a3601..000000000
--- a/editor/libeditor/crashtests/769008-1.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
-
-function boom()
-{
- var x = document.getElementById("x");
-
- window.getSelection().removeAllRanges();
-
- var range = document.createRange();
- range.setStart(x, 0);
- range.setEnd(x, 0);
- window.getSelection().addRange(range);
-
- document.execCommand("delete", false, "null");
-}
-
-</script>
-</head>
-<body contenteditable="true" onload="boom();"><div></div><span id="x"></span></body>
-</html>
diff --git a/editor/libeditor/crashtests/769967.xhtml b/editor/libeditor/crashtests/769967.xhtml
deleted file mode 100644
index 724f6b899..000000000
--- a/editor/libeditor/crashtests/769967.xhtml
+++ /dev/null
@@ -1,16 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml" contenteditable="true" style="-moz-user-select: all;"><sub>x</sub><script>
-function boom()
-{
- window.getSelection().removeAllRanges();
- var r = document.createRange();
- r.setStart(document.documentElement, 0);
- r.setEnd(document.documentElement, 0);
- window.getSelection().addRange(r);
-
- document.execCommand("subscript", false, null);
- document.execCommand("insertText", false, "y");
-}
-
-window.addEventListener("load", boom, false);
-
-</script></html>
diff --git a/editor/libeditor/crashtests/771749.html b/editor/libeditor/crashtests/771749.html
deleted file mode 100644
index 9237364f2..000000000
--- a/editor/libeditor/crashtests/771749.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
-
-function boom()
-{
- var root = document.documentElement;
- root.contentEditable = "true";
- document.removeChild(root);
- document.appendChild(root);
- document.execCommand("insertunorderedlist", false, null);
- document.execCommand("inserthtml", false, "<span></span>");
- document.execCommand("outdent", false, null);
-}
-
-</script>
-</head>
-
-<body onload="boom();"></body>
-</html>
diff --git a/editor/libeditor/crashtests/772282.html b/editor/libeditor/crashtests/772282.html
deleted file mode 100644
index f6259b344..000000000
--- a/editor/libeditor/crashtests/772282.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
-
-function boom()
-{
- var root = document.documentElement;
- while(root.firstChild) { root.removeChild(root.firstChild); }
- var body = document.createElementNS("http://www.w3.org/1999/xhtml", "body");
- body.setAttributeNS(null, "contenteditable", "true");
- var img = document.createElementNS("http://www.w3.org/1999/xhtml", "img");
- body.appendChild(img);
- root.appendChild(body);
- document.removeChild(root);
- document.appendChild(root);
- document.execCommand("insertText", false, "5");
- document.execCommand("selectAll", false, null);
- document.execCommand("insertParagraph", false, null);
- document.execCommand("increasefontsize", false, null);
-}
-
-</script>
-</head>
-
-<body onload="boom();"></body>
-</html>
diff --git a/editor/libeditor/crashtests/776323.html b/editor/libeditor/crashtests/776323.html
deleted file mode 100644
index 9fc2776c3..000000000
--- a/editor/libeditor/crashtests/776323.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html contenteditable="true">
-<head>
-<script>
-
-function boom()
-{
- document.execCommand("inserthtml", false, "b");
- var myrange = document.createRange();
- myrange.selectNodeContents(document.getElementsByTagName("img")[0]);
- window.getSelection().addRange(myrange);
- document.execCommand("strikethrough", false, null);
-}
-
-</script>
-</head>
-<body onload="boom();"><img></body>
-</html>
diff --git a/editor/libeditor/crashtests/793866.html b/editor/libeditor/crashtests/793866.html
deleted file mode 100644
index 4984474db..000000000
--- a/editor/libeditor/crashtests/793866.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
-
-function boom()
-{
- var b = document.body;
- b.contentEditable = "true";
- document.execCommand("contentReadOnly", false, null);
- b.focus();
- b.contentEditable = "false";
- document.documentElement.contentEditable = "true";
- document.createDocumentFragment().appendChild(b);
- document.documentElement.focus();
-}
-
-</script>
-</head>
-<body onload="boom();"></body>
-</html>
diff --git a/editor/libeditor/crashtests/crashtests.list b/editor/libeditor/crashtests/crashtests.list
deleted file mode 100644
index 7b1c57dbf..000000000
--- a/editor/libeditor/crashtests/crashtests.list
+++ /dev/null
@@ -1,72 +0,0 @@
-load 336081-1.xhtml
-load 336104.html
-load 382527-1.html
-load 382778-1.html
-load 402172-1.html
-load 403965-1.xhtml
-load 407074-1.html
-load 407079-1.html
-load 407256-1.html
-load 407277-1.html
-load 414178-1.html
-load 418923-1.html
-load 420439.html
-load 428489-1.html
-load 429586-1.html
-load 430624-1.html
-load 431086-1.xhtml
-load 448329-1.html
-load 448329-2.html
-load 448329-3.html
-load 456727-1.html
-load 456727-2.html
-load 459613.html
-needs-focus load 467647-1.html
-load 475132-1.xhtml
-load 499844-1.html
-load 503709-1.xhtml
-load 513375-1.xhtml
-load 535632-1.xhtml
-load 574558-1.xhtml
-load 580151-1.xhtml
-load 582138-1.xhtml
-load 612565-1.html
-load 615015-1.html
-load 615450-1.html
-load 633709.xhtml
-load 636074-1.html
-load 639736-1.xhtml
-load 643786-1.html
-load 650572-1.html
-load 667321-1.html
-load 682650-1.html
-load 713427-1.html
-load 713427-2.xhtml
-load 716456-1.html
-load 759748.html
-load 761861.html
-load 762183.html
-load 766305.html
-load 766360.html
-load 766387.html
-load 766413.html
-load 766795.html
-load 766845.xhtml
-load 767169.html
-load 768748.html
-load 768765.html
-load 769008-1.html
-load 769967.xhtml
-needs-focus load 771749.html
-load 772282.html
-load 776323.html
-needs-focus load 793866.html
-load 1057677.html
-needs-focus load 1128787.html
-load 1134545.html
-load 1158452.html
-load 1158651.html
-load 1244894.xhtml
-load 1272490.html
-load 1348851.html
-load 1317704.html
diff --git a/editor/libeditor/moz.build b/editor/libeditor/moz.build
deleted file mode 100644
index 1b5c3d97c..000000000
--- a/editor/libeditor/moz.build
+++ /dev/null
@@ -1,99 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-MOCHITEST_MANIFESTS += [
- 'tests/browserscope/mochitest.ini',
- 'tests/mochitest.ini',
-]
-
-MOCHITEST_CHROME_MANIFESTS += ['tests/chrome.ini']
-
-BROWSER_CHROME_MANIFESTS += ['tests/browser.ini']
-
-EXPORTS += [
- 'nsIEditRules.h',
-]
-
-EXPORTS.mozilla += [
- 'ChangeStyleTransaction.h',
- 'CSSEditUtils.h',
- 'EditorBase.h',
- 'EditorController.h',
- 'EditorUtils.h',
- 'EditTransactionBase.h',
- 'HTMLEditor.h',
- 'SelectionState.h',
- 'TextEditor.h',
- 'TextEditRules.h',
-]
-
-SOURCES += [
- 'ChangeAttributeTransaction.cpp',
- 'ChangeStyleTransaction.cpp',
- 'CompositionTransaction.cpp',
- 'CreateElementTransaction.cpp',
- 'CSSEditUtils.cpp',
- 'DeleteNodeTransaction.cpp',
- 'DeleteRangeTransaction.cpp',
- 'DeleteTextTransaction.cpp',
- 'EditAggregateTransaction.cpp',
- 'EditorBase.cpp',
- 'EditorCommands.cpp',
- 'EditorController.cpp',
- 'EditorEventListener.cpp',
- 'EditorUtils.cpp',
- 'EditTransactionBase.cpp',
- 'HTMLAbsPositionEditor.cpp',
- 'HTMLAnonymousNodeEditor.cpp',
- 'HTMLEditor.cpp',
- 'HTMLEditorDataTransfer.cpp',
- 'HTMLEditorEventListener.cpp',
- 'HTMLEditorObjectResizer.cpp',
- 'HTMLEditRules.cpp',
- 'HTMLEditUtils.cpp',
- 'HTMLInlineTableEditor.cpp',
- 'HTMLStyleEditor.cpp',
- 'HTMLTableEditor.cpp',
- 'HTMLURIRefObject.cpp',
- 'InsertNodeTransaction.cpp',
- 'InsertTextTransaction.cpp',
- 'InternetCiter.cpp',
- 'JoinNodeTransaction.cpp',
- 'PlaceholderTransaction.cpp',
- 'SelectionState.cpp',
- 'SetDocumentTitleTransaction.cpp',
- 'SplitNodeTransaction.cpp',
- 'StyleSheetTransactions.cpp',
- 'TextEditor.cpp',
- 'TextEditorDataTransfer.cpp',
- 'TextEditorTest.cpp',
- 'TextEditRules.cpp',
- 'TextEditRulesBidi.cpp',
- 'TextEditUtils.cpp',
- 'TypeInState.cpp',
- 'WSRunObject.cpp',
-]
-
-LOCAL_INCLUDES += [
- '/dom/base',
- '/editor/txmgr',
- '/layout/generic',
- '/layout/style',
- '/layout/tables',
- '/layout/xul',
- '/system/intl/spellcheck/src',
-]
-
-EXTRA_COMPONENTS += [
- 'EditorUtils.js',
- 'EditorUtils.manifest',
-]
-
-include('/ipc/chromium/chromium-config.mozbuild')
-
-FINAL_LIBRARY = 'xul'
-
-if CONFIG['GNU_CXX']:
- CXXFLAGS += ['-Wno-error=shadow']
diff --git a/editor/libeditor/nsIAbsorbingTransaction.h b/editor/libeditor/nsIAbsorbingTransaction.h
deleted file mode 100644
index 06329f3d4..000000000
--- a/editor/libeditor/nsIAbsorbingTransaction.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsIAbsorbingTransaction_h__
-#define nsIAbsorbingTransaction_h__
-
-#include "nsISupports.h"
-
-/*
-Transaction interface to outside world
-*/
-
-#define NS_IABSORBINGTRANSACTION_IID \
-{ /* a6cf9116-15b3-11d2-932e-00805f8add32 */ \
- 0xa6cf9116, \
- 0x15b3, \
- 0x11d2, \
- {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
-
-class nsIAtom;
-
-namespace mozilla {
-class EditorBase;
-class PlaceholderTransaction;
-class SelectionState;
-} // namespace mozilla
-
-/**
- * A transaction interface mixin - for transactions that can support.
- * the placeholder absorbtion idiom.
- */
-class nsIAbsorbingTransaction : public nsISupports{
-public:
-
- NS_DECLARE_STATIC_IID_ACCESSOR(NS_IABSORBINGTRANSACTION_IID)
-
- NS_IMETHOD EndPlaceHolderBatch()=0;
-
- NS_IMETHOD GetTxnName(nsIAtom **aName)=0;
-
- NS_IMETHOD StartSelectionEquals(mozilla::SelectionState* aSelState,
- bool* aResult) = 0;
-
- NS_IMETHOD ForwardEndBatchTo(nsIAbsorbingTransaction *aForwardingAddress)=0;
-
- NS_IMETHOD Commit()=0;
-
- NS_IMETHOD_(mozilla::PlaceholderTransaction*)
- AsPlaceholderTransaction() = 0;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsIAbsorbingTransaction,
- NS_IABSORBINGTRANSACTION_IID)
-
-#endif // nsIAbsorbingTransaction_h__
-
diff --git a/editor/libeditor/nsIEditRules.h b/editor/libeditor/nsIEditRules.h
deleted file mode 100644
index a493145cc..000000000
--- a/editor/libeditor/nsIEditRules.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsIEditRules_h
-#define nsIEditRules_h
-
-#define NS_IEDITRULES_IID \
-{ 0x3836386d, 0x806a, 0x488d, \
- { 0x8b, 0xab, 0xaf, 0x42, 0xbb, 0x4c, 0x90, 0x66 } }
-
-#include "mozilla/EditorBase.h" // for EditAction enum
-
-namespace mozilla {
-
-class TextEditor;
-namespace dom {
-class Selection;
-} // namespace dom
-
-/**
- * Base for an object to encapsulate any additional info needed to be passed
- * to rules system by the editor.
- */
-class RulesInfo
-{
-public:
- explicit RulesInfo(EditAction aAction)
- : action(aAction)
- {}
- virtual ~RulesInfo() {}
-
- EditAction action;
-};
-
-} // namespace mozilla
-
-/**
- * Interface of editing rules.
- */
-class nsIEditRules : public nsISupports
-{
-public:
- NS_DECLARE_STATIC_IID_ACCESSOR(NS_IEDITRULES_IID)
-
-//Interfaces for addref and release and queryinterface
-//NOTE: Use NS_DECL_ISUPPORTS_INHERITED in any class inherited from nsIEditRules
-
- NS_IMETHOD Init(mozilla::TextEditor* aTextEditor) = 0;
- NS_IMETHOD SetInitialValue(const nsAString& aValue) = 0;
- NS_IMETHOD DetachEditor() = 0;
- NS_IMETHOD BeforeEdit(EditAction action,
- nsIEditor::EDirection aDirection) = 0;
- NS_IMETHOD AfterEdit(EditAction action,
- nsIEditor::EDirection aDirection) = 0;
- NS_IMETHOD WillDoAction(mozilla::dom::Selection* aSelection,
- mozilla::RulesInfo* aInfo, bool* aCancel,
- bool* aHandled) = 0;
- NS_IMETHOD DidDoAction(mozilla::dom::Selection* aSelection,
- mozilla::RulesInfo* aInfo, nsresult aResult) = 0;
- NS_IMETHOD_(bool) DocumentIsEmpty() = 0;
- NS_IMETHOD DocumentModified() = 0;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsIEditRules, NS_IEDITRULES_IID)
-
-#endif // #ifndef nsIEditRules_h
diff --git a/editor/libeditor/tests/browser.ini b/editor/libeditor/tests/browser.ini
deleted file mode 100644
index bd234fc8d..000000000
--- a/editor/libeditor/tests/browser.ini
+++ /dev/null
@@ -1,8 +0,0 @@
-[browser_bug527935.js]
-skip-if = toolkit == 'android'
-support-files =
- bug527935.html
- bug527935_2.html
-[browser_bug629172.js]
-skip-if = toolkit == 'android'
-support-files = bug629172.html
diff --git a/editor/libeditor/tests/browser_bug527935.js b/editor/libeditor/tests/browser_bug527935.js
deleted file mode 100644
index dc6e74d3e..000000000
--- a/editor/libeditor/tests/browser_bug527935.js
+++ /dev/null
@@ -1,63 +0,0 @@
-add_task(function*() {
- yield new Promise(resolve => waitForFocus(resolve, window));
-
- const kPageURL = "http://example.org/browser/editor/libeditor/tests/bug527935.html";
- yield BrowserTestUtils.withNewTab({
- gBrowser,
- url: kPageURL
- }, function*(aBrowser) {
- var popupShown = false;
- function listener() {
- popupShown = true;
- }
- SpecialPowers.addAutoCompletePopupEventListener(window, "popupshowing", listener);
-
- yield ContentTask.spawn(aBrowser, {}, function*() {
- var window = content.window.wrappedJSObject;
- var document = window.document;
- var formTarget = document.getElementById("formTarget");
- var initValue = document.getElementById("initValue");
-
- window.loadPromise = new Promise(resolve => {
- formTarget.onload = resolve;
- });
-
- initValue.focus();
- initValue.value = "foo";
- });
-
- EventUtils.synthesizeKey("VK_RETURN", {});
-
- yield ContentTask.spawn(aBrowser, {}, function*() {
- var window = content.window.wrappedJSObject;
- var document = window.document;
-
- yield window.loadPromise;
-
- var newInput = document.createElement("input");
- newInput.setAttribute("name", "test");
- document.body.appendChild(newInput);
-
- var event = document.createEvent("KeyboardEvent");
-
- event.initKeyEvent("keypress", true, true, null, false, false,
- false, false, 0, "f".charCodeAt(0));
- newInput.value = "";
- newInput.focus();
- newInput.dispatchEvent(event);
- });
-
- yield new Promise(resolve => hitEventLoop(resolve, 100));
-
- ok(!popupShown, "Popup must not be opened");
- SpecialPowers.removeAutoCompletePopupEventListener(window, "popupshowing", listener);
- });
-});
-
-function hitEventLoop(func, times) {
- if (times > 0) {
- setTimeout(hitEventLoop, 0, func, times - 1);
- } else {
- setTimeout(func, 0);
- }
-}
diff --git a/editor/libeditor/tests/browser_bug629172.js b/editor/libeditor/tests/browser_bug629172.js
deleted file mode 100644
index 0c4f34069..000000000
--- a/editor/libeditor/tests/browser_bug629172.js
+++ /dev/null
@@ -1,106 +0,0 @@
-add_task(function*() {
- yield new Promise(resolve => waitForFocus(resolve, window));
-
- const kPageURL = "http://example.org/browser/editor/libeditor/tests/bug629172.html";
- yield BrowserTestUtils.withNewTab({
- gBrowser,
- url: kPageURL
- }, function*(aBrowser) {
- yield ContentTask.spawn(aBrowser, {}, function*() {
- var window = content.window.wrappedJSObject;
- var document = window.document;
-
- // Note: Using the with keyword, we would have been able to write this as:
- //
- // with (window) {
- // Screenshots = {};
- // // so on
- // }
- //
- // However, browser-chrome tests are somehow forced to run in strict mode,
- // which doesn't permit the usage of the with keyword, turning the following
- // into the ugliest test you've ever seen. :(
- var LTRRef = document.getElementById("ltr-ref");
- var RTLRef = document.getElementById("rtl-ref");
- window.Screenshots = {};
-
- // generate the reference screenshots
- LTRRef.style.display = "";
- document.body.clientWidth;
- window.Screenshots.ltr = window.snapshotWindow(window);
- LTRRef.parentNode.removeChild(LTRRef);
- RTLRef.style.display = "";
- document.body.clientWidth;
- window.Screenshots.rtl = window.snapshotWindow(window);
- RTLRef.parentNode.removeChild(RTLRef);
- window.Screenshots.get = function(dir, flip) {
- if (flip) {
- return this[dir == "rtl" ? "ltr" : "rtl"];
- } else {
- return this[dir];
- }
- };
- });
-
- function simulateCtrlShiftX(aBrowser) {
- // In e10s, the keypress event will be dispatched to the content process,
- // but in non-e10s it is handled by the browser UI code and hence won't
- // reach the web page. As a result, we need to observe the event in
- // the content process only in e10s mode.
- var waitForKeypressContent = BrowserTestUtils.waitForContentEvent(aBrowser, "keypress");
- EventUtils.synthesizeKey("x", {accelKey: true, shiftKey: true});
- if (gMultiProcessBrowser) {
- return waitForKeypressContent;
- }
- return Promise.resolve();
- }
-
- function* testDirection(initialDir, aBrowser) {
- yield ContentTask.spawn(aBrowser, {initialDir}, function({initialDir}) {
- var window = content.window.wrappedJSObject;
- var document = window.document;
-
- var t = window.t = document.createElement("textarea");
- t.setAttribute("dir", initialDir);
- t.value = "test.";
- window.inputEventCount = 0;
- t.oninput = function() { window.inputEventCount++; };
- document.getElementById("content").appendChild(t);
- document.body.clientWidth;
- var s1 = window.snapshotWindow(window);
- ok(window.compareSnapshots(s1, window.Screenshots.get(initialDir, false), true)[0],
- "Textarea should appear correctly before switching the direction (" + initialDir + ")");
- t.focus();
- is(window.inputEventCount, 0, "input event count must be 0 before");
- });
- yield simulateCtrlShiftX(aBrowser);
- yield ContentTask.spawn(aBrowser, {initialDir}, function({initialDir}) {
- var window = content.window.wrappedJSObject;
-
- is(window.t.getAttribute("dir"), initialDir == "ltr" ? "rtl" : "ltr", "The dir attribute must be correctly updated");
- is(window.inputEventCount, 1, "input event count must be 1 after");
- window.t.blur();
- var s2 = window.snapshotWindow(window);
- ok(window.compareSnapshots(s2, window.Screenshots.get(initialDir, true), true)[0],
- "Textarea should appear correctly after switching the direction (" + initialDir + ")");
- window.t.focus();
- is(window.inputEventCount, 1, "input event count must be 1 before");
- });
- yield simulateCtrlShiftX(aBrowser);
- yield ContentTask.spawn(aBrowser, {initialDir}, function({initialDir}) {
- var window = content.window.wrappedJSObject;
-
- is(window.inputEventCount, 2, "input event count must be 2 after");
- is(window.t.getAttribute("dir"), initialDir == "ltr" ? "ltr" : "rtl", "The dir attribute must be correctly updated");
- window.t.blur();
- var s3 = window.snapshotWindow(window);
- ok(window.compareSnapshots(s3, window.Screenshots.get(initialDir, false), true)[0],
- "Textarea should appear correctly after switching back the direction (" + initialDir + ")");
- window.t.parentNode.removeChild(window.t);
- });
- }
-
- yield testDirection("ltr", aBrowser);
- yield testDirection("rtl", aBrowser);
- });
-});
diff --git a/editor/libeditor/tests/browserscope/lib/richtext/LICENSE b/editor/libeditor/tests/browserscope/lib/richtext/LICENSE
deleted file mode 100644
index 57bc88a15..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext/LICENSE
+++ /dev/null
@@ -1,202 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext/README b/editor/libeditor/tests/browserscope/lib/richtext/README
deleted file mode 100644
index a3bc3110f..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext/README
+++ /dev/null
@@ -1,58 +0,0 @@
-README FOR BROWSERSCOPE
------------------------
-
-Hey there - thanks for downloading the code. This file has instructions
-for getting setup so that you can run the codebase locally.
-
-This project is built on Google App Engine using the
-Django web application framework and written in Python.
-
-To get started, you'll need to first download the App Engine SDK at:
-http://code.google.com/appengine/downloads.html
-
-For local development, just startup the server:
-./pathto/google_appengine/dev_appserver.py --port=8080 browserscope
-
-You should then be able to access the local application at:
-http://localhost:8080/
-
-Note: the first time you hit the homepage it may take a little
-while - that's because it's trying to read out median times for all
-of the tests from a nonexistent datastore and write to memcache.
-Just be a lil patient.
-
-You can run the unit tests at:
- http://localhost:8080/test
-
-
-CONTRIBUTING
-------------------
-
-Most likely you are interested in adding new tests or creating
-a new test category. If you are interested in adding tests to an existing
-"category" you may want to get in touch with the maintainer for that
-branch of the tree. We are really looking forward to receiving your
-code in patch format. Currently the category maintainers are:
-Network: Steve Souders <souders@gmail.com>
-Reflow: Lindsey Simon <elsigh@gmail.com>
-Security: Adam Barth <adam@adambarth.com> and Collin Jackson <collin@collinjackson.com>
-
-
-To create a completely new test category:
- * Copy one of the existing directories in categories/
- * Edit your test_set.py, handlers.py
- * Add your files in templates/ and static/
- * Update urls.py and settings.CATEGORIES
- * Follow the examples of other tests re:
- * beaconing using/testdriver_base
- * your GetScoreAndDisplayValue method
- * your GetRowScoreAndDisplayValue method
-
-References:
- * App Engine Docs - http://code.google.com/appengine/docs/python/overview.html
- * App Engine Group - http://groups.google.com/group/google-appengine
- * Python Docs - http://www.python.org/doc/
- * Django - http://www.djangoproject.com/
-
-
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext/README.Mozilla b/editor/libeditor/tests/browserscope/lib/richtext/README.Mozilla
deleted file mode 100644
index 5d304943f..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext/README.Mozilla
+++ /dev/null
@@ -1,17 +0,0 @@
-The BrowserScope project provides a set of cross-browser HTML editor tests,
-which we import in our test suite in order to run them as part of our
-continuous integration system.
-
-We pull tests occasionally from their Subversion repository using the pull
-script which can be found in this directory. We also record the revision ID
-which we've used in the current_revision file inside this directory.
-
-Using the pull script is quite easy, just switch to this directory, and say:
-
-sh update_from_upstream
-
-There are tests which we're currently failing on, and there will probably be
-more of those in the future. We should maintain a list of the failing tests
-manually in currentStatus.js (which can also be found in this directory), to
-make sure that the suite passes entirely, with failing tests marked as todo
-items.
diff --git a/editor/libeditor/tests/browserscope/lib/richtext/currentStatus.js b/editor/libeditor/tests/browserscope/lib/richtext/currentStatus.js
deleted file mode 100644
index b30775d04..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext/currentStatus.js
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * This file lists the tests in the BrowserScope suite which we are currently
- * failing. We mark them as todo items to keep track of them.
- */
-
-var knownFailures = {
- // Dummy result items. There is one for each category.
- 'apply' : {
- '0-undefined' : true
- },
- 'unapply' : {
- '0-undefined' : true
- },
- 'change' : {
- '0-undefined' : true
- },
- 'query' : {
- '0-undefined' : true
- },
- 'a' : {
- 'createbookmark-0' : true,
- 'fontsize-1' : true,
- 'subscript-1' : true,
- 'superscript-1' : true,
- },
- 'u': {
- 'removeformat-1' : true,
- 'removeformat-2' : true,
- 'strikethrough-2' : true,
- 'subscript-1' : true,
- 'superscript-1' : true,
- 'unbookmark-0' : true,
- },
- 'q': {
- 'fontsize-1' : true,
- 'fontsize-2' : true,
- },
- 'c': {
- 'fontsize-1' : true,
- 'fontsize-2' : true,
- },
-};
-
-function isKnownFailure(type, test, param) {
- return (type in knownFailures) && ((test + "-" + param) in knownFailures[type]);
-}
diff --git a/editor/libeditor/tests/browserscope/lib/richtext/current_revision b/editor/libeditor/tests/browserscope/lib/richtext/current_revision
deleted file mode 100644
index 1e2569914..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext/current_revision
+++ /dev/null
@@ -1 +0,0 @@
-775
diff --git a/editor/libeditor/tests/browserscope/lib/richtext/richtext/editable.html b/editor/libeditor/tests/browserscope/lib/richtext/richtext/editable.html
deleted file mode 100644
index a294f0b56..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext/richtext/editable.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<html>
-<head>
- <script>
- function load(){
- window.document.designMode = "On";
- }
- </script>
-</head>
-<body contentEditable="true" onload="load()">
-</body>
-</html> \ No newline at end of file
diff --git a/editor/libeditor/tests/browserscope/lib/richtext/richtext/js/range.js b/editor/libeditor/tests/browserscope/lib/richtext/richtext/js/range.js
deleted file mode 100644
index 3e4463e11..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext/richtext/js/range.js
+++ /dev/null
@@ -1,1069 +0,0 @@
-var goog$global = this, goog$isString = function(val) {
- return typeof val == "string"
-};
-Math.floor(Math.random() * 2147483648).toString(36);
-var goog$now = Date.now || function() {
- return(new Date).getTime()
-}, goog$inherits = function(childCtor, parentCtor) {
- function tempCtor() {
- }
- tempCtor.prototype = parentCtor.prototype;
- childCtor.superClass_ = parentCtor.prototype;
- childCtor.prototype = new tempCtor
-};var goog$array$peek = function(array) {
- return array[array.length - 1]
-}, goog$array$indexOf = function(arr, obj, opt_fromIndex) {
- if(arr.indexOf)return arr.indexOf(obj, opt_fromIndex);
- if(Array.indexOf)return Array.indexOf(arr, obj, opt_fromIndex);
- for(var fromIndex = opt_fromIndex == null ? 0 : opt_fromIndex < 0 ? Math.max(0, arr.length + opt_fromIndex) : opt_fromIndex, i = fromIndex;i < arr.length;i++)if(i in arr && arr[i] === obj)return i;
- return-1
-}, goog$array$map = function(arr, f, opt_obj) {
- if(arr.map)return arr.map(f, opt_obj);
- if(Array.map)return Array.map(arr, f, opt_obj);
- for(var l = arr.length, res = [], resLength = 0, arr2 = goog$isString(arr) ? arr.split("") : arr, i = 0;i < l;i++)if(i in arr2)res[resLength++] = f.call(opt_obj, arr2[i], i, arr);
- return res
-}, goog$array$some = function(arr, f, opt_obj) {
- if(arr.some)return arr.some(f, opt_obj);
- if(Array.some)return Array.some(arr, f, opt_obj);
- for(var l = arr.length, arr2 = goog$isString(arr) ? arr.split("") : arr, i = 0;i < l;i++)if(i in arr2 && f.call(opt_obj, arr2[i], i, arr))return true;
- return false
-}, goog$array$every = function(arr, f, opt_obj) {
- if(arr.every)return arr.every(f, opt_obj);
- if(Array.every)return Array.every(arr, f, opt_obj);
- for(var l = arr.length, arr2 = goog$isString(arr) ? arr.split("") : arr, i = 0;i < l;i++)if(i in arr2 && !f.call(opt_obj, arr2[i], i, arr))return false;
- return true
-}, goog$array$find = function(arr, f, opt_obj) {
- var i;
- JSCompiler_inline_label_goog$array$findIndex_12: {
- for(var JSCompiler_inline_l = arr.length, JSCompiler_inline_arr2 = goog$isString(arr) ? arr.split("") : arr, JSCompiler_inline_i = 0;JSCompiler_inline_i < JSCompiler_inline_l;JSCompiler_inline_i++)if(JSCompiler_inline_i in JSCompiler_inline_arr2 && f.call(opt_obj, JSCompiler_inline_arr2[JSCompiler_inline_i], JSCompiler_inline_i, arr)) {
- i = JSCompiler_inline_i;
- break JSCompiler_inline_label_goog$array$findIndex_12
- }i = -1
- }return i < 0 ? null : goog$isString(arr) ? arr.charAt(i) : arr[i]
-};var goog$string$trim = function(str) {
- return str.replace(/^[\s\xa0]+|[\s\xa0]+$/g, "")
-}, goog$string$htmlEscape = function(str, opt_isLikelyToContainHtmlChars) {
- if(opt_isLikelyToContainHtmlChars)return str.replace(goog$string$amperRe_, "&amp;").replace(goog$string$ltRe_, "&lt;").replace(goog$string$gtRe_, "&gt;").replace(goog$string$quotRe_, "&quot;");
- else {
- if(!goog$string$allRe_.test(str))return str;
- if(str.indexOf("&") != -1)str = str.replace(goog$string$amperRe_, "&amp;");
- if(str.indexOf("<") != -1)str = str.replace(goog$string$ltRe_, "&lt;");
- if(str.indexOf(">") != -1)str = str.replace(goog$string$gtRe_, "&gt;");
- if(str.indexOf('"') != -1)str = str.replace(goog$string$quotRe_, "&quot;");
- return str
- }
-}, goog$string$amperRe_ = /&/g, goog$string$ltRe_ = /</g, goog$string$gtRe_ = />/g, goog$string$quotRe_ = /\"/g, goog$string$allRe_ = /[&<>\"]/, goog$string$contains = function(s, ss) {
- return s.indexOf(ss) != -1
-}, goog$string$compareVersions = function(version1, version2) {
- for(var order = 0, v1Subs = goog$string$trim(String(version1)).split("."), v2Subs = goog$string$trim(String(version2)).split("."), subCount = Math.max(v1Subs.length, v2Subs.length), subIdx = 0;order == 0 && subIdx < subCount;subIdx++) {
- var v1Sub = v1Subs[subIdx] || "", v2Sub = v2Subs[subIdx] || "", v1CompParser = new RegExp("(\\d*)(\\D*)", "g"), v2CompParser = new RegExp("(\\d*)(\\D*)", "g");
- do {
- var v1Comp = v1CompParser.exec(v1Sub) || ["", "", ""], v2Comp = v2CompParser.exec(v2Sub) || ["", "", ""];
- if(v1Comp[0].length == 0 && v2Comp[0].length == 0)break;
- var v1CompNum = v1Comp[1].length == 0 ? 0 : parseInt(v1Comp[1], 10), v2CompNum = v2Comp[1].length == 0 ? 0 : parseInt(v2Comp[1], 10);
- order = goog$string$compareElements_(v1CompNum, v2CompNum) || goog$string$compareElements_(v1Comp[2].length == 0, v2Comp[2].length == 0) || goog$string$compareElements_(v1Comp[2], v2Comp[2])
- }while(order == 0)
- }return order
-}, goog$string$compareElements_ = function(left, right) {
- if(left < right)return-1;
- else if(left > right)return 1;
- return 0
-};
-goog$now();var goog$userAgent$detectedOpera_, goog$userAgent$detectedIe_, goog$userAgent$detectedWebkit_, goog$userAgent$detectedMobile_, goog$userAgent$detectedGecko_, goog$userAgent$detectedCamino_, goog$userAgent$detectedMac_, goog$userAgent$detectedWindows_, goog$userAgent$detectedLinux_, goog$userAgent$detectedX11_, goog$userAgent$getUserAgentString = function() {
- return goog$global.navigator ? goog$global.navigator.userAgent : null
-}, goog$userAgent$getNavigator = function() {
- return goog$global.navigator
-};
-goog$userAgent$detectedCamino_ = goog$userAgent$detectedGecko_ = goog$userAgent$detectedMobile_ = goog$userAgent$detectedWebkit_ = goog$userAgent$detectedIe_ = goog$userAgent$detectedOpera_ = false;
-var JSCompiler_inline_ua_15;
-if(JSCompiler_inline_ua_15 = goog$userAgent$getUserAgentString()) {
- var JSCompiler_inline_navigator$$1_16 = goog$userAgent$getNavigator();
- goog$userAgent$detectedOpera_ = JSCompiler_inline_ua_15.indexOf("Opera") == 0;
- goog$userAgent$detectedIe_ = !goog$userAgent$detectedOpera_ && JSCompiler_inline_ua_15.indexOf("MSIE") != -1;
- goog$userAgent$detectedMobile_ = (goog$userAgent$detectedWebkit_ = !goog$userAgent$detectedOpera_ && JSCompiler_inline_ua_15.indexOf("WebKit") != -1) && JSCompiler_inline_ua_15.indexOf("Mobile") != -1;
- goog$userAgent$detectedCamino_ = (goog$userAgent$detectedGecko_ = !goog$userAgent$detectedOpera_ && !goog$userAgent$detectedWebkit_ && JSCompiler_inline_navigator$$1_16.product == "Gecko") && JSCompiler_inline_navigator$$1_16.vendor == "Camino"
-}var goog$userAgent$OPERA = goog$userAgent$detectedOpera_, goog$userAgent$IE = goog$userAgent$detectedIe_, goog$userAgent$GECKO = goog$userAgent$detectedGecko_, goog$userAgent$WEBKIT = goog$userAgent$detectedWebkit_, goog$userAgent$MOBILE = goog$userAgent$detectedMobile_, goog$userAgent$PLATFORM, JSCompiler_inline_navigator$$2_19 = goog$userAgent$getNavigator();
-goog$userAgent$PLATFORM = JSCompiler_inline_navigator$$2_19 && JSCompiler_inline_navigator$$2_19.platform || "";
-goog$userAgent$detectedMac_ = goog$string$contains(goog$userAgent$PLATFORM, "Mac");
-goog$userAgent$detectedWindows_ = goog$string$contains(goog$userAgent$PLATFORM, "Win");
-goog$userAgent$detectedLinux_ = goog$string$contains(goog$userAgent$PLATFORM, "Linux");
-goog$userAgent$detectedX11_ = !!goog$userAgent$getNavigator() && goog$string$contains(goog$userAgent$getNavigator().appVersion || "", "X11");
-var goog$userAgent$VERSION, JSCompiler_inline_version$$6_26 = "", JSCompiler_inline_re$$2_27;
-if(goog$userAgent$OPERA && goog$global.opera) {
- var JSCompiler_inline_operaVersion_28 = goog$global.opera.version;
- JSCompiler_inline_version$$6_26 = typeof JSCompiler_inline_operaVersion_28 == "function" ? JSCompiler_inline_operaVersion_28() : JSCompiler_inline_operaVersion_28
-}else {
- if(goog$userAgent$GECKO)JSCompiler_inline_re$$2_27 = /rv\:([^\);]+)(\)|;)/;
- else if(goog$userAgent$IE)JSCompiler_inline_re$$2_27 = /MSIE\s+([^\);]+)(\)|;)/;
- else if(goog$userAgent$WEBKIT)JSCompiler_inline_re$$2_27 = /WebKit\/(\S+)/;
- if(JSCompiler_inline_re$$2_27) {
- var JSCompiler_inline_arr$$41_29 = JSCompiler_inline_re$$2_27.exec(goog$userAgent$getUserAgentString());
- JSCompiler_inline_version$$6_26 = JSCompiler_inline_arr$$41_29 ? JSCompiler_inline_arr$$41_29[1] : ""
- }
-}goog$userAgent$VERSION = JSCompiler_inline_version$$6_26;
-var goog$userAgent$isVersionCache_ = {}, goog$userAgent$isVersion = function(version) {
- return goog$userAgent$isVersionCache_[version] || (goog$userAgent$isVersionCache_[version] = goog$string$compareVersions(goog$userAgent$VERSION, version) >= 0)
-};var goog$dom$getWindow = function(opt_doc) {
- return opt_doc ? goog$dom$getWindow_(opt_doc) : window
-}, goog$dom$getWindow_ = function(doc) {
- if(doc.parentWindow)return doc.parentWindow;
- if(goog$userAgent$WEBKIT && !goog$userAgent$isVersion("500") && !goog$userAgent$MOBILE) {
- var scriptElement = doc.createElement("script");
- scriptElement.innerHTML = "document.parentWindow=window";
- var parentElement = doc.documentElement;
- parentElement.appendChild(scriptElement);
- parentElement.removeChild(scriptElement);
- return doc.parentWindow
- }return doc.defaultView
-}, goog$dom$appendChild = function(parent, child) {
- parent.appendChild(child)
-}, goog$dom$BAD_CONTAINS_WEBKIT_ = goog$userAgent$WEBKIT && goog$userAgent$isVersion("522"), goog$dom$contains = function(parent, descendant) {
- if(typeof parent.contains != "undefined" && !goog$dom$BAD_CONTAINS_WEBKIT_ && descendant.nodeType == 1)return parent == descendant || parent.contains(descendant);
- if(typeof parent.compareDocumentPosition != "undefined")return parent == descendant || Boolean(parent.compareDocumentPosition(descendant) & 16);
- for(;descendant && parent != descendant;)descendant = descendant.parentNode;
- return descendant == parent
-}, goog$dom$compareNodeOrder = function(node1, node2) {
- if(node1 == node2)return 0;
- if(node1.compareDocumentPosition)return node1.compareDocumentPosition(node2) & 2 ? 1 : -1;
- if("sourceIndex" in node1 || node1.parentNode && "sourceIndex" in node1.parentNode) {
- var isElement1 = node1.nodeType == 1, isElement2 = node2.nodeType == 1;
- if(isElement1 && isElement2)return node1.sourceIndex - node2.sourceIndex;
- else {
- var parent1 = node1.parentNode, parent2 = node2.parentNode;
- if(parent1 == parent2)return goog$dom$compareSiblingOrder_(node1, node2);
- if(!isElement1 && goog$dom$contains(parent1, node2))return-1 * goog$dom$compareParentsDescendantNodeIe_(node1, node2);
- if(!isElement2 && goog$dom$contains(parent2, node1))return goog$dom$compareParentsDescendantNodeIe_(node2, node1);
- return(isElement1 ? node1.sourceIndex : parent1.sourceIndex) - (isElement2 ? node2.sourceIndex : parent2.sourceIndex)
- }
- }var doc = goog$dom$getOwnerDocument(node1), range1, range2;
- range1 = doc.createRange();
- range1.selectNode(node1);
- range1.collapse(true);
- range2 = doc.createRange();
- range2.selectNode(node2);
- range2.collapse(true);
- return range1.compareBoundaryPoints(goog$global.Range.START_TO_END, range2)
-}, goog$dom$compareParentsDescendantNodeIe_ = function(textNode, node) {
- var parent = textNode.parentNode;
- if(parent == node)return-1;
- for(var sibling = node;sibling.parentNode != parent;)sibling = sibling.parentNode;
- return goog$dom$compareSiblingOrder_(sibling, textNode)
-}, goog$dom$compareSiblingOrder_ = function(node1, node2) {
- for(var s = node2;s = s.previousSibling;)if(s == node1)return-1;
- return 1
-}, goog$dom$findCommonAncestor = function() {
- var i, count = arguments.length;
- if(count) {
- if(count == 1)return arguments[0]
- }else return null;
- var paths = [], minLength = Infinity;
- for(i = 0;i < count;i++) {
- for(var ancestors = [], node = arguments[i];node;) {
- ancestors.unshift(node);
- node = node.parentNode
- }paths.push(ancestors);
- minLength = Math.min(minLength, ancestors.length)
- }var output = null;
- for(i = 0;i < minLength;i++) {
- for(var first = paths[0][i], j = 1;j < count;j++)if(first != paths[j][i])return output;
- output = first
- }return output
-}, goog$dom$getOwnerDocument = function(node) {
- // Added 'editorDoc' as hack for browsers that don't support node.ownerDocument
- return node.nodeType == 9 ? node : node.ownerDocument || node.document || editorDoc
-}, goog$dom$DomHelper = function(opt_document) {
- this.document_ = opt_document || goog$global.document || document
-};
-goog$dom$DomHelper.prototype.getDocument = function() {
- return this.document_
-};
-goog$dom$DomHelper.prototype.createElement = function(name) {
- return this.document_.createElement(name)
-};
-goog$dom$DomHelper.prototype.getWindow = function() {
- return goog$dom$getWindow_(this.document_)
-};
-goog$dom$DomHelper.prototype.appendChild = goog$dom$appendChild;
-goog$dom$DomHelper.prototype.contains = goog$dom$contains;var goog$Disposable = function() {
-};if("StopIteration" in goog$global)var goog$iter$StopIteration = goog$global.StopIteration;
-else goog$iter$StopIteration = Error("StopIteration");
-var goog$iter$Iterator = function() {
-};
-goog$iter$Iterator.prototype.next = function() {
- throw goog$iter$StopIteration;
-};
-goog$iter$Iterator.prototype.__iterator__ = function() {
- return this
-};var goog$debug$exposeException = function(err, opt_fn) {
- try {
- var e, JSCompiler_inline_href_34;
- JSCompiler_inline_label_goog$getObjectByName_61: {
- for(var JSCompiler_inline_parts = "window.location.href".split("."), JSCompiler_inline_cur = goog$global, JSCompiler_inline_part;JSCompiler_inline_part = JSCompiler_inline_parts.shift();)if(JSCompiler_inline_cur[JSCompiler_inline_part])JSCompiler_inline_cur = JSCompiler_inline_cur[JSCompiler_inline_part];
- else {
- JSCompiler_inline_href_34 = null;
- break JSCompiler_inline_label_goog$getObjectByName_61
- }JSCompiler_inline_href_34 = JSCompiler_inline_cur
- }e = typeof err == "string" ? {message:err, name:"Unknown error", lineNumber:"Not available", fileName:JSCompiler_inline_href_34, stack:"Not available"} : !err.lineNumber || !err.fileName || !err.stack ? {message:err.message, name:err.name, lineNumber:err.lineNumber || err.line || "Not available", fileName:err.fileName || err.filename || err.sourceURL || JSCompiler_inline_href_34, stack:err.stack || "Not available"} : err;
- var error = "Message: " + goog$string$htmlEscape(e.message) + '\nUrl: <a href="view-source:' + e.fileName + '" target="_new">' + e.fileName + "</a>\nLine: " + e.lineNumber + "\n\nBrowser stack:\n" + goog$string$htmlEscape(e.stack + "-> ") + "[end]\n\nJS stack traversal:\n" + goog$string$htmlEscape(goog$debug$getStacktrace(opt_fn) + "-> ");
- return error
- }catch(e2) {
- return"Exception trying to expose exception! You win, we lose. " + e2
- }
-}, goog$debug$getStacktrace = function(opt_fn) {
- return goog$debug$getStacktraceHelper_(opt_fn || arguments.callee.caller, [])
-}, goog$debug$getStacktraceHelper_ = function(fn, visited) {
- var sb = [], JSCompiler_inline_result_36;
- JSCompiler_inline_label_goog$array$contains_41:JSCompiler_inline_result_36 = visited.contains ? visited.contains(fn) : goog$array$indexOf(visited, fn) > -1;
- if(JSCompiler_inline_result_36)sb.push("[...circular reference...]");
- else if(fn && visited.length < 50) {
- sb.push(goog$debug$getFunctionName(fn) + "(");
- for(var args = fn.arguments, i = 0;i < args.length;i++) {
- i > 0 && sb.push(", ");
- var argDesc, arg = args[i];
- switch(typeof arg) {
- case "object":
- argDesc = arg ? "object" : "null";
- break;
- case "string":
- argDesc = arg;
- break;
- case "number":
- argDesc = String(arg);
- break;
- case "boolean":
- argDesc = arg ? "true" : "false";
- break;
- case "function":
- argDesc = (argDesc = goog$debug$getFunctionName(arg)) ? argDesc : "[fn]";
- break;
- case "undefined":
- ;
- default:
- argDesc = typeof arg;
- break
- }
- if(argDesc.length > 40)argDesc = argDesc.substr(0, 40) + "...";
- sb.push(argDesc)
- }visited.push(fn);
- sb.push(")\n");
- try {
- sb.push(goog$debug$getStacktraceHelper_(fn.caller, visited))
- }catch(e) {
- sb.push("[exception trying to get caller]\n")
- }
- }else fn ? sb.push("[...long stack...]") : sb.push("[end]");
- return sb.join("")
-}, goog$debug$getFunctionName = function(fn) {
- var functionSource = String(fn);
- if(!goog$debug$fnNameCache_[functionSource]) {
- var matches = /function ([^\(]+)/.exec(functionSource);
- if(matches) {
- var method = matches[1];
- goog$debug$fnNameCache_[functionSource] = method
- }else goog$debug$fnNameCache_[functionSource] = "[Anonymous]"
- }return goog$debug$fnNameCache_[functionSource]
-}, goog$debug$fnNameCache_ = {};var goog$debug$LogRecord = function(level, msg, loggerName, opt_time, opt_sequenceNumber) {
- this.sequenceNumber_ = typeof opt_sequenceNumber == "number" ? opt_sequenceNumber : goog$debug$LogRecord$nextSequenceNumber_++;
- this.time_ = opt_time || goog$now();
- this.level_ = level;
- this.msg_ = msg;
- this.loggerName_ = loggerName
-};
-goog$debug$LogRecord.prototype.exception_ = null;
-goog$debug$LogRecord.prototype.exceptionText_ = null;
-var goog$debug$LogRecord$nextSequenceNumber_ = 0;
-goog$debug$LogRecord.prototype.setException = function(exception) {
- this.exception_ = exception
-};
-goog$debug$LogRecord.prototype.setExceptionText = function(text) {
- this.exceptionText_ = text
-};
-goog$debug$LogRecord.prototype.setLevel = function(level) {
- this.level_ = level
-};var goog$debug$Logger = function(name) {
- this.name_ = name;
- this.parent_ = null;
- this.children_ = {};
- this.handlers_ = []
-};
-goog$debug$Logger.prototype.level_ = null;
-var goog$debug$Logger$Level = function(name, value) {
- this.name = name;
- this.value = value
-};
-goog$debug$Logger$Level.prototype.toString = function() {
- return this.name
-};
-new goog$debug$Logger$Level("OFF", Infinity);
-new goog$debug$Logger$Level("SHOUT", 1200);
-var goog$debug$Logger$Level$SEVERE = new goog$debug$Logger$Level("SEVERE", 1000), goog$debug$Logger$Level$WARNING = new goog$debug$Logger$Level("WARNING", 900);
-new goog$debug$Logger$Level("INFO", 800);
-var goog$debug$Logger$Level$CONFIG = new goog$debug$Logger$Level("CONFIG", 700);
-new goog$debug$Logger$Level("FINE", 500);
-new goog$debug$Logger$Level("FINER", 400);
-new goog$debug$Logger$Level("FINEST", 300);
-new goog$debug$Logger$Level("ALL", 0);
-goog$debug$Logger.prototype.setLevel = function(level) {
- this.level_ = level
-};
-goog$debug$Logger.prototype.isLoggable = function(level) {
- if(this.level_)return level.value >= this.level_.value;
- if(this.parent_)return this.parent_.isLoggable(level);
- return false
-};
-goog$debug$Logger.prototype.log = function(level, msg, opt_exception) {
- this.isLoggable(level) && this.logRecord(this.getLogRecord(level, msg, opt_exception))
-};
-goog$debug$Logger.prototype.getLogRecord = function(level, msg, opt_exception) {
- var logRecord = new goog$debug$LogRecord(level, String(msg), this.name_);
- if(opt_exception) {
- logRecord.setException(opt_exception);
- logRecord.setExceptionText(goog$debug$exposeException(opt_exception, arguments.callee.caller))
- }return logRecord
-};
-goog$debug$Logger.prototype.severe = function(msg, opt_exception) {
- this.log(goog$debug$Logger$Level$SEVERE, msg, opt_exception)
-};
-goog$debug$Logger.prototype.warning = function(msg, opt_exception) {
- this.log(goog$debug$Logger$Level$WARNING, msg, opt_exception)
-};
-goog$debug$Logger.prototype.logRecord = function(logRecord) {
- if(this.isLoggable(logRecord.level_))for(var target = this;target;) {
- target.callPublish_(logRecord);
- target = target.parent_
- }
-};
-goog$debug$Logger.prototype.callPublish_ = function(logRecord) {
- for(var i = 0;i < this.handlers_.length;i++)this.handlers_[i](logRecord)
-};
-goog$debug$Logger.prototype.setParent_ = function(parent) {
- this.parent_ = parent
-};
-goog$debug$Logger.prototype.addChild_ = function(name, logger) {
- this.children_[name] = logger
-};
-var goog$debug$LogManager$loggers_ = {}, goog$debug$LogManager$rootLogger_ = null, goog$debug$LogManager$getLogger = function(name) {
- if(!goog$debug$LogManager$rootLogger_) {
- goog$debug$LogManager$rootLogger_ = new goog$debug$Logger("");
- goog$debug$LogManager$loggers_[""] = goog$debug$LogManager$rootLogger_;
- goog$debug$LogManager$rootLogger_.setLevel(goog$debug$Logger$Level$CONFIG)
- }return name in goog$debug$LogManager$loggers_ ? goog$debug$LogManager$loggers_[name] : goog$debug$LogManager$createLogger_(name)
-}, goog$debug$LogManager$createLogger_ = function(name) {
- var logger = new goog$debug$Logger(name), parts = name.split("."), leafName = parts[parts.length - 1];
- parts.length = parts.length - 1;
- var parentName = parts.join("."), parentLogger = goog$debug$LogManager$getLogger(parentName);
- parentLogger.addChild_(leafName, logger);
- logger.setParent_(parentLogger);
- return goog$debug$LogManager$loggers_[name] = logger
-};var goog$dom$SavedRange = function() {
- goog$Disposable.call(this)
-};
-goog$inherits(goog$dom$SavedRange, goog$Disposable);
-goog$debug$LogManager$getLogger("goog.dom.SavedRange");var goog$dom$TagIterator = function(opt_node, opt_reversed, opt_unconstrained, opt_tagType, opt_depth) {
- this.reversed = !!opt_reversed;
- opt_node && this.setPosition(opt_node, opt_tagType);
- this.depth = opt_depth != undefined ? opt_depth : this.tagType || 0;
- if(this.reversed)this.depth *= -1;
- this.constrained = !opt_unconstrained
-};
-goog$inherits(goog$dom$TagIterator, goog$iter$Iterator);
-goog$dom$TagIterator.prototype.node = null;
-goog$dom$TagIterator.prototype.tagType = null;
-goog$dom$TagIterator.prototype.started_ = false;
-goog$dom$TagIterator.prototype.setPosition = function(node, opt_tagType, opt_depth) {
- if(this.node = node)this.tagType = typeof opt_tagType == "number" ? opt_tagType : this.node.nodeType != 1 ? 0 : this.reversed ? -1 : 1;
- if(typeof opt_depth == "number")this.depth = opt_depth
-};
-goog$dom$TagIterator.prototype.next = function() {
- var node;
- if(this.started_) {
- if(!this.node || this.constrained && this.depth == 0)throw goog$iter$StopIteration;node = this.node;
- var startType = this.reversed ? -1 : 1;
- if(this.tagType == startType) {
- var child = this.reversed ? node.lastChild : node.firstChild;
- child ? this.setPosition(child) : this.setPosition(node, startType * -1)
- }else {
- var sibling = this.reversed ? node.previousSibling : node.nextSibling;
- sibling ? this.setPosition(sibling) : this.setPosition(node.parentNode, startType * -1)
- }this.depth += this.tagType * (this.reversed ? -1 : 1)
- }else this.started_ = true;
- node = this.node;
- if(!this.node)throw goog$iter$StopIteration;return node
-};
-goog$dom$TagIterator.prototype.isStartTag = function() {
- return this.tagType == 1
-};var goog$dom$AbstractRange = function() {
-};
-goog$dom$AbstractRange.prototype.getTextRanges = function() {
- for(var output = [], i = 0, len = this.getTextRangeCount();i < len;i++)output.push(this.getTextRange(i));
- return output
-};
-goog$dom$AbstractRange.prototype.getAnchorNode = function() {
- return this.isReversed() ? this.getEndNode() : this.getStartNode()
-};
-goog$dom$AbstractRange.prototype.getAnchorOffset = function() {
- return this.isReversed() ? this.getEndOffset() : this.getStartOffset()
-};
-goog$dom$AbstractRange.prototype.getFocusNode = function() {
- return this.isReversed() ? this.getStartNode() : this.getEndNode()
-};
-goog$dom$AbstractRange.prototype.getFocusOffset = function() {
- return this.isReversed() ? this.getStartOffset() : this.getEndOffset()
-};
-goog$dom$AbstractRange.prototype.isReversed = function() {
- return false
-};
-goog$dom$AbstractRange.prototype.getDocument = function() {
- return goog$dom$getOwnerDocument(goog$userAgent$IE ? this.getContainer() : this.getStartNode())
-};
-goog$dom$AbstractRange.prototype.getWindow = function() {
- return goog$dom$getWindow(this.getDocument())
-};
-goog$dom$AbstractRange.prototype.containsNode = function(node, opt_allowPartial) {
- return this.containsRange(goog$dom$TextRange$createFromNodeContents(node, undefined), opt_allowPartial)
-};
-var goog$dom$RangeIterator = function(node, opt_reverse) {
- goog$dom$TagIterator.call(this, node, opt_reverse, true)
-};
-goog$inherits(goog$dom$RangeIterator, goog$dom$TagIterator);var goog$dom$AbstractMultiRange = function() {
-};
-goog$inherits(goog$dom$AbstractMultiRange, goog$dom$AbstractRange);
-goog$dom$AbstractMultiRange.prototype.containsRange = function(otherRange, opt_allowPartial) {
- var ranges = this.getTextRanges(), otherRanges = otherRange.getTextRanges(), fn = opt_allowPartial ? goog$array$some : goog$array$every;
- return fn(otherRanges, function(otherRange) {
- return goog$array$some(ranges, function(range) {
- return range.containsRange(otherRange, opt_allowPartial)
- })
- })
-};var goog$dom$TextRangeIterator = function(startNode, startOffset, endNode, endOffset, opt_reverse) {
- var goNext;
- if(startNode) {
- this.startNode_ = startNode;
- this.startOffset_ = startOffset;
- this.endNode_ = endNode;
- this.endOffset_ = endOffset;
- if(startNode.nodeType == 1 && startNode.tagName != "BR") {
- var startChildren = startNode.childNodes, candidate = startChildren[startOffset];
- if(candidate) {
- this.startNode_ = candidate;
- this.startOffset_ = 0
- }else {
- if(startChildren.length)this.startNode_ = goog$array$peek(startChildren);
- goNext = true
- }
- }if(endNode.nodeType == 1)if(this.endNode_ = endNode.childNodes[endOffset])this.endOffset_ = 0;
- else this.endNode_ = endNode
- }goog$dom$RangeIterator.call(this, opt_reverse ? this.endNode_ : this.startNode_, opt_reverse);
- if(goNext)try {
- this.next()
- }catch(e) {
- if(e != goog$iter$StopIteration)throw e;
- }
-};
-goog$inherits(goog$dom$TextRangeIterator, goog$dom$RangeIterator);
-goog$dom$TextRangeIterator.prototype.startNode_ = null;
-goog$dom$TextRangeIterator.prototype.endNode_ = null;
-goog$dom$TextRangeIterator.prototype.startOffset_ = 0;
-goog$dom$TextRangeIterator.prototype.endOffset_ = 0;
-goog$dom$TextRangeIterator.prototype.getStartNode = function() {
- return this.startNode_
-};
-goog$dom$TextRangeIterator.prototype.getEndNode = function() {
- return this.endNode_
-};
-goog$dom$TextRangeIterator.prototype.isLast = function() {
- return this.started_ && this.node == this.endNode_ && (!this.endOffset_ || !this.isStartTag())
-};
-goog$dom$TextRangeIterator.prototype.next = function() {
- if(this.isLast())throw goog$iter$StopIteration;return goog$dom$TextRangeIterator.superClass_.next.call(this)
-};var goog$userAgent$jscript$DETECTED_HAS_JSCRIPT_, goog$userAgent$jscript$DETECTED_VERSION_, JSCompiler_inline_hasScriptEngine_44 = "ScriptEngine" in goog$global;
-goog$userAgent$jscript$DETECTED_VERSION_ = (goog$userAgent$jscript$DETECTED_HAS_JSCRIPT_ = JSCompiler_inline_hasScriptEngine_44 && goog$global.ScriptEngine() == "JScript") ? goog$global.ScriptEngineMajorVersion() + "." + goog$global.ScriptEngineMinorVersion() + "." + goog$global.ScriptEngineBuildVersion() : "0";var goog$dom$browserrange$AbstractRange = function() {
-};
-goog$dom$browserrange$AbstractRange.prototype.containsRange = function(range, opt_allowPartial) {
- return this.containsBrowserRange(range.range_, opt_allowPartial)
-};
-goog$dom$browserrange$AbstractRange.prototype.containsBrowserRange = function(range, opt_allowPartial) {
- try {
- return opt_allowPartial ? this.compareBrowserRangeEndpoints(range, 0, 1) >= 0 && this.compareBrowserRangeEndpoints(range, 1, 0) <= 0 : this.compareBrowserRangeEndpoints(range, 0, 0) >= 0 && this.compareBrowserRangeEndpoints(range, 1, 1) <= 0
- }catch(e) {
- if(!goog$userAgent$IE)throw e;return false
- }
-};
-goog$dom$browserrange$AbstractRange.prototype.containsNode = function(node, opt_allowPartial) {
- return this.containsRange(goog$userAgent$IE ? goog$dom$browserrange$IeRange$createFromNodeContents(node) : goog$userAgent$WEBKIT ? new goog$dom$browserrange$WebKitRange(goog$dom$browserrange$W3cRange$getBrowserRangeForNode(node)) : goog$userAgent$GECKO ? new goog$dom$browserrange$GeckoRange(goog$dom$browserrange$W3cRange$getBrowserRangeForNode(node)) : new goog$dom$browserrange$W3cRange(goog$dom$browserrange$W3cRange$getBrowserRangeForNode(node)), opt_allowPartial)
-};
-goog$dom$browserrange$AbstractRange.prototype.__iterator__ = function() {
- return new goog$dom$TextRangeIterator(this.getStartNode(), this.getStartOffset(), this.getEndNode(), this.getEndOffset())
-};var goog$dom$browserrange$W3cRange = function(range) {
- this.range_ = range
-};
-goog$inherits(goog$dom$browserrange$W3cRange, goog$dom$browserrange$AbstractRange);
-var goog$dom$browserrange$W3cRange$getBrowserRangeForNode = function(node) {
- var nodeRange = goog$dom$getOwnerDocument(node).createRange();
- if(node.nodeType == 3) {
- nodeRange.setStart(node, 0);
- nodeRange.setEnd(node, node.length)
- }else {
- for(var tempNode, leaf = node;tempNode = leaf.firstChild;)leaf = tempNode;
- nodeRange.setStart(leaf, 0);
- for(leaf = node;tempNode = leaf.lastChild;)leaf = tempNode;
- nodeRange.setEnd(leaf, leaf.nodeType == 1 ? leaf.childNodes.length : leaf.length)
- }return nodeRange
-}, goog$dom$browserrange$W3cRange$getBrowserRangeForNodes_ = function(startNode, startOffset, endNode, endOffset) {
- var nodeRange = goog$dom$getOwnerDocument(startNode).createRange();
- nodeRange.setStart(startNode, startOffset);
- nodeRange.setEnd(endNode, endOffset);
- return nodeRange
-};
-goog$dom$browserrange$W3cRange.prototype.getContainer = function() {
- return this.range_.commonAncestorContainer
-};
-goog$dom$browserrange$W3cRange.prototype.getStartNode = function() {
- return this.range_.startContainer
-};
-goog$dom$browserrange$W3cRange.prototype.getStartOffset = function() {
- return this.range_.startOffset
-};
-goog$dom$browserrange$W3cRange.prototype.getEndNode = function() {
- return this.range_.endContainer
-};
-goog$dom$browserrange$W3cRange.prototype.getEndOffset = function() {
- return this.range_.endOffset
-};
-goog$dom$browserrange$W3cRange.prototype.compareBrowserRangeEndpoints = function(range, thisEndpoint, otherEndpoint) {
- return this.range_.compareBoundaryPoints(otherEndpoint == 1 ? thisEndpoint == 1 ? goog$global.Range.START_TO_START : goog$global.Range.START_TO_END : thisEndpoint == 1 ? goog$global.Range.END_TO_START : goog$global.Range.END_TO_END, range)
-};
-goog$dom$browserrange$W3cRange.prototype.isCollapsed = function() {
- return this.range_.collapsed
-};
-goog$dom$browserrange$W3cRange.prototype.select = function(reverse) {
- var win = goog$dom$getWindow(goog$dom$getOwnerDocument(this.getStartNode()));
- this.selectInternal(win.getSelection(), reverse)
-};
-goog$dom$browserrange$W3cRange.prototype.selectInternal = function(selection) {
- selection.addRange(this.range_)
-};
-goog$dom$browserrange$W3cRange.prototype.collapse = function(toStart) {
- this.range_.collapse(toStart)
-};var goog$dom$browserrange$GeckoRange = function(range) {
- goog$dom$browserrange$W3cRange.call(this, range)
-};
-goog$inherits(goog$dom$browserrange$GeckoRange, goog$dom$browserrange$W3cRange);
-goog$dom$browserrange$GeckoRange.prototype.selectInternal = function(selection, reversed) {
- var anchorNode = reversed ? this.getEndNode() : this.getStartNode(), anchorOffset = reversed ? this.getEndOffset() : this.getStartOffset(), focusNode = reversed ? this.getStartNode() : this.getEndNode(), focusOffset = reversed ? this.getStartOffset() : this.getEndOffset();
- selection.collapse(anchorNode, anchorOffset);
- if(anchorNode != focusNode || anchorOffset != focusOffset)selection.extend(focusNode, focusOffset)
-};var goog$dom$browserrange$IeRange = function(range, doc) {
- this.range_ = range;
- this.doc_ = doc
-};
-goog$inherits(goog$dom$browserrange$IeRange, goog$dom$browserrange$AbstractRange);
-var goog$dom$browserrange$IeRange$logger_ = goog$debug$LogManager$getLogger("goog.dom.browserrange.IeRange"), goog$dom$browserrange$IeRange$getBrowserRangeForNode_ = function(node) {
- var nodeRange = goog$dom$getOwnerDocument(node).body.createTextRange();
- if(node.nodeType == 1)nodeRange.moveToElementText(node);
- else {
- for(var offset = 0, sibling = node;sibling = sibling.previousSibling;) {
- var nodeType = sibling.nodeType;
- if(nodeType == 3)offset += sibling.length;
- else if(nodeType == 1) {
- nodeRange.moveToElementText(sibling);
- break
- }
- }sibling || nodeRange.moveToElementText(node.parentNode);
- nodeRange.collapse(!sibling);
- offset && nodeRange.move("character", offset);
- nodeRange.moveEnd("character", node.length)
- }return nodeRange
-}, goog$dom$browserrange$IeRange$getBrowserRangeForNodes_ = function(startNode, startOffset, endNode, endOffset) {
- var child, collapse = false;
- if(startNode.nodeType == 1) {
- startOffset > startNode.childNodes.length && goog$dom$browserrange$IeRange$logger_.severe("Cannot have startOffset > startNode child count");
- child = startNode.childNodes[startOffset];
- collapse = !child;
- startNode = child || startNode;
- startOffset = 0
- }var leftRange = goog$dom$browserrange$IeRange$getBrowserRangeForNode_(startNode);
- startOffset && leftRange.move("character", startOffset);
- collapse && leftRange.collapse(false);
- collapse = false;
- if(endNode.nodeType == 1) {
- startOffset > startNode.childNodes.length && goog$dom$browserrange$IeRange$logger_.severe("Cannot have endOffset > endNode child count");
- endNode = (child = endNode.childNodes[endOffset]) || endNode;
- if(endNode.tagName == "BR")endOffset = 1;
- else {
- endOffset = 0;
- collapse = !child
- }
- }var rightRange = goog$dom$browserrange$IeRange$getBrowserRangeForNode_(endNode);
- rightRange.collapse(!collapse);
- endOffset && rightRange.moveEnd("character", endOffset);
- leftRange.setEndPoint("EndToEnd", rightRange);
- return leftRange
-}, goog$dom$browserrange$IeRange$createFromNodeContents = function(node) {
- var range = new goog$dom$browserrange$IeRange(goog$dom$browserrange$IeRange$getBrowserRangeForNode_(node), goog$dom$getOwnerDocument(node));
- range.parentNode_ = node;
- return range
-};
-goog$dom$browserrange$IeRange.prototype.parentNode_ = null;
-goog$dom$browserrange$IeRange.prototype.startNode_ = null;
-goog$dom$browserrange$IeRange.prototype.endNode_ = null;
-goog$dom$browserrange$IeRange.prototype.clearCachedValues_ = function() {
- this.parentNode_ = this.startNode_ = this.endNode_ = null
-};
-goog$dom$browserrange$IeRange.prototype.getContainer = function() {
- if(!this.parentNode_) {
- for(var selectText = this.range_.text, i = 1;selectText.charAt(selectText.length - i) == " ";i++)this.range_.moveEnd("character", -1);
- for(var parent = this.range_.parentElement(), htmlText = this.range_.htmlText.replace(/(\r\n|\r|\n)+/g, " ");htmlText.length > parent.outerHTML.replace(/(\r\n|\r|\n)+/g, " ").length;)parent = parent.parentNode;
- for(;parent.childNodes.length == 1 && parent.innerText == (parent.firstChild.nodeType == 3 ? parent.firstChild.nodeValue : parent.firstChild.innerText);) {
- if(parent.firstChild.tagName == "IMG")break;
- parent = parent.firstChild
- }if(selectText.length == 0)parent = this.findDeepestContainer_(parent);
- this.parentNode_ = parent
- }return this.parentNode_
-};
-goog$dom$browserrange$IeRange.prototype.findDeepestContainer_ = function(node) {
- for(var childNodes = node.childNodes, i = 0, len = childNodes.length;i < len;i++) {
- var child = childNodes[i];
- if(child.nodeType == 1)if(this.range_.inRange(goog$dom$browserrange$IeRange$getBrowserRangeForNode_(child)))return this.findDeepestContainer_(child)
- }return node
-};
-goog$dom$browserrange$IeRange.prototype.getStartNode = function() {
- return this.startNode_ || (this.startNode_ = this.getEndpointNode_(1))
-};
-goog$dom$browserrange$IeRange.prototype.getStartOffset = function() {
- return this.getOffset_(1)
-};
-goog$dom$browserrange$IeRange.prototype.getEndNode = function() {
- return this.endNode_ || (this.endNode_ = this.getEndpointNode_(0))
-};
-goog$dom$browserrange$IeRange.prototype.getEndOffset = function() {
- return this.getOffset_(0)
-};
-goog$dom$browserrange$IeRange.prototype.containsRange = function(range, opt_allowPartial) {
- return this.containsBrowserRange(range.range_, opt_allowPartial)
-};
-goog$dom$browserrange$IeRange.prototype.compareBrowserRangeEndpoints = function(range, thisEndpoint, otherEndpoint) {
- return this.range_.compareEndPoints((thisEndpoint == 1 ? "Start" : "End") + "To" + (otherEndpoint == 1 ? "Start" : "End"), range)
-};
-goog$dom$browserrange$IeRange.prototype.getEndpointNode_ = function(endpoint, opt_node) {
- var node = opt_node || this.getContainer();
- if(!node || !node.firstChild) {
- if(endpoint == 0 && node.previousSibling && node.previousSibling.tagName == "BR" && this.getOffset_(endpoint, node) == 0)node = node.previousSibling;
- return node.tagName == "BR" ? node.parentNode : node
- }for(var child = endpoint == 1 ? node.firstChild : node.lastChild;child;) {
- if(this.containsNode(child, true))return this.getEndpointNode_(endpoint, child);
- child = endpoint == 1 ? child.nextSibling : child.previousSibling
- }return node
-};
-goog$dom$browserrange$IeRange.prototype.getOffset_ = function(endpoint, opt_container) {
- var container = opt_container || (endpoint == 1 ? this.getStartNode() : this.getEndNode());
- if(container.nodeType == 1) {
- for(var children = container.childNodes, len = children.length, i = endpoint == 1 ? 0 : len - 1;i >= 0 && i < len;) {
- var child = children[i];
- if(this.containsNode(child, true)) {
- endpoint == 0 && child.previousSibling && child.previousSibling.tagName == "BR" && this.getOffset_(endpoint, child) == 0 && i--;
- break
- }i += endpoint == 1 ? 1 : -1
- }return i == -1 ? 0 : i
- }else {
- var range = this.range_.duplicate(), nodeRange = goog$dom$browserrange$IeRange$getBrowserRangeForNode_(container);
- range.setEndPoint(endpoint == 1 ? "EndToEnd" : "StartToStart", nodeRange);
- var rangeLength = range.text.length;
- return endpoint == 0 ? rangeLength : container.length - rangeLength
- }
-};
-goog$dom$browserrange$IeRange.prototype.isCollapsed = function() {
- return this.range_.text == ""
-};
-goog$dom$browserrange$IeRange.prototype.select = function() {
- this.range_.select()
-};
-goog$dom$browserrange$IeRange.prototype.collapse = function(toStart) {
- this.range_.collapse(toStart);
- if(toStart)this.endNode_ = this.startNode_;
- else this.startNode_ = this.endNode_
-};var goog$dom$browserrange$WebKitRange = function(range) {
- goog$dom$browserrange$W3cRange.call(this, range)
-};
-goog$inherits(goog$dom$browserrange$WebKitRange, goog$dom$browserrange$W3cRange);
-goog$dom$browserrange$WebKitRange.prototype.compareBrowserRangeEndpoints = function(range, thisEndpoint, otherEndpoint) {
- if(goog$userAgent$isVersion("528"))return goog$dom$browserrange$WebKitRange.superClass_.compareBrowserRangeEndpoints.call(this, range, thisEndpoint, otherEndpoint);
- return this.range_.compareBoundaryPoints(otherEndpoint == 1 ? thisEndpoint == 1 ? goog$global.Range.START_TO_START : goog$global.Range.END_TO_START : thisEndpoint == 1 ? goog$global.Range.START_TO_END : goog$global.Range.END_TO_END, range)
-};
-goog$dom$browserrange$WebKitRange.prototype.selectInternal = function(selection, reversed) {
- selection.removeAllRanges();
- reversed ? selection.setBaseAndExtent(this.getEndNode(), this.getEndOffset(), this.getStartNode(), this.getStartOffset()) : selection.setBaseAndExtent(this.getStartNode(), this.getStartOffset(), this.getEndNode(), this.getEndOffset())
-};var goog$dom$browserrange$createRangeFromNodes = function(startNode, startOffset, endNode, endOffset) {
- return goog$userAgent$IE ? new goog$dom$browserrange$IeRange(goog$dom$browserrange$IeRange$getBrowserRangeForNodes_(startNode, startOffset, endNode, endOffset), goog$dom$getOwnerDocument(startNode)) : goog$userAgent$WEBKIT ? new goog$dom$browserrange$WebKitRange(goog$dom$browserrange$W3cRange$getBrowserRangeForNodes_(startNode, startOffset, endNode, endOffset)) : goog$userAgent$GECKO ? new goog$dom$browserrange$GeckoRange(goog$dom$browserrange$W3cRange$getBrowserRangeForNodes_(startNode, startOffset,
- endNode, endOffset)) : new goog$dom$browserrange$W3cRange(goog$dom$browserrange$W3cRange$getBrowserRangeForNodes_(startNode, startOffset, endNode, endOffset))
-};var goog$dom$TextRange = function() {
-};
-goog$inherits(goog$dom$TextRange, goog$dom$AbstractRange);
-var goog$dom$TextRange$createFromBrowserRangeWrapper_ = function(browserRange, opt_isReversed) {
- var range = new goog$dom$TextRange;
- range.browserRangeWrapper_ = browserRange;
- range.isReversed_ = !!opt_isReversed;
- return range
-}, goog$dom$TextRange$createFromNodeContents = function(node, opt_isReversed) {
- return goog$dom$TextRange$createFromBrowserRangeWrapper_(goog$userAgent$IE ? goog$dom$browserrange$IeRange$createFromNodeContents(node) : goog$userAgent$WEBKIT ? new goog$dom$browserrange$WebKitRange(goog$dom$browserrange$W3cRange$getBrowserRangeForNode(node)) : goog$userAgent$GECKO ? new goog$dom$browserrange$GeckoRange(goog$dom$browserrange$W3cRange$getBrowserRangeForNode(node)) : new goog$dom$browserrange$W3cRange(goog$dom$browserrange$W3cRange$getBrowserRangeForNode(node)), opt_isReversed)
-}, goog$dom$TextRange$createFromNodes = function(anchorNode, anchorOffset, focusNode, focusOffset) {
- var range = new goog$dom$TextRange;
- range.isReversed_ = goog$dom$Range$isReversed(anchorNode, anchorOffset, focusNode, focusOffset);
- if(anchorNode.tagName == "BR") {
- var parent = anchorNode.parentNode;
- anchorOffset = goog$array$indexOf(parent.childNodes, anchorNode);
- anchorNode = parent
- }if(focusNode.tagName == "BR") {
- parent = focusNode.parentNode;
- focusOffset = goog$array$indexOf(parent.childNodes, focusNode);
- focusNode = parent
- }if(range.isReversed_) {
- range.startNode_ = focusNode;
- range.startOffset_ = focusOffset;
- range.endNode_ = anchorNode;
- range.endOffset_ = anchorOffset
- }else {
- range.startNode_ = anchorNode;
- range.startOffset_ = anchorOffset;
- range.endNode_ = focusNode;
- range.endOffset_ = focusOffset
- }return range
-};
-goog$dom$TextRange.prototype.browserRangeWrapper_ = null;
-goog$dom$TextRange.prototype.startNode_ = null;
-goog$dom$TextRange.prototype.startOffset_ = null;
-goog$dom$TextRange.prototype.endNode_ = null;
-goog$dom$TextRange.prototype.endOffset_ = null;
-goog$dom$TextRange.prototype.isReversed_ = false;
-goog$dom$TextRange.prototype.getType = function() {
- return"text"
-};
-goog$dom$TextRange.prototype.getBrowserRangeObject = function() {
- return this.getBrowserRangeWrapper_().range_
-};
-goog$dom$TextRange.prototype.clearCachedValues_ = function() {
- this.startNode_ = this.startOffset_ = this.endNode_ = this.endOffset_ = null
-};
-goog$dom$TextRange.prototype.getTextRangeCount = function() {
- return 1
-};
-goog$dom$TextRange.prototype.getTextRange = function() {
- return this
-};
-goog$dom$TextRange.prototype.getBrowserRangeWrapper_ = function() {
- return this.browserRangeWrapper_ || (this.browserRangeWrapper_ = goog$dom$browserrange$createRangeFromNodes(this.getStartNode(), this.getStartOffset(), this.getEndNode(), this.getEndOffset()))
-};
-goog$dom$TextRange.prototype.getContainer = function() {
- return this.getBrowserRangeWrapper_().getContainer()
-};
-goog$dom$TextRange.prototype.getStartNode = function() {
- return this.startNode_ || (this.startNode_ = this.getBrowserRangeWrapper_().getStartNode())
-};
-goog$dom$TextRange.prototype.getStartOffset = function() {
- return this.startOffset_ != null ? this.startOffset_ : (this.startOffset_ = this.getBrowserRangeWrapper_().getStartOffset())
-};
-goog$dom$TextRange.prototype.getEndNode = function() {
- return this.endNode_ || (this.endNode_ = this.getBrowserRangeWrapper_().getEndNode())
-};
-goog$dom$TextRange.prototype.getEndOffset = function() {
- return this.endOffset_ != null ? this.endOffset_ : (this.endOffset_ = this.getBrowserRangeWrapper_().getEndOffset())
-};
-goog$dom$TextRange.prototype.isReversed = function() {
- return this.isReversed_
-};
-goog$dom$TextRange.prototype.containsRange = function(otherRange, opt_allowPartial) {
- var otherRangeType = otherRange.getType();
- if(otherRangeType == "text")return this.getBrowserRangeWrapper_().containsRange(otherRange.getBrowserRangeWrapper_(), opt_allowPartial);
- else if(otherRangeType == "control") {
- var elements = otherRange.getElements(), fn = opt_allowPartial ? goog$array$some : goog$array$every;
- return fn(elements, function(el) {
- return this.containsNode(el, opt_allowPartial)
- }, this)
- }
-};
-goog$dom$TextRange.prototype.isCollapsed = function() {
- return this.getBrowserRangeWrapper_().isCollapsed()
-};
-goog$dom$TextRange.prototype.__iterator__ = function() {
- return new goog$dom$TextRangeIterator(this.getStartNode(), this.getStartOffset(), this.getEndNode(), this.getEndOffset())
-};
-goog$dom$TextRange.prototype.select = function() {
- this.getBrowserRangeWrapper_().select(this.isReversed_)
-};
-goog$dom$TextRange.prototype.saveUsingDom = function() {
- return new goog$dom$DomSavedTextRange_(this)
-};
-goog$dom$TextRange.prototype.collapse = function(toAnchor) {
- var toStart = this.isReversed() ? !toAnchor : toAnchor;
- this.browserRangeWrapper_ && this.browserRangeWrapper_.collapse(toStart);
- if(toStart) {
- this.endNode_ = this.startNode_;
- this.endOffset_ = this.startOffset_
- }else {
- this.startNode_ = this.endNode_;
- this.startOffset_ = this.endOffset_
- }this.isReversed_ = false
-};
-var goog$dom$DomSavedTextRange_ = function(range) {
- this.anchorNode_ = range.getAnchorNode();
- this.anchorOffset_ = range.getAnchorOffset();
- this.focusNode_ = range.getFocusNode();
- this.focusOffset_ = range.getFocusOffset()
-};
-goog$inherits(goog$dom$DomSavedTextRange_, goog$dom$SavedRange);var goog$dom$ControlRange = function() {
-};
-goog$inherits(goog$dom$ControlRange, goog$dom$AbstractMultiRange);
-goog$dom$ControlRange.prototype.range_ = null;
-goog$dom$ControlRange.prototype.elements_ = null;
-goog$dom$ControlRange.prototype.sortedElements_ = null;
-goog$dom$ControlRange.prototype.clearCachedValues_ = function() {
- this.sortedElements_ = this.elements_ = null
-};
-goog$dom$ControlRange.prototype.getType = function() {
- return"control"
-};
-goog$dom$ControlRange.prototype.getBrowserRangeObject = function() {
- return this.range_ || document.body.createControlRange()
-};
-goog$dom$ControlRange.prototype.getTextRangeCount = function() {
- return this.range_ ? this.range_.length : 0
-};
-goog$dom$ControlRange.prototype.getTextRange = function(i) {
- return goog$dom$TextRange$createFromNodeContents(this.range_.item(i))
-};
-goog$dom$ControlRange.prototype.getContainer = function() {
- return goog$dom$findCommonAncestor.apply(null, this.getElements())
-};
-goog$dom$ControlRange.prototype.getStartNode = function() {
- return this.getSortedElements()[0]
-};
-goog$dom$ControlRange.prototype.getStartOffset = function() {
- return 0
-};
-goog$dom$ControlRange.prototype.getEndNode = function() {
- var sorted = this.getSortedElements(), startsLast = goog$array$peek(sorted);
- return goog$array$find(sorted, function(el) {
- return goog$dom$contains(el, startsLast)
- })
-};
-goog$dom$ControlRange.prototype.getEndOffset = function() {
- return this.getEndNode().childNodes.length
-};
-goog$dom$ControlRange.prototype.getElements = function() {
- if(!this.elements_) {
- this.elements_ = [];
- if(this.range_)for(var i = 0;i < this.range_.length;i++)this.elements_.push(this.range_.item(i))
- }return this.elements_
-};
-goog$dom$ControlRange.prototype.getSortedElements = function() {
- if(!this.sortedElements_) {
- this.sortedElements_ = this.getElements().concat();
- this.sortedElements_.sort(function(a, b) {
- return a.sourceIndex - b.sourceIndex
- })
- }return this.sortedElements_
-};
-goog$dom$ControlRange.prototype.isCollapsed = function() {
- return!this.range_ || !this.range_.length
-};
-goog$dom$ControlRange.prototype.__iterator__ = function() {
- return new goog$dom$ControlRangeIterator(this)
-};
-goog$dom$ControlRange.prototype.select = function() {
- this.range_ && this.range_.select()
-};
-goog$dom$ControlRange.prototype.saveUsingDom = function() {
- return new goog$dom$DomSavedControlRange_(this)
-};
-goog$dom$ControlRange.prototype.collapse = function() {
- this.range_ = null;
- this.clearCachedValues_()
-};
-var goog$dom$DomSavedControlRange_ = function(range) {
- this.elements_ = range.getElements()
-};
-goog$inherits(goog$dom$DomSavedControlRange_, goog$dom$SavedRange);
-var goog$dom$ControlRangeIterator = function(range) {
- if(range) {
- this.elements_ = range.getSortedElements();
- this.startNode_ = this.elements_.shift();
- this.endNode_ = goog$array$peek(this.elements_) || this.startNode_
- }goog$dom$RangeIterator.call(this, this.startNode_, false)
-};
-goog$inherits(goog$dom$ControlRangeIterator, goog$dom$RangeIterator);
-goog$dom$ControlRangeIterator.prototype.startNode_ = null;
-goog$dom$ControlRangeIterator.prototype.endNode_ = null;
-goog$dom$ControlRangeIterator.prototype.elements_ = null;
-goog$dom$ControlRangeIterator.prototype.getStartNode = function() {
- return this.startNode_
-};
-goog$dom$ControlRangeIterator.prototype.getEndNode = function() {
- return this.endNode_
-};
-goog$dom$ControlRangeIterator.prototype.isLast = function() {
- return!this.depth && !this.elements_.length
-};
-goog$dom$ControlRangeIterator.prototype.next = function() {
- if(this.isLast())throw goog$iter$StopIteration;else if(!this.depth) {
- var el = this.elements_.shift();
- this.setPosition(el, 1, 1);
- return el
- }return goog$dom$ControlRangeIterator.superClass_.next.call(this)
-};var goog$dom$MultiRange = function() {
- this.browserRanges_ = [];
- this.ranges_ = [];
- this.container_ = this.sortedRanges_ = null
-};
-goog$inherits(goog$dom$MultiRange, goog$dom$AbstractMultiRange);
-goog$dom$MultiRange.prototype.logger_ = goog$debug$LogManager$getLogger("goog.dom.MultiRange");
-goog$dom$MultiRange.prototype.clearCachedValues_ = function() {
- this.ranges_ = [];
- this.container_ = this.sortedRanges_ = null
-};
-goog$dom$MultiRange.prototype.getType = function() {
- return"mutli"
-};
-goog$dom$MultiRange.prototype.getBrowserRangeObject = function() {
- this.browserRanges_.length > 1 && this.logger_.warning("getBrowserRangeObject called on MultiRange with more than 1 range");
- return this.browserRanges_[0]
-};
-goog$dom$MultiRange.prototype.getTextRangeCount = function() {
- return this.browserRanges_.length
-};
-goog$dom$MultiRange.prototype.getTextRange = function(i) {
- this.ranges_[i] || (this.ranges_[i] = goog$dom$TextRange$createFromBrowserRangeWrapper_(goog$userAgent$IE ? new goog$dom$browserrange$IeRange(this.browserRanges_[i], goog$dom$getOwnerDocument(this.browserRanges_[i].parentElement())) : goog$userAgent$WEBKIT ? new goog$dom$browserrange$WebKitRange(this.browserRanges_[i]) : goog$userAgent$GECKO ? new goog$dom$browserrange$GeckoRange(this.browserRanges_[i]) : new goog$dom$browserrange$W3cRange(this.browserRanges_[i]), undefined));
- return this.ranges_[i]
-};
-goog$dom$MultiRange.prototype.getContainer = function() {
- if(!this.container_) {
- for(var nodes = [], i = 0, len = this.getTextRangeCount();i < len;i++)nodes.push(this.getTextRange(i).getContainer());
- this.container_ = goog$dom$findCommonAncestor.apply(null, nodes)
- }return this.container_
-};
-goog$dom$MultiRange.prototype.getSortedRanges = function() {
- if(!this.sortedRanges_) {
- this.sortedRanges_ = this.getTextRanges();
- this.sortedRanges_.sort(function(a, b) {
- var aStartNode = a.getStartNode(), aStartOffset = a.getStartOffset(), bStartNode = b.getStartNode(), bStartOffset = b.getStartOffset();
- if(aStartNode == bStartNode && aStartOffset == bStartOffset)return 0;
- return goog$dom$Range$isReversed(aStartNode, aStartOffset, bStartNode, bStartOffset) ? 1 : -1
- })
- }return this.sortedRanges_
-};
-goog$dom$MultiRange.prototype.getStartNode = function() {
- return this.getSortedRanges()[0].getStartNode()
-};
-goog$dom$MultiRange.prototype.getStartOffset = function() {
- return this.getSortedRanges()[0].getStartOffset()
-};
-goog$dom$MultiRange.prototype.getEndNode = function() {
- return goog$array$peek(this.getSortedRanges()).getEndNode()
-};
-goog$dom$MultiRange.prototype.getEndOffset = function() {
- return goog$array$peek(this.getSortedRanges()).getEndOffset()
-};
-goog$dom$MultiRange.prototype.isCollapsed = function() {
- return this.browserRanges_.length == 0 || this.browserRanges_.length == 1 && this.getTextRange(0).isCollapsed()
-};
-goog$dom$MultiRange.prototype.__iterator__ = function() {
- return new goog$dom$MultiRangeIterator(this)
-};
-goog$dom$MultiRange.prototype.select = function() {
- var selection;
- JSCompiler_inline_label_goog$dom$AbstractRange$getBrowserSelectionForWindow_50: {
- var JSCompiler_inline_win = this.getWindow();
- if(JSCompiler_inline_win.getSelection)selection = JSCompiler_inline_win.getSelection();
- else {
- var JSCompiler_inline_doc = JSCompiler_inline_win.document;
- selection = JSCompiler_inline_doc.selection || JSCompiler_inline_doc.getSelection && JSCompiler_inline_doc.getSelection()
- }
- }selection.removeAllRanges();
- for(var i = 0, len = this.getTextRangeCount();i < len;i++)selection.addRange(this.getTextRange(i).getBrowserRangeObject())
-};
-goog$dom$MultiRange.prototype.saveUsingDom = function() {
- return new goog$dom$DomSavedMultiRange_(this)
-};
-goog$dom$MultiRange.prototype.collapse = function(toAnchor) {
- if(!this.isCollapsed()) {
- var range = toAnchor ? this.getTextRange(0) : this.getTextRange(this.getTextRangeCount() - 1);
- this.clearCachedValues_();
- range.collapse(toAnchor);
- this.ranges_ = [range];
- this.sortedRanges_ = [range];
- this.browserRanges_ = [range.getBrowserRangeObject()]
- }
-};
-var goog$dom$DomSavedMultiRange_ = function(range) {
- this.savedRanges_ = goog$array$map(range.getTextRanges(), function(range) {
- return range.saveUsingDom()
- })
-};
-goog$inherits(goog$dom$DomSavedMultiRange_, goog$dom$SavedRange);
-var goog$dom$MultiRangeIterator = function(range) {
- if(range) {
- this.ranges_ = range.getSortedRanges();
- if(this.ranges_.length) {
- this.startNode_ = this.ranges_[0].getStartNode();
- this.endNode_ = goog$array$peek(this.ranges_).getEndNode()
- }
- }goog$dom$RangeIterator.call(this, this.startNode_, false)
-};
-goog$inherits(goog$dom$MultiRangeIterator, goog$dom$RangeIterator);
-goog$dom$MultiRangeIterator.prototype.startNode_ = null;
-goog$dom$MultiRangeIterator.prototype.endNode_ = null;
-goog$dom$MultiRangeIterator.prototype.ranges_ = null;
-goog$dom$MultiRangeIterator.prototype.getStartNode = function() {
- return this.startNode_
-};
-goog$dom$MultiRangeIterator.prototype.getEndNode = function() {
- return this.endNode_
-};
-goog$dom$MultiRangeIterator.prototype.isLast = function() {
- return this.ranges_.length == 1 && this.ranges_[0].isLast()
-};
-goog$dom$MultiRangeIterator.prototype.next = function() {
- do try {
- this.ranges_[0].next();
- break
- }catch(ex) {
- if(ex != goog$iter$StopIteration)throw ex;this.ranges_.shift()
- }while(this.ranges_.length);
- if(this.ranges_.length) {
- var range = this.ranges_[0];
- this.setPosition(range.node, range.tagType, range.depth);
- return range.node
- }else throw goog$iter$StopIteration;
-};var goog$dom$Range$createCaret = function(node, offset) {
- return goog$dom$TextRange$createFromNodes(node, offset, node, offset)
-}, goog$dom$Range$createFromNodes = function(startNode, startOffset, endNode, endOffset) {
- return goog$dom$TextRange$createFromNodes(startNode, startOffset, endNode, endOffset)
-}, goog$dom$Range$isReversed = function(anchorNode, anchorOffset, focusNode, focusOffset) {
- if(anchorNode == focusNode)return focusOffset < anchorOffset;
- var child;
- if(anchorNode.nodeType == 1 && anchorOffset)if(child = anchorNode.childNodes[anchorOffset]) {
- anchorNode = child;
- anchorOffset = 0
- }else if(goog$dom$contains(anchorNode, focusNode))return true;
- if(focusNode.nodeType == 1 && focusOffset)if(child = focusNode.childNodes[focusOffset]) {
- focusNode = child;
- focusOffset = 0
- }else if(goog$dom$contains(focusNode, anchorNode))return false;
- return(goog$dom$compareNodeOrder(anchorNode, focusNode) || anchorOffset - focusOffset) > 0
-};window.createCaret = goog$dom$Range$createCaret;
-window.createFromNodes = goog$dom$Range$createFromNodes;
-try {
- goog$dom$Range$createCaret(document.body, 0).select()
-}catch(e$$13) {
-};
-
-/**************************************************
- Trace:
- 56.427 Start Handling request
- 0 56.427 Start Building cUnit
- 1 56.428 Done 1 ms Building cUnit
- 0 56.428 Start Checking memcacheg
- 0 56.428 Start Connecting to memcacheg
- 8 56.436 Done 8 ms Connecting to memcacheg
- 1 56.437 Done 9 ms Checking memcacheg
- 0 56.437 Done 10 ms Handling request
-**************************************************/
diff --git a/editor/libeditor/tests/browserscope/lib/richtext/richtext/richtext.html b/editor/libeditor/tests/browserscope/lib/richtext/richtext/richtext.html
deleted file mode 100644
index ef0e22f2a..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext/richtext/richtext.html
+++ /dev/null
@@ -1,1081 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
- <meta http-equiv="content-type" content="text/html; charset=utf-8" />
- <title>Rich Text Tests</title>
- <script src="js/range.js"></script>
- <script>
- /**
- * Color class allows cross-browser comparison of values, which can
- * be returned from queryCommandValue in several formats:
- * 0xff00ff
- * rgb(255, 0, 0)
- * Number containing the hex value
- */
- function Color(value) {
- this.compare = function(other) {
- if (!this.valid || !other.valid) {
- return false;
- }
- return this.red == other.red && this.green == other.green && this.blue == other.blue;
- }
- this.parse = function(value) {
- var hexMatch = String(value).match(/#([0-9a-f]{6})/i);
- if (hexMatch) {
- this.red = parseInt(hexMatch[1].substring(0, 2), 16);
- this.green = parseInt(hexMatch[1].substring(2, 4), 16);
- this.blue = parseInt(hexMatch[1].substring(4, 6), 16);
- return true;
- }
- var rgbMatch = String(value).match(/rgb\(([0-9]{1,3}),\s*([0-9]{1,3}),\s*([0-9]{1,3})\)/i);
- if (rgbMatch) {
- this.red = Number(rgbMatch[1]);
- this.green = Number(rgbMatch[2]);
- this.blue = Number(rgbMatch[3]);
- return true;
- }
- if (Number(value)) {
- this.red = value & 0xFF;
- this.green = (value & 0xFF00) >> 8;
- this.blue = (value & 0xFF0000) >> 16;
- return true;
- }
- return false;
- }
- this.toString = function() {
- return this.red + ',' + this.green + ',' + this.blue;
- }
- this.valid = this.parse(value);
- }
-
- /**
- * Utility class for converting font sizes to the size
- * attribute in a font tag. Currently only converts px because
- * only the sizes and px ever come from queryCommandValue.
- */
- function Size(value) {
- var pxMatch = String(value).match(/([0-9]+)px/);
- if (pxMatch) {
- var px = Number(pxMatch[1]);
- if (px <= 10) {
- this.size = 1;
- } else if (px <= 13) {
- this.size = 2;
- } else if (px <= 16) {
- this.size = 3;
- } else if (px <= 18) {
- this.size = 4;
- } else if (px <= 24) {
- this.size = 5;
- } else if (px <= 32) {
- this.size = 6;
- } else if (px <= 47) {
- this.size = 7;
- } else {
- this.size = NaN;
- }
- } else if (Number(value)) {
- this.size = Number(value);
- } else {
- switch (value) {
- case 'x-small':
- this.size = 1;
- break;
- case 'small':
- this.size = 2;
- break;
- case 'medium':
- this.size = 3;
- break;
- case 'large':
- this.size = 4;
- break;
- case 'x-large':
- this.size = 5;
- break;
- case 'xx-large':
- this.size = 6;
- break;
- case 'xxx-large':
- case '-webkit-xxx-large':
- this.size = 7;
- break;
- default:
- this.size = null;
- }
- }
- this.compare = function(other) {
- return this.size == other.size;
- }
- this.toString = function() {
- return String(this.size);
- }
- }
-
- var IMAGE_URI = '/tests/editor/libeditor/tests/green.png';
-
- var APPLY_TESTS = {
- 'backcolor' : {
- opt_arg: '#FF0000',
- styleWithCSS: 'background-color'},
- 'bold' : {
- opt_arg: null,
- styleWithCSS: 'font-weight'},
- 'createbookmark' : {
- opt_arg: 'bookmark_name'},
- 'createlink' : {
- opt_arg: 'http://www.openweb.org'},
- 'decreasefontsize' : {
- opt_arg: null},
- 'fontname' : {
- opt_arg: 'Arial',
- styleWithCSS: 'font-family'},
- 'fontsize' : {
- opt_arg: 4,
- styleWithCSS: 'font-size'},
- 'forecolor' : {
- opt_arg: '#FF0000',
- styleWithCSS: 'color'},
- 'formatblock' : {
- opt_arg: 'h1',
- wholeline: true},
- 'hilitecolor' : {
- opt_arg: '#FF0000',
- styleWithCSS: 'background-color'},
- 'indent' : {
- opt_arg: null,
- wholeline: true,
- styleWithCSS: 'margin'},
- 'inserthorizontalrule' : {
- opt_arg: null,
- collapse: true},
- 'inserthtml': {
- opt_arg: '<br>',
- collapse: true},
- 'insertimage': {
- opt_arg: IMAGE_URI,
- collapse: true},
- 'insertorderedlist' : {
- opt_arg: null,
- wholeline: true},
- 'insertunorderedlist' : {
- opt_arg: null,
- wholeline: true},
- 'italic' : {
- opt_arg: null,
- styleWithCSS: 'font-style'},
- 'justifycenter' : {
- opt_arg: null,
- wholeline: true,
- styleWithCSS: 'text-align'},
- 'justifyfull' : {
- opt_arg: null,
- wholeline: true,
- styleWithCSS: 'text-align'},
- 'justifyleft' : {
- opt_arg: null,
- wholeline: true,
- styleWithCSS: 'text-align'},
- 'justifyright' : {
- opt_arg: null,
- wholeline: true,
- styleWithCSS: 'text-align'},
- 'strikethrough' : {
- opt_arg: null,
- styleWithCSS: 'text-decoration'},
- 'subscript' : {
- opt_arg: null,
- styleWithCSS: 'vertical-align'},
- 'superscript' : {
- opt_arg: null,
- styleWithCSS: 'vertical-align'},
- 'underline' : {
- opt_arg: null,
- styleWithCSS: 'text-decoration'}};
-
- var UNAPPLY_TESTS = {
- 'bold' : {
- tags: [
- ['<b>', '</b>'],
- ['<STRONG>', '</STRONG>'],
- ['<span style="font-weight: bold;">', '</span>']]},
- 'italic' : {
- tags: [
- ['<i>', '</i>'],
- ['<EM>', '</EM>'],
- ['<span style="font-style: italic;">', '</span>']]},
- 'outdent' : {
- unapply: 'indent',
- block: true,
- tags: [
- ['<blockquote>', '</blockquote>'],
- ['<blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">', '</blockquote>'],
- ['<ul><li>', '</li></ul>'],
- ['<ol><li>', '</li></ol>'],
- ['<div style="margin-left: 40px;">', '</div>']]},
- 'removeformat' : {
- unapply: '*',
- block: true,
- tags: [
- ['<b>', '</b>'],
- ['<a href="http://www.foo.com">', '</a>'],
- ['<table><tr><td>', '</td></tr></table>']]},
- 'strikethrough' : {
- tags: [
- ['<strike>', '</strike>'],
- ['<s>', '</s>'],
- ['<del>', '</del>'],
- ['<span style="text-decoration: line-through;">', '</span>']]},
- 'subscript' : {
- tags: [
- ['<sub>', '</sub>'],
- ['<span style="vertical-align: sub;">', '</span>']]},
- 'superscript' : {
- tags: [
- ['<sup>', '</sup>'],
- ['<span style="vertical-align: super;">', '</span>']]},
- 'unbookmark' : {
- unapply: 'createbookmark',
- tags: [
- ['<a name="bookmark">', '</a>']]},
- 'underline' : {
- tags: [
- ['<u>', '</u>'],
- ['<span style="text-decoration: underline;">', '</span>']]},
- 'unlink' : {
- unapply: 'createbookmark',
- tags: [
- ['<a href="http://www.foo.com">', '</a>']]}};
-
- var QUERY_TESTS = {
- 'backcolor' : {
- type: 'value',
- tests: [
- {html: '<FONT style="BACKGROUND-COLOR: #ffccaa">foo bar baz</FONT>', expected: new Color('#ffccaa')},
- {html: '<span class="Apple-style-span" style="background-color: rgb(255, 0, 0);">foo bar baz</span>', expected: new Color('#ff0000')},
- {html: '<span style="background-color: #ff0000">foo bar baz</span>', expected: new Color('#ff0000')}
- ]
- },
- 'bold' : {
- type: 'state',
- tests: [
- {html: 'foo bar baz', expected: false},
- {html: '<b>foo bar baz</b>', expected: true},
- {html: '<STRONG>foo bar baz</STRONG>', expected: true},
- {html: '<span style="font-weight:bold">foo bar baz</span>', expected: true},
- {html: '<b style="font-weight:normal">foo bar baz</b>', expected: false},
- {html: '<b><span style="font-weight:normal;">foo bar baz</span>', expected: false}
- ]
- },
- 'fontname' : {
- type: 'value',
- tests: [
- {html: '<font face="Arial">foo bar baz</font>', expected: 'Arial'},
- {html: '<span style="font-family:Arial">foo bar baz</span>', expected: 'Arial'},
- {html: '<font face="Arial" style="font-family:Courier">foo bar baz</font>', expected: 'Courier'},
- {html: '<font face="Courier"><font face="Arial">foo bar baz</font></font>', expected: 'Arial'},
- {html: '<span style="font-family:Courier"><font face="Arial">foo bar baz</font></span>', expected: 'Arial'}
- ]
- },
- 'fontsize' : {
- type: 'value',
- tests: [
- {html: '<font size=4>foo bar baz</font>', expected: new Size(4)},
- // IE adds +1 to font size from font-size style attributes.
- // This is hard to correct for since it does NOT add +1 to size attribute from font tag.
- {html: '<span class="Apple-style-span" style="font-size: large;">foo bar baz</span>', expected: new Size(4)},
- {html: '<font size=1 style="font-size:x-large;">foo bar baz</font>', expected: new Size(5)}
- ]
- },
- 'forecolor' : {
- type: 'value',
- tests: [
- {html: '<font color="#ff0000">foo bar baz</font>', expected: new Color('#ff0000')},
- {html: '<span style="color:#ff0000">foo bar baz</span>', expected: new Color('#ff0000')},
- {html: '<font color="#0000ff" style="color:#ff0000">foo bar baz</span>', expected: new Color('#ff0000')}
- ]
- },
- 'hilitecolor' : {
- type: 'value',
- tests: [
- {html: '<FONT style="BACKGROUND-COLOR: #ffccaa">foo bar baz</FONT>', expected: new Color('#ffccaa')},
- {html: '<span class="Apple-style-span" style="background-color: rgb(255, 0, 0);">foo bar baz</span>', expected: new Color('#ff0000')},
- {html: '<span style="background-color: #ff0000">foo bar baz</span>', expected: new Color('#ff0000')}
- ]
- },
- 'insertorderedlist' : {
- type: 'state',
- tests: [
- {html: 'foo bar baz', expected: false},
- {html: '<ol><li>foo bar baz</li></ol>', expected: true},
- {html: '<ul><li>foo bar baz</li></ul>', expected: false}
- ]
- },
- 'insertunorderedlist' : {
- type: 'state',
- tests: [
- {html: 'foo bar baz', expected: false},
- {html: '<ol><li>foo bar baz</li></ol>', expected: false},
- {html: '<ul><li>foo bar baz</li></ul>', expected: true}
- ]
- },
- 'italic' : {
- type: 'state',
- tests: [
- {html: 'foo bar baz', expected: false},
- {html: '<i>foo bar baz</i>', expected: true},
- {html: '<EM>foo bar baz</EM>', expected: true},
- {html: '<span style="font-style:italic">foo bar baz</span>', expected: true},
- {html: '<i><span style="font-style:normal">foo bar baz</span></i>', expected: false}
- ]
- },
- 'justifycenter' : {
- type: 'state',
- tests: [
- {html: 'foo bar baz', expected: false},
- {html: '<div align="center">foo bar baz</div>', expected: true},
- {html: '<p align="center">foo bar baz</p>', expected: true},
- {html: '<div style="text-align: center;">foo bar baz</div>', expected: true}
- ]
- },
- 'justifyfull' : {
- type: 'state',
- tests: [
- {html: 'foo bar baz', expected: false},
- {html: '<div align="justify">foo bar baz</div>', expected: true},
- {html: '<p align="justify">foo bar baz</p>', expected: true},
- {html: '<div style="text-align: justify;">foo bar baz</div>', expected: true}
- ]
- },
- 'justifyleft' : {
- type: 'state',
- tests: [
- {html: '<div align="left">foo bar baz</div>', expected: true},
- {html: '<p align="left">foo bar baz</p>', expected: true},
- {html: '<div style="text-align: left;">foo bar baz</div>', expected: true}
- ]
- },
- 'justifyright' : {
- type: 'state',
- tests: [
- {html: 'foo bar baz', expected: false},
- {html: '<div align="right">foo bar baz</div>', expected: true},
- {html: '<p align="right">foo bar baz</p>', expected: true},
- {html: '<div style="text-align: right;">foo bar baz</div>', expected: true}
- ]
- },
- 'strikethrough' : {
- type: 'state',
- tests: [
- {html: 'foo bar baz', expected: false},
- {html: '<strike>foo bar baz</strike>', expected: true},
- {html: '<strike style="text-decoration: none">foo bar baz</strike>', expected: false},
- {html: '<s>foo bar baz</s>', expected: true},
- {html: '<del>foo bar baz</del>', expected: true},
- {html: '<span style="text-decoration:line-through">foo bar baz</span>', expected: true}
- ]
- },
- 'subscript' : {
- type: 'state',
- tests: [
- {html: 'foo bar baz', expected: false},
- {html: '<sub>foo bar baz</sub>', expected: true}
- ]
- },
- 'superscript' : {
- type: 'state',
- tests: [
- {html: 'foo bar baz', expected: false},
- {html: '<sup>foo bar baz</sup>', expected: true}
- ]
- },
- 'underline' : {
- type: 'state',
- tests: [
- {html: 'foo bar baz', expected: false},
- {html: '<u>foo bar baz</u>', expected: true},
- {html: '<a href="http://www.foo.com">foo bar baz</a>', expected: true},
- {html: '<span style="text-decoration:underline">foo bar baz</span>', expected: true},
- {html: '<u style="text-decoration:none">foo bar baz</u>', expected: false},
- {html: '<a style="text-decoration:none" href="http://www.foo.com">foo bar baz</a>', expected: false}
- ]
- }
- };
-
- var CHANGE_TESTS = {
- 'backcolor' : {
- type: 'value',
- tests: [
- {html: '<FONT style="BACKGROUND-COLOR: #ffccaa">foo bar baz</FONT>', opt_arg: '#884422'},
- {html: '<span class="Apple-style-span" style="background-color: rgb(255, 0, 0);">foo bar baz</span>', opt_arg: '#0000ff'},
- {html: '<span style="background-color: #ff0000">foo bar baz</span>', opt_arg: '#0000ff'}
- ]
- },
- 'fontname' : {
- type: 'value',
- tests: [
- {html: '<font face="Arial">foo bar baz</font>', opt_arg: 'Courier'},
- {html: '<span style="font-family:Arial">foo bar baz</span>', opt_arg: 'Courier'},
- {html: '<font face="Arial" style="font-family:Verdana">foo bar baz</font>', opt_arg: 'Courier'},
- {html: '<font face="Verdana"><font face="Arial">foo bar baz</font></font>', opt_arg: 'Courier'},
- {html: '<span style="font-family:Verdana"><font face="Arial">foo bar baz</font></span>', opt_arg: 'Courier'}
- ]
- },
- 'fontsize' : {
- type: 'value',
- tests: [
- {html: '<font size=4>foo bar baz</font>', opt_arg: 1},
- {html: '<span class="Apple-style-span" style="font-size: large;">foo bar baz</span>', opt_arg: 1},
- {html: '<font size=1 style="font-size:x-small;">foo bar baz</font>', opt_arg: 5}
- ]
- },
- 'forecolor' : {
- type: 'value',
- tests: [
- {html: '<font color="#ff0000">foo bar baz</font>', opt_arg: '#00ff00'},
- {html: '<span style="color:#ff0000">foo bar baz</span>', opt_arg: '#00ff00'},
- {html: '<font color="#0000ff" style="color:#ff0000">foo bar baz</span>', opt_arg: '#00ff00'}
- ]
- },
- 'hilitecolor' : {
- type: 'value',
- tests: [
- {html: '<FONT style="BACKGROUND-COLOR: #ffccaa">foo bar baz</FONT>', opt_arg: '#884422'},
- {html: '<span class="Apple-style-span" style="background-color: rgb(255, 0, 0);">foo bar baz</span>', opt_arg: '#00ff00'},
- {html: '<span style="background-color: #ff0000">foo bar baz</span>', opt_arg: '#00ff00'}
- ]
- }
- };
-
- /** The document of the editable iframe */
- var editorDoc = null;
- /** Dummy text to apply and unapply formatting to */
- var TEST_CONTENT = 'foo bar baz';
- /**
- * Word in dummy text that should change. Formatting is sometimes applied
- * to a single word instead of the entire text node because sometimes a
- * style might get applied to the body node instead of wrapped around
- * the text, and that's not what's being tested.
- */
- var TEST_WORD = 'bar';
- /** Constant for indicating an action is unsupported (threw exception) */
- var UNSUPPORTED = 'UNSUPPORTED';
- /** <br> and <p> are acceptable HTML to be left over from block elements */
- var BLOCK_REMOVE_TAGS = [/\s*<br>\s*/i, /\s*<p>\s*/i];
- /** Array used to accumulate test results */
- // Tack on the actual display tests with bogus data
- // otherwise the beacon will fail.
- var results = ['apply=0', 'unapply=0', 'change=0', 'query=0'];
-
- /**
- *
- */
- function resetIframe(newHtml) {
- // These attributes can get set on the iframe by some errant execCommands
- editorDoc.body.setAttribute('style', '');
- editorDoc.body.setAttribute('bgcolor', '');
- editorDoc.body.innerHTML = newHtml;
- }
-
- /**
- * Finds the text node in the given node containing the given word.
- * Returns null if not found.
- */
- function findTextNode(word, node) {
- if (node.nodeType == 3) {
- // Text node, check value.
- if (node.data.indexOf(word) != -1) {
- return node;
- }
- } else if (node.nodeType == 1) {
- // Element node, check children.
- for (var i = 0; i < node.childNodes.length; i++) {
- var result = findTextNode(word, node.childNodes[i]);
- if (result) {
- return result;
- }
- }
- }
- return null;
- }
-
- /**
- * Sets the selection to be collapsed at the start of the word,
- * or the start of the editor if no word is passed in.
- */
- function selectStart(word) {
- var textNode = findTextNode(word || '', editorDoc.body);
- var startOffset = 0;
- if (word) {
- startOffset = textNode.data.indexOf(word);
- }
- var range = createCaret(textNode, startOffset);
- range.select();
- }
-
- /**
- * Selects the given word in the editor iframe.
- */
- function selectWord(word) {
- var textNode = findTextNode(word, editorDoc.body);
- if (!textNode) {
- return;
- }
- var start = textNode.data.indexOf(word);
- var range = createFromNodes(textNode, start, textNode, start + word.length);
- range.select();
- }
-
- /**
- * Gets the HTML before the text, so that we know how the browser
- * applied a style
- */
- function getSurroundingTags(text) {
- var html = editorDoc.body.innerHTML;
- var tagStart = html.indexOf('<');
- var index = editorDoc.body.innerHTML.indexOf(text);
- if (tagStart == -1 || index == -1) {
- return '';
- }
- return editorDoc.body.innerHTML.substring(tagStart, index);
- }
-
- /**
- * Does the test for an apply execCommand.
- */
- function doApplyTest(command, styleWithCSS) {
- try {
- // Set styleWithCSS
- try {
- editorDoc.execCommand('styleWithCSS', false, styleWithCSS);
- } catch (ex) {
- // Ignore errors
- }
- resetIframe(TEST_CONTENT);
- if (APPLY_TESTS[command].collapse) {
- selectStart(TEST_WORD);
- } else {
- selectWord(TEST_WORD);
- }
- try {
- editorDoc.execCommand(command, false, APPLY_TESTS[command].opt_arg);
- } catch (ex) {
- return UNSUPPORTED;
- }
- return getSurroundingTags(APPLY_TESTS[command].wholeline? TEST_CONTENT : TEST_WORD);
- } catch (ex) {
- return UNSUPPORTED;
- }
- }
-
- /**
- * Outputs the result of the apply command to a table.
- * @return {boolean} success
- */
- function outputApplyResult(command, result, styleWithCSS) {
- // The apply command "succeeded" if HTML was generated.
- var success = (result != UNSUPPORTED) && result;
- // Except for styleWithCSS commands, which only succeed if the
- // expected style was applied.
- if (styleWithCSS) {
- success = result && result.toLowerCase().indexOf(APPLY_TESTS[command].styleWithCSS) != -1;
- }
- results.push('a-' + command + '-' + (styleWithCSS ? 1 : 0) + '=' + (success ? '1' : '0'));
-
- // Each command is displayed as a table row with 3 columns
- var tr = document.createElement('TR');
- tr.className = success ? 'success' : 'fail';
-
- // Column 1: command name
- var td = document.createElement('TD');
- td.innerHTML = command;
- tr.appendChild(td);
-
- // Column 2: styleWithCSS
- var td = document.createElement('TD');
- td.innerHTML = styleWithCSS ? 'true' : 'false';
- tr.appendChild(td);
-
- // Column 3: pass/fail
- td = document.createElement('TD');
- td.innerHTML = success ? 'PASS' : 'FAIL';
- tr.appendChild(td);
-
- // Column 4: generated HTML (for passing commands)
- td = document.createElement('TD');
- // Escape the HTML in the result for printing.
- result = result.replace(/\</g, '&lt;').replace(/\>/g, '&gt;');
- td.innerHTML = result;
- tr.appendChild(td);
- var table = document.getElementById('apply_output');
- table.appendChild(tr);
- return success;
- }
-
- /**
- * Does the test for an unapply execCommand.
- */
- function doUnapplyTest(command, index) {
- try {
- var wordStart = TEST_CONTENT.indexOf(TEST_WORD);
- resetIframe(
- TEST_CONTENT.substring(0, wordStart) +
- UNAPPLY_TESTS[command].tags[index][0] +
- TEST_WORD +
- UNAPPLY_TESTS[command].tags[index][1] +
- TEST_CONTENT.substring(wordStart + TEST_WORD.length));
- selectWord(TEST_WORD);
- try {
- editorDoc.execCommand(command, false, UNAPPLY_TESTS[command].opt_arg || null);
- } catch (ex) {
- return UNSUPPORTED;
- }
- return getSurroundingTags(TEST_WORD);
- } catch (ex) {
- return UNSUPPORTED;
- }
- }
-
- /**
- * Check if the given unapply execCommand succeeded. It succeeded if
- * the following conditions are true:
- * - The execCommand did not throw an exception
- * - One of the following:
- * - The html was removed after the execCommand
- * - The html was block and the html was replaced with <p> or <br>
- */
- function unapplyCommandSucceeded(command, result) {
- if (result != UNSUPPORTED) {
- if (!result) {
- return true;
- } else if (UNAPPLY_TESTS[command].block) {
- for (var i = 0; i < BLOCK_REMOVE_TAGS.length; i++) {
- if (result.match(BLOCK_REMOVE_TAGS[i])) {
- return true;
- }
- }
- }
- }
- return false;
- }
-
- /**
- * Outputs the result of the unapply command to a table.
- * @return {boolean} success
- */
- function outputUnapplyResult(command, result, index) {
- // The apply command "succeeded" if HTML was removed.
- var success = unapplyCommandSucceeded(command, result);
- results.push('u-' + command + '-' + index + '=' + (success ? '1' : '0'));
-
- // Each command is displayed as a table row with 5 columns
- var tr = document.createElement('TR');
- tr.className = success ? 'success' : 'fail';
-
- // Column 1: command name
- var td = document.createElement('TD');
- td.innerHTML = command;
- tr.appendChild(td);
-
- // Column 2: command name being unapplied
- var td = document.createElement('TD');
- td.innerHTML = UNAPPLY_TESTS[command].unapply || command;
- tr.appendChild(td);
-
- // Column 3: pass/fail
- td = document.createElement('TD');
- td.innerHTML = success ? 'PASS' : 'FAIL';
- tr.appendChild(td);
-
- // Column 4: html being removed
- td = document.createElement('TD');
- // Escape the html for printing.
- var htmlToRemove = UNAPPLY_TESTS[command].tags[index][0].replace(/\</g, '&lt;').replace(/\>/g, '&gt;');
- td.innerHTML = htmlToRemove;
- tr.appendChild(td);
-
- // Column 5: resulting html
- td = document.createElement('TD');
- // Escape the HTML in the result for printing.
- result = result.replace(/\</g, '&lt;').replace(/\>/g, '&gt;');
- td.innerHTML = success ? '&nbsp;' : result;
- tr.appendChild(td);
- var table = document.getElementById('unapply_output');
- table.appendChild(tr);
- return success;
- }
-
- /**
- * Does a queryCommandState or queryCommandValue test for an execCommand.
- */
- function doQueryTest(command, index) {
- try {
- resetIframe(QUERY_TESTS[command].tests[index].html);
- selectWord(TEST_WORD);
- // Dummy val that won't match any expected vals, including false.
- var result = UNSUPPORTED;
- if (QUERY_TESTS[command].type == 'state') {
- try {
- result = editorDoc.queryCommandState(command);
- } catch (ex) {
- result = UNSUPPORTED;
- }
- } else {
- try {
- // A return value of false indicates the command is not supported.
- result = editorDoc.queryCommandValue(command) || UNSUPPORTED;
- } catch (ex) {
- result = UNSUPPORTED;
- }
- }
- return result;
- } catch (ex) {
- return UNSUPPORTED;
- }
- }
-
- /**
- * Check if the given queryCommandState or queryCommandValue succeeded.
- */
- function queryCommandSucceeded(command, index, result) {
- var expected = QUERY_TESTS[command].tests[index].expected;
- if (expected instanceof Color) {
- return expected.compare(new Color(result));
- } else if (expected instanceof Size) {
- return expected.compare(new Size(result));
- } else {
- return (result == expected);
- }
- }
-
- /**
- * @return {boolean} success
- */
- function outputQueryResult(command, index, result) {
- // Create table row for results.
- var tr = document.createElement('TR');
- var success = queryCommandSucceeded(command, index, result);
- tr.className = success ? 'success' : 'fail';
- results.push('q-' + command + '-' + index + '=' + (success ? '1' : '0'));
-
- // Column 1: command name
- var td = document.createElement('TD');
- td.innerHTML = command;
- tr.appendChild(td);
-
- // Column 2: pass/fail
- td = document.createElement('TD');
- td.innerHTML = success ? 'PASS' : 'FAIL';
- tr.appendChild(td);
-
- // Column 3: test HTML
- td = document.createElement('TD');
- var testHtml = QUERY_TESTS[command].tests[index].html.replace(/</g, '&lt;').replace(/>/g, '&gt;');
- td.innerHTML = testHtml.substring(0, testHtml.indexOf(TEST_CONTENT));
- tr.appendChild(td);
-
- // Column 4: Expected result
- td = document.createElement('TD');
- td.innerHTML = QUERY_TESTS[command].tests[index].expected;
- tr.appendChild(td);
-
- // Column 5: Actual result
- td = document.createElement('TD');
- td.innerHTML = result;
- tr.appendChild(td);
-
- // Append result to the state or value table, depending on what
- // type of command this is.
- var table = document.getElementById(
- QUERY_TESTS[command].type == 'state' ? 'querystate_output' : 'queryvalue_output');
- table.appendChild(tr);
- return success;
- }
-
- function doChangeTest(command, index) {
- try {
- resetIframe(CHANGE_TESTS[command].tests[index].html);
- selectWord(TEST_CONTENT);
- try {
- editorDoc.execCommand(command, false, CHANGE_TESTS[command].tests[index].opt_arg);
- } catch (ex) {
- return UNSUPPORTED;
- }
- } catch (ex) {
- return UNSUPPORTED;
- }
- }
-
- function checkChangeSuccess(command, index) {
- var textNode = findTextNode(TEST_CONTENT, editorDoc.body);
- if (!textNode) {
- // The text has been removed from the document, or split up for no reason.
- return false;
- }
- var expected = null, attributeName = null, styleName = null;
- switch (command) {
- case 'backcolor':
- case 'hilitecolor':
- expected = new Color(CHANGE_TESTS[command].tests[index].opt_arg);
- styleName = 'backgroundColor';
- break;
- case 'fontname':
- expected = CHANGE_TESTS[command].tests[index].opt_arg;
- attributeName = 'face';
- styleName = 'fontFamily';
- break;
- case 'fontsize':
- expected = new Size(CHANGE_TESTS[command].tests[index].opt_arg);
- attributeName = 'size';
- styleName = 'fontSize';
- break;
- case 'forecolor':
- expected = new Color(CHANGE_TESTS[command].tests[index].opt_arg);
- attributeName = 'color';
- styleName = 'color';
- }
- var foundExpected = false;
-
- // Loop through all the parent nodes that format the text node,
- // checking that there is exactly one font attribute or
- // style, and that it's set correctly.
- var currentNode = textNode.parentNode;
- while(currentNode && currentNode.nodeName != 'BODY') {
- // Check font attribute.
- if (attributeName && currentNode.nodeName == 'FONT' && currentNode.getAttribute(attributeName)) {
- var foundAttribute = false;
- switch(command) {
- case 'backcolor':
- case 'forecolor':
- case 'hilitecolor':
- foundAttribute = new Color(currentNode.getAttribute(attributeName)).compare(expected);
- break;
- case 'fontsize':
- foundAttribute = new Size(currentNode.getAttribute(attributeName)).compare(expected);
- break;
- case 'fontname':
- foundAttribute = (currentNode.getAttribute(attributeName).toLowerCase() == expected.toLowerCase());
- }
- if (foundAttribute && foundExpected) {
- // This is the correct attribute, but the style has been applied
- // twice. This makes it hard for other browsers to remove the
- // style.
- return false;
- } else if (!foundAttribute) {
- // This node has an incorrect font attribute.
- return false;
- }
- // The expected font attribute was found.
- foundExpected = true;
- }
- // Check node style.
- if (currentNode.style[styleName]) {
- var foundStyle = false;
- switch(command) {
- case 'backcolor':
- case 'forecolor':
- case 'hilitecolor':
- foundStyle = new Color(currentNode.style[styleName]).compare(expected);
- break;
- case 'fontsize':
- foundStyle = new Size(currentNode.style[styleName]).compare(expected);
- break;
- case 'fontname':
- foundStyle = (currentNode.style[styleName].toLowerCase() == expected.toLowerCase());
- }
- if (foundStyle && foundExpected) {
- // This is the correct style, but the style has been
- // applied twice. This makes it hard for other browsers to
- // remove the style.
- return false;
- } else if (!foundStyle) {
- // This node has an incorrect font style.
- return false;
- }
- foundExpected = true;
- }
- currentNode = currentNode.parentNode;
- }
- return foundExpected;
- }
-
- /**
- * @return {boolean} success
- */
- function outputChangeResult(command, index) {
- // Each command is displayed as a table row with 4 columns
- var tr = document.createElement('TR');
- var success = checkChangeSuccess(command, index);
- tr.className = success ? 'success' : 'fail';
- results.push('c-' + command + '-' + index + '=' + (success ? '1' : '0'));
-
- // Column 1: command name
- var td = document.createElement('TD');
- td.innerHTML = command;
- tr.appendChild(td);
-
- // Column 2: status
- td = document.createElement('TD');
- td.innerHTML = (success == null) ? '?' : (success == true ? 'PASS' : 'FAIL');
- tr.appendChild(td);
-
- // Column 3: opt_arg
- td = document.createElement('TD');
- td.innerHTML = CHANGE_TESTS[command].tests[index].opt_arg;
- tr.appendChild(td);
-
- // Column 4: original html
- td = document.createElement('TD');
- td.innerHTML = CHANGE_TESTS[command].tests[index].html.replace(/\</g, '&lt;').replace(/\>/g, '&gt;');;
- tr.appendChild(td);
-
- // Column 5: resulting html
- td = document.createElement('TD');
- td.innerHTML = editorDoc.body.innerHTML.replace(/\</g, '&lt;').replace(/\>/g, '&gt;');;
- tr.appendChild(td);
-
- var table = document.getElementById('change_output');
- table.appendChild(tr);
- return success;
- }
-
- function runTests() {
- // Wrap initialization code in a try/catch so we can fail gracefully
- // on older browsers.
- try {
- editorDoc = document.getElementById('editor').contentWindow.document;
- // Default styleWithCSS to false, since it's not supported by IE.
- try {
- editorDoc.execCommand('styleWithCSS', false, false);
- } catch (ex) {
- // Not supported by IE.
- }
- } catch (ex) {}
-
- // Apply tests
- var apply_score = 0;
- var apply_count = 0;
- var unapply_score= 0;
- var unapply_count = 0;
- var change_score = 0;
- var change_count = 0;
- var query_score = 0;
- var query_count = 0;
- for (var command in APPLY_TESTS) {
- try {
- var result = doApplyTest(command, false);
- var success = outputApplyResult(command, result, false);
- apply_score += success ? 1 : 0;
- } catch (ex) {
- // An exception is counted as a failed test, don't increment success.
- }
- apply_count++;
- if (APPLY_TESTS[command].styleWithCSS) {
- try {
- var result = doApplyTest(command, true);
- var success = outputApplyResult(command, result, true);
- apply_score += success ? 1 : 0;
- } catch (ex) {
- // An exception is counted as a failed test, don't increment success.
- }
- apply_count++;
- }
- }
-
- // Unapply tests
- for (var command in UNAPPLY_TESTS) {
- for (var i = 0; i < UNAPPLY_TESTS[command].tags.length; i++) {
- try {
- var result = doUnapplyTest(command, i);
- var success = outputUnapplyResult(command, result, i);
- unapply_score += success ? 1 : 0;
- } catch (ex) {
- // An exception is counted as a failed test, don't increment success.
- }
- unapply_count++;
- }
- }
-
- // Query tests
- for (var command in QUERY_TESTS) {
- for (var i = 0; i < QUERY_TESTS[command].tests.length; i++) {
- try {
- var result = doQueryTest(command, i);
- var success = outputQueryResult(command, i, result);
- query_score += success ? 1 : 0;
- } catch (ex) {
- // An exception is counted as a failed test, don't increment success.
- }
- query_count++;
- }
- }
-
- // Change tests
- for (var command in CHANGE_TESTS) {
- for (var i = 0; i < CHANGE_TESTS[command].tests.length; i++) {
- try {
- doChangeTest(command, i);
- var success = outputChangeResult(command, i);
- change_score += success ? 1 : 0;
- } catch (ex) {
- // An exception is counted as a failed test, don't increment success.
- }
- change_count++;
- }
- }
-
- // Beacon all test results.
- // and construct a shorter version for the results page.
- try {
- document.getElementById('apply-score').innerHTML =
- apply_score + '/' + apply_count;
- document.getElementById('unapply-score').innerHTML =
- unapply_score + '/' + unapply_count;
- document.getElementById('query-score').innerHTML =
- query_score + '/' + query_count;
- document.getElementById('change-score').innerHTML =
- change_score + '/' + change_count;
- } catch (ex) {}
- var continueParams = [
- 'apply=' + apply_score,
- 'unapply=' + unapply_score,
- 'query=' + query_score,
- 'change=' + change_score
- ];
- parent.sendScore(results, continueParams);
- }
- </script>
- <style>
- .success {
- background-color: #93c47d;
- }
- .fail {
- background-color: #ea9999;
- }
- .score {
- color: #666;
- }
- </style>
-</head>
-<body onload="runTests()">
- <h1>Apply Formatting <span id="apply-score" class="score"></span></h1>
- <table id="apply"><tbody id="apply_output"><tr><th>Command</th><th>styleWithCSS</th><th>Status</th><th>Output</th></tr></tbody></table>
- <h1>Unapply Formatting <span id="unapply-score" class="score"></span></h1>
- <table id="unapply">
- <thead><tr><th>Command</th><th>Command unapplied</th><th>Status</th><th>HTML Attempted to Unapply</th><th>Resulting HTML</th></tr></thead>
- <tbody id="unapply_output"></tbody></table>
- <h1>Query Formatting State <span id="query-score" class="score"></span></h1>
- <table id="querystate">
- <thead><tr><th>Command</th><th>Status</th><th>HTML</th><th>Expected</th><th>Actual</th></tr></thead>
- <tbody id="querystate_output"></tbody></table>
- <h1>Query Formatting Value </h1>
- <table id="queryvalue">
- <thead><tr><th>Command</th><th>Status</th><th>HTML</th><th>Expected</th><th>Actual</th></tr></thead>
- <tbody id="queryvalue_output"></tbody></table>
- <h1>Change Formatting <span id="change-score" class="score"></span></h1>
- <table id="change">
- <thead><tr><th>Command</th><th>Status</th><th>Argument</th><th>Original HTML</th><th>Resulting HTML</th></tr></thead>
- <tbody id="change_output"></tbody></table>
- <iframe name="editor" id="editor" src="editable.html"></iframe>
-</body>
-</html>
diff --git a/editor/libeditor/tests/browserscope/lib/richtext/update_from_upstream b/editor/libeditor/tests/browserscope/lib/richtext/update_from_upstream
deleted file mode 100644
index 2071454a8..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext/update_from_upstream
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-
-set -x
-
-if test -d richtext; then
- rm -drf richtext;
-fi
-
-svn checkout http://browserscope.googlecode.com/svn/trunk/categories/richtext/static richtext | tail -1 | sed 's/[^0-9]//g' > current_revision
-
-find richtext -type d -name .svn -exec rm -drf \{\} \; 2> /dev/null
-
-hg add current_revision richtext
-
-hg stat .
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/LICENSE b/editor/libeditor/tests/browserscope/lib/richtext2/LICENSE
deleted file mode 100644
index 57bc88a15..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/LICENSE
+++ /dev/null
@@ -1,202 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/README b/editor/libeditor/tests/browserscope/lib/richtext2/README
deleted file mode 100644
index a3bc3110f..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/README
+++ /dev/null
@@ -1,58 +0,0 @@
-README FOR BROWSERSCOPE
------------------------
-
-Hey there - thanks for downloading the code. This file has instructions
-for getting setup so that you can run the codebase locally.
-
-This project is built on Google App Engine using the
-Django web application framework and written in Python.
-
-To get started, you'll need to first download the App Engine SDK at:
-http://code.google.com/appengine/downloads.html
-
-For local development, just startup the server:
-./pathto/google_appengine/dev_appserver.py --port=8080 browserscope
-
-You should then be able to access the local application at:
-http://localhost:8080/
-
-Note: the first time you hit the homepage it may take a little
-while - that's because it's trying to read out median times for all
-of the tests from a nonexistent datastore and write to memcache.
-Just be a lil patient.
-
-You can run the unit tests at:
- http://localhost:8080/test
-
-
-CONTRIBUTING
-------------------
-
-Most likely you are interested in adding new tests or creating
-a new test category. If you are interested in adding tests to an existing
-"category" you may want to get in touch with the maintainer for that
-branch of the tree. We are really looking forward to receiving your
-code in patch format. Currently the category maintainers are:
-Network: Steve Souders <souders@gmail.com>
-Reflow: Lindsey Simon <elsigh@gmail.com>
-Security: Adam Barth <adam@adambarth.com> and Collin Jackson <collin@collinjackson.com>
-
-
-To create a completely new test category:
- * Copy one of the existing directories in categories/
- * Edit your test_set.py, handlers.py
- * Add your files in templates/ and static/
- * Update urls.py and settings.CATEGORIES
- * Follow the examples of other tests re:
- * beaconing using/testdriver_base
- * your GetScoreAndDisplayValue method
- * your GetRowScoreAndDisplayValue method
-
-References:
- * App Engine Docs - http://code.google.com/appengine/docs/python/overview.html
- * App Engine Group - http://groups.google.com/group/google-appengine
- * Python Docs - http://www.python.org/doc/
- * Django - http://www.djangoproject.com/
-
-
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/README.Mozilla b/editor/libeditor/tests/browserscope/lib/richtext2/README.Mozilla
deleted file mode 100644
index 3e667a0b7..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/README.Mozilla
+++ /dev/null
@@ -1,23 +0,0 @@
-The BrowserScope project provides a set of cross-browser HTML editor tests,
-which we import in our test suite in order to run them as part of our
-continuous integration system.
-
-We pull tests occasionally from their Subversion repository using the pull
-script which can be found in this directory. We also record the revision ID
-which we've used in the current_revision file inside this directory.
-
-Using the pull script is quite easy, just switch to this directory, and say:
-
-sh update_from_upstream
-
-There are tests which we're currently failing on, and there will probably be
-more of those in the future. We should maintain a list of the failing tests
-manually in currentStatus.js (which can also be found in this directory), to
-make sure that the suite passes entirely, with failing tests marked as todo
-items.
-
-The current status of the test suite needs to be updated whenever an editor
-bug gets fixed, which makes us pass one of the tests. When that happens,
-you should set the UPDATE_TEST_RESULTS constant to true in test_richtext2.html,
-run the test suite, paste the result JSON string in a JSON beautifier (such
-as http://jsbeautifier.org/), and use the result to update currentStatus.js.
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/currentStatus.js b/editor/libeditor/tests/browserscope/lib/richtext2/currentStatus.js
deleted file mode 100644
index 570853afa..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/currentStatus.js
+++ /dev/null
@@ -1,1850 +0,0 @@
-/**
- * The current status of the test suite.
- *
- * See README.Mozilla for details on how to generate this.
- */
-const knownFailures = {
- "value": {
- "A-Proposed-FS:18px_TEXT-1_SI-dM": true,
- "A-Proposed-FS:18px_TEXT-1_SI-body": true,
- "A-Proposed-FS:18px_TEXT-1_SI-div": true,
- "A-Proposed-FS:large_TEXT-1_SI-dM": true,
- "A-Proposed-FS:large_TEXT-1_SI-body": true,
- "A-Proposed-FS:large_TEXT-1_SI-div": true,
- "A-Proposed-CB:name_TEXT-1_SI-dM": true,
- "A-Proposed-CB:name_TEXT-1_SI-body": true,
- "A-Proposed-CB:name_TEXT-1_SI-div": true,
- "AC-Proposed-SUB_TEXT-1_SI-dM": true,
- "AC-Proposed-SUB_TEXT-1_SI-body": true,
- "AC-Proposed-SUB_TEXT-1_SI-div": true,
- "AC-Proposed-SUP_TEXT-1_SI-dM": true,
- "AC-Proposed-SUP_TEXT-1_SI-body": true,
- "AC-Proposed-SUP_TEXT-1_SI-div": true,
- "AC-Proposed-FS:2_TEXT-1_SI-dM": true,
- "AC-Proposed-FS:2_TEXT-1_SI-body": true,
- "AC-Proposed-FS:2_TEXT-1_SI-div": true,
- "AC-Proposed-FS:18px_TEXT-1_SI-dM": true,
- "AC-Proposed-FS:18px_TEXT-1_SI-body": true,
- "AC-Proposed-FS:18px_TEXT-1_SI-div": true,
- "AC-Proposed-FS:large_TEXT-1_SI-dM": true,
- "AC-Proposed-FS:large_TEXT-1_SI-body": true,
- "AC-Proposed-FS:large_TEXT-1_SI-div": true,
- "C-Proposed-BC:ace_FONT.ass.s:bc:rgb-1_SW-dM": true,
- "C-Proposed-BC:ace_FONT.ass.s:bc:rgb-1_SW-body": true,
- "C-Proposed-BC:ace_FONT.ass.s:bc:rgb-1_SW-div": true,
- "C-Proposed-HC:g_SPAN.ass.s:c:rgb-1_SW-dM": true,
- "C-Proposed-HC:g_SPAN.ass.s:c:rgb-1_SW-body": true,
- "C-Proposed-HC:g_SPAN.ass.s:c:rgb-1_SW-div": true,
- "C-Proposed-FN:c_FONTf:a-1_SI-dM": true,
- "C-Proposed-FN:c_FONTf:a-1_SI-body": true,
- "C-Proposed-FN:c_FONTf:a-1_SI-div": true,
- "C-Proposed-FN:c_FONTf:a-2_SL-dM": true,
- "C-Proposed-FN:c_FONTf:a-2_SL-body": true,
- "C-Proposed-FN:c_FONTf:a-2_SL-div": true,
- "C-Proposed-FS:1_SPAN.ass.s:fs:large-1_SW-dM": true,
- "C-Proposed-FS:1_SPAN.ass.s:fs:large-1_SW-body": true,
- "C-Proposed-FS:1_SPAN.ass.s:fs:large-1_SW-div": true,
- "C-Proposed-FS:5_FONTsz:1.s:fs:xs-1_SW-dM": true,
- "C-Proposed-FS:5_FONTsz:1.s:fs:xs-1_SW-body": true,
- "C-Proposed-FS:5_FONTsz:1.s:fs:xs-1_SW-div": true,
- "C-Proposed-FS:larger_FONTsz:4-dM": true,
- "C-Proposed-FS:larger_FONTsz:4-body": true,
- "C-Proposed-FS:larger_FONTsz:4-div": true,
- "C-Proposed-FS:smaller_FONTsz:4-dM": true,
- "C-Proposed-FS:smaller_FONTsz:4-body": true,
- "C-Proposed-FS:smaller_FONTsz:4-div": true,
- "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SO-dM": true,
- "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SO-body": true,
- "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SO-div": true,
- "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SW-dM": true,
- "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SW-body": true,
- "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SW-div": true,
- "C-Proposed-FB:h1_ADDRESS-FONT.ass.sz:4-1_SW-dM": true,
- "C-Proposed-FB:h1_ADDRESS-FONT.ass.sz:4-1_SW-body": true,
- "C-Proposed-FB:h1_ADDRESS-FONT.ass.sz:4-1_SW-div": true,
- "CC-Proposed-I_B-1_SW-dM": true,
- "CC-Proposed-I_B-1_SW-body": true,
- "CC-Proposed-I_B-1_SW-div": true,
- "CC-Proposed-BC:gray_SPANs:bc:b-1_SI-dM": true,
- "CC-Proposed-BC:gray_SPANs:bc:b-1_SI-body": true,
- "CC-Proposed-BC:gray_SPANs:bc:b-1_SI-div": true,
- "CC-Proposed-BC:gray_P-SPANs:bc:b-3_SL-dM": true,
- "CC-Proposed-BC:gray_P-SPANs:bc:b-3_SL-body": true,
- "CC-Proposed-BC:gray_P-SPANs:bc:b-3_SL-div": true,
- "CC-Proposed-BC:gray_SPANs:bc:b-2_SL-dM": true,
- "CC-Proposed-BC:gray_SPANs:bc:b-2_SL-body": true,
- "CC-Proposed-BC:gray_SPANs:bc:b-2_SL-div": true,
- "CC-Proposed-BC:gray_SPANs:bc:b-2_SR-dM": true,
- "CC-Proposed-BC:gray_SPANs:bc:b-2_SR-body": true,
- "CC-Proposed-BC:gray_SPANs:bc:b-2_SR-div": true,
- "CC-Proposed-FN:c_FONTf:a-1_SI-dM": true,
- "CC-Proposed-FN:c_FONTf:a-1_SI-body": true,
- "CC-Proposed-FN:c_FONTf:a-1_SI-div": true,
- "CC-Proposed-FN:c_FONTf:a-2_SL-dM": true,
- "CC-Proposed-FN:c_FONTf:a-2_SL-body": true,
- "CC-Proposed-FN:c_FONTf:a-2_SL-div": true,
- "CC-Proposed-FS:1_SPANs:fs:l-1_SW-dM": true,
- "CC-Proposed-FS:1_SPANs:fs:l-1_SW-body": true,
- "CC-Proposed-FS:1_SPANs:fs:l-1_SW-div": true,
- "CC-Proposed-FS:18px_SPANs:fs:l-1_SW-dM": true,
- "CC-Proposed-FS:18px_SPANs:fs:l-1_SW-body": true,
- "CC-Proposed-FS:18px_SPANs:fs:l-1_SW-div": true,
- "CC-Proposed-FS:4_SPANs:fs:l-1_SW-dM": true,
- "CC-Proposed-FS:4_SPANs:fs:l-1_SW-body": true,
- "CC-Proposed-FS:4_SPANs:fs:l-1_SW-div": true,
- "CC-Proposed-FS:4_SPANs:fs:18px-1_SW-dM": true,
- "CC-Proposed-FS:4_SPANs:fs:18px-1_SW-body": true,
- "CC-Proposed-FS:4_SPANs:fs:18px-1_SW-div": true,
- "CC-Proposed-FS:larger_SPANs:fs:l-1_SI-dM": true,
- "CC-Proposed-FS:larger_SPANs:fs:l-1_SI-body": true,
- "CC-Proposed-FS:larger_SPANs:fs:l-1_SI-div": true,
- "CC-Proposed-FS:smaller_SPANs:fs:l-1_SI-dM": true,
- "CC-Proposed-FS:smaller_SPANs:fs:l-1_SI-body": true,
- "CC-Proposed-FS:smaller_SPANs:fs:l-1_SI-div": true,
- "U-RFC-UNLINK_A-1_SO-dM": true,
- "U-RFC-UNLINK_A-1_SO-body": true,
- "U-RFC-UNLINK_A-1_SO-div": true,
- "U-RFC-UNLINK_A-1_SW-dM": true,
- "U-RFC-UNLINK_A-1_SW-body": true,
- "U-RFC-UNLINK_A-1_SW-div": true,
- "U-RFC-UNLINK_A-2_SO-dM": true,
- "U-RFC-UNLINK_A-2_SO-body": true,
- "U-RFC-UNLINK_A-2_SO-div": true,
- "U-RFC-UNLINK_A2-1_SO-dM": true,
- "U-RFC-UNLINK_A2-1_SO-body": true,
- "U-RFC-UNLINK_A2-1_SO-div": true,
- "U-Proposed-B_B-P-I..P-1_SO-I-dM": true,
- "U-Proposed-B_B-P-I..P-1_SO-I-body": true,
- "U-Proposed-B_B-P-I..P-1_SO-I-div": true,
- "U-Proposed-B_B-2_SL-dM": true,
- "U-Proposed-B_B-2_SL-body": true,
- "U-Proposed-B_B-2_SL-div": true,
- "U-Proposed-B_B-2_SR-dM": true,
- "U-Proposed-B_B-2_SR-body": true,
- "U-Proposed-B_B-2_SR-div": true,
- "U-Proposed-U_U-S-2_SI-dM": true,
- "U-Proposed-U_U-S-2_SI-body": true,
- "U-Proposed-U_U-S-2_SI-div": true,
- "U-Proposed-S_DEL-1_SW-dM": true,
- "U-Proposed-S_DEL-1_SW-body": true,
- "U-Proposed-S_DEL-1_SW-div": true,
- "U-Proposed-SUB_SPANs:va:sub-1_SW-dM": true,
- "U-Proposed-SUB_SPANs:va:sub-1_SW-body": true,
- "U-Proposed-SUB_SPANs:va:sub-1_SW-div": true,
- "U-Proposed-SUP_SPANs:va:super-1_SW-dM": true,
- "U-Proposed-SUP_SPANs:va:super-1_SW-body": true,
- "U-Proposed-SUP_SPANs:va:super-1_SW-div": true,
- "U-Proposed-UNLINK_A-1_SC-dM": true,
- "U-Proposed-UNLINK_A-1_SC-body": true,
- "U-Proposed-UNLINK_A-1_SC-div": true,
- "U-Proposed-UNLINK_A-1_SI-dM": true,
- "U-Proposed-UNLINK_A-1_SI-body": true,
- "U-Proposed-UNLINK_A-1_SI-div": true,
- "U-Proposed-UNLINK_A-2_SL-dM": true,
- "U-Proposed-UNLINK_A-2_SL-body": true,
- "U-Proposed-UNLINK_A-2_SL-div": true,
- "U-Proposed-UNLINK_A-3_SR-dM": true,
- "U-Proposed-UNLINK_A-3_SR-body": true,
- "U-Proposed-UNLINK_A-3_SR-div": true,
- "U-Proposed-OUTDENT_BQ-1_SW-dM": true,
- "U-Proposed-OUTDENT_BQ-1_SW-body": true,
- "U-Proposed-OUTDENT_BQ-1_SW-div": true,
- "U-Proposed-OUTDENT_BQ.wibq.s:m:00040.b:n.p:0-1_SW-dM": true,
- "U-Proposed-OUTDENT_BQ.wibq.s:m:00040.b:n.p:0-1_SW-body": true,
- "U-Proposed-OUTDENT_BQ.wibq.s:m:00040.b:n.p:0-1_SW-div": true,
- "U-Proposed-OUTDENT_OL-LI-1_SW-dM": true,
- "U-Proposed-OUTDENT_OL-LI-1_SW-body": true,
- "U-Proposed-OUTDENT_OL-LI-1_SW-div": true,
- "U-Proposed-OUTDENT_UL-LI-1_SW-dM": true,
- "U-Proposed-OUTDENT_UL-LI-1_SW-body": true,
- "U-Proposed-OUTDENT_UL-LI-1_SW-div": true,
- "U-Proposed-OUTDENT_DIV-1_SW-dM": true,
- "U-Proposed-OUTDENT_DIV-1_SW-body": true,
- "U-Proposed-OUTDENT_DIV-1_SW-div": true,
- "U-Proposed-REMOVEFORMAT_Ahref:url-1_SW-dM": true,
- "U-Proposed-REMOVEFORMAT_Ahref:url-1_SW-body": true,
- "U-Proposed-REMOVEFORMAT_Ahref:url-1_SW-div": true,
- "U-Proposed-REMOVEFORMAT_TABLE-TBODY-TR-TD-1_SW-dM": true,
- "U-Proposed-REMOVEFORMAT_TABLE-TBODY-TR-TD-1_SW-body": true,
- "U-Proposed-REMOVEFORMAT_TABLE-TBODY-TR-TD-1_SW-div": true,
- "U-Proposed-UNBOOKMARK_An:name-1_SW-dM": true,
- "U-Proposed-UNBOOKMARK_An:name-1_SW-body": true,
- "U-Proposed-UNBOOKMARK_An:name-1_SW-div": true,
- "UC-Proposed-S_SPANc:s-1_SW-dM": true,
- "UC-Proposed-S_SPANc:s-1_SW-body": true,
- "UC-Proposed-S_SPANc:s-1_SW-div": true,
- "UC-Proposed-S_SPANc:s-2_SI-dM": true,
- "UC-Proposed-S_SPANc:s-2_SI-body": true,
- "UC-Proposed-S_SPANc:s-2_SI-div": true,
- "D-Proposed-CHAR-3_SC-dM": true,
- "D-Proposed-CHAR-3_SC-body": true,
- "D-Proposed-CHAR-3_SC-div": true,
- "D-Proposed-CHAR-4_SC-dM": true,
- "D-Proposed-CHAR-4_SC-body": true,
- "D-Proposed-CHAR-4_SC-div": true,
- "D-Proposed-CHAR-5_SC-dM": true,
- "D-Proposed-CHAR-5_SC-body": true,
- "D-Proposed-CHAR-5_SC-div": true,
- "D-Proposed-CHAR-5_SI-1-dM": true,
- "D-Proposed-CHAR-5_SI-1-body": true,
- "D-Proposed-CHAR-5_SI-1-div": true,
- "D-Proposed-CHAR-5_SI-2-dM": true,
- "D-Proposed-CHAR-5_SI-2-body": true,
- "D-Proposed-CHAR-5_SI-2-div": true,
- "D-Proposed-CHAR-5_SR-dM": true,
- "D-Proposed-CHAR-5_SR-body": true,
- "D-Proposed-CHAR-5_SR-div": true,
- "D-Proposed-CHAR-6_SC-dM": true,
- "D-Proposed-CHAR-6_SC-body": true,
- "D-Proposed-CHAR-6_SC-div": true,
- "D-Proposed-CHAR-7_SC-dM": true,
- "D-Proposed-CHAR-7_SC-body": true,
- "D-Proposed-CHAR-7_SC-div": true,
- "D-Proposed-OL-LI-1_SW-dM": true,
- "D-Proposed-OL-LI-1_SW-body": true,
- "D-Proposed-OL-LI-1_SW-div": true,
- "D-Proposed-TR2rs:2-1_SO1-dM": true,
- "D-Proposed-TR2rs:2-1_SO1-body": true,
- "D-Proposed-TR2rs:2-1_SO1-div": true,
- "D-Proposed-TR2rs:2-1_SO2-dM": true,
- "D-Proposed-TR2rs:2-1_SO2-body": true,
- "D-Proposed-TR2rs:2-1_SO2-div": true,
- "D-Proposed-TR3rs:3-1_SO1-dM": true,
- "D-Proposed-TR3rs:3-1_SO1-body": true,
- "D-Proposed-TR3rs:3-1_SO1-div": true,
- "D-Proposed-TR3rs:3-1_SO2-dM": true,
- "D-Proposed-TR3rs:3-1_SO2-body": true,
- "D-Proposed-TR3rs:3-1_SO2-div": true,
- "D-Proposed-TR3rs:3-1_SO3-dM": true,
- "D-Proposed-TR3rs:3-1_SO3-body": true,
- "D-Proposed-TR3rs:3-1_SO3-div": true,
- "D-Proposed-DIV:ce:false-1_SB-dM": true,
- "D-Proposed-DIV:ce:false-1_SB-body": true,
- "D-Proposed-DIV:ce:false-1_SB-div": true,
- "D-Proposed-DIV:ce:false-1_SL-dM": true,
- "D-Proposed-DIV:ce:false-1_SL-body": true,
- "D-Proposed-DIV:ce:false-1_SL-div": true,
- "D-Proposed-DIV:ce:false-1_SR-dM": true,
- "D-Proposed-DIV:ce:false-1_SR-body": true,
- "D-Proposed-DIV:ce:false-1_SR-div": true,
- "D-Proposed-DIV:ce:false-1_SI-dM": true,
- "FD-Proposed-OL-LI-1_SW-dM": true,
- "FD-Proposed-OL-LI-1_SW-body": true,
- "FD-Proposed-OL-LI-1_SW-div": true,
- "FD-Proposed-TR2rs:2-1_SO1-dM": true,
- "FD-Proposed-TR2rs:2-1_SO1-body": true,
- "FD-Proposed-TR2rs:2-1_SO1-div": true,
- "FD-Proposed-TR2rs:2-1_SO2-dM": true,
- "FD-Proposed-TR2rs:2-1_SO2-body": true,
- "FD-Proposed-TR2rs:2-1_SO2-div": true,
- "FD-Proposed-TR3rs:3-1_SO1-dM": true,
- "FD-Proposed-TR3rs:3-1_SO1-body": true,
- "FD-Proposed-TR3rs:3-1_SO1-div": true,
- "FD-Proposed-TR3rs:3-1_SO2-dM": true,
- "FD-Proposed-TR3rs:3-1_SO2-body": true,
- "FD-Proposed-TR3rs:3-1_SO2-div": true,
- "FD-Proposed-TR3rs:3-1_SO3-dM": true,
- "FD-Proposed-TR3rs:3-1_SO3-body": true,
- "FD-Proposed-TR3rs:3-1_SO3-div": true,
- "FD-Proposed-DIV:ce:false-1_SB-dM": true,
- "FD-Proposed-DIV:ce:false-1_SB-body": true,
- "FD-Proposed-DIV:ce:false-1_SB-div": true,
- "FD-Proposed-DIV:ce:false-1_SL-dM": true,
- "FD-Proposed-DIV:ce:false-1_SL-body": true,
- "FD-Proposed-DIV:ce:false-1_SL-div": true,
- "FD-Proposed-DIV:ce:false-1_SR-dM": true,
- "FD-Proposed-DIV:ce:false-1_SR-body": true,
- "FD-Proposed-DIV:ce:false-1_SR-div": true,
- "FD-Proposed-DIV:ce:false-1_SI-dM": true,
- "I-Proposed-IIMG:._SPAN-IMG-1_SO-dM": true,
- "I-Proposed-IIMG:._SPAN-IMG-1_SO-body": true,
- "I-Proposed-IIMG:._SPAN-IMG-1_SO-div": true,
- "I-Proposed-IIMG:._IMG-1_SO-dM": true,
- "I-Proposed-IIMG:._IMG-1_SO-body": true,
- "I-Proposed-IIMG:._IMG-1_SO-div": true,
- "Q-Proposed-UNSELECT_TEXT-1-dM": true,
- "Q-Proposed-UNSELECT_TEXT-1-body": true,
- "Q-Proposed-UNSELECT_TEXT-1-div": true,
- "Q-Proposed-CREATEBOOKMARK_TEXT-1-dM": true,
- "Q-Proposed-CREATEBOOKMARK_TEXT-1-body": true,
- "Q-Proposed-CREATEBOOKMARK_TEXT-1-div": true,
- "Q-Proposed-UNBOOKMARK_TEXT-1-dM": true,
- "Q-Proposed-UNBOOKMARK_TEXT-1-body": true,
- "Q-Proposed-UNBOOKMARK_TEXT-1-div": true,
- "Q-Proposed-PASTE_TEXT-1-dM": true,
- "Q-Proposed-PASTE_TEXT-1-body": true,
- "Q-Proposed-PASTE_TEXT-1-div": true,
- "QE-Proposed-UNSELECT_TEXT-1-dM": true,
- "QE-Proposed-UNSELECT_TEXT-1-body": true,
- "QE-Proposed-UNSELECT_TEXT-1-div": true,
- "QE-Proposed-REDO_TEXT-1-dM": true,
- "QE-Proposed-REDO_TEXT-1-body": true,
- "QE-Proposed-REDO_TEXT-1-div": true,
- "QE-Proposed-CREATEBOOKMARK_TEXT-1-dM": true,
- "QE-Proposed-CREATEBOOKMARK_TEXT-1-body": true,
- "QE-Proposed-CREATEBOOKMARK_TEXT-1-div": true,
- "QE-Proposed-UNBOOKMARK_TEXT-1-dM": true,
- "QE-Proposed-UNBOOKMARK_TEXT-1-body": true,
- "QE-Proposed-UNBOOKMARK_TEXT-1-div": true,
- "QE-Proposed-COPY_TEXT-1-dM": true,
- "QE-Proposed-COPY_TEXT-1-body": true,
- "QE-Proposed-COPY_TEXT-1-div": true,
- "QE-Proposed-CUT_TEXT-1-dM": true,
- "QE-Proposed-CUT_TEXT-1-body": true,
- "QE-Proposed-CUT_TEXT-1-div": true,
- "QE-Proposed-PASTE_TEXT-1-dM": true,
- "QE-Proposed-PASTE_TEXT-1-body": true,
- "QE-Proposed-PASTE_TEXT-1-div": true,
- "QS-Proposed-SUB_SPAN.sub-1-SI-dM": true,
- "QS-Proposed-SUB_SPAN.sub-1-SI-body": true,
- "QS-Proposed-SUB_SPAN.sub-1-SI-div": true,
- "QS-Proposed-SUB_MYSUB-1-SI-dM": true,
- "QS-Proposed-SUB_MYSUB-1-SI-body": true,
- "QS-Proposed-SUB_MYSUB-1-SI-div": true,
- "QS-Proposed-SUP_SPAN.sup-1-SI-dM": true,
- "QS-Proposed-SUP_SPAN.sup-1-SI-body": true,
- "QS-Proposed-SUP_SPAN.sup-1-SI-div": true,
- "QS-Proposed-SUP_MYSUP-1-SI-dM": true,
- "QS-Proposed-SUP_MYSUP-1-SI-body": true,
- "QS-Proposed-SUP_MYSUP-1-SI-div": true,
- "QS-Proposed-JC_SPANs:ta:c-1_SI-dM": true,
- "QS-Proposed-JC_SPANs:ta:c-1_SI-body": true,
- "QS-Proposed-JC_SPANs:ta:c-1_SI-div": true,
- "QS-Proposed-JC_SPAN.jc-1-SI-dM": true,
- "QS-Proposed-JC_SPAN.jc-1-SI-body": true,
- "QS-Proposed-JC_SPAN.jc-1-SI-div": true,
- "QS-Proposed-JC_MYJC-1-SI-dM": true,
- "QS-Proposed-JC_MYJC-1-SI-body": true,
- "QS-Proposed-JC_MYJC-1-SI-div": true,
- "QS-Proposed-JF_SPANs:ta:j-1_SI-dM": true,
- "QS-Proposed-JF_SPANs:ta:j-1_SI-body": true,
- "QS-Proposed-JF_SPANs:ta:j-1_SI-div": true,
- "QS-Proposed-JF_SPAN.jf-1-SI-dM": true,
- "QS-Proposed-JF_SPAN.jf-1-SI-body": true,
- "QS-Proposed-JF_SPAN.jf-1-SI-div": true,
- "QS-Proposed-JF_MYJF-1-SI-dM": true,
- "QS-Proposed-JF_MYJF-1-SI-body": true,
- "QS-Proposed-JF_MYJF-1-SI-div": true,
- "QS-Proposed-JL_TEXT_SI-dM": true,
- "QS-Proposed-JL_TEXT_SI-body": true,
- "QS-Proposed-JL_TEXT_SI-div": true,
- "QS-Proposed-JR_SPANs:ta:r-1_SI-dM": true,
- "QS-Proposed-JR_SPANs:ta:r-1_SI-body": true,
- "QS-Proposed-JR_SPANs:ta:r-1_SI-div": true,
- "QS-Proposed-JR_SPAN.jr-1-SI-dM": true,
- "QS-Proposed-JR_SPAN.jr-1-SI-body": true,
- "QS-Proposed-JR_SPAN.jr-1-SI-div": true,
- "QS-Proposed-JR_MYJR-1-SI-dM": true,
- "QS-Proposed-JR_MYJR-1-SI-body": true,
- "QS-Proposed-JR_MYJR-1-SI-div": true,
- "QV-Proposed-B_TEXT_SI-dM": true,
- "QV-Proposed-B_TEXT_SI-body": true,
- "QV-Proposed-B_TEXT_SI-div": true,
- "QV-Proposed-B_B-1_SI-dM": true,
- "QV-Proposed-B_B-1_SI-body": true,
- "QV-Proposed-B_B-1_SI-div": true,
- "QV-Proposed-B_STRONG-1_SI-dM": true,
- "QV-Proposed-B_STRONG-1_SI-body": true,
- "QV-Proposed-B_STRONG-1_SI-div": true,
- "QV-Proposed-B_SPANs:fw:b-1_SI-dM": true,
- "QV-Proposed-B_SPANs:fw:b-1_SI-body": true,
- "QV-Proposed-B_SPANs:fw:b-1_SI-div": true,
- "QV-Proposed-B_SPANs:fw:n-1_SI-dM": true,
- "QV-Proposed-B_SPANs:fw:n-1_SI-body": true,
- "QV-Proposed-B_SPANs:fw:n-1_SI-div": true,
- "QV-Proposed-B_Bs:fw:n-1_SI-dM": true,
- "QV-Proposed-B_Bs:fw:n-1_SI-body": true,
- "QV-Proposed-B_Bs:fw:n-1_SI-div": true,
- "QV-Proposed-B_SPAN.b-1_SI-dM": true,
- "QV-Proposed-B_SPAN.b-1_SI-body": true,
- "QV-Proposed-B_SPAN.b-1_SI-div": true,
- "QV-Proposed-B_MYB-1-SI-dM": true,
- "QV-Proposed-B_MYB-1-SI-body": true,
- "QV-Proposed-B_MYB-1-SI-div": true,
- "QV-Proposed-I_TEXT_SI-dM": true,
- "QV-Proposed-I_TEXT_SI-body": true,
- "QV-Proposed-I_TEXT_SI-div": true,
- "QV-Proposed-I_I-1_SI-dM": true,
- "QV-Proposed-I_I-1_SI-body": true,
- "QV-Proposed-I_I-1_SI-div": true,
- "QV-Proposed-I_EM-1_SI-dM": true,
- "QV-Proposed-I_EM-1_SI-body": true,
- "QV-Proposed-I_EM-1_SI-div": true,
- "QV-Proposed-I_SPANs:fs:i-1_SI-dM": true,
- "QV-Proposed-I_SPANs:fs:i-1_SI-body": true,
- "QV-Proposed-I_SPANs:fs:i-1_SI-div": true,
- "QV-Proposed-I_SPANs:fs:n-1_SI-dM": true,
- "QV-Proposed-I_SPANs:fs:n-1_SI-body": true,
- "QV-Proposed-I_SPANs:fs:n-1_SI-div": true,
- "QV-Proposed-I_I-SPANs:fs:n-1_SI-dM": true,
- "QV-Proposed-I_I-SPANs:fs:n-1_SI-body": true,
- "QV-Proposed-I_I-SPANs:fs:n-1_SI-div": true,
- "QV-Proposed-I_SPAN.i-1_SI-dM": true,
- "QV-Proposed-I_SPAN.i-1_SI-body": true,
- "QV-Proposed-I_SPAN.i-1_SI-div": true,
- "QV-Proposed-I_MYI-1-SI-dM": true,
- "QV-Proposed-I_MYI-1-SI-body": true,
- "QV-Proposed-I_MYI-1-SI-div": true,
- "QV-Proposed-FB_BQ-1_SC-dM": true,
- "QV-Proposed-FB_BQ-1_SC-body": true,
- "QV-Proposed-FB_BQ-1_SC-div": true,
- "QV-Proposed-FB_H1-H2-1_SL-dM": true,
- "QV-Proposed-FB_H1-H2-1_SL-body": true,
- "QV-Proposed-FB_H1-H2-1_SL-div": true,
- "QV-Proposed-FB_H1-H2-1_SR-dM": true,
- "QV-Proposed-FB_H1-H2-1_SR-body": true,
- "QV-Proposed-FB_H1-H2-1_SR-div": true,
- "QV-Proposed-FB_TEXT-ADDRESS-1_SL-dM": true,
- "QV-Proposed-FB_TEXT-ADDRESS-1_SL-body": true,
- "QV-Proposed-FB_TEXT-ADDRESS-1_SL-div": true,
- "QV-Proposed-FB_H1-H2.TEXT.H2-1_SM-dM": true,
- "QV-Proposed-FB_H1-H2.TEXT.H2-1_SM-body": true,
- "QV-Proposed-FB_H1-H2.TEXT.H2-1_SM-div": true,
- "QV-Proposed-H_P-1_SC-dM": true,
- "QV-Proposed-H_P-1_SC-body": true,
- "QV-Proposed-H_P-1_SC-div": true,
- "QV-Proposed-FS_FONTs:fs:l-1_SI-dM": true,
- "QV-Proposed-FS_FONTs:fs:l-1_SI-body": true,
- "QV-Proposed-FS_FONTs:fs:l-1_SI-div": true,
- "QV-Proposed-FS_FONT.ass.s:fs:l-1_SI-dM": true,
- "QV-Proposed-FS_FONT.ass.s:fs:l-1_SI-body": true,
- "QV-Proposed-FS_FONT.ass.s:fs:l-1_SI-div": true,
- "QV-Proposed-FS_FONTsz:1.s:fs:xl-1_SI-dM": true,
- "QV-Proposed-FS_FONTsz:1.s:fs:xl-1_SI-body": true,
- "QV-Proposed-FS_FONTsz:1.s:fs:xl-1_SI-div": true,
- "QV-Proposed-FS_SPAN.large-1_SI-dM": true,
- "QV-Proposed-FS_SPAN.large-1_SI-body": true,
- "QV-Proposed-FS_SPAN.large-1_SI-div": true,
- "QV-Proposed-FS_SPAN.fs18px-1_SI-dM": true,
- "QV-Proposed-FS_SPAN.fs18px-1_SI-body": true,
- "QV-Proposed-FS_SPAN.fs18px-1_SI-div": true,
- "QV-Proposed-FA_MYLARGE-1-SI-dM": true,
- "QV-Proposed-FA_MYLARGE-1-SI-body": true,
- "QV-Proposed-FA_MYLARGE-1-SI-div": true,
- "QV-Proposed-FA_MYFS18PX-1-SI-dM": true,
- "QV-Proposed-FA_MYFS18PX-1-SI-body": true,
- "QV-Proposed-FA_MYFS18PX-1-SI-div": true,
- "QV-Proposed-BC_FONTs:bc:fca-1_SI-dM": true,
- "QV-Proposed-BC_FONTs:bc:fca-1_SI-body": true,
- "QV-Proposed-BC_FONTs:bc:fca-1_SI-div": true,
- "QV-Proposed-BC_SPANs:bc:abc-1_SI-dM": true,
- "QV-Proposed-BC_SPANs:bc:abc-1_SI-body": true,
- "QV-Proposed-BC_SPANs:bc:abc-1_SI-div": true,
- "QV-Proposed-BC_FONTs:bc:084-SPAN-1_SI-dM": true,
- "QV-Proposed-BC_FONTs:bc:084-SPAN-1_SI-body": true,
- "QV-Proposed-BC_FONTs:bc:084-SPAN-1_SI-div": true,
- "QV-Proposed-BC_SPANs:bc:cde-SPAN-1_SI-dM": true,
- "QV-Proposed-BC_SPANs:bc:cde-SPAN-1_SI-body": true,
- "QV-Proposed-BC_SPANs:bc:cde-SPAN-1_SI-div": true,
- "QV-Proposed-BC_SPAN.ass.s:bc:rgb-1_SI-dM": true,
- "QV-Proposed-BC_SPAN.ass.s:bc:rgb-1_SI-body": true,
- "QV-Proposed-BC_SPAN.ass.s:bc:rgb-1_SI-div": true,
- "QV-Proposed-BC_SPAN.bcred-1_SI-dM": true,
- "QV-Proposed-BC_SPAN.bcred-1_SI-body": true,
- "QV-Proposed-BC_SPAN.bcred-1_SI-div": true,
- "QV-Proposed-BC_MYBCRED-1-SI-dM": true,
- "QV-Proposed-BC_MYBCRED-1-SI-body": true,
- "QV-Proposed-BC_MYBCRED-1-SI-div": true,
- "QV-Proposed-HC_FONTs:bc:fc0-1_SI-dM": true,
- "QV-Proposed-HC_FONTs:bc:fc0-1_SI-body": true,
- "QV-Proposed-HC_FONTs:bc:fc0-1_SI-div": true,
- "QV-Proposed-HC_SPANs:bc:a0c-1_SI-dM": true,
- "QV-Proposed-HC_SPANs:bc:a0c-1_SI-body": true,
- "QV-Proposed-HC_SPANs:bc:a0c-1_SI-div": true,
- "QV-Proposed-HC_SPAN.ass.s:bc:rgb-1_SI-dM": true,
- "QV-Proposed-HC_SPAN.ass.s:bc:rgb-1_SI-body": true,
- "QV-Proposed-HC_SPAN.ass.s:bc:rgb-1_SI-div": true,
- "QV-Proposed-HC_FONTs:bc:83e-SPAN-1_SI-dM": true,
- "QV-Proposed-HC_FONTs:bc:83e-SPAN-1_SI-body": true,
- "QV-Proposed-HC_FONTs:bc:83e-SPAN-1_SI-div": true,
- "QV-Proposed-HC_SPANs:bc:b12-SPAN-1_SI-dM": true,
- "QV-Proposed-HC_SPANs:bc:b12-SPAN-1_SI-body": true,
- "QV-Proposed-HC_SPANs:bc:b12-SPAN-1_SI-div": true,
- "QV-Proposed-HC_SPAN.bcred-1_SI-dM": true,
- "QV-Proposed-HC_SPAN.bcred-1_SI-body": true,
- "QV-Proposed-HC_SPAN.bcred-1_SI-div": true,
- "QV-Proposed-HC_MYBCRED-1-SI-dM": true,
- "QV-Proposed-HC_MYBCRED-1-SI-body": true,
- "QV-Proposed-HC_MYBCRED-1-SI-div": true
- },
- "select": {
- "S-Proposed-UNSEL_TEXT-1_SI-dM": true,
- "S-Proposed-UNSEL_TEXT-1_SI-body": true,
- "S-Proposed-UNSEL_TEXT-1_SI-div": true,
- "S-Proposed-SM:m.f.c_TEXT-1_SI-1-dM": true,
- "S-Proposed-SM:m.f.c_TEXT-1_SI-1-body": true,
- "S-Proposed-SM:m.f.c_TEXT-1_SI-1-div": true,
- "S-Proposed-SM:m.b.c_TEXT-1_SI-1-dM": true,
- "S-Proposed-SM:m.b.c_TEXT-1_SI-1-body": true,
- "S-Proposed-SM:m.b.c_TEXT-1_SI-1-div": true,
- "S-Proposed-SM:m.b.w_TEXT-1_SI-1-dM": true,
- "S-Proposed-SM:m.b.w_TEXT-1_SI-1-body": true,
- "S-Proposed-SM:m.b.w_TEXT-1_SI-1-div": true,
- "S-Proposed-SM:m.f.c_CHAR-5_SI-2-dM": true,
- "S-Proposed-SM:m.f.c_CHAR-5_SI-2-body": true,
- "S-Proposed-SM:m.f.c_CHAR-5_SI-2-div": true,
- "S-Proposed-SM:m.f.c_CHAR-5_SR-dM": true,
- "S-Proposed-SM:m.f.c_CHAR-5_SR-body": true,
- "S-Proposed-SM:m.f.c_CHAR-5_SR-div": true,
- "S-Proposed-SM:m.b.c_CHAR-5_SR-dM": true,
- "S-Proposed-SM:m.b.c_CHAR-5_SR-body": true,
- "S-Proposed-SM:m.b.c_CHAR-5_SR-div": true,
- "S-Proposed-SM:m.f.w_TEXT-jp_SC-1-dM": true,
- "S-Proposed-SM:m.f.w_TEXT-jp_SC-1-body": true,
- "S-Proposed-SM:m.f.w_TEXT-jp_SC-1-div": true,
- "S-Proposed-SM:m.f.w_TEXT-jp_SC-2-dM": true,
- "S-Proposed-SM:m.f.w_TEXT-jp_SC-2-body": true,
- "S-Proposed-SM:m.f.w_TEXT-jp_SC-2-div": true,
- "S-Proposed-SM:m.f.w_TEXT-jp_SC-5-dM": true,
- "S-Proposed-SM:m.f.w_TEXT-jp_SC-5-body": true,
- "S-Proposed-SM:m.f.w_TEXT-jp_SC-5-div": true,
- "S-Proposed-SM:e.b.w_TEXT-1_SI-3-dM": true,
- "S-Proposed-SM:e.b.w_TEXT-1_SI-3-body": true,
- "S-Proposed-SM:e.b.w_TEXT-1_SI-3-div": true,
- "S-Proposed-SM:e.b.w_TEXT-1_SI-4-dM": true,
- "S-Proposed-SM:e.b.w_TEXT-1_SI-4-body": true,
- "S-Proposed-SM:e.b.w_TEXT-1_SI-4-div": true,
- "S-Proposed-SM:e.b.w_TEXT-1_SI-5-dM": true,
- "S-Proposed-SM:e.b.w_TEXT-1_SI-5-body": true,
- "S-Proposed-SM:e.b.w_TEXT-1_SI-5-div": true,
- "S-Proposed-SM:e.f.w_TEXT-1_SIR-1-dM": true,
- "S-Proposed-SM:e.f.w_TEXT-1_SIR-1-body": true,
- "S-Proposed-SM:e.f.w_TEXT-1_SIR-1-div": true,
- "S-Proposed-SM:e.f.w_TEXT-1_SIR-3-dM": true,
- "S-Proposed-SM:e.f.w_TEXT-1_SIR-3-body": true,
- "S-Proposed-SM:e.f.w_TEXT-1_SIR-3-div": true,
- "S-Proposed-SM:e.f.lb_BR.BR-1_SI-1-dM": true,
- "S-Proposed-SM:e.f.lb_BR.BR-1_SI-1-body": true,
- "S-Proposed-SM:e.f.lb_BR.BR-1_SI-1-div": true,
- "S-Proposed-SM:e.f.lb_P.P.P-1_SI-1-dM": true,
- "S-Proposed-SM:e.f.lb_P.P.P-1_SI-1-body": true,
- "S-Proposed-SM:e.f.lb_P.P.P-1_SI-1-div": true,
- "S-Proposed-SM:e.b.lb_BR.BR-1_SIR-2-dM": true,
- "S-Proposed-SM:e.b.lb_BR.BR-1_SIR-2-body": true,
- "S-Proposed-SM:e.b.lb_BR.BR-1_SIR-2-div": true,
- "S-Proposed-SM:e.b.lb_P.P.P-1_SIR-2-dM": true,
- "S-Proposed-SM:e.b.lb_P.P.P-1_SIR-2-body": true,
- "S-Proposed-SM:e.b.lb_P.P.P-1_SIR-2-div": true,
- "S-Proposed-SM:e.f.l_BR.BR-2_SI-1-dM": true,
- "S-Proposed-SM:e.f.l_BR.BR-2_SI-1-body": true,
- "S-Proposed-SM:e.f.l_BR.BR-2_SI-1-div": true,
- "A-Proposed-B_TEXT-1_SI-dM": true,
- "A-Proposed-B_TEXT-1_SI-body": true,
- "A-Proposed-B_TEXT-1_SI-div": true,
- "A-Proposed-B_TEXT-1_SIR-dM": true,
- "A-Proposed-B_TEXT-1_SIR-body": true,
- "A-Proposed-B_TEXT-1_SIR-div": true,
- "A-Proposed-B_I-1_SL-dM": true,
- "A-Proposed-B_I-1_SL-body": true,
- "A-Proposed-B_I-1_SL-div": true,
- "A-Proposed-I_TEXT-1_SI-dM": true,
- "A-Proposed-I_TEXT-1_SI-body": true,
- "A-Proposed-I_TEXT-1_SI-div": true,
- "A-Proposed-U_TEXT-1_SI-dM": true,
- "A-Proposed-U_TEXT-1_SI-body": true,
- "A-Proposed-U_TEXT-1_SI-div": true,
- "A-Proposed-S_TEXT-1_SI-dM": true,
- "A-Proposed-S_TEXT-1_SI-body": true,
- "A-Proposed-S_TEXT-1_SI-div": true,
- "A-Proposed-SUB_TEXT-1_SI-dM": true,
- "A-Proposed-SUB_TEXT-1_SI-body": true,
- "A-Proposed-SUB_TEXT-1_SI-div": true,
- "A-Proposed-SUP_TEXT-1_SI-dM": true,
- "A-Proposed-SUP_TEXT-1_SI-body": true,
- "A-Proposed-SUP_TEXT-1_SI-div": true,
- "A-Proposed-CL:url_TEXT-1_SI-dM": true,
- "A-Proposed-CL:url_TEXT-1_SI-body": true,
- "A-Proposed-CL:url_TEXT-1_SI-div": true,
- "A-Proposed-BC:blue_TEXT-1_SI-dM": true,
- "A-Proposed-BC:blue_TEXT-1_SI-body": true,
- "A-Proposed-BC:blue_TEXT-1_SI-div": true,
- "A-Proposed-FC:blue_TEXT-1_SI-dM": true,
- "A-Proposed-FC:blue_TEXT-1_SI-body": true,
- "A-Proposed-FC:blue_TEXT-1_SI-div": true,
- "A-Proposed-HC:blue_TEXT-1_SI-dM": true,
- "A-Proposed-HC:blue_TEXT-1_SI-body": true,
- "A-Proposed-HC:blue_TEXT-1_SI-div": true,
- "A-Proposed-FN:a_TEXT-1_SI-dM": true,
- "A-Proposed-FN:a_TEXT-1_SI-body": true,
- "A-Proposed-FN:a_TEXT-1_SI-div": true,
- "A-Proposed-FS:2_TEXT-1_SI-dM": true,
- "A-Proposed-FS:2_TEXT-1_SI-body": true,
- "A-Proposed-FS:2_TEXT-1_SI-div": true,
- "A-Proposed-FS:18px_TEXT-1_SI-dM": true,
- "A-Proposed-FS:18px_TEXT-1_SI-body": true,
- "A-Proposed-FS:18px_TEXT-1_SI-div": true,
- "A-Proposed-FS:large_TEXT-1_SI-dM": true,
- "A-Proposed-FS:large_TEXT-1_SI-body": true,
- "A-Proposed-FS:large_TEXT-1_SI-div": true,
- "A-Proposed-INCFS:2_TEXT-1_SI-dM": true,
- "A-Proposed-INCFS:2_TEXT-1_SI-body": true,
- "A-Proposed-INCFS:2_TEXT-1_SI-div": true,
- "A-Proposed-DECFS:2_TEXT-1_SI-dM": true,
- "A-Proposed-DECFS:2_TEXT-1_SI-body": true,
- "A-Proposed-DECFS:2_TEXT-1_SI-div": true,
- "A-Proposed-CB:name_TEXT-1_SI-dM": true,
- "A-Proposed-CB:name_TEXT-1_SI-body": true,
- "A-Proposed-CB:name_TEXT-1_SI-div": true,
- "AC-Proposed-B_TEXT-1_SI-dM": true,
- "AC-Proposed-B_TEXT-1_SI-body": true,
- "AC-Proposed-B_TEXT-1_SI-div": true,
- "AC-Proposed-I_TEXT-1_SI-dM": true,
- "AC-Proposed-I_TEXT-1_SI-body": true,
- "AC-Proposed-I_TEXT-1_SI-div": true,
- "AC-Proposed-U_TEXT-1_SI-dM": true,
- "AC-Proposed-U_TEXT-1_SI-body": true,
- "AC-Proposed-U_TEXT-1_SI-div": true,
- "AC-Proposed-S_TEXT-1_SI-dM": true,
- "AC-Proposed-S_TEXT-1_SI-body": true,
- "AC-Proposed-S_TEXT-1_SI-div": true,
- "AC-Proposed-SUB_TEXT-1_SI-dM": true,
- "AC-Proposed-SUB_TEXT-1_SI-body": true,
- "AC-Proposed-SUB_TEXT-1_SI-div": true,
- "AC-Proposed-SUP_TEXT-1_SI-dM": true,
- "AC-Proposed-SUP_TEXT-1_SI-body": true,
- "AC-Proposed-SUP_TEXT-1_SI-div": true,
- "AC-Proposed-BC:blue_TEXT-1_SI-dM": true,
- "AC-Proposed-BC:blue_TEXT-1_SI-body": true,
- "AC-Proposed-BC:blue_TEXT-1_SI-div": true,
- "AC-Proposed-FC:blue_TEXT-1_SI-dM": true,
- "AC-Proposed-FC:blue_TEXT-1_SI-body": true,
- "AC-Proposed-FC:blue_TEXT-1_SI-div": true,
- "AC-Proposed-HC:blue_TEXT-1_SI-dM": true,
- "AC-Proposed-HC:blue_TEXT-1_SI-body": true,
- "AC-Proposed-HC:blue_TEXT-1_SI-div": true,
- "AC-Proposed-FN:a_TEXT-1_SI-dM": true,
- "AC-Proposed-FN:a_TEXT-1_SI-body": true,
- "AC-Proposed-FN:a_TEXT-1_SI-div": true,
- "AC-Proposed-FS:2_TEXT-1_SI-dM": true,
- "AC-Proposed-FS:2_TEXT-1_SI-body": true,
- "AC-Proposed-FS:2_TEXT-1_SI-div": true,
- "AC-Proposed-FS:18px_TEXT-1_SI-dM": true,
- "AC-Proposed-FS:18px_TEXT-1_SI-body": true,
- "AC-Proposed-FS:18px_TEXT-1_SI-div": true,
- "AC-Proposed-FS:large_TEXT-1_SI-dM": true,
- "AC-Proposed-FS:large_TEXT-1_SI-body": true,
- "AC-Proposed-FS:large_TEXT-1_SI-div": true,
- "C-Proposed-I_I-1_SL-dM": true,
- "C-Proposed-I_I-1_SL-body": true,
- "C-Proposed-I_I-1_SL-div": true,
- "C-Proposed-I_B-I-1_SO-dM": true,
- "C-Proposed-I_B-I-1_SO-body": true,
- "C-Proposed-I_B-I-1_SO-div": true,
- "C-Proposed-U_U-1_SO-dM": true,
- "C-Proposed-U_U-1_SO-body": true,
- "C-Proposed-U_U-1_SO-div": true,
- "C-Proposed-U_U-1_SL-dM": true,
- "C-Proposed-U_U-1_SL-body": true,
- "C-Proposed-U_U-1_SL-div": true,
- "C-Proposed-U_S-U-1_SO-dM": true,
- "C-Proposed-U_S-U-1_SO-body": true,
- "C-Proposed-U_S-U-1_SO-div": true,
- "C-Proposed-BC:ace_FONT.ass.s:bc:rgb-1_SW-dM": true,
- "C-Proposed-BC:ace_FONT.ass.s:bc:rgb-1_SW-body": true,
- "C-Proposed-BC:ace_FONT.ass.s:bc:rgb-1_SW-div": true,
- "C-Proposed-FC:g_FONTc:b.sz:6-1_SI-dM": true,
- "C-Proposed-FC:g_FONTc:b.sz:6-1_SI-body": true,
- "C-Proposed-FC:g_FONTc:b.sz:6-1_SI-div": true,
- "C-Proposed-HC:g_SPAN.ass.s:c:rgb-1_SW-dM": true,
- "C-Proposed-HC:g_SPAN.ass.s:c:rgb-1_SW-body": true,
- "C-Proposed-HC:g_SPAN.ass.s:c:rgb-1_SW-div": true,
- "C-Proposed-FN:c_FONTf:a-1_SI-dM": true,
- "C-Proposed-FN:c_FONTf:a-1_SI-body": true,
- "C-Proposed-FN:c_FONTf:a-1_SI-div": true,
- "C-Proposed-FN:c_FONTf:a-2_SL-dM": true,
- "C-Proposed-FN:c_FONTf:a-2_SL-body": true,
- "C-Proposed-FN:c_FONTf:a-2_SL-div": true,
- "C-Proposed-FS:1_SPAN.ass.s:fs:large-1_SW-dM": true,
- "C-Proposed-FS:1_SPAN.ass.s:fs:large-1_SW-body": true,
- "C-Proposed-FS:1_SPAN.ass.s:fs:large-1_SW-div": true,
- "C-Proposed-FS:5_FONTsz:1.s:fs:xs-1_SW-dM": true,
- "C-Proposed-FS:5_FONTsz:1.s:fs:xs-1_SW-body": true,
- "C-Proposed-FS:5_FONTsz:1.s:fs:xs-1_SW-div": true,
- "C-Proposed-FS:2_FONTc:b.sz:6-1_SI-dM": true,
- "C-Proposed-FS:2_FONTc:b.sz:6-1_SI-body": true,
- "C-Proposed-FS:2_FONTc:b.sz:6-1_SI-div": true,
- "C-Proposed-FS:larger_FONTsz:4-dM": true,
- "C-Proposed-FS:larger_FONTsz:4-body": true,
- "C-Proposed-FS:larger_FONTsz:4-div": true,
- "C-Proposed-FS:smaller_FONTsz:4-dM": true,
- "C-Proposed-FS:smaller_FONTsz:4-body": true,
- "C-Proposed-FS:smaller_FONTsz:4-div": true,
- "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SO-dM": true,
- "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SO-body": true,
- "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SO-div": true,
- "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SW-dM": true,
- "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SW-body": true,
- "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SW-div": true,
- "C-Proposed-FB:h1_ADDRESS-FONT.ass.sz:4-1_SW-dM": true,
- "C-Proposed-FB:h1_ADDRESS-FONT.ass.sz:4-1_SW-body": true,
- "C-Proposed-FB:h1_ADDRESS-FONT.ass.sz:4-1_SW-div": true,
- "CC-Proposed-I_I-1_SL-dM": true,
- "CC-Proposed-I_I-1_SL-body": true,
- "CC-Proposed-I_I-1_SL-div": true,
- "CC-Proposed-I_B-1_SL-dM": true,
- "CC-Proposed-I_B-1_SL-body": true,
- "CC-Proposed-I_B-1_SL-div": true,
- "CC-Proposed-I_B-1_SW-dM": true,
- "CC-Proposed-I_B-1_SW-body": true,
- "CC-Proposed-I_B-1_SW-div": true,
- "CC-Proposed-BC:gray_SPANs:bc:b-1_SI-dM": true,
- "CC-Proposed-BC:gray_SPANs:bc:b-1_SI-body": true,
- "CC-Proposed-BC:gray_SPANs:bc:b-1_SI-div": true,
- "CC-Proposed-BC:gray_P-SPANs:bc:b-3_SL-dM": true,
- "CC-Proposed-BC:gray_P-SPANs:bc:b-3_SL-body": true,
- "CC-Proposed-BC:gray_P-SPANs:bc:b-3_SL-div": true,
- "CC-Proposed-BC:gray_SPANs:bc:b-2_SL-dM": true,
- "CC-Proposed-BC:gray_SPANs:bc:b-2_SL-body": true,
- "CC-Proposed-BC:gray_SPANs:bc:b-2_SL-div": true,
- "CC-Proposed-BC:gray_SPANs:bc:b-2_SR-dM": true,
- "CC-Proposed-BC:gray_SPANs:bc:b-2_SR-body": true,
- "CC-Proposed-BC:gray_SPANs:bc:b-2_SR-div": true,
- "CC-Proposed-FN:c_FONTf:a-1_SI-dM": true,
- "CC-Proposed-FN:c_FONTf:a-1_SI-body": true,
- "CC-Proposed-FN:c_FONTf:a-1_SI-div": true,
- "CC-Proposed-FN:c_FONTf:a-2_SL-dM": true,
- "CC-Proposed-FN:c_FONTf:a-2_SL-body": true,
- "CC-Proposed-FN:c_FONTf:a-2_SL-div": true,
- "CC-Proposed-FS:1_SPANs:fs:l-1_SW-dM": true,
- "CC-Proposed-FS:1_SPANs:fs:l-1_SW-body": true,
- "CC-Proposed-FS:1_SPANs:fs:l-1_SW-div": true,
- "CC-Proposed-FS:18px_SPANs:fs:l-1_SW-dM": true,
- "CC-Proposed-FS:18px_SPANs:fs:l-1_SW-body": true,
- "CC-Proposed-FS:18px_SPANs:fs:l-1_SW-div": true,
- "CC-Proposed-FS:4_SPANs:fs:l-1_SW-dM": true,
- "CC-Proposed-FS:4_SPANs:fs:l-1_SW-body": true,
- "CC-Proposed-FS:4_SPANs:fs:l-1_SW-div": true,
- "CC-Proposed-FS:4_SPANs:fs:18px-1_SW-dM": true,
- "CC-Proposed-FS:4_SPANs:fs:18px-1_SW-body": true,
- "CC-Proposed-FS:4_SPANs:fs:18px-1_SW-div": true,
- "CC-Proposed-FS:larger_SPANs:fs:l-1_SI-dM": true,
- "CC-Proposed-FS:larger_SPANs:fs:l-1_SI-body": true,
- "CC-Proposed-FS:larger_SPANs:fs:l-1_SI-div": true,
- "CC-Proposed-FS:smaller_SPANs:fs:l-1_SI-dM": true,
- "CC-Proposed-FS:smaller_SPANs:fs:l-1_SI-body": true,
- "CC-Proposed-FS:smaller_SPANs:fs:l-1_SI-div": true,
- "U-RFC-UNLINK_A-1_SO-dM": true,
- "U-RFC-UNLINK_A-1_SO-body": true,
- "U-RFC-UNLINK_A-1_SO-div": true,
- "U-RFC-UNLINK_A-1_SW-dM": true,
- "U-RFC-UNLINK_A-1_SW-body": true,
- "U-RFC-UNLINK_A-1_SW-div": true,
- "U-RFC-UNLINK_A-2_SO-dM": true,
- "U-RFC-UNLINK_A-2_SO-body": true,
- "U-RFC-UNLINK_A-2_SO-div": true,
- "U-RFC-UNLINK_A2-1_SO-dM": true,
- "U-RFC-UNLINK_A2-1_SO-body": true,
- "U-RFC-UNLINK_A2-1_SO-div": true,
- "U-Proposed-B_B-P3-1_SO12-dM": true,
- "U-Proposed-B_B-P3-1_SO12-body": true,
- "U-Proposed-B_B-P3-1_SO12-div": true,
- "U-Proposed-B_B-P-I..P-1_SO-I-dM": true,
- "U-Proposed-B_B-P-I..P-1_SO-I-body": true,
- "U-Proposed-B_B-P-I..P-1_SO-I-div": true,
- "U-Proposed-B_B-2_SL-dM": true,
- "U-Proposed-B_B-2_SL-body": true,
- "U-Proposed-B_B-2_SL-div": true,
- "U-Proposed-B_B-2_SR-dM": true,
- "U-Proposed-B_B-2_SR-body": true,
- "U-Proposed-B_B-2_SR-div": true,
- "U-Proposed-I_I-P3-1_SO2-dM": true,
- "U-Proposed-I_I-P3-1_SO2-body": true,
- "U-Proposed-I_I-P3-1_SO2-div": true,
- "U-Proposed-U_U-S-1_SO-dM": true,
- "U-Proposed-U_U-S-1_SO-body": true,
- "U-Proposed-U_U-S-1_SO-div": true,
- "U-Proposed-U_U-S-2_SI-dM": true,
- "U-Proposed-U_U-S-2_SI-body": true,
- "U-Proposed-U_U-S-2_SI-div": true,
- "U-Proposed-U_U-P3-1_SO-dM": true,
- "U-Proposed-U_U-P3-1_SO-body": true,
- "U-Proposed-U_U-P3-1_SO-div": true,
- "U-Proposed-S_DEL-1_SW-dM": true,
- "U-Proposed-S_DEL-1_SW-body": true,
- "U-Proposed-S_DEL-1_SW-div": true,
- "U-Proposed-S_S-U-1_SI-dM": true,
- "U-Proposed-S_S-U-1_SI-body": true,
- "U-Proposed-S_S-U-1_SI-div": true,
- "U-Proposed-S_U-S-1_SI-dM": true,
- "U-Proposed-S_U-S-1_SI-body": true,
- "U-Proposed-S_U-S-1_SI-div": true,
- "U-Proposed-SUB_SPANs:va:sub-1_SW-dM": true,
- "U-Proposed-SUB_SPANs:va:sub-1_SW-body": true,
- "U-Proposed-SUB_SPANs:va:sub-1_SW-div": true,
- "U-Proposed-SUP_SPANs:va:super-1_SW-dM": true,
- "U-Proposed-SUP_SPANs:va:super-1_SW-body": true,
- "U-Proposed-SUP_SPANs:va:super-1_SW-div": true,
- "U-Proposed-UNLINK_A-1_SC-dM": true,
- "U-Proposed-UNLINK_A-1_SC-body": true,
- "U-Proposed-UNLINK_A-1_SC-div": true,
- "U-Proposed-UNLINK_A-1_SI-dM": true,
- "U-Proposed-UNLINK_A-1_SI-body": true,
- "U-Proposed-UNLINK_A-1_SI-div": true,
- "U-Proposed-UNLINK_A-2_SL-dM": true,
- "U-Proposed-UNLINK_A-2_SL-body": true,
- "U-Proposed-UNLINK_A-2_SL-div": true,
- "U-Proposed-UNLINK_A-3_SR-dM": true,
- "U-Proposed-UNLINK_A-3_SR-body": true,
- "U-Proposed-UNLINK_A-3_SR-div": true,
- "U-Proposed-OUTDENT_DIV-1_SW-dM": true,
- "U-Proposed-OUTDENT_DIV-1_SW-body": true,
- "U-Proposed-OUTDENT_DIV-1_SW-div": true,
- "U-Proposed-REMOVEFORMAT_Ahref:url-1_SW-dM": true,
- "U-Proposed-REMOVEFORMAT_Ahref:url-1_SW-body": true,
- "U-Proposed-REMOVEFORMAT_Ahref:url-1_SW-div": true,
- "U-Proposed-REMOVEFORMAT_TABLE-TBODY-TR-TD-1_SW-dM": true,
- "U-Proposed-REMOVEFORMAT_TABLE-TBODY-TR-TD-1_SW-body": true,
- "U-Proposed-REMOVEFORMAT_TABLE-TBODY-TR-TD-1_SW-div": true,
- "U-Proposed-UNBOOKMARK_An:name-1_SW-dM": true,
- "U-Proposed-UNBOOKMARK_An:name-1_SW-body": true,
- "U-Proposed-UNBOOKMARK_An:name-1_SW-div": true,
- "UC-Proposed-S_SPANc:s-1_SW-dM": true,
- "UC-Proposed-S_SPANc:s-1_SW-body": true,
- "UC-Proposed-S_SPANc:s-1_SW-div": true,
- "UC-Proposed-S_SPANc:s-2_SI-dM": true,
- "UC-Proposed-S_SPANc:s-2_SI-body": true,
- "UC-Proposed-S_SPANc:s-2_SI-div": true,
- "D-Proposed-CHAR-3_SC-dM": true,
- "D-Proposed-CHAR-3_SC-body": true,
- "D-Proposed-CHAR-3_SC-div": true,
- "D-Proposed-CHAR-4_SC-dM": true,
- "D-Proposed-CHAR-4_SC-body": true,
- "D-Proposed-CHAR-4_SC-div": true,
- "D-Proposed-CHAR-5_SC-dM": true,
- "D-Proposed-CHAR-5_SC-body": true,
- "D-Proposed-CHAR-5_SC-div": true,
- "D-Proposed-CHAR-5_SI-1-dM": true,
- "D-Proposed-CHAR-5_SI-1-body": true,
- "D-Proposed-CHAR-5_SI-1-div": true,
- "D-Proposed-CHAR-5_SI-2-dM": true,
- "D-Proposed-CHAR-5_SI-2-body": true,
- "D-Proposed-CHAR-5_SI-2-div": true,
- "D-Proposed-CHAR-5_SR-dM": true,
- "D-Proposed-CHAR-5_SR-body": true,
- "D-Proposed-CHAR-5_SR-div": true,
- "D-Proposed-CHAR-6_SC-dM": true,
- "D-Proposed-CHAR-6_SC-body": true,
- "D-Proposed-CHAR-6_SC-div": true,
- "D-Proposed-CHAR-7_SC-dM": true,
- "D-Proposed-CHAR-7_SC-body": true,
- "D-Proposed-CHAR-7_SC-div": true,
- "D-Proposed-B-1_SW-div": true,
- "D-Proposed-B-1_SL-dM": true,
- "D-Proposed-B-1_SL-body": true,
- "D-Proposed-B-1_SL-div": true,
- "D-Proposed-B-1_SR-dM": true,
- "D-Proposed-B-1_SR-body": true,
- "D-Proposed-B-1_SR-div": true,
- "D-Proposed-B.I-1_SM-dM": true,
- "D-Proposed-B.I-1_SM-body": true,
- "D-Proposed-B.I-1_SM-div": true,
- "D-Proposed-OL-LI2-1_SO1-dM": true,
- "D-Proposed-OL-LI2-1_SO1-body": true,
- "D-Proposed-OL-LI2-1_SO1-div": true,
- "D-Proposed-OL-LI-1_SW-dM": true,
- "D-Proposed-OL-LI-1_SW-body": true,
- "D-Proposed-OL-LI-1_SW-div": true,
- "D-Proposed-OL-LI-1_SO-dM": true,
- "D-Proposed-OL-LI-1_SO-body": true,
- "D-Proposed-OL-LI-1_SO-div": true,
- "D-Proposed-HR.BR-1_SM-dM": true,
- "D-Proposed-HR.BR-1_SM-body": true,
- "D-Proposed-HR.BR-1_SM-div": true,
- "D-Proposed-TR2rs:2-1_SO1-dM": true,
- "D-Proposed-TR2rs:2-1_SO1-body": true,
- "D-Proposed-TR2rs:2-1_SO1-div": true,
- "D-Proposed-TR2rs:2-1_SO2-dM": true,
- "D-Proposed-TR2rs:2-1_SO2-body": true,
- "D-Proposed-TR2rs:2-1_SO2-div": true,
- "D-Proposed-TR3rs:3-1_SO1-dM": true,
- "D-Proposed-TR3rs:3-1_SO1-body": true,
- "D-Proposed-TR3rs:3-1_SO1-div": true,
- "D-Proposed-TR3rs:3-1_SO2-dM": true,
- "D-Proposed-TR3rs:3-1_SO2-body": true,
- "D-Proposed-TR3rs:3-1_SO2-div": true,
- "D-Proposed-TR3rs:3-1_SO3-dM": true,
- "D-Proposed-TR3rs:3-1_SO3-body": true,
- "D-Proposed-TR3rs:3-1_SO3-div": true,
- "D-Proposed-DIV:ce:false-1_SB-dM": true,
- "D-Proposed-DIV:ce:false-1_SB-body": true,
- "D-Proposed-DIV:ce:false-1_SB-div": true,
- "D-Proposed-DIV:ce:false-1_SL-dM": true,
- "D-Proposed-DIV:ce:false-1_SL-body": true,
- "D-Proposed-DIV:ce:false-1_SL-div": true,
- "D-Proposed-DIV:ce:false-1_SR-dM": true,
- "D-Proposed-DIV:ce:false-1_SR-body": true,
- "D-Proposed-DIV:ce:false-1_SR-div": true,
- "D-Proposed-DIV:ce:false-1_SI-dM": true,
- "D-Proposed-SPAN:d:ib-2_SL-dM": true,
- "D-Proposed-SPAN:d:ib-2_SL-body": true,
- "D-Proposed-SPAN:d:ib-2_SL-div": true,
- "D-Proposed-SPAN:d:ib-3_SR-dM": true,
- "D-Proposed-SPAN:d:ib-3_SR-body": true,
- "D-Proposed-SPAN:d:ib-3_SR-div": true,
- "FD-Proposed-B-1_SW-div": true,
- "FD-Proposed-OL-LI-1_SW-dM": true,
- "FD-Proposed-OL-LI-1_SW-body": true,
- "FD-Proposed-OL-LI-1_SW-div": true,
- "FD-Proposed-OL-LI-1_SO-dM": true,
- "FD-Proposed-OL-LI-1_SO-body": true,
- "FD-Proposed-OL-LI-1_SO-div": true,
- "FD-Proposed-TABLE-1_SB-dM": true,
- "FD-Proposed-TABLE-1_SB-body": true,
- "FD-Proposed-TABLE-1_SB-div": true,
- "FD-Proposed-TD-1_SE-dM": true,
- "FD-Proposed-TD-1_SE-body": true,
- "FD-Proposed-TD-1_SE-div": true,
- "FD-Proposed-TD2-1_SE1-dM": true,
- "FD-Proposed-TD2-1_SE1-body": true,
- "FD-Proposed-TD2-1_SE1-div": true,
- "FD-Proposed-TD2-1_SM-dM": true,
- "FD-Proposed-TD2-1_SM-body": true,
- "FD-Proposed-TD2-1_SM-div": true,
- "FD-Proposed-TR2rs:2-1_SO1-dM": true,
- "FD-Proposed-TR2rs:2-1_SO1-body": true,
- "FD-Proposed-TR2rs:2-1_SO1-div": true,
- "FD-Proposed-TR2rs:2-1_SO2-dM": true,
- "FD-Proposed-TR2rs:2-1_SO2-body": true,
- "FD-Proposed-TR2rs:2-1_SO2-div": true,
- "FD-Proposed-TR3rs:3-1_SO1-dM": true,
- "FD-Proposed-TR3rs:3-1_SO1-body": true,
- "FD-Proposed-TR3rs:3-1_SO1-div": true,
- "FD-Proposed-TR3rs:3-1_SO2-dM": true,
- "FD-Proposed-TR3rs:3-1_SO2-body": true,
- "FD-Proposed-TR3rs:3-1_SO2-div": true,
- "FD-Proposed-TR3rs:3-1_SO3-dM": true,
- "FD-Proposed-TR3rs:3-1_SO3-body": true,
- "FD-Proposed-TR3rs:3-1_SO3-div": true,
- "FD-Proposed-DIV:ce:false-1_SB-dM": true,
- "FD-Proposed-DIV:ce:false-1_SB-body": true,
- "FD-Proposed-DIV:ce:false-1_SB-div": true,
- "FD-Proposed-DIV:ce:false-1_SL-dM": true,
- "FD-Proposed-DIV:ce:false-1_SL-body": true,
- "FD-Proposed-DIV:ce:false-1_SL-div": true,
- "FD-Proposed-DIV:ce:false-1_SR-dM": true,
- "FD-Proposed-DIV:ce:false-1_SR-body": true,
- "FD-Proposed-DIV:ce:false-1_SR-div": true,
- "FD-Proposed-DIV:ce:false-1_SI-dM": true,
- "I-Proposed-IHR_TEXT-1_SC-dM": true,
- "I-Proposed-IHR_TEXT-1_SC-body": true,
- "I-Proposed-IHR_TEXT-1_SC-div": true,
- "I-Proposed-IHR_TEXT-1_SI-dM": true,
- "I-Proposed-IHR_TEXT-1_SI-body": true,
- "I-Proposed-IHR_TEXT-1_SI-div": true,
- "I-Proposed-IHR_B-1_SC-dM": true,
- "I-Proposed-IHR_B-1_SC-body": true,
- "I-Proposed-IHR_B-1_SC-div": true,
- "I-Proposed-IHR_B-1_SS-dM": true,
- "I-Proposed-IHR_B-1_SS-body": true,
- "I-Proposed-IHR_B-1_SS-div": true,
- "I-Proposed-IHR_B-I-1_SMR-dM": true,
- "I-Proposed-IHR_B-I-1_SMR-body": true,
- "I-Proposed-IHR_B-I-1_SMR-div": true,
- "I-Proposed-IBR_LI-1_SC-dM": true,
- "I-Proposed-IBR_LI-1_SC-body": true,
- "I-Proposed-IBR_LI-1_SC-div": true,
- "I-Proposed-IIMG:._SPAN-IMG-1_SO-dM": true,
- "I-Proposed-IIMG:._SPAN-IMG-1_SO-body": true,
- "I-Proposed-IIMG:._SPAN-IMG-1_SO-div": true,
- "I-Proposed-IIMG:._IMG-1_SO-dM": true,
- "I-Proposed-IIMG:._IMG-1_SO-body": true,
- "I-Proposed-IIMG:._IMG-1_SO-div": true,
- "I-Proposed-IHTML:BR_TEXT-1_SC-dM": true,
- "I-Proposed-IHTML:BR_TEXT-1_SC-body": true,
- "I-Proposed-IHTML:BR_TEXT-1_SC-div": true,
- "I-Proposed-IHTML:S_TEXT-1_SI-dM": true,
- "I-Proposed-IHTML:S_TEXT-1_SI-body": true,
- "I-Proposed-IHTML:S_TEXT-1_SI-div": true,
- "I-Proposed-IHTML:H1.H2_TEXT-1_SI-dM": true,
- "I-Proposed-IHTML:H1.H2_TEXT-1_SI-body": true,
- "I-Proposed-IHTML:H1.H2_TEXT-1_SI-div": true,
- "I-Proposed-IHTML:P-B_TEXT-1_SI-dM": true,
- "I-Proposed-IHTML:P-B_TEXT-1_SI-body": true,
- "I-Proposed-IHTML:P-B_TEXT-1_SI-div": true,
- "Q-Proposed-SELECTALL_TEXT-1-dM": true,
- "Q-Proposed-SELECTALL_TEXT-1-body": true,
- "Q-Proposed-SELECTALL_TEXT-1-div": true,
- "Q-Proposed-UNSELECT_TEXT-1-dM": true,
- "Q-Proposed-UNSELECT_TEXT-1-body": true,
- "Q-Proposed-UNSELECT_TEXT-1-div": true,
- "Q-Proposed-UNDO_TEXT-1-dM": true,
- "Q-Proposed-UNDO_TEXT-1-body": true,
- "Q-Proposed-UNDO_TEXT-1-div": true,
- "Q-Proposed-REDO_TEXT-1-dM": true,
- "Q-Proposed-REDO_TEXT-1-body": true,
- "Q-Proposed-REDO_TEXT-1-div": true,
- "Q-Proposed-BOLD_TEXT-1-dM": true,
- "Q-Proposed-BOLD_TEXT-1-body": true,
- "Q-Proposed-BOLD_TEXT-1-div": true,
- "Q-Proposed-BOLD_B-dM": true,
- "Q-Proposed-BOLD_B-body": true,
- "Q-Proposed-BOLD_B-div": true,
- "Q-Proposed-ITALIC_TEXT-1-dM": true,
- "Q-Proposed-ITALIC_TEXT-1-body": true,
- "Q-Proposed-ITALIC_TEXT-1-div": true,
- "Q-Proposed-ITALIC_I-dM": true,
- "Q-Proposed-ITALIC_I-body": true,
- "Q-Proposed-ITALIC_I-div": true,
- "Q-Proposed-UNDERLINE_TEXT-1-dM": true,
- "Q-Proposed-UNDERLINE_TEXT-1-body": true,
- "Q-Proposed-UNDERLINE_TEXT-1-div": true,
- "Q-Proposed-STRIKETHROUGH_TEXT-1-dM": true,
- "Q-Proposed-STRIKETHROUGH_TEXT-1-body": true,
- "Q-Proposed-STRIKETHROUGH_TEXT-1-div": true,
- "Q-Proposed-SUBSCRIPT_TEXT-1-dM": true,
- "Q-Proposed-SUBSCRIPT_TEXT-1-body": true,
- "Q-Proposed-SUBSCRIPT_TEXT-1-div": true,
- "Q-Proposed-SUPERSCRIPT_TEXT-1-dM": true,
- "Q-Proposed-SUPERSCRIPT_TEXT-1-body": true,
- "Q-Proposed-SUPERSCRIPT_TEXT-1-div": true,
- "Q-Proposed-FORMATBLOCK_TEXT-1-dM": true,
- "Q-Proposed-FORMATBLOCK_TEXT-1-body": true,
- "Q-Proposed-FORMATBLOCK_TEXT-1-div": true,
- "Q-Proposed-CREATELINK_TEXT-1-dM": true,
- "Q-Proposed-CREATELINK_TEXT-1-body": true,
- "Q-Proposed-CREATELINK_TEXT-1-div": true,
- "Q-Proposed-UNLINK_TEXT-1-dM": true,
- "Q-Proposed-UNLINK_TEXT-1-body": true,
- "Q-Proposed-UNLINK_TEXT-1-div": true,
- "Q-Proposed-INSERTHTML_TEXT-1-dM": true,
- "Q-Proposed-INSERTHTML_TEXT-1-body": true,
- "Q-Proposed-INSERTHTML_TEXT-1-div": true,
- "Q-Proposed-INSERTHORIZONTALRULE_TEXT-1-dM": true,
- "Q-Proposed-INSERTHORIZONTALRULE_TEXT-1-body": true,
- "Q-Proposed-INSERTHORIZONTALRULE_TEXT-1-div": true,
- "Q-Proposed-INSERTIMAGE_TEXT-1-dM": true,
- "Q-Proposed-INSERTIMAGE_TEXT-1-body": true,
- "Q-Proposed-INSERTIMAGE_TEXT-1-div": true,
- "Q-Proposed-INSERTLINEBREAK_TEXT-1-dM": true,
- "Q-Proposed-INSERTLINEBREAK_TEXT-1-body": true,
- "Q-Proposed-INSERTLINEBREAK_TEXT-1-div": true,
- "Q-Proposed-INSERTPARAGRAPH_TEXT-1-dM": true,
- "Q-Proposed-INSERTPARAGRAPH_TEXT-1-body": true,
- "Q-Proposed-INSERTPARAGRAPH_TEXT-1-div": true,
- "Q-Proposed-INSERTORDEREDLIST_TEXT-1-dM": true,
- "Q-Proposed-INSERTORDEREDLIST_TEXT-1-body": true,
- "Q-Proposed-INSERTORDEREDLIST_TEXT-1-div": true,
- "Q-Proposed-INSERTUNORDEREDLIST_TEXT-1-dM": true,
- "Q-Proposed-INSERTUNORDEREDLIST_TEXT-1-body": true,
- "Q-Proposed-INSERTUNORDEREDLIST_TEXT-1-div": true,
- "Q-Proposed-INSERTTEXT_TEXT-1-dM": true,
- "Q-Proposed-INSERTTEXT_TEXT-1-body": true,
- "Q-Proposed-INSERTTEXT_TEXT-1-div": true,
- "Q-Proposed-DELETE_TEXT-1-dM": true,
- "Q-Proposed-DELETE_TEXT-1-body": true,
- "Q-Proposed-DELETE_TEXT-1-div": true,
- "Q-Proposed-FORWARDDELETE_TEXT-1-dM": true,
- "Q-Proposed-FORWARDDELETE_TEXT-1-body": true,
- "Q-Proposed-FORWARDDELETE_TEXT-1-div": true,
- "Q-Proposed-STYLEWITHCSS_TEXT-1-dM": true,
- "Q-Proposed-STYLEWITHCSS_TEXT-1-body": true,
- "Q-Proposed-STYLEWITHCSS_TEXT-1-div": true,
- "Q-Proposed-CONTENTREADONLY_TEXT-1-dM": true,
- "Q-Proposed-CONTENTREADONLY_TEXT-1-body": true,
- "Q-Proposed-CONTENTREADONLY_TEXT-1-div": true,
- "Q-Proposed-BACKCOLOR_TEXT-1-dM": true,
- "Q-Proposed-BACKCOLOR_TEXT-1-body": true,
- "Q-Proposed-BACKCOLOR_TEXT-1-div": true,
- "Q-Proposed-FORECOLOR_TEXT-1-dM": true,
- "Q-Proposed-FORECOLOR_TEXT-1-body": true,
- "Q-Proposed-FORECOLOR_TEXT-1-div": true,
- "Q-Proposed-HILITECOLOR_TEXT-1-dM": true,
- "Q-Proposed-HILITECOLOR_TEXT-1-body": true,
- "Q-Proposed-HILITECOLOR_TEXT-1-div": true,
- "Q-Proposed-FONTNAME_TEXT-1-dM": true,
- "Q-Proposed-FONTNAME_TEXT-1-body": true,
- "Q-Proposed-FONTNAME_TEXT-1-div": true,
- "Q-Proposed-FONTSIZE_TEXT-1-dM": true,
- "Q-Proposed-FONTSIZE_TEXT-1-body": true,
- "Q-Proposed-FONTSIZE_TEXT-1-div": true,
- "Q-Proposed-INCREASEFONTSIZE_TEXT-1-dM": true,
- "Q-Proposed-INCREASEFONTSIZE_TEXT-1-body": true,
- "Q-Proposed-INCREASEFONTSIZE_TEXT-1-div": true,
- "Q-Proposed-DECREASEFONTSIZE_TEXT-1-dM": true,
- "Q-Proposed-DECREASEFONTSIZE_TEXT-1-body": true,
- "Q-Proposed-DECREASEFONTSIZE_TEXT-1-div": true,
- "Q-Proposed-HEADING_TEXT-1-dM": true,
- "Q-Proposed-HEADING_TEXT-1-body": true,
- "Q-Proposed-HEADING_TEXT-1-div": true,
- "Q-Proposed-INDENT_TEXT-1-dM": true,
- "Q-Proposed-INDENT_TEXT-1-body": true,
- "Q-Proposed-INDENT_TEXT-1-div": true,
- "Q-Proposed-OUTDENT_TEXT-1-dM": true,
- "Q-Proposed-OUTDENT_TEXT-1-body": true,
- "Q-Proposed-OUTDENT_TEXT-1-div": true,
- "Q-Proposed-CREATEBOOKMARK_TEXT-1-dM": true,
- "Q-Proposed-CREATEBOOKMARK_TEXT-1-body": true,
- "Q-Proposed-CREATEBOOKMARK_TEXT-1-div": true,
- "Q-Proposed-UNBOOKMARK_TEXT-1-dM": true,
- "Q-Proposed-UNBOOKMARK_TEXT-1-body": true,
- "Q-Proposed-UNBOOKMARK_TEXT-1-div": true,
- "Q-Proposed-JUSTIFYCENTER_TEXT-1-dM": true,
- "Q-Proposed-JUSTIFYCENTER_TEXT-1-body": true,
- "Q-Proposed-JUSTIFYCENTER_TEXT-1-div": true,
- "Q-Proposed-JUSTIFYFULL_TEXT-1-dM": true,
- "Q-Proposed-JUSTIFYFULL_TEXT-1-body": true,
- "Q-Proposed-JUSTIFYFULL_TEXT-1-div": true,
- "Q-Proposed-JUSTIFYLEFT_TEXT-1-dM": true,
- "Q-Proposed-JUSTIFYLEFT_TEXT-1-body": true,
- "Q-Proposed-JUSTIFYLEFT_TEXT-1-div": true,
- "Q-Proposed-JUSTIFYRIGHT_TEXT-1-dM": true,
- "Q-Proposed-JUSTIFYRIGHT_TEXT-1-body": true,
- "Q-Proposed-JUSTIFYRIGHT_TEXT-1-div": true,
- "Q-Proposed-REMOVEFORMAT_TEXT-1-dM": true,
- "Q-Proposed-REMOVEFORMAT_TEXT-1-body": true,
- "Q-Proposed-REMOVEFORMAT_TEXT-1-div": true,
- "Q-Proposed-COPY_TEXT-1-dM": true,
- "Q-Proposed-COPY_TEXT-1-body": true,
- "Q-Proposed-COPY_TEXT-1-div": true,
- "Q-Proposed-CUT_TEXT-1-dM": true,
- "Q-Proposed-CUT_TEXT-1-body": true,
- "Q-Proposed-CUT_TEXT-1-div": true,
- "Q-Proposed-PASTE_TEXT-1-dM": true,
- "Q-Proposed-PASTE_TEXT-1-body": true,
- "Q-Proposed-PASTE_TEXT-1-div": true,
- "Q-Proposed-garbage-1_TEXT-1-dM": true,
- "Q-Proposed-garbage-1_TEXT-1-body": true,
- "Q-Proposed-garbage-1_TEXT-1-div": true,
- "QE-Proposed-SELECTALL_TEXT-1-dM": true,
- "QE-Proposed-SELECTALL_TEXT-1-body": true,
- "QE-Proposed-SELECTALL_TEXT-1-div": true,
- "QE-Proposed-UNSELECT_TEXT-1-dM": true,
- "QE-Proposed-UNSELECT_TEXT-1-body": true,
- "QE-Proposed-UNSELECT_TEXT-1-div": true,
- "QE-Proposed-UNDO_TEXT-1-dM": true,
- "QE-Proposed-UNDO_TEXT-1-body": true,
- "QE-Proposed-UNDO_TEXT-1-div": true,
- "QE-Proposed-REDO_TEXT-1-dM": true,
- "QE-Proposed-REDO_TEXT-1-body": true,
- "QE-Proposed-REDO_TEXT-1-div": true,
- "QE-Proposed-BOLD_TEXT-1-dM": true,
- "QE-Proposed-BOLD_TEXT-1-body": true,
- "QE-Proposed-BOLD_TEXT-1-div": true,
- "QE-Proposed-ITALIC_TEXT-1-dM": true,
- "QE-Proposed-ITALIC_TEXT-1-body": true,
- "QE-Proposed-ITALIC_TEXT-1-div": true,
- "QE-Proposed-UNDERLINE_TEXT-1-dM": true,
- "QE-Proposed-UNDERLINE_TEXT-1-body": true,
- "QE-Proposed-UNDERLINE_TEXT-1-div": true,
- "QE-Proposed-STRIKETHROUGH_TEXT-1-dM": true,
- "QE-Proposed-STRIKETHROUGH_TEXT-1-body": true,
- "QE-Proposed-STRIKETHROUGH_TEXT-1-div": true,
- "QE-Proposed-SUBSCRIPT_TEXT-1-dM": true,
- "QE-Proposed-SUBSCRIPT_TEXT-1-body": true,
- "QE-Proposed-SUBSCRIPT_TEXT-1-div": true,
- "QE-Proposed-SUPERSCRIPT_TEXT-1-dM": true,
- "QE-Proposed-SUPERSCRIPT_TEXT-1-body": true,
- "QE-Proposed-SUPERSCRIPT_TEXT-1-div": true,
- "QE-Proposed-FORMATBLOCK_TEXT-1-dM": true,
- "QE-Proposed-FORMATBLOCK_TEXT-1-body": true,
- "QE-Proposed-FORMATBLOCK_TEXT-1-div": true,
- "QE-Proposed-CREATELINK_TEXT-1-dM": true,
- "QE-Proposed-CREATELINK_TEXT-1-body": true,
- "QE-Proposed-CREATELINK_TEXT-1-div": true,
- "QE-Proposed-UNLINK_TEXT-1-dM": true,
- "QE-Proposed-UNLINK_TEXT-1-body": true,
- "QE-Proposed-UNLINK_TEXT-1-div": true,
- "QE-Proposed-INSERTHTML_TEXT-1-dM": true,
- "QE-Proposed-INSERTHTML_TEXT-1-body": true,
- "QE-Proposed-INSERTHTML_TEXT-1-div": true,
- "QE-Proposed-INSERTHORIZONTALRULE_TEXT-1-dM": true,
- "QE-Proposed-INSERTHORIZONTALRULE_TEXT-1-body": true,
- "QE-Proposed-INSERTHORIZONTALRULE_TEXT-1-div": true,
- "QE-Proposed-INSERTIMAGE_TEXT-1-dM": true,
- "QE-Proposed-INSERTIMAGE_TEXT-1-body": true,
- "QE-Proposed-INSERTIMAGE_TEXT-1-div": true,
- "QE-Proposed-INSERTLINEBREAK_TEXT-1-dM": true,
- "QE-Proposed-INSERTLINEBREAK_TEXT-1-body": true,
- "QE-Proposed-INSERTLINEBREAK_TEXT-1-div": true,
- "QE-Proposed-INSERTPARAGRAPH_TEXT-1-dM": true,
- "QE-Proposed-INSERTPARAGRAPH_TEXT-1-body": true,
- "QE-Proposed-INSERTPARAGRAPH_TEXT-1-div": true,
- "QE-Proposed-INSERTORDEREDLIST_TEXT-1-dM": true,
- "QE-Proposed-INSERTORDEREDLIST_TEXT-1-body": true,
- "QE-Proposed-INSERTORDEREDLIST_TEXT-1-div": true,
- "QE-Proposed-INSERTUNORDEREDLIST_TEXT-1-dM": true,
- "QE-Proposed-INSERTUNORDEREDLIST_TEXT-1-body": true,
- "QE-Proposed-INSERTUNORDEREDLIST_TEXT-1-div": true,
- "QE-Proposed-INSERTTEXT_TEXT-1-dM": true,
- "QE-Proposed-INSERTTEXT_TEXT-1-body": true,
- "QE-Proposed-INSERTTEXT_TEXT-1-div": true,
- "QE-Proposed-DELETE_TEXT-1-dM": true,
- "QE-Proposed-DELETE_TEXT-1-body": true,
- "QE-Proposed-DELETE_TEXT-1-div": true,
- "QE-Proposed-FORWARDDELETE_TEXT-1-dM": true,
- "QE-Proposed-FORWARDDELETE_TEXT-1-body": true,
- "QE-Proposed-FORWARDDELETE_TEXT-1-div": true,
- "QE-Proposed-STYLEWITHCSS_TEXT-1-dM": true,
- "QE-Proposed-STYLEWITHCSS_TEXT-1-body": true,
- "QE-Proposed-STYLEWITHCSS_TEXT-1-div": true,
- "QE-Proposed-CONTENTREADONLY_TEXT-1-dM": true,
- "QE-Proposed-CONTENTREADONLY_TEXT-1-body": true,
- "QE-Proposed-CONTENTREADONLY_TEXT-1-div": true,
- "QE-Proposed-BACKCOLOR_TEXT-1-dM": true,
- "QE-Proposed-BACKCOLOR_TEXT-1-body": true,
- "QE-Proposed-BACKCOLOR_TEXT-1-div": true,
- "QE-Proposed-FORECOLOR_TEXT-1-dM": true,
- "QE-Proposed-FORECOLOR_TEXT-1-body": true,
- "QE-Proposed-FORECOLOR_TEXT-1-div": true,
- "QE-Proposed-HILITECOLOR_TEXT-1-dM": true,
- "QE-Proposed-HILITECOLOR_TEXT-1-body": true,
- "QE-Proposed-HILITECOLOR_TEXT-1-div": true,
- "QE-Proposed-FONTNAME_TEXT-1-dM": true,
- "QE-Proposed-FONTNAME_TEXT-1-body": true,
- "QE-Proposed-FONTNAME_TEXT-1-div": true,
- "QE-Proposed-FONTSIZE_TEXT-1-dM": true,
- "QE-Proposed-FONTSIZE_TEXT-1-body": true,
- "QE-Proposed-FONTSIZE_TEXT-1-div": true,
- "QE-Proposed-INCREASEFONTSIZE_TEXT-1-dM": true,
- "QE-Proposed-INCREASEFONTSIZE_TEXT-1-body": true,
- "QE-Proposed-INCREASEFONTSIZE_TEXT-1-div": true,
- "QE-Proposed-DECREASEFONTSIZE_TEXT-1-dM": true,
- "QE-Proposed-DECREASEFONTSIZE_TEXT-1-body": true,
- "QE-Proposed-DECREASEFONTSIZE_TEXT-1-div": true,
- "QE-Proposed-HEADING_TEXT-1-dM": true,
- "QE-Proposed-HEADING_TEXT-1-body": true,
- "QE-Proposed-HEADING_TEXT-1-div": true,
- "QE-Proposed-INDENT_TEXT-1-dM": true,
- "QE-Proposed-INDENT_TEXT-1-body": true,
- "QE-Proposed-INDENT_TEXT-1-div": true,
- "QE-Proposed-OUTDENT_TEXT-1-dM": true,
- "QE-Proposed-OUTDENT_TEXT-1-body": true,
- "QE-Proposed-OUTDENT_TEXT-1-div": true,
- "QE-Proposed-CREATEBOOKMARK_TEXT-1-dM": true,
- "QE-Proposed-CREATEBOOKMARK_TEXT-1-body": true,
- "QE-Proposed-CREATEBOOKMARK_TEXT-1-div": true,
- "QE-Proposed-UNBOOKMARK_TEXT-1-dM": true,
- "QE-Proposed-UNBOOKMARK_TEXT-1-body": true,
- "QE-Proposed-UNBOOKMARK_TEXT-1-div": true,
- "QE-Proposed-JUSTIFYCENTER_TEXT-1-dM": true,
- "QE-Proposed-JUSTIFYCENTER_TEXT-1-body": true,
- "QE-Proposed-JUSTIFYCENTER_TEXT-1-div": true,
- "QE-Proposed-JUSTIFYFULL_TEXT-1-dM": true,
- "QE-Proposed-JUSTIFYFULL_TEXT-1-body": true,
- "QE-Proposed-JUSTIFYFULL_TEXT-1-div": true,
- "QE-Proposed-JUSTIFYLEFT_TEXT-1-dM": true,
- "QE-Proposed-JUSTIFYLEFT_TEXT-1-body": true,
- "QE-Proposed-JUSTIFYLEFT_TEXT-1-div": true,
- "QE-Proposed-JUSTIFYRIGHT_TEXT-1-dM": true,
- "QE-Proposed-JUSTIFYRIGHT_TEXT-1-body": true,
- "QE-Proposed-JUSTIFYRIGHT_TEXT-1-div": true,
- "QE-Proposed-REMOVEFORMAT_TEXT-1-dM": true,
- "QE-Proposed-REMOVEFORMAT_TEXT-1-body": true,
- "QE-Proposed-REMOVEFORMAT_TEXT-1-div": true,
- "QE-Proposed-COPY_TEXT-1-dM": true,
- "QE-Proposed-COPY_TEXT-1-body": true,
- "QE-Proposed-COPY_TEXT-1-div": true,
- "QE-Proposed-CUT_TEXT-1-dM": true,
- "QE-Proposed-CUT_TEXT-1-body": true,
- "QE-Proposed-CUT_TEXT-1-div": true,
- "QE-Proposed-PASTE_TEXT-1-dM": true,
- "QE-Proposed-PASTE_TEXT-1-body": true,
- "QE-Proposed-PASTE_TEXT-1-div": true,
- "QE-Proposed-garbage-1_TEXT-1-dM": true,
- "QE-Proposed-garbage-1_TEXT-1-body": true,
- "QE-Proposed-garbage-1_TEXT-1-div": true,
- "QI-Proposed-SELECTALL_TEXT-1-dM": true,
- "QI-Proposed-SELECTALL_TEXT-1-body": true,
- "QI-Proposed-SELECTALL_TEXT-1-div": true,
- "QI-Proposed-UNSELECT_TEXT-1-dM": true,
- "QI-Proposed-UNSELECT_TEXT-1-body": true,
- "QI-Proposed-UNSELECT_TEXT-1-div": true,
- "QI-Proposed-UNDO_TEXT-1-dM": true,
- "QI-Proposed-UNDO_TEXT-1-body": true,
- "QI-Proposed-UNDO_TEXT-1-div": true,
- "QI-Proposed-REDO_TEXT-1-dM": true,
- "QI-Proposed-REDO_TEXT-1-body": true,
- "QI-Proposed-REDO_TEXT-1-div": true,
- "QI-Proposed-BOLD_TEXT-1-dM": true,
- "QI-Proposed-BOLD_TEXT-1-body": true,
- "QI-Proposed-BOLD_TEXT-1-div": true,
- "QI-Proposed-ITALIC_TEXT-1-dM": true,
- "QI-Proposed-ITALIC_TEXT-1-body": true,
- "QI-Proposed-ITALIC_TEXT-1-div": true,
- "QI-Proposed-UNDERLINE_TEXT-1-dM": true,
- "QI-Proposed-UNDERLINE_TEXT-1-body": true,
- "QI-Proposed-UNDERLINE_TEXT-1-div": true,
- "QI-Proposed-STRIKETHROUGH_TEXT-1-dM": true,
- "QI-Proposed-STRIKETHROUGH_TEXT-1-body": true,
- "QI-Proposed-STRIKETHROUGH_TEXT-1-div": true,
- "QI-Proposed-SUBSCRIPT_TEXT-1-dM": true,
- "QI-Proposed-SUBSCRIPT_TEXT-1-body": true,
- "QI-Proposed-SUBSCRIPT_TEXT-1-div": true,
- "QI-Proposed-SUPERSCRIPT_TEXT-1-dM": true,
- "QI-Proposed-SUPERSCRIPT_TEXT-1-body": true,
- "QI-Proposed-SUPERSCRIPT_TEXT-1-div": true,
- "QI-Proposed-FORMATBLOCK_TEXT-1-dM": true,
- "QI-Proposed-FORMATBLOCK_TEXT-1-body": true,
- "QI-Proposed-FORMATBLOCK_TEXT-1-div": true,
- "QI-Proposed-CREATELINK_TEXT-1-dM": true,
- "QI-Proposed-CREATELINK_TEXT-1-body": true,
- "QI-Proposed-CREATELINK_TEXT-1-div": true,
- "QI-Proposed-UNLINK_TEXT-1-dM": true,
- "QI-Proposed-UNLINK_TEXT-1-body": true,
- "QI-Proposed-UNLINK_TEXT-1-div": true,
- "QI-Proposed-INSERTHTML_TEXT-1-dM": true,
- "QI-Proposed-INSERTHTML_TEXT-1-body": true,
- "QI-Proposed-INSERTHTML_TEXT-1-div": true,
- "QI-Proposed-INSERTHORIZONTALRULE_TEXT-1-dM": true,
- "QI-Proposed-INSERTHORIZONTALRULE_TEXT-1-body": true,
- "QI-Proposed-INSERTHORIZONTALRULE_TEXT-1-div": true,
- "QI-Proposed-INSERTIMAGE_TEXT-1-dM": true,
- "QI-Proposed-INSERTIMAGE_TEXT-1-body": true,
- "QI-Proposed-INSERTIMAGE_TEXT-1-div": true,
- "QI-Proposed-INSERTLINEBREAK_TEXT-1-dM": true,
- "QI-Proposed-INSERTLINEBREAK_TEXT-1-body": true,
- "QI-Proposed-INSERTLINEBREAK_TEXT-1-div": true,
- "QI-Proposed-INSERTPARAGRAPH_TEXT-1-dM": true,
- "QI-Proposed-INSERTPARAGRAPH_TEXT-1-body": true,
- "QI-Proposed-INSERTPARAGRAPH_TEXT-1-div": true,
- "QI-Proposed-INSERTORDEREDLIST_TEXT-1-dM": true,
- "QI-Proposed-INSERTORDEREDLIST_TEXT-1-body": true,
- "QI-Proposed-INSERTORDEREDLIST_TEXT-1-div": true,
- "QI-Proposed-INSERTUNORDEREDLIST_TEXT-1-dM": true,
- "QI-Proposed-INSERTUNORDEREDLIST_TEXT-1-body": true,
- "QI-Proposed-INSERTUNORDEREDLIST_TEXT-1-div": true,
- "QI-Proposed-INSERTTEXT_TEXT-1-dM": true,
- "QI-Proposed-INSERTTEXT_TEXT-1-body": true,
- "QI-Proposed-INSERTTEXT_TEXT-1-div": true,
- "QI-Proposed-DELETE_TEXT-1-dM": true,
- "QI-Proposed-DELETE_TEXT-1-body": true,
- "QI-Proposed-DELETE_TEXT-1-div": true,
- "QI-Proposed-FORWARDDELETE_TEXT-1-dM": true,
- "QI-Proposed-FORWARDDELETE_TEXT-1-body": true,
- "QI-Proposed-FORWARDDELETE_TEXT-1-div": true,
- "QI-Proposed-STYLEWITHCSS_TEXT-1-dM": true,
- "QI-Proposed-STYLEWITHCSS_TEXT-1-body": true,
- "QI-Proposed-STYLEWITHCSS_TEXT-1-div": true,
- "QI-Proposed-CONTENTREADONLY_TEXT-1-dM": true,
- "QI-Proposed-CONTENTREADONLY_TEXT-1-body": true,
- "QI-Proposed-CONTENTREADONLY_TEXT-1-div": true,
- "QI-Proposed-BACKCOLOR_TEXT-1-dM": true,
- "QI-Proposed-BACKCOLOR_TEXT-1-body": true,
- "QI-Proposed-BACKCOLOR_TEXT-1-div": true,
- "QI-Proposed-FORECOLOR_TEXT-1-dM": true,
- "QI-Proposed-FORECOLOR_TEXT-1-body": true,
- "QI-Proposed-FORECOLOR_TEXT-1-div": true,
- "QI-Proposed-HILITECOLOR_TEXT-1-dM": true,
- "QI-Proposed-HILITECOLOR_TEXT-1-body": true,
- "QI-Proposed-HILITECOLOR_TEXT-1-div": true,
- "QI-Proposed-FONTNAME_TEXT-1-dM": true,
- "QI-Proposed-FONTNAME_TEXT-1-body": true,
- "QI-Proposed-FONTNAME_TEXT-1-div": true,
- "QI-Proposed-FONTSIZE_TEXT-1-dM": true,
- "QI-Proposed-FONTSIZE_TEXT-1-body": true,
- "QI-Proposed-FONTSIZE_TEXT-1-div": true,
- "QI-Proposed-INCREASEFONTSIZE_TEXT-1-dM": true,
- "QI-Proposed-INCREASEFONTSIZE_TEXT-1-body": true,
- "QI-Proposed-INCREASEFONTSIZE_TEXT-1-div": true,
- "QI-Proposed-DECREASEFONTSIZE_TEXT-1-dM": true,
- "QI-Proposed-DECREASEFONTSIZE_TEXT-1-body": true,
- "QI-Proposed-DECREASEFONTSIZE_TEXT-1-div": true,
- "QI-Proposed-HEADING_TEXT-1-dM": true,
- "QI-Proposed-HEADING_TEXT-1-body": true,
- "QI-Proposed-HEADING_TEXT-1-div": true,
- "QI-Proposed-INDENT_TEXT-1-dM": true,
- "QI-Proposed-INDENT_TEXT-1-body": true,
- "QI-Proposed-INDENT_TEXT-1-div": true,
- "QI-Proposed-OUTDENT_TEXT-1-dM": true,
- "QI-Proposed-OUTDENT_TEXT-1-body": true,
- "QI-Proposed-OUTDENT_TEXT-1-div": true,
- "QI-Proposed-CREATEBOOKMARK_TEXT-1-dM": true,
- "QI-Proposed-CREATEBOOKMARK_TEXT-1-body": true,
- "QI-Proposed-CREATEBOOKMARK_TEXT-1-div": true,
- "QI-Proposed-UNBOOKMARK_TEXT-1-dM": true,
- "QI-Proposed-UNBOOKMARK_TEXT-1-body": true,
- "QI-Proposed-UNBOOKMARK_TEXT-1-div": true,
- "QI-Proposed-JUSTIFYCENTER_TEXT-1-dM": true,
- "QI-Proposed-JUSTIFYCENTER_TEXT-1-body": true,
- "QI-Proposed-JUSTIFYCENTER_TEXT-1-div": true,
- "QI-Proposed-JUSTIFYFULL_TEXT-1-dM": true,
- "QI-Proposed-JUSTIFYFULL_TEXT-1-body": true,
- "QI-Proposed-JUSTIFYFULL_TEXT-1-div": true,
- "QI-Proposed-JUSTIFYLEFT_TEXT-1-dM": true,
- "QI-Proposed-JUSTIFYLEFT_TEXT-1-body": true,
- "QI-Proposed-JUSTIFYLEFT_TEXT-1-div": true,
- "QI-Proposed-JUSTIFYRIGHT_TEXT-1-dM": true,
- "QI-Proposed-JUSTIFYRIGHT_TEXT-1-body": true,
- "QI-Proposed-JUSTIFYRIGHT_TEXT-1-div": true,
- "QI-Proposed-REMOVEFORMAT_TEXT-1-dM": true,
- "QI-Proposed-REMOVEFORMAT_TEXT-1-body": true,
- "QI-Proposed-REMOVEFORMAT_TEXT-1-div": true,
- "QI-Proposed-COPY_TEXT-1-dM": true,
- "QI-Proposed-COPY_TEXT-1-body": true,
- "QI-Proposed-COPY_TEXT-1-div": true,
- "QI-Proposed-CUT_TEXT-1-dM": true,
- "QI-Proposed-CUT_TEXT-1-body": true,
- "QI-Proposed-CUT_TEXT-1-div": true,
- "QI-Proposed-PASTE_TEXT-1-dM": true,
- "QI-Proposed-PASTE_TEXT-1-body": true,
- "QI-Proposed-PASTE_TEXT-1-div": true,
- "QI-Proposed-garbage-1_TEXT-1-dM": true,
- "QI-Proposed-garbage-1_TEXT-1-body": true,
- "QI-Proposed-garbage-1_TEXT-1-div": true,
- "QS-Proposed-B_TEXT_SI-dM": true,
- "QS-Proposed-B_TEXT_SI-body": true,
- "QS-Proposed-B_TEXT_SI-div": true,
- "QS-Proposed-B_B-1_SI-dM": true,
- "QS-Proposed-B_B-1_SI-body": true,
- "QS-Proposed-B_B-1_SI-div": true,
- "QS-Proposed-B_STRONG-1_SI-dM": true,
- "QS-Proposed-B_STRONG-1_SI-body": true,
- "QS-Proposed-B_STRONG-1_SI-div": true,
- "QS-Proposed-B_SPANs:fw:b-1_SI-dM": true,
- "QS-Proposed-B_SPANs:fw:b-1_SI-body": true,
- "QS-Proposed-B_SPANs:fw:b-1_SI-div": true,
- "QS-Proposed-B_SPANs:fw:n-1_SI-dM": true,
- "QS-Proposed-B_SPANs:fw:n-1_SI-body": true,
- "QS-Proposed-B_SPANs:fw:n-1_SI-div": true,
- "QS-Proposed-B_Bs:fw:n-1_SI-dM": true,
- "QS-Proposed-B_Bs:fw:n-1_SI-body": true,
- "QS-Proposed-B_Bs:fw:n-1_SI-div": true,
- "QS-Proposed-B_B-SPANs:fw:n-1_SI-dM": true,
- "QS-Proposed-B_B-SPANs:fw:n-1_SI-body": true,
- "QS-Proposed-B_B-SPANs:fw:n-1_SI-div": true,
- "QS-Proposed-B_SPAN.b-1-SI-dM": true,
- "QS-Proposed-B_SPAN.b-1-SI-body": true,
- "QS-Proposed-B_SPAN.b-1-SI-div": true,
- "QS-Proposed-B_MYB-1-SI-dM": true,
- "QS-Proposed-B_MYB-1-SI-body": true,
- "QS-Proposed-B_MYB-1-SI-div": true,
- "QS-Proposed-B_B-I-1_SC-dM": true,
- "QS-Proposed-B_B-I-1_SC-body": true,
- "QS-Proposed-B_B-I-1_SC-div": true,
- "QS-Proposed-B_B-I-1_SL-dM": true,
- "QS-Proposed-B_B-I-1_SL-body": true,
- "QS-Proposed-B_B-I-1_SL-div": true,
- "QS-Proposed-B_B-I-1_SR-dM": true,
- "QS-Proposed-B_B-I-1_SR-body": true,
- "QS-Proposed-B_B-I-1_SR-div": true,
- "QS-Proposed-B_STRONG-I-1_SC-dM": true,
- "QS-Proposed-B_STRONG-I-1_SC-body": true,
- "QS-Proposed-B_STRONG-I-1_SC-div": true,
- "QS-Proposed-B_B-I-U-1_SC-dM": true,
- "QS-Proposed-B_B-I-U-1_SC-body": true,
- "QS-Proposed-B_B-I-U-1_SC-div": true,
- "QS-Proposed-B_B-I-U-1_SM-dM": true,
- "QS-Proposed-B_B-I-U-1_SM-body": true,
- "QS-Proposed-B_B-I-U-1_SM-div": true,
- "QS-Proposed-B_TEXT-B-1_SO-1-dM": true,
- "QS-Proposed-B_TEXT-B-1_SO-1-body": true,
- "QS-Proposed-B_TEXT-B-1_SO-1-div": true,
- "QS-Proposed-B_TEXT-B-1_SO-2-dM": true,
- "QS-Proposed-B_TEXT-B-1_SO-2-body": true,
- "QS-Proposed-B_TEXT-B-1_SO-2-div": true,
- "QS-Proposed-B_TEXT-B-1_SL-dM": true,
- "QS-Proposed-B_TEXT-B-1_SL-body": true,
- "QS-Proposed-B_TEXT-B-1_SL-div": true,
- "QS-Proposed-B_TEXT-B-1_SR-dM": true,
- "QS-Proposed-B_TEXT-B-1_SR-body": true,
- "QS-Proposed-B_TEXT-B-1_SR-div": true,
- "QS-Proposed-B_TEXT-B-1_SO-3-dM": true,
- "QS-Proposed-B_TEXT-B-1_SO-3-body": true,
- "QS-Proposed-B_TEXT-B-1_SO-3-div": true,
- "QS-Proposed-B_B.TEXT.B-1_SM-dM": true,
- "QS-Proposed-B_B.TEXT.B-1_SM-body": true,
- "QS-Proposed-B_B.TEXT.B-1_SM-div": true,
- "QS-Proposed-B_B.B.B-1_SM-dM": true,
- "QS-Proposed-B_B.B.B-1_SM-body": true,
- "QS-Proposed-B_B.B.B-1_SM-div": true,
- "QS-Proposed-B_B.STRONG.B-1_SM-dM": true,
- "QS-Proposed-B_B.STRONG.B-1_SM-body": true,
- "QS-Proposed-B_B.STRONG.B-1_SM-div": true,
- "QS-Proposed-B_SPAN.b.MYB.SPANs:fw:b-1_SM-dM": true,
- "QS-Proposed-B_SPAN.b.MYB.SPANs:fw:b-1_SM-body": true,
- "QS-Proposed-B_SPAN.b.MYB.SPANs:fw:b-1_SM-div": true,
- "QS-Proposed-I_TEXT_SI-dM": true,
- "QS-Proposed-I_TEXT_SI-body": true,
- "QS-Proposed-I_TEXT_SI-div": true,
- "QS-Proposed-I_I-1_SI-dM": true,
- "QS-Proposed-I_I-1_SI-body": true,
- "QS-Proposed-I_I-1_SI-div": true,
- "QS-Proposed-I_EM-1_SI-dM": true,
- "QS-Proposed-I_EM-1_SI-body": true,
- "QS-Proposed-I_EM-1_SI-div": true,
- "QS-Proposed-I_SPANs:fs:i-1_SI-dM": true,
- "QS-Proposed-I_SPANs:fs:i-1_SI-body": true,
- "QS-Proposed-I_SPANs:fs:i-1_SI-div": true,
- "QS-Proposed-I_SPANs:fs:n-1_SI-dM": true,
- "QS-Proposed-I_SPANs:fs:n-1_SI-body": true,
- "QS-Proposed-I_SPANs:fs:n-1_SI-div": true,
- "QS-Proposed-I_I-SPANs:fs:n-1_SI-dM": true,
- "QS-Proposed-I_I-SPANs:fs:n-1_SI-body": true,
- "QS-Proposed-I_I-SPANs:fs:n-1_SI-div": true,
- "QS-Proposed-I_SPAN.i-1-SI-dM": true,
- "QS-Proposed-I_SPAN.i-1-SI-body": true,
- "QS-Proposed-I_SPAN.i-1-SI-div": true,
- "QS-Proposed-I_MYI-1-SI-dM": true,
- "QS-Proposed-I_MYI-1-SI-body": true,
- "QS-Proposed-I_MYI-1-SI-div": true,
- "QS-Proposed-U_TEXT_SI-dM": true,
- "QS-Proposed-U_TEXT_SI-body": true,
- "QS-Proposed-U_TEXT_SI-div": true,
- "QS-Proposed-U_U-1_SI-dM": true,
- "QS-Proposed-U_U-1_SI-body": true,
- "QS-Proposed-U_U-1_SI-div": true,
- "QS-Proposed-U_Us:td:n-1_SI-dM": true,
- "QS-Proposed-U_Us:td:n-1_SI-body": true,
- "QS-Proposed-U_Us:td:n-1_SI-div": true,
- "QS-Proposed-U_Ah:url-1_SI-dM": true,
- "QS-Proposed-U_Ah:url-1_SI-body": true,
- "QS-Proposed-U_Ah:url-1_SI-div": true,
- "QS-Proposed-U_Ah:url.s:td:n-1_SI-dM": true,
- "QS-Proposed-U_Ah:url.s:td:n-1_SI-body": true,
- "QS-Proposed-U_Ah:url.s:td:n-1_SI-div": true,
- "QS-Proposed-U_SPANs:td:u-1_SI-dM": true,
- "QS-Proposed-U_SPANs:td:u-1_SI-body": true,
- "QS-Proposed-U_SPANs:td:u-1_SI-div": true,
- "QS-Proposed-U_SPAN.u-1-SI-dM": true,
- "QS-Proposed-U_SPAN.u-1-SI-body": true,
- "QS-Proposed-U_SPAN.u-1-SI-div": true,
- "QS-Proposed-U_MYU-1-SI-dM": true,
- "QS-Proposed-U_MYU-1-SI-body": true,
- "QS-Proposed-U_MYU-1-SI-div": true,
- "QS-Proposed-S_TEXT_SI-dM": true,
- "QS-Proposed-S_TEXT_SI-body": true,
- "QS-Proposed-S_TEXT_SI-div": true,
- "QS-Proposed-S_S-1_SI-dM": true,
- "QS-Proposed-S_S-1_SI-body": true,
- "QS-Proposed-S_S-1_SI-div": true,
- "QS-Proposed-S_STRIKE-1_SI-dM": true,
- "QS-Proposed-S_STRIKE-1_SI-body": true,
- "QS-Proposed-S_STRIKE-1_SI-div": true,
- "QS-Proposed-S_STRIKEs:td:n-1_SI-dM": true,
- "QS-Proposed-S_STRIKEs:td:n-1_SI-body": true,
- "QS-Proposed-S_STRIKEs:td:n-1_SI-div": true,
- "QS-Proposed-S_DEL-1_SI-dM": true,
- "QS-Proposed-S_DEL-1_SI-body": true,
- "QS-Proposed-S_DEL-1_SI-div": true,
- "QS-Proposed-S_SPANs:td:lt-1_SI-dM": true,
- "QS-Proposed-S_SPANs:td:lt-1_SI-body": true,
- "QS-Proposed-S_SPANs:td:lt-1_SI-div": true,
- "QS-Proposed-S_SPAN.s-1-SI-dM": true,
- "QS-Proposed-S_SPAN.s-1-SI-body": true,
- "QS-Proposed-S_SPAN.s-1-SI-div": true,
- "QS-Proposed-S_MYS-1-SI-dM": true,
- "QS-Proposed-S_MYS-1-SI-body": true,
- "QS-Proposed-S_MYS-1-SI-div": true,
- "QS-Proposed-S_S.STRIKE.DEL-1_SM-dM": true,
- "QS-Proposed-S_S.STRIKE.DEL-1_SM-body": true,
- "QS-Proposed-S_S.STRIKE.DEL-1_SM-div": true,
- "QS-Proposed-SUB_TEXT_SI-dM": true,
- "QS-Proposed-SUB_TEXT_SI-body": true,
- "QS-Proposed-SUB_TEXT_SI-div": true,
- "QS-Proposed-SUB_SUB-1_SI-dM": true,
- "QS-Proposed-SUB_SUB-1_SI-body": true,
- "QS-Proposed-SUB_SUB-1_SI-div": true,
- "QS-Proposed-SUB_SPAN.sub-1-SI-dM": true,
- "QS-Proposed-SUB_SPAN.sub-1-SI-body": true,
- "QS-Proposed-SUB_SPAN.sub-1-SI-div": true,
- "QS-Proposed-SUB_MYSUB-1-SI-dM": true,
- "QS-Proposed-SUB_MYSUB-1-SI-body": true,
- "QS-Proposed-SUB_MYSUB-1-SI-div": true,
- "QS-Proposed-SUP_TEXT_SI-dM": true,
- "QS-Proposed-SUP_TEXT_SI-body": true,
- "QS-Proposed-SUP_TEXT_SI-div": true,
- "QS-Proposed-SUP_SUP-1_SI-dM": true,
- "QS-Proposed-SUP_SUP-1_SI-body": true,
- "QS-Proposed-SUP_SUP-1_SI-div": true,
- "QS-Proposed-IOL_TEXT_SI-dM": true,
- "QS-Proposed-IOL_TEXT_SI-body": true,
- "QS-Proposed-IOL_TEXT_SI-div": true,
- "QS-Proposed-SUP_SPAN.sup-1-SI-dM": true,
- "QS-Proposed-SUP_SPAN.sup-1-SI-body": true,
- "QS-Proposed-SUP_SPAN.sup-1-SI-div": true,
- "QS-Proposed-SUP_MYSUP-1-SI-dM": true,
- "QS-Proposed-SUP_MYSUP-1-SI-body": true,
- "QS-Proposed-SUP_MYSUP-1-SI-div": true,
- "QS-Proposed-IOL_TEXT-1_SI-dM": true,
- "QS-Proposed-IOL_TEXT-1_SI-body": true,
- "QS-Proposed-IOL_TEXT-1_SI-div": true,
- "QS-Proposed-IOL_OL-LI-1_SI-dM": true,
- "QS-Proposed-IOL_OL-LI-1_SI-body": true,
- "QS-Proposed-IOL_OL-LI-1_SI-div": true,
- "QS-Proposed-IOL_UL_LI-1_SI-dM": true,
- "QS-Proposed-IOL_UL_LI-1_SI-body": true,
- "QS-Proposed-IOL_UL_LI-1_SI-div": true,
- "QS-Proposed-IUL_TEXT_SI-dM": true,
- "QS-Proposed-IUL_TEXT_SI-body": true,
- "QS-Proposed-IUL_TEXT_SI-div": true,
- "QS-Proposed-IUL_OL-LI-1_SI-dM": true,
- "QS-Proposed-IUL_OL-LI-1_SI-body": true,
- "QS-Proposed-IUL_OL-LI-1_SI-div": true,
- "QS-Proposed-IUL_UL-LI-1_SI-dM": true,
- "QS-Proposed-IUL_UL-LI-1_SI-body": true,
- "QS-Proposed-IUL_UL-LI-1_SI-div": true,
- "QS-Proposed-JC_TEXT_SI-dM": true,
- "QS-Proposed-JC_TEXT_SI-body": true,
- "QS-Proposed-JC_TEXT_SI-div": true,
- "QS-Proposed-JC_DIVa:c-1_SI-dM": true,
- "QS-Proposed-JC_DIVa:c-1_SI-body": true,
- "QS-Proposed-JC_DIVa:c-1_SI-div": true,
- "QS-Proposed-JC_Pa:c-1_SI-dM": true,
- "QS-Proposed-JC_Pa:c-1_SI-body": true,
- "QS-Proposed-JC_Pa:c-1_SI-div": true,
- "QS-Proposed-JC_SPANs:ta:c-1_SI-dM": true,
- "QS-Proposed-JC_SPANs:ta:c-1_SI-body": true,
- "QS-Proposed-JC_SPANs:ta:c-1_SI-div": true,
- "QS-Proposed-JC_SPAN.jc-1-SI-dM": true,
- "QS-Proposed-JC_SPAN.jc-1-SI-body": true,
- "QS-Proposed-JC_SPAN.jc-1-SI-div": true,
- "QS-Proposed-JC_MYJC-1-SI-dM": true,
- "QS-Proposed-JC_MYJC-1-SI-body": true,
- "QS-Proposed-JC_MYJC-1-SI-div": true,
- "QS-Proposed-JF_TEXT_SI-dM": true,
- "QS-Proposed-JF_TEXT_SI-body": true,
- "QS-Proposed-JF_TEXT_SI-div": true,
- "QS-Proposed-JF_DIVa:j-1_SI-dM": true,
- "QS-Proposed-JF_DIVa:j-1_SI-body": true,
- "QS-Proposed-JF_DIVa:j-1_SI-div": true,
- "QS-Proposed-JF_Pa:j-1_SI-dM": true,
- "QS-Proposed-JF_Pa:j-1_SI-body": true,
- "QS-Proposed-JF_Pa:j-1_SI-div": true,
- "QS-Proposed-JF_SPANs:ta:j-1_SI-dM": true,
- "QS-Proposed-JF_SPANs:ta:j-1_SI-body": true,
- "QS-Proposed-JF_SPANs:ta:j-1_SI-div": true,
- "QS-Proposed-JF_SPAN.jf-1-SI-dM": true,
- "QS-Proposed-JF_SPAN.jf-1-SI-body": true,
- "QS-Proposed-JF_SPAN.jf-1-SI-div": true,
- "QS-Proposed-JF_MYJF-1-SI-dM": true,
- "QS-Proposed-JF_MYJF-1-SI-body": true,
- "QS-Proposed-JF_MYJF-1-SI-div": true,
- "QS-Proposed-JL_TEXT_SI-dM": true,
- "QS-Proposed-JL_TEXT_SI-body": true,
- "QS-Proposed-JL_TEXT_SI-div": true,
- "QS-Proposed-JL_DIVa:l-1_SI-dM": true,
- "QS-Proposed-JL_DIVa:l-1_SI-body": true,
- "QS-Proposed-JL_DIVa:l-1_SI-div": true,
- "QS-Proposed-JL_Pa:l-1_SI-dM": true,
- "QS-Proposed-JL_Pa:l-1_SI-body": true,
- "QS-Proposed-JL_Pa:l-1_SI-div": true,
- "QS-Proposed-JL_SPANs:ta:l-1_SI-dM": true,
- "QS-Proposed-JL_SPANs:ta:l-1_SI-body": true,
- "QS-Proposed-JL_SPANs:ta:l-1_SI-div": true,
- "QS-Proposed-JL_SPAN.jl-1-SI-dM": true,
- "QS-Proposed-JL_SPAN.jl-1-SI-body": true,
- "QS-Proposed-JL_SPAN.jl-1-SI-div": true,
- "QS-Proposed-JL_MYJL-1-SI-dM": true,
- "QS-Proposed-JL_MYJL-1-SI-body": true,
- "QS-Proposed-JL_MYJL-1-SI-div": true,
- "QS-Proposed-JR_TEXT_SI-dM": true,
- "QS-Proposed-JR_TEXT_SI-body": true,
- "QS-Proposed-JR_TEXT_SI-div": true,
- "QS-Proposed-JR_DIVa:r-1_SI-dM": true,
- "QS-Proposed-JR_DIVa:r-1_SI-body": true,
- "QS-Proposed-JR_DIVa:r-1_SI-div": true,
- "QS-Proposed-JR_Pa:r-1_SI-dM": true,
- "QS-Proposed-JR_Pa:r-1_SI-body": true,
- "QS-Proposed-JR_Pa:r-1_SI-div": true,
- "QS-Proposed-JR_SPANs:ta:r-1_SI-dM": true,
- "QS-Proposed-JR_SPANs:ta:r-1_SI-body": true,
- "QS-Proposed-JR_SPANs:ta:r-1_SI-div": true,
- "QS-Proposed-JR_SPAN.jr-1-SI-dM": true,
- "QS-Proposed-JR_SPAN.jr-1-SI-body": true,
- "QS-Proposed-JR_SPAN.jr-1-SI-div": true,
- "QS-Proposed-JR_MYJR-1-SI-dM": true,
- "QS-Proposed-JR_MYJR-1-SI-body": true,
- "QS-Proposed-JR_MYJR-1-SI-div": true,
- "QV-Proposed-B_TEXT_SI-dM": true,
- "QV-Proposed-B_TEXT_SI-body": true,
- "QV-Proposed-B_TEXT_SI-div": true,
- "QV-Proposed-B_B-1_SI-dM": true,
- "QV-Proposed-B_B-1_SI-body": true,
- "QV-Proposed-B_B-1_SI-div": true,
- "QV-Proposed-B_STRONG-1_SI-dM": true,
- "QV-Proposed-B_STRONG-1_SI-body": true,
- "QV-Proposed-B_STRONG-1_SI-div": true,
- "QV-Proposed-B_SPANs:fw:b-1_SI-dM": true,
- "QV-Proposed-B_SPANs:fw:b-1_SI-body": true,
- "QV-Proposed-B_SPANs:fw:b-1_SI-div": true,
- "QV-Proposed-B_SPANs:fw:n-1_SI-dM": true,
- "QV-Proposed-B_SPANs:fw:n-1_SI-body": true,
- "QV-Proposed-B_SPANs:fw:n-1_SI-div": true,
- "QV-Proposed-B_Bs:fw:n-1_SI-dM": true,
- "QV-Proposed-B_Bs:fw:n-1_SI-body": true,
- "QV-Proposed-B_Bs:fw:n-1_SI-div": true,
- "QV-Proposed-B_SPAN.b-1_SI-dM": true,
- "QV-Proposed-B_SPAN.b-1_SI-body": true,
- "QV-Proposed-B_SPAN.b-1_SI-div": true,
- "QV-Proposed-B_MYB-1-SI-dM": true,
- "QV-Proposed-B_MYB-1-SI-body": true,
- "QV-Proposed-B_MYB-1-SI-div": true,
- "QV-Proposed-I_TEXT_SI-dM": true,
- "QV-Proposed-I_TEXT_SI-body": true,
- "QV-Proposed-I_TEXT_SI-div": true,
- "QV-Proposed-I_I-1_SI-dM": true,
- "QV-Proposed-I_I-1_SI-body": true,
- "QV-Proposed-I_I-1_SI-div": true,
- "QV-Proposed-I_EM-1_SI-dM": true,
- "QV-Proposed-I_EM-1_SI-body": true,
- "QV-Proposed-I_EM-1_SI-div": true,
- "QV-Proposed-I_SPANs:fs:i-1_SI-dM": true,
- "QV-Proposed-I_SPANs:fs:i-1_SI-body": true,
- "QV-Proposed-I_SPANs:fs:i-1_SI-div": true,
- "QV-Proposed-I_SPANs:fs:n-1_SI-dM": true,
- "QV-Proposed-I_SPANs:fs:n-1_SI-body": true,
- "QV-Proposed-I_SPANs:fs:n-1_SI-div": true,
- "QV-Proposed-I_I-SPANs:fs:n-1_SI-dM": true,
- "QV-Proposed-I_I-SPANs:fs:n-1_SI-body": true,
- "QV-Proposed-I_I-SPANs:fs:n-1_SI-div": true,
- "QV-Proposed-I_SPAN.i-1_SI-dM": true,
- "QV-Proposed-I_SPAN.i-1_SI-body": true,
- "QV-Proposed-I_SPAN.i-1_SI-div": true,
- "QV-Proposed-I_MYI-1-SI-dM": true,
- "QV-Proposed-I_MYI-1-SI-body": true,
- "QV-Proposed-I_MYI-1-SI-div": true,
- "QV-Proposed-FB_TEXT-1_SC-dM": true,
- "QV-Proposed-FB_TEXT-1_SC-body": true,
- "QV-Proposed-FB_TEXT-1_SC-div": true,
- "QV-Proposed-FB_H1-1_SC-dM": true,
- "QV-Proposed-FB_H1-1_SC-body": true,
- "QV-Proposed-FB_H1-1_SC-div": true,
- "QV-Proposed-FB_PRE-1_SC-dM": true,
- "QV-Proposed-FB_PRE-1_SC-body": true,
- "QV-Proposed-FB_PRE-1_SC-div": true,
- "QV-Proposed-FB_BQ-1_SC-dM": true,
- "QV-Proposed-FB_BQ-1_SC-body": true,
- "QV-Proposed-FB_BQ-1_SC-div": true,
- "QV-Proposed-FB_ADDRESS-1_SC-dM": true,
- "QV-Proposed-FB_ADDRESS-1_SC-body": true,
- "QV-Proposed-FB_ADDRESS-1_SC-div": true,
- "QV-Proposed-FB_H1-H2-1_SC-dM": true,
- "QV-Proposed-FB_H1-H2-1_SC-body": true,
- "QV-Proposed-FB_H1-H2-1_SC-div": true,
- "QV-Proposed-FB_H1-H2-1_SL-dM": true,
- "QV-Proposed-FB_H1-H2-1_SL-body": true,
- "QV-Proposed-FB_H1-H2-1_SL-div": true,
- "QV-Proposed-FB_H1-H2-1_SR-dM": true,
- "QV-Proposed-FB_H1-H2-1_SR-body": true,
- "QV-Proposed-FB_H1-H2-1_SR-div": true,
- "QV-Proposed-FB_TEXT-ADDRESS-1_SL-dM": true,
- "QV-Proposed-FB_TEXT-ADDRESS-1_SL-body": true,
- "QV-Proposed-FB_TEXT-ADDRESS-1_SL-div": true,
- "QV-Proposed-FB_TEXT-ADDRESS-1_SR-dM": true,
- "QV-Proposed-FB_TEXT-ADDRESS-1_SR-body": true,
- "QV-Proposed-FB_TEXT-ADDRESS-1_SR-div": true,
- "QV-Proposed-FB_H1-H2.TEXT.H2-1_SM-dM": true,
- "QV-Proposed-FB_H1-H2.TEXT.H2-1_SM-body": true,
- "QV-Proposed-FB_H1-H2.TEXT.H2-1_SM-div": true,
- "QV-Proposed-H_H1-1_SC-dM": true,
- "QV-Proposed-H_H1-1_SC-body": true,
- "QV-Proposed-H_H1-1_SC-div": true,
- "QV-Proposed-H_H3-1_SC-dM": true,
- "QV-Proposed-H_H3-1_SC-body": true,
- "QV-Proposed-H_H3-1_SC-div": true,
- "QV-Proposed-H_H1-H2-H3-H4-1_SC-dM": true,
- "QV-Proposed-H_H1-H2-H3-H4-1_SC-body": true,
- "QV-Proposed-H_H1-H2-H3-H4-1_SC-div": true,
- "QV-Proposed-H_P-1_SC-dM": true,
- "QV-Proposed-H_P-1_SC-body": true,
- "QV-Proposed-H_P-1_SC-div": true,
- "QV-Proposed-FN_FONTf:a-1_SI-dM": true,
- "QV-Proposed-FN_FONTf:a-1_SI-body": true,
- "QV-Proposed-FN_FONTf:a-1_SI-div": true,
- "QV-Proposed-FN_SPANs:ff:a-1_SI-dM": true,
- "QV-Proposed-FN_SPANs:ff:a-1_SI-body": true,
- "QV-Proposed-FN_SPANs:ff:a-1_SI-div": true,
- "QV-Proposed-FN_FONTf:a.s:ff:c-1_SI-dM": true,
- "QV-Proposed-FN_FONTf:a.s:ff:c-1_SI-body": true,
- "QV-Proposed-FN_FONTf:a.s:ff:c-1_SI-div": true,
- "QV-Proposed-FN_FONTf:a-FONTf:c-1_SI-dM": true,
- "QV-Proposed-FN_FONTf:a-FONTf:c-1_SI-body": true,
- "QV-Proposed-FN_FONTf:a-FONTf:c-1_SI-div": true,
- "QV-Proposed-FN_SPANs:ff:c-FONTf:a-1_SI-dM": true,
- "QV-Proposed-FN_SPANs:ff:c-FONTf:a-1_SI-body": true,
- "QV-Proposed-FN_SPANs:ff:c-FONTf:a-1_SI-div": true,
- "QV-Proposed-FN_SPAN.fs18px-1_SI-dM": true,
- "QV-Proposed-FN_SPAN.fs18px-1_SI-body": true,
- "QV-Proposed-FN_SPAN.fs18px-1_SI-div": true,
- "QV-Proposed-FN_MYCOURIER-1-SI-dM": true,
- "QV-Proposed-FN_MYCOURIER-1-SI-body": true,
- "QV-Proposed-FN_MYCOURIER-1-SI-div": true,
- "QV-Proposed-FS_FONTsz:4-1_SI-dM": true,
- "QV-Proposed-FS_FONTsz:4-1_SI-body": true,
- "QV-Proposed-FS_FONTsz:4-1_SI-div": true,
- "QV-Proposed-FS_FONTs:fs:l-1_SI-dM": true,
- "QV-Proposed-FS_FONTs:fs:l-1_SI-body": true,
- "QV-Proposed-FS_FONTs:fs:l-1_SI-div": true,
- "QV-Proposed-FS_FONT.ass.s:fs:l-1_SI-dM": true,
- "QV-Proposed-FS_FONT.ass.s:fs:l-1_SI-body": true,
- "QV-Proposed-FS_FONT.ass.s:fs:l-1_SI-div": true,
- "QV-Proposed-FS_FONTsz:1.s:fs:xl-1_SI-dM": true,
- "QV-Proposed-FS_FONTsz:1.s:fs:xl-1_SI-body": true,
- "QV-Proposed-FS_FONTsz:1.s:fs:xl-1_SI-div": true,
- "QV-Proposed-FS_SPAN.large-1_SI-dM": true,
- "QV-Proposed-FS_SPAN.large-1_SI-body": true,
- "QV-Proposed-FS_SPAN.large-1_SI-div": true,
- "QV-Proposed-FS_SPAN.fs18px-1_SI-dM": true,
- "QV-Proposed-FS_SPAN.fs18px-1_SI-body": true,
- "QV-Proposed-FS_SPAN.fs18px-1_SI-div": true,
- "QV-Proposed-FA_MYLARGE-1-SI-dM": true,
- "QV-Proposed-FA_MYLARGE-1-SI-body": true,
- "QV-Proposed-FA_MYLARGE-1-SI-div": true,
- "QV-Proposed-FA_MYFS18PX-1-SI-dM": true,
- "QV-Proposed-FA_MYFS18PX-1-SI-body": true,
- "QV-Proposed-FA_MYFS18PX-1-SI-div": true,
- "QV-Proposed-BC_FONTs:bc:fca-1_SI-dM": true,
- "QV-Proposed-BC_FONTs:bc:fca-1_SI-body": true,
- "QV-Proposed-BC_FONTs:bc:fca-1_SI-div": true,
- "QV-Proposed-BC_SPANs:bc:abc-1_SI-dM": true,
- "QV-Proposed-BC_SPANs:bc:abc-1_SI-body": true,
- "QV-Proposed-BC_SPANs:bc:abc-1_SI-div": true,
- "QV-Proposed-BC_FONTs:bc:084-SPAN-1_SI-dM": true,
- "QV-Proposed-BC_FONTs:bc:084-SPAN-1_SI-body": true,
- "QV-Proposed-BC_FONTs:bc:084-SPAN-1_SI-div": true,
- "QV-Proposed-BC_SPANs:bc:cde-SPAN-1_SI-dM": true,
- "QV-Proposed-BC_SPANs:bc:cde-SPAN-1_SI-body": true,
- "QV-Proposed-BC_SPANs:bc:cde-SPAN-1_SI-div": true,
- "QV-Proposed-BC_SPAN.ass.s:bc:rgb-1_SI-dM": true,
- "QV-Proposed-BC_SPAN.ass.s:bc:rgb-1_SI-body": true,
- "QV-Proposed-BC_SPAN.ass.s:bc:rgb-1_SI-div": true,
- "QV-Proposed-BC_SPAN.bcred-1_SI-dM": true,
- "QV-Proposed-BC_SPAN.bcred-1_SI-body": true,
- "QV-Proposed-BC_SPAN.bcred-1_SI-div": true,
- "QV-Proposed-BC_MYBCRED-1-SI-dM": true,
- "QV-Proposed-BC_MYBCRED-1-SI-body": true,
- "QV-Proposed-BC_MYBCRED-1-SI-div": true,
- "QV-Proposed-FC_FONTc:f00-1_SI-dM": true,
- "QV-Proposed-FC_FONTc:f00-1_SI-body": true,
- "QV-Proposed-FC_FONTc:f00-1_SI-div": true,
- "QV-Proposed-FC_SPANs:c:0f0-1_SI-dM": true,
- "QV-Proposed-FC_SPANs:c:0f0-1_SI-body": true,
- "QV-Proposed-FC_SPANs:c:0f0-1_SI-div": true,
- "QV-Proposed-FC_FONTc:333.s:c:999-1_SI-dM": true,
- "QV-Proposed-FC_FONTc:333.s:c:999-1_SI-body": true,
- "QV-Proposed-FC_FONTc:333.s:c:999-1_SI-div": true,
- "QV-Proposed-FC_FONTc:641-SPAN-1_SI-dM": true,
- "QV-Proposed-FC_FONTc:641-SPAN-1_SI-body": true,
- "QV-Proposed-FC_FONTc:641-SPAN-1_SI-div": true,
- "QV-Proposed-FC_SPANs:c:d95-SPAN-1_SI-dM": true,
- "QV-Proposed-FC_SPANs:c:d95-SPAN-1_SI-body": true,
- "QV-Proposed-FC_SPANs:c:d95-SPAN-1_SI-div": true,
- "QV-Proposed-FC_SPAN.red-1_SI-dM": true,
- "QV-Proposed-FC_SPAN.red-1_SI-body": true,
- "QV-Proposed-FC_SPAN.red-1_SI-div": true,
- "QV-Proposed-FC_MYRED-1-SI-dM": true,
- "QV-Proposed-FC_MYRED-1-SI-body": true,
- "QV-Proposed-FC_MYRED-1-SI-div": true,
- "QV-Proposed-HC_FONTs:bc:fc0-1_SI-dM": true,
- "QV-Proposed-HC_FONTs:bc:fc0-1_SI-body": true,
- "QV-Proposed-HC_FONTs:bc:fc0-1_SI-div": true,
- "QV-Proposed-HC_SPANs:bc:a0c-1_SI-dM": true,
- "QV-Proposed-HC_SPANs:bc:a0c-1_SI-body": true,
- "QV-Proposed-HC_SPANs:bc:a0c-1_SI-div": true,
- "QV-Proposed-HC_SPAN.ass.s:bc:rgb-1_SI-dM": true,
- "QV-Proposed-HC_SPAN.ass.s:bc:rgb-1_SI-body": true,
- "QV-Proposed-HC_SPAN.ass.s:bc:rgb-1_SI-div": true,
- "QV-Proposed-HC_FONTs:bc:83e-SPAN-1_SI-dM": true,
- "QV-Proposed-HC_FONTs:bc:83e-SPAN-1_SI-body": true,
- "QV-Proposed-HC_FONTs:bc:83e-SPAN-1_SI-div": true,
- "QV-Proposed-HC_SPANs:bc:b12-SPAN-1_SI-dM": true,
- "QV-Proposed-HC_SPANs:bc:b12-SPAN-1_SI-body": true,
- "QV-Proposed-HC_SPANs:bc:b12-SPAN-1_SI-div": true,
- "QV-Proposed-HC_SPAN.bcred-1_SI-dM": true,
- "QV-Proposed-HC_SPAN.bcred-1_SI-body": true,
- "QV-Proposed-HC_SPAN.bcred-1_SI-div": true,
- "QV-Proposed-HC_MYBCRED-1-SI-dM": true,
- "QV-Proposed-HC_MYBCRED-1-SI-body": true,
- "QV-Proposed-HC_MYBCRED-1-SI-div": true
- }
-}
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/current_revision b/editor/libeditor/tests/browserscope/lib/richtext2/current_revision
deleted file mode 100644
index cc34bb397..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/current_revision
+++ /dev/null
@@ -1 +0,0 @@
-805
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/__init__.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/__init__.py
+++ /dev/null
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/common.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/common.py
deleted file mode 100644
index 345f9bbb0..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/common.py
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/python2.5
-#
-# Copyright 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the 'License')
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an 'AS IS' BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Common constants"""
-
-__author__ = 'rolandsteiner@google.com (Roland Steiner)'
-
-CATEGORY = 'richtext2'
-
-TEST_ID_PREFIX = 'RTE2'
-
-CLASSES = ['Finalized', 'RFC', 'Proposed'] \ No newline at end of file
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/handlers.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/handlers.py
deleted file mode 100644
index 2ee1e79ad..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/handlers.py
+++ /dev/null
@@ -1,107 +0,0 @@
-#!/usr/bin/python2.5
-#
-# Copyright 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the 'License')
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an 'AS IS' BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Handlers for New Rich Text Tests"""
-
-__author__ = 'rolandsteiner@google.com (Roland Steiner)'
-
-from google.appengine.api import users
-from google.appengine.ext import db
-from google.appengine.api import memcache
-from google.appengine.ext import webapp
-from google.appengine.ext.webapp import template
-
-import django
-from django import http
-from django import shortcuts
-
-from django.template import add_to_builtins
-add_to_builtins('base.custom_filters')
-
-# Shared stuff
-from categories import all_test_sets
-from base import decorators
-from base import util
-
-# common to the RichText2 suite
-from categories.richtext2 import common
-
-# tests
-from categories.richtext2.tests.apply import APPLY_TESTS
-from categories.richtext2.tests.applyCSS import APPLY_TESTS_CSS
-from categories.richtext2.tests.change import CHANGE_TESTS
-from categories.richtext2.tests.changeCSS import CHANGE_TESTS_CSS
-from categories.richtext2.tests.delete import DELETE_TESTS
-from categories.richtext2.tests.forwarddelete import FORWARDDELETE_TESTS
-from categories.richtext2.tests.insert import INSERT_TESTS
-from categories.richtext2.tests.selection import SELECTION_TESTS
-from categories.richtext2.tests.unapply import UNAPPLY_TESTS
-from categories.richtext2.tests.unapplyCSS import UNAPPLY_TESTS_CSS
-
-from categories.richtext2.tests.querySupported import QUERYSUPPORTED_TESTS
-from categories.richtext2.tests.queryEnabled import QUERYENABLED_TESTS
-from categories.richtext2.tests.queryIndeterm import QUERYINDETERM_TESTS
-from categories.richtext2.tests.queryState import QUERYSTATE_TESTS, QUERYSTATE_TESTS_CSS
-from categories.richtext2.tests.queryValue import QUERYVALUE_TESTS, QUERYVALUE_TESTS_CSS
-
-
-def About(request):
- """About page."""
- overview = """These tests cover browers' implementations of
- <a href="http://blog.whatwg.org/the-road-to-html-5-contenteditable">contenteditable</a>
- for basic rich text formatting commands. Most browser implementations do very
- well at editing the HTML which is generated by their own execCommands. But a
- big problem happens when developers try to make cross-browser web
- applications using contenteditable - most browsers are not able to correctly
- change formatting generated by other browsers. On top of that, most browsers
- allow users to to paste arbitrary HTML from other webpages into a
- contenteditable region, which is even harder for browsers to properly
- format. These tests check how well the execCommand, queryCommandState,
- and queryCommandValue functions work with different types of HTML."""
- return util.About(request, common.CATEGORY, category_title='Rich Text',
- overview=overview, show_hidden=False)
-
-
-def RunRichText2Tests(request):
- params = {
- 'classes': common.CLASSES,
- 'commonIDPrefix': common.TEST_ID_PREFIX,
- 'strict': False,
- 'suites': [
- SELECTION_TESTS,
- APPLY_TESTS,
- APPLY_TESTS_CSS,
- CHANGE_TESTS,
- CHANGE_TESTS_CSS,
- UNAPPLY_TESTS,
- UNAPPLY_TESTS_CSS,
- DELETE_TESTS,
- FORWARDDELETE_TESTS,
- INSERT_TESTS,
-
- QUERYSUPPORTED_TESTS,
- QUERYENABLED_TESTS,
- QUERYINDETERM_TESTS,
- QUERYSTATE_TESTS,
- QUERYSTATE_TESTS_CSS,
- QUERYVALUE_TESTS,
- QUERYVALUE_TESTS_CSS
- ]
- }
- return shortcuts.render_to_response('%s/templates/richtext2.html' % common.CATEGORY, params)
-
-
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/common.css b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/common.css
deleted file mode 100644
index 77c6bb872..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/common.css
+++ /dev/null
@@ -1,116 +0,0 @@
-.framed {
- vertical-align: top;
- margin: 8px;
- border: 1px solid black;
-}
-
-.legend {
- padding: 12px;
- background-color: #f8f8ff;
-}
-
-.legendHdr {
- font-size: large;
- text-decoration: underline;
-}
-
-table.legend {
- display: inline-table;
-}
-
-.suite-thead {
- text-align: left;
-}
-
-.lo {
- background-color: #dddddd;
-}
-.hi {
- background-color: #eeeeee;
-}
-
-.lo .grey {
- background-color: #dddddd;
-}
-.lo .na {
- background-color: #dddddd;
-}
-.lo .pass {
- background-color: #d4ffc0;
-}
-.lo .canary {
- background-color: #ffcccc;
-}
-.lo .fail {
- background-color: #ffcccc;
-}
-.lo .accept {
- background-color: #ffffc0;
-}
-.lo .exception {
- background-color: #f0d0f4;
-}
-.lo .unsupported {
- background-color: #f0d0f4;
-}
-
-.hi .grey {
- background-color: #eeeeee;
-}
-.hi .na {
- background-color: #eeeeee;
-}
-.hi .pass {
- background-color: #e0ffdc;
-}
-.hi .canary {
- background-color: #ffd8d8;
-}
-.hi .fail {
- background-color: #ffd8d8;
-}
-.hi .accept {
- background-color: #ffffd8;
-}
-.hi .exception {
- background-color: #f4dcf8;
-}
-.hi .unsupported {
- background-color: #f4dcf8;
-}
-
-
-.sel {
- color: blue;
-}
-
-.txt {
- padding: 1px;
- margin: 1px;
- border: 1px solid #b0b0b0;
-}
-
-.idLabel {
- font-size: small;
-}
-
-.fade {
- color: grey;
-}
-.accexp {
- color: #606070;
-}
-.comment {
- color: grey;
-}
-
-.score {
- color: #666666;
-}
-
-.fatalerror {
- color: red;
- font-size: large;
- font-weight: bold;
-}
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-body.html b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-body.html
deleted file mode 100644
index a254adc03..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-body.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <meta http-equiv="content-type" content="text/html; charset=utf-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
-
- <link rel="stylesheet" href="editable.css" type="text/css">
-</head>
-<body contentEditable="true">
-</body>
-</html>
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-dM.html b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-dM.html
deleted file mode 100644
index e16de3ab9..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-dM.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <meta http-equiv="content-type" content="text/html; charset=utf-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
-
- <link rel="stylesheet" href="editable.css" type="text/css">
-
- <script>
- function setDesignMode() {
- window.document.designMode = "On";
- }
- </script>
-</head>
-<body onload="setDesignMode()">
-</body>
-</html>
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-div.html b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-div.html
deleted file mode 100644
index 7dd600dbd..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-div.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <meta http-equiv="content-type" content="text/html; charset=utf-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
-
- <link rel="stylesheet" href="editable.css" type="text/css">
-</head>
-<body>
-</body>
-</html>
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable.css b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable.css
deleted file mode 100644
index 99fec4950..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable.css
+++ /dev/null
@@ -1,66 +0,0 @@
-.b, myb {
- font-weight: bold;
-}
-
-.i, myi {
- font-style: italic;
-}
-
-.s, mys {
- text-decoration: line-through;
-}
-
-.u, myu {
- text-decoration: underline;
-}
-
-.sub, mysub {
- vertical-align: sub;
-}
-
-.sup, mysup {
- vertical-align: super;
-}
-
-.jc, myjc {
- text-align: center;
-}
-
-.jf, myjf {
- text-align: justify;
-}
-
-.jl, myjl {
- text-align: left;
-}
-
-.jr, myjr {
- text-align: right;
-}
-
-.red, myred {
- color: red;
-}
-
-.bcred, mybcred {
- background-color: red;
-}
-
-.large, mylarge {
- font-size: large;
-}
-
-.fs18px, myfs18px {
- font-size: 18px;
-}
-
-.courier, mycourier {
- font-family: courier;
-}
-
-gen::before {
- content: "[BEFORE]";
-}
-gen::after {
- content: "[AFTER]";
-}
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/canonicalize.js b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/canonicalize.js
deleted file mode 100644
index 2236d9dfc..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/canonicalize.js
+++ /dev/null
@@ -1,436 +0,0 @@
-/**
- * @fileoverview
- * Canonicalization functions used in the RTE test suite.
- *
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the 'License')
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an 'AS IS' BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @version 0.1
- * @author rolandsteiner@google.com
- */
-
-/**
- * Canonicalize HTML entities to their actual character
- *
- * @param str {String} the HTML string to be canonicalized
- * @return {String} the canonicalized string
- */
-
-function canonicalizeEntities(str) {
- // TODO(rolandsteiner): this function is very much not optimized, but that shouldn't
- // theoretically matter too much - look into it at some point.
- var match;
- while (match = str.match(/&#x([0-9A-F]+);/i)) {
- str = str.replace('&#x' + match[1] + ';', String.fromCharCode(parseInt(match[1], 16)));
- }
- while (match = str.match(/&#([0-9]+);/)) {
- str = str.replace('&#' + match[1] + ';', String.fromCharCode(Number(match[1])));
- }
- return str;
-}
-
-/**
- * Canonicalize the contents of the HTML 'style' attribute.
- * I.e. sorts the CSS attributes alphabetically and canonicalizes the values
- * CSS attributes where necessary.
- *
- * If this would return an empty string, return null instead to suppress the
- * whole 'style' attribute.
- *
- * Avoid tests that contain {, } or : within CSS values!
- *
- * Note that this function relies on the spaces of the input string already
- * having been normalized by canonicalizeSpaces!
- *
- * FIXME: does not canonicalize the contents of compound attributes
- * (e.g., 'border').
- *
- * @param str {String} contents of the 'style' attribute
- * @param emitFlags {Object} flags used for this output
- * @return {String/null} canonicalized string, null instead of the empty string
- */
-function canonicalizeStyle(str, emitFlags) {
- // Remove any enclosing curly brackets
- str = str.replace(/ ?[\{\}] ?/g, '');
-
- var attributes = str.split(';');
- var count = attributes.length;
- var resultArr = [];
-
- for (var a = 0; a < count; ++a) {
- // Retrieve "name: value" pair
- // Note: may expectedly fail if the last pair was terminated with ';'
- var avPair = attributes[a].match(/ ?([^ :]+) ?: ?(.+)/);
- if (!avPair)
- continue;
-
- var name = avPair[1];
- var value = avPair[2].replace(/ $/, ''); // Remove any trailing space.
-
- switch (name) {
- case 'color':
- case 'background-color':
- case 'border-color':
- if (emitFlags.canonicalizeUnits) {
- resultArr.push(name + ': #' + new Color(value).toHexString());
- } else {
- resultArr.push(name + ': ' + value);
- }
- break;
-
- case 'font-family':
- if (emitFlags.canonicalizeUnits) {
- resultArr.push(name + ': ' + new FontName(value).toString());
- } else {
- resultArr.push(name + ': ' + value);
- }
- break;
-
- case 'font-size':
- if (emitFlags.canonicalizeUnits) {
- resultArr.push(name + ': ' + new FontSize(value).toString());
- } else {
- resultArr.push(name + ': ' + value);
- }
- break;
-
- default:
- resultArr.push(name + ': ' + value);
- }
- }
-
- // Sort by name, assuming no duplicate CSS attribute names.
- resultArr.sort();
-
- return resultArr.join('; ') || null;
-}
-
-/**
- * Canonicalize a single attribute value.
- *
- * Note that this function relies on the spaces of the input string already
- * having been normalized by canonicalizeSpaces!
- *
- * @param elemName {String} the name of the element
- * @param attrName {String} the name of the attribute
- * @param attrValue {String} the value of the attribute
- * @param emitFlags {Object} flags used for this output
- * @return {String/null} the canonicalized value, or null if the attribute should be skipped.
- */
-function canonicalizeSingleAttribute(elemName, attrName, attrValue, emitFlags) {
- // We emit attributes as name="value", so change any contained apostrophes
- // to quote marks.
- attrValue = attrValue.replace(/\x22/, '\x27');
-
- switch (attrName) {
- case 'class':
- return emitFlags.emitClass ? attrValue : null;
-
- case 'id':
- if (!emitFlags.emitID) {
- return null;
- }
- if (attrValue && attrValue.substr(0, 7) == 'editor-') {
- return null;
- }
- return attrValue;
-
- // Remove empty style attributes, canonicalize the contents otherwise,
- // provided the test cares for styles.
- case 'style':
- return (emitFlags.emitStyle && attrValue)
- ? canonicalizeStyle(attrValue, emitFlags)
- : null;
-
- // Never output onload handlers as they are set by the test environment.
- case 'onload':
- return null;
-
- // Canonicalize colors.
- case 'bgcolor':
- case 'color':
- if (!attrValue) {
- return null;
- }
- return emitFlags.canonicalizeUnits ? new Color(attrValue).toString() : attrValue;
-
- // Canonicalize font names.
- case 'face':
- return emitFlags.canonicalizeUnits ? new FontName(attrValue).toString() : attrValue;
-
- // Canonicalize font sizes (leave other 'size' attributes as-is).
- case 'size':
- if (!attrValue) {
- return null;
- }
- switch (elemName) {
- case 'basefont':
- case 'font':
- return emitFlags.canonicalizeUnits ? new FontSize(attrValue).toString() : attrValue;
- }
- return attrValue;
-
- // Remove spans with value 1. Retain spans with other values, even if
- // empty or with a value 0, since those indicate a flawed implementation.
- case 'colspan':
- case 'rowspan':
- case 'span':
- return (attrValue == '1' || attrValue === '') ? null : attrValue;
-
- // Boolean attributes: presence equals true. If present, the value must be
- // the empty string or the attribute's canonical name.
- // (http://www.whatwg.org/specs/web-apps/current-work/#boolean-attributes)
- // Below we only normalize empty string to the canonical name for
- // comparison purposes. All other values are not touched and will therefore
- // in all likelihood result in a failed test (even if they may be accepted
- // by the UA).
- case 'async':
- case 'autofocus':
- case 'checked':
- case 'compact':
- case 'declare':
- case 'defer':
- case 'disabled':
- case 'formnovalidate':
- case 'frameborder':
- case 'ismap':
- case 'loop':
- case 'multiple':
- case 'nohref':
- case 'nosize':
- case 'noshade':
- case 'novalidate':
- case 'nowrap':
- case 'open':
- case 'readonly':
- case 'required':
- case 'reversed':
- case 'seamless':
- case 'selected':
- return attrValue ? attrValue : attrName;
-
- default:
- return attrValue;
- }
-}
-
-/**
- * Canonicalize the contents of an element tag.
- *
- * I.e. sorts the attributes alphabetically and canonicalizes their
- * values where necessary. Also removes attributes we're not interested in.
- *
- * Note that this function relies on the spaces of the input string already
- * having been normalized by canonicalizeSpaces!
- *
- * @param str {String} the contens of the element tag, excluding < and >.
- * @param emitFlags {Object} flags used for this output
- * @return {String} the canonicalized contents.
- */
-function canonicalizeElementTag(str, emitFlags) {
- // FIXME: lowercase only if emitFlags.lowercase is set
- str = str.toLowerCase();
-
- var pos = str.search(' ');
-
- // element name only
- if (pos == -1) {
- return str;
- }
-
- var elemName = str.substr(0, pos);
- str = str.substr(pos + 1);
-
- // Even if emitFlags.emitAttrs is not set, we must iterate over the
- // attributes to catch the special selection attribute and/or selection
- // markers. :(
-
- // Iterate over attributes, add them to an array, canonicalize their
- // contents, and finally output the (remaining) attributes in sorted order.
- // Note: We can't do a simple split on space here, because the value of,
- // e.g., 'style' attributes may also contain spaces.
- var attrs = [];
- var selStartInTag = false;
- var selEndInTag = false;
-
- while (str) {
- var attrName;
- var attrValue = '';
-
- pos = str.search(/[ =]/);
- if (pos >= 0) {
- attrName = str.substr(0, pos);
- if (str.charAt(pos) == ' ') {
- ++pos;
- }
- if (str.charAt(pos) == '=') {
- ++pos;
- if (str.charAt(pos) == ' ') {
- ++pos;
- }
- str = str.substr(pos);
- switch (str.charAt(0)) {
- case '"':
- case "'":
- pos = str.indexOf(str.charAt(0), 1);
- pos = (pos < 0) ? str.length : pos;
- attrValue = str.substring(1, pos);
- ++pos;
- break;
-
- default:
- pos = str.indexOf(' ', 0);
- pos = (pos < 0) ? str.length : pos;
- attrValue = (pos == -1) ? str : str.substr(0, pos);
- break;
- }
- attrValue = attrValue.replace(/^ /, '');
- attrValue = attrValue.replace(/ $/, '');
- }
- } else {
- attrName = str;
- }
- str = (pos == -1 || pos >= str.length) ? '' : str.substr(pos + 1);
-
- // Remove special selection attributes.
- switch (attrName) {
- case ATTRNAME_SEL_START:
- selStartInTag = true;
- continue;
-
- case ATTRNAME_SEL_END:
- selEndInTag = true;
- continue;
- }
-
- switch (attrName) {
- case '':
- case 'onload':
- case 'xmlns':
- break;
-
- default:
- if (!emitFlags.emitAttrs) {
- break;
- }
- // >>> fall through >>>
-
- case 'contenteditable':
- attrValue = canonicalizeEntities(attrValue);
- attrValue = canonicalizeSingleAttribute(elemName, attrName, attrValue, emitFlags);
- if (attrValue !== null) {
- attrs.push(attrName + '="' + attrValue + '"');
- }
- }
- }
-
- var result = elemName;
-
- // Sort alphabetically (on full string rather than just attribute value for
- // simplicity. Also, attribute names will differ when encountering the '=').
- if (attrs.length > 0) {
- attrs.sort();
- result += ' ' + attrs.join(' ');
- }
-
- // Add intra-tag selection marker(s) or attribute(s), if any, at the end.
- if (selStartInTag && selEndInTag) {
- result += ' |';
- } else if (selStartInTag) {
- result += ' {';
- } else if (selEndInTag) {
- result += ' }';
- }
-
- return result;
-}
-
-/**
- * Canonicalize elements and attributes to facilitate comparison to the
- * expectation string: sort attributes, canonicalize values and remove chaff.
- *
- * Note that this function relies on the spaces of the input string already
- * having been normalized by canonicalizeSpaces!
- *
- * @param str {String} the HTML string to be canonicalized
- * @param emitFlags {Object} flags used for this output
- * @return {String} the canonicalized string
- */
-function canonicalizeElementsAndAttributes(str, emitFlags) {
- var tagStart = str.indexOf('<');
- var tagEnd = 0;
- var result = '';
-
- while (tagStart >= 0) {
- ++tagStart;
- if (str.charAt(tagStart) == '/') {
- ++tagStart;
- }
- result = result + canonicalizeEntities(str.substring(tagEnd, tagStart));
- tagEnd = str.indexOf('>', tagStart);
- if (tagEnd < 0) {
- tagEnd = str.length - 1;
- }
- if (str.charAt(tagEnd - 1) == '/') {
- --tagEnd;
- }
- var elemStr = str.substring(tagStart, tagEnd);
- elemStr = canonicalizeElementTag(elemStr, emitFlags);
- result = result + elemStr;
- tagStart = str.indexOf('<', tagEnd);
- }
- return result + canonicalizeEntities(str.substring(tagEnd));
-}
-
-/**
- * Canonicalize an innerHTML string to uniform single whitespaces.
- *
- * FIXME: running this prevents testing for pre-formatted content
- * and the CSS 'white-space' attribute.
- *
- * @param str {String} the HTML string to be canonicalized
- * @return {String} the canonicalized string
- */
-function canonicalizeSpaces(str) {
- // Collapse sequential whitespace.
- str = str.replace(/\s+/g, ' ');
-
- // Remove spaces immediately inside angle brackets <, >, </ and />.
- // While doing this also canonicalize <.../> to <...>.
- str = str.replace(/\< ?/g, '<');
- str = str.replace(/\<\/ ?/g, '</');
- str = str.replace(/ ?\/?\>/g, '>');
-
- return str;
-}
-
-/**
- * Canonicalize an innerHTML string to uniform single whitespaces.
- * Also remove comments to retain only embedded selection markers, and
- * remove </br> and </hr> if present.
- *
- * FIXME: running this prevents testing for pre-formatted content
- * and the CSS 'white-space' attribute.
- *
- * @param str {String} the HTML string to be canonicalized
- * @return {String} the canonicalized string
- */
-function initialCanonicalizationOf(str) {
- str = canonicalizeSpaces(str);
- str = str.replace(/ ?<!-- ?/g, '');
- str = str.replace(/ ?--> ?/g, '');
- str = str.replace(/<\/[bh]r>/g, '');
-
- return str;
-}
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/compare.js b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/compare.js
deleted file mode 100644
index be059cfc8..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/compare.js
+++ /dev/null
@@ -1,489 +0,0 @@
-/**
- * @fileoverview
- * Comparison functions used in the RTE test suite.
- *
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the 'License')
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an 'AS IS' BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @version 0.1
- * @author rolandsteiner@google.com
- */
-
-/**
- * constants used only in the compare functions.
- */
-var RESULT_DIFF = 0; // actual result doesn't match expectation
-var RESULT_SEL = 1; // actual result matches expectation in HTML only
-var RESULT_EQUAL = 2; // actual result matches expectation in both HTML and selection
-
-/**
- * Gets the test expectations as an array from the passed-in field.
- *
- * @param {Array|String} the test expectation(s) as string or array.
- * @return {Array} test expectations as an array.
- */
-function getExpectationArray(expected) {
- if (expected === undefined) {
- return [];
- }
- if (expected === null) {
- return [null];
- }
- switch (typeof expected) {
- case 'string':
- case 'boolean':
- case 'number':
- return [expected];
- }
- // Assume it's already an array.
- return expected;
-}
-
-/**
- * Compare a test result to a single expectation string.
- *
- * FIXME: add support for optional elements/attributes.
- *
- * @param expected {String} the already canonicalized (with the exception of selection marks) expectation string
- * @param actual {String} the already canonicalized (with the exception of selection marks) actual result
- * @return {Integer} one of the RESULT_... return values
- * @see variables.js for return values
- */
-function compareHTMLToSingleExpectation(expected, actual) {
- // If the test checks the selection, then the actual string must match the
- // expectation exactly.
- if (expected == actual) {
- return RESULT_EQUAL;
- }
-
- // Remove selection markers and see if strings match then.
- expected = expected.replace(/ [{}\|]>/g, '>'); // intra-tag
- expected = expected.replace(/[\[\]\^{}\|]/g, ''); // outside tag
- actual = actual.replace(/ [{}\|]>/g, '>'); // intra-tag
- actual = actual.replace(/[\[\]\^{}\|]/g, ''); // outside tag
-
- return (expected == actual) ? RESULT_SEL : RESULT_DIFF;
-}
-
-/**
- * Compare the current HTMLtest result to the expectation string(s).
- *
- * @param actual {String/Boolean} actual value
- * @param expected {String/Array} expectation(s)
- * @param emitFlags {Object} flags to use for canonicalization
- * @return {Integer} one of the RESULT_... return values
- * @see variables.js for return values
- */
-function compareHTMLToExpectation(actual, expected, emitFlags) {
- // Find the most favorable result among the possible expectation strings.
- var expectedArr = getExpectationArray(expected);
- var count = expectedArr ? expectedArr.length : 0;
- var best = RESULT_DIFF;
-
- for (var idx = 0; idx < count && best < RESULT_EQUAL; ++idx) {
- var expected = expectedArr[idx];
- expected = canonicalizeSpaces(expected);
- expected = canonicalizeElementsAndAttributes(expected, emitFlags);
-
- var singleResult = compareHTMLToSingleExpectation(expected, actual);
-
- best = Math.max(best, singleResult);
- }
- return best;
-}
-
-/**
- * Compare the current HTMLtest result to expected and acceptable results
- *
- * @param expected {String/Array} expected result(s)
- * @param accepted {String/Array} accepted result(s)
- * @param actual {String} actual result
- * @param emitFlags {Object} how to canonicalize the HTML strings
- * @param result {Object} [out] object recieving the result of the comparison.
- */
-function compareHTMLTestResultTo(expected, accepted, actual, emitFlags, result) {
- actual = actual.replace(/[\x60\xb4]/g, '');
- actual = canonicalizeElementsAndAttributes(actual, emitFlags);
-
- var bestExpected = compareHTMLToExpectation(actual, expected, emitFlags);
-
- if (bestExpected == RESULT_EQUAL) {
- // Shortcut - it doesn't get any better
- result.valresult = VALRESULT_EQUAL;
- result.selresult = SELRESULT_EQUAL;
- return;
- }
-
- var bestAccepted = compareHTMLToExpectation(actual, accepted, emitFlags);
-
- switch (bestExpected) {
- case RESULT_SEL:
- switch (bestAccepted) {
- case RESULT_EQUAL:
- // The HTML was equal to the/an expected HTML result as well
- // (just not the selection there), therefore the difference
- // between expected and accepted can only lie in the selection.
- result.valresult = VALRESULT_EQUAL;
- result.selresult = SELRESULT_ACCEPT;
- return;
-
- case RESULT_SEL:
- case RESULT_DIFF:
- // The acceptable expectations did not yield a better result
- // -> stay with the original (i.e., comparison to 'expected') result.
- result.valresult = VALRESULT_EQUAL;
- result.selresult = SELRESULT_DIFF;
- return;
- }
- break;
-
- case RESULT_DIFF:
- switch (bestAccepted) {
- case RESULT_EQUAL:
- result.valresult = VALRESULT_ACCEPT;
- result.selresult = SELRESULT_EQUAL;
- return;
-
- case RESULT_SEL:
- result.valresult = VALRESULT_ACCEPT;
- result.selresult = SELRESULT_DIFF;
- return;
-
- case RESULT_DIFF:
- result.valresult = VALRESULT_DIFF;
- result.selresult = SELRESULT_NA;
- return;
- }
- break;
- }
-
- throw INTERNAL_ERR + HTML_COMPARISON;
-}
-
-/**
- * Verify that the canaries are unviolated.
- *
- * @param container {Object} the test container descriptor as object reference
- * @param result {Object} object reference that contains the result data
- * @return {Boolean} whether the canaries' HTML is OK (selection flagged, but not fatal)
- */
-function verifyCanaries(container, result) {
- if (!container.canary) {
- return true;
- }
-
- var str = canonicalizeElementsAndAttributes(result.bodyInnerHTML, emitFlagsForCanary);
-
- if (str.length < 2 * container.canary.length) {
- result.valresult = VALRESULT_CANARY;
- result.selresult = SELRESULT_NA;
- result.output = result.bodyOuterHTML;
- return false;
- }
-
- var strBefore = str.substr(0, container.canary.length);
- var strAfter = str.substr(str.length - container.canary.length);
-
- // Verify that the canary stretch doesn't contain any selection markers
- if (SELECTION_MARKERS.test(strBefore) || SELECTION_MARKERS.test(strAfter)) {
- str = str.replace(SELECTION_MARKERS, '');
- if (str.length < 2 * container.canary.length) {
- result.valresult = VALRESULT_CANARY;
- result.selresult = SELRESULT_NA;
- result.output = result.bodyOuterHTML;
- return false;
- }
-
- // Selection escaped contentEditable element, but HTML may still be ok.
- result.selresult = SELRESULT_CANARY;
- strBefore = str.substr(0, container.canary.length);
- strAfter = str.substr(str.length - container.canary.length);
- }
-
- if (strBefore !== container.canary || strAfter !== container.canary) {
- result.valresult = VALRESULT_CANARY;
- result.selresult = SELRESULT_NA;
- result.output = result.bodyOuterHTML;
- return false;
- }
-
- return true;
-}
-
-/**
- * Compare the current HTMLtest result to the expectation string(s).
- * Sets the global result variables.
- *
- * @param suite {Object} the test suite as object reference
- * @param group {Object} group of tests within the suite the test belongs to
- * @param test {Object} the test as object reference
- * @param container {Object} the test container description
- * @param result {Object} [in/out] the result description, incl. HTML strings
- * @see variables.js for result values
- */
-function compareHTMLTestResult(suite, group, test, container, result) {
- if (!verifyCanaries(container, result)) {
- return;
- }
-
- var emitFlags = {
- emitAttrs: getTestParameter(suite, group, test, PARAM_CHECK_ATTRIBUTES),
- emitStyle: getTestParameter(suite, group, test, PARAM_CHECK_STYLE),
- emitClass: getTestParameter(suite, group, test, PARAM_CHECK_CLASS),
- emitID: getTestParameter(suite, group, test, PARAM_CHECK_ID),
- lowercase: true,
- canonicalizeUnits: true
- };
-
- // 2a.) Compare opening tag -
- // decide whether to compare vs. outer or inner HTML based on this.
- var openingTagEnd = result.outerHTML.indexOf('>') + 1;
- var openingTag = result.outerHTML.substr(0, openingTagEnd);
-
- openingTag = canonicalizeElementsAndAttributes(openingTag, emitFlags);
- var tagCmp = compareHTMLToExpectation(openingTag, container.tagOpen, emitFlags);
-
- if (tagCmp == RESULT_EQUAL) {
- result.output = result.innerHTML;
- compareHTMLTestResultTo(
- getTestParameter(suite, group, test, PARAM_EXPECTED),
- getTestParameter(suite, group, test, PARAM_ACCEPT),
- result.innerHTML,
- emitFlags,
- result)
- } else {
- result.output = result.outerHTML;
- compareHTMLTestResultTo(
- getContainerParameter(suite, group, test, container, PARAM_EXPECTED_OUTER),
- getContainerParameter(suite, group, test, container, PARAM_ACCEPT_OUTER),
- result.outerHTML,
- emitFlags,
- result)
- }
-}
-
-/**
- * Insert a selection position indicator.
- *
- * @param node {DOMNode} the node where to insert the selection indicator
- * @param offs {Integer} the offset of the selection indicator
- * @param textInd {String} the indicator to use if the node is a text node
- * @param elemInd {String} the indicator to use if the node is an element node
- */
-function insertSelectionIndicator(node, offs, textInd, elemInd) {
- switch (node.nodeType) {
- case DOM_NODE_TYPE_TEXT:
- // Insert selection marker for text node into text content.
- var text = node.data;
- node.data = text.substring(0, offs) + textInd + text.substring(offs);
- break;
-
- case DOM_NODE_TYPE_ELEMENT:
- var child = node.firstChild;
- try {
- // node has other children: insert marker as comment node
- var comment = document.createComment(elemInd);
- while (child && offs) {
- --offs;
- child = child.nextSibling;
- }
- if (child) {
- node.insertBefore(comment, child);
- } else {
- node.appendChild(comment);
- }
- } catch (ex) {
- // can't append child comment -> insert as special attribute(s)
- switch (elemInd) {
- case '|':
- node.setAttribute(ATTRNAME_SEL_START, '1');
- node.setAttribute(ATTRNAME_SEL_END, '1');
- break;
-
- case '{':
- node.setAttribute(ATTRNAME_SEL_START, '1');
- break;
-
- case '}':
- node.setAttribute(ATTRNAME_SEL_END, '1');
- break;
- }
- }
- break;
- }
-}
-
-/**
- * Adds quotes around all text nodes to show cases with non-normalized
- * text nodes. Those are not a bug, but may still be usefil in helping to
- * debug erroneous cases.
- *
- * @param node {DOMNode} root node from which to descend
- */
-function encloseTextNodesWithQuotes(node) {
- switch (node.nodeType) {
- case DOM_NODE_TYPE_ELEMENT:
- for (var i = 0; i < node.childNodes.length; ++i) {
- encloseTextNodesWithQuotes(node.childNodes[i]);
- }
- break;
-
- case DOM_NODE_TYPE_TEXT:
- node.data = '\x60' + node.data + '\xb4';
- break;
- }
-}
-
-/**
- * Retrieve the result of a test run and do some preliminary canonicalization.
- *
- * @param container {Object} the container where to retrieve the result from as object reference
- * @param result {Object} object reference that contains the result data
- * @return {String} a preliminarily canonicalized innerHTML with selection markers
- */
-function prepareHTMLTestResult(container, result) {
- // Start with empty strings in case any of the below throws.
- result.innerHTML = '';
- result.outerHTML = '';
-
- // 1.) insert selection markers
- var selRange = createFromWindow(container.win);
- if (selRange) {
- // save values, since range object gets auto-modified
- var node1 = selRange.getAnchorNode();
- var offs1 = selRange.getAnchorOffset();
- var node2 = selRange.getFocusNode();
- var offs2 = selRange.getFocusOffset();
-
- // add markers
- if (node1 && node1 == node2 && offs1 == offs2) {
- // collapsed selection
- insertSelectionIndicator(node1, offs1, '^', '|');
- } else {
- // Start point and end point are different
- if (node1) {
- insertSelectionIndicator(node1, offs1, '[', '{');
- }
-
- if (node2) {
- if (node1 == node2 && offs1 < offs2) {
- // Anchor indicator was inserted under the same node, so we need
- // to shift the offset by 1
- ++offs2;
- }
- insertSelectionIndicator(node2, offs2, ']', '}');
- }
- }
- }
-
- // 2.) insert markers for text node boundaries;
- encloseTextNodesWithQuotes(container.editor);
-
- // 3.) retrieve inner and outer HTML
- result.innerHTML = initialCanonicalizationOf(container.editor.innerHTML);
- result.bodyInnerHTML = initialCanonicalizationOf(container.body.innerHTML);
- if (goog.userAgent.IE) {
- result.outerHTML = initialCanonicalizationOf(container.editor.outerHTML);
- result.bodyOuterHTML = initialCanonicalizationOf(container.body.outerHTML);
- result.outerHTML = result.outerHTML.replace(/^\s+/, '');
- result.outerHTML = result.outerHTML.replace(/\s+$/, '');
- result.bodyOuterHTML = result.bodyOuterHTML.replace(/^\s+/, '');
- result.bodyOuterHTML = result.bodyOuterHTML.replace(/\s+$/, '');
- } else {
- result.outerHTML = initialCanonicalizationOf(new XMLSerializer().serializeToString(container.editor));
- result.bodyOuterHTML = initialCanonicalizationOf(new XMLSerializer().serializeToString(container.body));
- }
-}
-
-/**
- * Compare a text test result to the expectation string(s).
- *
- * @param suite {Object} the test suite as object reference
- * @param group {Object} group of tests within the suite the test belongs to
- * @param test {Object} the test as object reference
- * @param actual {String/Boolean} actual value
- * @param expected {String/Array} expectation(s)
- * @return {Boolean} whether we found a match
- */
-function compareTextTestResultWith(suite, group, test, actual, expected) {
- var expectedArr = getExpectationArray(expected);
- // Find the most favorable result among the possible expectation strings.
- var count = expectedArr.length;
-
- // If the value matches the expectation exactly, then we're fine.
- for (var idx = 0; idx < count; ++idx) {
- if (actual === expectedArr[idx])
- return true;
- }
-
- // Otherwise see if we should canonicalize specific value types.
- //
- // We only need to look at font name, color and size units if the originating
- // test was both a) queryCommandValue and b) querying a font name/color/size
- // specific criterion.
- //
- // TODO(rolandsteiner): This is ugly! Refactor!
- switch (getTestParameter(suite, group, test, PARAM_QUERYCOMMANDVALUE)) {
- case 'backcolor':
- case 'forecolor':
- case 'hilitecolor':
- for (var idx = 0; idx < count; ++idx) {
- if (new Color(actual).compare(new Color(expectedArr[idx])))
- return true;
- }
- return false;
-
- case 'fontname':
- for (var idx = 0; idx < count; ++idx) {
- if (new FontName(actual).compare(new FontName(expectedArr[idx])))
- return true;
- }
- return false;
-
- case 'fontsize':
- for (var idx = 0; idx < count; ++idx) {
- if (new FontSize(actual).compare(new FontSize(expectedArr[idx])))
- return true;
- }
- return false;
- }
-
- return false;
-}
-
-/**
- * Compare the passed-in text test result to the expectation string(s).
- * Sets the global result variables.
- *
- * @param suite {Object} the test suite as object reference
- * @param group {Object} group of tests within the suite the test belongs to
- * @param test {Object} the test as object reference
- * @param actual {String/Boolean} actual value
- * @return {Integer} a RESUTLHTML... result value
- * @see variables.js for result values
- */
-function compareTextTestResult(suite, group, test, result) {
- var expected = getTestParameter(suite, group, test, PARAM_EXPECTED);
- if (compareTextTestResultWith(suite, group, test, result.output, expected)) {
- result.valresult = VALRESULT_EQUAL;
- return;
- }
- var accepted = getTestParameter(suite, group, test, PARAM_ACCEPT);
- if (accepted && compareTextTestResultWith(suite, group, test, result.output, accepted)) {
- result.valresult = VALRESULT_ACCEPT;
- return;
- }
- result.valresult = VALRESULT_DIFF;
-}
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/output.js b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/output.js
deleted file mode 100644
index 897efa011..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/output.js
+++ /dev/null
@@ -1,456 +0,0 @@
-/**
- * @fileoverview
- * Functions used to format the test result output.
- *
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the 'License')
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an 'AS IS' BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @version 0.1
- * @author rolandsteiner@google.com
- */
-
-/**
- * Writes a fatal error to the output (replaces alert box)
- *
- * @param text {String} text to output
- */
-function writeFatalError(text) {
- var errorsStart = document.getElementById('errors');
- var divider = document.getElementById('divider');
- if (!errorsStart) {
- errorsStart = document.createElement('hr');
- errorsStart.id = 'errors';
- divider.parentNode.insertBefore(errorsStart, divider);
- }
- var error = document.createElement('div');
- error.className = 'fatalerror';
- error.innerHTML = 'FATAL ERROR: ' + escapeOutput(text);
- errorsStart.parentNode.insertBefore(error, divider);
-}
-
-/**
- * Generates a unique ID for a given single test out of the suite ID and
- * test ID.
- *
- * @param suiteID {string} ID string of the suite
- * @param testID {string} ID string of the individual tests
- * @return {string} globally unique ID
- */
-function generateOutputID(suiteID, testID) {
- return commonIDPrefix + '-' + suiteID + '_' + testID;
-}
-
-/**
- * Function to highlight the selection markers
- *
- * @param str {String} a HTML string containing selection markers
- * @return {String} the HTML string with highlighting tags around the markers
- */
-function highlightSelectionMarkers(str) {
- str = str.replace(/\[/g, '<span class="sel">[</span>');
- str = str.replace(/\]/g, '<span class="sel">]</span>');
- str = str.replace(/\^/g, '<span class="sel">^</span>');
- str = str.replace(/{/g, '<span class="sel">{</span>');
- str = str.replace(/}/g, '<span class="sel">}</span>');
- str = str.replace(/\|/g, '<b class="sel">|</b>');
- return str;
-}
-
-/**
- * Function to highlight the selection markers
- *
- * @param str {String} a HTML string containing selection markers
- * @return {String} the HTML string with highlighting tags around the markers
- */
-function highlightSelectionMarkersAndTextNodes(str) {
- str = highlightSelectionMarkers(str);
- str = str.replace(/\x60/g, '<span class="txt">');
- str = str.replace(/\xb4/g, '</span>');
- return str;
-}
-
-/**
- * Function to format output according to type
- *
- * @param value {String/Boolean} string or value to format
- * @return {String} HTML-formatted string
- */
-function formatValueOrString(value) {
- if (value === undefined)
- return '<i>undefined</i>';
- if (value === null)
- return '<i>null</i>';
-
- switch (typeof value) {
- case 'boolean':
- return '<i>' + value.toString() + '</i>';
-
- case 'number':
- return value.toString();
-
- case 'string':
- return "'" + escapeOutput(value) + "'";
-
- default:
- return '<i>(' + escapeOutput(value.toString()) + ')</i>';
- }
-}
-
-/**
- * Function to highlight text nodes
- *
- * @param suite {Object} the suite the test belongs to
- * @param group {Object} the group within the suite the test belongs to
- * @param test {Object} the test description as object reference
- * @param actual {String} a HTML string containing text nodes with markers
- * @return {String} string with highlighting tags around the text node parts
- */
-function formatActualResult(suite, group, test, actual) {
- if (typeof actual != 'string')
- return formatValueOrString(actual);
-
- actual = escapeOutput(actual);
-
- // Fade attributes (or just style) if not actually tested for
- if (!getTestParameter(suite, group, test, PARAM_CHECK_ATTRIBUTES)) {
- actual = actual.replace(/([^ =]+)=\x22([^\x22]*)\x22/g, '<span class="fade">$1="$2"</span>');
- } else {
- // NOTE: convert 'class="..."' first, before adding other <span class="fade">...</span> !!!
- if (!getTestParameter(suite, group, test, PARAM_CHECK_CLASS)) {
- actual = actual.replace(/class=\x22([^\x22]*)\x22/g, '<span class="fade">class="$1"</span>');
- }
- if (!getTestParameter(suite, group, test, PARAM_CHECK_STYLE)) {
- actual = actual.replace(/style=\x22([^\x22]*)\x22/g, '<span class="fade">style="$1"</span>');
- }
- if (!getTestParameter(suite, group, test, PARAM_CHECK_ID)) {
- actual = actual.replace(/id=\x22([^\x22]*)\x22/g, '<span class="fade">id="$1"</span>');
- } else {
- // fade out contenteditable host element's 'editor-<xyz>' ID.
- actual = actual.replace(/id=\x22editor-([^\x22]*)\x22/g, '<span class="fade">id="editor-$1"</span>');
- }
- // grey out 'xmlns'
- actual = actual.replace(/xmlns=\x22([^\x22]*)\x22/g, '<span class="fade">xmlns="$1"</span>');
- // remove 'onload'
- actual = actual.replace(/onload=\x22[^\x22]*\x22 ?/g, '');
- }
- // Highlight selection markers and text nodes.
- actual = highlightSelectionMarkersAndTextNodes(actual);
-
- return actual;
-}
-
-/**
- * Escape text content for use with .innerHTML.
- *
- * @param str {String} HTML text to displayed
- * @return {String} the escaped HTML
- */
-function escapeOutput(str) {
- return str ? str.replace(/\</g, '&lt;').replace(/\>/g, '&gt;') : '';
-}
-
-/**
- * Fills in a single output table cell
- *
- * @param id {String} ID of the table cell
- * @param val {String} inner HTML to set
- * @param ttl {String, optional} value of the 'title' attribute
- * @param cls {String, optional} class name for the cell
- */
-function setTD(id, val, ttl, cls) {
- var td = document.getElementById(id);
- if (td) {
- td.innerHTML = val;
- if (ttl) {
- td.title = ttl;
- }
- if (cls) {
- td.className = cls;
- }
- }
-}
-
-/**
- * Outputs the results of a single test suite
- *
- * @param suite {Object} test suite as object reference
- * @param clsID {String} test class ID ('Proposed', 'RFC', 'Final')
- * @param group {Object} the group of tests within the suite the test belongs to
- * @param testIdx {Object} the test as object reference
- */
-function outputTestResults(suite, clsID, group, test) {
- var suiteID = suite.id;
- var cls = suite[clsID];
- var trID = generateOutputID(suiteID, test.id);
- var testResult = results[suiteID][clsID][test.id];
- var testValOut = VALOUTPUT[testResult.valresult];
- var testSelOut = SELOUTPUT[testResult.selresult];
-
- var suiteChecksSelOnly = !suiteChecksHTMLOrText(suite);
- var testUsesHTML = !!getTestParameter(suite, group, test, PARAM_EXECCOMMAND) ||
- !!getTestParameter(suite, group, test, PARAM_FUNCTION);
-
- // Set background color for test ID
- var td = document.getElementById(trID + IDOUT_TESTID);
- if (td) {
- td.className = (suiteChecksSelOnly && testResult.selresult != SELRESULT_NA) ? testSelOut.css : testValOut.css;
- }
-
- // Fill in "Command" and "Value" cells
- var cmd;
- var cmdOutput = '&nbsp;';
- var valOutput = '&nbsp;';
-
- if (cmd = getTestParameter(suite, group, test, PARAM_EXECCOMMAND)) {
- cmdOutput = escapeOutput(cmd);
- var val = getTestParameter(suite, group, test, PARAM_VALUE);
- if (val !== undefined) {
- valOutput = formatValueOrString(val);
- }
- } else if (cmd = getTestParameter(suite, group, test, PARAM_FUNCTION)) {
- cmdOutput = '<i>' + escapeOutput(cmd) + '</i>';
- } else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDSUPPORTED)) {
- cmdOutput = '<i>queryCommandSupported</i>';
- valOutput = escapeOutput(cmd);
- } else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDENABLED)) {
- cmdOutput = '<i>queryCommandEnabled</i>';
- valOutput = escapeOutput(cmd);
- } else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDINDETERM)) {
- cmdOutput = '<i>queryCommandIndeterm</i>';
- valOutput = escapeOutput(cmd);
- } else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDSTATE)) {
- cmdOutput = '<i>queryCommandState</i>';
- valOutput = escapeOutput(cmd);
- } else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDVALUE)) {
- cmdOutput = '<i>queryCommandValue</i>';
- valOutput = escapeOutput(cmd);
- } else {
- cmdOutput = '<i>(none)</i>';
- }
- setTD(trID + IDOUT_COMMAND, cmdOutput);
- setTD(trID + IDOUT_VALUE, valOutput);
-
- // Fill in "Attribute checked?" and "Style checked?" cells
- if (testUsesHTML) {
- var checkAttrs = getTestParameter(suite, group, test, PARAM_CHECK_ATTRIBUTES);
- var checkStyle = getTestParameter(suite, group, test, PARAM_CHECK_STYLE);
-
- setTD(trID + IDOUT_CHECKATTRS,
- checkAttrs ? OUTSTR_YES : OUTSTR_NO,
- checkAttrs ? 'attributes must match' : 'attributes are ignored');
-
- if (checkAttrs && checkStyle) {
- setTD(trID + IDOUT_CHECKSTYLE, OUTSTR_YES, 'style attribute contents must match');
- } else if (checkAttrs) {
- setTD(trID + IDOUT_CHECKSTYLE, OUTSTR_NO, 'style attribute contents is ignored');
- } else {
- setTD(trID + IDOUT_CHECKSTYLE, OUTSTR_NO, 'all attributes (incl. style) are ignored');
- }
- } else {
- setTD(trID + IDOUT_CHECKATTRS, OUTSTR_NA, 'attributes not applicable');
- setTD(trID + IDOUT_CHECKSTYLE, OUTSTR_NA, 'style not applicable');
- }
-
- // Fill in test pad specification cell (initial HTML + selection markers)
- setTD(trID + IDOUT_PAD, highlightSelectionMarkers(escapeOutput(getTestParameter(suite, group, test, PARAM_PAD))));
-
- // Fill in expected result(s) cell
- var expectedOutput = '';
- var expectedArr = getExpectationArray(getTestParameter(suite, group, test, PARAM_EXPECTED));
- for (var idx = 0; idx < expectedArr.length; ++idx) {
- if (expectedOutput) {
- expectedOutput += '\xA0\xA0\xA0<i>or</i><br>';
- }
- expectedOutput += testUsesHTML ? highlightSelectionMarkers(escapeOutput(expectedArr[idx]))
- : formatValueOrString(expectedArr[idx]);
- }
- var acceptedArr = getExpectationArray(getTestParameter(suite, group, test, PARAM_ACCEPT));
- for (var idx = 0; idx < acceptedArr.length; ++idx) {
- expectedOutput += '<span class="accexp">\xA0\xA0\xA0<i>or</i></span><br><span class="accexp">';
- expectedOutput += testUsesHTML ? highlightSelectionMarkers(escapeOutput(acceptedArr[idx]))
- : formatValueOrString(acceptedArr[idx]);
- expectedOutput += '</span>';
- }
- // TODO(rolandsteiner): THIS IS UGLY, relying on 'div' container being index 2,
- // AND not allowing other containers to have 'outer' results - change!!!
- var outerOutput = '';
- expectedArr = getExpectationArray(getContainerParameter(suite, group, test, containers[2], PARAM_EXPECTED_OUTER));
- for (var idx = 0; idx < expectedArr.length; ++idx) {
- if (outerOutput) {
- outerOutput += '\xA0\xA0\xA0<i>or</i><br>';
- }
- outerOutput += testUsesHTML ? highlightSelectionMarkers(escapeOutput(expectedArr[idx]))
- : formatValueOrString(expectedArr[idx]);
- }
- acceptedArr = getExpectationArray(getContainerParameter(suite, group, test, containers[2], PARAM_ACCEPT_OUTER));
- for (var idx = 0; idx < acceptedArr.length; ++idx) {
- if (outerOutput) {
- outerOutput += '<span class="accexp">\xA0\xA0\xA0<i>or</i></span><br>';
- }
- outerOutput += '<span class="accexp">';
- outerOutput += testUsesHTML ? highlightSelectionMarkers(escapeOutput(acceptedArr[idx]))
- : formatValueOrString(acceptedArr[idx]);
- outerOutput += '</span>';
- }
- if (outerOutput) {
- expectedOutput += '<hr>' + outerOutput;
- }
- setTD(trID + IDOUT_EXPECTED, expectedOutput);
-
- // Iterate over the individual container results
- for (var cntIdx = 0; cntIdx < containers.length; ++cntIdx) {
- var cntID = containers[cntIdx].id;
- var cntTD = document.getElementById(trID + IDOUT_CONTAINER + cntID);
- var cntResult = testResult[cntID];
- var cntValOut = VALOUTPUT[cntResult.valresult];
- var cntSelOut = SELOUTPUT[cntResult.selresult];
- var cssVal = cntValOut.css;
- var cssSel = (!suiteChecksSelOnly || cntResult.selresult != SELRESULT_NA) ? cntSelOut.css : cssVal;
- var cssCnt = cssVal;
-
- // Fill in result status cell ("PASS", "ACC.", "FAIL", "EXC.", etc.)
- setTD(trID + IDOUT_STATUSVAL + cntID, cntValOut.output, cntValOut.title, cssVal);
-
- // Fill in selection status cell ("PASS", "ACC.", "FAIL", "N/A")
- setTD(trID + IDOUT_STATUSSEL + cntID, cntSelOut.output, cntSelOut.title, cssSel);
-
- // Fill in actual result
- switch (cntResult.valresult) {
- case VALRESULT_SETUP_EXCEPTION:
- setTD(trID + IDOUT_ACTUAL + cntID,
- SETUP_EXCEPTION + '(mouseover)',
- escapeOutput(cntResult.output),
- cssVal);
- break;
-
- case VALRESULT_EXECUTION_EXCEPTION:
- setTD(trID + IDOUT_ACTUAL + cntID,
- EXECUTION_EXCEPTION + '(mouseover)',
- escapeOutput(cntResult.output.toString()),
- cssVal);
- break;
-
- case VALRESULT_VERIFICATION_EXCEPTION:
- setTD(trID + IDOUT_ACTUAL + cntID,
- VERIFICATION_EXCEPTION + '(mouseover)',
- escapeOutput(cntResult.output.toString()),
- cssVal);
- break;
-
- case VALRESULT_UNSUPPORTED:
- setTD(trID + IDOUT_ACTUAL + cntID,
- escapeOutput(cntResult.output),
- '',
- cssVal);
- break;
-
- case VALRESULT_CANARY:
- setTD(trID + IDOUT_ACTUAL + cntID,
- highlightSelectionMarkersAndTextNodes(escapeOutput(cntResult.output)),
- '',
- cssVal);
- break;
-
- case VALRESULT_DIFF:
- case VALRESULT_ACCEPT:
- case VALRESULT_EQUAL:
- if (!testUsesHTML) {
- setTD(trID + IDOUT_ACTUAL + cntID,
- formatValueOrString(cntResult.output),
- '',
- cssVal);
- } else if (cntResult.selresult == SELRESULT_CANARY) {
- cssCnt = suiteChecksSelOnly ? cssSel : cssVal;
- setTD(trID + IDOUT_ACTUAL + cntID,
- highlightSelectionMarkersAndTextNodes(escapeOutput(cntResult.output)),
- '',
- cssCnt);
- } else {
- cssCnt = suiteChecksSelOnly ? cssSel : cssVal;
- setTD(trID + IDOUT_ACTUAL + cntID,
- formatActualResult(suite, group, test, cntResult.output),
- '',
- cssCnt);
- }
- break;
-
- default:
- cssCnt = 'exception';
- setTD(trID + IDOUT_ACTUAL + cntID,
- INTERNAL_ERR + 'UNKNOWN RESULT VALUE',
- '',
- cssCnt);
- }
-
- if (cntTD) {
- cntTD.className = cssCnt;
- }
- }
-}
-
-/**
- * Outputs the results of a single test suite
- *
- * @param {Object} suite as object reference
- */
-function outputTestSuiteResults(suite) {
- var suiteID = suite.id;
- var span;
-
- span = document.getElementById(suiteID + '-score');
- if (span) {
- span.innerHTML = results[suiteID].valscore + '/' + results[suiteID].count;
- }
- span = document.getElementById(suiteID + '-selscore');
- if (span) {
- span.innerHTML = results[suiteID].selscore + '/' + results[suiteID].count;
- }
- span = document.getElementById(suiteID + '-time');
- if (span) {
- span.innerHTML = results[suiteID].time;
- }
- span = document.getElementById(suiteID + '-progress');
- if (span) {
- span.style.color = 'green';
- }
-
- for (var clsIdx = 0; clsIdx < testClassCount; ++clsIdx) {
- var clsID = testClassIDs[clsIdx];
- var cls = suite[clsID];
- if (!cls)
- continue;
-
- span = document.getElementById(suiteID + '-' + clsID + '-score');
- if (span) {
- span.innerHTML = results[suiteID][clsID].valscore + '/' + results[suiteID][clsID].count;
- }
- span = document.getElementById(suiteID + '-' + clsID + '-selscore');
- if (span) {
- span.innerHTML = results[suiteID][clsID].selscore + '/' + results[suiteID][clsID].count;
- }
-
- var groupCount = cls.length;
-
- for (var groupIdx = 0; groupIdx < groupCount; ++groupIdx) {
- var group = cls[groupIdx];
- var testCount = group.tests.length;
-
- for (var testIdx = 0; testIdx < testCount; ++testIdx) {
- var test = group.tests[testIdx];
-
- outputTestResults(suite, clsID, group, test);
- }
- }
- }
-}
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/pad.js b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/pad.js
deleted file mode 100644
index 282f0d907..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/pad.js
+++ /dev/null
@@ -1,269 +0,0 @@
-/**
- * @fileoverview
- * Functions used to handle test and expectation strings.
- *
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the 'License')
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an 'AS IS' BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @version 0.1
- * @author rolandsteiner@google.com
- */
-
-/**
- * Normalize text selection indicators and convert inter-element selection
- * indicators to comments.
- *
- * Note that this function relies on the spaces of the input string already
- * having been normalized by canonicalizeSpaces!
- *
- * @param pad {String} HTML string that includes selection marker characters
- * @return {String} the HTML string with the selection markers converted
- */
-function convertSelectionIndicators(pad) {
- // Sanity check: Markers { } | only directly before or after an element,
- // or just before a closing > (i.e., not within a text node).
- // Note that intra-tag selection markers have already been converted to the
- // special selection attribute(s) above.
- if (/[^>][{}\|][^<>]/.test(pad) ||
- /^[{}\|][^<]/.test(pad) ||
- /[^>][{}\|]$/.test(pad) ||
- /^[{}\|]*$/.test(pad)) {
- throw SETUP_BAD_SELECTION_SPEC;
- }
-
- // Convert intra-tag selection markers to special attributes.
- pad = pad.replace(/\{\>/g, ATTRNAME_SEL_START + '="1">');
- pad = pad.replace(/\}\>/g, ATTRNAME_SEL_END + '="1">');
- pad = pad.replace(/\|\>/g, ATTRNAME_SEL_START + '="1" ' +
- ATTRNAME_SEL_END + '="1">');
-
- // Convert remaining {, }, | to comments with '[' and ']' data.
- pad = pad.replace('{', '<!--[-->');
- pad = pad.replace('}', '<!--]-->');
- pad = pad.replace('|', '<!--[--><!--]-->');
-
- // Convert caret indicator ^ to empty selection indicator []
- // (this simplifies further processing).
- pad = pad.replace(/\^/, '[]');
-
- return pad;
-}
-
-/**
- * Derives one point of the selection from the indicators with the HTML tree:
- * '[' or ']' within a text or comment node, or the special selection
- * attributes within an element node.
- *
- * @param root {DOMNode} root node of the recursive search
- * @param marker {String} which marker to look for: '[' or ']'
- * @return {Object} a pair object: {node: {DOMNode}/null, offset: {Integer}}
- */
-function deriveSelectionPoint(root, marker) {
- switch (root.nodeType) {
- case DOM_NODE_TYPE_ELEMENT:
- if (root.attributes) {
- // Note: getAttribute() is necessary for this to work on all browsers!
- if (marker == '[' && root.getAttribute(ATTRNAME_SEL_START)) {
- root.removeAttribute(ATTRNAME_SEL_START);
- return {node: root, offs: 0};
- }
- if (marker == ']' && root.getAttribute(ATTRNAME_SEL_END)) {
- root.removeAttribute(ATTRNAME_SEL_END);
- return {node: root, offs: 0};
- }
- }
- for (var i = 0; i < root.childNodes.length; ++i) {
- var pair = deriveSelectionPoint(root.childNodes[i], marker);
- if (pair.node) {
- return pair;
- }
- }
- break;
-
- case DOM_NODE_TYPE_TEXT:
- var pos = root.data.indexOf(marker);
- if (pos != -1) {
- // Remove selection marker from text.
- var nodeText = root.data;
- root.data = nodeText.substr(0, pos) + nodeText.substr(pos + 1);
- return {node: root, offs: pos };
- }
- break;
-
- case DOM_NODE_TYPE_COMMENT:
- var pos = root.data.indexOf(marker);
- if (pos != -1) {
- // Remove comment node from parent.
- var helper = root.previousSibling;
-
- for (pos = 0; helper; ++pos ) {
- helper = helper.previousSibling;
- }
- helper = root;
- root = root.parentNode;
- root.removeChild(helper);
- return {node: root, offs: pos };
- }
- break;
- }
-
- return {node: null, offs: 0 };
-}
-
-/**
- * Initialize the test HTML with the starting state specified in the test.
- *
- * The selection is specified "inline", using special characters:
- * ^ a collapsed text caret selection (same as [])
- * [ the selection start within a text node
- * ] the selection end within a text node
- * | collapsed selection between elements (same as {})
- * { selection starting with the following element
- * } selection ending with the preceding element
- * {, } and | can also be used within an element tag, just before the closing
- * angle bracket > to specify a selection [element, 0] where the element
- * doesn't otherwise have any children. Ex.: <hr {>foobarbaz<hr }>
- *
- * Explicit and implicit specification can also be mixed between the 2 points.
- *
- * A pad string must only contain at most ONE of the above that is suitable for
- * that start or end point, respectively, and must contain either both or none.
- *
- * @param suite {Object} suite that test originates in as object reference
- * @param group {Object} group of tests within the suite the test belongs to
- * @param test {Object} test to be run as object reference
- * @param container {Object} container descriptor as object reference
- */
-function initContainer(suite, group, test, container) {
- var pad = getTestParameter(suite, group, test, PARAM_PAD);
- pad = canonicalizeSpaces(pad);
- pad = convertSelectionIndicators(pad);
-
- if (container.editorID) {
- container.body.innerHTML = container.canary + container.tagOpen + pad + container.tagClose + container.canary;
- container.editor = container.doc.getElementById(container.editorID);
- } else {
- container.body.innerHTML = pad;
- container.editor = container.body;
- }
-
- win = container.win;
- doc = container.doc;
- body = container.body;
- editor = container.editor;
- sel = null;
-
- if (!editor) {
- throw SETUP_CONTAINER;
- }
-
- if (getTestParameter(suite, group, test, PARAM_STYLE_WITH_CSS)) {
- try {
- container.doc.execCommand('styleWithCSS', false, true);
- } catch (ex) {
- // ignore exception if unsupported
- }
- }
-
- var selAnchor = deriveSelectionPoint(editor, '[');
- var selFocus = deriveSelectionPoint(editor, ']');
-
- // sanity check
- if (!selAnchor || !selFocus) {
- throw SETUP_SELECTION;
- }
-
- if (!selAnchor.node || !selFocus.node) {
- if (selAnchor.node || selFocus.node) {
- // Broken test: only one selection point was specified
- throw SETUP_BAD_SELECTION_SPEC;
- }
- sel = null;
- return;
- }
-
- if (selAnchor.node === selFocus.node) {
- if (selAnchor.offs > selFocus.offs) {
- // Both selection points are within the same node, the selection was
- // specified inline (thus the end indicator element or character was
- // removed), and the end point is before the start (reversed selection).
- // Start offset that was derived is now off by 1 and needs adjustment.
- --selAnchor.offs;
- }
-
- if (selAnchor.offs === selFocus.offs) {
- createCaret(selAnchor.node, selAnchor.offs).select();
- try {
- sel = win.getSelection();
- } catch (ex) {
- sel = undefined;
- }
- return;
- }
- }
-
- createFromNodes(selAnchor.node, selAnchor.offs, selFocus.node, selFocus.offs).select();
-
- try {
- sel = win.getSelection();
- } catch (ex) {
- sel = undefined;
- }
-}
-
-/**
- * Reset the editor element after a test is run.
- *
- * @param container {Object} container descriptor as object reference
- */
-function resetContainer(container) {
- // Remove errant styles and attributes that may have been set on the <body>.
- container.body.removeAttribute('style');
- container.body.removeAttribute('color');
- container.body.removeAttribute('bgcolor');
-
- try {
- container.doc.execCommand('styleWithCSS', false, false);
- } catch (ex) {
- // Ignore exception if unsupported.
- }
-}
-
-/**
- * Initialize the editor document.
- */
-function initEditorDocs() {
- for (var c = 0; c < containers.length; ++c) {
- var container = containers[c];
-
- container.iframe = document.getElementById('iframe-' + container.id);
- container.win = container.iframe.contentWindow;
- container.doc = container.win.document;
- container.body = container.doc.body;
- // container.editor is set per test (changes on embedded editor elements).
-
- // Some browsers require a selection to go with their 'styleWithCSS'.
- try {
- container.win.getSelection().selectAllChildren(editor);
- } catch (ex) {
- // ignore exception if unsupported
- }
- // Default styleWithCSS to false.
- try {
- container.doc.execCommand('styleWithCSS', false, false);
- } catch (ex) {
- // ignore exception if unsupported
- }
- }
-}
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/range-bootstrap.js b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/range-bootstrap.js
deleted file mode 100644
index 24aef7ae9..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/range-bootstrap.js
+++ /dev/null
@@ -1,5 +0,0 @@
-goog.require('goog.dom.Range');
-
-window.createFromWindow = goog.dom.Range.createFromWindow;
-window.createFromNodes = goog.dom.Range.createFromNodes;
-window.createCaret = goog.dom.Range.createCaret;
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/range.js b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/range.js
deleted file mode 100644
index f323cf9b6..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/range.js
+++ /dev/null
@@ -1,6184 +0,0 @@
-var COMPILED = false;
-var goog = goog || {};
-goog.global = this;
-goog.DEBUG = true;
-goog.LOCALE = "en";
-goog.evalWorksForGlobals_ = null;
-goog.provide = function(name) {
- if(!COMPILED) {
- if(goog.getObjectByName(name) && !goog.implicitNamespaces_[name]) {
- throw Error('Namespace "' + name + '" already declared.');
- }
- var namespace = name;
- while(namespace = namespace.substring(0, namespace.lastIndexOf("."))) {
- goog.implicitNamespaces_[namespace] = true
- }
- }
- goog.exportPath_(name)
-};
-if(!COMPILED) {
- goog.implicitNamespaces_ = {}
-}
-goog.exportPath_ = function(name, opt_object, opt_objectToExportTo) {
- var parts = name.split(".");
- var cur = opt_objectToExportTo || goog.global;
- if(!(parts[0] in cur) && cur.execScript) {
- cur.execScript("var " + parts[0])
- }
- for(var part;parts.length && (part = parts.shift());) {
- if(!parts.length && goog.isDef(opt_object)) {
- cur[part] = opt_object
- }else {
- if(cur[part]) {
- cur = cur[part]
- }else {
- cur = cur[part] = {}
- }
- }
- }
-};
-goog.getObjectByName = function(name, opt_obj) {
- var parts = name.split(".");
- var cur = opt_obj || goog.global;
- for(var part;part = parts.shift();) {
- if(cur[part]) {
- cur = cur[part]
- }else {
- return null
- }
- }
- return cur
-};
-goog.globalize = function(obj, opt_global) {
- var global = opt_global || goog.global;
- for(var x in obj) {
- global[x] = obj[x]
- }
-};
-goog.addDependency = function(relPath, provides, requires) {
- if(!COMPILED) {
- var provide, require;
- var path = relPath.replace(/\\/g, "/");
- var deps = goog.dependencies_;
- for(var i = 0;provide = provides[i];i++) {
- deps.nameToPath[provide] = path;
- if(!(path in deps.pathToNames)) {
- deps.pathToNames[path] = {}
- }
- deps.pathToNames[path][provide] = true
- }
- for(var j = 0;require = requires[j];j++) {
- if(!(path in deps.requires)) {
- deps.requires[path] = {}
- }
- deps.requires[path][require] = true
- }
- }
-};
-goog.require = function(rule) {
- if(!COMPILED) {
- if(goog.getObjectByName(rule)) {
- return
- }
- var path = goog.getPathFromDeps_(rule);
- if(path) {
- goog.included_[path] = true;
- goog.writeScripts_()
- }else {
- var errorMessage = "goog.require could not find: " + rule;
- if(goog.global.console) {
- goog.global.console["error"](errorMessage)
- }
- throw Error(errorMessage);
- }
- }
-};
-goog.basePath = "";
-goog.global.CLOSURE_BASE_PATH;
-goog.nullFunction = function() {
-};
-goog.identityFunction = function(var_args) {
- return arguments[0]
-};
-goog.abstractMethod = function() {
- throw Error("unimplemented abstract method");
-};
-goog.addSingletonGetter = function(ctor) {
- ctor.getInstance = function() {
- return ctor.instance_ || (ctor.instance_ = new ctor)
- }
-};
-if(!COMPILED) {
- goog.included_ = {};
- goog.dependencies_ = {pathToNames:{}, nameToPath:{}, requires:{}, visited:{}, written:{}};
- goog.inHtmlDocument_ = function() {
- var doc = goog.global.document;
- return typeof doc != "undefined" && "write" in doc
- };
- goog.findBasePath_ = function() {
- if(!goog.inHtmlDocument_()) {
- return
- }
- var doc = goog.global.document;
- if(goog.global.CLOSURE_BASE_PATH) {
- goog.basePath = goog.global.CLOSURE_BASE_PATH;
- return
- }
- var scripts = doc.getElementsByTagName("script");
- for(var i = scripts.length - 1;i >= 0;--i) {
- var src = scripts[i].src;
- var l = src.length;
- if(src.substr(l - 7) == "base.js") {
- goog.basePath = src.substr(0, l - 7);
- return
- }
- }
- };
- goog.writeScriptTag_ = function(src) {
- if(goog.inHtmlDocument_() && !goog.dependencies_.written[src]) {
- goog.dependencies_.written[src] = true;
- var doc = goog.global.document;
- doc.write('<script type="text/javascript" src="' + src + '"></' + "script>")
- }
- };
- goog.writeScripts_ = function() {
- var scripts = [];
- var seenScript = {};
- var deps = goog.dependencies_;
- function visitNode(path) {
- if(path in deps.written) {
- return
- }
- if(path in deps.visited) {
- if(!(path in seenScript)) {
- seenScript[path] = true;
- scripts.push(path)
- }
- return
- }
- deps.visited[path] = true;
- if(path in deps.requires) {
- for(var requireName in deps.requires[path]) {
- if(requireName in deps.nameToPath) {
- visitNode(deps.nameToPath[requireName])
- }else {
- if(!goog.getObjectByName(requireName)) {
- throw Error("Undefined nameToPath for " + requireName);
- }
- }
- }
- }
- if(!(path in seenScript)) {
- seenScript[path] = true;
- scripts.push(path)
- }
- }
- for(var path in goog.included_) {
- if(!deps.written[path]) {
- visitNode(path)
- }
- }
- for(var i = 0;i < scripts.length;i++) {
- if(scripts[i]) {
- goog.writeScriptTag_(goog.basePath + scripts[i])
- }else {
- throw Error("Undefined script input");
- }
- }
- };
- goog.getPathFromDeps_ = function(rule) {
- if(rule in goog.dependencies_.nameToPath) {
- return goog.dependencies_.nameToPath[rule]
- }else {
- return null
- }
- };
- goog.findBasePath_();
-}
-goog.typeOf = function(value) {
- var s = typeof value;
- if(s == "object") {
- if(value) {
- if(value instanceof Array || !(value instanceof Object) && Object.prototype.toString.call(value) == "[object Array]" || typeof value.length == "number" && typeof value.splice != "undefined" && typeof value.propertyIsEnumerable != "undefined" && !value.propertyIsEnumerable("splice")) {
- return"array"
- }
- if(!(value instanceof Object) && (Object.prototype.toString.call(value) == "[object Function]" || typeof value.call != "undefined" && typeof value.propertyIsEnumerable != "undefined" && !value.propertyIsEnumerable("call"))) {
- return"function"
- }
- }else {
- return"null"
- }
- }else {
- if(s == "function" && typeof value.call == "undefined") {
- return"object"
- }
- }
- return s
-};
-goog.propertyIsEnumerableCustom_ = function(object, propName) {
- if(propName in object) {
- for(var key in object) {
- if(key == propName && Object.prototype.hasOwnProperty.call(object, propName)) {
- return true
- }
- }
- }
- return false
-};
-goog.propertyIsEnumerable_ = function(object, propName) {
- if(object instanceof Object) {
- return Object.prototype.propertyIsEnumerable.call(object, propName)
- }else {
- return goog.propertyIsEnumerableCustom_(object, propName)
- }
-};
-goog.isDef = function(val) {
- return val !== undefined
-};
-goog.isNull = function(val) {
- return val === null
-};
-goog.isDefAndNotNull = function(val) {
- return val != null
-};
-goog.isArray = function(val) {
- return goog.typeOf(val) == "array"
-};
-goog.isArrayLike = function(val) {
- var type = goog.typeOf(val);
- return type == "array" || type == "object" && typeof val.length == "number"
-};
-goog.isDateLike = function(val) {
- return goog.isObject(val) && typeof val.getFullYear == "function"
-};
-goog.isString = function(val) {
- return typeof val == "string"
-};
-goog.isBoolean = function(val) {
- return typeof val == "boolean"
-};
-goog.isNumber = function(val) {
- return typeof val == "number"
-};
-goog.isFunction = function(val) {
- return goog.typeOf(val) == "function"
-};
-goog.isObject = function(val) {
- var type = goog.typeOf(val);
- return type == "object" || type == "array" || type == "function"
-};
-goog.getUid = function(obj) {
- return obj[goog.UID_PROPERTY_] || (obj[goog.UID_PROPERTY_] = ++goog.uidCounter_)
-};
-goog.removeUid = function(obj) {
- if("removeAttribute" in obj) {
- obj.removeAttribute(goog.UID_PROPERTY_)
- }
- try {
- delete obj[goog.UID_PROPERTY_]
- }catch(ex) {
- }
-};
-goog.UID_PROPERTY_ = "closure_uid_" + Math.floor(Math.random() * 2147483648).toString(36);
-goog.uidCounter_ = 0;
-goog.getHashCode = goog.getUid;
-goog.removeHashCode = goog.removeUid;
-goog.cloneObject = function(obj) {
- var type = goog.typeOf(obj);
- if(type == "object" || type == "array") {
- if(obj.clone) {
- return obj.clone()
- }
- var clone = type == "array" ? [] : {};
- for(var key in obj) {
- clone[key] = goog.cloneObject(obj[key])
- }
- return clone
- }
- return obj
-};
-Object.prototype.clone;
-goog.bind = function(fn, selfObj, var_args) {
- var context = selfObj || goog.global;
- if(arguments.length > 2) {
- var boundArgs = Array.prototype.slice.call(arguments, 2);
- return function() {
- var newArgs = Array.prototype.slice.call(arguments);
- Array.prototype.unshift.apply(newArgs, boundArgs);
- return fn.apply(context, newArgs)
- }
- }else {
- return function() {
- return fn.apply(context, arguments)
- }
- }
-};
-goog.partial = function(fn, var_args) {
- var args = Array.prototype.slice.call(arguments, 1);
- return function() {
- var newArgs = Array.prototype.slice.call(arguments);
- newArgs.unshift.apply(newArgs, args);
- return fn.apply(this, newArgs)
- }
-};
-goog.mixin = function(target, source) {
- for(var x in source) {
- target[x] = source[x]
- }
-};
-goog.now = Date.now || function() {
- return+new Date
-};
-goog.globalEval = function(script) {
- if(goog.global.execScript) {
- goog.global.execScript(script, "JavaScript")
- }else {
- if(goog.global.eval) {
- if(goog.evalWorksForGlobals_ == null) {
- goog.global.eval("var _et_ = 1;");
- if(typeof goog.global["_et_"] != "undefined") {
- delete goog.global["_et_"];
- goog.evalWorksForGlobals_ = true
- }else {
- goog.evalWorksForGlobals_ = false
- }
- }
- if(goog.evalWorksForGlobals_) {
- goog.global.eval(script)
- }else {
- var doc = goog.global.document;
- var scriptElt = doc.createElement("script");
- scriptElt.type = "text/javascript";
- scriptElt.defer = false;
- scriptElt.appendChild(doc.createTextNode(script));
- doc.body.appendChild(scriptElt);
- doc.body.removeChild(scriptElt)
- }
- }else {
- throw Error("goog.globalEval not available");
- }
- }
-};
-goog.typedef = true;
-goog.cssNameMapping_;
-goog.getCssName = function(className, opt_modifier) {
- var cssName = className + (opt_modifier ? "-" + opt_modifier : "");
- return goog.cssNameMapping_ && cssName in goog.cssNameMapping_ ? goog.cssNameMapping_[cssName] : cssName
-};
-goog.setCssNameMapping = function(mapping) {
- goog.cssNameMapping_ = mapping
-};
-goog.getMsg = function(str, opt_values) {
- var values = opt_values || {};
- for(var key in values) {
- var value = ("" + values[key]).replace(/\$/g, "$$$$");
- str = str.replace(new RegExp("\\{\\$" + key + "\\}", "gi"), value)
- }
- return str
-};
-goog.exportSymbol = function(publicPath, object, opt_objectToExportTo) {
- goog.exportPath_(publicPath, object, opt_objectToExportTo)
-};
-goog.exportProperty = function(object, publicName, symbol) {
- object[publicName] = symbol
-};
-goog.inherits = function(childCtor, parentCtor) {
- function tempCtor() {
- }
- tempCtor.prototype = parentCtor.prototype;
- childCtor.superClass_ = parentCtor.prototype;
- childCtor.prototype = new tempCtor;
- childCtor.prototype.constructor = childCtor
-};
-goog.base = function(me, opt_methodName, var_args) {
- var caller = arguments.callee.caller;
- if(caller.superClass_) {
- return caller.superClass_.constructor.apply(me, Array.prototype.slice.call(arguments, 1))
- }
- var args = Array.prototype.slice.call(arguments, 2);
- var foundCaller = false;
- for(var ctor = me.constructor;ctor;ctor = ctor.superClass_ && ctor.superClass_.constructor) {
- if(ctor.prototype[opt_methodName] === caller) {
- foundCaller = true
- }else {
- if(foundCaller) {
- return ctor.prototype[opt_methodName].apply(me, args)
- }
- }
- }
- if(me[opt_methodName] === caller) {
- return me.constructor.prototype[opt_methodName].apply(me, args)
- }else {
- throw Error("goog.base called from a method of one name " + "to a method of a different name");
- }
-};
-goog.scope = function(fn) {
- fn.call(goog.global)
-};
-goog.provide("goog.debug.Error");
-goog.debug.Error = function(opt_msg) {
- this.stack = (new Error).stack || "";
- if(opt_msg) {
- this.message = String(opt_msg)
- }
-};
-goog.inherits(goog.debug.Error, Error);
-goog.debug.Error.prototype.name = "CustomError";
-goog.provide("goog.string");
-goog.provide("goog.string.Unicode");
-goog.string.Unicode = {NBSP:"\u00a0"};
-goog.string.startsWith = function(str, prefix) {
- return str.lastIndexOf(prefix, 0) == 0
-};
-goog.string.endsWith = function(str, suffix) {
- var l = str.length - suffix.length;
- return l >= 0 && str.indexOf(suffix, l) == l
-};
-goog.string.caseInsensitiveStartsWith = function(str, prefix) {
- return goog.string.caseInsensitiveCompare(prefix, str.substr(0, prefix.length)) == 0
-};
-goog.string.caseInsensitiveEndsWith = function(str, suffix) {
- return goog.string.caseInsensitiveCompare(suffix, str.substr(str.length - suffix.length, suffix.length)) == 0
-};
-goog.string.subs = function(str, var_args) {
- for(var i = 1;i < arguments.length;i++) {
- var replacement = String(arguments[i]).replace(/\$/g, "$$$$");
- str = str.replace(/\%s/, replacement)
- }
- return str
-};
-goog.string.collapseWhitespace = function(str) {
- return str.replace(/[\s\xa0]+/g, " ").replace(/^\s+|\s+$/g, "")
-};
-goog.string.isEmpty = function(str) {
- return/^[\s\xa0]*$/.test(str)
-};
-goog.string.isEmptySafe = function(str) {
- return goog.string.isEmpty(goog.string.makeSafe(str))
-};
-goog.string.isBreakingWhitespace = function(str) {
- return!/[^\t\n\r ]/.test(str)
-};
-goog.string.isAlpha = function(str) {
- return!/[^a-zA-Z]/.test(str)
-};
-goog.string.isNumeric = function(str) {
- return!/[^0-9]/.test(str)
-};
-goog.string.isAlphaNumeric = function(str) {
- return!/[^a-zA-Z0-9]/.test(str)
-};
-goog.string.isSpace = function(ch) {
- return ch == " "
-};
-goog.string.isUnicodeChar = function(ch) {
- return ch.length == 1 && ch >= " " && ch <= "~" || ch >= "\u0080" && ch <= "\ufffd"
-};
-goog.string.stripNewlines = function(str) {
- return str.replace(/(\r\n|\r|\n)+/g, " ")
-};
-goog.string.canonicalizeNewlines = function(str) {
- return str.replace(/(\r\n|\r|\n)/g, "\n")
-};
-goog.string.normalizeWhitespace = function(str) {
- return str.replace(/\xa0|\s/g, " ")
-};
-goog.string.normalizeSpaces = function(str) {
- return str.replace(/\xa0|[ \t]+/g, " ")
-};
-goog.string.trim = function(str) {
- return str.replace(/^[\s\xa0]+|[\s\xa0]+$/g, "")
-};
-goog.string.trimLeft = function(str) {
- return str.replace(/^[\s\xa0]+/, "")
-};
-goog.string.trimRight = function(str) {
- return str.replace(/[\s\xa0]+$/, "")
-};
-goog.string.caseInsensitiveCompare = function(str1, str2) {
- var test1 = String(str1).toLowerCase();
- var test2 = String(str2).toLowerCase();
- if(test1 < test2) {
- return-1
- }else {
- if(test1 == test2) {
- return 0
- }else {
- return 1
- }
- }
-};
-goog.string.numerateCompareRegExp_ = /(\.\d+)|(\d+)|(\D+)/g;
-goog.string.numerateCompare = function(str1, str2) {
- if(str1 == str2) {
- return 0
- }
- if(!str1) {
- return-1
- }
- if(!str2) {
- return 1
- }
- var tokens1 = str1.toLowerCase().match(goog.string.numerateCompareRegExp_);
- var tokens2 = str2.toLowerCase().match(goog.string.numerateCompareRegExp_);
- var count = Math.min(tokens1.length, tokens2.length);
- for(var i = 0;i < count;i++) {
- var a = tokens1[i];
- var b = tokens2[i];
- if(a != b) {
- var num1 = parseInt(a, 10);
- if(!isNaN(num1)) {
- var num2 = parseInt(b, 10);
- if(!isNaN(num2) && num1 - num2) {
- return num1 - num2
- }
- }
- return a < b ? -1 : 1
- }
- }
- if(tokens1.length != tokens2.length) {
- return tokens1.length - tokens2.length
- }
- return str1 < str2 ? -1 : 1
-};
-goog.string.encodeUriRegExp_ = /^[a-zA-Z0-9\-_.!~*'()]*$/;
-goog.string.urlEncode = function(str) {
- str = String(str);
- if(!goog.string.encodeUriRegExp_.test(str)) {
- return encodeURIComponent(str)
- }
- return str
-};
-goog.string.urlDecode = function(str) {
- return decodeURIComponent(str.replace(/\+/g, " "))
-};
-goog.string.newLineToBr = function(str, opt_xml) {
- return str.replace(/(\r\n|\r|\n)/g, opt_xml ? "<br />" : "<br>")
-};
-goog.string.htmlEscape = function(str, opt_isLikelyToContainHtmlChars) {
- if(opt_isLikelyToContainHtmlChars) {
- return str.replace(goog.string.amperRe_, "&amp;").replace(goog.string.ltRe_, "&lt;").replace(goog.string.gtRe_, "&gt;").replace(goog.string.quotRe_, "&quot;")
- }else {
- if(!goog.string.allRe_.test(str)) {
- return str
- }
- if(str.indexOf("&") != -1) {
- str = str.replace(goog.string.amperRe_, "&amp;")
- }
- if(str.indexOf("<") != -1) {
- str = str.replace(goog.string.ltRe_, "&lt;")
- }
- if(str.indexOf(">") != -1) {
- str = str.replace(goog.string.gtRe_, "&gt;")
- }
- if(str.indexOf('"') != -1) {
- str = str.replace(goog.string.quotRe_, "&quot;")
- }
- return str
- }
-};
-goog.string.amperRe_ = /&/g;
-goog.string.ltRe_ = /</g;
-goog.string.gtRe_ = />/g;
-goog.string.quotRe_ = /\"/g;
-goog.string.allRe_ = /[&<>\"]/;
-goog.string.unescapeEntities = function(str) {
- if(goog.string.contains(str, "&")) {
- if("document" in goog.global && !goog.string.contains(str, "<")) {
- return goog.string.unescapeEntitiesUsingDom_(str)
- }else {
- return goog.string.unescapePureXmlEntities_(str)
- }
- }
- return str
-};
-goog.string.unescapeEntitiesUsingDom_ = function(str) {
- var el = goog.global["document"]["createElement"]("a");
- el["innerHTML"] = str;
- if(el[goog.string.NORMALIZE_FN_]) {
- el[goog.string.NORMALIZE_FN_]()
- }
- str = el["firstChild"]["nodeValue"];
- el["innerHTML"] = "";
- return str
-};
-goog.string.unescapePureXmlEntities_ = function(str) {
- return str.replace(/&([^;]+);/g, function(s, entity) {
- switch(entity) {
- case "amp":
- return"&";
- case "lt":
- return"<";
- case "gt":
- return">";
- case "quot":
- return'"';
- default:
- if(entity.charAt(0) == "#") {
- var n = Number("0" + entity.substr(1));
- if(!isNaN(n)) {
- return String.fromCharCode(n)
- }
- }
- return s
- }
- })
-};
-goog.string.NORMALIZE_FN_ = "normalize";
-goog.string.whitespaceEscape = function(str, opt_xml) {
- return goog.string.newLineToBr(str.replace(/ /g, " &#160;"), opt_xml)
-};
-goog.string.stripQuotes = function(str, quoteChars) {
- var length = quoteChars.length;
- for(var i = 0;i < length;i++) {
- var quoteChar = length == 1 ? quoteChars : quoteChars.charAt(i);
- if(str.charAt(0) == quoteChar && str.charAt(str.length - 1) == quoteChar) {
- return str.substring(1, str.length - 1)
- }
- }
- return str
-};
-goog.string.truncate = function(str, chars, opt_protectEscapedCharacters) {
- if(opt_protectEscapedCharacters) {
- str = goog.string.unescapeEntities(str)
- }
- if(str.length > chars) {
- str = str.substring(0, chars - 3) + "..."
- }
- if(opt_protectEscapedCharacters) {
- str = goog.string.htmlEscape(str)
- }
- return str
-};
-goog.string.truncateMiddle = function(str, chars, opt_protectEscapedCharacters) {
- if(opt_protectEscapedCharacters) {
- str = goog.string.unescapeEntities(str)
- }
- if(str.length > chars) {
- var half = Math.floor(chars / 2);
- var endPos = str.length - half;
- half += chars % 2;
- str = str.substring(0, half) + "..." + str.substring(endPos)
- }
- if(opt_protectEscapedCharacters) {
- str = goog.string.htmlEscape(str)
- }
- return str
-};
-goog.string.specialEscapeChars_ = {"\u0000":"\\0", "\u0008":"\\b", "\u000c":"\\f", "\n":"\\n", "\r":"\\r", "\t":"\\t", "\u000b":"\\x0B", '"':'\\"', "\\":"\\\\"};
-goog.string.jsEscapeCache_ = {"'":"\\'"};
-goog.string.quote = function(s) {
- s = String(s);
- if(s.quote) {
- return s.quote()
- }else {
- var sb = ['"'];
- for(var i = 0;i < s.length;i++) {
- var ch = s.charAt(i);
- var cc = ch.charCodeAt(0);
- sb[i + 1] = goog.string.specialEscapeChars_[ch] || (cc > 31 && cc < 127 ? ch : goog.string.escapeChar(ch))
- }
- sb.push('"');
- return sb.join("")
- }
-};
-goog.string.escapeString = function(str) {
- var sb = [];
- for(var i = 0;i < str.length;i++) {
- sb[i] = goog.string.escapeChar(str.charAt(i))
- }
- return sb.join("")
-};
-goog.string.escapeChar = function(c) {
- if(c in goog.string.jsEscapeCache_) {
- return goog.string.jsEscapeCache_[c]
- }
- if(c in goog.string.specialEscapeChars_) {
- return goog.string.jsEscapeCache_[c] = goog.string.specialEscapeChars_[c]
- }
- var rv = c;
- var cc = c.charCodeAt(0);
- if(cc > 31 && cc < 127) {
- rv = c
- }else {
- if(cc < 256) {
- rv = "\\x";
- if(cc < 16 || cc > 256) {
- rv += "0"
- }
- }else {
- rv = "\\u";
- if(cc < 4096) {
- rv += "0"
- }
- }
- rv += cc.toString(16).toUpperCase()
- }
- return goog.string.jsEscapeCache_[c] = rv
-};
-goog.string.toMap = function(s) {
- var rv = {};
- for(var i = 0;i < s.length;i++) {
- rv[s.charAt(i)] = true
- }
- return rv
-};
-goog.string.contains = function(s, ss) {
- return s.indexOf(ss) != -1
-};
-goog.string.removeAt = function(s, index, stringLength) {
- var resultStr = s;
- if(index >= 0 && index < s.length && stringLength > 0) {
- resultStr = s.substr(0, index) + s.substr(index + stringLength, s.length - index - stringLength)
- }
- return resultStr
-};
-goog.string.remove = function(s, ss) {
- var re = new RegExp(goog.string.regExpEscape(ss), "");
- return s.replace(re, "")
-};
-goog.string.removeAll = function(s, ss) {
- var re = new RegExp(goog.string.regExpEscape(ss), "g");
- return s.replace(re, "")
-};
-goog.string.regExpEscape = function(s) {
- return String(s).replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, "\\$1").replace(/\x08/g, "\\x08")
-};
-goog.string.repeat = function(string, length) {
- return(new Array(length + 1)).join(string)
-};
-goog.string.padNumber = function(num, length, opt_precision) {
- var s = goog.isDef(opt_precision) ? num.toFixed(opt_precision) : String(num);
- var index = s.indexOf(".");
- if(index == -1) {
- index = s.length
- }
- return goog.string.repeat("0", Math.max(0, length - index)) + s
-};
-goog.string.makeSafe = function(obj) {
- return obj == null ? "" : String(obj)
-};
-goog.string.buildString = function(var_args) {
- return Array.prototype.join.call(arguments, "")
-};
-goog.string.getRandomString = function() {
- return Math.floor(Math.random() * 2147483648).toString(36) + (Math.floor(Math.random() * 2147483648) ^ goog.now()).toString(36)
-};
-goog.string.compareVersions = function(version1, version2) {
- var order = 0;
- var v1Subs = goog.string.trim(String(version1)).split(".");
- var v2Subs = goog.string.trim(String(version2)).split(".");
- var subCount = Math.max(v1Subs.length, v2Subs.length);
- for(var subIdx = 0;order == 0 && subIdx < subCount;subIdx++) {
- var v1Sub = v1Subs[subIdx] || "";
- var v2Sub = v2Subs[subIdx] || "";
- var v1CompParser = new RegExp("(\\d*)(\\D*)", "g");
- var v2CompParser = new RegExp("(\\d*)(\\D*)", "g");
- do {
- var v1Comp = v1CompParser.exec(v1Sub) || ["", "", ""];
- var v2Comp = v2CompParser.exec(v2Sub) || ["", "", ""];
- if(v1Comp[0].length == 0 && v2Comp[0].length == 0) {
- break
- }
- var v1CompNum = v1Comp[1].length == 0 ? 0 : parseInt(v1Comp[1], 10);
- var v2CompNum = v2Comp[1].length == 0 ? 0 : parseInt(v2Comp[1], 10);
- order = goog.string.compareElements_(v1CompNum, v2CompNum) || goog.string.compareElements_(v1Comp[2].length == 0, v2Comp[2].length == 0) || goog.string.compareElements_(v1Comp[2], v2Comp[2])
- }while(order == 0)
- }
- return order
-};
-goog.string.compareElements_ = function(left, right) {
- if(left < right) {
- return-1
- }else {
- if(left > right) {
- return 1
- }
- }
- return 0
-};
-goog.string.HASHCODE_MAX_ = 4294967296;
-goog.string.hashCode = function(str) {
- var result = 0;
- for(var i = 0;i < str.length;++i) {
- result = 31 * result + str.charCodeAt(i);
- result %= goog.string.HASHCODE_MAX_
- }
- return result
-};
-goog.string.uniqueStringCounter_ = Math.random() * 2147483648 | 0;
-goog.string.createUniqueString = function() {
- return"goog_" + goog.string.uniqueStringCounter_++
-};
-goog.string.toNumber = function(str) {
- var num = Number(str);
- if(num == 0 && goog.string.isEmpty(str)) {
- return NaN
- }
- return num
-};
-goog.provide("goog.asserts");
-goog.provide("goog.asserts.AssertionError");
-goog.require("goog.debug.Error");
-goog.require("goog.string");
-goog.asserts.ENABLE_ASSERTS = goog.DEBUG;
-goog.asserts.AssertionError = function(messagePattern, messageArgs) {
- messageArgs.unshift(messagePattern);
- goog.debug.Error.call(this, goog.string.subs.apply(null, messageArgs));
- messageArgs.shift();
- this.messagePattern = messagePattern
-};
-goog.inherits(goog.asserts.AssertionError, goog.debug.Error);
-goog.asserts.AssertionError.prototype.name = "AssertionError";
-goog.asserts.doAssertFailure_ = function(defaultMessage, defaultArgs, givenMessage, givenArgs) {
- var message = "Assertion failed";
- if(givenMessage) {
- message += ": " + givenMessage;
- var args = givenArgs
- }else {
- if(defaultMessage) {
- message += ": " + defaultMessage;
- args = defaultArgs
- }
- }
- throw new goog.asserts.AssertionError("" + message, args || []);
-};
-goog.asserts.assert = function(condition, opt_message, var_args) {
- if(goog.asserts.ENABLE_ASSERTS && !condition) {
- goog.asserts.doAssertFailure_("", null, opt_message, Array.prototype.slice.call(arguments, 2))
- }
- return condition
-};
-goog.asserts.fail = function(opt_message, var_args) {
- if(goog.asserts.ENABLE_ASSERTS) {
- throw new goog.asserts.AssertionError("Failure" + (opt_message ? ": " + opt_message : ""), Array.prototype.slice.call(arguments, 1));
- }
-};
-goog.asserts.assertNumber = function(value, opt_message, var_args) {
- if(goog.asserts.ENABLE_ASSERTS && !goog.isNumber(value)) {
- goog.asserts.doAssertFailure_("Expected number but got %s: %s.", [goog.typeOf(value), value], opt_message, Array.prototype.slice.call(arguments, 2))
- }
- return value
-};
-goog.asserts.assertString = function(value, opt_message, var_args) {
- if(goog.asserts.ENABLE_ASSERTS && !goog.isString(value)) {
- goog.asserts.doAssertFailure_("Expected string but got %s: %s.", [goog.typeOf(value), value], opt_message, Array.prototype.slice.call(arguments, 2))
- }
- return value
-};
-goog.asserts.assertFunction = function(value, opt_message, var_args) {
- if(goog.asserts.ENABLE_ASSERTS && !goog.isFunction(value)) {
- goog.asserts.doAssertFailure_("Expected function but got %s: %s.", [goog.typeOf(value), value], opt_message, Array.prototype.slice.call(arguments, 2))
- }
- return value
-};
-goog.asserts.assertObject = function(value, opt_message, var_args) {
- if(goog.asserts.ENABLE_ASSERTS && !goog.isObject(value)) {
- goog.asserts.doAssertFailure_("Expected object but got %s: %s.", [goog.typeOf(value), value], opt_message, Array.prototype.slice.call(arguments, 2))
- }
- return value
-};
-goog.asserts.assertArray = function(value, opt_message, var_args) {
- if(goog.asserts.ENABLE_ASSERTS && !goog.isArray(value)) {
- goog.asserts.doAssertFailure_("Expected array but got %s: %s.", [goog.typeOf(value), value], opt_message, Array.prototype.slice.call(arguments, 2))
- }
- return value
-};
-goog.asserts.assertBoolean = function(value, opt_message, var_args) {
- if(goog.asserts.ENABLE_ASSERTS && !goog.isBoolean(value)) {
- goog.asserts.doAssertFailure_("Expected boolean but got %s: %s.", [goog.typeOf(value), value], opt_message, Array.prototype.slice.call(arguments, 2))
- }
- return value
-};
-goog.asserts.assertInstanceof = function(value, type, opt_message, var_args) {
- if(goog.asserts.ENABLE_ASSERTS && !(value instanceof type)) {
- goog.asserts.doAssertFailure_("instanceof check failed.", null, opt_message, Array.prototype.slice.call(arguments, 3))
- }
-};
-goog.provide("goog.array");
-goog.require("goog.asserts");
-goog.array.ArrayLike;
-goog.array.peek = function(array) {
- return array[array.length - 1]
-};
-goog.array.ARRAY_PROTOTYPE_ = Array.prototype;
-goog.array.indexOf = goog.array.ARRAY_PROTOTYPE_.indexOf ? function(arr, obj, opt_fromIndex) {
- goog.asserts.assert(arr.length != null);
- return goog.array.ARRAY_PROTOTYPE_.indexOf.call(arr, obj, opt_fromIndex)
-} : function(arr, obj, opt_fromIndex) {
- var fromIndex = opt_fromIndex == null ? 0 : opt_fromIndex < 0 ? Math.max(0, arr.length + opt_fromIndex) : opt_fromIndex;
- if(goog.isString(arr)) {
- if(!goog.isString(obj) || obj.length != 1) {
- return-1
- }
- return arr.indexOf(obj, fromIndex)
- }
- for(var i = fromIndex;i < arr.length;i++) {
- if(i in arr && arr[i] === obj) {
- return i
- }
- }
- return-1
-};
-goog.array.lastIndexOf = goog.array.ARRAY_PROTOTYPE_.lastIndexOf ? function(arr, obj, opt_fromIndex) {
- goog.asserts.assert(arr.length != null);
- var fromIndex = opt_fromIndex == null ? arr.length - 1 : opt_fromIndex;
- return goog.array.ARRAY_PROTOTYPE_.lastIndexOf.call(arr, obj, fromIndex)
-} : function(arr, obj, opt_fromIndex) {
- var fromIndex = opt_fromIndex == null ? arr.length - 1 : opt_fromIndex;
- if(fromIndex < 0) {
- fromIndex = Math.max(0, arr.length + fromIndex)
- }
- if(goog.isString(arr)) {
- if(!goog.isString(obj) || obj.length != 1) {
- return-1
- }
- return arr.lastIndexOf(obj, fromIndex)
- }
- for(var i = fromIndex;i >= 0;i--) {
- if(i in arr && arr[i] === obj) {
- return i
- }
- }
- return-1
-};
-goog.array.forEach = goog.array.ARRAY_PROTOTYPE_.forEach ? function(arr, f, opt_obj) {
- goog.asserts.assert(arr.length != null);
- goog.array.ARRAY_PROTOTYPE_.forEach.call(arr, f, opt_obj)
-} : function(arr, f, opt_obj) {
- var l = arr.length;
- var arr2 = goog.isString(arr) ? arr.split("") : arr;
- for(var i = 0;i < l;i++) {
- if(i in arr2) {
- f.call(opt_obj, arr2[i], i, arr)
- }
- }
-};
-goog.array.forEachRight = function(arr, f, opt_obj) {
- var l = arr.length;
- var arr2 = goog.isString(arr) ? arr.split("") : arr;
- for(var i = l - 1;i >= 0;--i) {
- if(i in arr2) {
- f.call(opt_obj, arr2[i], i, arr)
- }
- }
-};
-goog.array.filter = goog.array.ARRAY_PROTOTYPE_.filter ? function(arr, f, opt_obj) {
- goog.asserts.assert(arr.length != null);
- return goog.array.ARRAY_PROTOTYPE_.filter.call(arr, f, opt_obj)
-} : function(arr, f, opt_obj) {
- var l = arr.length;
- var res = [];
- var resLength = 0;
- var arr2 = goog.isString(arr) ? arr.split("") : arr;
- for(var i = 0;i < l;i++) {
- if(i in arr2) {
- var val = arr2[i];
- if(f.call(opt_obj, val, i, arr)) {
- res[resLength++] = val
- }
- }
- }
- return res
-};
-goog.array.map = goog.array.ARRAY_PROTOTYPE_.map ? function(arr, f, opt_obj) {
- goog.asserts.assert(arr.length != null);
- return goog.array.ARRAY_PROTOTYPE_.map.call(arr, f, opt_obj)
-} : function(arr, f, opt_obj) {
- var l = arr.length;
- var res = new Array(l);
- var arr2 = goog.isString(arr) ? arr.split("") : arr;
- for(var i = 0;i < l;i++) {
- if(i in arr2) {
- res[i] = f.call(opt_obj, arr2[i], i, arr)
- }
- }
- return res
-};
-goog.array.reduce = function(arr, f, val, opt_obj) {
- if(arr.reduce) {
- if(opt_obj) {
- return arr.reduce(goog.bind(f, opt_obj), val)
- }else {
- return arr.reduce(f, val)
- }
- }
- var rval = val;
- goog.array.forEach(arr, function(val, index) {
- rval = f.call(opt_obj, rval, val, index, arr)
- });
- return rval
-};
-goog.array.reduceRight = function(arr, f, val, opt_obj) {
- if(arr.reduceRight) {
- if(opt_obj) {
- return arr.reduceRight(goog.bind(f, opt_obj), val)
- }else {
- return arr.reduceRight(f, val)
- }
- }
- var rval = val;
- goog.array.forEachRight(arr, function(val, index) {
- rval = f.call(opt_obj, rval, val, index, arr)
- });
- return rval
-};
-goog.array.some = goog.array.ARRAY_PROTOTYPE_.some ? function(arr, f, opt_obj) {
- goog.asserts.assert(arr.length != null);
- return goog.array.ARRAY_PROTOTYPE_.some.call(arr, f, opt_obj)
-} : function(arr, f, opt_obj) {
- var l = arr.length;
- var arr2 = goog.isString(arr) ? arr.split("") : arr;
- for(var i = 0;i < l;i++) {
- if(i in arr2 && f.call(opt_obj, arr2[i], i, arr)) {
- return true
- }
- }
- return false
-};
-goog.array.every = goog.array.ARRAY_PROTOTYPE_.every ? function(arr, f, opt_obj) {
- goog.asserts.assert(arr.length != null);
- return goog.array.ARRAY_PROTOTYPE_.every.call(arr, f, opt_obj)
-} : function(arr, f, opt_obj) {
- var l = arr.length;
- var arr2 = goog.isString(arr) ? arr.split("") : arr;
- for(var i = 0;i < l;i++) {
- if(i in arr2 && !f.call(opt_obj, arr2[i], i, arr)) {
- return false
- }
- }
- return true
-};
-goog.array.find = function(arr, f, opt_obj) {
- var i = goog.array.findIndex(arr, f, opt_obj);
- return i < 0 ? null : goog.isString(arr) ? arr.charAt(i) : arr[i]
-};
-goog.array.findIndex = function(arr, f, opt_obj) {
- var l = arr.length;
- var arr2 = goog.isString(arr) ? arr.split("") : arr;
- for(var i = 0;i < l;i++) {
- if(i in arr2 && f.call(opt_obj, arr2[i], i, arr)) {
- return i
- }
- }
- return-1
-};
-goog.array.findRight = function(arr, f, opt_obj) {
- var i = goog.array.findIndexRight(arr, f, opt_obj);
- return i < 0 ? null : goog.isString(arr) ? arr.charAt(i) : arr[i]
-};
-goog.array.findIndexRight = function(arr, f, opt_obj) {
- var l = arr.length;
- var arr2 = goog.isString(arr) ? arr.split("") : arr;
- for(var i = l - 1;i >= 0;i--) {
- if(i in arr2 && f.call(opt_obj, arr2[i], i, arr)) {
- return i
- }
- }
- return-1
-};
-goog.array.contains = function(arr, obj) {
- return goog.array.indexOf(arr, obj) >= 0
-};
-goog.array.isEmpty = function(arr) {
- return arr.length == 0
-};
-goog.array.clear = function(arr) {
- if(!goog.isArray(arr)) {
- for(var i = arr.length - 1;i >= 0;i--) {
- delete arr[i]
- }
- }
- arr.length = 0
-};
-goog.array.insert = function(arr, obj) {
- if(!goog.array.contains(arr, obj)) {
- arr.push(obj)
- }
-};
-goog.array.insertAt = function(arr, obj, opt_i) {
- goog.array.splice(arr, opt_i, 0, obj)
-};
-goog.array.insertArrayAt = function(arr, elementsToAdd, opt_i) {
- goog.partial(goog.array.splice, arr, opt_i, 0).apply(null, elementsToAdd)
-};
-goog.array.insertBefore = function(arr, obj, opt_obj2) {
- var i;
- if(arguments.length == 2 || (i = goog.array.indexOf(arr, opt_obj2)) < 0) {
- arr.push(obj)
- }else {
- goog.array.insertAt(arr, obj, i)
- }
-};
-goog.array.remove = function(arr, obj) {
- var i = goog.array.indexOf(arr, obj);
- var rv;
- if(rv = i >= 0) {
- goog.array.removeAt(arr, i)
- }
- return rv
-};
-goog.array.removeAt = function(arr, i) {
- goog.asserts.assert(arr.length != null);
- return goog.array.ARRAY_PROTOTYPE_.splice.call(arr, i, 1).length == 1
-};
-goog.array.removeIf = function(arr, f, opt_obj) {
- var i = goog.array.findIndex(arr, f, opt_obj);
- if(i >= 0) {
- goog.array.removeAt(arr, i);
- return true
- }
- return false
-};
-goog.array.concat = function(var_args) {
- return goog.array.ARRAY_PROTOTYPE_.concat.apply(goog.array.ARRAY_PROTOTYPE_, arguments)
-};
-goog.array.clone = function(arr) {
- if(goog.isArray(arr)) {
- return goog.array.concat(arr)
- }else {
- var rv = [];
- for(var i = 0, len = arr.length;i < len;i++) {
- rv[i] = arr[i]
- }
- return rv
- }
-};
-goog.array.toArray = function(object) {
- if(goog.isArray(object)) {
- return goog.array.concat(object)
- }
- return goog.array.clone(object)
-};
-goog.array.extend = function(arr1, var_args) {
- for(var i = 1;i < arguments.length;i++) {
- var arr2 = arguments[i];
- var isArrayLike;
- if(goog.isArray(arr2) || (isArrayLike = goog.isArrayLike(arr2)) && arr2.hasOwnProperty("callee")) {
- arr1.push.apply(arr1, arr2)
- }else {
- if(isArrayLike) {
- var len1 = arr1.length;
- var len2 = arr2.length;
- for(var j = 0;j < len2;j++) {
- arr1[len1 + j] = arr2[j]
- }
- }else {
- arr1.push(arr2)
- }
- }
- }
-};
-goog.array.splice = function(arr, index, howMany, var_args) {
- goog.asserts.assert(arr.length != null);
- return goog.array.ARRAY_PROTOTYPE_.splice.apply(arr, goog.array.slice(arguments, 1))
-};
-goog.array.slice = function(arr, start, opt_end) {
- goog.asserts.assert(arr.length != null);
- if(arguments.length <= 2) {
- return goog.array.ARRAY_PROTOTYPE_.slice.call(arr, start)
- }else {
- return goog.array.ARRAY_PROTOTYPE_.slice.call(arr, start, opt_end)
- }
-};
-goog.array.removeDuplicates = function(arr, opt_rv) {
- var rv = opt_rv || arr;
- var seen = {}, cursorInsert = 0, cursorRead = 0;
- while(cursorRead < arr.length) {
- var current = arr[cursorRead++];
- var uid = goog.isObject(current) ? goog.getUid(current) : current;
- if(!Object.prototype.hasOwnProperty.call(seen, uid)) {
- seen[uid] = true;
- rv[cursorInsert++] = current
- }
- }
- rv.length = cursorInsert
-};
-goog.array.binarySearch = function(arr, target, opt_compareFn) {
- return goog.array.binarySearch_(arr, opt_compareFn || goog.array.defaultCompare, false, target)
-};
-goog.array.binarySelect = function(arr, evaluator, opt_obj) {
- return goog.array.binarySearch_(arr, evaluator, true, undefined, opt_obj)
-};
-goog.array.binarySearch_ = function(arr, compareFn, isEvaluator, opt_target, opt_selfObj) {
- var left = 0;
- var right = arr.length;
- var found;
- while(left < right) {
- var middle = left + right >> 1;
- var compareResult;
- if(isEvaluator) {
- compareResult = compareFn.call(opt_selfObj, arr[middle], middle, arr)
- }else {
- compareResult = compareFn(opt_target, arr[middle])
- }
- if(compareResult > 0) {
- left = middle + 1
- }else {
- right = middle;
- found = !compareResult
- }
- }
- return found ? left : ~left
-};
-goog.array.sort = function(arr, opt_compareFn) {
- goog.asserts.assert(arr.length != null);
- goog.array.ARRAY_PROTOTYPE_.sort.call(arr, opt_compareFn || goog.array.defaultCompare)
-};
-goog.array.stableSort = function(arr, opt_compareFn) {
- for(var i = 0;i < arr.length;i++) {
- arr[i] = {index:i, value:arr[i]}
- }
- var valueCompareFn = opt_compareFn || goog.array.defaultCompare;
- function stableCompareFn(obj1, obj2) {
- return valueCompareFn(obj1.value, obj2.value) || obj1.index - obj2.index
- }
- goog.array.sort(arr, stableCompareFn);
- for(var i = 0;i < arr.length;i++) {
- arr[i] = arr[i].value
- }
-};
-goog.array.sortObjectsByKey = function(arr, key, opt_compareFn) {
- var compare = opt_compareFn || goog.array.defaultCompare;
- goog.array.sort(arr, function(a, b) {
- return compare(a[key], b[key])
- })
-};
-goog.array.equals = function(arr1, arr2, opt_equalsFn) {
- if(!goog.isArrayLike(arr1) || !goog.isArrayLike(arr2) || arr1.length != arr2.length) {
- return false
- }
- var l = arr1.length;
- var equalsFn = opt_equalsFn || goog.array.defaultCompareEquality;
- for(var i = 0;i < l;i++) {
- if(!equalsFn(arr1[i], arr2[i])) {
- return false
- }
- }
- return true
-};
-goog.array.compare = function(arr1, arr2, opt_equalsFn) {
- return goog.array.equals(arr1, arr2, opt_equalsFn)
-};
-goog.array.defaultCompare = function(a, b) {
- return a > b ? 1 : a < b ? -1 : 0
-};
-goog.array.defaultCompareEquality = function(a, b) {
- return a === b
-};
-goog.array.binaryInsert = function(array, value, opt_compareFn) {
- var index = goog.array.binarySearch(array, value, opt_compareFn);
- if(index < 0) {
- goog.array.insertAt(array, value, -(index + 1));
- return true
- }
- return false
-};
-goog.array.binaryRemove = function(array, value, opt_compareFn) {
- var index = goog.array.binarySearch(array, value, opt_compareFn);
- return index >= 0 ? goog.array.removeAt(array, index) : false
-};
-goog.array.bucket = function(array, sorter) {
- var buckets = {};
- for(var i = 0;i < array.length;i++) {
- var value = array[i];
- var key = sorter(value, i, array);
- if(goog.isDef(key)) {
- var bucket = buckets[key] || (buckets[key] = []);
- bucket.push(value)
- }
- }
- return buckets
-};
-goog.array.repeat = function(value, n) {
- var array = [];
- for(var i = 0;i < n;i++) {
- array[i] = value
- }
- return array
-};
-goog.array.flatten = function(var_args) {
- var result = [];
- for(var i = 0;i < arguments.length;i++) {
- var element = arguments[i];
- if(goog.isArray(element)) {
- result.push.apply(result, goog.array.flatten.apply(null, element))
- }else {
- result.push(element)
- }
- }
- return result
-};
-goog.array.rotate = function(array, n) {
- goog.asserts.assert(array.length != null);
- if(array.length) {
- n %= array.length;
- if(n > 0) {
- goog.array.ARRAY_PROTOTYPE_.unshift.apply(array, array.splice(-n, n))
- }else {
- if(n < 0) {
- goog.array.ARRAY_PROTOTYPE_.push.apply(array, array.splice(0, -n))
- }
- }
- }
- return array
-};
-goog.array.zip = function(var_args) {
- if(!arguments.length) {
- return[]
- }
- var result = [];
- for(var i = 0;true;i++) {
- var value = [];
- for(var j = 0;j < arguments.length;j++) {
- var arr = arguments[j];
- if(i >= arr.length) {
- return result
- }
- value.push(arr[i])
- }
- result.push(value)
- }
-};
-goog.provide("goog.userAgent");
-goog.require("goog.string");
-goog.userAgent.ASSUME_IE = false;
-goog.userAgent.ASSUME_GECKO = false;
-goog.userAgent.ASSUME_WEBKIT = false;
-goog.userAgent.ASSUME_MOBILE_WEBKIT = false;
-goog.userAgent.ASSUME_OPERA = false;
-goog.userAgent.BROWSER_KNOWN_ = goog.userAgent.ASSUME_IE || goog.userAgent.ASSUME_GECKO || goog.userAgent.ASSUME_MOBILE_WEBKIT || goog.userAgent.ASSUME_WEBKIT || goog.userAgent.ASSUME_OPERA;
-goog.userAgent.getUserAgentString = function() {
- return goog.global["navigator"] ? goog.global["navigator"].userAgent : null
-};
-goog.userAgent.getNavigator = function() {
- return goog.global["navigator"]
-};
-goog.userAgent.init_ = function() {
- goog.userAgent.detectedOpera_ = false;
- goog.userAgent.detectedIe_ = false;
- goog.userAgent.detectedWebkit_ = false;
- goog.userAgent.detectedMobile_ = false;
- goog.userAgent.detectedGecko_ = false;
- var ua;
- if(!goog.userAgent.BROWSER_KNOWN_ && (ua = goog.userAgent.getUserAgentString())) {
- var navigator = goog.userAgent.getNavigator();
- goog.userAgent.detectedOpera_ = ua.indexOf("Opera") == 0;
- goog.userAgent.detectedIe_ = !goog.userAgent.detectedOpera_ && ua.indexOf("MSIE") != -1;
- goog.userAgent.detectedWebkit_ = !goog.userAgent.detectedOpera_ && ua.indexOf("WebKit") != -1;
- goog.userAgent.detectedMobile_ = goog.userAgent.detectedWebkit_ && ua.indexOf("Mobile") != -1;
- goog.userAgent.detectedGecko_ = !goog.userAgent.detectedOpera_ && !goog.userAgent.detectedWebkit_ && navigator.product == "Gecko"
- }
-};
-if(!goog.userAgent.BROWSER_KNOWN_) {
- goog.userAgent.init_()
-}
-goog.userAgent.OPERA = goog.userAgent.BROWSER_KNOWN_ ? goog.userAgent.ASSUME_OPERA : goog.userAgent.detectedOpera_;
-goog.userAgent.IE = goog.userAgent.BROWSER_KNOWN_ ? goog.userAgent.ASSUME_IE : goog.userAgent.detectedIe_;
-goog.userAgent.GECKO = goog.userAgent.BROWSER_KNOWN_ ? goog.userAgent.ASSUME_GECKO : goog.userAgent.detectedGecko_;
-goog.userAgent.WEBKIT = goog.userAgent.BROWSER_KNOWN_ ? goog.userAgent.ASSUME_WEBKIT || goog.userAgent.ASSUME_MOBILE_WEBKIT : goog.userAgent.detectedWebkit_;
-goog.userAgent.MOBILE = goog.userAgent.ASSUME_MOBILE_WEBKIT || goog.userAgent.detectedMobile_;
-goog.userAgent.SAFARI = goog.userAgent.WEBKIT;
-goog.userAgent.determinePlatform_ = function() {
- var navigator = goog.userAgent.getNavigator();
- return navigator && navigator.platform || ""
-};
-goog.userAgent.PLATFORM = goog.userAgent.determinePlatform_();
-goog.userAgent.ASSUME_MAC = false;
-goog.userAgent.ASSUME_WINDOWS = false;
-goog.userAgent.ASSUME_LINUX = false;
-goog.userAgent.ASSUME_X11 = false;
-goog.userAgent.PLATFORM_KNOWN_ = goog.userAgent.ASSUME_MAC || goog.userAgent.ASSUME_WINDOWS || goog.userAgent.ASSUME_LINUX || goog.userAgent.ASSUME_X11;
-goog.userAgent.initPlatform_ = function() {
- goog.userAgent.detectedMac_ = goog.string.contains(goog.userAgent.PLATFORM, "Mac");
- goog.userAgent.detectedWindows_ = goog.string.contains(goog.userAgent.PLATFORM, "Win");
- goog.userAgent.detectedLinux_ = goog.string.contains(goog.userAgent.PLATFORM, "Linux");
- goog.userAgent.detectedX11_ = !!goog.userAgent.getNavigator() && goog.string.contains(goog.userAgent.getNavigator()["appVersion"] || "", "X11")
-};
-if(!goog.userAgent.PLATFORM_KNOWN_) {
- goog.userAgent.initPlatform_()
-}
-goog.userAgent.MAC = goog.userAgent.PLATFORM_KNOWN_ ? goog.userAgent.ASSUME_MAC : goog.userAgent.detectedMac_;
-goog.userAgent.WINDOWS = goog.userAgent.PLATFORM_KNOWN_ ? goog.userAgent.ASSUME_WINDOWS : goog.userAgent.detectedWindows_;
-goog.userAgent.LINUX = goog.userAgent.PLATFORM_KNOWN_ ? goog.userAgent.ASSUME_LINUX : goog.userAgent.detectedLinux_;
-goog.userAgent.X11 = goog.userAgent.PLATFORM_KNOWN_ ? goog.userAgent.ASSUME_X11 : goog.userAgent.detectedX11_;
-goog.userAgent.determineVersion_ = function() {
- var version = "", re;
- if(goog.userAgent.OPERA && goog.global["opera"]) {
- var operaVersion = goog.global["opera"].version;
- version = typeof operaVersion == "function" ? operaVersion() : operaVersion
- }else {
- if(goog.userAgent.GECKO) {
- re = /rv\:([^\);]+)(\)|;)/
- }else {
- if(goog.userAgent.IE) {
- re = /MSIE\s+([^\);]+)(\)|;)/
- }else {
- if(goog.userAgent.WEBKIT) {
- re = /WebKit\/(\S+)/
- }
- }
- }
- if(re) {
- var arr = re.exec(goog.userAgent.getUserAgentString());
- version = arr ? arr[1] : ""
- }
- }
- if(goog.userAgent.IE) {
- var docMode = goog.userAgent.getDocumentMode_();
- if(docMode > parseFloat(version)) {
- return String(docMode)
- }
- }
- return version
-};
-goog.userAgent.getDocumentMode_ = function() {
- var doc = goog.global["document"];
- return doc ? doc["documentMode"] : undefined
-};
-goog.userAgent.VERSION = goog.userAgent.determineVersion_();
-goog.userAgent.compare = function(v1, v2) {
- return goog.string.compareVersions(v1, v2)
-};
-goog.userAgent.isVersionCache_ = {};
-goog.userAgent.isVersion = function(version) {
- return goog.userAgent.isVersionCache_[version] || (goog.userAgent.isVersionCache_[version] = goog.string.compareVersions(goog.userAgent.VERSION, version) >= 0)
-};
-goog.provide("goog.dom.BrowserFeature");
-goog.require("goog.userAgent");
-goog.dom.BrowserFeature = {
- CAN_ADD_NAME_OR_TYPE_ATTRIBUTES: !goog.userAgent.IE || goog.userAgent.isVersion("9"),
- CAN_USE_INNER_TEXT: goog.userAgent.IE && !goog.userAgent.isVersion("9"),
- INNER_HTML_NEEDS_SCOPED_ELEMENT: goog.userAgent.IE
-};
-goog.provide("goog.dom.TagName");
-goog.dom.TagName = {A:"A", ABBR:"ABBR", ACRONYM:"ACRONYM", ADDRESS:"ADDRESS", APPLET:"APPLET", AREA:"AREA", B:"B", BASE:"BASE", BASEFONT:"BASEFONT", BDO:"BDO", BIG:"BIG", BLOCKQUOTE:"BLOCKQUOTE", BODY:"BODY", BR:"BR", BUTTON:"BUTTON", CANVAS:"CANVAS", CAPTION:"CAPTION", CENTER:"CENTER", CITE:"CITE", CODE:"CODE", COL:"COL", COLGROUP:"COLGROUP", DD:"DD", DEL:"DEL", DFN:"DFN", DIR:"DIR", DIV:"DIV", DL:"DL", DT:"DT", EM:"EM", FIELDSET:"FIELDSET", FONT:"FONT", FORM:"FORM", FRAME:"FRAME", FRAMESET:"FRAMESET",
-H1:"H1", H2:"H2", H3:"H3", H4:"H4", H5:"H5", H6:"H6", HEAD:"HEAD", HR:"HR", HTML:"HTML", I:"I", IFRAME:"IFRAME", IMG:"IMG", INPUT:"INPUT", INS:"INS", ISINDEX:"ISINDEX", KBD:"KBD", LABEL:"LABEL", LEGEND:"LEGEND", LI:"LI", LINK:"LINK", MAP:"MAP", MENU:"MENU", META:"META", NOFRAMES:"NOFRAMES", NOSCRIPT:"NOSCRIPT", OBJECT:"OBJECT", OL:"OL", OPTGROUP:"OPTGROUP", OPTION:"OPTION", P:"P", PARAM:"PARAM", PRE:"PRE", Q:"Q", S:"S", SAMP:"SAMP", SCRIPT:"SCRIPT", SELECT:"SELECT", SMALL:"SMALL", SPAN:"SPAN", STRIKE:"STRIKE",
-STRONG:"STRONG", STYLE:"STYLE", SUB:"SUB", SUP:"SUP", TABLE:"TABLE", TBODY:"TBODY", TD:"TD", TEXTAREA:"TEXTAREA", TFOOT:"TFOOT", TH:"TH", THEAD:"THEAD", TITLE:"TITLE", TR:"TR", TT:"TT", U:"U", UL:"UL", VAR:"VAR"};
-goog.provide("goog.dom.classes");
-goog.require("goog.array");
-goog.dom.classes.set = function(element, className) {
- element.className = className
-};
-goog.dom.classes.get = function(element) {
- var className = element.className;
- return className && typeof className.split == "function" ? className.split(/\s+/) : []
-};
-goog.dom.classes.add = function(element, var_args) {
- var classes = goog.dom.classes.get(element);
- var args = goog.array.slice(arguments, 1);
- var b = goog.dom.classes.add_(classes, args);
- element.className = classes.join(" ");
- return b
-};
-goog.dom.classes.remove = function(element, var_args) {
- var classes = goog.dom.classes.get(element);
- var args = goog.array.slice(arguments, 1);
- var b = goog.dom.classes.remove_(classes, args);
- element.className = classes.join(" ");
- return b
-};
-goog.dom.classes.add_ = function(classes, args) {
- var rv = 0;
- for(var i = 0;i < args.length;i++) {
- if(!goog.array.contains(classes, args[i])) {
- classes.push(args[i]);
- rv++
- }
- }
- return rv == args.length
-};
-goog.dom.classes.remove_ = function(classes, args) {
- var rv = 0;
- for(var i = 0;i < classes.length;i++) {
- if(goog.array.contains(args, classes[i])) {
- goog.array.splice(classes, i--, 1);
- rv++
- }
- }
- return rv == args.length
-};
-goog.dom.classes.swap = function(element, fromClass, toClass) {
- var classes = goog.dom.classes.get(element);
- var removed = false;
- for(var i = 0;i < classes.length;i++) {
- if(classes[i] == fromClass) {
- goog.array.splice(classes, i--, 1);
- removed = true
- }
- }
- if(removed) {
- classes.push(toClass);
- element.className = classes.join(" ")
- }
- return removed
-};
-goog.dom.classes.addRemove = function(element, classesToRemove, classesToAdd) {
- var classes = goog.dom.classes.get(element);
- if(goog.isString(classesToRemove)) {
- goog.array.remove(classes, classesToRemove)
- }else {
- if(goog.isArray(classesToRemove)) {
- goog.dom.classes.remove_(classes, classesToRemove)
- }
- }
- if(goog.isString(classesToAdd) && !goog.array.contains(classes, classesToAdd)) {
- classes.push(classesToAdd)
- }else {
- if(goog.isArray(classesToAdd)) {
- goog.dom.classes.add_(classes, classesToAdd)
- }
- }
- element.className = classes.join(" ")
-};
-goog.dom.classes.has = function(element, className) {
- return goog.array.contains(goog.dom.classes.get(element), className)
-};
-goog.dom.classes.enable = function(element, className, enabled) {
- if(enabled) {
- goog.dom.classes.add(element, className)
- }else {
- goog.dom.classes.remove(element, className)
- }
-};
-goog.dom.classes.toggle = function(element, className) {
- var add = !goog.dom.classes.has(element, className);
- goog.dom.classes.enable(element, className, add);
- return add
-};
-goog.provide("goog.math.Coordinate");
-goog.math.Coordinate = function(opt_x, opt_y) {
- this.x = goog.isDef(opt_x) ? opt_x : 0;
- this.y = goog.isDef(opt_y) ? opt_y : 0
-};
-goog.math.Coordinate.prototype.clone = function() {
- return new goog.math.Coordinate(this.x, this.y)
-};
-if(goog.DEBUG) {
- goog.math.Coordinate.prototype.toString = function() {
- return"(" + this.x + ", " + this.y + ")"
- }
-}
-goog.math.Coordinate.equals = function(a, b) {
- if(a == b) {
- return true
- }
- if(!a || !b) {
- return false
- }
- return a.x == b.x && a.y == b.y
-};
-goog.math.Coordinate.distance = function(a, b) {
- var dx = a.x - b.x;
- var dy = a.y - b.y;
- return Math.sqrt(dx * dx + dy * dy)
-};
-goog.math.Coordinate.squaredDistance = function(a, b) {
- var dx = a.x - b.x;
- var dy = a.y - b.y;
- return dx * dx + dy * dy
-};
-goog.math.Coordinate.difference = function(a, b) {
- return new goog.math.Coordinate(a.x - b.x, a.y - b.y)
-};
-goog.math.Coordinate.sum = function(a, b) {
- return new goog.math.Coordinate(a.x + b.x, a.y + b.y)
-};
-goog.provide("goog.math.Size");
-goog.math.Size = function(width, height) {
- this.width = width;
- this.height = height
-};
-goog.math.Size.equals = function(a, b) {
- if(a == b) {
- return true
- }
- if(!a || !b) {
- return false
- }
- return a.width == b.width && a.height == b.height
-};
-goog.math.Size.prototype.clone = function() {
- return new goog.math.Size(this.width, this.height)
-};
-if(goog.DEBUG) {
- goog.math.Size.prototype.toString = function() {
- return"(" + this.width + " x " + this.height + ")"
- }
-}
-goog.math.Size.prototype.getLongest = function() {
- return Math.max(this.width, this.height)
-};
-goog.math.Size.prototype.getShortest = function() {
- return Math.min(this.width, this.height)
-};
-goog.math.Size.prototype.area = function() {
- return this.width * this.height
-};
-goog.math.Size.prototype.perimeter = function() {
- return(this.width + this.height) * 2
-};
-goog.math.Size.prototype.aspectRatio = function() {
- return this.width / this.height
-};
-goog.math.Size.prototype.isEmpty = function() {
- return!this.area()
-};
-goog.math.Size.prototype.ceil = function() {
- this.width = Math.ceil(this.width);
- this.height = Math.ceil(this.height);
- return this
-};
-goog.math.Size.prototype.fitsInside = function(target) {
- return this.width <= target.width && this.height <= target.height
-};
-goog.math.Size.prototype.floor = function() {
- this.width = Math.floor(this.width);
- this.height = Math.floor(this.height);
- return this
-};
-goog.math.Size.prototype.round = function() {
- this.width = Math.round(this.width);
- this.height = Math.round(this.height);
- return this
-};
-goog.math.Size.prototype.scale = function(s) {
- this.width *= s;
- this.height *= s;
- return this
-};
-goog.math.Size.prototype.scaleToFit = function(target) {
- var s = this.aspectRatio() > target.aspectRatio() ? target.width / this.width : target.height / this.height;
- return this.scale(s)
-};
-goog.provide("goog.object");
-goog.object.forEach = function(obj, f, opt_obj) {
- for(var key in obj) {
- f.call(opt_obj, obj[key], key, obj)
- }
-};
-goog.object.filter = function(obj, f, opt_obj) {
- var res = {};
- for(var key in obj) {
- if(f.call(opt_obj, obj[key], key, obj)) {
- res[key] = obj[key]
- }
- }
- return res
-};
-goog.object.map = function(obj, f, opt_obj) {
- var res = {};
- for(var key in obj) {
- res[key] = f.call(opt_obj, obj[key], key, obj)
- }
- return res
-};
-goog.object.some = function(obj, f, opt_obj) {
- for(var key in obj) {
- if(f.call(opt_obj, obj[key], key, obj)) {
- return true
- }
- }
- return false
-};
-goog.object.every = function(obj, f, opt_obj) {
- for(var key in obj) {
- if(!f.call(opt_obj, obj[key], key, obj)) {
- return false
- }
- }
- return true
-};
-goog.object.getCount = function(obj) {
- var rv = 0;
- for(var key in obj) {
- rv++
- }
- return rv
-};
-goog.object.getAnyKey = function(obj) {
- for(var key in obj) {
- return key
- }
-};
-goog.object.getAnyValue = function(obj) {
- for(var key in obj) {
- return obj[key]
- }
-};
-goog.object.contains = function(obj, val) {
- return goog.object.containsValue(obj, val)
-};
-goog.object.getValues = function(obj) {
- var res = [];
- var i = 0;
- for(var key in obj) {
- res[i++] = obj[key]
- }
- return res
-};
-goog.object.getKeys = function(obj) {
- var res = [];
- var i = 0;
- for(var key in obj) {
- res[i++] = key
- }
- return res
-};
-goog.object.containsKey = function(obj, key) {
- return key in obj
-};
-goog.object.containsValue = function(obj, val) {
- for(var key in obj) {
- if(obj[key] == val) {
- return true
- }
- }
- return false
-};
-goog.object.findKey = function(obj, f, opt_this) {
- for(var key in obj) {
- if(f.call(opt_this, obj[key], key, obj)) {
- return key
- }
- }
- return undefined
-};
-goog.object.findValue = function(obj, f, opt_this) {
- var key = goog.object.findKey(obj, f, opt_this);
- return key && obj[key]
-};
-goog.object.isEmpty = function(obj) {
- for(var key in obj) {
- return false
- }
- return true
-};
-goog.object.clear = function(obj) {
- var keys = goog.object.getKeys(obj);
- for(var i = keys.length - 1;i >= 0;i--) {
- goog.object.remove(obj, keys[i])
- }
-};
-goog.object.remove = function(obj, key) {
- var rv;
- if(rv = key in obj) {
- delete obj[key]
- }
- return rv
-};
-goog.object.add = function(obj, key, val) {
- if(key in obj) {
- throw Error('The object already contains the key "' + key + '"');
- }
- goog.object.set(obj, key, val)
-};
-goog.object.get = function(obj, key, opt_val) {
- if(key in obj) {
- return obj[key]
- }
- return opt_val
-};
-goog.object.set = function(obj, key, value) {
- obj[key] = value
-};
-goog.object.setIfUndefined = function(obj, key, value) {
- return key in obj ? obj[key] : obj[key] = value
-};
-goog.object.clone = function(obj) {
- var res = {};
- for(var key in obj) {
- res[key] = obj[key]
- }
- return res
-};
-goog.object.transpose = function(obj) {
- var transposed = {};
- for(var key in obj) {
- transposed[obj[key]] = key
- }
- return transposed
-};
-goog.object.PROTOTYPE_FIELDS_ = ["constructor", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "toLocaleString", "toString", "valueOf"];
-goog.object.extend = function(target, var_args) {
- var key, source;
- for(var i = 1;i < arguments.length;i++) {
- source = arguments[i];
- for(key in source) {
- target[key] = source[key]
- }
- for(var j = 0;j < goog.object.PROTOTYPE_FIELDS_.length;j++) {
- key = goog.object.PROTOTYPE_FIELDS_[j];
- if(Object.prototype.hasOwnProperty.call(source, key)) {
- target[key] = source[key]
- }
- }
- }
-};
-goog.object.create = function(var_args) {
- var argLength = arguments.length;
- if(argLength == 1 && goog.isArray(arguments[0])) {
- return goog.object.create.apply(null, arguments[0])
- }
- if(argLength % 2) {
- throw Error("Uneven number of arguments");
- }
- var rv = {};
- for(var i = 0;i < argLength;i += 2) {
- rv[arguments[i]] = arguments[i + 1]
- }
- return rv
-};
-goog.object.createSet = function(var_args) {
- var argLength = arguments.length;
- if(argLength == 1 && goog.isArray(arguments[0])) {
- return goog.object.createSet.apply(null, arguments[0])
- }
- var rv = {};
- for(var i = 0;i < argLength;i++) {
- rv[arguments[i]] = true
- }
- return rv
-};
-goog.provide("goog.dom");
-goog.provide("goog.dom.DomHelper");
-goog.provide("goog.dom.NodeType");
-goog.require("goog.array");
-goog.require("goog.dom.BrowserFeature");
-goog.require("goog.dom.TagName");
-goog.require("goog.dom.classes");
-goog.require("goog.math.Coordinate");
-goog.require("goog.math.Size");
-goog.require("goog.object");
-goog.require("goog.string");
-goog.require("goog.userAgent");
-goog.dom.ASSUME_QUIRKS_MODE = false;
-goog.dom.ASSUME_STANDARDS_MODE = false;
-goog.dom.COMPAT_MODE_KNOWN_ = goog.dom.ASSUME_QUIRKS_MODE || goog.dom.ASSUME_STANDARDS_MODE;
-goog.dom.NodeType = {ELEMENT:1, ATTRIBUTE:2, TEXT:3, CDATA_SECTION:4, ENTITY_REFERENCE:5, ENTITY:6, PROCESSING_INSTRUCTION:7, COMMENT:8, DOCUMENT:9, DOCUMENT_TYPE:10, DOCUMENT_FRAGMENT:11, NOTATION:12};
-goog.dom.getDomHelper = function(opt_element) {
- return opt_element ? new goog.dom.DomHelper(goog.dom.getOwnerDocument(opt_element)) : goog.dom.defaultDomHelper_ || (goog.dom.defaultDomHelper_ = new goog.dom.DomHelper)
-};
-goog.dom.defaultDomHelper_;
-goog.dom.getDocument = function() {
- return document
-};
-goog.dom.getElement = function(element) {
- return goog.isString(element) ? document.getElementById(element) : element
-};
-goog.dom.$ = goog.dom.getElement;
-goog.dom.getElementsByTagNameAndClass = function(opt_tag, opt_class, opt_el) {
- return goog.dom.getElementsByTagNameAndClass_(document, opt_tag, opt_class, opt_el)
-};
-goog.dom.getElementsByClass = function(className, opt_el) {
- var parent = opt_el || document;
- if(goog.dom.canUseQuerySelector_(parent)) {
- return parent.querySelectorAll("." + className)
- }else {
- if(parent.getElementsByClassName) {
- return parent.getElementsByClassName(className)
- }
- }
- return goog.dom.getElementsByTagNameAndClass_(document, "*", className, opt_el)
-};
-goog.dom.getElementByClass = function(className, opt_el) {
- var parent = opt_el || document;
- var retVal = null;
- if(goog.dom.canUseQuerySelector_(parent)) {
- retVal = parent.querySelector("." + className)
- }else {
- retVal = goog.dom.getElementsByClass(className, opt_el)[0]
- }
- return retVal || null
-};
-goog.dom.canUseQuerySelector_ = function(parent) {
- return parent.querySelectorAll && parent.querySelector && (!goog.userAgent.WEBKIT || goog.dom.isCss1CompatMode_(document) || goog.userAgent.isVersion("528"))
-};
-goog.dom.getElementsByTagNameAndClass_ = function(doc, opt_tag, opt_class, opt_el) {
- var parent = opt_el || doc;
- var tagName = opt_tag && opt_tag != "*" ? opt_tag.toUpperCase() : "";
- if(goog.dom.canUseQuerySelector_(parent) && (tagName || opt_class)) {
- var query = tagName + (opt_class ? "." + opt_class : "");
- return parent.querySelectorAll(query)
- }
- if(opt_class && parent.getElementsByClassName) {
- var els = parent.getElementsByClassName(opt_class);
- if(tagName) {
- var arrayLike = {};
- var len = 0;
- for(var i = 0, el;el = els[i];i++) {
- if(tagName == el.nodeName) {
- arrayLike[len++] = el
- }
- }
- arrayLike.length = len;
- return arrayLike
- }else {
- return els
- }
- }
- var els = parent.getElementsByTagName(tagName || "*");
- if(opt_class) {
- var arrayLike = {};
- var len = 0;
- for(var i = 0, el;el = els[i];i++) {
- var className = el.className;
- if(typeof className.split == "function" && goog.array.contains(className.split(/\s+/), opt_class)) {
- arrayLike[len++] = el
- }
- }
- arrayLike.length = len;
- return arrayLike
- }else {
- return els
- }
-};
-goog.dom.$$ = goog.dom.getElementsByTagNameAndClass;
-goog.dom.setProperties = function(element, properties) {
- goog.object.forEach(properties, function(val, key) {
- if(key == "style") {
- element.style.cssText = val
- }else {
- if(key == "class") {
- element.className = val
- }else {
- if(key == "for") {
- element.htmlFor = val
- }else {
- if(key in goog.dom.DIRECT_ATTRIBUTE_MAP_) {
- element.setAttribute(goog.dom.DIRECT_ATTRIBUTE_MAP_[key], val)
- }else {
- element[key] = val
- }
- }
- }
- }
- })
-};
-goog.dom.DIRECT_ATTRIBUTE_MAP_ = {cellpadding:"cellPadding", cellspacing:"cellSpacing", colspan:"colSpan", rowspan:"rowSpan", valign:"vAlign", height:"height", width:"width", usemap:"useMap", frameborder:"frameBorder", type:"type"};
-goog.dom.getViewportSize = function(opt_window) {
- return goog.dom.getViewportSize_(opt_window || window)
-};
-goog.dom.getViewportSize_ = function(win) {
- var doc = win.document;
- if(goog.userAgent.WEBKIT && !goog.userAgent.isVersion("500") && !goog.userAgent.MOBILE) {
- if(typeof win.innerHeight == "undefined") {
- win = window
- }
- var innerHeight = win.innerHeight;
- var scrollHeight = win.document.documentElement.scrollHeight;
- if(win == win.top) {
- if(scrollHeight < innerHeight) {
- innerHeight -= 15
- }
- }
- return new goog.math.Size(win.innerWidth, innerHeight)
- }
- var readsFromDocumentElement = goog.dom.isCss1CompatMode_(doc);
- if(goog.userAgent.OPERA && !goog.userAgent.isVersion("9.50")) {
- readsFromDocumentElement = false
- }
- var el = readsFromDocumentElement ? doc.documentElement : doc.body;
- return new goog.math.Size(el.clientWidth, el.clientHeight)
-};
-goog.dom.getDocumentHeight = function() {
- return goog.dom.getDocumentHeight_(window)
-};
-goog.dom.getDocumentHeight_ = function(win) {
- var doc = win.document;
- var height = 0;
- if(doc) {
- var vh = goog.dom.getViewportSize_(win).height;
- var body = doc.body;
- var docEl = doc.documentElement;
- if(goog.dom.isCss1CompatMode_(doc) && docEl.scrollHeight) {
- height = docEl.scrollHeight != vh ? docEl.scrollHeight : docEl.offsetHeight
- }else {
- var sh = docEl.scrollHeight;
- var oh = docEl.offsetHeight;
- if(docEl.clientHeight != oh) {
- sh = body.scrollHeight;
- oh = body.offsetHeight
- }
- if(sh > vh) {
- height = sh > oh ? sh : oh
- }else {
- height = sh < oh ? sh : oh
- }
- }
- }
- return height
-};
-goog.dom.getPageScroll = function(opt_window) {
- var win = opt_window || goog.global || window;
- return goog.dom.getDomHelper(win.document).getDocumentScroll()
-};
-goog.dom.getDocumentScroll = function() {
- return goog.dom.getDocumentScroll_(document)
-};
-goog.dom.getDocumentScroll_ = function(doc) {
- var el = goog.dom.getDocumentScrollElement_(doc);
- return new goog.math.Coordinate(el.scrollLeft, el.scrollTop)
-};
-goog.dom.getDocumentScrollElement = function() {
- return goog.dom.getDocumentScrollElement_(document)
-};
-goog.dom.getDocumentScrollElement_ = function(doc) {
- return!goog.userAgent.WEBKIT && goog.dom.isCss1CompatMode_(doc) ? doc.documentElement : doc.body
-};
-goog.dom.getWindow = function(opt_doc) {
- return opt_doc ? goog.dom.getWindow_(opt_doc) : window
-};
-goog.dom.getWindow_ = function(doc) {
- return doc.parentWindow || doc.defaultView
-};
-goog.dom.createDom = function(tagName, opt_attributes, var_args) {
- return goog.dom.createDom_(document, arguments)
-};
-goog.dom.createDom_ = function(doc, args) {
- var tagName = args[0];
- var attributes = args[1];
- if(!goog.dom.BrowserFeature.CAN_ADD_NAME_OR_TYPE_ATTRIBUTES && attributes && (attributes.name || attributes.type)) {
- var tagNameArr = ["<", tagName];
- if(attributes.name) {
- tagNameArr.push(' name="', goog.string.htmlEscape(attributes.name), '"')
- }
- if(attributes.type) {
- tagNameArr.push(' type="', goog.string.htmlEscape(attributes.type), '"');
- var clone = {};
- goog.object.extend(clone, attributes);
- attributes = clone;
- delete attributes.type
- }
- tagNameArr.push(">");
- tagName = tagNameArr.join("")
- }
- var element = doc.createElement(tagName);
- if(attributes) {
- if(goog.isString(attributes)) {
- element.className = attributes
- }else {
- if(goog.isArray(attributes)) {
- goog.dom.classes.add.apply(null, [element].concat(attributes))
- }else {
- goog.dom.setProperties(element, attributes)
- }
- }
- }
- if(args.length > 2) {
- goog.dom.append_(doc, element, args, 2)
- }
- return element
-};
-goog.dom.append_ = function(doc, parent, args, startIndex) {
- function childHandler(child) {
- if(child) {
- parent.appendChild(goog.isString(child) ? doc.createTextNode(child) : child)
- }
- }
- for(var i = startIndex;i < args.length;i++) {
- var arg = args[i];
- if(goog.isArrayLike(arg) && !goog.dom.isNodeLike(arg)) {
- goog.array.forEach(goog.dom.isNodeList(arg) ? goog.array.clone(arg) : arg, childHandler)
- }else {
- childHandler(arg)
- }
- }
-};
-goog.dom.$dom = goog.dom.createDom;
-goog.dom.createElement = function(name) {
- return document.createElement(name)
-};
-goog.dom.createTextNode = function(content) {
- return document.createTextNode(content)
-};
-goog.dom.createTable = function(rows, columns, opt_fillWithNbsp) {
- return goog.dom.createTable_(document, rows, columns, !!opt_fillWithNbsp)
-};
-goog.dom.createTable_ = function(doc, rows, columns, fillWithNbsp) {
- var rowHtml = ["<tr>"];
- for(var i = 0;i < columns;i++) {
- rowHtml.push(fillWithNbsp ? "<td>&nbsp;</td>" : "<td></td>")
- }
- rowHtml.push("</tr>");
- rowHtml = rowHtml.join("");
- var totalHtml = ["<table>"];
- for(i = 0;i < rows;i++) {
- totalHtml.push(rowHtml)
- }
- totalHtml.push("</table>");
- var elem = doc.createElement(goog.dom.TagName.DIV);
- elem.innerHTML = totalHtml.join("");
- return elem.removeChild(elem.firstChild)
-};
-goog.dom.htmlToDocumentFragment = function(htmlString) {
- return goog.dom.htmlToDocumentFragment_(document, htmlString)
-};
-goog.dom.htmlToDocumentFragment_ = function(doc, htmlString) {
- var tempDiv = doc.createElement("div");
- if(goog.dom.BrowserFeature.INNER_HTML_NEEDS_SCOPED_ELEMENT) {
- tempDiv.innerHTML = "<br>" + htmlString;
- tempDiv.removeChild(tempDiv.firstChild)
- }else {
- tempDiv.innerHTML = htmlString
- }
- if(tempDiv.childNodes.length == 1) {
- return tempDiv.removeChild(tempDiv.firstChild)
- }else {
- var fragment = doc.createDocumentFragment();
- while(tempDiv.firstChild) {
- fragment.appendChild(tempDiv.firstChild)
- }
- return fragment
- }
-};
-goog.dom.getCompatMode = function() {
- return goog.dom.isCss1CompatMode() ? "CSS1Compat" : "BackCompat"
-};
-goog.dom.isCss1CompatMode = function() {
- return goog.dom.isCss1CompatMode_(document)
-};
-goog.dom.isCss1CompatMode_ = function(doc) {
- if(goog.dom.COMPAT_MODE_KNOWN_) {
- return goog.dom.ASSUME_STANDARDS_MODE
- }
- return doc.compatMode == "CSS1Compat"
-};
-goog.dom.canHaveChildren = function(node) {
- if(node.nodeType != goog.dom.NodeType.ELEMENT) {
- return false
- }
- switch(node.tagName) {
- case goog.dom.TagName.APPLET:
- ;
- case goog.dom.TagName.AREA:
- ;
- case goog.dom.TagName.BASE:
- ;
- case goog.dom.TagName.BR:
- ;
- case goog.dom.TagName.COL:
- ;
- case goog.dom.TagName.FRAME:
- ;
- case goog.dom.TagName.HR:
- ;
- case goog.dom.TagName.IMG:
- ;
- case goog.dom.TagName.INPUT:
- ;
- case goog.dom.TagName.IFRAME:
- ;
- case goog.dom.TagName.ISINDEX:
- ;
- case goog.dom.TagName.LINK:
- ;
- case goog.dom.TagName.NOFRAMES:
- ;
- case goog.dom.TagName.NOSCRIPT:
- ;
- case goog.dom.TagName.META:
- ;
- case goog.dom.TagName.OBJECT:
- ;
- case goog.dom.TagName.PARAM:
- ;
- case goog.dom.TagName.SCRIPT:
- ;
- case goog.dom.TagName.STYLE:
- return false
- }
- return true
-};
-goog.dom.appendChild = function(parent, child) {
- parent.appendChild(child)
-};
-goog.dom.append = function(parent, var_args) {
- goog.dom.append_(goog.dom.getOwnerDocument(parent), parent, arguments, 1)
-};
-goog.dom.removeChildren = function(node) {
- var child;
- while(child = node.firstChild) {
- node.removeChild(child)
- }
-};
-goog.dom.insertSiblingBefore = function(newNode, refNode) {
- if(refNode.parentNode) {
- refNode.parentNode.insertBefore(newNode, refNode)
- }
-};
-goog.dom.insertSiblingAfter = function(newNode, refNode) {
- if(refNode.parentNode) {
- refNode.parentNode.insertBefore(newNode, refNode.nextSibling)
- }
-};
-goog.dom.removeNode = function(node) {
- return node && node.parentNode ? node.parentNode.removeChild(node) : null
-};
-goog.dom.replaceNode = function(newNode, oldNode) {
- var parent = oldNode.parentNode;
- if(parent) {
- parent.replaceChild(newNode, oldNode)
- }
-};
-goog.dom.flattenElement = function(element) {
- var child, parent = element.parentNode;
- if(parent && parent.nodeType != goog.dom.NodeType.DOCUMENT_FRAGMENT) {
- if(element.removeNode) {
- return element.removeNode(false)
- }else {
- while(child = element.firstChild) {
- parent.insertBefore(child, element)
- }
- return goog.dom.removeNode(element)
- }
- }
-};
-goog.dom.getFirstElementChild = function(node) {
- return goog.dom.getNextElementNode_(node.firstChild, true)
-};
-goog.dom.getLastElementChild = function(node) {
- return goog.dom.getNextElementNode_(node.lastChild, false)
-};
-goog.dom.getNextElementSibling = function(node) {
- return goog.dom.getNextElementNode_(node.nextSibling, true)
-};
-goog.dom.getPreviousElementSibling = function(node) {
- return goog.dom.getNextElementNode_(node.previousSibling, false)
-};
-goog.dom.getNextElementNode_ = function(node, forward) {
- while(node && node.nodeType != goog.dom.NodeType.ELEMENT) {
- node = forward ? node.nextSibling : node.previousSibling
- }
- return node
-};
-goog.dom.getNextNode = function(node) {
- if(!node) {
- return null
- }
- if(node.firstChild) {
- return node.firstChild
- }
- while(node && !node.nextSibling) {
- node = node.parentNode
- }
- return node ? node.nextSibling : null
-};
-goog.dom.getPreviousNode = function(node) {
- if(!node) {
- return null
- }
- if(!node.previousSibling) {
- return node.parentNode
- }
- node = node.previousSibling;
- while(node && node.lastChild) {
- node = node.lastChild
- }
- return node
-};
-goog.dom.isNodeLike = function(obj) {
- return goog.isObject(obj) && obj.nodeType > 0
-};
-goog.dom.contains = function(parent, descendant) {
- if(parent.contains && descendant.nodeType == goog.dom.NodeType.ELEMENT) {
- return parent == descendant || parent.contains(descendant)
- }
- if(typeof parent.compareDocumentPosition != "undefined") {
- return parent == descendant || Boolean(parent.compareDocumentPosition(descendant) & 16)
- }
- while(descendant && parent != descendant) {
- descendant = descendant.parentNode
- }
- return descendant == parent
-};
-goog.dom.compareNodeOrder = function(node1, node2) {
- if(node1 == node2) {
- return 0
- }
- if(node1.compareDocumentPosition) {
- return node1.compareDocumentPosition(node2) & 2 ? 1 : -1
- }
- if("sourceIndex" in node1 || node1.parentNode && "sourceIndex" in node1.parentNode) {
- var isElement1 = node1.nodeType == goog.dom.NodeType.ELEMENT;
- var isElement2 = node2.nodeType == goog.dom.NodeType.ELEMENT;
- if(isElement1 && isElement2) {
- return node1.sourceIndex - node2.sourceIndex
- }else {
- var parent1 = node1.parentNode;
- var parent2 = node2.parentNode;
- if(parent1 == parent2) {
- return goog.dom.compareSiblingOrder_(node1, node2)
- }
- if(!isElement1 && goog.dom.contains(parent1, node2)) {
- return-1 * goog.dom.compareParentsDescendantNodeIe_(node1, node2)
- }
- if(!isElement2 && goog.dom.contains(parent2, node1)) {
- return goog.dom.compareParentsDescendantNodeIe_(node2, node1)
- }
- return(isElement1 ? node1.sourceIndex : parent1.sourceIndex) - (isElement2 ? node2.sourceIndex : parent2.sourceIndex)
- }
- }
- var doc = goog.dom.getOwnerDocument(node1);
- var range1, range2;
- range1 = doc.createRange();
- range1.selectNode(node1);
- range1.collapse(true);
- range2 = doc.createRange();
- range2.selectNode(node2);
- range2.collapse(true);
- return range1.compareBoundaryPoints(goog.global["Range"].START_TO_END, range2)
-};
-goog.dom.compareParentsDescendantNodeIe_ = function(textNode, node) {
- var parent = textNode.parentNode;
- if(parent == node) {
- return-1
- }
- var sibling = node;
- while(sibling.parentNode != parent) {
- sibling = sibling.parentNode
- }
- return goog.dom.compareSiblingOrder_(sibling, textNode)
-};
-goog.dom.compareSiblingOrder_ = function(node1, node2) {
- var s = node2;
- while(s = s.previousSibling) {
- if(s == node1) {
- return-1
- }
- }
- return 1
-};
-goog.dom.findCommonAncestor = function(var_args) {
- var i, count = arguments.length;
- if(!count) {
- return null
- }else {
- if(count == 1) {
- return arguments[0]
- }
- }
- var paths = [];
- var minLength = Infinity;
- for(i = 0;i < count;i++) {
- var ancestors = [];
- var node = arguments[i];
- while(node) {
- ancestors.unshift(node);
- node = node.parentNode
- }
- paths.push(ancestors);
- minLength = Math.min(minLength, ancestors.length)
- }
- var output = null;
- for(i = 0;i < minLength;i++) {
- var first = paths[0][i];
- for(var j = 1;j < count;j++) {
- if(first != paths[j][i]) {
- return output
- }
- }
- output = first
- }
- return output
-};
-goog.dom.getOwnerDocument = function(node) {
- return node.nodeType == goog.dom.NodeType.DOCUMENT ? node : node.ownerDocument || node.document
-};
-goog.dom.getFrameContentDocument = function(frame) {
- var doc;
- if(goog.userAgent.WEBKIT) {
- doc = frame.document || frame.contentWindow.document
- }else {
- doc = frame.contentDocument || frame.contentWindow.document
- }
- return doc
-};
-goog.dom.getFrameContentWindow = function(frame) {
- return frame.contentWindow || goog.dom.getWindow_(goog.dom.getFrameContentDocument(frame))
-};
-goog.dom.setTextContent = function(element, text) {
- if("textContent" in element) {
- element.textContent = text
- }else {
- if(element.firstChild && element.firstChild.nodeType == goog.dom.NodeType.TEXT) {
- while(element.lastChild != element.firstChild) {
- element.removeChild(element.lastChild)
- }
- element.firstChild.data = text
- }else {
- goog.dom.removeChildren(element);
- var doc = goog.dom.getOwnerDocument(element);
- element.appendChild(doc.createTextNode(text))
- }
- }
-};
-goog.dom.getOuterHtml = function(element) {
- if("outerHTML" in element) {
- return element.outerHTML
- }else {
- var doc = goog.dom.getOwnerDocument(element);
- var div = doc.createElement("div");
- div.appendChild(element.cloneNode(true));
- return div.innerHTML
- }
-};
-goog.dom.findNode = function(root, p) {
- var rv = [];
- var found = goog.dom.findNodes_(root, p, rv, true);
- return found ? rv[0] : undefined
-};
-goog.dom.findNodes = function(root, p) {
- var rv = [];
- goog.dom.findNodes_(root, p, rv, false);
- return rv
-};
-goog.dom.findNodes_ = function(root, p, rv, findOne) {
- if(root != null) {
- for(var i = 0, child;child = root.childNodes[i];i++) {
- if(p(child)) {
- rv.push(child);
- if(findOne) {
- return true
- }
- }
- if(goog.dom.findNodes_(child, p, rv, findOne)) {
- return true
- }
- }
- }
- return false
-};
-goog.dom.TAGS_TO_IGNORE_ = {SCRIPT:1, STYLE:1, HEAD:1, IFRAME:1, OBJECT:1};
-goog.dom.PREDEFINED_TAG_VALUES_ = {IMG:" ", BR:"\n"};
-goog.dom.isFocusableTabIndex = function(element) {
- var attrNode = element.getAttributeNode("tabindex");
- if(attrNode && attrNode.specified) {
- var index = element.tabIndex;
- return goog.isNumber(index) && index >= 0
- }
- return false
-};
-goog.dom.setFocusableTabIndex = function(element, enable) {
- if(enable) {
- element.tabIndex = 0
- }else {
- element.removeAttribute("tabIndex")
- }
-};
-goog.dom.getTextContent = function(node) {
- var textContent;
- if(goog.dom.BrowserFeature.CAN_USE_INNER_TEXT && "innerText" in node) {
- textContent = goog.string.canonicalizeNewlines(node.innerText)
- }else {
- var buf = [];
- goog.dom.getTextContent_(node, buf, true);
- textContent = buf.join("")
- }
- textContent = textContent.replace(/ \xAD /g, " ").replace(/\xAD/g, "");
- if(!goog.userAgent.IE) {
- textContent = textContent.replace(/ +/g, " ")
- }
- if(textContent != " ") {
- textContent = textContent.replace(/^\s*/, "")
- }
- return textContent
-};
-goog.dom.getRawTextContent = function(node) {
- var buf = [];
- goog.dom.getTextContent_(node, buf, false);
- return buf.join("")
-};
-goog.dom.getTextContent_ = function(node, buf, normalizeWhitespace) {
- if(node.nodeName in goog.dom.TAGS_TO_IGNORE_) {
- }else {
- if(node.nodeType == goog.dom.NodeType.TEXT) {
- if(normalizeWhitespace) {
- buf.push(String(node.nodeValue).replace(/(\r\n|\r|\n)/g, ""))
- }else {
- buf.push(node.nodeValue)
- }
- }else {
- if(node.nodeName in goog.dom.PREDEFINED_TAG_VALUES_) {
- buf.push(goog.dom.PREDEFINED_TAG_VALUES_[node.nodeName])
- }else {
- var child = node.firstChild;
- while(child) {
- goog.dom.getTextContent_(child, buf, normalizeWhitespace);
- child = child.nextSibling
- }
- }
- }
- }
-};
-goog.dom.getNodeTextLength = function(node) {
- return goog.dom.getTextContent(node).length
-};
-goog.dom.getNodeTextOffset = function(node, opt_offsetParent) {
- var root = opt_offsetParent || goog.dom.getOwnerDocument(node).body;
- var buf = [];
- while(node && node != root) {
- var cur = node;
- while(cur = cur.previousSibling) {
- buf.unshift(goog.dom.getTextContent(cur))
- }
- node = node.parentNode
- }
- return goog.string.trimLeft(buf.join("")).replace(/ +/g, " ").length
-};
-goog.dom.getNodeAtOffset = function(parent, offset, opt_result) {
- var stack = [parent], pos = 0, cur;
- while(stack.length > 0 && pos < offset) {
- cur = stack.pop();
- if(cur.nodeName in goog.dom.TAGS_TO_IGNORE_) {
- }else {
- if(cur.nodeType == goog.dom.NodeType.TEXT) {
- var text = cur.nodeValue.replace(/(\r\n|\r|\n)/g, "").replace(/ +/g, " ");
- pos += text.length
- }else {
- if(cur.nodeName in goog.dom.PREDEFINED_TAG_VALUES_) {
- pos += goog.dom.PREDEFINED_TAG_VALUES_[cur.nodeName].length
- }else {
- for(var i = cur.childNodes.length - 1;i >= 0;i--) {
- stack.push(cur.childNodes[i])
- }
- }
- }
- }
- }
- if(goog.isObject(opt_result)) {
- opt_result.remainder = cur ? cur.nodeValue.length + offset - pos - 1 : 0;
- opt_result.node = cur
- }
- return cur
-};
-goog.dom.isNodeList = function(val) {
- if(val && typeof val.length == "number") {
- if(goog.isObject(val)) {
- return typeof val.item == "function" || typeof val.item == "string"
- }else {
- if(goog.isFunction(val)) {
- return typeof val.item == "function"
- }
- }
- }
- return false
-};
-goog.dom.getAncestorByTagNameAndClass = function(element, opt_tag, opt_class) {
- var tagName = opt_tag ? opt_tag.toUpperCase() : null;
- return goog.dom.getAncestor(element, function(node) {
- return(!tagName || node.nodeName == tagName) && (!opt_class || goog.dom.classes.has(node, opt_class))
- }, true)
-};
-goog.dom.getAncestor = function(element, matcher, opt_includeNode, opt_maxSearchSteps) {
- if(!opt_includeNode) {
- element = element.parentNode
- }
- var ignoreSearchSteps = opt_maxSearchSteps == null;
- var steps = 0;
- while(element && (ignoreSearchSteps || steps <= opt_maxSearchSteps)) {
- if(matcher(element)) {
- return element
- }
- element = element.parentNode;
- steps++
- }
- return null
-};
-goog.dom.DomHelper = function(opt_document) {
- this.document_ = opt_document || goog.global.document || document
-};
-goog.dom.DomHelper.prototype.getDomHelper = goog.dom.getDomHelper;
-goog.dom.DomHelper.prototype.setDocument = function(document) {
- this.document_ = document
-};
-goog.dom.DomHelper.prototype.getDocument = function() {
- return this.document_
-};
-goog.dom.DomHelper.prototype.getElement = function(element) {
- if(goog.isString(element)) {
- return this.document_.getElementById(element)
- }else {
- return element
- }
-};
-goog.dom.DomHelper.prototype.$ = goog.dom.DomHelper.prototype.getElement;
-goog.dom.DomHelper.prototype.getElementsByTagNameAndClass = function(opt_tag, opt_class, opt_el) {
- return goog.dom.getElementsByTagNameAndClass_(this.document_, opt_tag, opt_class, opt_el)
-};
-goog.dom.DomHelper.prototype.getElementsByClass = function(className, opt_el) {
- var doc = opt_el || this.document_;
- return goog.dom.getElementsByClass(className, doc)
-};
-goog.dom.DomHelper.prototype.getElementByClass = function(className, opt_el) {
- var doc = opt_el || this.document_;
- return goog.dom.getElementByClass(className, doc)
-};
-goog.dom.DomHelper.prototype.$$ = goog.dom.DomHelper.prototype.getElementsByTagNameAndClass;
-goog.dom.DomHelper.prototype.setProperties = goog.dom.setProperties;
-goog.dom.DomHelper.prototype.getViewportSize = function(opt_window) {
- return goog.dom.getViewportSize(opt_window || this.getWindow())
-};
-goog.dom.DomHelper.prototype.getDocumentHeight = function() {
- return goog.dom.getDocumentHeight_(this.getWindow())
-};
-goog.dom.Appendable;
-goog.dom.DomHelper.prototype.createDom = function(tagName, opt_attributes, var_args) {
- return goog.dom.createDom_(this.document_, arguments)
-};
-goog.dom.DomHelper.prototype.$dom = goog.dom.DomHelper.prototype.createDom;
-goog.dom.DomHelper.prototype.createElement = function(name) {
- return this.document_.createElement(name)
-};
-goog.dom.DomHelper.prototype.createTextNode = function(content) {
- return this.document_.createTextNode(content)
-};
-goog.dom.DomHelper.prototype.createTable = function(rows, columns, opt_fillWithNbsp) {
- return goog.dom.createTable_(this.document_, rows, columns, !!opt_fillWithNbsp)
-};
-goog.dom.DomHelper.prototype.htmlToDocumentFragment = function(htmlString) {
- return goog.dom.htmlToDocumentFragment_(this.document_, htmlString)
-};
-goog.dom.DomHelper.prototype.getCompatMode = function() {
- return this.isCss1CompatMode() ? "CSS1Compat" : "BackCompat"
-};
-goog.dom.DomHelper.prototype.isCss1CompatMode = function() {
- return goog.dom.isCss1CompatMode_(this.document_)
-};
-goog.dom.DomHelper.prototype.getWindow = function() {
- return goog.dom.getWindow_(this.document_)
-};
-goog.dom.DomHelper.prototype.getDocumentScrollElement = function() {
- return goog.dom.getDocumentScrollElement_(this.document_)
-};
-goog.dom.DomHelper.prototype.getDocumentScroll = function() {
- return goog.dom.getDocumentScroll_(this.document_)
-};
-goog.dom.DomHelper.prototype.appendChild = goog.dom.appendChild;
-goog.dom.DomHelper.prototype.append = goog.dom.append;
-goog.dom.DomHelper.prototype.removeChildren = goog.dom.removeChildren;
-goog.dom.DomHelper.prototype.insertSiblingBefore = goog.dom.insertSiblingBefore;
-goog.dom.DomHelper.prototype.insertSiblingAfter = goog.dom.insertSiblingAfter;
-goog.dom.DomHelper.prototype.removeNode = goog.dom.removeNode;
-goog.dom.DomHelper.prototype.replaceNode = goog.dom.replaceNode;
-goog.dom.DomHelper.prototype.flattenElement = goog.dom.flattenElement;
-goog.dom.DomHelper.prototype.getFirstElementChild = goog.dom.getFirstElementChild;
-goog.dom.DomHelper.prototype.getLastElementChild = goog.dom.getLastElementChild;
-goog.dom.DomHelper.prototype.getNextElementSibling = goog.dom.getNextElementSibling;
-goog.dom.DomHelper.prototype.getPreviousElementSibling = goog.dom.getPreviousElementSibling;
-goog.dom.DomHelper.prototype.getNextNode = goog.dom.getNextNode;
-goog.dom.DomHelper.prototype.getPreviousNode = goog.dom.getPreviousNode;
-goog.dom.DomHelper.prototype.isNodeLike = goog.dom.isNodeLike;
-goog.dom.DomHelper.prototype.contains = goog.dom.contains;
-goog.dom.DomHelper.prototype.getOwnerDocument = goog.dom.getOwnerDocument;
-goog.dom.DomHelper.prototype.getFrameContentDocument = goog.dom.getFrameContentDocument;
-goog.dom.DomHelper.prototype.getFrameContentWindow = goog.dom.getFrameContentWindow;
-goog.dom.DomHelper.prototype.setTextContent = goog.dom.setTextContent;
-goog.dom.DomHelper.prototype.findNode = goog.dom.findNode;
-goog.dom.DomHelper.prototype.findNodes = goog.dom.findNodes;
-goog.dom.DomHelper.prototype.getTextContent = goog.dom.getTextContent;
-goog.dom.DomHelper.prototype.getNodeTextLength = goog.dom.getNodeTextLength;
-goog.dom.DomHelper.prototype.getNodeTextOffset = goog.dom.getNodeTextOffset;
-goog.dom.DomHelper.prototype.getAncestorByTagNameAndClass = goog.dom.getAncestorByTagNameAndClass;
-goog.dom.DomHelper.prototype.getAncestor = goog.dom.getAncestor;
-goog.provide("goog.Disposable");
-goog.provide("goog.dispose");
-goog.Disposable = function() {
-};
-goog.Disposable.prototype.disposed_ = false;
-goog.Disposable.prototype.isDisposed = function() {
- return this.disposed_
-};
-goog.Disposable.prototype.getDisposed = goog.Disposable.prototype.isDisposed;
-goog.Disposable.prototype.dispose = function() {
- if(!this.disposed_) {
- this.disposed_ = true;
- this.disposeInternal()
- }
-};
-goog.Disposable.prototype.disposeInternal = function() {
-};
-goog.dispose = function(obj) {
- if(obj && typeof obj.dispose == "function") {
- obj.dispose()
- }
-};
-goog.provide("goog.structs");
-goog.require("goog.array");
-goog.require("goog.object");
-goog.structs.getCount = function(col) {
- if(typeof col.getCount == "function") {
- return col.getCount()
- }
- if(goog.isArrayLike(col) || goog.isString(col)) {
- return col.length
- }
- return goog.object.getCount(col)
-};
-goog.structs.getValues = function(col) {
- if(typeof col.getValues == "function") {
- return col.getValues()
- }
- if(goog.isString(col)) {
- return col.split("")
- }
- if(goog.isArrayLike(col)) {
- var rv = [];
- var l = col.length;
- for(var i = 0;i < l;i++) {
- rv.push(col[i])
- }
- return rv
- }
- return goog.object.getValues(col)
-};
-goog.structs.getKeys = function(col) {
- if(typeof col.getKeys == "function") {
- return col.getKeys()
- }
- if(typeof col.getValues == "function") {
- return undefined
- }
- if(goog.isArrayLike(col) || goog.isString(col)) {
- var rv = [];
- var l = col.length;
- for(var i = 0;i < l;i++) {
- rv.push(i)
- }
- return rv
- }
- return goog.object.getKeys(col)
-};
-goog.structs.contains = function(col, val) {
- if(typeof col.contains == "function") {
- return col.contains(val)
- }
- if(typeof col.containsValue == "function") {
- return col.containsValue(val)
- }
- if(goog.isArrayLike(col) || goog.isString(col)) {
- return goog.array.contains(col, val)
- }
- return goog.object.containsValue(col, val)
-};
-goog.structs.isEmpty = function(col) {
- if(typeof col.isEmpty == "function") {
- return col.isEmpty()
- }
- if(goog.isArrayLike(col) || goog.isString(col)) {
- return goog.array.isEmpty(col)
- }
- return goog.object.isEmpty(col)
-};
-goog.structs.clear = function(col) {
- if(typeof col.clear == "function") {
- col.clear()
- }else {
- if(goog.isArrayLike(col)) {
- goog.array.clear(col)
- }else {
- goog.object.clear(col)
- }
- }
-};
-goog.structs.forEach = function(col, f, opt_obj) {
- if(typeof col.forEach == "function") {
- col.forEach(f, opt_obj)
- }else {
- if(goog.isArrayLike(col) || goog.isString(col)) {
- goog.array.forEach(col, f, opt_obj)
- }else {
- var keys = goog.structs.getKeys(col);
- var values = goog.structs.getValues(col);
- var l = values.length;
- for(var i = 0;i < l;i++) {
- f.call(opt_obj, values[i], keys && keys[i], col)
- }
- }
- }
-};
-goog.structs.filter = function(col, f, opt_obj) {
- if(typeof col.filter == "function") {
- return col.filter(f, opt_obj)
- }
- if(goog.isArrayLike(col) || goog.isString(col)) {
- return goog.array.filter(col, f, opt_obj)
- }
- var rv;
- var keys = goog.structs.getKeys(col);
- var values = goog.structs.getValues(col);
- var l = values.length;
- if(keys) {
- rv = {};
- for(var i = 0;i < l;i++) {
- if(f.call(opt_obj, values[i], keys[i], col)) {
- rv[keys[i]] = values[i]
- }
- }
- }else {
- rv = [];
- for(var i = 0;i < l;i++) {
- if(f.call(opt_obj, values[i], undefined, col)) {
- rv.push(values[i])
- }
- }
- }
- return rv
-};
-goog.structs.map = function(col, f, opt_obj) {
- if(typeof col.map == "function") {
- return col.map(f, opt_obj)
- }
- if(goog.isArrayLike(col) || goog.isString(col)) {
- return goog.array.map(col, f, opt_obj)
- }
- var rv;
- var keys = goog.structs.getKeys(col);
- var values = goog.structs.getValues(col);
- var l = values.length;
- if(keys) {
- rv = {};
- for(var i = 0;i < l;i++) {
- rv[keys[i]] = f.call(opt_obj, values[i], keys[i], col)
- }
- }else {
- rv = [];
- for(var i = 0;i < l;i++) {
- rv[i] = f.call(opt_obj, values[i], undefined, col)
- }
- }
- return rv
-};
-goog.structs.some = function(col, f, opt_obj) {
- if(typeof col.some == "function") {
- return col.some(f, opt_obj)
- }
- if(goog.isArrayLike(col) || goog.isString(col)) {
- return goog.array.some(col, f, opt_obj)
- }
- var keys = goog.structs.getKeys(col);
- var values = goog.structs.getValues(col);
- var l = values.length;
- for(var i = 0;i < l;i++) {
- if(f.call(opt_obj, values[i], keys && keys[i], col)) {
- return true
- }
- }
- return false
-};
-goog.structs.every = function(col, f, opt_obj) {
- if(typeof col.every == "function") {
- return col.every(f, opt_obj)
- }
- if(goog.isArrayLike(col) || goog.isString(col)) {
- return goog.array.every(col, f, opt_obj)
- }
- var keys = goog.structs.getKeys(col);
- var values = goog.structs.getValues(col);
- var l = values.length;
- for(var i = 0;i < l;i++) {
- if(!f.call(opt_obj, values[i], keys && keys[i], col)) {
- return false
- }
- }
- return true
-};
-goog.provide("goog.iter");
-goog.provide("goog.iter.Iterator");
-goog.provide("goog.iter.StopIteration");
-goog.require("goog.array");
-goog.iter.Iterable;
-if("StopIteration" in goog.global) {
- goog.iter.StopIteration = goog.global["StopIteration"]
-}else {
- goog.iter.StopIteration = Error("StopIteration")
-}
-goog.iter.Iterator = function() {
-};
-goog.iter.Iterator.prototype.next = function() {
- throw goog.iter.StopIteration;
-};
-goog.iter.Iterator.prototype.__iterator__ = function(opt_keys) {
- return this
-};
-goog.iter.toIterator = function(iterable) {
- if(iterable instanceof goog.iter.Iterator) {
- return iterable
- }
- if(typeof iterable.__iterator__ == "function") {
- return iterable.__iterator__(false)
- }
- if(goog.isArrayLike(iterable)) {
- var i = 0;
- var newIter = new goog.iter.Iterator;
- newIter.next = function() {
- while(true) {
- if(i >= iterable.length) {
- throw goog.iter.StopIteration;
- }
- if(!(i in iterable)) {
- i++;
- continue
- }
- return iterable[i++]
- }
- };
- return newIter
- }
- throw Error("Not implemented");
-};
-goog.iter.forEach = function(iterable, f, opt_obj) {
- if(goog.isArrayLike(iterable)) {
- try {
- goog.array.forEach(iterable, f, opt_obj)
- }catch(ex) {
- if(ex !== goog.iter.StopIteration) {
- throw ex;
- }
- }
- }else {
- iterable = goog.iter.toIterator(iterable);
- try {
- while(true) {
- f.call(opt_obj, iterable.next(), undefined, iterable)
- }
- }catch(ex) {
- if(ex !== goog.iter.StopIteration) {
- throw ex;
- }
- }
- }
-};
-goog.iter.filter = function(iterable, f, opt_obj) {
- iterable = goog.iter.toIterator(iterable);
- var newIter = new goog.iter.Iterator;
- newIter.next = function() {
- while(true) {
- var val = iterable.next();
- if(f.call(opt_obj, val, undefined, iterable)) {
- return val
- }
- }
- };
- return newIter
-};
-goog.iter.range = function(startOrStop, opt_stop, opt_step) {
- var start = 0;
- var stop = startOrStop;
- var step = opt_step || 1;
- if(arguments.length > 1) {
- start = startOrStop;
- stop = opt_stop
- }
- if(step == 0) {
- throw Error("Range step argument must not be zero");
- }
- var newIter = new goog.iter.Iterator;
- newIter.next = function() {
- if(step > 0 && start >= stop || step < 0 && start <= stop) {
- throw goog.iter.StopIteration;
- }
- var rv = start;
- start += step;
- return rv
- };
- return newIter
-};
-goog.iter.join = function(iterable, deliminator) {
- return goog.iter.toArray(iterable).join(deliminator)
-};
-goog.iter.map = function(iterable, f, opt_obj) {
- iterable = goog.iter.toIterator(iterable);
- var newIter = new goog.iter.Iterator;
- newIter.next = function() {
- while(true) {
- var val = iterable.next();
- return f.call(opt_obj, val, undefined, iterable)
- }
- };
- return newIter
-};
-goog.iter.reduce = function(iterable, f, val, opt_obj) {
- var rval = val;
- goog.iter.forEach(iterable, function(val) {
- rval = f.call(opt_obj, rval, val)
- });
- return rval
-};
-goog.iter.some = function(iterable, f, opt_obj) {
- iterable = goog.iter.toIterator(iterable);
- try {
- while(true) {
- if(f.call(opt_obj, iterable.next(), undefined, iterable)) {
- return true
- }
- }
- }catch(ex) {
- if(ex !== goog.iter.StopIteration) {
- throw ex;
- }
- }
- return false
-};
-goog.iter.every = function(iterable, f, opt_obj) {
- iterable = goog.iter.toIterator(iterable);
- try {
- while(true) {
- if(!f.call(opt_obj, iterable.next(), undefined, iterable)) {
- return false
- }
- }
- }catch(ex) {
- if(ex !== goog.iter.StopIteration) {
- throw ex;
- }
- }
- return true
-};
-goog.iter.chain = function(var_args) {
- var args = arguments;
- var length = args.length;
- var i = 0;
- var newIter = new goog.iter.Iterator;
- newIter.next = function() {
- try {
- if(i >= length) {
- throw goog.iter.StopIteration;
- }
- var current = goog.iter.toIterator(args[i]);
- return current.next()
- }catch(ex) {
- if(ex !== goog.iter.StopIteration || i >= length) {
- throw ex;
- }else {
- i++;
- return this.next()
- }
- }
- };
- return newIter
-};
-goog.iter.dropWhile = function(iterable, f, opt_obj) {
- iterable = goog.iter.toIterator(iterable);
- var newIter = new goog.iter.Iterator;
- var dropping = true;
- newIter.next = function() {
- while(true) {
- var val = iterable.next();
- if(dropping && f.call(opt_obj, val, undefined, iterable)) {
- continue
- }else {
- dropping = false
- }
- return val
- }
- };
- return newIter
-};
-goog.iter.takeWhile = function(iterable, f, opt_obj) {
- iterable = goog.iter.toIterator(iterable);
- var newIter = new goog.iter.Iterator;
- var taking = true;
- newIter.next = function() {
- while(true) {
- if(taking) {
- var val = iterable.next();
- if(f.call(opt_obj, val, undefined, iterable)) {
- return val
- }else {
- taking = false
- }
- }else {
- throw goog.iter.StopIteration;
- }
- }
- };
- return newIter
-};
-goog.iter.toArray = function(iterable) {
- if(goog.isArrayLike(iterable)) {
- return goog.array.toArray(iterable)
- }
- iterable = goog.iter.toIterator(iterable);
- var array = [];
- goog.iter.forEach(iterable, function(val) {
- array.push(val)
- });
- return array
-};
-goog.iter.equals = function(iterable1, iterable2) {
- iterable1 = goog.iter.toIterator(iterable1);
- iterable2 = goog.iter.toIterator(iterable2);
- var b1, b2;
- try {
- while(true) {
- b1 = b2 = false;
- var val1 = iterable1.next();
- b1 = true;
- var val2 = iterable2.next();
- b2 = true;
- if(val1 != val2) {
- return false
- }
- }
- }catch(ex) {
- if(ex !== goog.iter.StopIteration) {
- throw ex;
- }else {
- if(b1 && !b2) {
- return false
- }
- if(!b2) {
- try {
- val2 = iterable2.next();
- return false
- }catch(ex1) {
- if(ex1 !== goog.iter.StopIteration) {
- throw ex1;
- }
- return true
- }
- }
- }
- }
- return false
-};
-goog.iter.nextOrValue = function(iterable, defaultValue) {
- try {
- return goog.iter.toIterator(iterable).next()
- }catch(e) {
- if(e != goog.iter.StopIteration) {
- throw e;
- }
- return defaultValue
- }
-};
-goog.provide("goog.structs.Map");
-goog.require("goog.iter.Iterator");
-goog.require("goog.iter.StopIteration");
-goog.require("goog.object");
-goog.require("goog.structs");
-goog.structs.Map = function(opt_map, var_args) {
- this.map_ = {};
- this.keys_ = [];
- var argLength = arguments.length;
- if(argLength > 1) {
- if(argLength % 2) {
- throw Error("Uneven number of arguments");
- }
- for(var i = 0;i < argLength;i += 2) {
- this.set(arguments[i], arguments[i + 1])
- }
- }else {
- if(opt_map) {
- this.addAll(opt_map)
- }
- }
-};
-goog.structs.Map.prototype.count_ = 0;
-goog.structs.Map.prototype.version_ = 0;
-goog.structs.Map.prototype.getCount = function() {
- return this.count_
-};
-goog.structs.Map.prototype.getValues = function() {
- this.cleanupKeysArray_();
- var rv = [];
- for(var i = 0;i < this.keys_.length;i++) {
- var key = this.keys_[i];
- rv.push(this.map_[key])
- }
- return rv
-};
-goog.structs.Map.prototype.getKeys = function() {
- this.cleanupKeysArray_();
- return this.keys_.concat()
-};
-goog.structs.Map.prototype.containsKey = function(key) {
- return goog.structs.Map.hasKey_(this.map_, key)
-};
-goog.structs.Map.prototype.containsValue = function(val) {
- for(var i = 0;i < this.keys_.length;i++) {
- var key = this.keys_[i];
- if(goog.structs.Map.hasKey_(this.map_, key) && this.map_[key] == val) {
- return true
- }
- }
- return false
-};
-goog.structs.Map.prototype.equals = function(otherMap, opt_equalityFn) {
- if(this === otherMap) {
- return true
- }
- if(this.count_ != otherMap.getCount()) {
- return false
- }
- var equalityFn = opt_equalityFn || goog.structs.Map.defaultEquals;
- this.cleanupKeysArray_();
- for(var key, i = 0;key = this.keys_[i];i++) {
- if(!equalityFn(this.get(key), otherMap.get(key))) {
- return false
- }
- }
- return true
-};
-goog.structs.Map.defaultEquals = function(a, b) {
- return a === b
-};
-goog.structs.Map.prototype.isEmpty = function() {
- return this.count_ == 0
-};
-goog.structs.Map.prototype.clear = function() {
- this.map_ = {};
- this.keys_.length = 0;
- this.count_ = 0;
- this.version_ = 0
-};
-goog.structs.Map.prototype.remove = function(key) {
- if(goog.structs.Map.hasKey_(this.map_, key)) {
- delete this.map_[key];
- this.count_--;
- this.version_++;
- if(this.keys_.length > 2 * this.count_) {
- this.cleanupKeysArray_()
- }
- return true
- }
- return false
-};
-goog.structs.Map.prototype.cleanupKeysArray_ = function() {
- if(this.count_ != this.keys_.length) {
- var srcIndex = 0;
- var destIndex = 0;
- while(srcIndex < this.keys_.length) {
- var key = this.keys_[srcIndex];
- if(goog.structs.Map.hasKey_(this.map_, key)) {
- this.keys_[destIndex++] = key
- }
- srcIndex++
- }
- this.keys_.length = destIndex
- }
- if(this.count_ != this.keys_.length) {
- var seen = {};
- var srcIndex = 0;
- var destIndex = 0;
- while(srcIndex < this.keys_.length) {
- var key = this.keys_[srcIndex];
- if(!goog.structs.Map.hasKey_(seen, key)) {
- this.keys_[destIndex++] = key;
- seen[key] = 1
- }
- srcIndex++
- }
- this.keys_.length = destIndex
- }
-};
-goog.structs.Map.prototype.get = function(key, opt_val) {
- if(goog.structs.Map.hasKey_(this.map_, key)) {
- return this.map_[key]
- }
- return opt_val
-};
-goog.structs.Map.prototype.set = function(key, value) {
- if(!goog.structs.Map.hasKey_(this.map_, key)) {
- this.count_++;
- this.keys_.push(key);
- this.version_++
- }
- this.map_[key] = value
-};
-goog.structs.Map.prototype.addAll = function(map) {
- var keys, values;
- if(map instanceof goog.structs.Map) {
- keys = map.getKeys();
- values = map.getValues()
- }else {
- keys = goog.object.getKeys(map);
- values = goog.object.getValues(map)
- }
- for(var i = 0;i < keys.length;i++) {
- this.set(keys[i], values[i])
- }
-};
-goog.structs.Map.prototype.clone = function() {
- return new goog.structs.Map(this)
-};
-goog.structs.Map.prototype.transpose = function() {
- var transposed = new goog.structs.Map;
- for(var i = 0;i < this.keys_.length;i++) {
- var key = this.keys_[i];
- var value = this.map_[key];
- transposed.set(value, key)
- }
- return transposed
-};
-goog.structs.Map.prototype.toObject = function() {
- this.cleanupKeysArray_();
- var obj = {};
- for(var i = 0;i < this.keys_.length;i++) {
- var key = this.keys_[i];
- obj[key] = this.map_[key]
- }
- return obj
-};
-goog.structs.Map.prototype.getKeyIterator = function() {
- return this.__iterator__(true)
-};
-goog.structs.Map.prototype.getValueIterator = function() {
- return this.__iterator__(false)
-};
-goog.structs.Map.prototype.__iterator__ = function(opt_keys) {
- this.cleanupKeysArray_();
- var i = 0;
- var keys = this.keys_;
- var map = this.map_;
- var version = this.version_;
- var selfObj = this;
- var newIter = new goog.iter.Iterator;
- newIter.next = function() {
- while(true) {
- if(version != selfObj.version_) {
- throw Error("The map has changed since the iterator was created");
- }
- if(i >= keys.length) {
- throw goog.iter.StopIteration;
- }
- var key = keys[i++];
- return opt_keys ? key : map[key]
- }
- };
- return newIter
-};
-goog.structs.Map.hasKey_ = function(obj, key) {
- return Object.prototype.hasOwnProperty.call(obj, key)
-};
-goog.provide("goog.structs.Set");
-goog.require("goog.structs");
-goog.require("goog.structs.Map");
-goog.structs.Set = function(opt_values) {
- this.map_ = new goog.structs.Map;
- if(opt_values) {
- this.addAll(opt_values)
- }
-};
-goog.structs.Set.getKey_ = function(val) {
- var type = typeof val;
- if(type == "object" && val || type == "function") {
- return"o" + goog.getUid(val)
- }else {
- return type.substr(0, 1) + val
- }
-};
-goog.structs.Set.prototype.getCount = function() {
- return this.map_.getCount()
-};
-goog.structs.Set.prototype.add = function(element) {
- this.map_.set(goog.structs.Set.getKey_(element), element)
-};
-goog.structs.Set.prototype.addAll = function(col) {
- var values = goog.structs.getValues(col);
- var l = values.length;
- for(var i = 0;i < l;i++) {
- this.add(values[i])
- }
-};
-goog.structs.Set.prototype.removeAll = function(col) {
- var values = goog.structs.getValues(col);
- var l = values.length;
- for(var i = 0;i < l;i++) {
- this.remove(values[i])
- }
-};
-goog.structs.Set.prototype.remove = function(element) {
- return this.map_.remove(goog.structs.Set.getKey_(element))
-};
-goog.structs.Set.prototype.clear = function() {
- this.map_.clear()
-};
-goog.structs.Set.prototype.isEmpty = function() {
- return this.map_.isEmpty()
-};
-goog.structs.Set.prototype.contains = function(element) {
- return this.map_.containsKey(goog.structs.Set.getKey_(element))
-};
-goog.structs.Set.prototype.containsAll = function(col) {
- return goog.structs.every(col, this.contains, this)
-};
-goog.structs.Set.prototype.intersection = function(col) {
- var result = new goog.structs.Set;
- var values = goog.structs.getValues(col);
- for(var i = 0;i < values.length;i++) {
- var value = values[i];
- if(this.contains(value)) {
- result.add(value)
- }
- }
- return result
-};
-goog.structs.Set.prototype.getValues = function() {
- return this.map_.getValues()
-};
-goog.structs.Set.prototype.clone = function() {
- return new goog.structs.Set(this)
-};
-goog.structs.Set.prototype.equals = function(col) {
- return this.getCount() == goog.structs.getCount(col) && this.isSubsetOf(col)
-};
-goog.structs.Set.prototype.isSubsetOf = function(col) {
- var colCount = goog.structs.getCount(col);
- if(this.getCount() > colCount) {
- return false
- }
- if(!(col instanceof goog.structs.Set) && colCount > 5) {
- col = new goog.structs.Set(col)
- }
- return goog.structs.every(this, function(value) {
- return goog.structs.contains(col, value)
- })
-};
-goog.structs.Set.prototype.__iterator__ = function(opt_keys) {
- return this.map_.__iterator__(false)
-};
-goog.provide("goog.debug");
-goog.require("goog.array");
-goog.require("goog.string");
-goog.require("goog.structs.Set");
-goog.debug.catchErrors = function(logFunc, opt_cancel, opt_target) {
- var target = opt_target || goog.global;
- var oldErrorHandler = target.onerror;
- target.onerror = function(message, url, line) {
- if(oldErrorHandler) {
- oldErrorHandler(message, url, line)
- }
- logFunc({message:message, fileName:url, line:line});
- return Boolean(opt_cancel)
- }
-};
-goog.debug.expose = function(obj, opt_showFn) {
- if(typeof obj == "undefined") {
- return"undefined"
- }
- if(obj == null) {
- return"NULL"
- }
- var str = [];
- for(var x in obj) {
- if(!opt_showFn && goog.isFunction(obj[x])) {
- continue
- }
- var s = x + " = ";
- try {
- s += obj[x]
- }catch(e) {
- s += "*** " + e + " ***"
- }
- str.push(s)
- }
- return str.join("\n")
-};
-goog.debug.deepExpose = function(obj, opt_showFn) {
- var previous = new goog.structs.Set;
- var str = [];
- var helper = function(obj, space) {
- var nestspace = space + " ";
- var indentMultiline = function(str) {
- return str.replace(/\n/g, "\n" + space)
- };
- try {
- if(!goog.isDef(obj)) {
- str.push("undefined")
- }else {
- if(goog.isNull(obj)) {
- str.push("NULL")
- }else {
- if(goog.isString(obj)) {
- str.push('"' + indentMultiline(obj) + '"')
- }else {
- if(goog.isFunction(obj)) {
- str.push(indentMultiline(String(obj)))
- }else {
- if(goog.isObject(obj)) {
- if(previous.contains(obj)) {
- str.push("*** reference loop detected ***")
- }else {
- previous.add(obj);
- str.push("{");
- for(var x in obj) {
- if(!opt_showFn && goog.isFunction(obj[x])) {
- continue
- }
- str.push("\n");
- str.push(nestspace);
- str.push(x + " = ");
- helper(obj[x], nestspace)
- }
- str.push("\n" + space + "}")
- }
- }else {
- str.push(obj)
- }
- }
- }
- }
- }
- }catch(e) {
- str.push("*** " + e + " ***")
- }
- };
- helper(obj, "");
- return str.join("")
-};
-goog.debug.exposeArray = function(arr) {
- var str = [];
- for(var i = 0;i < arr.length;i++) {
- if(goog.isArray(arr[i])) {
- str.push(goog.debug.exposeArray(arr[i]))
- }else {
- str.push(arr[i])
- }
- }
- return"[ " + str.join(", ") + " ]"
-};
-goog.debug.exposeException = function(err, opt_fn) {
- try {
- var e = goog.debug.normalizeErrorObject(err);
- var error = "Message: " + goog.string.htmlEscape(e.message) + '\nUrl: <a href="view-source:' + e.fileName + '" target="_new">' + e.fileName + "</a>\nLine: " + e.lineNumber + "\n\nBrowser stack:\n" + goog.string.htmlEscape(e.stack + "-> ") + "[end]\n\nJS stack traversal:\n" + goog.string.htmlEscape(goog.debug.getStacktrace(opt_fn) + "-> ");
- return error
- }catch(e2) {
- return"Exception trying to expose exception! You win, we lose. " + e2
- }
-};
-goog.debug.normalizeErrorObject = function(err) {
- var href = goog.getObjectByName("window.location.href");
- return typeof err == "string" ? {message:err, name:"Unknown error", lineNumber:"Not available", fileName:href, stack:"Not available"} : !err.lineNumber || !err.fileName || !err.stack ? {message:err.message, name:err.name, lineNumber:err.lineNumber || err.line || "Not available", fileName:err.fileName || err.filename || err.sourceURL || href, stack:err.stack || "Not available"} : err
-};
-goog.debug.enhanceError = function(err, opt_message) {
- var error = typeof err == "string" ? Error(err) : err;
- if(!error.stack) {
- error.stack = goog.debug.getStacktrace(arguments.callee.caller)
- }
- if(opt_message) {
- var x = 0;
- while(error["message" + x]) {
- ++x
- }
- error["message" + x] = String(opt_message)
- }
- return error
-};
-goog.debug.getStacktraceSimple = function(opt_depth) {
- var sb = [];
- var fn = arguments.callee.caller;
- var depth = 0;
- while(fn && (!opt_depth || depth < opt_depth)) {
- sb.push(goog.debug.getFunctionName(fn));
- sb.push("()\n");
- try {
- fn = fn.caller
- }catch(e) {
- sb.push("[exception trying to get caller]\n");
- break
- }
- depth++;
- if(depth >= goog.debug.MAX_STACK_DEPTH) {
- sb.push("[...long stack...]");
- break
- }
- }
- if(opt_depth && depth >= opt_depth) {
- sb.push("[...reached max depth limit...]")
- }else {
- sb.push("[end]")
- }
- return sb.join("")
-};
-goog.debug.MAX_STACK_DEPTH = 50;
-goog.debug.getStacktrace = function(opt_fn) {
- return goog.debug.getStacktraceHelper_(opt_fn || arguments.callee.caller, [])
-};
-goog.debug.getStacktraceHelper_ = function(fn, visited) {
- var sb = [];
- if(goog.array.contains(visited, fn)) {
- sb.push("[...circular reference...]")
- }else {
- if(fn && visited.length < goog.debug.MAX_STACK_DEPTH) {
- sb.push(goog.debug.getFunctionName(fn) + "(");
- var args = fn.arguments;
- for(var i = 0;i < args.length;i++) {
- if(i > 0) {
- sb.push(", ")
- }
- var argDesc;
- var arg = args[i];
- switch(typeof arg) {
- case "object":
- argDesc = arg ? "object" : "null";
- break;
- case "string":
- argDesc = arg;
- break;
- case "number":
- argDesc = String(arg);
- break;
- case "boolean":
- argDesc = arg ? "true" : "false";
- break;
- case "function":
- argDesc = goog.debug.getFunctionName(arg);
- argDesc = argDesc ? argDesc : "[fn]";
- break;
- case "undefined":
- ;
- default:
- argDesc = typeof arg;
- break
- }
- if(argDesc.length > 40) {
- argDesc = argDesc.substr(0, 40) + "..."
- }
- sb.push(argDesc)
- }
- visited.push(fn);
- sb.push(")\n");
- try {
- sb.push(goog.debug.getStacktraceHelper_(fn.caller, visited))
- }catch(e) {
- sb.push("[exception trying to get caller]\n")
- }
- }else {
- if(fn) {
- sb.push("[...long stack...]")
- }else {
- sb.push("[end]")
- }
- }
- }
- return sb.join("")
-};
-goog.debug.getFunctionName = function(fn) {
- var functionSource = String(fn);
- if(!goog.debug.fnNameCache_[functionSource]) {
- var matches = /function ([^\(]+)/.exec(functionSource);
- if(matches) {
- var method = matches[1];
- goog.debug.fnNameCache_[functionSource] = method
- }else {
- goog.debug.fnNameCache_[functionSource] = "[Anonymous]"
- }
- }
- return goog.debug.fnNameCache_[functionSource]
-};
-goog.debug.makeWhitespaceVisible = function(string) {
- return string.replace(/ /g, "[_]").replace(/\f/g, "[f]").replace(/\n/g, "[n]\n").replace(/\r/g, "[r]").replace(/\t/g, "[t]")
-};
-goog.debug.fnNameCache_ = {};
-goog.provide("goog.debug.LogRecord");
-goog.debug.LogRecord = function(level, msg, loggerName, opt_time, opt_sequenceNumber) {
- this.reset(level, msg, loggerName, opt_time, opt_sequenceNumber)
-};
-goog.debug.LogRecord.prototype.time_;
-goog.debug.LogRecord.prototype.level_;
-goog.debug.LogRecord.prototype.msg_;
-goog.debug.LogRecord.prototype.loggerName_;
-goog.debug.LogRecord.prototype.sequenceNumber_ = 0;
-goog.debug.LogRecord.prototype.exception_ = null;
-goog.debug.LogRecord.prototype.exceptionText_ = null;
-goog.debug.LogRecord.ENABLE_SEQUENCE_NUMBERS = true;
-goog.debug.LogRecord.nextSequenceNumber_ = 0;
-goog.debug.LogRecord.prototype.reset = function(level, msg, loggerName, opt_time, opt_sequenceNumber) {
- if(goog.debug.LogRecord.ENABLE_SEQUENCE_NUMBERS) {
- this.sequenceNumber_ = typeof opt_sequenceNumber == "number" ? opt_sequenceNumber : goog.debug.LogRecord.nextSequenceNumber_++
- }
- this.time_ = opt_time || goog.now();
- this.level_ = level;
- this.msg_ = msg;
- this.loggerName_ = loggerName;
- delete this.exception_;
- delete this.exceptionText_
-};
-goog.debug.LogRecord.prototype.getLoggerName = function() {
- return this.loggerName_
-};
-goog.debug.LogRecord.prototype.getException = function() {
- return this.exception_
-};
-goog.debug.LogRecord.prototype.setException = function(exception) {
- this.exception_ = exception
-};
-goog.debug.LogRecord.prototype.getExceptionText = function() {
- return this.exceptionText_
-};
-goog.debug.LogRecord.prototype.setExceptionText = function(text) {
- this.exceptionText_ = text
-};
-goog.debug.LogRecord.prototype.setLoggerName = function(loggerName) {
- this.loggerName_ = loggerName
-};
-goog.debug.LogRecord.prototype.getLevel = function() {
- return this.level_
-};
-goog.debug.LogRecord.prototype.setLevel = function(level) {
- this.level_ = level
-};
-goog.debug.LogRecord.prototype.getMessage = function() {
- return this.msg_
-};
-goog.debug.LogRecord.prototype.setMessage = function(msg) {
- this.msg_ = msg
-};
-goog.debug.LogRecord.prototype.getMillis = function() {
- return this.time_
-};
-goog.debug.LogRecord.prototype.setMillis = function(time) {
- this.time_ = time
-};
-goog.debug.LogRecord.prototype.getSequenceNumber = function() {
- return this.sequenceNumber_
-};
-goog.provide("goog.debug.LogBuffer");
-goog.require("goog.asserts");
-goog.require("goog.debug.LogRecord");
-goog.debug.LogBuffer = function() {
- goog.asserts.assert(goog.debug.LogBuffer.isBufferingEnabled(), "Cannot use goog.debug.LogBuffer without defining " + "goog.debug.LogBuffer.CAPACITY.");
- this.clear()
-};
-goog.debug.LogBuffer.getInstance = function() {
- if(!goog.debug.LogBuffer.instance_) {
- goog.debug.LogBuffer.instance_ = new goog.debug.LogBuffer
- }
- return goog.debug.LogBuffer.instance_
-};
-goog.debug.LogBuffer.CAPACITY = 0;
-goog.debug.LogBuffer.prototype.buffer_;
-goog.debug.LogBuffer.prototype.curIndex_;
-goog.debug.LogBuffer.prototype.isFull_;
-goog.debug.LogBuffer.prototype.addRecord = function(level, msg, loggerName) {
- var curIndex = (this.curIndex_ + 1) % goog.debug.LogBuffer.CAPACITY;
- this.curIndex_ = curIndex;
- if(this.isFull_) {
- var ret = this.buffer_[curIndex];
- ret.reset(level, msg, loggerName);
- return ret
- }
- this.isFull_ = curIndex == goog.debug.LogBuffer.CAPACITY - 1;
- return this.buffer_[curIndex] = new goog.debug.LogRecord(level, msg, loggerName)
-};
-goog.debug.LogBuffer.isBufferingEnabled = function() {
- return goog.debug.LogBuffer.CAPACITY > 0
-};
-goog.debug.LogBuffer.prototype.clear = function() {
- this.buffer_ = new Array(goog.debug.LogBuffer.CAPACITY);
- this.curIndex_ = -1;
- this.isFull_ = false
-};
-goog.debug.LogBuffer.prototype.forEachRecord = function(func) {
- var buffer = this.buffer_;
- if(!buffer[0]) {
- return
- }
- var curIndex = this.curIndex_;
- var i = this.isFull_ ? curIndex : -1;
- do {
- i = (i + 1) % goog.debug.LogBuffer.CAPACITY;
- func(buffer[i])
- }while(i != curIndex)
-};
-goog.provide("goog.debug.LogManager");
-goog.provide("goog.debug.Logger");
-goog.provide("goog.debug.Logger.Level");
-goog.require("goog.array");
-goog.require("goog.asserts");
-goog.require("goog.debug");
-goog.require("goog.debug.LogBuffer");
-goog.require("goog.debug.LogRecord");
-goog.debug.Logger = function(name) {
- this.name_ = name
-};
-goog.debug.Logger.prototype.parent_ = null;
-goog.debug.Logger.prototype.level_ = null;
-goog.debug.Logger.prototype.children_ = null;
-goog.debug.Logger.prototype.handlers_ = null;
-goog.debug.Logger.ENABLE_HIERARCHY = true;
-if(!goog.debug.Logger.ENABLE_HIERARCHY) {
- goog.debug.Logger.rootHandlers_ = [];
- goog.debug.Logger.rootLevel_
-}
-goog.debug.Logger.Level = function(name, value) {
- this.name = name;
- this.value = value
-};
-goog.debug.Logger.Level.prototype.toString = function() {
- return this.name
-};
-goog.debug.Logger.Level.OFF = new goog.debug.Logger.Level("OFF", Infinity);
-goog.debug.Logger.Level.SHOUT = new goog.debug.Logger.Level("SHOUT", 1200);
-goog.debug.Logger.Level.SEVERE = new goog.debug.Logger.Level("SEVERE", 1E3);
-goog.debug.Logger.Level.WARNING = new goog.debug.Logger.Level("WARNING", 900);
-goog.debug.Logger.Level.INFO = new goog.debug.Logger.Level("INFO", 800);
-goog.debug.Logger.Level.CONFIG = new goog.debug.Logger.Level("CONFIG", 700);
-goog.debug.Logger.Level.FINE = new goog.debug.Logger.Level("FINE", 500);
-goog.debug.Logger.Level.FINER = new goog.debug.Logger.Level("FINER", 400);
-goog.debug.Logger.Level.FINEST = new goog.debug.Logger.Level("FINEST", 300);
-goog.debug.Logger.Level.ALL = new goog.debug.Logger.Level("ALL", 0);
-goog.debug.Logger.Level.PREDEFINED_LEVELS = [goog.debug.Logger.Level.OFF, goog.debug.Logger.Level.SHOUT, goog.debug.Logger.Level.SEVERE, goog.debug.Logger.Level.WARNING, goog.debug.Logger.Level.INFO, goog.debug.Logger.Level.CONFIG, goog.debug.Logger.Level.FINE, goog.debug.Logger.Level.FINER, goog.debug.Logger.Level.FINEST, goog.debug.Logger.Level.ALL];
-goog.debug.Logger.Level.predefinedLevelsCache_ = null;
-goog.debug.Logger.Level.createPredefinedLevelsCache_ = function() {
- goog.debug.Logger.Level.predefinedLevelsCache_ = {};
- for(var i = 0, level;level = goog.debug.Logger.Level.PREDEFINED_LEVELS[i];i++) {
- goog.debug.Logger.Level.predefinedLevelsCache_[level.value] = level;
- goog.debug.Logger.Level.predefinedLevelsCache_[level.name] = level
- }
-};
-goog.debug.Logger.Level.getPredefinedLevel = function(name) {
- if(!goog.debug.Logger.Level.predefinedLevelsCache_) {
- goog.debug.Logger.Level.createPredefinedLevelsCache_()
- }
- return goog.debug.Logger.Level.predefinedLevelsCache_[name] || null
-};
-goog.debug.Logger.Level.getPredefinedLevelByValue = function(value) {
- if(!goog.debug.Logger.Level.predefinedLevelsCache_) {
- goog.debug.Logger.Level.createPredefinedLevelsCache_()
- }
- if(value in goog.debug.Logger.Level.predefinedLevelsCache_) {
- return goog.debug.Logger.Level.predefinedLevelsCache_[value]
- }
- for(var i = 0;i < goog.debug.Logger.Level.PREDEFINED_LEVELS.length;++i) {
- var level = goog.debug.Logger.Level.PREDEFINED_LEVELS[i];
- if(level.value <= value) {
- return level
- }
- }
- return null
-};
-goog.debug.Logger.getLogger = function(name) {
- return goog.debug.LogManager.getLogger(name)
-};
-goog.debug.Logger.prototype.getName = function() {
- return this.name_
-};
-goog.debug.Logger.prototype.addHandler = function(handler) {
- if(goog.debug.Logger.ENABLE_HIERARCHY) {
- if(!this.handlers_) {
- this.handlers_ = []
- }
- this.handlers_.push(handler)
- }else {
- goog.asserts.assert(!this.name_, "Cannot call addHandler on a non-root logger when " + "goog.debug.Logger.ENABLE_HIERARCHY is false.");
- goog.debug.Logger.rootHandlers_.push(handler)
- }
-};
-goog.debug.Logger.prototype.removeHandler = function(handler) {
- var handlers = goog.debug.Logger.ENABLE_HIERARCHY ? this.handlers_ : goog.debug.Logger.rootHandlers_;
- return!!handlers && goog.array.remove(handlers, handler)
-};
-goog.debug.Logger.prototype.getParent = function() {
- return this.parent_
-};
-goog.debug.Logger.prototype.getChildren = function() {
- if(!this.children_) {
- this.children_ = {}
- }
- return this.children_
-};
-goog.debug.Logger.prototype.setLevel = function(level) {
- if(goog.debug.Logger.ENABLE_HIERARCHY) {
- this.level_ = level
- }else {
- goog.asserts.assert(!this.name_, "Cannot call setLevel() on a non-root logger when " + "goog.debug.Logger.ENABLE_HIERARCHY is false.");
- goog.debug.Logger.rootLevel_ = level
- }
-};
-goog.debug.Logger.prototype.getLevel = function() {
- return this.level_
-};
-goog.debug.Logger.prototype.getEffectiveLevel = function() {
- if(!goog.debug.Logger.ENABLE_HIERARCHY) {
- return goog.debug.Logger.rootLevel_
- }
- if(this.level_) {
- return this.level_
- }
- if(this.parent_) {
- return this.parent_.getEffectiveLevel()
- }
- goog.asserts.fail("Root logger has no level set.");
- return null
-};
-goog.debug.Logger.prototype.isLoggable = function(level) {
- return level.value >= this.getEffectiveLevel().value
-};
-goog.debug.Logger.prototype.log = function(level, msg, opt_exception) {
- if(this.isLoggable(level)) {
- this.doLogRecord_(this.getLogRecord(level, msg, opt_exception))
- }
-};
-goog.debug.Logger.prototype.getLogRecord = function(level, msg, opt_exception) {
- if(goog.debug.LogBuffer.isBufferingEnabled()) {
- var logRecord = goog.debug.LogBuffer.getInstance().addRecord(level, msg, this.name_)
- }else {
- logRecord = new goog.debug.LogRecord(level, String(msg), this.name_)
- }
- if(opt_exception) {
- logRecord.setException(opt_exception);
- logRecord.setExceptionText(goog.debug.exposeException(opt_exception, arguments.callee.caller))
- }
- return logRecord
-};
-goog.debug.Logger.prototype.shout = function(msg, opt_exception) {
- this.log(goog.debug.Logger.Level.SHOUT, msg, opt_exception)
-};
-goog.debug.Logger.prototype.severe = function(msg, opt_exception) {
- this.log(goog.debug.Logger.Level.SEVERE, msg, opt_exception)
-};
-goog.debug.Logger.prototype.warning = function(msg, opt_exception) {
- this.log(goog.debug.Logger.Level.WARNING, msg, opt_exception)
-};
-goog.debug.Logger.prototype.info = function(msg, opt_exception) {
- this.log(goog.debug.Logger.Level.INFO, msg, opt_exception)
-};
-goog.debug.Logger.prototype.config = function(msg, opt_exception) {
- this.log(goog.debug.Logger.Level.CONFIG, msg, opt_exception)
-};
-goog.debug.Logger.prototype.fine = function(msg, opt_exception) {
- this.log(goog.debug.Logger.Level.FINE, msg, opt_exception)
-};
-goog.debug.Logger.prototype.finer = function(msg, opt_exception) {
- this.log(goog.debug.Logger.Level.FINER, msg, opt_exception)
-};
-goog.debug.Logger.prototype.finest = function(msg, opt_exception) {
- this.log(goog.debug.Logger.Level.FINEST, msg, opt_exception)
-};
-goog.debug.Logger.prototype.logRecord = function(logRecord) {
- if(this.isLoggable(logRecord.getLevel())) {
- this.doLogRecord_(logRecord)
- }
-};
-goog.debug.Logger.prototype.doLogRecord_ = function(logRecord) {
- if(goog.debug.Logger.ENABLE_HIERARCHY) {
- var target = this;
- while(target) {
- target.callPublish_(logRecord);
- target = target.getParent()
- }
- }else {
- for(var i = 0, handler;handler = goog.debug.Logger.rootHandlers_[i++];) {
- handler(logRecord)
- }
- }
-};
-goog.debug.Logger.prototype.callPublish_ = function(logRecord) {
- if(this.handlers_) {
- for(var i = 0, handler;handler = this.handlers_[i];i++) {
- handler(logRecord)
- }
- }
-};
-goog.debug.Logger.prototype.setParent_ = function(parent) {
- this.parent_ = parent
-};
-goog.debug.Logger.prototype.addChild_ = function(name, logger) {
- this.getChildren()[name] = logger
-};
-goog.debug.LogManager = {};
-goog.debug.LogManager.loggers_ = {};
-goog.debug.LogManager.rootLogger_ = null;
-goog.debug.LogManager.initialize = function() {
- if(!goog.debug.LogManager.rootLogger_) {
- goog.debug.LogManager.rootLogger_ = new goog.debug.Logger("");
- goog.debug.LogManager.loggers_[""] = goog.debug.LogManager.rootLogger_;
- goog.debug.LogManager.rootLogger_.setLevel(goog.debug.Logger.Level.CONFIG)
- }
-};
-goog.debug.LogManager.getLoggers = function() {
- return goog.debug.LogManager.loggers_
-};
-goog.debug.LogManager.getRoot = function() {
- goog.debug.LogManager.initialize();
- return goog.debug.LogManager.rootLogger_
-};
-goog.debug.LogManager.getLogger = function(name) {
- goog.debug.LogManager.initialize();
- var ret = goog.debug.LogManager.loggers_[name];
- return ret || goog.debug.LogManager.createLogger_(name)
-};
-goog.debug.LogManager.createFunctionForCatchErrors = function(opt_logger) {
- return function(info) {
- var logger = opt_logger || goog.debug.LogManager.getRoot();
- logger.severe("Error: " + info.message + " (" + info.fileName + " @ Line: " + info.line + ")")
- }
-};
-goog.debug.LogManager.createLogger_ = function(name) {
- var logger = new goog.debug.Logger(name);
- if(goog.debug.Logger.ENABLE_HIERARCHY) {
- var lastDotIndex = name.lastIndexOf(".");
- var parentName = name.substr(0, lastDotIndex);
- var leafName = name.substr(lastDotIndex + 1);
- var parentLogger = goog.debug.LogManager.getLogger(parentName);
- parentLogger.addChild_(leafName, logger);
- logger.setParent_(parentLogger)
- }
- goog.debug.LogManager.loggers_[name] = logger;
- return logger
-};
-goog.provide("goog.dom.SavedRange");
-goog.require("goog.Disposable");
-goog.require("goog.debug.Logger");
-goog.dom.SavedRange = function() {
- goog.Disposable.call(this)
-};
-goog.inherits(goog.dom.SavedRange, goog.Disposable);
-goog.dom.SavedRange.logger_ = goog.debug.Logger.getLogger("goog.dom.SavedRange");
-goog.dom.SavedRange.prototype.restore = function(opt_stayAlive) {
- if(this.isDisposed()) {
- goog.dom.SavedRange.logger_.severe("Disposed SavedRange objects cannot be restored.")
- }
- var range = this.restoreInternal();
- if(!opt_stayAlive) {
- this.dispose()
- }
- return range
-};
-goog.dom.SavedRange.prototype.restoreInternal = goog.abstractMethod;
-goog.provide("goog.dom.SavedCaretRange");
-goog.require("goog.array");
-goog.require("goog.dom");
-goog.require("goog.dom.SavedRange");
-goog.require("goog.dom.TagName");
-goog.require("goog.string");
-goog.dom.SavedCaretRange = function(range) {
- goog.dom.SavedRange.call(this);
- this.startCaretId_ = goog.string.createUniqueString();
- this.endCaretId_ = goog.string.createUniqueString();
- this.dom_ = goog.dom.getDomHelper(range.getDocument());
- range.surroundWithNodes(this.createCaret_(true), this.createCaret_(false))
-};
-goog.inherits(goog.dom.SavedCaretRange, goog.dom.SavedRange);
-goog.dom.SavedCaretRange.prototype.toAbstractRange = function() {
- var range = null;
- var startCaret = this.getCaret(true);
- var endCaret = this.getCaret(false);
- if(startCaret && endCaret) {
- range = goog.dom.Range.createFromNodes(startCaret, 0, endCaret, 0)
- }
- return range
-};
-goog.dom.SavedCaretRange.prototype.getCaret = function(start) {
- return this.dom_.getElement(start ? this.startCaretId_ : this.endCaretId_)
-};
-goog.dom.SavedCaretRange.prototype.removeCarets = function(opt_range) {
- goog.dom.removeNode(this.getCaret(true));
- goog.dom.removeNode(this.getCaret(false));
- return opt_range
-};
-goog.dom.SavedCaretRange.prototype.setRestorationDocument = function(doc) {
- this.dom_.setDocument(doc)
-};
-goog.dom.SavedCaretRange.prototype.restoreInternal = function() {
- var range = null;
- var startCaret = this.getCaret(true);
- var endCaret = this.getCaret(false);
- if(startCaret && endCaret) {
- var startNode = startCaret.parentNode;
- var startOffset = goog.array.indexOf(startNode.childNodes, startCaret);
- var endNode = endCaret.parentNode;
- var endOffset = goog.array.indexOf(endNode.childNodes, endCaret);
- if(endNode == startNode) {
- endOffset -= 1
- }
- range = goog.dom.Range.createFromNodes(startNode, startOffset, endNode, endOffset);
- range = this.removeCarets(range);
- range.select()
- }else {
- this.removeCarets()
- }
- return range
-};
-goog.dom.SavedCaretRange.prototype.disposeInternal = function() {
- this.removeCarets();
- this.dom_ = null
-};
-goog.dom.SavedCaretRange.prototype.createCaret_ = function(start) {
- return this.dom_.createDom(goog.dom.TagName.SPAN, {id:start ? this.startCaretId_ : this.endCaretId_})
-};
-goog.dom.SavedCaretRange.CARET_REGEX = /<span\s+id="?goog_\d+"?><\/span>/ig;
-goog.dom.SavedCaretRange.htmlEqual = function(str1, str2) {
- return str1 == str2 || str1.replace(goog.dom.SavedCaretRange.CARET_REGEX, "") == str2.replace(goog.dom.SavedCaretRange.CARET_REGEX, "")
-};
-goog.provide("goog.dom.TagIterator");
-goog.provide("goog.dom.TagWalkType");
-goog.require("goog.dom.NodeType");
-goog.require("goog.iter.Iterator");
-goog.require("goog.iter.StopIteration");
-goog.dom.TagWalkType = {START_TAG:1, OTHER:0, END_TAG:-1};
-goog.dom.TagIterator = function(opt_node, opt_reversed, opt_unconstrained, opt_tagType, opt_depth) {
- this.reversed = !!opt_reversed;
- if(opt_node) {
- this.setPosition(opt_node, opt_tagType)
- }
- this.depth = opt_depth != undefined ? opt_depth : this.tagType || 0;
- if(this.reversed) {
- this.depth *= -1
- }
- this.constrained = !opt_unconstrained
-};
-goog.inherits(goog.dom.TagIterator, goog.iter.Iterator);
-goog.dom.TagIterator.prototype.node = null;
-goog.dom.TagIterator.prototype.tagType = goog.dom.TagWalkType.OTHER;
-goog.dom.TagIterator.prototype.depth;
-goog.dom.TagIterator.prototype.reversed;
-goog.dom.TagIterator.prototype.constrained;
-goog.dom.TagIterator.prototype.started_ = false;
-goog.dom.TagIterator.prototype.setPosition = function(node, opt_tagType, opt_depth) {
- this.node = node;
- if(node) {
- if(goog.isNumber(opt_tagType)) {
- this.tagType = opt_tagType
- }else {
- this.tagType = this.node.nodeType != goog.dom.NodeType.ELEMENT ? goog.dom.TagWalkType.OTHER : this.reversed ? goog.dom.TagWalkType.END_TAG : goog.dom.TagWalkType.START_TAG
- }
- }
- if(goog.isNumber(opt_depth)) {
- this.depth = opt_depth
- }
-};
-goog.dom.TagIterator.prototype.copyFrom = function(other) {
- this.node = other.node;
- this.tagType = other.tagType;
- this.depth = other.depth;
- this.reversed = other.reversed;
- this.constrained = other.constrained
-};
-goog.dom.TagIterator.prototype.clone = function() {
- return new goog.dom.TagIterator(this.node, this.reversed, !this.constrained, this.tagType, this.depth)
-};
-goog.dom.TagIterator.prototype.skipTag = function() {
- var check = this.reversed ? goog.dom.TagWalkType.END_TAG : goog.dom.TagWalkType.START_TAG;
- if(this.tagType == check) {
- this.tagType = check * -1;
- this.depth += this.tagType * (this.reversed ? -1 : 1)
- }
-};
-goog.dom.TagIterator.prototype.restartTag = function() {
- var check = this.reversed ? goog.dom.TagWalkType.START_TAG : goog.dom.TagWalkType.END_TAG;
- if(this.tagType == check) {
- this.tagType = check * -1;
- this.depth += this.tagType * (this.reversed ? -1 : 1)
- }
-};
-goog.dom.TagIterator.prototype.next = function() {
- var node;
- if(this.started_) {
- if(!this.node || this.constrained && this.depth == 0) {
- throw goog.iter.StopIteration;
- }
- node = this.node;
- var startType = this.reversed ? goog.dom.TagWalkType.END_TAG : goog.dom.TagWalkType.START_TAG;
- if(this.tagType == startType) {
- var child = this.reversed ? node.lastChild : node.firstChild;
- if(child) {
- this.setPosition(child)
- }else {
- this.setPosition(node, startType * -1)
- }
- }else {
- var sibling = this.reversed ? node.previousSibling : node.nextSibling;
- if(sibling) {
- this.setPosition(sibling)
- }else {
- this.setPosition(node.parentNode, startType * -1)
- }
- }
- this.depth += this.tagType * (this.reversed ? -1 : 1)
- }else {
- this.started_ = true
- }
- node = this.node;
- if(!this.node) {
- throw goog.iter.StopIteration;
- }
- return node
-};
-goog.dom.TagIterator.prototype.isStarted = function() {
- return this.started_
-};
-goog.dom.TagIterator.prototype.isStartTag = function() {
- return this.tagType == goog.dom.TagWalkType.START_TAG
-};
-goog.dom.TagIterator.prototype.isEndTag = function() {
- return this.tagType == goog.dom.TagWalkType.END_TAG
-};
-goog.dom.TagIterator.prototype.isNonElement = function() {
- return this.tagType == goog.dom.TagWalkType.OTHER
-};
-goog.dom.TagIterator.prototype.equals = function(other) {
- return other.node == this.node && (!this.node || other.tagType == this.tagType)
-};
-goog.dom.TagIterator.prototype.splice = function(var_args) {
- var node = this.node;
- this.restartTag();
- this.reversed = !this.reversed;
- goog.dom.TagIterator.prototype.next.call(this);
- this.reversed = !this.reversed;
- var arr = goog.isArrayLike(arguments[0]) ? arguments[0] : arguments;
- for(var i = arr.length - 1;i >= 0;i--) {
- goog.dom.insertSiblingAfter(arr[i], node)
- }
- goog.dom.removeNode(node)
-};
-goog.provide("goog.dom.AbstractRange");
-goog.provide("goog.dom.RangeIterator");
-goog.provide("goog.dom.RangeType");
-goog.require("goog.dom");
-goog.require("goog.dom.NodeType");
-goog.require("goog.dom.SavedCaretRange");
-goog.require("goog.dom.TagIterator");
-goog.require("goog.userAgent");
-goog.dom.RangeType = {TEXT:"text", CONTROL:"control", MULTI:"mutli"};
-goog.dom.AbstractRange = function() {
-};
-goog.dom.AbstractRange.getBrowserSelectionForWindow = function(win) {
- if(win.getSelection) {
- return win.getSelection()
- }else {
- var doc = win.document;
- var sel = doc.selection;
- if(sel) {
- try {
- var range = sel.createRange();
- if(range.parentElement) {
- if(range.parentElement().document != doc) {
- return null
- }
- }else {
- if(!range.length || range.item(0).document != doc) {
- return null
- }
- }
- }catch(e) {
- return null
- }
- return sel
- }
- return null
- }
-};
-goog.dom.AbstractRange.isNativeControlRange = function(range) {
- return!!range && !!range.addElement
-};
-goog.dom.AbstractRange.prototype.clone = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.getType = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.getBrowserRangeObject = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.setBrowserRangeObject = function(nativeRange) {
- return false
-};
-goog.dom.AbstractRange.prototype.getTextRangeCount = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.getTextRange = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.getTextRanges = function() {
- var output = [];
- for(var i = 0, len = this.getTextRangeCount();i < len;i++) {
- output.push(this.getTextRange(i))
- }
- return output
-};
-goog.dom.AbstractRange.prototype.getContainer = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.getContainerElement = function() {
- var node = this.getContainer();
- return node.nodeType == goog.dom.NodeType.ELEMENT ? node : node.parentNode
-};
-goog.dom.AbstractRange.prototype.getStartNode = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.getStartOffset = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.getEndNode = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.getEndOffset = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.getAnchorNode = function() {
- return this.isReversed() ? this.getEndNode() : this.getStartNode()
-};
-goog.dom.AbstractRange.prototype.getAnchorOffset = function() {
- return this.isReversed() ? this.getEndOffset() : this.getStartOffset()
-};
-goog.dom.AbstractRange.prototype.getFocusNode = function() {
- return this.isReversed() ? this.getStartNode() : this.getEndNode()
-};
-goog.dom.AbstractRange.prototype.getFocusOffset = function() {
- return this.isReversed() ? this.getStartOffset() : this.getEndOffset()
-};
-goog.dom.AbstractRange.prototype.isReversed = function() {
- return false
-};
-goog.dom.AbstractRange.prototype.getDocument = function() {
- return goog.dom.getOwnerDocument(goog.userAgent.IE ? this.getContainer() : this.getStartNode())
-};
-goog.dom.AbstractRange.prototype.getWindow = function() {
- return goog.dom.getWindow(this.getDocument())
-};
-goog.dom.AbstractRange.prototype.containsRange = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.containsNode = function(node, opt_allowPartial) {
- return this.containsRange(goog.dom.Range.createFromNodeContents(node), opt_allowPartial)
-};
-goog.dom.AbstractRange.prototype.isRangeInDocument = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.isCollapsed = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.getText = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.getHtmlFragment = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.getValidHtml = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.getPastableHtml = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.__iterator__ = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.select = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.removeContents = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.insertNode = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.replaceContentsWithNode = function(node) {
- if(!this.isCollapsed()) {
- this.removeContents()
- }
- return this.insertNode(node, true)
-};
-goog.dom.AbstractRange.prototype.surroundWithNodes = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.saveUsingDom = goog.abstractMethod;
-goog.dom.AbstractRange.prototype.saveUsingCarets = function() {
- return this.getStartNode() && this.getEndNode() ? new goog.dom.SavedCaretRange(this) : null
-};
-goog.dom.AbstractRange.prototype.collapse = goog.abstractMethod;
-goog.dom.RangeIterator = function(node, opt_reverse) {
- goog.dom.TagIterator.call(this, node, opt_reverse, true)
-};
-goog.inherits(goog.dom.RangeIterator, goog.dom.TagIterator);
-goog.dom.RangeIterator.prototype.getStartTextOffset = goog.abstractMethod;
-goog.dom.RangeIterator.prototype.getEndTextOffset = goog.abstractMethod;
-goog.dom.RangeIterator.prototype.getStartNode = goog.abstractMethod;
-goog.dom.RangeIterator.prototype.getEndNode = goog.abstractMethod;
-goog.dom.RangeIterator.prototype.isLast = goog.abstractMethod;
-goog.provide("goog.dom.AbstractMultiRange");
-goog.require("goog.array");
-goog.require("goog.dom");
-goog.require("goog.dom.AbstractRange");
-goog.dom.AbstractMultiRange = function() {
-};
-goog.inherits(goog.dom.AbstractMultiRange, goog.dom.AbstractRange);
-goog.dom.AbstractMultiRange.prototype.containsRange = function(otherRange, opt_allowPartial) {
- var ranges = this.getTextRanges();
- var otherRanges = otherRange.getTextRanges();
- var fn = opt_allowPartial ? goog.array.some : goog.array.every;
- return fn(otherRanges, function(otherRange) {
- return goog.array.some(ranges, function(range) {
- return range.containsRange(otherRange, opt_allowPartial)
- })
- })
-};
-goog.dom.AbstractMultiRange.prototype.insertNode = function(node, before) {
- if(before) {
- goog.dom.insertSiblingBefore(node, this.getStartNode())
- }else {
- goog.dom.insertSiblingAfter(node, this.getEndNode())
- }
- return node
-};
-goog.dom.AbstractMultiRange.prototype.surroundWithNodes = function(startNode, endNode) {
- this.insertNode(startNode, true);
- this.insertNode(endNode, false)
-};
-goog.provide("goog.dom.TextRangeIterator");
-goog.require("goog.array");
-goog.require("goog.dom.NodeType");
-goog.require("goog.dom.RangeIterator");
-goog.require("goog.dom.TagName");
-goog.require("goog.iter.StopIteration");
-goog.dom.TextRangeIterator = function(startNode, startOffset, endNode, endOffset, opt_reverse) {
- var goNext;
- if(startNode) {
- this.startNode_ = startNode;
- this.startOffset_ = startOffset;
- this.endNode_ = endNode;
- this.endOffset_ = endOffset;
- if(startNode.nodeType == goog.dom.NodeType.ELEMENT && startNode.tagName != goog.dom.TagName.BR) {
- var startChildren = startNode.childNodes;
- var candidate = startChildren[startOffset];
- if(candidate) {
- this.startNode_ = candidate;
- this.startOffset_ = 0
- }else {
- if(startChildren.length) {
- this.startNode_ = goog.array.peek(startChildren)
- }
- goNext = true
- }
- }
- if(endNode.nodeType == goog.dom.NodeType.ELEMENT) {
- this.endNode_ = endNode.childNodes[endOffset];
- if(this.endNode_) {
- this.endOffset_ = 0
- }else {
- this.endNode_ = endNode
- }
- }
- }
- goog.dom.RangeIterator.call(this, opt_reverse ? this.endNode_ : this.startNode_, opt_reverse);
- if(goNext) {
- try {
- this.next()
- }catch(e) {
- if(e != goog.iter.StopIteration) {
- throw e;
- }
- }
- }
-};
-goog.inherits(goog.dom.TextRangeIterator, goog.dom.RangeIterator);
-goog.dom.TextRangeIterator.prototype.startNode_ = null;
-goog.dom.TextRangeIterator.prototype.endNode_ = null;
-goog.dom.TextRangeIterator.prototype.startOffset_ = 0;
-goog.dom.TextRangeIterator.prototype.endOffset_ = 0;
-goog.dom.TextRangeIterator.prototype.getStartTextOffset = function() {
- return this.node.nodeType != goog.dom.NodeType.TEXT ? -1 : this.node == this.startNode_ ? this.startOffset_ : 0
-};
-goog.dom.TextRangeIterator.prototype.getEndTextOffset = function() {
- return this.node.nodeType != goog.dom.NodeType.TEXT ? -1 : this.node == this.endNode_ ? this.endOffset_ : this.node.nodeValue.length
-};
-goog.dom.TextRangeIterator.prototype.getStartNode = function() {
- return this.startNode_
-};
-goog.dom.TextRangeIterator.prototype.setStartNode = function(node) {
- if(!this.isStarted()) {
- this.setPosition(node)
- }
- this.startNode_ = node;
- this.startOffset_ = 0
-};
-goog.dom.TextRangeIterator.prototype.getEndNode = function() {
- return this.endNode_
-};
-goog.dom.TextRangeIterator.prototype.setEndNode = function(node) {
- this.endNode_ = node;
- this.endOffset_ = 0
-};
-goog.dom.TextRangeIterator.prototype.isLast = function() {
- return this.isStarted() && this.node == this.endNode_ && (!this.endOffset_ || !this.isStartTag())
-};
-goog.dom.TextRangeIterator.prototype.next = function() {
- if(this.isLast()) {
- throw goog.iter.StopIteration;
- }
- return goog.dom.TextRangeIterator.superClass_.next.call(this)
-};
-goog.dom.TextRangeIterator.prototype.skipTag = function() {
- goog.dom.TextRangeIterator.superClass_.skipTag.apply(this);
- if(goog.dom.contains(this.node, this.endNode_)) {
- throw goog.iter.StopIteration;
- }
-};
-goog.dom.TextRangeIterator.prototype.copyFrom = function(other) {
- this.startNode_ = other.startNode_;
- this.endNode_ = other.endNode_;
- this.startOffset_ = other.startOffset_;
- this.endOffset_ = other.endOffset_;
- this.isReversed_ = other.isReversed_;
- goog.dom.TextRangeIterator.superClass_.copyFrom.call(this, other)
-};
-goog.dom.TextRangeIterator.prototype.clone = function() {
- var copy = new goog.dom.TextRangeIterator(this.startNode_, this.startOffset_, this.endNode_, this.endOffset_, this.isReversed_);
- copy.copyFrom(this);
- return copy
-};
-goog.provide("goog.dom.RangeEndpoint");
-goog.dom.RangeEndpoint = {START:1, END:0};
-goog.provide("goog.userAgent.jscript");
-goog.require("goog.string");
-goog.userAgent.jscript.ASSUME_NO_JSCRIPT = false;
-goog.userAgent.jscript.init_ = function() {
- var hasScriptEngine = "ScriptEngine" in goog.global;
- goog.userAgent.jscript.DETECTED_HAS_JSCRIPT_ = hasScriptEngine && goog.global["ScriptEngine"]() == "JScript";
- goog.userAgent.jscript.DETECTED_VERSION_ = goog.userAgent.jscript.DETECTED_HAS_JSCRIPT_ ? goog.global["ScriptEngineMajorVersion"]() + "." + goog.global["ScriptEngineMinorVersion"]() + "." + goog.global["ScriptEngineBuildVersion"]() : "0"
-};
-if(!goog.userAgent.jscript.ASSUME_NO_JSCRIPT) {
- goog.userAgent.jscript.init_()
-}
-goog.userAgent.jscript.HAS_JSCRIPT = goog.userAgent.jscript.ASSUME_NO_JSCRIPT ? false : goog.userAgent.jscript.DETECTED_HAS_JSCRIPT_;
-goog.userAgent.jscript.VERSION = goog.userAgent.jscript.ASSUME_NO_JSCRIPT ? "0" : goog.userAgent.jscript.DETECTED_VERSION_;
-goog.userAgent.jscript.isVersion = function(version) {
- return goog.string.compareVersions(goog.userAgent.jscript.VERSION, version) >= 0
-};
-goog.provide("goog.string.StringBuffer");
-goog.require("goog.userAgent.jscript");
-goog.string.StringBuffer = function(opt_a1, var_args) {
- this.buffer_ = goog.userAgent.jscript.HAS_JSCRIPT ? [] : "";
- if(opt_a1 != null) {
- this.append.apply(this, arguments)
- }
-};
-goog.string.StringBuffer.prototype.set = function(s) {
- this.clear();
- this.append(s)
-};
-if(goog.userAgent.jscript.HAS_JSCRIPT) {
- goog.string.StringBuffer.prototype.bufferLength_ = 0;
- goog.string.StringBuffer.prototype.append = function(a1, opt_a2, var_args) {
- if(opt_a2 == null) {
- this.buffer_[this.bufferLength_++] = a1
- }else {
- this.buffer_.push.apply(this.buffer_, arguments);
- this.bufferLength_ = this.buffer_.length
- }
- return this
- }
-}else {
- goog.string.StringBuffer.prototype.append = function(a1, opt_a2, var_args) {
- this.buffer_ += a1;
- if(opt_a2 != null) {
- for(var i = 1;i < arguments.length;i++) {
- this.buffer_ += arguments[i]
- }
- }
- return this
- }
-}
-goog.string.StringBuffer.prototype.clear = function() {
- if(goog.userAgent.jscript.HAS_JSCRIPT) {
- this.buffer_.length = 0;
- this.bufferLength_ = 0
- }else {
- this.buffer_ = ""
- }
-};
-goog.string.StringBuffer.prototype.getLength = function() {
- return this.toString().length
-};
-goog.string.StringBuffer.prototype.toString = function() {
- if(goog.userAgent.jscript.HAS_JSCRIPT) {
- var str = this.buffer_.join("");
- this.clear();
- if(str) {
- this.append(str)
- }
- return str
- }else {
- return this.buffer_
- }
-};
-goog.provide("goog.dom.browserrange.AbstractRange");
-goog.require("goog.dom");
-goog.require("goog.dom.NodeType");
-goog.require("goog.dom.RangeEndpoint");
-goog.require("goog.dom.TagName");
-goog.require("goog.dom.TextRangeIterator");
-goog.require("goog.iter");
-goog.require("goog.string");
-goog.require("goog.string.StringBuffer");
-goog.require("goog.userAgent");
-goog.dom.browserrange.AbstractRange = function() {
-};
-goog.dom.browserrange.AbstractRange.prototype.clone = goog.abstractMethod;
-goog.dom.browserrange.AbstractRange.prototype.getBrowserRange = goog.abstractMethod;
-goog.dom.browserrange.AbstractRange.prototype.getContainer = goog.abstractMethod;
-goog.dom.browserrange.AbstractRange.prototype.getStartNode = goog.abstractMethod;
-goog.dom.browserrange.AbstractRange.prototype.getStartOffset = goog.abstractMethod;
-goog.dom.browserrange.AbstractRange.prototype.getEndNode = goog.abstractMethod;
-goog.dom.browserrange.AbstractRange.prototype.getEndOffset = goog.abstractMethod;
-goog.dom.browserrange.AbstractRange.prototype.compareBrowserRangeEndpoints = goog.abstractMethod;
-goog.dom.browserrange.AbstractRange.prototype.containsRange = function(abstractRange, opt_allowPartial) {
- var checkPartial = opt_allowPartial && !abstractRange.isCollapsed();
- var range = abstractRange.getBrowserRange();
- var start = goog.dom.RangeEndpoint.START, end = goog.dom.RangeEndpoint.END;
- try {
- if(checkPartial) {
- return this.compareBrowserRangeEndpoints(range, end, start) >= 0 && this.compareBrowserRangeEndpoints(range, start, end) <= 0
- }else {
- return this.compareBrowserRangeEndpoints(range, end, end) >= 0 && this.compareBrowserRangeEndpoints(range, start, start) <= 0
- }
- }catch(e) {
- if(!goog.userAgent.IE) {
- throw e;
- }
- return false
- }
-};
-goog.dom.browserrange.AbstractRange.prototype.containsNode = function(node, opt_allowPartial) {
- return this.containsRange(goog.dom.browserrange.createRangeFromNodeContents(node), opt_allowPartial)
-};
-goog.dom.browserrange.AbstractRange.prototype.isCollapsed = goog.abstractMethod;
-goog.dom.browserrange.AbstractRange.prototype.getText = goog.abstractMethod;
-goog.dom.browserrange.AbstractRange.prototype.getHtmlFragment = function() {
- var output = new goog.string.StringBuffer;
- goog.iter.forEach(this, function(node, ignore, it) {
- if(node.nodeType == goog.dom.NodeType.TEXT) {
- output.append(goog.string.htmlEscape(node.nodeValue.substring(it.getStartTextOffset(), it.getEndTextOffset())))
- }else {
- if(node.nodeType == goog.dom.NodeType.ELEMENT) {
- if(it.isEndTag()) {
- if(goog.dom.canHaveChildren(node)) {
- output.append("</" + node.tagName + ">")
- }
- }else {
- var shallow = node.cloneNode(false);
- var html = goog.dom.getOuterHtml(shallow);
- if(goog.userAgent.IE && node.tagName == goog.dom.TagName.LI) {
- output.append(html)
- }else {
- var index = html.lastIndexOf("<");
- output.append(index ? html.substr(0, index) : html)
- }
- }
- }
- }
- }, this);
- return output.toString()
-};
-goog.dom.browserrange.AbstractRange.prototype.getValidHtml = goog.abstractMethod;
-goog.dom.browserrange.AbstractRange.prototype.__iterator__ = function(opt_keys) {
- return new goog.dom.TextRangeIterator(this.getStartNode(), this.getStartOffset(), this.getEndNode(), this.getEndOffset())
-};
-goog.dom.browserrange.AbstractRange.prototype.select = goog.abstractMethod;
-goog.dom.browserrange.AbstractRange.prototype.removeContents = goog.abstractMethod;
-goog.dom.browserrange.AbstractRange.prototype.surroundContents = goog.abstractMethod;
-goog.dom.browserrange.AbstractRange.prototype.insertNode = goog.abstractMethod;
-goog.dom.browserrange.AbstractRange.prototype.surroundWithNodes = goog.abstractMethod;
-goog.dom.browserrange.AbstractRange.prototype.collapse = goog.abstractMethod;
-goog.provide("goog.dom.browserrange.W3cRange");
-goog.require("goog.dom");
-goog.require("goog.dom.NodeType");
-goog.require("goog.dom.RangeEndpoint");
-goog.require("goog.dom.browserrange.AbstractRange");
-goog.require("goog.string");
-goog.dom.browserrange.W3cRange = function(range) {
- this.range_ = range
-};
-goog.inherits(goog.dom.browserrange.W3cRange, goog.dom.browserrange.AbstractRange);
-goog.dom.browserrange.W3cRange.getBrowserRangeForNode = function(node) {
- var nodeRange = goog.dom.getOwnerDocument(node).createRange();
- if(node.nodeType == goog.dom.NodeType.TEXT) {
- nodeRange.setStart(node, 0);
- nodeRange.setEnd(node, node.length)
- }else {
- if(!goog.dom.browserrange.canContainRangeEndpoint(node)) {
- var rangeParent = node.parentNode;
- var rangeStartOffset = goog.array.indexOf(rangeParent.childNodes, node);
- nodeRange.setStart(rangeParent, rangeStartOffset);
- nodeRange.setEnd(rangeParent, rangeStartOffset + 1)
- }else {
- var tempNode, leaf = node;
- while((tempNode = leaf.firstChild) && goog.dom.browserrange.canContainRangeEndpoint(tempNode)) {
- leaf = tempNode
- }
- nodeRange.setStart(leaf, 0);
- leaf = node;
- while((tempNode = leaf.lastChild) && goog.dom.browserrange.canContainRangeEndpoint(tempNode)) {
- leaf = tempNode
- }
- nodeRange.setEnd(leaf, leaf.nodeType == goog.dom.NodeType.ELEMENT ? leaf.childNodes.length : leaf.length)
- }
- }
- return nodeRange
-};
-goog.dom.browserrange.W3cRange.getBrowserRangeForNodes = function(startNode, startOffset, endNode, endOffset) {
- var nodeRange = goog.dom.getOwnerDocument(startNode).createRange();
- nodeRange.setStart(startNode, startOffset);
- nodeRange.setEnd(endNode, endOffset);
- return nodeRange
-};
-goog.dom.browserrange.W3cRange.createFromNodeContents = function(node) {
- return new goog.dom.browserrange.W3cRange(goog.dom.browserrange.W3cRange.getBrowserRangeForNode(node))
-};
-goog.dom.browserrange.W3cRange.createFromNodes = function(startNode, startOffset, endNode, endOffset) {
- return new goog.dom.browserrange.W3cRange(goog.dom.browserrange.W3cRange.getBrowserRangeForNodes(startNode, startOffset, endNode, endOffset))
-};
-goog.dom.browserrange.W3cRange.prototype.clone = function() {
- return new this.constructor(this.range_.cloneRange())
-};
-goog.dom.browserrange.W3cRange.prototype.getBrowserRange = function() {
- return this.range_
-};
-goog.dom.browserrange.W3cRange.prototype.getContainer = function() {
- return this.range_.commonAncestorContainer
-};
-goog.dom.browserrange.W3cRange.prototype.getStartNode = function() {
- return this.range_.startContainer
-};
-goog.dom.browserrange.W3cRange.prototype.getStartOffset = function() {
- return this.range_.startOffset
-};
-goog.dom.browserrange.W3cRange.prototype.getEndNode = function() {
- return this.range_.endContainer
-};
-goog.dom.browserrange.W3cRange.prototype.getEndOffset = function() {
- return this.range_.endOffset
-};
-goog.dom.browserrange.W3cRange.prototype.compareBrowserRangeEndpoints = function(range, thisEndpoint, otherEndpoint) {
- return this.range_.compareBoundaryPoints(otherEndpoint == goog.dom.RangeEndpoint.START ? thisEndpoint == goog.dom.RangeEndpoint.START ? goog.global["Range"].START_TO_START : goog.global["Range"].START_TO_END : thisEndpoint == goog.dom.RangeEndpoint.START ? goog.global["Range"].END_TO_START : goog.global["Range"].END_TO_END, range)
-};
-goog.dom.browserrange.W3cRange.prototype.isCollapsed = function() {
- return this.range_.collapsed
-};
-goog.dom.browserrange.W3cRange.prototype.getText = function() {
- return this.range_.toString()
-};
-goog.dom.browserrange.W3cRange.prototype.getValidHtml = function() {
- var div = goog.dom.getDomHelper(this.range_.startContainer).createDom("div");
- div.appendChild(this.range_.cloneContents());
- var result = div.innerHTML;
- if(goog.string.startsWith(result, "<") || !this.isCollapsed() && !goog.string.contains(result, "<")) {
- return result
- }
- var container = this.getContainer();
- container = container.nodeType == goog.dom.NodeType.ELEMENT ? container : container.parentNode;
- var html = goog.dom.getOuterHtml(container.cloneNode(false));
- return html.replace(">", ">" + result)
-};
-goog.dom.browserrange.W3cRange.prototype.select = function(reverse) {
- var win = goog.dom.getWindow(goog.dom.getOwnerDocument(this.getStartNode()));
- this.selectInternal(win.getSelection(), reverse)
-};
-goog.dom.browserrange.W3cRange.prototype.selectInternal = function(selection, reverse) {
- selection.removeAllRanges();
- selection.addRange(this.range_)
-};
-goog.dom.browserrange.W3cRange.prototype.removeContents = function() {
- var range = this.range_;
- range.extractContents();
- if(range.startContainer.hasChildNodes()) {
- var rangeStartContainer = range.startContainer.childNodes[range.startOffset];
- if(rangeStartContainer) {
- var rangePrevious = rangeStartContainer.previousSibling;
- if(goog.dom.getRawTextContent(rangeStartContainer) == "") {
- goog.dom.removeNode(rangeStartContainer)
- }
- if(rangePrevious && goog.dom.getRawTextContent(rangePrevious) == "") {
- goog.dom.removeNode(rangePrevious)
- }
- }
- }
-};
-goog.dom.browserrange.W3cRange.prototype.surroundContents = function(element) {
- this.range_.surroundContents(element);
- return element
-};
-goog.dom.browserrange.W3cRange.prototype.insertNode = function(node, before) {
- var range = this.range_.cloneRange();
- range.collapse(before);
- range.insertNode(node);
- range.detach();
- return node
-};
-goog.dom.browserrange.W3cRange.prototype.surroundWithNodes = function(startNode, endNode) {
- var win = goog.dom.getWindow(goog.dom.getOwnerDocument(this.getStartNode()));
- var selectionRange = goog.dom.Range.createFromWindow(win);
- if(selectionRange) {
- var sNode = selectionRange.getStartNode();
- var eNode = selectionRange.getEndNode();
- var sOffset = selectionRange.getStartOffset();
- var eOffset = selectionRange.getEndOffset()
- }
- var clone1 = this.range_.cloneRange();
- var clone2 = this.range_.cloneRange();
- clone1.collapse(false);
- clone2.collapse(true);
- clone1.insertNode(endNode);
- clone2.insertNode(startNode);
- clone1.detach();
- clone2.detach();
- if(selectionRange) {
- var isInsertedNode = function(n) {
- return n == startNode || n == endNode
- };
- if(sNode.nodeType == goog.dom.NodeType.TEXT) {
- while(sOffset > sNode.length) {
- sOffset -= sNode.length;
- do {
- sNode = sNode.nextSibling
- }while(isInsertedNode(sNode))
- }
- }
- if(eNode.nodeType == goog.dom.NodeType.TEXT) {
- while(eOffset > eNode.length) {
- eOffset -= eNode.length;
- do {
- eNode = eNode.nextSibling
- }while(isInsertedNode(eNode))
- }
- }
- goog.dom.Range.createFromNodes(sNode, sOffset, eNode, eOffset).select()
- }
-};
-goog.dom.browserrange.W3cRange.prototype.collapse = function(toStart) {
- this.range_.collapse(toStart)
-};
-goog.provide("goog.dom.browserrange.GeckoRange");
-goog.require("goog.dom.browserrange.W3cRange");
-goog.dom.browserrange.GeckoRange = function(range) {
- goog.dom.browserrange.W3cRange.call(this, range)
-};
-goog.inherits(goog.dom.browserrange.GeckoRange, goog.dom.browserrange.W3cRange);
-goog.dom.browserrange.GeckoRange.createFromNodeContents = function(node) {
- return new goog.dom.browserrange.GeckoRange(goog.dom.browserrange.W3cRange.getBrowserRangeForNode(node))
-};
-goog.dom.browserrange.GeckoRange.createFromNodes = function(startNode, startOffset, endNode, endOffset) {
- return new goog.dom.browserrange.GeckoRange(goog.dom.browserrange.W3cRange.getBrowserRangeForNodes(startNode, startOffset, endNode, endOffset))
-};
-goog.dom.browserrange.GeckoRange.prototype.selectInternal = function(selection, reversed) {
- var anchorNode = reversed ? this.getEndNode() : this.getStartNode();
- var anchorOffset = reversed ? this.getEndOffset() : this.getStartOffset();
- var focusNode = reversed ? this.getStartNode() : this.getEndNode();
- var focusOffset = reversed ? this.getStartOffset() : this.getEndOffset();
- selection.collapse(anchorNode, anchorOffset);
- if(anchorNode != focusNode || anchorOffset != focusOffset) {
- selection.extend(focusNode, focusOffset)
- }
-};
-goog.provide("goog.dom.NodeIterator");
-goog.require("goog.dom.TagIterator");
-goog.dom.NodeIterator = function(opt_node, opt_reversed, opt_unconstrained, opt_depth) {
- goog.dom.TagIterator.call(this, opt_node, opt_reversed, opt_unconstrained, null, opt_depth)
-};
-goog.inherits(goog.dom.NodeIterator, goog.dom.TagIterator);
-goog.dom.NodeIterator.prototype.next = function() {
- do {
- goog.dom.NodeIterator.superClass_.next.call(this)
- }while(this.isEndTag());
- return this.node
-};
-goog.provide("goog.dom.browserrange.IeRange");
-goog.require("goog.array");
-goog.require("goog.debug.Logger");
-goog.require("goog.dom");
-goog.require("goog.dom.NodeIterator");
-goog.require("goog.dom.NodeType");
-goog.require("goog.dom.RangeEndpoint");
-goog.require("goog.dom.TagName");
-goog.require("goog.dom.browserrange.AbstractRange");
-goog.require("goog.iter");
-goog.require("goog.iter.StopIteration");
-goog.require("goog.string");
-goog.dom.browserrange.IeRange = function(range, doc) {
- this.range_ = range;
- this.doc_ = doc
-};
-goog.inherits(goog.dom.browserrange.IeRange, goog.dom.browserrange.AbstractRange);
-goog.dom.browserrange.IeRange.logger_ = goog.debug.Logger.getLogger("goog.dom.browserrange.IeRange");
-goog.dom.browserrange.IeRange.getBrowserRangeForNode_ = function(node) {
- var nodeRange = goog.dom.getOwnerDocument(node).body.createTextRange();
- if(node.nodeType == goog.dom.NodeType.ELEMENT) {
- nodeRange.moveToElementText(node);
- if(goog.dom.browserrange.canContainRangeEndpoint(node) && !node.childNodes.length) {
- nodeRange.collapse(false)
- }
- }else {
- var offset = 0;
- var sibling = node;
- while(sibling = sibling.previousSibling) {
- var nodeType = sibling.nodeType;
- if(nodeType == goog.dom.NodeType.TEXT) {
- offset += sibling.length
- }else {
- if(nodeType == goog.dom.NodeType.ELEMENT) {
- nodeRange.moveToElementText(sibling);
- break
- }
- }
- }
- if(!sibling) {
- nodeRange.moveToElementText(node.parentNode)
- }
- nodeRange.collapse(!sibling);
- if(offset) {
- nodeRange.move("character", offset)
- }
- nodeRange.moveEnd("character", node.length)
- }
- return nodeRange
-};
-goog.dom.browserrange.IeRange.getBrowserRangeForNodes_ = function(startNode, startOffset, endNode, endOffset) {
- var child, collapse = false;
- if(startNode.nodeType == goog.dom.NodeType.ELEMENT) {
- if(startOffset > startNode.childNodes.length) {
- goog.dom.browserrange.IeRange.logger_.severe("Cannot have startOffset > startNode child count")
- }
- child = startNode.childNodes[startOffset];
- collapse = !child;
- startNode = child || startNode.lastChild || startNode;
- startOffset = 0
- }
- var leftRange = goog.dom.browserrange.IeRange.getBrowserRangeForNode_(startNode);
- if(startOffset) {
- leftRange.move("character", startOffset)
- }
- if(startNode == endNode && startOffset == endOffset) {
- leftRange.collapse(true);
- return leftRange
- }
- if(collapse) {
- leftRange.collapse(false)
- }
- collapse = false;
- if(endNode.nodeType == goog.dom.NodeType.ELEMENT) {
- if(endOffset > endNode.childNodes.length) {
- goog.dom.browserrange.IeRange.logger_.severe("Cannot have endOffset > endNode child count")
- }
- child = endNode.childNodes[endOffset];
- endNode = child || endNode.lastChild || endNode;
- endOffset = 0;
- collapse = !child
- }
- var rightRange = goog.dom.browserrange.IeRange.getBrowserRangeForNode_(endNode);
- rightRange.collapse(!collapse);
- if(endOffset) {
- rightRange.moveEnd("character", endOffset)
- }
- leftRange.setEndPoint("EndToEnd", rightRange);
- return leftRange
-};
-goog.dom.browserrange.IeRange.createFromNodeContents = function(node) {
- var range = new goog.dom.browserrange.IeRange(goog.dom.browserrange.IeRange.getBrowserRangeForNode_(node), goog.dom.getOwnerDocument(node));
- if(!goog.dom.browserrange.canContainRangeEndpoint(node)) {
- range.startNode_ = range.endNode_ = range.parentNode_ = node.parentNode;
- range.startOffset_ = goog.array.indexOf(range.parentNode_.childNodes, node);
- range.endOffset_ = range.startOffset_ + 1
- }else {
- var tempNode, leaf = node;
- while((tempNode = leaf.firstChild) && goog.dom.browserrange.canContainRangeEndpoint(tempNode)) {
- leaf = tempNode
- }
- range.startNode_ = leaf;
- range.startOffset_ = 0;
- leaf = node;
- while((tempNode = leaf.lastChild) && goog.dom.browserrange.canContainRangeEndpoint(tempNode)) {
- leaf = tempNode
- }
- range.endNode_ = leaf;
- range.endOffset_ = leaf.nodeType == goog.dom.NodeType.ELEMENT ? leaf.childNodes.length : leaf.length;
- range.parentNode_ = node
- }
- return range
-};
-goog.dom.browserrange.IeRange.createFromNodes = function(startNode, startOffset, endNode, endOffset) {
- var range = new goog.dom.browserrange.IeRange(goog.dom.browserrange.IeRange.getBrowserRangeForNodes_(startNode, startOffset, endNode, endOffset), goog.dom.getOwnerDocument(startNode));
- range.startNode_ = startNode;
- range.startOffset_ = startOffset;
- range.endNode_ = endNode;
- range.endOffset_ = endOffset;
- return range
-};
-goog.dom.browserrange.IeRange.prototype.parentNode_ = null;
-goog.dom.browserrange.IeRange.prototype.startNode_ = null;
-goog.dom.browserrange.IeRange.prototype.endNode_ = null;
-goog.dom.browserrange.IeRange.prototype.startOffset_ = -1;
-goog.dom.browserrange.IeRange.prototype.endOffset_ = -1;
-goog.dom.browserrange.IeRange.prototype.clone = function() {
- var range = new goog.dom.browserrange.IeRange(this.range_.duplicate(), this.doc_);
- range.parentNode_ = this.parentNode_;
- range.startNode_ = this.startNode_;
- range.endNode_ = this.endNode_;
- return range
-};
-goog.dom.browserrange.IeRange.prototype.getBrowserRange = function() {
- return this.range_
-};
-goog.dom.browserrange.IeRange.prototype.clearCachedValues_ = function() {
- this.parentNode_ = this.startNode_ = this.endNode_ = null;
- this.startOffset_ = this.endOffset_ = -1
-};
-goog.dom.browserrange.IeRange.prototype.getContainer = function() {
- if(!this.parentNode_) {
- var selectText = this.range_.text;
- var range = this.range_.duplicate();
- var rightTrimmedSelectText = selectText.replace(/ +$/, "");
- var numSpacesAtEnd = selectText.length - rightTrimmedSelectText.length;
- if(numSpacesAtEnd) {
- range.moveEnd("character", -numSpacesAtEnd)
- }
- var parent = range.parentElement();
- var htmlText = range.htmlText;
- var htmlTextLen = goog.string.stripNewlines(htmlText).length;
- if(this.isCollapsed() && htmlTextLen > 0) {
- return this.parentNode_ = parent
- }
- while(htmlTextLen > goog.string.stripNewlines(parent.outerHTML).length) {
- parent = parent.parentNode
- }
- while(parent.childNodes.length == 1 && parent.innerText == goog.dom.browserrange.IeRange.getNodeText_(parent.firstChild)) {
- if(!goog.dom.browserrange.canContainRangeEndpoint(parent.firstChild)) {
- break
- }
- parent = parent.firstChild
- }
- if(selectText.length == 0) {
- parent = this.findDeepestContainer_(parent)
- }
- this.parentNode_ = parent
- }
- return this.parentNode_
-};
-goog.dom.browserrange.IeRange.prototype.findDeepestContainer_ = function(node) {
- var childNodes = node.childNodes;
- for(var i = 0, len = childNodes.length;i < len;i++) {
- var child = childNodes[i];
- if(goog.dom.browserrange.canContainRangeEndpoint(child)) {
- var childRange = goog.dom.browserrange.IeRange.getBrowserRangeForNode_(child);
- var start = goog.dom.RangeEndpoint.START;
- var end = goog.dom.RangeEndpoint.END;
- var isChildRangeErratic = childRange.htmlText != child.outerHTML;
- var isNativeInRangeErratic = this.isCollapsed() && isChildRangeErratic;
- var inChildRange = isNativeInRangeErratic ? this.compareBrowserRangeEndpoints(childRange, start, start) >= 0 && this.compareBrowserRangeEndpoints(childRange, start, end) <= 0 : this.range_.inRange(childRange);
- if(inChildRange) {
- return this.findDeepestContainer_(child)
- }
- }
- }
- return node
-};
-goog.dom.browserrange.IeRange.prototype.getStartNode = function() {
- if(!this.startNode_) {
- this.startNode_ = this.getEndpointNode_(goog.dom.RangeEndpoint.START);
- if(this.isCollapsed()) {
- this.endNode_ = this.startNode_
- }
- }
- return this.startNode_
-};
-goog.dom.browserrange.IeRange.prototype.getStartOffset = function() {
- if(this.startOffset_ < 0) {
- this.startOffset_ = this.getOffset_(goog.dom.RangeEndpoint.START);
- if(this.isCollapsed()) {
- this.endOffset_ = this.startOffset_
- }
- }
- return this.startOffset_
-};
-goog.dom.browserrange.IeRange.prototype.getEndNode = function() {
- if(this.isCollapsed()) {
- return this.getStartNode()
- }
- if(!this.endNode_) {
- this.endNode_ = this.getEndpointNode_(goog.dom.RangeEndpoint.END)
- }
- return this.endNode_
-};
-goog.dom.browserrange.IeRange.prototype.getEndOffset = function() {
- if(this.isCollapsed()) {
- return this.getStartOffset()
- }
- if(this.endOffset_ < 0) {
- this.endOffset_ = this.getOffset_(goog.dom.RangeEndpoint.END);
- if(this.isCollapsed()) {
- this.startOffset_ = this.endOffset_
- }
- }
- return this.endOffset_
-};
-goog.dom.browserrange.IeRange.prototype.compareBrowserRangeEndpoints = function(range, thisEndpoint, otherEndpoint) {
- return this.range_.compareEndPoints((thisEndpoint == goog.dom.RangeEndpoint.START ? "Start" : "End") + "To" + (otherEndpoint == goog.dom.RangeEndpoint.START ? "Start" : "End"), range)
-};
-goog.dom.browserrange.IeRange.prototype.getEndpointNode_ = function(endpoint, opt_node) {
- var node = opt_node || this.getContainer();
- if(!node || !node.firstChild) {
- return node
- }
- var start = goog.dom.RangeEndpoint.START, end = goog.dom.RangeEndpoint.END;
- var isStartEndpoint = endpoint == start;
- for(var j = 0, length = node.childNodes.length;j < length;j++) {
- var i = isStartEndpoint ? j : length - j - 1;
- var child = node.childNodes[i];
- var childRange;
- try {
- childRange = goog.dom.browserrange.createRangeFromNodeContents(child)
- }catch(e) {
- continue
- }
- var ieRange = childRange.getBrowserRange();
- if(this.isCollapsed()) {
- if(!goog.dom.browserrange.canContainRangeEndpoint(child)) {
- if(this.compareBrowserRangeEndpoints(ieRange, start, start) == 0) {
- this.startOffset_ = this.endOffset_ = i;
- return node
- }
- }else {
- if(childRange.containsRange(this)) {
- return this.getEndpointNode_(endpoint, child)
- }
- }
- }else {
- if(this.containsRange(childRange)) {
- if(!goog.dom.browserrange.canContainRangeEndpoint(child)) {
- if(isStartEndpoint) {
- this.startOffset_ = i
- }else {
- this.endOffset_ = i + 1
- }
- return node
- }
- return this.getEndpointNode_(endpoint, child)
- }else {
- if(this.compareBrowserRangeEndpoints(ieRange, start, end) < 0 && this.compareBrowserRangeEndpoints(ieRange, end, start) > 0) {
- return this.getEndpointNode_(endpoint, child)
- }
- }
- }
- }
- return node
-};
-goog.dom.browserrange.IeRange.prototype.compareNodeEndpoints_ = function(node, thisEndpoint, otherEndpoint) {
- return this.range_.compareEndPoints((thisEndpoint == goog.dom.RangeEndpoint.START ? "Start" : "End") + "To" + (otherEndpoint == goog.dom.RangeEndpoint.START ? "Start" : "End"), goog.dom.browserrange.createRangeFromNodeContents(node).getBrowserRange())
-};
-goog.dom.browserrange.IeRange.prototype.getOffset_ = function(endpoint, opt_container) {
- var isStartEndpoint = endpoint == goog.dom.RangeEndpoint.START;
- var container = opt_container || (isStartEndpoint ? this.getStartNode() : this.getEndNode());
- if(container.nodeType == goog.dom.NodeType.ELEMENT) {
- var children = container.childNodes;
- var len = children.length;
- var edge = isStartEndpoint ? 0 : len - 1;
- var sign = isStartEndpoint ? 1 : -1;
- for(var i = edge;i >= 0 && i < len;i += sign) {
- var child = children[i];
- if(goog.dom.browserrange.canContainRangeEndpoint(child)) {
- continue
- }
- var endPointCompare = this.compareNodeEndpoints_(child, endpoint, endpoint);
- if(endPointCompare == 0) {
- return isStartEndpoint ? i : i + 1
- }
- }
- return i == -1 ? 0 : i
- }else {
- var range = this.range_.duplicate();
- var nodeRange = goog.dom.browserrange.IeRange.getBrowserRangeForNode_(container);
- range.setEndPoint(isStartEndpoint ? "EndToEnd" : "StartToStart", nodeRange);
- var rangeLength = range.text.length;
- return isStartEndpoint ? container.length - rangeLength : rangeLength
- }
-};
-goog.dom.browserrange.IeRange.getNodeText_ = function(node) {
- return node.nodeType == goog.dom.NodeType.TEXT ? node.nodeValue : node.innerText
-};
-goog.dom.browserrange.IeRange.prototype.isRangeInDocument = function() {
- var range = this.doc_.body.createTextRange();
- range.moveToElementText(this.doc_.body);
- return this.containsRange(new goog.dom.browserrange.IeRange(range, this.doc_), true)
-};
-goog.dom.browserrange.IeRange.prototype.isCollapsed = function() {
- return this.range_.compareEndPoints("StartToEnd", this.range_) == 0
-};
-goog.dom.browserrange.IeRange.prototype.getText = function() {
- return this.range_.text
-};
-goog.dom.browserrange.IeRange.prototype.getValidHtml = function() {
- return this.range_.htmlText
-};
-goog.dom.browserrange.IeRange.prototype.select = function(opt_reverse) {
- this.range_.select()
-};
-goog.dom.browserrange.IeRange.prototype.removeContents = function() {
- if(this.range_.htmlText) {
- var startNode = this.getStartNode();
- var endNode = this.getEndNode();
- var oldText = this.range_.text;
- var clone = this.range_.duplicate();
- clone.moveStart("character", 1);
- clone.moveStart("character", -1);
- if(clone.text != oldText) {
- var iter = new goog.dom.NodeIterator(startNode, false, true);
- var toDelete = [];
- goog.iter.forEach(iter, function(node) {
- if(node.nodeType != goog.dom.NodeType.TEXT && this.containsNode(node)) {
- toDelete.push(node);
- iter.skipTag()
- }
- if(node == endNode) {
- throw goog.iter.StopIteration;
- }
- });
- this.collapse(true);
- goog.array.forEach(toDelete, goog.dom.removeNode);
- this.clearCachedValues_();
- return
- }
- this.range_ = clone;
- this.range_.text = "";
- this.clearCachedValues_();
- var newStartNode = this.getStartNode();
- var newStartOffset = this.getStartOffset();
- try {
- var sibling = startNode.nextSibling;
- if(startNode == endNode && startNode.parentNode && startNode.nodeType == goog.dom.NodeType.TEXT && sibling && sibling.nodeType == goog.dom.NodeType.TEXT) {
- startNode.nodeValue += sibling.nodeValue;
- goog.dom.removeNode(sibling);
- this.range_ = goog.dom.browserrange.IeRange.getBrowserRangeForNode_(newStartNode);
- this.range_.move("character", newStartOffset);
- this.clearCachedValues_()
- }
- }catch(e) {
- }
- }
-};
-goog.dom.browserrange.IeRange.getDomHelper_ = function(range) {
- return goog.dom.getDomHelper(range.parentElement())
-};
-goog.dom.browserrange.IeRange.pasteElement_ = function(range, element, opt_domHelper) {
- opt_domHelper = opt_domHelper || goog.dom.browserrange.IeRange.getDomHelper_(range);
- var id;
- var originalId = id = element.id;
- if(!id) {
- id = element.id = goog.string.createUniqueString()
- }
- range.pasteHTML(element.outerHTML);
- element = opt_domHelper.getElement(id);
- if(element) {
- if(!originalId) {
- element.removeAttribute("id")
- }
- }
- return element
-};
-goog.dom.browserrange.IeRange.prototype.surroundContents = function(element) {
- goog.dom.removeNode(element);
- element.innerHTML = this.range_.htmlText;
- element = goog.dom.browserrange.IeRange.pasteElement_(this.range_, element);
- if(element) {
- this.range_.moveToElementText(element)
- }
- this.clearCachedValues_();
- return element
-};
-goog.dom.browserrange.IeRange.insertNode_ = function(clone, node, before, opt_domHelper) {
- opt_domHelper = opt_domHelper || goog.dom.browserrange.IeRange.getDomHelper_(clone);
- var isNonElement;
- if(node.nodeType != goog.dom.NodeType.ELEMENT) {
- isNonElement = true;
- node = opt_domHelper.createDom(goog.dom.TagName.DIV, null, node)
- }
- clone.collapse(before);
- node = goog.dom.browserrange.IeRange.pasteElement_(clone, node, opt_domHelper);
- if(isNonElement) {
- var newNonElement = node.firstChild;
- opt_domHelper.flattenElement(node);
- node = newNonElement
- }
- return node
-};
-goog.dom.browserrange.IeRange.prototype.insertNode = function(node, before) {
- var output = goog.dom.browserrange.IeRange.insertNode_(this.range_.duplicate(), node, before);
- this.clearCachedValues_();
- return output
-};
-goog.dom.browserrange.IeRange.prototype.surroundWithNodes = function(startNode, endNode) {
- var clone1 = this.range_.duplicate();
- var clone2 = this.range_.duplicate();
- goog.dom.browserrange.IeRange.insertNode_(clone1, startNode, true);
- goog.dom.browserrange.IeRange.insertNode_(clone2, endNode, false);
- this.clearCachedValues_()
-};
-goog.dom.browserrange.IeRange.prototype.collapse = function(toStart) {
- this.range_.collapse(toStart);
- if(toStart) {
- this.endNode_ = this.startNode_;
- this.endOffset_ = this.startOffset_
- }else {
- this.startNode_ = this.endNode_;
- this.startOffset_ = this.endOffset_
- }
-};
-goog.provide("goog.dom.browserrange.OperaRange");
-goog.require("goog.dom.browserrange.W3cRange");
-goog.dom.browserrange.OperaRange = function(range) {
- goog.dom.browserrange.W3cRange.call(this, range)
-};
-goog.inherits(goog.dom.browserrange.OperaRange, goog.dom.browserrange.W3cRange);
-goog.dom.browserrange.OperaRange.createFromNodeContents = function(node) {
- return new goog.dom.browserrange.OperaRange(goog.dom.browserrange.W3cRange.getBrowserRangeForNode(node))
-};
-goog.dom.browserrange.OperaRange.createFromNodes = function(startNode, startOffset, endNode, endOffset) {
- return new goog.dom.browserrange.OperaRange(goog.dom.browserrange.W3cRange.getBrowserRangeForNodes(startNode, startOffset, endNode, endOffset))
-};
-goog.dom.browserrange.OperaRange.prototype.selectInternal = function(selection, reversed) {
- selection.collapse(this.getStartNode(), this.getStartOffset());
- if(this.getEndNode() != this.getStartNode() || this.getEndOffset() != this.getStartOffset()) {
- selection.extend(this.getEndNode(), this.getEndOffset())
- }
- if(selection.rangeCount == 0) {
- selection.addRange(this.range_)
- }
-};
-goog.provide("goog.dom.browserrange.WebKitRange");
-goog.require("goog.dom.RangeEndpoint");
-goog.require("goog.dom.browserrange.W3cRange");
-goog.require("goog.userAgent");
-goog.dom.browserrange.WebKitRange = function(range) {
- goog.dom.browserrange.W3cRange.call(this, range)
-};
-goog.inherits(goog.dom.browserrange.WebKitRange, goog.dom.browserrange.W3cRange);
-goog.dom.browserrange.WebKitRange.createFromNodeContents = function(node) {
- return new goog.dom.browserrange.WebKitRange(goog.dom.browserrange.W3cRange.getBrowserRangeForNode(node))
-};
-goog.dom.browserrange.WebKitRange.createFromNodes = function(startNode, startOffset, endNode, endOffset) {
- return new goog.dom.browserrange.WebKitRange(goog.dom.browserrange.W3cRange.getBrowserRangeForNodes(startNode, startOffset, endNode, endOffset))
-};
-goog.dom.browserrange.WebKitRange.prototype.compareBrowserRangeEndpoints = function(range, thisEndpoint, otherEndpoint) {
- if(goog.userAgent.isVersion("528")) {
- return goog.dom.browserrange.WebKitRange.superClass_.compareBrowserRangeEndpoints.call(this, range, thisEndpoint, otherEndpoint)
- }
- return this.range_.compareBoundaryPoints(otherEndpoint == goog.dom.RangeEndpoint.START ? thisEndpoint == goog.dom.RangeEndpoint.START ? goog.global["Range"].START_TO_START : goog.global["Range"].END_TO_START : thisEndpoint == goog.dom.RangeEndpoint.START ? goog.global["Range"].START_TO_END : goog.global["Range"].END_TO_END, range)
-};
-goog.dom.browserrange.WebKitRange.prototype.selectInternal = function(selection, reversed) {
- selection.removeAllRanges();
- if(reversed) {
- selection.setBaseAndExtent(this.getEndNode(), this.getEndOffset(), this.getStartNode(), this.getStartOffset())
- }else {
- selection.setBaseAndExtent(this.getStartNode(), this.getStartOffset(), this.getEndNode(), this.getEndOffset())
- }
-};
-goog.provide("goog.dom.browserrange");
-goog.provide("goog.dom.browserrange.Error");
-goog.require("goog.dom");
-goog.require("goog.dom.browserrange.GeckoRange");
-goog.require("goog.dom.browserrange.IeRange");
-goog.require("goog.dom.browserrange.OperaRange");
-goog.require("goog.dom.browserrange.W3cRange");
-goog.require("goog.dom.browserrange.WebKitRange");
-goog.require("goog.userAgent");
-goog.dom.browserrange.Error = {NOT_IMPLEMENTED:"Not Implemented"};
-goog.dom.browserrange.createRange = function(range) {
- if(goog.userAgent.IE && !goog.userAgent.isVersion("9")) {
- return new goog.dom.browserrange.IeRange(range, goog.dom.getOwnerDocument(range.parentElement()))
- }else {
- if(goog.userAgent.WEBKIT) {
- return new goog.dom.browserrange.WebKitRange(range)
- }else {
- if(goog.userAgent.GECKO) {
- return new goog.dom.browserrange.GeckoRange(range)
- }else {
- if(goog.userAgent.OPERA) {
- return new goog.dom.browserrange.OperaRange(range)
- }else {
- return new goog.dom.browserrange.W3cRange(range)
- }
- }
- }
- }
-};
-goog.dom.browserrange.createRangeFromNodeContents = function(node) {
- if(goog.userAgent.IE && !goog.userAgent.isVersion("9")) {
- return goog.dom.browserrange.IeRange.createFromNodeContents(node)
- }else {
- if(goog.userAgent.WEBKIT) {
- return goog.dom.browserrange.WebKitRange.createFromNodeContents(node)
- }else {
- if(goog.userAgent.GECKO) {
- return goog.dom.browserrange.GeckoRange.createFromNodeContents(node)
- }else {
- if(goog.userAgent.OPERA) {
- return goog.dom.browserrange.OperaRange.createFromNodeContents(node)
- }else {
- return goog.dom.browserrange.W3cRange.createFromNodeContents(node)
- }
- }
- }
- }
-};
-goog.dom.browserrange.createRangeFromNodes = function(startNode, startOffset, endNode, endOffset) {
- if(goog.userAgent.IE && !goog.userAgent.isVersion("9")) {
- return goog.dom.browserrange.IeRange.createFromNodes(startNode, startOffset, endNode, endOffset)
- }else {
- if(goog.userAgent.WEBKIT) {
- return goog.dom.browserrange.WebKitRange.createFromNodes(startNode, startOffset, endNode, endOffset)
- }else {
- if(goog.userAgent.GECKO) {
- return goog.dom.browserrange.GeckoRange.createFromNodes(startNode, startOffset, endNode, endOffset)
- }else {
- if(goog.userAgent.OPERA) {
- return goog.dom.browserrange.OperaRange.createFromNodes(startNode, startOffset, endNode, endOffset)
- }else {
- return goog.dom.browserrange.W3cRange.createFromNodes(startNode, startOffset, endNode, endOffset)
- }
- }
- }
- }
-};
-goog.dom.browserrange.canContainRangeEndpoint = function(node) {
- return goog.dom.canHaveChildren(node) || node.nodeType == goog.dom.NodeType.TEXT
-};
-goog.provide("goog.dom.TextRange");
-goog.require("goog.array");
-goog.require("goog.dom");
-goog.require("goog.dom.AbstractRange");
-goog.require("goog.dom.RangeType");
-goog.require("goog.dom.SavedRange");
-goog.require("goog.dom.TagName");
-goog.require("goog.dom.TextRangeIterator");
-goog.require("goog.dom.browserrange");
-goog.require("goog.string");
-goog.require("goog.userAgent");
-goog.dom.TextRange = function() {
-};
-goog.inherits(goog.dom.TextRange, goog.dom.AbstractRange);
-goog.dom.TextRange.createFromBrowserRange = function(range, opt_isReversed) {
- return goog.dom.TextRange.createFromBrowserRangeWrapper_(goog.dom.browserrange.createRange(range), opt_isReversed)
-};
-goog.dom.TextRange.createFromBrowserRangeWrapper_ = function(browserRange, opt_isReversed) {
- var range = new goog.dom.TextRange;
- range.browserRangeWrapper_ = browserRange;
- range.isReversed_ = !!opt_isReversed;
- return range
-};
-goog.dom.TextRange.createFromNodeContents = function(node, opt_isReversed) {
- return goog.dom.TextRange.createFromBrowserRangeWrapper_(goog.dom.browserrange.createRangeFromNodeContents(node), opt_isReversed)
-};
-goog.dom.TextRange.createFromNodes = function(anchorNode, anchorOffset, focusNode, focusOffset) {
- var range = new goog.dom.TextRange;
- range.isReversed_ = goog.dom.Range.isReversed(anchorNode, anchorOffset, focusNode, focusOffset);
- if(anchorNode.tagName == "BR") {
- var parent = anchorNode.parentNode;
- anchorOffset = goog.array.indexOf(parent.childNodes, anchorNode);
- anchorNode = parent
- }
- if(focusNode.tagName == "BR") {
- var parent = focusNode.parentNode;
- focusOffset = goog.array.indexOf(parent.childNodes, focusNode);
- focusNode = parent
- }
- if(range.isReversed_) {
- range.startNode_ = focusNode;
- range.startOffset_ = focusOffset;
- range.endNode_ = anchorNode;
- range.endOffset_ = anchorOffset
- }else {
- range.startNode_ = anchorNode;
- range.startOffset_ = anchorOffset;
- range.endNode_ = focusNode;
- range.endOffset_ = focusOffset
- }
- return range
-};
-goog.dom.TextRange.prototype.browserRangeWrapper_ = null;
-goog.dom.TextRange.prototype.startNode_ = null;
-goog.dom.TextRange.prototype.startOffset_ = null;
-goog.dom.TextRange.prototype.endNode_ = null;
-goog.dom.TextRange.prototype.endOffset_ = null;
-goog.dom.TextRange.prototype.isReversed_ = false;
-goog.dom.TextRange.prototype.clone = function() {
- var range = new goog.dom.TextRange;
- range.browserRangeWrapper_ = this.browserRangeWrapper_;
- range.startNode_ = this.startNode_;
- range.startOffset_ = this.startOffset_;
- range.endNode_ = this.endNode_;
- range.endOffset_ = this.endOffset_;
- range.isReversed_ = this.isReversed_;
- return range
-};
-goog.dom.TextRange.prototype.getType = function() {
- return goog.dom.RangeType.TEXT
-};
-goog.dom.TextRange.prototype.getBrowserRangeObject = function() {
- return this.getBrowserRangeWrapper_().getBrowserRange()
-};
-goog.dom.TextRange.prototype.setBrowserRangeObject = function(nativeRange) {
- if(goog.dom.AbstractRange.isNativeControlRange(nativeRange)) {
- return false
- }
- this.browserRangeWrapper_ = goog.dom.browserrange.createRange(nativeRange);
- this.clearCachedValues_();
- return true
-};
-goog.dom.TextRange.prototype.clearCachedValues_ = function() {
- this.startNode_ = this.startOffset_ = this.endNode_ = this.endOffset_ = null
-};
-goog.dom.TextRange.prototype.getTextRangeCount = function() {
- return 1
-};
-goog.dom.TextRange.prototype.getTextRange = function(i) {
- return this
-};
-goog.dom.TextRange.prototype.getBrowserRangeWrapper_ = function() {
- return this.browserRangeWrapper_ || (this.browserRangeWrapper_ = goog.dom.browserrange.createRangeFromNodes(this.getStartNode(), this.getStartOffset(), this.getEndNode(), this.getEndOffset()))
-};
-goog.dom.TextRange.prototype.getContainer = function() {
- return this.getBrowserRangeWrapper_().getContainer()
-};
-goog.dom.TextRange.prototype.getStartNode = function() {
- return this.startNode_ || (this.startNode_ = this.getBrowserRangeWrapper_().getStartNode())
-};
-goog.dom.TextRange.prototype.getStartOffset = function() {
- return this.startOffset_ != null ? this.startOffset_ : this.startOffset_ = this.getBrowserRangeWrapper_().getStartOffset()
-};
-goog.dom.TextRange.prototype.getEndNode = function() {
- return this.endNode_ || (this.endNode_ = this.getBrowserRangeWrapper_().getEndNode())
-};
-goog.dom.TextRange.prototype.getEndOffset = function() {
- return this.endOffset_ != null ? this.endOffset_ : this.endOffset_ = this.getBrowserRangeWrapper_().getEndOffset()
-};
-goog.dom.TextRange.prototype.moveToNodes = function(startNode, startOffset, endNode, endOffset, isReversed) {
- this.startNode_ = startNode;
- this.startOffset_ = startOffset;
- this.endNode_ = endNode;
- this.endOffset_ = endOffset;
- this.isReversed_ = isReversed;
- this.browserRangeWrapper_ = null
-};
-goog.dom.TextRange.prototype.isReversed = function() {
- return this.isReversed_
-};
-goog.dom.TextRange.prototype.containsRange = function(otherRange, opt_allowPartial) {
- var otherRangeType = otherRange.getType();
- if(otherRangeType == goog.dom.RangeType.TEXT) {
- return this.getBrowserRangeWrapper_().containsRange(otherRange.getBrowserRangeWrapper_(), opt_allowPartial)
- }else {
- if(otherRangeType == goog.dom.RangeType.CONTROL) {
- var elements = otherRange.getElements();
- var fn = opt_allowPartial ? goog.array.some : goog.array.every;
- return fn(elements, function(el) {
- return this.containsNode(el, opt_allowPartial)
- }, this)
- }
- }
- return false
-};
-goog.dom.TextRange.isAttachedNode = function(node) {
- if(goog.userAgent.IE) {
- var returnValue = false;
- try {
- returnValue = node.parentNode
- }catch(e) {
- }
- return!!returnValue
- }else {
- return goog.dom.contains(node.ownerDocument.body, node)
- }
-};
-goog.dom.TextRange.prototype.isRangeInDocument = function() {
- return(!this.startNode_ || goog.dom.TextRange.isAttachedNode(this.startNode_)) && (!this.endNode_ || goog.dom.TextRange.isAttachedNode(this.endNode_)) && (!goog.userAgent.IE || this.getBrowserRangeWrapper_().isRangeInDocument())
-};
-goog.dom.TextRange.prototype.isCollapsed = function() {
- return this.getBrowserRangeWrapper_().isCollapsed()
-};
-goog.dom.TextRange.prototype.getText = function() {
- return this.getBrowserRangeWrapper_().getText()
-};
-goog.dom.TextRange.prototype.getHtmlFragment = function() {
- return this.getBrowserRangeWrapper_().getHtmlFragment()
-};
-goog.dom.TextRange.prototype.getValidHtml = function() {
- return this.getBrowserRangeWrapper_().getValidHtml()
-};
-goog.dom.TextRange.prototype.getPastableHtml = function() {
- var html = this.getValidHtml();
- if(html.match(/^\s*<td\b/i)) {
- html = "<table><tbody><tr>" + html + "</tr></tbody></table>"
- }else {
- if(html.match(/^\s*<tr\b/i)) {
- html = "<table><tbody>" + html + "</tbody></table>"
- }else {
- if(html.match(/^\s*<tbody\b/i)) {
- html = "<table>" + html + "</table>"
- }else {
- if(html.match(/^\s*<li\b/i)) {
- var container = this.getContainer();
- var tagType = goog.dom.TagName.UL;
- while(container) {
- if(container.tagName == goog.dom.TagName.OL) {
- tagType = goog.dom.TagName.OL;
- break
- }else {
- if(container.tagName == goog.dom.TagName.UL) {
- break
- }
- }
- container = container.parentNode
- }
- html = goog.string.buildString("<", tagType, ">", html, "</", tagType, ">")
- }
- }
- }
- }
- return html
-};
-goog.dom.TextRange.prototype.__iterator__ = function(opt_keys) {
- return new goog.dom.TextRangeIterator(this.getStartNode(), this.getStartOffset(), this.getEndNode(), this.getEndOffset())
-};
-goog.dom.TextRange.prototype.select = function() {
- this.getBrowserRangeWrapper_().select(this.isReversed_)
-};
-goog.dom.TextRange.prototype.removeContents = function() {
- this.getBrowserRangeWrapper_().removeContents();
- this.clearCachedValues_()
-};
-goog.dom.TextRange.prototype.surroundContents = function(element) {
- var output = this.getBrowserRangeWrapper_().surroundContents(element);
- this.clearCachedValues_();
- return output
-};
-goog.dom.TextRange.prototype.insertNode = function(node, before) {
- var output = this.getBrowserRangeWrapper_().insertNode(node, before);
- this.clearCachedValues_();
- return output
-};
-goog.dom.TextRange.prototype.surroundWithNodes = function(startNode, endNode) {
- this.getBrowserRangeWrapper_().surroundWithNodes(startNode, endNode);
- this.clearCachedValues_()
-};
-goog.dom.TextRange.prototype.saveUsingDom = function() {
- return new goog.dom.DomSavedTextRange_(this)
-};
-goog.dom.TextRange.prototype.collapse = function(toAnchor) {
- var toStart = this.isReversed() ? !toAnchor : toAnchor;
- if(this.browserRangeWrapper_) {
- this.browserRangeWrapper_.collapse(toStart)
- }
- if(toStart) {
- this.endNode_ = this.startNode_;
- this.endOffset_ = this.startOffset_
- }else {
- this.startNode_ = this.endNode_;
- this.startOffset_ = this.endOffset_
- }
- this.isReversed_ = false
-};
-goog.dom.DomSavedTextRange_ = function(range) {
- this.anchorNode_ = range.getAnchorNode();
- this.anchorOffset_ = range.getAnchorOffset();
- this.focusNode_ = range.getFocusNode();
- this.focusOffset_ = range.getFocusOffset()
-};
-goog.inherits(goog.dom.DomSavedTextRange_, goog.dom.SavedRange);
-goog.dom.DomSavedTextRange_.prototype.restoreInternal = function() {
- return goog.dom.Range.createFromNodes(this.anchorNode_, this.anchorOffset_, this.focusNode_, this.focusOffset_)
-};
-goog.dom.DomSavedTextRange_.prototype.disposeInternal = function() {
- goog.dom.DomSavedTextRange_.superClass_.disposeInternal.call(this);
- this.anchorNode_ = null;
- this.focusNode_ = null
-};
-goog.provide("goog.dom.ControlRange");
-goog.provide("goog.dom.ControlRangeIterator");
-goog.require("goog.array");
-goog.require("goog.dom");
-goog.require("goog.dom.AbstractMultiRange");
-goog.require("goog.dom.AbstractRange");
-goog.require("goog.dom.RangeIterator");
-goog.require("goog.dom.RangeType");
-goog.require("goog.dom.SavedRange");
-goog.require("goog.dom.TagWalkType");
-goog.require("goog.dom.TextRange");
-goog.require("goog.iter.StopIteration");
-goog.require("goog.userAgent");
-goog.dom.ControlRange = function() {
-};
-goog.inherits(goog.dom.ControlRange, goog.dom.AbstractMultiRange);
-goog.dom.ControlRange.createFromBrowserRange = function(controlRange) {
- var range = new goog.dom.ControlRange;
- range.range_ = controlRange;
- return range
-};
-goog.dom.ControlRange.createFromElements = function(var_args) {
- var range = goog.dom.getOwnerDocument(arguments[0]).body.createControlRange();
- for(var i = 0, len = arguments.length;i < len;i++) {
- range.addElement(arguments[i])
- }
- return goog.dom.ControlRange.createFromBrowserRange(range)
-};
-goog.dom.ControlRange.prototype.range_ = null;
-goog.dom.ControlRange.prototype.elements_ = null;
-goog.dom.ControlRange.prototype.sortedElements_ = null;
-goog.dom.ControlRange.prototype.clearCachedValues_ = function() {
- this.elements_ = null;
- this.sortedElements_ = null
-};
-goog.dom.ControlRange.prototype.clone = function() {
- return goog.dom.ControlRange.createFromElements.apply(this, this.getElements())
-};
-goog.dom.ControlRange.prototype.getType = function() {
- return goog.dom.RangeType.CONTROL
-};
-goog.dom.ControlRange.prototype.getBrowserRangeObject = function() {
- return this.range_ || document.body.createControlRange()
-};
-goog.dom.ControlRange.prototype.setBrowserRangeObject = function(nativeRange) {
- if(!goog.dom.AbstractRange.isNativeControlRange(nativeRange)) {
- return false
- }
- this.range_ = nativeRange;
- return true
-};
-goog.dom.ControlRange.prototype.getTextRangeCount = function() {
- return this.range_ ? this.range_.length : 0
-};
-goog.dom.ControlRange.prototype.getTextRange = function(i) {
- return goog.dom.TextRange.createFromNodeContents(this.range_.item(i))
-};
-goog.dom.ControlRange.prototype.getContainer = function() {
- return goog.dom.findCommonAncestor.apply(null, this.getElements())
-};
-goog.dom.ControlRange.prototype.getStartNode = function() {
- return this.getSortedElements()[0]
-};
-goog.dom.ControlRange.prototype.getStartOffset = function() {
- return 0
-};
-goog.dom.ControlRange.prototype.getEndNode = function() {
- var sorted = this.getSortedElements();
- var startsLast = goog.array.peek(sorted);
- return goog.array.find(sorted, function(el) {
- return goog.dom.contains(el, startsLast)
- })
-};
-goog.dom.ControlRange.prototype.getEndOffset = function() {
- return this.getEndNode().childNodes.length
-};
-goog.dom.ControlRange.prototype.getElements = function() {
- if(!this.elements_) {
- this.elements_ = [];
- if(this.range_) {
- for(var i = 0;i < this.range_.length;i++) {
- this.elements_.push(this.range_.item(i))
- }
- }
- }
- return this.elements_
-};
-goog.dom.ControlRange.prototype.getSortedElements = function() {
- if(!this.sortedElements_) {
- this.sortedElements_ = this.getElements().concat();
- this.sortedElements_.sort(function(a, b) {
- return a.sourceIndex - b.sourceIndex
- })
- }
- return this.sortedElements_
-};
-goog.dom.ControlRange.prototype.isRangeInDocument = function() {
- var returnValue = false;
- try {
- returnValue = goog.array.every(this.getElements(), function(element) {
- return goog.userAgent.IE ? element.parentNode : goog.dom.contains(element.ownerDocument.body, element)
- })
- }catch(e) {
- }
- return returnValue
-};
-goog.dom.ControlRange.prototype.isCollapsed = function() {
- return!this.range_ || !this.range_.length
-};
-goog.dom.ControlRange.prototype.getText = function() {
- return""
-};
-goog.dom.ControlRange.prototype.getHtmlFragment = function() {
- return goog.array.map(this.getSortedElements(), goog.dom.getOuterHtml).join("")
-};
-goog.dom.ControlRange.prototype.getValidHtml = function() {
- return this.getHtmlFragment()
-};
-goog.dom.ControlRange.prototype.getPastableHtml = goog.dom.ControlRange.prototype.getValidHtml;
-goog.dom.ControlRange.prototype.__iterator__ = function(opt_keys) {
- return new goog.dom.ControlRangeIterator(this)
-};
-goog.dom.ControlRange.prototype.select = function() {
- if(this.range_) {
- this.range_.select()
- }
-};
-goog.dom.ControlRange.prototype.removeContents = function() {
- if(this.range_) {
- var nodes = [];
- for(var i = 0, len = this.range_.length;i < len;i++) {
- nodes.push(this.range_.item(i))
- }
- goog.array.forEach(nodes, goog.dom.removeNode);
- this.collapse(false)
- }
-};
-goog.dom.ControlRange.prototype.replaceContentsWithNode = function(node) {
- var result = this.insertNode(node, true);
- if(!this.isCollapsed()) {
- this.removeContents()
- }
- return result
-};
-goog.dom.ControlRange.prototype.saveUsingDom = function() {
- return new goog.dom.DomSavedControlRange_(this)
-};
-goog.dom.ControlRange.prototype.collapse = function(toAnchor) {
- this.range_ = null;
- this.clearCachedValues_()
-};
-goog.dom.DomSavedControlRange_ = function(range) {
- this.elements_ = range.getElements()
-};
-goog.inherits(goog.dom.DomSavedControlRange_, goog.dom.SavedRange);
-goog.dom.DomSavedControlRange_.prototype.restoreInternal = function() {
- var doc = this.elements_.length ? goog.dom.getOwnerDocument(this.elements_[0]) : document;
- var controlRange = doc.body.createControlRange();
- for(var i = 0, len = this.elements_.length;i < len;i++) {
- controlRange.addElement(this.elements_[i])
- }
- return goog.dom.ControlRange.createFromBrowserRange(controlRange)
-};
-goog.dom.DomSavedControlRange_.prototype.disposeInternal = function() {
- goog.dom.DomSavedControlRange_.superClass_.disposeInternal.call(this);
- delete this.elements_
-};
-goog.dom.ControlRangeIterator = function(range) {
- if(range) {
- this.elements_ = range.getSortedElements();
- this.startNode_ = this.elements_.shift();
- this.endNode_ = goog.array.peek(this.elements_) || this.startNode_
- }
- goog.dom.RangeIterator.call(this, this.startNode_, false)
-};
-goog.inherits(goog.dom.ControlRangeIterator, goog.dom.RangeIterator);
-goog.dom.ControlRangeIterator.prototype.startNode_ = null;
-goog.dom.ControlRangeIterator.prototype.endNode_ = null;
-goog.dom.ControlRangeIterator.prototype.elements_ = null;
-goog.dom.ControlRangeIterator.prototype.getStartTextOffset = function() {
- return 0
-};
-goog.dom.ControlRangeIterator.prototype.getEndTextOffset = function() {
- return 0
-};
-goog.dom.ControlRangeIterator.prototype.getStartNode = function() {
- return this.startNode_
-};
-goog.dom.ControlRangeIterator.prototype.getEndNode = function() {
- return this.endNode_
-};
-goog.dom.ControlRangeIterator.prototype.isLast = function() {
- return!this.depth && !this.elements_.length
-};
-goog.dom.ControlRangeIterator.prototype.next = function() {
- if(this.isLast()) {
- throw goog.iter.StopIteration;
- }else {
- if(!this.depth) {
- var el = this.elements_.shift();
- this.setPosition(el, goog.dom.TagWalkType.START_TAG, goog.dom.TagWalkType.START_TAG);
- return el
- }
- }
- return goog.dom.ControlRangeIterator.superClass_.next.call(this)
-};
-goog.dom.ControlRangeIterator.prototype.copyFrom = function(other) {
- this.elements_ = other.elements_;
- this.startNode_ = other.startNode_;
- this.endNode_ = other.endNode_;
- goog.dom.ControlRangeIterator.superClass_.copyFrom.call(this, other)
-};
-goog.dom.ControlRangeIterator.prototype.clone = function() {
- var copy = new goog.dom.ControlRangeIterator(null);
- copy.copyFrom(this);
- return copy
-};
-goog.provide("goog.dom.MultiRange");
-goog.provide("goog.dom.MultiRangeIterator");
-goog.require("goog.array");
-goog.require("goog.debug.Logger");
-goog.require("goog.dom.AbstractMultiRange");
-goog.require("goog.dom.AbstractRange");
-goog.require("goog.dom.RangeIterator");
-goog.require("goog.dom.RangeType");
-goog.require("goog.dom.SavedRange");
-goog.require("goog.dom.TextRange");
-goog.require("goog.iter.StopIteration");
-goog.dom.MultiRange = function() {
- this.browserRanges_ = [];
- this.ranges_ = [];
- this.sortedRanges_ = null;
- this.container_ = null
-};
-goog.inherits(goog.dom.MultiRange, goog.dom.AbstractMultiRange);
-goog.dom.MultiRange.createFromBrowserSelection = function(selection) {
- var range = new goog.dom.MultiRange;
- for(var i = 0, len = selection.rangeCount;i < len;i++) {
- range.browserRanges_.push(selection.getRangeAt(i))
- }
- return range
-};
-goog.dom.MultiRange.createFromBrowserRanges = function(browserRanges) {
- var range = new goog.dom.MultiRange;
- range.browserRanges_ = goog.array.clone(browserRanges);
- return range
-};
-goog.dom.MultiRange.createFromTextRanges = function(textRanges) {
- var range = new goog.dom.MultiRange;
- range.ranges_ = textRanges;
- range.browserRanges_ = goog.array.map(textRanges, function(range) {
- return range.getBrowserRangeObject()
- });
- return range
-};
-goog.dom.MultiRange.prototype.logger_ = goog.debug.Logger.getLogger("goog.dom.MultiRange");
-goog.dom.MultiRange.prototype.clearCachedValues_ = function() {
- this.ranges_ = [];
- this.sortedRanges_ = null;
- this.container_ = null
-};
-goog.dom.MultiRange.prototype.clone = function() {
- return goog.dom.MultiRange.createFromBrowserRanges(this.browserRanges_)
-};
-goog.dom.MultiRange.prototype.getType = function() {
- return goog.dom.RangeType.MULTI
-};
-goog.dom.MultiRange.prototype.getBrowserRangeObject = function() {
- if(this.browserRanges_.length > 1) {
- this.logger_.warning("getBrowserRangeObject called on MultiRange with more than 1 range")
- }
- return this.browserRanges_[0]
-};
-goog.dom.MultiRange.prototype.setBrowserRangeObject = function(nativeRange) {
- return false
-};
-goog.dom.MultiRange.prototype.getTextRangeCount = function() {
- return this.browserRanges_.length
-};
-goog.dom.MultiRange.prototype.getTextRange = function(i) {
- if(!this.ranges_[i]) {
- this.ranges_[i] = goog.dom.TextRange.createFromBrowserRange(this.browserRanges_[i])
- }
- return this.ranges_[i]
-};
-goog.dom.MultiRange.prototype.getContainer = function() {
- if(!this.container_) {
- var nodes = [];
- for(var i = 0, len = this.getTextRangeCount();i < len;i++) {
- nodes.push(this.getTextRange(i).getContainer())
- }
- this.container_ = goog.dom.findCommonAncestor.apply(null, nodes)
- }
- return this.container_
-};
-goog.dom.MultiRange.prototype.getSortedRanges = function() {
- if(!this.sortedRanges_) {
- this.sortedRanges_ = this.getTextRanges();
- this.sortedRanges_.sort(function(a, b) {
- var aStartNode = a.getStartNode();
- var aStartOffset = a.getStartOffset();
- var bStartNode = b.getStartNode();
- var bStartOffset = b.getStartOffset();
- if(aStartNode == bStartNode && aStartOffset == bStartOffset) {
- return 0
- }
- return goog.dom.Range.isReversed(aStartNode, aStartOffset, bStartNode, bStartOffset) ? 1 : -1
- })
- }
- return this.sortedRanges_
-};
-goog.dom.MultiRange.prototype.getStartNode = function() {
- return this.getSortedRanges()[0].getStartNode()
-};
-goog.dom.MultiRange.prototype.getStartOffset = function() {
- return this.getSortedRanges()[0].getStartOffset()
-};
-goog.dom.MultiRange.prototype.getEndNode = function() {
- return goog.array.peek(this.getSortedRanges()).getEndNode()
-};
-goog.dom.MultiRange.prototype.getEndOffset = function() {
- return goog.array.peek(this.getSortedRanges()).getEndOffset()
-};
-/*
-goog.dom.MultiRange.prototype.isRangeInDocument = function() {
- return goog.array.every(this.getTextRanges(), function(range) {
- return range.isRangeInDocument()
- })
-};
-*/
-goog.dom.MultiRange.prototype.isCollapsed = function() {
- return this.browserRanges_.length == 0 || this.browserRanges_.length == 1 && this.getTextRange(0).isCollapsed()
-};
-goog.dom.MultiRange.prototype.getText = function() {
- return goog.array.map(this.getTextRanges(), function(range) {
- return range.getText()
- }).join("")
-};
-goog.dom.MultiRange.prototype.getHtmlFragment = function() {
- return this.getValidHtml()
-};
-goog.dom.MultiRange.prototype.getValidHtml = function() {
- return goog.array.map(this.getTextRanges(), function(range) {
- return range.getValidHtml()
- }).join("")
-};
-goog.dom.MultiRange.prototype.getPastableHtml = function() {
- return this.getValidHtml()
-};
-goog.dom.MultiRange.prototype.__iterator__ = function(opt_keys) {
- return new goog.dom.MultiRangeIterator(this)
-};
-goog.dom.MultiRange.prototype.select = function() {
- var selection = goog.dom.AbstractRange.getBrowserSelectionForWindow(this.getWindow());
- selection.removeAllRanges();
- for(var i = 0, len = this.getTextRangeCount();i < len;i++) {
- selection.addRange(this.getTextRange(i).getBrowserRangeObject())
- }
-};
-goog.dom.MultiRange.prototype.removeContents = function() {
- goog.array.forEach(this.getTextRanges(), function(range) {
- range.removeContents()
- })
-};
-goog.dom.MultiRange.prototype.saveUsingDom = function() {
- return new goog.dom.DomSavedMultiRange_(this)
-};
-goog.dom.MultiRange.prototype.collapse = function(toAnchor) {
- if(!this.isCollapsed()) {
- var range = toAnchor ? this.getTextRange(0) : this.getTextRange(this.getTextRangeCount() - 1);
- this.clearCachedValues_();
- range.collapse(toAnchor);
- this.ranges_ = [range];
- this.sortedRanges_ = [range];
- this.browserRanges_ = [range.getBrowserRangeObject()]
- }
-};
-goog.dom.DomSavedMultiRange_ = function(range) {
- this.savedRanges_ = goog.array.map(range.getTextRanges(), function(range) {
- return range.saveUsingDom()
- })
-};
-goog.inherits(goog.dom.DomSavedMultiRange_, goog.dom.SavedRange);
-goog.dom.DomSavedMultiRange_.prototype.restoreInternal = function() {
- var ranges = goog.array.map(this.savedRanges_, function(savedRange) {
- return savedRange.restore()
- });
- return goog.dom.MultiRange.createFromTextRanges(ranges)
-};
-goog.dom.DomSavedMultiRange_.prototype.disposeInternal = function() {
- goog.dom.DomSavedMultiRange_.superClass_.disposeInternal.call(this);
- goog.array.forEach(this.savedRanges_, function(savedRange) {
- savedRange.dispose()
- });
- delete this.savedRanges_
-};
-goog.dom.MultiRangeIterator = function(range) {
- if(range) {
- this.iterators_ = goog.array.map(range.getSortedRanges(), function(r) {
- return goog.iter.toIterator(r)
- })
- }
- goog.dom.RangeIterator.call(this, range ? this.getStartNode() : null, false)
-};
-goog.inherits(goog.dom.MultiRangeIterator, goog.dom.RangeIterator);
-goog.dom.MultiRangeIterator.prototype.iterators_ = null;
-goog.dom.MultiRangeIterator.prototype.currentIdx_ = 0;
-goog.dom.MultiRangeIterator.prototype.getStartTextOffset = function() {
- return this.iterators_[this.currentIdx_].getStartTextOffset()
-};
-goog.dom.MultiRangeIterator.prototype.getEndTextOffset = function() {
- return this.iterators_[this.currentIdx_].getEndTextOffset()
-};
-goog.dom.MultiRangeIterator.prototype.getStartNode = function() {
- return this.iterators_[0].getStartNode()
-};
-goog.dom.MultiRangeIterator.prototype.getEndNode = function() {
- return goog.array.peek(this.iterators_).getEndNode()
-};
-goog.dom.MultiRangeIterator.prototype.isLast = function() {
- return this.iterators_[this.currentIdx_].isLast()
-};
-goog.dom.MultiRangeIterator.prototype.next = function() {
- try {
- var it = this.iterators_[this.currentIdx_];
- var next = it.next();
- this.setPosition(it.node, it.tagType, it.depth);
- return next
- }catch(ex) {
- if(ex !== goog.iter.StopIteration || this.iterators_.length - 1 == this.currentIdx_) {
- throw ex;
- }else {
- this.currentIdx_++;
- return this.next()
- }
- }
-};
-goog.dom.MultiRangeIterator.prototype.copyFrom = function(other) {
- this.iterators_ = goog.array.clone(other.iterators_);
- goog.dom.MultiRangeIterator.superClass_.copyFrom.call(this, other)
-};
-goog.dom.MultiRangeIterator.prototype.clone = function() {
- var copy = new goog.dom.MultiRangeIterator(null);
- copy.copyFrom(this);
- return copy
-};
-goog.provide("goog.dom.Range");
-goog.require("goog.dom");
-goog.require("goog.dom.AbstractRange");
-goog.require("goog.dom.ControlRange");
-goog.require("goog.dom.MultiRange");
-goog.require("goog.dom.NodeType");
-goog.require("goog.dom.TextRange");
-goog.require("goog.userAgent");
-goog.dom.Range.createFromWindow = function(opt_win) {
- var sel = goog.dom.AbstractRange.getBrowserSelectionForWindow(opt_win || window);
- return sel && goog.dom.Range.createFromBrowserSelection(sel)
-};
-goog.dom.Range.createFromBrowserSelection = function(selection) {
- var range;
- var isReversed = false;
- if(selection.createRange) {
- try {
- range = selection.createRange()
- }catch(e) {
- return null
- }
- }else {
- if(selection.rangeCount) {
- if(selection.rangeCount > 1) {
- return goog.dom.MultiRange.createFromBrowserSelection(selection)
- }else {
- range = selection.getRangeAt(0);
- isReversed = goog.dom.Range.isReversed(selection.anchorNode, selection.anchorOffset, selection.focusNode, selection.focusOffset)
- }
- }else {
- return null
- }
- }
- return goog.dom.Range.createFromBrowserRange(range, isReversed)
-};
-goog.dom.Range.createFromBrowserRange = function(range, opt_isReversed) {
- return goog.dom.AbstractRange.isNativeControlRange(range) ? goog.dom.ControlRange.createFromBrowserRange(range) : goog.dom.TextRange.createFromBrowserRange(range, opt_isReversed)
-};
-goog.dom.Range.createFromNodeContents = function(node, opt_isReversed) {
- return goog.dom.TextRange.createFromNodeContents(node, opt_isReversed)
-};
-goog.dom.Range.createCaret = function(node, offset) {
- return goog.dom.TextRange.createFromNodes(node, offset, node, offset)
-};
-goog.dom.Range.createFromNodes = function(startNode, startOffset, endNode, endOffset) {
- return goog.dom.TextRange.createFromNodes(startNode, startOffset, endNode, endOffset)
-};
-goog.dom.Range.clearSelection = function(opt_win) {
- var sel = goog.dom.AbstractRange.getBrowserSelectionForWindow(opt_win || window);
- if(!sel) {
- return
- }
- if(sel.empty) {
- try {
- sel.empty()
- }catch(e) {
- }
- }else {
- sel.removeAllRanges()
- }
-};
-goog.dom.Range.hasSelection = function(opt_win) {
- var sel = goog.dom.AbstractRange.getBrowserSelectionForWindow(opt_win || window);
- return!!sel && (goog.userAgent.IE ? sel.type != "None" : !!sel.rangeCount)
-};
-goog.dom.Range.isReversed = function(anchorNode, anchorOffset, focusNode, focusOffset) {
- if(anchorNode == focusNode) {
- return focusOffset < anchorOffset
- }
- var child;
- if(anchorNode.nodeType == goog.dom.NodeType.ELEMENT && anchorOffset) {
- child = anchorNode.childNodes[anchorOffset];
- if(child) {
- anchorNode = child;
- anchorOffset = 0
- }else {
- if(goog.dom.contains(anchorNode, focusNode)) {
- return true
- }
- }
- }
- if(focusNode.nodeType == goog.dom.NodeType.ELEMENT && focusOffset) {
- child = focusNode.childNodes[focusOffset];
- if(child) {
- focusNode = child;
- focusOffset = 0
- }else {
- if(goog.dom.contains(focusNode, anchorNode)) {
- return false
- }
- }
- }
- return(goog.dom.compareNodeOrder(anchorNode, focusNode) || anchorOffset - focusOffset) > 0
-};
-window.createFromWindow = goog.dom.Range.createFromWindow;
-window.createFromNodes = goog.dom.Range.createFromNodes;
-window.createCaret = goog.dom.Range.createCaret; \ No newline at end of file
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/run.js b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/run.js
deleted file mode 100644
index 6e2acd937..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/run.js
+++ /dev/null
@@ -1,383 +0,0 @@
-/**
- * @fileoverview
- * Main functions used in running the RTE test suite.
- *
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the 'License')
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an 'AS IS' BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @version 0.1
- * @author rolandsteiner@google.com
- */
-
-/**
- * Info function: returns true if the suite (mainly) tests the result HTML/Text.
- *
- * @param suite {String} the test suite
- * @return {boolean} Whether the suite main focus is the output HTML/Text
- */
-function suiteChecksHTMLOrText(suite) {
- return suite.id[0] != 'S';
-}
-
-/**
- * Info function: returns true if the suite checks the result selection.
- *
- * @param suite {String} the test suite
- * @return {boolean} Whether the suite checks the selection
- */
-function suiteChecksSelection(suite) {
- return suite.id[0] != 'Q';
-}
-
-/**
- * Helper function returning the effective value of a test parameter.
- *
- * @param suite {Object} the test suite
- * @param group {Object} group of tests within the suite the test belongs to
- * @param test {Object} the test
- * @param param {String} the test parameter to be checked
- * @return {Any} the effective value of the parameter (can be undefined)
- */
-function getTestParameter(suite, group, test, param) {
- var val = test[param];
- if (val === undefined) {
- val = group[param];
- }
- if (val === undefined) {
- val = suite[param];
- }
- return val;
-}
-
-/**
- * Helper function returning the effective value of a container/test parameter.
- *
- * @param suite {Object} the test suite
- * @param group {Object} group of tests within the suite the test belongs to
- * @param test {Object} the test
- * @param container {Object} the container descriptor object
- * @param param {String} the test parameter to be checked
- * @return {Any} the effective value of the parameter (can be undefined)
- */
-function getContainerParameter(suite, group, test, container, param) {
- var val = undefined;
- if (test[container.id]) {
- val = test[container.id][param];
- }
- if (val === undefined) {
- val = test[param];
- }
- if (val === undefined) {
- val = group[param];
- }
- if (val === undefined) {
- val = suite[param];
- }
- return val;
-}
-
-/**
- * Initializes the global variables before any tests are run.
- */
-function initVariables() {
- results = {
- count: 0,
- valscore: 0,
- selscore: 0
- };
-}
-
-/**
- * Runs a single test - outputs and sets the result variables.
- *
- * @param suite {Object} suite that test originates in as object reference
- * @param group {Object} group of tests within the suite the test belongs to
- * @param test {Object} test to be run as object reference
- * @param container {Object} container descriptor as object reference
- * @see variables.js for RESULT... values
- */
-function runSingleTest(suite, group, test, container) {
- var result = {
- valscore: 0,
- selscore: 0,
- valresult: VALRESULT_NOT_RUN,
- selresult: SELRESULT_NOT_RUN,
- output: ''
- };
-
- // 1.) Populate the editor element with the initial test setup HTML.
- try {
- initContainer(suite, group, test, container);
- } catch(ex) {
- result.valresult = VALRESULT_SETUP_EXCEPTION;
- result.selresult = SELRESULT_NA;
- result.output = SETUP_EXCEPTION + ex.toString();
- return result;
- }
-
- // 2.) Run the test command, general function or query function.
- var isHTMLTest = false;
-
- try {
- var cmd = undefined;
-
- if (cmd = getTestParameter(suite, group, test, PARAM_EXECCOMMAND)) {
- isHTMLTest = true;
- // Note: "getTestParameter(suite, group, test, PARAM_VALUE) || null"
- // doesn't work, since value might be the empty string, e.g., for 'insertText'!
- var value = getTestParameter(suite, group, test, PARAM_VALUE);
- if (value === undefined) {
- value = null;
- }
- container.doc.execCommand(cmd, false, value);
- } else if (cmd = getTestParameter(suite, group, test, PARAM_FUNCTION)) {
- isHTMLTest = true;
- eval(cmd);
- } else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDSUPPORTED)) {
- result.output = container.doc.queryCommandSupported(cmd);
- } else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDENABLED)) {
- result.output = container.doc.queryCommandEnabled(cmd);
- } else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDINDETERM)) {
- result.output = container.doc.queryCommandIndeterm(cmd);
- } else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDSTATE)) {
- result.output = container.doc.queryCommandState(cmd);
- } else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDVALUE)) {
- result.output = container.doc.queryCommandValue(cmd);
- if (result.output === false) {
- // A return value of boolean 'false' for queryCommandValue means 'not supported'.
- result.valresult = VALRESULT_UNSUPPORTED;
- result.selresult = SELRESULT_NA;
- result.output = UNSUPPORTED;
- return result;
- }
- } else {
- result.valresult = VALRESULT_SETUP_EXCEPTION;
- result.selresult = SELRESULT_NA;
- result.output = SETUP_EXCEPTION + SETUP_NOCOMMAND;
- return result;
- }
- } catch (ex) {
- result.valresult = VALRESULT_EXECUTION_EXCEPTION;
- result.selresult = SELRESULT_NA;
- result.output = EXECUTION_EXCEPTION + ex.toString();
- return result;
- }
-
- // 4.) Verify test result
- try {
- if (isHTMLTest) {
- // First, retrieve HTML from container
- prepareHTMLTestResult(container, result);
-
- // Compare result to expectations
- compareHTMLTestResult(suite, group, test, container, result);
-
- result.valscore = (result.valresult === VALRESULT_EQUAL) ? 1 : 0;
- result.selscore = (result.selresult === SELRESULT_EQUAL) ? 1 : 0;
- } else {
- compareTextTestResult(suite, group, test, result);
-
- result.selresult = SELRESULT_NA;
- result.valscore = (result.valresult === VALRESULT_EQUAL) ? 1 : 0;
- }
- } catch (ex) {
- result.valresult = VALRESULT_VERIFICATION_EXCEPTION;
- result.selresult = SELRESULT_NA;
- result.output = VERIFICATION_EXCEPTION + ex.toString();
- return result;
- }
-
- return result;
-}
-
-/**
- * Initializes the results dictionary for a given test suite.
- * (for all classes -> tests -> containers)
- *
- * @param {Object} suite as object reference
- */
-function initTestSuiteResults(suite) {
- var suiteID = suite.id;
-
- // Initialize results entries for this suite
- results[suiteID] = {
- count: 0,
- valscore: 0,
- selscore: 0,
- time: 0
- };
- var totalTestCount = 0;
-
- for (var clsIdx = 0; clsIdx < testClassCount; ++clsIdx) {
- var clsID = testClassIDs[clsIdx];
- var cls = suite[clsID];
- if (!cls)
- continue;
-
- results[suiteID][clsID] = {
- count: 0,
- valscore: 0,
- selscore: 0
- };
- var clsTestCount = 0;
-
- var groupCount = cls.length;
- for (var groupIdx = 0; groupIdx < groupCount; ++groupIdx) {
- var group = cls[groupIdx];
- var testCount = group.tests.length;
-
- clsTestCount += testCount;
- totalTestCount += testCount;
-
- for (var testIdx = 0; testIdx < testCount; ++testIdx) {
- var test = group.tests[testIdx];
-
- results[suiteID][clsID ][test.id] = {
- valscore: 0,
- selscore: 0,
- valresult: VALRESULT_NOT_RUN,
- selresult: SELRESULT_NOT_RUN
- };
- for (var cntIdx = 0; cntIdx < containers.length; ++cntIdx) {
- var cntID = containers[cntIdx].id;
-
- results[suiteID][clsID][test.id][cntID] = {
- valscore: 0,
- selscore: 0,
- valresult: VALRESULT_NOT_RUN,
- selresult: SELRESULT_NOT_RUN,
- output: ''
- }
- }
- }
- }
- results[suiteID][clsID].count = clsTestCount;
- }
- results[suiteID].count = totalTestCount;
-}
-
-/**
- * Runs a single test suite (such as DELETE tests or INSERT tests).
- *
- * @param suite {Object} suite as object reference
- */
-function runTestSuite(suite) {
- var suiteID = suite.id;
- var suiteStartTime = new Date().getTime();
-
- initTestSuiteResults(suite);
-
- for (var clsIdx = 0; clsIdx < testClassCount; ++clsIdx) {
- var clsID = testClassIDs[clsIdx];
- var cls = suite[clsID];
- if (!cls)
- continue;
-
- var groupCount = cls.length;
-
- for (var groupIdx = 0; groupIdx < groupCount; ++groupIdx) {
- var group = cls[groupIdx];
- var testCount = group.tests.length;
-
- for (var testIdx = 0; testIdx < testCount; ++testIdx) {
- var test = group.tests[testIdx];
-
- var valscore = 1;
- var selscore = 1;
- var valresult = VALRESULT_EQUAL;
- var selresult = SELRESULT_EQUAL;
-
- for (var cntIdx = 0; cntIdx < containers.length; ++cntIdx) {
- var container = containers[cntIdx];
- var cntID = container.id;
-
- var result = runSingleTest(suite, group, test, container);
-
- results[suiteID][clsID][test.id][cntID] = result;
-
- valscore = Math.min(valscore, result.valscore);
- selscore = Math.min(selscore, result.selscore);
- valresult = Math.min(valresult, result.valresult);
- selresult = Math.min(selresult, result.selresult);
-
- resetContainer(container);
- }
-
- results[suiteID][clsID][test.id].valscore = valscore;
- results[suiteID][clsID][test.id].selscore = selscore;
- results[suiteID][clsID][test.id].valresult = valresult;
- results[suiteID][clsID][test.id].selresult = selresult;
-
- results[suiteID][clsID].valscore += valscore;
- results[suiteID][clsID].selscore += selscore;
- results[suiteID].valscore += valscore;
- results[suiteID].selscore += selscore;
- results.valscore += valscore;
- results.selscore += selscore;
- }
- }
- }
-
- results[suiteID].time = new Date().getTime() - suiteStartTime;
-}
-
-/**
- * Runs a single test suite (such as DELETE tests or INSERT tests)
- * and updates the output HTML.
- *
- * @param {Object} suite as object reference
- */
-function runAndOutputTestSuite(suite) {
- runTestSuite(suite);
- outputTestSuiteResults(suite);
-}
-
-/**
- * Fills the beacon with the test results.
- */
-function fillResults() {
- // Result totals of the individual categories
- categoryTotals = [
- 'selection=' + results['S'].selscore,
- 'apply=' + results['A'].valscore,
- 'applyCSS=' + results['AC'].valscore,
- 'change=' + results['C'].valscore,
- 'changeCSS=' + results['CC'].valscore,
- 'unapply=' + results['U'].valscore,
- 'unapplyCSS=' + results['UC'].valscore,
- 'delete=' + results['D'].valscore,
- 'forwarddelete=' + results['FD'].valscore,
- 'insert=' + results['I'].valscore,
- 'selectionResult=' + (results['A'].selscore +
- results['AC'].selscore +
- results['C'].selscore +
- results['CC'].selscore +
- results['U'].selscore +
- results['UC'].selscore +
- results['D'].selscore +
- results['FD'].selscore +
- results['I'].selscore),
- 'querySupported=' + results['Q'].valscore,
- 'queryEnabled=' + results['QE'].valscore,
- 'queryIndeterm=' + results['QI'].valscore,
- 'queryState=' + results['QS'].valscore,
- 'queryStateCSS=' + results['QSC'].valscore,
- 'queryValue=' + results['QV'].valscore,
- 'queryValueCSS=' + results['QVC'].valscore
- ];
-
- // Beacon copies category results
- beacon = categoryTotals.slice(0);
-}
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/units.js b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/units.js
deleted file mode 100644
index f2c23fbe5..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/units.js
+++ /dev/null
@@ -1,416 +0,0 @@
-/**
- * @fileoverview
- * Common constants and variables used in the RTE test suite.
- *
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the 'License')
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an 'AS IS' BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @version 0.1
- * @author rolandsteiner@google.com
- */
-
-// All colors defined in CSS3.
-var colorChart = {
- 'aliceblue': {red: 0xF0, green: 0xF8, blue: 0xFF},
- 'antiquewhite': {red: 0xFA, green: 0xEB, blue: 0xD7},
- 'aqua': {red: 0x00, green: 0xFF, blue: 0xFF},
- 'aquamarine': {red: 0x7F, green: 0xFF, blue: 0xD4},
- 'azure': {red: 0xF0, green: 0xFF, blue: 0xFF},
- 'beige': {red: 0xF5, green: 0xF5, blue: 0xDC},
- 'bisque': {red: 0xFF, green: 0xE4, blue: 0xC4},
- 'black': {red: 0x00, green: 0x00, blue: 0x00},
- 'blanchedalmond': {red: 0xFF, green: 0xEB, blue: 0xCD},
- 'blue': {red: 0x00, green: 0x00, blue: 0xFF},
- 'blueviolet': {red: 0x8A, green: 0x2B, blue: 0xE2},
- 'brown': {red: 0xA5, green: 0x2A, blue: 0x2A},
- 'burlywood': {red: 0xDE, green: 0xB8, blue: 0x87},
- 'cadetblue': {red: 0x5F, green: 0x9E, blue: 0xA0},
- 'chartreuse': {red: 0x7F, green: 0xFF, blue: 0x00},
- 'chocolate': {red: 0xD2, green: 0x69, blue: 0x1E},
- 'coral': {red: 0xFF, green: 0x7F, blue: 0x50},
- 'cornflowerblue': {red: 0x64, green: 0x95, blue: 0xED},
- 'cornsilk': {red: 0xFF, green: 0xF8, blue: 0xDC},
- 'crimson': {red: 0xDC, green: 0x14, blue: 0x3C},
- 'cyan': {red: 0x00, green: 0xFF, blue: 0xFF},
- 'darkblue': {red: 0x00, green: 0x00, blue: 0x8B},
- 'darkcyan': {red: 0x00, green: 0x8B, blue: 0x8B},
- 'darkgoldenrod': {red: 0xB8, green: 0x86, blue: 0x0B},
- 'darkgray': {red: 0xA9, green: 0xA9, blue: 0xA9},
- 'darkgreen': {red: 0x00, green: 0x64, blue: 0x00},
- 'darkgrey': {red: 0xA9, green: 0xA9, blue: 0xA9},
- 'darkkhaki': {red: 0xBD, green: 0xB7, blue: 0x6B},
- 'darkmagenta': {red: 0x8B, green: 0x00, blue: 0x8B},
- 'darkolivegreen': {red: 0x55, green: 0x6B, blue: 0x2F},
- 'darkorange': {red: 0xFF, green: 0x8C, blue: 0x00},
- 'darkorchid': {red: 0x99, green: 0x32, blue: 0xCC},
- 'darkred': {red: 0x8B, green: 0x00, blue: 0x00},
- 'darksalmon': {red: 0xE9, green: 0x96, blue: 0x7A},
- 'darkseagreen': {red: 0x8F, green: 0xBC, blue: 0x8F},
- 'darkslateblue': {red: 0x48, green: 0x3D, blue: 0x8B},
- 'darkslategray': {red: 0x2F, green: 0x4F, blue: 0x4F},
- 'darkslategrey': {red: 0x2F, green: 0x4F, blue: 0x4F},
- 'darkturquoise': {red: 0x00, green: 0xCE, blue: 0xD1},
- 'darkviolet': {red: 0x94, green: 0x00, blue: 0xD3},
- 'deeppink': {red: 0xFF, green: 0x14, blue: 0x93},
- 'deepskyblue': {red: 0x00, green: 0xBF, blue: 0xFF},
- 'dimgray': {red: 0x69, green: 0x69, blue: 0x69},
- 'dimgrey': {red: 0x69, green: 0x69, blue: 0x69},
- 'dodgerblue': {red: 0x1E, green: 0x90, blue: 0xFF},
- 'firebrick': {red: 0xB2, green: 0x22, blue: 0x22},
- 'floralwhite': {red: 0xFF, green: 0xFA, blue: 0xF0},
- 'forestgreen': {red: 0x22, green: 0x8B, blue: 0x22},
- 'fuchsia': {red: 0xFF, green: 0x00, blue: 0xFF},
- 'gainsboro': {red: 0xDC, green: 0xDC, blue: 0xDC},
- 'ghostwhite': {red: 0xF8, green: 0xF8, blue: 0xFF},
- 'gold': {red: 0xFF, green: 0xD7, blue: 0x00},
- 'goldenrod': {red: 0xDA, green: 0xA5, blue: 0x20},
- 'gray': {red: 0x80, green: 0x80, blue: 0x80},
- 'green': {red: 0x00, green: 0x80, blue: 0x00},
- 'greenyellow': {red: 0xAD, green: 0xFF, blue: 0x2F},
- 'grey': {red: 0x80, green: 0x80, blue: 0x80},
- 'honeydew': {red: 0xF0, green: 0xFF, blue: 0xF0},
- 'hotpink': {red: 0xFF, green: 0x69, blue: 0xB4},
- 'indianred': {red: 0xCD, green: 0x5C, blue: 0x5C},
- 'indigo': {red: 0x4B, green: 0x00, blue: 0x82},
- 'ivory': {red: 0xFF, green: 0xFF, blue: 0xF0},
- 'khaki': {red: 0xF0, green: 0xE6, blue: 0x8C},
- 'lavender': {red: 0xE6, green: 0xE6, blue: 0xFA},
- 'lavenderblush': {red: 0xFF, green: 0xF0, blue: 0xF5},
- 'lawngreen': {red: 0x7C, green: 0xFC, blue: 0x00},
- 'lemonchiffon': {red: 0xFF, green: 0xFA, blue: 0xCD},
- 'lightblue': {red: 0xAD, green: 0xD8, blue: 0xE6},
- 'lightcoral': {red: 0xF0, green: 0x80, blue: 0x80},
- 'lightcyan': {red: 0xE0, green: 0xFF, blue: 0xFF},
- 'lightgoldenrodyellow': {red: 0xFA, green: 0xFA, blue: 0xD2},
- 'lightgray': {red: 0xD3, green: 0xD3, blue: 0xD3},
- 'lightgreen': {red: 0x90, green: 0xEE, blue: 0x90},
- 'lightgrey': {red: 0xD3, green: 0xD3, blue: 0xD3},
- 'lightpink': {red: 0xFF, green: 0xB6, blue: 0xC1},
- 'lightsalmon': {red: 0xFF, green: 0xA0, blue: 0x7A},
- 'lightseagreen': {red: 0x20, green: 0xB2, blue: 0xAA},
- 'lightskyblue': {red: 0x87, green: 0xCE, blue: 0xFA},
- 'lightslategray': {red: 0x77, green: 0x88, blue: 0x99},
- 'lightslategrey': {red: 0x77, green: 0x88, blue: 0x99},
- 'lightsteelblue': {red: 0xB0, green: 0xC4, blue: 0xDE},
- 'lightyellow': {red: 0xFF, green: 0xFF, blue: 0xE0},
- 'lime': {red: 0x00, green: 0xFF, blue: 0x00},
- 'limegreen': {red: 0x32, green: 0xCD, blue: 0x32},
- 'linen': {red: 0xFA, green: 0xF0, blue: 0xE6},
- 'magenta': {red: 0xFF, green: 0x00, blue: 0xFF},
- 'maroon': {red: 0x80, green: 0x00, blue: 0x00},
- 'mediumaquamarine': {red: 0x66, green: 0xCD, blue: 0xAA},
- 'mediumblue': {red: 0x00, green: 0x00, blue: 0xCD},
- 'mediumorchid': {red: 0xBA, green: 0x55, blue: 0xD3},
- 'mediumpurple': {red: 0x93, green: 0x70, blue: 0xDB},
- 'mediumseagreen': {red: 0x3C, green: 0xB3, blue: 0x71},
- 'mediumslateblue': {red: 0x7B, green: 0x68, blue: 0xEE},
- 'mediumspringgreen': {red: 0x00, green: 0xFA, blue: 0x9A},
- 'mediumturquoise': {red: 0x48, green: 0xD1, blue: 0xCC},
- 'mediumvioletred': {red: 0xC7, green: 0x15, blue: 0x85},
- 'midnightblue': {red: 0x19, green: 0x19, blue: 0x70},
- 'mintcream': {red: 0xF5, green: 0xFF, blue: 0xFA},
- 'mistyrose': {red: 0xFF, green: 0xE4, blue: 0xE1},
- 'moccasin': {red: 0xFF, green: 0xE4, blue: 0xB5},
- 'navajowhite': {red: 0xFF, green: 0xDE, blue: 0xAD},
- 'navy': {red: 0x00, green: 0x00, blue: 0x80},
- 'oldlace': {red: 0xFD, green: 0xF5, blue: 0xE6},
- 'olive': {red: 0x80, green: 0x80, blue: 0x00},
- 'olivedrab': {red: 0x6B, green: 0x8E, blue: 0x23},
- 'orange': {red: 0xFF, green: 0xA5, blue: 0x00},
- 'orangered': {red: 0xFF, green: 0x45, blue: 0x00},
- 'orchid': {red: 0xDA, green: 0x70, blue: 0xD6},
- 'palegoldenrod': {red: 0xEE, green: 0xE8, blue: 0xAA},
- 'palegreen': {red: 0x98, green: 0xFB, blue: 0x98},
- 'paleturquoise': {red: 0xAF, green: 0xEE, blue: 0xEE},
- 'palevioletred': {red: 0xDB, green: 0x70, blue: 0x93},
- 'papayawhip': {red: 0xFF, green: 0xEF, blue: 0xD5},
- 'peachpuff': {red: 0xFF, green: 0xDA, blue: 0xB9},
- 'peru': {red: 0xCD, green: 0x85, blue: 0x3F},
- 'pink': {red: 0xFF, green: 0xC0, blue: 0xCB},
- 'plum': {red: 0xDD, green: 0xA0, blue: 0xDD},
- 'powderblue': {red: 0xB0, green: 0xE0, blue: 0xE6},
- 'purple': {red: 0x80, green: 0x00, blue: 0x80},
- 'red': {red: 0xFF, green: 0x00, blue: 0x00},
- 'rosybrown': {red: 0xBC, green: 0x8F, blue: 0x8F},
- 'royalblue': {red: 0x41, green: 0x69, blue: 0xE1},
- 'saddlebrown': {red: 0x8B, green: 0x45, blue: 0x13},
- 'salmon': {red: 0xFA, green: 0x80, blue: 0x72},
- 'sandybrown': {red: 0xF4, green: 0xA4, blue: 0x60},
- 'seagreen': {red: 0x2E, green: 0x8B, blue: 0x57},
- 'seashell': {red: 0xFF, green: 0xF5, blue: 0xEE},
- 'sienna': {red: 0xA0, green: 0x52, blue: 0x2D},
- 'silver': {red: 0xC0, green: 0xC0, blue: 0xC0},
- 'skyblue': {red: 0x87, green: 0xCE, blue: 0xEB},
- 'slateblue': {red: 0x6A, green: 0x5A, blue: 0xCD},
- 'slategray': {red: 0x70, green: 0x80, blue: 0x90},
- 'slategrey': {red: 0x70, green: 0x80, blue: 0x90},
- 'snow': {red: 0xFF, green: 0xFA, blue: 0xFA},
- 'springgreen': {red: 0x00, green: 0xFF, blue: 0x7F},
- 'steelblue': {red: 0x46, green: 0x82, blue: 0xB4},
- 'tan': {red: 0xD2, green: 0xB4, blue: 0x8C},
- 'teal': {red: 0x00, green: 0x80, blue: 0x80},
- 'thistle': {red: 0xD8, green: 0xBF, blue: 0xD8},
- 'tomato': {red: 0xFF, green: 0x63, blue: 0x47},
- 'turquoise': {red: 0x40, green: 0xE0, blue: 0xD0},
- 'violet': {red: 0xEE, green: 0x82, blue: 0xEE},
- 'wheat': {red: 0xF5, green: 0xDE, blue: 0xB3},
- 'white': {red: 0xFF, green: 0xFF, blue: 0xFF},
- 'whitesmoke': {red: 0xF5, green: 0xF5, blue: 0xF5},
- 'yellow': {red: 0xFF, green: 0xFF, blue: 0x00},
- 'yellowgreen': {red: 0x9A, green: 0xCD, blue: 0x32},
-
- 'transparent': {red: 0x00, green: 0x00, blue: 0x00, alpha: 0.0}
-};
-
-/**
- * Color class allows cross-browser comparison of values, which can
- * be returned from queryCommandValue in several formats:
- * #ff00ff
- * #f0f
- * rgb(255, 0, 0)
- * rgb(100%, 0%, 28%) // disabled for the time being (see below)
- * rgba(127, 0, 64, 0.25)
- * rgba(50%, 0%, 10%, 0.65) // disabled for the time being (see below)
- * palegoldenrod
- * transparent
- *
- * @constructor
- * @param value {String} original value
- */
-function Color(value) {
- this.compare = function(other) {
- if (!this.valid || !other.valid) {
- return false;
- }
- if (this.alpha != other.alpha) {
- return false;
- }
- if (this.alpha == 0.0) {
- // both are fully transparent -> ignore the specific color information
- return true;
- }
- // TODO(rolandsteiner): handle hsl/hsla values
- return this.red == other.red && this.green == other.green && this.blue == other.blue;
- }
- this.parse = function(value) {
- if (!value)
- return false;
- value = String(value).toLowerCase();
- var match;
- // '#' + 6 hex digits, e.g., #ff3300
- match = value.match(/#([0-9a-f]{6})/i);
- if (match) {
- this.red = parseInt(match[1].substring(0, 2), 16);
- this.green = parseInt(match[1].substring(2, 4), 16);
- this.blue = parseInt(match[1].substring(4, 6), 16);
- this.alpha = 1.0;
- return true;
- }
- // '#' + 3 hex digits, e.g., #f30
- match = value.match(/#([0-9a-f]{3})/i);
- if (match) {
- this.red = parseInt(match[1].substring(0, 1), 16) * 16;
- this.green = parseInt(match[1].substring(1, 2), 16) * 16;
- this.blue = parseInt(match[1].substring(2, 3), 16) * 16;
- this.alpha = 1.0;
- return true;
- }
- // a color name, e.g., springgreen
- match = colorChart[value];
- if (match) {
- this.red = match.red;
- this.green = match.green;
- this.blue = match.blue;
- this.alpha = (match.alpha === undefined) ? 1.0 : match.alpha;
- return true;
- }
- // rgb(r, g, b), e.g., rgb(128, 12, 217)
- match = value.match(/rgb\(([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/i);
- if (match) {
- this.red = Number(match[1]);
- this.green = Number(match[2]);
- this.blue = Number(match[3]);
- this.alpha = 1.0;
- return true;
- }
- // rgb(r%, g%, b%), e.g., rgb(100%, 0%, 50%)
-// Commented out for the time being, since it seems likely that the resulting
-// decimal values will create false negatives when compared with non-% values.
-//
-// => store as separate percent values and do exact matching when compared with % values
-// and fuzzy matching when compared with non-% values?
-//
-// match = value.match(/rgb\(([0-9]{0,3}(?:\.[0-9]+)?)%\s*,\s*([0-9]{0,3}(?:\.[0-9]+)?)%\s*,\s*([0-9]{0,3}(?:\.[0-9]+)?)%\s*\)/i);
-// if (match) {
-// this.red = Number(match[1]) * 255 / 100;
-// this.green = Number(match[2]) * 255 / 100;
-// this.blue = Number(match[3]) * 255 / 100;
-// this.alpha = 1.0;
-// return true;
-// }
- // rgba(r, g, b, a), e.g., rgb(128, 12, 217, 0.2)
- match = value.match(/rgba\(([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/i);
- if (match) {
- this.red = Number(match[1]);
- this.green = Number(match[2]);
- this.blue = Number(match[3]);
- this.alpha = Number(match[4]);
- return true;
- }
- // rgba(r%, g%, b%, a), e.g., rgb(100%, 0%, 50%, 0.3)
-// Commented out for the time being (cf. rgb() matching above)
-// match = value.match(/rgba\(([0-9]{0,3}(?:\.[0-9]+)?)%\s*,\s*([0-9]{0,3}(?:\.[0-9]+)?)%\s*,\s*([0-9]{0,3}(?:\.[0-9]+)?)%,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/i);
-// if (match) {
-// this.red = Number(match[1]) * 255 / 100;
-// this.green = Number(match[2]) * 255 / 100;
-// this.blue = Number(match[3]) * 255 / 100;
-// this.alpha = Number(match[4]);
-// return true;
-// }
- // TODO(rolandsteiner): handle "hsl(h, s, l)" and "hsla(h, s, l, a)" notation
- return false;
- }
- this.toString = function() {
- return this.valid ? this.red + ',' + this.green + ',' + this.blue : '(invalid)';
- }
- this.toHexString = function() {
- if (!this.valid)
- return '(invalid)';
- return ((this.red < 16) ? '0' : '') + this.red.toString(16) +
- ((this.green < 16) ? '0' : '') + this.green.toString(16) +
- ((this.blue < 16) ? '0' : '') + this.blue.toString(16);
- }
- this.valid = this.parse(value);
-}
-
-/**
- * Utility class for converting font sizes to the size
- * attribute in a font tag. Currently only converts px because
- * only the sizes and px ever come from queryCommandValue.
- *
- * @constructor
- * @param value {String} original value
- */
-function FontSize(value) {
- this.parse = function(str) {
- if (!str)
- this.valid = false;
- var match;
- if (match = String(str).match(/([0-9]+)px/)) {
- var px = Number(match[1]);
- if (px <= 0 || px > 47)
- return false;
- if (px <= 10) {
- this.size = '1';
- } else if (px <= 13) {
- this.size = '2';
- } else if (px <= 16) {
- this.size = '3';
- } else if (px <= 18) {
- this.size = '4';
- } else if (px <= 24) {
- this.size = '5';
- } else if (px <= 32) {
- this.size = '6';
- } else {
- this.size = '7';
- }
- return true;
- }
- if (match = String(str).match(/([+-][0-9]+)/)) {
- this.size = match[1];
- return this.size >= 1 && this.size <= 7;
- }
- if (Number(str)) {
- this.size = String(Number(str));
- return this.size >= 1 && this.size <= 7;
- }
- switch (str) {
- case 'x-small':
- this.size = '1';
- return true;
- case 'small':
- this.size = '2';
- return true;
- case 'medium':
- this.size = '3';
- return true;
- case 'large':
- this.size = '4';
- return true;
- case 'x-large':
- this.size = '5';
- return true;
- case 'xx-large':
- this.size = '6';
- return true;
- case 'xxx-large':
- this.size = '7';
- return true;
- case '-webkit-xxx-large':
- this.size = '7';
- return true;
- case 'larger':
- this.size = '+1';
- return true;
- case 'smaller':
- this.size = '-1';
- return true;
- }
- return false;
- }
- this.compare = function(other) {
- return this.valid && other.valid && this.size === other.size;
- }
- this.toString = function() {
- return this.valid ? this.size : '(invalid)';
- }
- this.valid = this.parse(value);
-}
-
-/**
- * Utility class for converting & canonicalizing font names.
- *
- * @constructor
- * @param value {String} original value
- */
-function FontName(value) {
- this.parse = function(str) {
- if (!str)
- return false;
- str = String(str).toLowerCase();
- switch (str) {
- case 'arial new':
- this.fontname = 'arial';
- return true;
- case 'courier new':
- this.fontname = 'courier';
- return true;
- case 'times new':
- case 'times roman':
- case 'times new roman':
- this.fontname = 'times';
- return true;
- }
- this.fontname = value;
- return true;
- }
- this.compare = function(other) {
- return this.valid && other.valid && this.fontname === other.fontname;
- }
- this.toString = function() {
- return this.valid ? this.fontname : '(invalid)';
- }
- this.valid = this.parse(value);
-}
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/variables.js b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/variables.js
deleted file mode 100644
index cdc6f1e92..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/variables.js
+++ /dev/null
@@ -1,227 +0,0 @@
-/**
- * @fileoverview
- * Common constants and variables used in the RTE test suite.
- *
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the 'License')
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an 'AS IS' BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @version 0.1
- * @author rolandsteiner@google.com
- */
-
-// Constant for indicating a test setup is unsupported or incorrect
-// (threw exception).
-var INTERNAL_ERR = 'INTERNAL ERROR: ';
-var SETUP_EXCEPTION = 'SETUP EXCEPTION: ';
-var EXECUTION_EXCEPTION = 'EXECUTION EXCEPTION: ';
-var VERIFICATION_EXCEPTION = 'VERIFICATION EXCEPTION: ';
-
-var SETUP_CONTAINER = 'WHEN INITIALIZING TEST CONTAINER';
-var SETUP_BAD_SELECTION_SPEC = 'BAD SELECTION SPECIFICATION IN TEST OR EXPECTATION STRING';
-var SETUP_HTML = 'WHEN SETTING TEST HTML';
-var SETUP_SELECTION = 'WHEN SETTING SELECTION';
-var SETUP_NOCOMMAND = 'NO COMMAND, GENERAL FUNCTION OR QUERY FUNCTION GIVEN';
-var HTML_COMPARISON = 'WHEN COMPARING OUTPUT HTML';
-
-// Exceptiona to be thrown on unsupported selection operations
-var SELMODIFY_UNSUPPORTED = 'UNSUPPORTED selection.modify()';
-var SELALLCHILDREN_UNSUPPORTED = 'UNSUPPORTED selection.selectAllChildren()';
-
-// Output string for unsupported functions
-// (returning bool 'false' as opposed to throwing an exception)
-var UNSUPPORTED = '<i>false</i> (UNSUPPORTED)';
-
-// HTML comparison result contants.
-var VALRESULT_NOT_RUN = 0; // test hasn't been run yet
-var VALRESULT_SETUP_EXCEPTION = 1;
-var VALRESULT_EXECUTION_EXCEPTION = 2;
-var VALRESULT_VERIFICATION_EXCEPTION = 3;
-var VALRESULT_UNSUPPORTED = 4;
-var VALRESULT_CANARY = 5; // HTML changes bled into the canary.
-var VALRESULT_DIFF = 6;
-var VALRESULT_ACCEPT = 7; // HTML technically correct, but not ideal.
-var VALRESULT_EQUAL = 8;
-
-var VALOUTPUT = [ // IMPORTANT: this array MUST be coordinated with the values above!!
- {css: 'grey', output: '???', title: 'The test has not been run yet.'}, // VALRESULT_NOT_RUN
- {css: 'exception', output: 'EXC.', title: 'Exception was thrown during setup.'}, // VALRESULT_SETUP_EXCEPTION
- {css: 'exception', output: 'EXC.', title: 'Exception was thrown during execution.'}, // VALRESULT_EXECUTION_EXCEPTION
- {css: 'exception', output: 'EXC.', title: 'Exception was thrown during result verification.'}, // VALRESULT_VERIFICATION_EXCEPTION
- {css: 'unsupported', output: 'UNS.', title: 'Unsupported command or value'}, // VALRESULT_UNSUPPORTED
- {css: 'canary', output: 'CANARY', title: 'The command affected the contentEditable root element, or outside HTML.'}, // VALRESULT_CANARY
- {css: 'fail', output: 'FAIL', title: 'The result differs from the expectation(s).'}, // VALRESULT_DIFF
- {css: 'accept', output: 'ACC.', title: 'The result is technically correct, but sub-optimal.'}, // VALRESULT_ACCEPT
- {css: 'pass', output: 'PASS', title: 'The test result matches the expectation.'} // VALRESULT_EQUAL
-]
-
-// Selection comparison result contants.
-var SELRESULT_NOT_RUN = 0; // test hasn't been run yet
-var SELRESULT_CANARY = 1; // selection escapes the contentEditable element
-var SELRESULT_DIFF = 2;
-var SELRESULT_NA = 3;
-var SELRESULT_ACCEPT = 4; // Selection is acceptable, but not ideal.
-var SELRESULT_EQUAL = 5;
-
-var SELOUTPUT = [ // IMPORTANT: this array MUST be coordinated with the values above!!
- {css: 'grey', output: 'grey', title: 'The test has not been run yet.'}, // SELRESULT_NOT_RUN
- {css: 'canary', output: 'CANARY', title: 'The selection escaped the contentEditable boundary!'}, // SELRESULT_CANARY
- {css: 'fail', output: 'FAIL', title: 'The selection differs from the expectation(s).'}, // SELRESULT_DIFF
- {css: 'na', output: 'N/A', title: 'The correctness of the selection could not be verified.'}, // SELRESULT_NA
- {css: 'accept', output: 'ACC.', title: 'The selection is technically correct, but sub-optimal.'}, // SELRESULT_ACCEPT
- {css: 'pass', output: 'PASS', title: 'The selection matches the expectation.'} // SELRESULT_EQUAL
-];
-
-// RegExp for selection markers
-var SELECTION_MARKERS = /[\[\]\{\}\|\^]/;
-
-// Special attributes used to mark selections within elements that otherwise
-// have no children. Important: attribute name MUST be lower case!
-var ATTRNAME_SEL_START = 'bsselstart';
-var ATTRNAME_SEL_END = 'bsselend';
-
-// DOM node type constants.
-var DOM_NODE_TYPE_ELEMENT = 1;
-var DOM_NODE_TYPE_TEXT = 3;
-var DOM_NODE_TYPE_COMMENT = 8;
-
-// Test parameter names
-var PARAM_DESCRIPTION = 'desc';
-var PARAM_PAD = 'pad';
-var PARAM_EXECCOMMAND = 'command';
-var PARAM_FUNCTION = 'function';
-var PARAM_QUERYCOMMANDSUPPORTED = 'qcsupported';
-var PARAM_QUERYCOMMANDENABLED = 'qcenabled';
-var PARAM_QUERYCOMMANDINDETERM = 'qcindeterm';
-var PARAM_QUERYCOMMANDSTATE = 'qcstate';
-var PARAM_QUERYCOMMANDVALUE = 'qcvalue';
-var PARAM_VALUE = 'value';
-var PARAM_EXPECTED = 'expected';
-var PARAM_EXPECTED_OUTER = 'expOuter';
-var PARAM_ACCEPT = 'accept';
-var PARAM_ACCEPT_OUTER = 'accOuter';
-var PARAM_CHECK_ATTRIBUTES = 'checkAttrs';
-var PARAM_CHECK_STYLE = 'checkStyle';
-var PARAM_CHECK_CLASS = 'checkClass';
-var PARAM_CHECK_ID = 'checkID';
-var PARAM_STYLE_WITH_CSS = 'styleWithCSS';
-
-// ID suffixes for the output columns
-var IDOUT_TR = '_:TR:'; // per container
-var IDOUT_TESTID = '_:tid'; // per test
-var IDOUT_COMMAND = '_:cmd'; // per test
-var IDOUT_VALUE = '_:val'; // per test
-var IDOUT_CHECKATTRS = '_:att'; // per test
-var IDOUT_CHECKSTYLE = '_:sty'; // per test
-var IDOUT_CONTAINER = '_:cnt:'; // per container
-var IDOUT_STATUSVAL = '_:sta:'; // per container
-var IDOUT_STATUSSEL = '_:sel:'; // per container
-var IDOUT_PAD = '_:pad'; // per test
-var IDOUT_EXPECTED = '_:exp'; // per test
-var IDOUT_ACTUAL = '_:act:'; // per container
-
-// Output strings to use for yes/no/NA
-var OUTSTR_YES = '&#x25CF;';
-var OUTSTR_NO = '&#x25CB;';
-var OUTSTR_NA = '-';
-
-// Tags at the start of HTML strings where they were taken from
-var HTMLTAG_BODY = 'B:';
-var HTMLTAG_OUTER = 'O:';
-var HTMLTAG_INNER = 'I:';
-
-// What to use for the canary
-var CANARY = 'CAN<br>ARY';
-
-// Containers for tests, and their associated DOM elements:
-// iframe, win, doc, body, elem
-var containers = [
- { id: 'dM',
- iframe: null,
- win: null,
- doc: null,
- body: null,
- editor: null,
- tagOpen: '<body>',
- tagClose: '</body>',
- editorID: null,
- canary: '',
- },
- { id: 'body',
- iframe: null,
- win: null,
- doc: null,
- body: null,
- editor: null,
- tagOpen: '<body contenteditable="true">',
- tagClose: '</body>',
- editorID: null,
- canary: ''
- },
- { id: 'div',
- iframe: null,
- win: null,
- doc: null,
- body: null,
- editor: null,
- tagOpen: '<div contenteditable="true" id="editor-div">',
- tagClose: '</div>',
- editorID: 'editor-div',
- canary: CANARY
- }
-];
-
-// Helper variables to use in test functions
-var win = null; // window object to use for test functions
-var doc = null; // document object to use for test functions
-var body = null; // The <body> element of the current document
-var editor = null; // The contentEditable element (i.e., the <body> or <div>)
-var sel = null; // The current selection after the pad is set up
-
-// Canonicalization emit flags for various purposes
-var emitFlagsForCanary = {
- emitAttrs: true,
- emitStyle: true,
- emitClass: true,
- emitID: true,
- lowercase: true,
- canonicalizeUnits: true
-};
-var emitFlagsForOutput = {
- emitAttrs: true,
- emitStyle: true,
- emitClass: true,
- emitID: true,
- lowercase: false,
- canonicalizeUnits: false
-};
-
-// Shades of output colors
-var colorShades = ['Lo', 'Hi'];
-
-// Classes of tests
-var testClassIDs = ['Finalized', 'RFC', 'Proposed'];
-var testClassCount = testClassIDs.length;
-
-// Dictionary storing the detailed test results.
-var results = {
- count: 0,
- score: 0
-};
-
-// Results - populated by the fillResults() function.
-var beacon = [];
-
-// "compatibility" between Python and JS for test quines
-var True = true;
-var False = false;
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/templates/output.html b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/templates/output.html
deleted file mode 100644
index 62d917d69..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/templates/output.html
+++ /dev/null
@@ -1,138 +0,0 @@
-<!-- Legend -->
-<TABLE CLASS="legend framed">
- <THEAD>
- <TR><TH COLSPAN=3 CLASS="legendHdr">Result Description</TH></TR>
- <TR><TH>Status</TH><TH ALIGN="LEFT">Meaning</TH><TH ALIGN="LEFT">Explanation</TH><TH>Scoring</TH></TR>
- </THEAD>
- <TBODY>
- <TR CLASS="lo"><TD CLASS="pass" ALIGN="CENTER">&nbsp;PASS&nbsp;</TD><TD CLASS="legend" ROWSPAN=2>Passed</TD><TD CLASS="legend" ROWSPAN=2>The result matches the expectation.</TD><TD ROWSPAN=2 ALIGN="CENTER" CLASS="pass">PASS (+1)</TD></TR>
- <TR CLASS="hi"><TD CLASS="pass" ALIGN="CENTER">&nbsp;PASS&nbsp;</TD></TR>
- <TR CLASS="lo"><TD CLASS="accept" ALIGN="CENTER">&nbsp;ACC.&nbsp;</TD><TD CLASS="legend" ROWSPAN=2>Acceptable</TD><TD CLASS="legend" ROWSPAN=2>The result is technically correct, but not ideal (too verbose, deprecated usage, etc.) - for informative purposes only.</TD><TD ROWSPAN=2 ALIGN="CENTER" CLASS="fail">FAIL (+0)</TD></TR>
- <TR CLASS="hi"><TD CLASS="accept" ALIGN="CENTER">&nbsp;ACC.&nbsp;</TD></TR>
- <TR CLASS="lo"><TD CLASS="fail" ALIGN="CENTER">&nbsp;FAIL&nbsp;</TD><TD CLASS="legend" ROWSPAN=2>Failure</TD><TD CLASS="legend" ROWSPAN=2>The result does not match any given expectation.</TD><TD ROWSPAN=2 ALIGN="CENTER" CLASS="fail">FAIL (+0)</TD></TR>
- <TR CLASS="hi"><TD CLASS="fail" ALIGN="CENTER">&nbsp;FAIL&nbsp;</TD></TR>
- <TR CLASS="lo"><TD CLASS="canary" ALIGN="CENTER">&nbsp;CANARY&nbsp;</TD><TD CLASS="legend" ROWSPAN=2>Canary</TD><TD CLASS="legend" ROWSPAN=2>The result changes HTML other than children of the contentEditable element.</TD><TD ROWSPAN=2 ALIGN="CENTER" CLASS="fail">FAIL (+0)</TD></TR>
- <TR CLASS="hi"><TD CLASS="canary" ALIGN="CENTER">&nbsp;CANARY&nbsp;</TD></TR>
- <TR CLASS="lo"><TD CLASS="unsupported" ALIGN="CENTER">&nbsp;UNS.&nbsp;</TD><TD CLASS="legend" ROWSPAN=2>Unsupported</TD><TD CLASS="legend" ROWSPAN=2>The specific function or value is unsupported (returned boolean 'false').</TD><TD ROWSPAN=2 ALIGN="CENTER" CLASS="fail">FAIL (+0)</TD></TR>
- <TR CLASS="hi"><TD CLASS="unsupported" ALIGN="CENTER">&nbsp;UNS.&nbsp;</TD></TR>
- <TR CLASS="lo"><TD CLASS="exception" ALIGN="CENTER">&nbsp;EXC.&nbsp;</TD><TD CLASS="legend" ROWSPAN=2>Exception</TD><TD CLASS="legend" ROWSPAN=2>An unexpected exception was thrown during the execution of the test.</TD><TD ROWSPAN=2 ALIGN="CENTER" CLASS="fail">FAIL (+0)</TD></TR>
- <TR CLASS="hi"><TD CLASS="exception" ALIGN="CENTER">&nbsp;EXC.&nbsp;</TD></TR>
- <TR CLASS="lo"><TD CLASS="na" ALIGN="CENTER">&nbsp;N/A&nbsp;</TD><TD CLASS="legend" ROWSPAN=2>Not Applicable</TD><TD CLASS="legend" ROWSPAN=2>The selection could not be tested, because the tested function failed to return a known result.</TD><TD ROWSPAN=2 ALIGN="CENTER" CLASS="fail">FAIL (+0)</TD></TR>
- <TR CLASS="hi"><TD CLASS="na" ALIGN="CENTER">&nbsp;N/A&nbsp;</TD></TR>
- </TBODY>
-</TABLE>
-<TABLE CLASS="legend framed">
- <THEAD>
- <TR><TH COLSPAN=2 CLASS="legendHdr">Selection and Result Display</TH></TR>
- <TR><TH>Character</TH><TH ALIGN="LEFT">Explanation</TH></TR>
- </THEAD>
- <TBODY>
- <TR><TD CLASS="sel" ALIGN="CENTER">[</TD><TD>Start of selection - selection point is within a text node.</TD></TR>
- <TR><TD CLASS="sel" ALIGN="CENTER">]</TD><TD>End of selection - selection point is within a text node.</TD></TR>
- <TR><TD CLASS="sel" ALIGN="CENTER">^</TD><TD>Collapsed selection - selection point is within a text node.</TD></TR>
- <TR><TD COLSPAN=2>&nbsp;</TD></TR>
- <TR><TD CLASS="sel" ALIGN="CENTER">{</TD><TD>Start of selection - selection point is within an element node.</TD></TR>
- <TR><TD CLASS="sel" ALIGN="CENTER">}</TD><TD>End of selection - selection point is within an element node.</TD></TR>
- <TR><TD CLASS="sel" ALIGN="CENTER">|</TD><TD>Collapsed selection - selection point is within an element node.</TD></TR>
- <TR><TD COLSPAN=2>&nbsp;</TD></TR>
- <TR><TD ALIGN="CENTER"><SPAN CLASS="fade">foo</SPAN></TD><TD>Greyed text indicates parts of the output that are ignored for the purposes of checking the result.</TD></TR>
- <TR><TD ALIGN="CENTER"><SPAN CLASS="txt">foo</SPAN></TD><TD>Grey border indicates extent of text nodes in the result.</TD></TR>
- </TBODY>
-</TABLE>
-<!-- progress meter -->
-<HR ID="divider">
-<H1>Running Test Suites: {% for s in suites %}<A HREF="#{{ s.id }}" ID="{{ s.id }}-progress" STYLE="color: #eeeeee">{{ s.id }}</A> {% endfor %}<SPAN ID="done">&nbsp;</SPAN></H1>
-<HR>
-<!-- main output -->
-{% for s in suites %}
- <H1 ID="{{ s.id }}"><A NAME="{{ s.id }}" HREF="#{{ s.id }}">{{ s.id }}</A> - {{ s.caption }}:
- <SPAN ID="{{ s.id }}-{% ifequal s.id.0 'S' %}sel{% endifequal %}score">?/?</SPAN>
- {% ifnotequal s.id.0 "Q" %}{% ifnotequal s.id.0 "S" %}
- (Selection: <SPAN ID="{{ s.id }}-selscore">?/?</SPAN>)
- {% endifnotequal %}{% endifnotequal %}
- (time: <SPAN ID="{{ s.id }}-time">?</SPAN>&nbsp;ms)
- </H1>
- {% if s.comment %}
- <DIV CLASS="comment">{{ s.comment|safe }}</DIV>
- {% endif %}
- {% for cls in classes %}{% for pk, pv in s.items %}{% ifequal pk cls %}
- <H2 ID="{{ s.id }}-{{ cls }}"><A NAME="{{ s.id }}-{{ cls }}" HREF="#{{ s.id }}-{{ cls }}">{{ cls }} Tests</A>:
- <SPAN ID="{{ s.id }}-{{ cls }}-{% ifequal s.id.0 'S' %}sel{% endifequal %}score">?/?</SPAN>
- {% ifnotequal s.id.0 "Q" %}{% ifnotequal s.id.0 "S" %}
- (Selection: <SPAN ID="{{ s.id }}-{{ cls }}-selscore">?/?</SPAN>)
- {% endifnotequal %}{% endifnotequal %}
- </H2>
- <TABLE WIDTH=100%>
- <THEAD>
- <TR>
- <TH TITLE="Unique ID of the test" ALIGN="LEFT">ID</TH>
- <TH TITLE="Command or function used in the test" ALIGN="LEFT">Command</TH>
- <TH TITLE="Value field for commands" ALIGN="LEFT">Value</TH>
- {% ifnotequal s.id.0 "S" %}{% ifnotequal s.id.0 "Q" %}{% comment %} Don't output attribute and style columns for selection and "queryCommand..." tests. {% endcomment %}
- <TH TITLE="check Atributes?">A</TH>
- <TH TITLE="check Style">S</TH>
- {% endifnotequal %}{% endifnotequal %}
- <TH TITLE="Testing HTML Element">Env.</TH>
- {% ifnotequal s.id.0 "S" %}{% comment %} Don't output HTML status column for selection tests. {% endcomment %}
- <TH TITLE="State of the test">Status</TH>
- {% endifnotequal %}
- {% ifnotequal s.id.0 "Q" %}{% comment %} Don't output selection result column for "queryCommand..." tests. {% endcomment %}
- <TH TITLE="State of the test regarding the selection">Selection</TH>
- {% endifnotequal %}
- <TH TITLE="Initial HTML and selection" ALIGN="LEFT">Initial</TH>
- <TH TITLE="Expected HTML and selection" ALIGN="LEFT">Expected</TH>
- <TH TITLE="Actual result HTML and selection" ALIGN="LEFT">Actual (lower case, canonicalized, selection marks)</TH>
- <TH TITLE="Short description of the test" ALIGN="LEFT">Description</TH>
- </TR>
- </THEAD>
- <TBODY>
- {% for g in pv %}{% for t in g.tests %}
- <TR ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:TR:dM" CLASS="{% cycle 'lo' 'lo' 'lo' 'hi' 'hi' 'hi' as shade %}">
- <TD ROWSPAN=3 ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:tid"><A CLASS="idLabel" NAME="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}" HREF="#{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}">{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}</A></TD>
- <TD ROWSPAN=3 ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:cmd">&nbsp;</TD>
- <TD ROWSPAN=3 ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:val">&nbsp;</TD>
- {% ifnotequal s.id.0 "S" %}{% ifnotequal s.id.0 "Q" %}{% comment %} Don't output attribute and style columns for selection and "queryCommand..." tests. {% endcomment %}
- <TD ROWSPAN=3 ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:att" ALIGN="CENTER">&nbsp;</TD>
- <TD ROWSPAN=3 ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:sty" ALIGN="CENTER">&nbsp;</TD>
- {% endifnotequal %}{% endifnotequal %}
- <TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:cnt:dM" TITLE="designMode=&quot;on&quot;" ALIGN="CENTER">dM</TD>
- {% ifnotequal s.id.0 "S" %}
- <TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:sta:dM" ALIGN="CENTER">NONE</TD>
- {% endifnotequal %}
- {% ifnotequal s.id.0 "Q" %}
- <TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:sel:dM" ALIGN="CENTER">NONE</TD>
- {% endifnotequal %}
- <TD ROWSPAN=3 ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:pad">&nbsp;</TD>
- <TD ROWSPAN=3 ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:exp">&nbsp;</TD>
- <TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:act:dM"><I>Processing...</I></TD>
- <TD ROWSPAN=3>{{ t.desc|default:"&nbsp;" }}</TD>
- </TR>
- <TR ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:TR:body" CLASS="{% cycle shade %}">
- <TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:cnt:body" TITLE="&lt;body contentEditable=&quot;true&quot;&gt;" ALIGN="CENTER">body</TD>
- {% ifnotequal s.id.0 "S" %}
- <TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:sta:body" ALIGN="CENTER">NONE</TD>
- {% endifnotequal %}
- {% ifnotequal s.id.0 "Q" %}
- <TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:sel:body" ALIGN="CENTER">NONE</TD>
- {% endifnotequal %}
- <TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:act:body"><I>Processing...</I></TD>
- </TR>
- <TR ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:TR:div" CLASS="{% cycle shade %}">
- <TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:cnt:div" TITLE="&lt;div contentEditable=&quot;true&quot;&gt;" ALIGN="CENTER">div</TD>
- {% ifnotequal s.id.0 "S" %}
- <TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:sta:div" ALIGN="CENTER">NONE</TD>
- {% endifnotequal %}
- {% ifnotequal s.id.0 "Q" %}
- <TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:sel:div" ALIGN="CENTER">NONE</TD>
- {% endifnotequal %}
- <TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:act:div"><I>Processing...</I></TD>
- </TR>
- {% endfor %}{% endfor %}
- </TBODY>
- </TABLE>
- {% endifequal %}{% endfor %}{% endfor %}
-{% endfor %}
-
-
-
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/templates/richtext2.html b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/templates/richtext2.html
deleted file mode 100644
index 98de8796d..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/templates/richtext2.html
+++ /dev/null
@@ -1,107 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
- <meta http-equiv="content-type" content="text/html; charset=utf-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
-
- <title>New Rich Text Tests</title>
-
- <link rel="stylesheet" href="static/common.css" type="text/css">
- <link rel="stylesheet" href="static/editable.css" type="text/css">
-
- <!-- utility scripts -->
- <script src="static/js/variables.js"></script>
-
- <script src="static/js/canonicalize.js"></script>
- <script src="static/js/compare.js"></script>
- <script src="static/js/output.js"></script>
- <script src="static/js/pad.js"></script>
- <script src="static/js/range.js"></script>
- <script src="static/js/units.js"></script>
-
- <script src="static/js/run.js"></script>
-
- <!-- new tests -->
- <script type="text/javascript">
- {% autoescape off %}
-
- var commonIDPrefix = '{{ commonIDPrefix }}';
- {% for s in suites %}
- var {{ s.id }}_TESTS = {{ s }};
- {% endfor %}
-
- /**
- * Stuff to do after all tests are run:
- * - write a nice "DONE!" at the end of the progress meter
- * - beacon the results
- * - remove the testing <iframe>s
- */
- function finish() {
- var span = document.getElementById('done');
- if (span)
- span.innerHTML = ' ... DONE!';
-
- fillResults();
- parent.sendScore(beacon, categoryTotals);
-
- cleanUp();
- }
-
- /**
- * Run every individual suite, with a a brief timeout in between
- * to allow for screen updates.
- */
-{% for s in suites %}
- {% if not forloop.first %}
- setTimeout("runSuite{{ s.id }}()", 100);
- }
- {% endif %}
-
- function runSuite{{ s.id }}() {
- runAndOutputTestSuite({{ s.id }}_TESTS);
-{% endfor %}
- finish();
- }
-
- /**
- * Runs all tests in all suites.
- */
- function doRunTests() {
- initVariables();
- initEditorDocs();
-
- // Start with the first test suite
- runSuite{{ suites.0.id }}();
- }
-
- /**
- * Runs after allowing for some time to have everything loaded
- * (aka. horrible IE9 kludge)
- */
- function runTests() {
- setTimeout("doRunTests()", 1500);
- }
-
- /**
- * Removes the <iframe>s after all tests are finished
- */
- function cleanUp() {
- var e = document.getElementById('iframe-dM');
- e.parentNode.removeChild(e);
- e = document.getElementById('iframe-body');
- e.parentNode.removeChild(e);
- e = document.getElementById('iframe-div');
- e.parentNode.removeChild(e);
- }
- {% endautoescape %}
- </script>
-</head>
-
-<body onload="runTests()">
- {% include "richtext2/templates/output.html" %}
- <hr>
- <iframe name="iframe-dM" id="iframe-dM" src="static/editable-dM.html"></iframe>
- <iframe name="iframe-body" id="iframe-body" src="static/editable-body.html"></iframe>
- <iframe name="iframe-div" id="iframe-div" src="static/editable-div.html"></iframe>
-</body>
-</html>
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/__init__.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/__init__.py
deleted file mode 100644
index a1f5279ad..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-__all__ = [
- 'apply',
- 'applyCSS',
- 'change',
- 'changeCSS',
- 'delete',
- 'forwarddelete',
- 'insert',
- 'queryEnabled',
- 'queryIndeterm',
- 'queryState',
- 'querySupported',
- 'queryValue',
- 'selection',
- 'unapply',
- 'unapplyCSS'
-] \ No newline at end of file
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/apply.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/apply.py
deleted file mode 100644
index 3eb465c84..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/apply.py
+++ /dev/null
@@ -1,364 +0,0 @@
-
-APPLY_TESTS = {
- 'id': 'A',
- 'caption': 'Apply Formatting Tests',
- 'checkAttrs': True,
- 'checkStyle': True,
- 'styleWithCSS': False,
-
- 'Proposed': [
- { 'desc': '',
- 'command': '',
- 'tests': [
- ]
- },
-
- { 'desc': '[HTML5] bold',
- 'command': 'bold',
- 'tests': [
- { 'id': 'B_TEXT-1_SI',
- 'rte1-id': 'a-bold-0',
- 'desc': 'Bold selection',
- 'pad': 'foo[bar]baz',
- 'expected': [ 'foo<b>[bar]</b>baz',
- 'foo<strong>[bar]</strong>baz' ] },
-
- { 'id': 'B_TEXT-1_SIR',
- 'desc': 'Bold reversed selection',
- 'pad': 'foo]bar[baz',
- 'expected': [ 'foo<b>[bar]</b>baz',
- 'foo<strong>[bar]</strong>baz' ] },
-
- { 'id': 'B_I-1_SL',
- 'desc': 'Bold selection, partially including italic',
- 'pad': 'foo[bar<i>baz]qoz</i>quz',
- 'expected': [ 'foo<b>[bar</b><i><b>baz]</b>qoz</i>quz',
- 'foo<b>[bar<i>baz]</i></b><i>qoz</i>quz',
- 'foo<strong>[bar</strong><i><strong>baz]</strong>qoz</i>quz',
- 'foo<strong>[bar<i>baz]</i></strong><i>qoz</i>quz' ] }
- ]
- },
-
- { 'desc': '[HTML5] italic',
- 'command': 'italic',
- 'tests': [
- { 'id': 'I_TEXT-1_SI',
- 'rte1-id': 'a-italic-0',
- 'desc': 'Italicize selection',
- 'pad': 'foo[bar]baz',
- 'expected': [ 'foo<i>[bar]</i>baz',
- 'foo<em>[bar]</em>baz' ] }
- ]
- },
-
- { 'desc': '[HTML5] underline',
- 'command': 'underline',
- 'tests': [
- { 'id': 'U_TEXT-1_SI',
- 'rte1-id': 'a-underline-0',
- 'desc': 'Underline selection',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<u>[bar]</u>baz' }
- ]
- },
-
- { 'desc': '[HTML5] strikethrough',
- 'command': 'strikethrough',
- 'tests': [
- { 'id': 'S_TEXT-1_SI',
- 'rte1-id': 'a-strikethrough-0',
- 'desc': 'Strike-through selection',
- 'pad': 'foo[bar]baz',
- 'expected': [ 'foo<s>[bar]</s>baz',
- 'foo<strike>[bar]</strike>baz',
- 'foo<del>[bar]</del>baz' ] }
- ]
- },
-
- { 'desc': '[HTML5] subscript',
- 'command': 'subscript',
- 'tests': [
- { 'id': 'SUB_TEXT-1_SI',
- 'rte1-id': 'a-subscript-0',
- 'desc': 'Change selection to subscript',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<sub>[bar]</sub>baz' }
- ]
- },
-
- { 'desc': '[HTML5] superscript',
- 'command': 'superscript',
- 'tests': [
- { 'id': 'SUP_TEXT-1_SI',
- 'rte1-id': 'a-superscript-0',
- 'desc': 'Change selection to superscript',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<sup>[bar]</sup>baz' }
- ]
- },
-
- { 'desc': '[HTML5] createlink',
- 'command': 'createlink',
- 'tests': [
- { 'id': 'CL:url_TEXT-1_SI',
- 'rte1-id': 'a-createlink-0',
- 'desc': 'create a link around the selection',
- 'value': '#foo',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<a href="#foo">[bar]</a>baz' }
- ]
- },
-
- { 'desc': '[HTML5] formatBlock',
- 'command': 'formatblock',
- 'tests': [
- { 'id': 'FB:H1_TEXT-1_SI',
- 'rte1-id': 'a-formatblock-0',
- 'desc': 'format the selection into a block: use <h1>',
- 'value': 'h1',
- 'pad': 'foo[bar]baz',
- 'expected': '<h1>foo[bar]baz</h1>' },
-
- { 'id': 'FB:P_TEXT-1_SI',
- 'desc': 'format the selection into a block: use <p>',
- 'value': 'p',
- 'pad': 'foo[bar]baz',
- 'expected': '<p>foo[bar]baz</p>' },
-
- { 'id': 'FB:PRE_TEXT-1_SI',
- 'desc': 'format the selection into a block: use <pre>',
- 'value': 'pre',
- 'pad': 'foo[bar]baz',
- 'expected': '<pre>foo[bar]baz</pre>' },
-
- { 'id': 'FB:ADDRESS_TEXT-1_SI',
- 'desc': 'format the selection into a block: use <address>',
- 'value': 'address',
- 'pad': 'foo[bar]baz',
- 'expected': '<address>foo[bar]baz</address>' },
-
- { 'id': 'FB:BQ_TEXT-1_SI',
- 'desc': 'format the selection into a block: use <blockquote>',
- 'value': 'blockquote',
- 'pad': 'foo[bar]baz',
- 'expected': '<blockquote>foo[bar]baz</blockquote>' },
-
- { 'id': 'FB:BQ_BR.BR-1_SM',
- 'desc': 'format a multi-line selection into a block: use <blockquote>',
- 'command': 'formatblock',
- 'value': 'blockquote',
- 'pad': 'fo[o<br>bar<br>b]az',
- 'expected': '<blockquote>fo[o<br>bar<br>b]az</blockquote>' }
- ]
- },
-
-
- { 'desc': '[MIDAS] backcolor',
- 'command': 'backcolor',
- 'tests': [
- { 'id': 'BC:blue_TEXT-1_SI',
- 'rte1-id': 'a-backcolor-0',
- 'desc': 'Change background color (note: no non-CSS variant available)',
- 'value': 'blue',
- 'pad': 'foo[bar]baz',
- 'expected': [ 'foo<span style="background-color: blue">[bar]</span>baz',
- 'foo<font style="background-color: blue">[bar]</font>baz' ] }
- ]
- },
-
- { 'desc': '[MIDAS] forecolor',
- 'command': 'forecolor',
- 'tests': [
- { 'id': 'FC:blue_TEXT-1_SI',
- 'rte1-id': 'a-forecolor-0',
- 'desc': 'Change the text color',
- 'value': 'blue',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<font color="blue">[bar]</font>baz' }
- ]
- },
-
- { 'desc': '[MIDAS] hilitecolor',
- 'command': 'hilitecolor',
- 'tests': [
- { 'id': 'HC:blue_TEXT-1_SI',
- 'rte1-id': 'a-hilitecolor-0',
- 'desc': 'Change the hilite color',
- 'value': 'blue',
- 'pad': 'foo[bar]baz',
- 'expected': [ 'foo<span style="background-color: blue">[bar]</span>baz',
- 'foo<font style="background-color: blue">[bar]</font>baz' ] }
- ]
- },
-
- { 'desc': '[MIDAS] fontname',
- 'command': 'fontname',
- 'tests': [
- { 'id': 'FN:a_TEXT-1_SI',
- 'rte1-id': 'a-fontname-0',
- 'desc': 'Change the font name',
- 'value': 'arial',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<font face="arial">[bar]</font>baz' }
- ]
- },
-
- { 'desc': '[MIDAS] fontsize',
- 'command': 'fontsize',
- 'tests': [
- { 'id': 'FS:2_TEXT-1_SI',
- 'rte1-id': 'a-fontsize-0',
- 'desc': 'Change the font size to "2"',
- 'value': '2',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<font size="2">[bar]</font>baz' },
-
- { 'id': 'FS:18px_TEXT-1_SI',
- 'desc': 'Change the font size to "18px"',
- 'value': '18px',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<font size="18px">[bar]</font>baz' },
-
- { 'id': 'FS:large_TEXT-1_SI',
- 'desc': 'Change the font size to "large"',
- 'value': 'large',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<font size="large">[bar]</font>baz' }
- ]
- },
-
- { 'desc': '[MIDAS] increasefontsize',
- 'command': 'increasefontsize',
- 'tests': [
- { 'id': 'INCFS:2_TEXT-1_SI',
- 'desc': 'Decrease the font size (to small)',
- 'pad': 'foo[bar]baz',
- 'expected': [ 'foo<font size="4">[bar]</font>baz',
- 'foo<font size="+1">[bar]</font>baz',
- 'foo<big>[bar]</big>baz' ] }
- ]
- },
-
- { 'desc': '[MIDAS] decreasefontsize',
- 'command': 'decreasefontsize',
- 'tests': [
- { 'id': 'DECFS:2_TEXT-1_SI',
- 'rte1-id': 'a-decreasefontsize-0',
- 'desc': 'Decrease the font size (to small)',
- 'pad': 'foo[bar]baz',
- 'expected': [ 'foo<font size="2">[bar]</font>baz',
- 'foo<font size="-1">[bar]</font>baz',
- 'foo<small>[bar]</small>baz' ] }
- ]
- },
-
- { 'desc': '[MIDAS] indent (note: accept the de-facto standard indent of 40px)',
- 'command': 'indent',
- 'tests': [
- { 'id': 'IND_TEXT-1_SI',
- 'rte1-id': 'a-indent-0',
- 'desc': 'Indent the text (accept the de-facto standard of 40px indent)',
- 'pad': 'foo[bar]baz',
- 'checkAttrs': False,
- 'expected': [ '<blockquote>foo[bar]baz</blockquote>',
- '<div style="margin-left: 40px">foo[bar]baz</div>' ],
- 'div': {
- 'accOuter': '<div contenteditable="true" style="margin-left: 40px">foo[bar]baz</div>' } }
- ]
- },
-
- { 'desc': '[MIDAS] outdent (-> unapply tests)',
- 'command': 'outdent',
- 'tests': [
- ]
- },
-
- { 'desc': '[MIDAS] justifycenter',
- 'command': 'justifycenter',
- 'tests': [
- { 'id': 'JC_TEXT-1_SC',
- 'rte1-id': 'a-justifycenter-0',
- 'desc': 'justify the text centrally',
- 'pad': 'foo^bar',
- 'expected': [ '<center>foo^bar</center>',
- '<p align="center">foo^bar</p>',
- '<p align="middle">foo^bar</p>',
- '<div align="center">foo^bar</div>',
- '<div align="middle">foo^bar</div>' ],
- 'div': {
- 'accOuter': [ '<div align="center" contenteditable="true">foo^bar</div>',
- '<div align="middle" contenteditable="true">foo^bar</div>' ] } }
- ]
- },
-
- { 'desc': '[MIDAS] justifyfull',
- 'command': 'justifyfull',
- 'tests': [
- { 'id': 'JF_TEXT-1_SC',
- 'rte1-id': 'a-justifyfull-0',
- 'desc': 'justify the text fully',
- 'pad': 'foo^bar',
- 'expected': [ '<p align="justify">foo^bar</p>',
- '<div align="justify">foo^bar</div>' ],
- 'div': {
- 'accOuter': '<div align="justify" contenteditable="true">foo^bar</div>' } }
- ]
- },
-
- { 'desc': '[MIDAS] justifyleft',
- 'command': 'justifyleft',
- 'tests': [
- { 'id': 'JL_TEXT-1_SC',
- 'rte1-id': 'a-justifyleft-0',
- 'desc': 'justify the text left',
- 'pad': 'foo^bar',
- 'expected': [ '<p align="left">foo^bar</p>',
- '<div align="left">foo^bar</div>' ],
- 'div': {
- 'accOuter': '<div align="left" contenteditable="true">foo^bar</div>' } }
- ]
- },
-
- { 'desc': '[MIDAS] justifyright',
- 'command': 'justifyright',
- 'tests': [
- { 'id': 'JR_TEXT-1_SC',
- 'rte1-id': 'a-justifyright-0',
- 'desc': 'justify the text right',
- 'pad': 'foo^bar',
- 'expected': [ '<p align="right">foo^bar</p>',
- '<div align="right">foo^bar</div>' ],
- 'div': {
- 'accOuter': '<div align="right" contenteditable="true">foo^bar</div>' } }
- ]
- },
-
- { 'desc': '[MIDAS] heading',
- 'command': 'heading',
- 'tests': [
- { 'id': 'H:H1_TEXT-1_SC',
- 'desc': 'create a heading from the paragraph that contains the selection',
- 'value': 'h1',
- 'pad': 'foo[bar]baz',
- 'expected': '<h1>foo[bar]baz</h1>' }
- ]
- },
-
-
- { 'desc': '[Other] createbookmark',
- 'command': 'createbookmark',
- 'tests': [
- { 'id': 'CB:name_TEXT-1_SI',
- 'rte1-id': 'a-createbookmark-0',
- 'desc': 'create a bookmark (named link) around selection',
- 'value': 'created',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<a name="created">[bar]</a>baz' }
- ]
- }
- ]
-}
-
-
-
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/applyCSS.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/applyCSS.py
deleted file mode 100644
index 94cdad83f..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/applyCSS.py
+++ /dev/null
@@ -1,244 +0,0 @@
-
-APPLY_TESTS_CSS = {
- 'id': 'AC',
- 'caption': 'Apply Formatting Tests, using styleWithCSS',
- 'checkAttrs': True,
- 'checkStyle': True,
- 'styleWithCSS': True,
-
- 'Proposed': [
- { 'desc': '',
- 'command': '',
- 'tests': [
- ]
- },
-
- { 'desc': '[HTML5] bold',
- 'command': 'bold',
- 'tests': [
- { 'id': 'B_TEXT-1_SI',
- 'rte1-id': 'a-bold-1',
- 'desc': 'Bold selection',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<span style="font-weight: bold">[bar]</span>baz' }
- ]
- },
-
- { 'desc': '[HTML5] italic',
- 'command': 'italic',
- 'tests': [
- { 'id': 'I_TEXT-1_SI',
- 'rte1-id': 'a-italic-1',
- 'desc': 'Italicize selection',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<span style="font-style: italic">[bar]</span>baz' }
- ]
- },
-
- { 'desc': '[HTML5] underline',
- 'command': 'underline',
- 'tests': [
- { 'id': 'U_TEXT-1_SI',
- 'rte1-id': 'a-underline-1',
- 'desc': 'Underline selection',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<span style="text-decoration: underline">[bar]</span>baz' }
- ]
- },
-
- { 'desc': '[HTML5] strikethrough',
- 'command': 'strikethrough',
- 'tests': [
- { 'id': 'S_TEXT-1_SI',
- 'rte1-id': 'a-strikethrough-1',
- 'desc': 'Strike-through selection',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<span style="text-decoration: line-through">[bar]</span>baz' }
- ]
- },
-
- { 'desc': '[HTML5] subscript',
- 'command': 'subscript',
- 'tests': [
- { 'id': 'SUB_TEXT-1_SI',
- 'rte1-id': 'a-subscript-1',
- 'desc': 'Change selection to subscript',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<span style="vertical-align: sub">[bar]</span>baz' }
- ]
- },
-
- { 'desc': '[HTML5] superscript',
- 'command': 'superscript',
- 'tests': [
- { 'id': 'SUP_TEXT-1_SI',
- 'rte1-id': 'a-superscript-1',
- 'desc': 'Change selection to superscript',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<span style="vertical-align: super">[bar]</span>baz' }
- ]
- },
-
-
- { 'desc': '[MIDAS] backcolor',
- 'command': 'backcolor',
- 'tests': [
- { 'id': 'BC:blue_TEXT-1_SI',
- 'rte1-id': 'a-backcolor-1',
- 'desc': 'Change background color',
- 'value': 'blue',
- 'pad': 'foo[bar]baz',
- 'expected': [ 'foo<span style="background-color: blue">[bar]</span>baz',
- 'foo<font style="background-color: blue">[bar]</font>baz' ] }
- ]
- },
-
- { 'desc': '[MIDAS] forecolor',
- 'command': 'forecolor',
- 'tests': [
- { 'id': 'FC:blue_TEXT-1_SI',
- 'rte1-id': 'a-forecolor-1',
- 'desc': 'Change the text color',
- 'value': 'blue',
- 'pad': 'foo[bar]baz',
- 'expected': [ 'foo<span style="color: blue">[bar]</span>baz',
- 'foo<font style="color: blue">[bar]</font>baz' ] }
- ]
- },
-
- { 'desc': '[MIDAS] hilitecolor',
- 'command': 'hilitecolor',
- 'tests': [
- { 'id': 'HC:blue_TEXT-1_SI',
- 'rte1-id': 'a-hilitecolor-1',
- 'desc': 'Change the hilite color',
- 'value': 'blue',
- 'pad': 'foo[bar]baz',
- 'expected': [ 'foo<span style="background-color: blue">[bar]</span>baz',
- 'foo<font style="background-color: blue">[bar]</font>baz' ] }
- ]
- },
-
- { 'desc': '[MIDAS] fontname',
- 'command': 'fontname',
- 'tests': [
- { 'id': 'FN:a_TEXT-1_SI',
- 'rte1-id': 'a-fontname-1',
- 'desc': 'Change the font name',
- 'value': 'arial',
- 'pad': 'foo[bar]baz',
- 'expected': [ 'foo<span style="font-family: arial">[bar]</span>baz',
- 'foo<font style="font-family: blue">[bar]</font>baz' ] }
- ]
- },
-
- { 'desc': '[MIDAS] fontsize',
- 'command': 'fontsize',
- 'tests': [
- { 'id': 'FS:2_TEXT-1_SI',
- 'rte1-id': 'a-fontsize-1',
- 'desc': 'Change the font size to "2"',
- 'value': '2',
- 'pad': 'foo[bar]baz',
- 'expected': [ 'foo<span style="font-size: small">[bar]</span>baz',
- 'foo<font style="font-size: small">[bar]</font>baz' ] },
-
- { 'id': 'FS:18px_TEXT-1_SI',
- 'desc': 'Change the font size to "18px"',
- 'value': '18px',
- 'pad': 'foo[bar]baz',
- 'expected': [ 'foo<span style="font-size: 18px">[bar]</span>baz',
- 'foo<font style="font-size: 18px">[bar]</font>baz' ] },
-
- { 'id': 'FS:large_TEXT-1_SI',
- 'desc': 'Change the font size to "large"',
- 'value': 'large',
- 'pad': 'foo[bar]baz',
- 'expected': [ 'foo<span style="font-size: large">[bar]</span>baz',
- 'foo<font style="font-size: large">[bar]</font>baz' ] }
- ]
- },
-
- { 'desc': '[MIDAS] indent',
- 'command': 'indent',
- 'tests': [
- { 'id': 'IND_TEXT-1_SI',
- 'rte1-id': 'a-indent-1',
- 'desc': 'Indent the text (assume "standard" 40px)',
- 'pad': 'foo[bar]baz',
- 'expected': [ '<div style="margin-left: 40px">foo[bar]baz</div>',
- '<div style="margin: 0 0 0 40px">foo[bar]baz</div>',
- '<blockquote style="margin-left: 40px">foo[bar]baz</blockquote>',
- '<blockquote style="margin: 0 0 0 40px">foo[bar]baz</blockquote>' ],
- 'div': {
- 'accOuter': [ '<div contenteditable="true" style="margin-left: 40px">foo[bar]baz</div>',
- '<div contenteditable="true" style="margin: 0 0 0 40px">foo[bar]baz</div>' ] } }
- ]
- },
-
- { 'desc': '[MIDAS] outdent (-> unapply tests)',
- 'command': 'outdent',
- 'tests': [
- ]
- },
-
- { 'desc': '[MIDAS] justifycenter',
- 'command': 'justifycenter',
- 'tests': [
- { 'id': 'JC_TEXT-1_SC',
- 'rte1-id': 'a-justifycenter-1',
- 'desc': 'justify the text centrally',
- 'pad': 'foo^bar',
- 'expected': [ '<p style="text-align: center">foo^bar</p>',
- '<div style="text-align: center">foo^bar</div>' ],
- 'div': {
- 'accOuter': '<div contenteditable="true" style="text-align: center">foo^bar</div>' } }
- ]
- },
-
- { 'desc': '[MIDAS] justifyfull',
- 'command': 'justifyfull',
- 'tests': [
- { 'id': 'JF_TEXT-1_SC',
- 'rte1-id': 'a-justifyfull-1',
- 'desc': 'justify the text fully',
- 'pad': 'foo^bar',
- 'expected': [ '<p style="text-align: justify">foo^bar</p>',
- '<div style="text-align: justify">foo^bar</div>' ],
- 'div': {
- 'accOuter': '<div contenteditable="true" style="text-align: justify">foo^bar</div>' } }
- ]
- },
-
- { 'desc': '[MIDAS] justifyleft',
- 'command': 'justifyleft',
- 'tests': [
- { 'id': 'JL_TEXT-1_SC',
- 'rte1-id': 'a-justifyleft-1',
- 'desc': 'justify the text left',
- 'pad': 'foo^bar',
- 'expected': [ '<p style="text-align: left">foo^bar</p>',
- '<div style="text-align: left">foo^bar</div>' ],
- 'div': {
- 'accOuter': '<div contenteditable="true" style="text-align: left">foo^bar</div>' } }
- ]
- },
-
- { 'desc': '[MIDAS] justifyright',
- 'command': 'justifyright',
- 'tests': [
- { 'id': 'JR_TEXT-1_SC',
- 'rte1-id': 'a-justifyright-1',
- 'desc': 'justify the text right',
- 'pad': 'foo^bar',
- 'expected': [ '<p style="text-align: right">foo^bar</p>',
- '<div style="text-align: right">foo^bar</div>' ],
- 'div': {
- 'accOuter': '<div contenteditable="true" style="text-align: right">foo^bar</div>' } }
- ]
- }
- ]
-}
-
-
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/change.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/change.py
deleted file mode 100644
index 6a76d3d5f..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/change.py
+++ /dev/null
@@ -1,273 +0,0 @@
-
-CHANGE_TESTS = {
- 'id': 'C',
- 'caption': 'Change Existing Format to Different Format Tests',
- 'checkAttrs': True,
- 'checkStyle': True,
- 'styleWithCSS': False,
-
- 'Proposed': [
- { 'desc': '',
- 'command': '',
- 'tests': [
- ]
- },
-
- { 'desc': '[HTML5] italic',
- 'command': 'italic',
- 'tests': [
- { 'id': 'I_I-1_SL',
- 'desc': 'Italicize partially italicized text',
- 'pad': 'foo[bar<i>baz]</i>qoz',
- 'expected': 'foo<i>[barbaz]</i>qoz' },
-
- { 'id': 'I_B-I-1_SO',
- 'desc': 'Italicize partially italicized text in bold context',
- 'pad': '<b>foo[bar<i>baz</i>}</b>',
- 'expected': '<b>foo<i>[barbaz]</i></b>' }
- ]
- },
-
- { 'desc': '[HTML5] underline',
- 'command': 'underline',
- 'tests': [
- { 'id': 'U_U-1_SO',
- 'desc': 'Underline partially underlined text',
- 'pad': 'foo[bar<u>baz</u>qoz]quz',
- 'expected': 'foo<u>[barbazqoz]</u>quz' },
-
- { 'id': 'U_U-1_SL',
- 'desc': 'Underline partially underlined text',
- 'pad': 'foo[bar<u>baz]qoz</u>quz',
- 'expected': 'foo<u>[barbaz]qoz</u>quz' },
-
- { 'id': 'U_S-U-1_SO',
- 'desc': 'Underline partially underlined text in striked context',
- 'pad': '<s>foo[bar<u>baz</u>}</s>',
- 'expected': '<s>foo<u>[barbaz]</u></s>' }
- ]
- },
-
-
- { 'desc': '[MIDAS] backcolor',
- 'command': 'backcolor',
- 'tests': [
- { 'id': 'BC:842_FONTs:bc:fca-1_SW',
- 'rte1-id': 'c-backcolor-0',
- 'desc': 'Change background color to new color',
- 'value': '#884422',
- 'pad': '<font style="background-color: #ffccaa">[foobarbaz]</font>',
- 'expected': [ '<font style="background-color: #884422">[foobarbaz]</font>',
- '<span style="background-color: #884422">[foobarbaz]</span>' ] },
-
- { 'id': 'BC:00f_SPANs:bc:f00-1_SW',
- 'rte1-id': 'c-backcolor-2',
- 'desc': 'Change background color to new color',
- 'value': '#0000ff',
- 'pad': '<span style="background-color: #ff0000">[foobarbaz]</span>',
- 'expected': [ '<font style="background-color: #0000ff">[foobarbaz]</font>',
- '<span style="background-color: #0000ff">[foobarbaz]</span>' ] },
-
- { 'id': 'BC:ace_FONT.ass.s:bc:rgb-1_SW',
- 'rte1-id': 'c-backcolor-1',
- 'desc': 'Change background color in styled span to new color',
- 'value': '#aaccee',
- 'pad': '<span class="Apple-style-span" style="background-color: rgb(255, 0, 0)">[foobarbaz]</span>',
- 'expected': [ '<font style="background-color: #aaccee">[foobarbaz]</font>',
- '<span style="background-color: #aaccee">[foobarbaz]</span>' ] }
- ]
- },
-
- { 'desc': '[MIDAS] forecolor',
- 'command': 'forecolor',
- 'tests': [
- { 'id': 'FC:g_FONTc:b-1_SW',
- 'rte1-id': 'c-forecolor-0',
- 'desc': 'Change the text color (without CSS)',
- 'value': 'green',
- 'pad': '<font color="blue">[foobarbaz]</font>',
- 'expected': '<font color="green">[foobarbaz]</font>' },
-
- { 'id': 'FC:g_SPANs:c:g-1_SW',
- 'rte1-id': 'c-forecolor-1',
- 'desc': 'Change the text color from a styled span (without CSS)',
- 'value': 'green',
- 'pad': '<span style="color: blue">[foobarbaz]</span>',
- 'expected': '<font color="green">[foobarbaz]</font>' },
-
- { 'id': 'FC:g_FONTc:b.s:c:r-1_SW',
- 'rte1-id': 'c-forecolor-2',
- 'desc': 'Change the text color from conflicting color and style (without CSS)',
- 'value': 'green',
- 'pad': '<font color="blue" style="color: red">[foobarbaz]</font>',
- 'expected': '<font color="green">[foobarbaz]</font>' },
-
- { 'id': 'FC:g_FONTc:b.sz:6-1_SI',
- 'desc': 'Change the font color in content with a different font size and font color',
- 'value': 'green',
- 'pad': '<font color="blue" size="6">foo[bar]baz</font>',
- 'expected': [ '<font color="blue" size="6">foo<font color="green">[bar]</font>baz</font>',
- '<font size="6"><font color="blue">foo<font color="green">[bar]</font><font color="blue">baz</font></font>' ] }
- ]
- },
-
- { 'desc': '[MIDAS] hilitecolor',
- 'command': 'hilitecolor',
- 'tests': [
- { 'id': 'HC:g_FONTs:c:b-1_SW',
- 'rte1-id': 'c-hilitecolor-0',
- 'desc': 'Change the hilite color (without CSS)',
- 'value': 'green',
- 'pad': '<font style="background-color: blue">[foobarbaz]</font>',
- 'expected': [ '<font style="background-color: green">[foobarbaz]</font>',
- '<span style="background-color: green">[foobarbaz]</span>' ] },
-
- { 'id': 'HC:g_SPANs:c:g-1_SW',
- 'rte1-id': 'c-hilitecolor-2',
- 'desc': 'Change the hilite color from a styled span (without CSS)',
- 'value': 'green',
- 'pad': '<span style="background-color: blue">[foobarbaz]</span>',
- 'expected': '<span style="background-color: green">[foobarbaz]</span>' },
-
- { 'id': 'HC:g_SPAN.ass.s:c:rgb-1_SW',
- 'rte1-id': 'c-hilitecolor-1',
- 'desc': 'Change the hilite color from a styled span (without CSS)',
- 'value': 'green',
- 'pad': '<span class="Apple-style-span" style="background-color: rgb(255, 0, 0);">[foobarbaz]</span>',
- 'expected': '<span style="background-color: green">[foobarbaz]</span>' }
- ]
- },
-
- { 'desc': '[MIDAS] fontname',
- 'command': 'fontname',
- 'tests': [
- { 'id': 'FN:c_FONTf:a-1_SW',
- 'rte1-id': 'c-fontname-0',
- 'desc': 'Change existing font name to new font name (without CSS)',
- 'value': 'courier',
- 'pad': '<font face="arial">[foobarbaz]</font>',
- 'expected': '<font face="courier">[foobarbaz]</font>' },
-
- { 'id': 'FN:c_SPANs:ff:a-1_SW',
- 'rte1-id': 'c-fontname-1',
- 'desc': 'Change existing font name from style to new font name (without CSS)',
- 'value': 'courier',
- 'pad': '<span style="font-family: arial">[foobarbaz]</span>',
- 'expected': '<font face="courier">[foobarbaz]</font>' },
-
- { 'id': 'FN:c_FONTf:a.s:ff:v-1_SW',
- 'rte1-id': 'c-fontname-2',
- 'desc': 'Change existing font name with conflicting face and style to new font name (without CSS)',
- 'value': 'courier',
- 'pad': '<font face="arial" style="font-family: verdana">[foobarbaz]</font>',
- 'expected': '<font face="courier">[foobarbaz]</font>' },
-
- { 'id': 'FN:c_FONTf:a-1_SI',
- 'desc': 'Change existing font name to new font name, text partially selected',
- 'value': 'courier',
- 'pad': '<font face="arial">foo[bar]baz</font>',
- 'expected': '<font face="arial">foo</font><font face="courier">[bar]</font><font face="arial">baz</font>',
- 'accept': '<font face="arial">foo<font face="courier">[bar]</font>baz</font>' },
-
- { 'id': 'FN:c_FONTf:a-2_SL',
- 'desc': 'Change existing font name to new font name, using CSS styling',
- 'value': 'courier',
- 'pad': 'foo[bar<font face="arial">baz]qoz</font>',
- 'expected': 'foo<font face="courier">[barbaz]</font><font face="arial">qoz</font>' },
-
- { 'id': 'FN:c_FONTf:v-FONTf:a-1_SW',
- 'rte1-id': 'c-fontname-3',
- 'desc': 'Change existing font name in nested <font> tags to new font name (without CSS)',
- 'value': 'courier',
- 'pad': '<font face="verdana"><font face="arial">[foobarbaz]</font></font>',
- 'expected': '<font face="courier">[foobarbaz]</font>',
- 'accept': '<font face="verdana"><font face="courier">[foobarbaz]</font></font>' },
-
- { 'id': 'FN:c_SPANs:ff:v-FONTf:a-1_SW',
- 'rte1-id': 'c-fontname-4',
- 'desc': 'Change existing font name in nested mixed tags to new font name (without CSS)',
- 'value': 'courier',
- 'pad': '<span style="font-family: verdana"><font face="arial">[foobarbaz]</font></span>',
- 'expected': '<font face="courier">[foobarbaz]</font>',
- 'accept': '<span style="font-family: verdana"><font face="courier">[foobarbaz]</font></span>' }
- ]
- },
-
- { 'desc': '[MIDAS] fontsize',
- 'command': 'fontsize',
- 'tests': [
- { 'id': 'FS:1_FONTsz:4-1_SW',
- 'rte1-id': 'c-fontsize-0',
- 'desc': 'Change existing font size to new size (without CSS)',
- 'value': '1',
- 'pad': '<font size="4">[foobarbaz]</font>',
- 'expected': '<font size="1">[foobarbaz]</font>' },
-
- { 'id': 'FS:1_SPAN.ass.s:fs:large-1_SW',
- 'rte1-id': 'c-fontsize-1',
- 'desc': 'Change existing font size from styled span to new size (without CSS)',
- 'value': '1',
- 'pad': '<span class="Apple-style-span" style="font-size: large">[foobarbaz]</span>',
- 'expected': '<font size="1">[foobarbaz]</font>' },
-
- { 'id': 'FS:5_FONTsz:1.s:fs:xs-1_SW',
- 'rte1-id': 'c-fontsize-2',
- 'desc': 'Change existing font size from tag with conflicting size and style to new size (without CSS)',
- 'value': '5',
- 'pad': '<font size="1" style="font-size:x-small">[foobarbaz]</font>',
- 'expected': '<font size="5">[foobarbaz]</font>' },
-
- { 'id': 'FS:2_FONTc:b.sz:6-1_SI',
- 'desc': 'Change the font size in content with a different font size and font color',
- 'value': '2',
- 'pad': '<font color="blue" size="6">foo[bar]baz</font>',
- 'expected': [ '<font color="blue" size="6">foo<font size="2">[bar]</font>baz</font>',
- '<font color="blue"><font size="6">foo</font><font size="2">[bar]</font><font size="6">baz</font></font>' ] },
-
- { 'id': 'FS:larger_FONTsz:4',
- 'desc': 'Change selection to use next larger font',
- 'value': 'larger',
- 'pad': '<font size="4">foo[bar]baz</font>',
- 'expected': '<font size="4">foo<font size="larger">[bar]</font>baz</font>',
- 'accept': '<font size="4">foo</font><font size="5">[bar]</font><font size="4">baz</font>' },
-
- { 'id': 'FS:smaller_FONTsz:4',
- 'desc': 'Change selection to use next smaller font',
- 'value': 'smaller',
- 'pad': '<font size="4">foo[bar]baz</font>',
- 'expected': '<font size="4">foo<font size="smaller">[bar]</font>baz</font>',
- 'accept': '<font size="4">foo</font><font size="3">[bar]</font><font size="4">baz</font>' }
- ]
- },
-
- { 'desc': '[MIDAS] formatblock',
- 'command': 'formatblock',
- 'tests': [
- { 'id': 'FB:h1_ADDRESS-1_SW',
- 'desc': 'change block from <address> to <h1>',
- 'value': 'h1',
- 'pad': '<address>foo [bar] baz</address>',
- 'expected': '<h1>foo [bar] baz</h1>' },
-
- { 'id': 'FB:h1_ADDRESS-FONTsz:4-1_SO',
- 'desc': 'change block from <address> with partially formatted content to <h1>',
- 'value': 'h1',
- 'pad': '<address>foo [<font size="4">bar</font>] baz</address>',
- 'expected': '<h1>foo [bar] baz</h1>' },
-
- { 'id': 'FB:h1_ADDRESS-FONTsz:4-1_SW',
- 'desc': 'change block from <address> with partially formatted content to <h1>',
- 'value': 'h1',
- 'pad': '<address>foo <font size="4">[bar]</font> baz</address>',
- 'expected': '<h1>foo [bar] baz</h1>' },
-
- { 'id': 'FB:h1_ADDRESS-FONT.ass.sz:4-1_SW',
- 'desc': 'change block from <address> with partially formatted content to <h1>',
- 'value': 'h1',
- 'pad': '<address>foo <font class="Apple-style-span" size="4">[bar]</font> baz</address>',
- 'expected': '<h1>foo [bar] baz</h1>' }
- ]
- }
- ]
-}
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/changeCSS.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/changeCSS.py
deleted file mode 100644
index 4862b9b73..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/changeCSS.py
+++ /dev/null
@@ -1,210 +0,0 @@
-
-CHANGE_TESTS_CSS = {
- 'id': 'CC',
- 'caption': 'Change Existing Format to Different Format Tests, using styleWithCSS',
- 'checkAttrs': True,
- 'checkStyle': True,
- 'styleWithCSS': True,
-
- 'Proposed': [
- { 'desc': '',
- 'command': '',
- 'tests': [
- ]
- },
-
- { 'desc': '[HTML5] italic',
- 'command': 'italic',
- 'tests': [
- { 'id': 'I_I-1_SL',
- 'desc': 'Italicize partially italicized text',
- 'pad': 'foo[bar<i>baz]</i>qoz',
- 'expected': 'foo<span style="font-style: italic">[barbaz]</span>qoz' },
-
- { 'id': 'I_B-1_SL',
- 'desc': 'Italicize partially bolded text',
- 'pad': 'foo[bar<b>baz]</b>qoz',
- 'expected': 'foo<span style="font-style: italic">[bar<b>baz]</b></span>qoz',
- 'accept': 'foo<span style="font-style: italic">[bar<b>baz</b>}</span>qoz' },
-
- { 'id': 'I_B-1_SW',
- 'desc': 'Italicize bold text, ideally combining both',
- 'pad': 'foobar<b>[baz]</b>qoz',
- 'expected': 'foobar<span style="font-style: italic; font-weight: bold">[baz]</span>qoz',
- 'accept': 'foobar<b><span style="font-style: italic">[baz]</span></b>qoz' }
- ]
- },
-
- { 'desc': '[MIDAS] backcolor',
- 'command': 'backcolor',
- 'tests': [
- { 'id': 'BC:gray_SPANs:bc:b-1_SW',
- 'desc': 'Change background color from blue to gray',
- 'value': 'gray',
- 'pad': '<span style="background-color: blue">[foobarbaz]</span>',
- 'expected': '<span style="background-color: gray">[foobarbaz]</span>' },
-
- { 'id': 'BC:gray_SPANs:bc:b-1_SO',
- 'desc': 'Change background color from blue to gray',
- 'value': 'gray',
- 'pad': '{<span style="background-color: blue">foobarbaz</span>}',
- 'expected': [ '{<span style="background-color: gray">foobarbaz</span>}',
- '<span style="background-color: gray">[foobarbaz]</span>' ] },
-
- { 'id': 'BC:gray_SPANs:bc:b-1_SI',
- 'desc': 'Change background color from blue to gray',
- 'value': 'gray',
- 'pad': '<span style="background-color: blue">foo[bar]baz</span>',
- 'expected': '<span style="background-color: blue">foo</span><span style="background-color: gray">[bar]</span><span style="background-color: blue">baz</span>',
- 'accept': '<span style="background-color: blue">foo<span style="background-color: gray">[bar]</span>baz</span>' },
-
- { 'id': 'BC:gray_P-SPANs:bc:b-1_SW',
- 'desc': 'Change background color within a paragraph from blue to gray',
- 'value': 'gray',
- 'pad': '<p><span style="background-color: blue">[foobarbaz]</span></p>',
- 'expected': [ '<p><span style="background-color: gray">[foobarbaz]</span></p>',
- '<p style="background-color: gray">[foobarbaz]</p>' ] },
-
- { 'id': 'BC:gray_P-SPANs:bc:b-2_SW',
- 'desc': 'Change background color within a paragraph from blue to gray',
- 'value': 'gray',
- 'pad': '<p>foo<span style="background-color: blue">[bar]</span>baz</p>',
- 'expected': '<p>foo<span style="background-color: gray">[bar]</span>baz</p>' },
-
- { 'id': 'BC:gray_P-SPANs:bc:b-3_SO',
- 'desc': 'Change background color within a paragraph from blue to gray (selection encloses more than previous span)',
- 'value': 'gray',
- 'pad': '<p>[foo<span style="background-color: blue">barbaz</span>qoz]quz</p>',
- 'expected': '<p><span style="background-color: gray">[foobarbazqoz]</span>quz</p>' },
-
- { 'id': 'BC:gray_P-SPANs:bc:b-3_SL',
- 'desc': 'Change background color within a paragraph from blue to gray (previous span partially selected)',
- 'value': 'gray',
- 'pad': '<p>[foo<span style="background-color: blue">bar]baz</span>qozquz</p>',
- 'expected': '<p><span style="background-color: gray">[foobar]</span><span style="background-color: blue">baz</span>qozquz</p>' },
-
- { 'id': 'BC:gray_SPANs:bc:b-2_SL',
- 'desc': 'Change background color from blue to gray on partially covered span, selection extends left',
- 'value': 'gray',
- 'pad': 'foo [bar <span style="background-color: blue">baz] qoz</span> quz sic',
- 'expected': 'foo <span style="background-color: gray">[bar baz]</span><span style="background-color: blue"> qoz</span> quz sic' },
-
- { 'id': 'BC:gray_SPANs:bc:b-2_SR',
- 'desc': 'Change background color from blue to gray on partially covered span, selection extends right',
- 'value': 'gray',
- 'pad': 'foo bar <span style="background-color: blue">baz [qoz</span> quz] sic',
- 'expected': 'foo bar <span style="background-color: blue">baz </span><span style="background-color: gray">[qoz quz]</span> sic' }
- ]
- },
-
- { 'desc': '[MIDAS] fontname',
- 'command': 'fontname',
- 'tests': [
- { 'id': 'FN:c_SPANs:ff:a-1_SW',
- 'desc': 'Change existing font name to new font name, using CSS styling',
- 'value': 'courier',
- 'pad': '<span style="font-family: arial">[foobarbaz]</span>',
- 'expected': '<span style="font-family: courier">[foobarbaz]</span>' },
-
- { 'id': 'FN:c_FONTf:a-1_SW',
- 'desc': 'Change existing font name to new font name, using CSS styling',
- 'value': 'courier',
- 'pad': '<font face="arial">[foobarbaz]</font>',
- 'expected': [ '<font style="font-family: courier">[foobarbaz]</font>',
- '<span style="font-family: courier">[foobarbaz]</span>' ] },
-
- { 'id': 'FN:c_FONTf:a-1_SI',
- 'desc': 'Change existing font name to new font name, using CSS styling',
- 'value': 'courier',
- 'pad': '<font face="arial">foo[bar]baz</font>',
- 'expected': '<font face="arial">foo</font><span style="font-family: courier">[bar]</span><font face="arial">baz</font>' },
-
- { 'id': 'FN:a_FONTf:a-1_SI',
- 'desc': 'Change existing font name to same font name, using CSS styling (should be noop)',
- 'value': 'arial',
- 'pad': '<font face="arial">foo[bar]baz</font>',
- 'expected': '<font face="arial">foo[bar]baz</font>' },
-
- { 'id': 'FN:a_FONTf:a-1_SW',
- 'desc': 'Change existing font name to same font name, using CSS styling (should be noop or perhaps change tag)',
- 'value': 'arial',
- 'pad': '<font face="arial">[foobarbaz]</font>',
- 'expected': [ '<font face="arial">[foobarbaz]</font>',
- '<span style="font-family: arial">[foobarbaz]</span>' ] },
-
- { 'id': 'FN:a_FONTf:a-1_SO',
- 'desc': 'Change existing font name to same font name, using CSS styling (should be noop or perhaps change tag)',
- 'value': 'arial',
- 'pad': '{<font face="arial">foobarbaz</font>}',
- 'expected': [ '{<font face="arial">foobarbaz</font>}',
- '<font face="arial">[foobarbaz]</font>',
- '{<span style="font-family: arial">foobarbaz</span>}',
- '<span style="font-family: arial">[foobarbaz]</span>' ] },
-
- { 'id': 'FN:a_SPANs:ff:a-1_SI',
- 'desc': 'Change existing font name to same font name, using CSS styling (should be noop)',
- 'value': 'arial',
- 'pad': '<span style="font-family: arial">[foobarbaz]</span>',
- 'expected': '<span style="font-family: arial">[foobarbaz]</span>' },
-
- { 'id': 'FN:c_FONTf:a-2_SL',
- 'desc': 'Change existing font name to new font name, using CSS styling',
- 'value': 'courier',
- 'pad': 'foo[bar<font face="arial">baz]qoz</font>',
- 'expected': 'foo<span style="font-family: courier">[barbaz]</span><font face="arial">qoz</font>' }
- ]
- },
-
- { 'desc': '[MIDAS] fontsize',
- 'command': 'fontsize',
- 'tests': [
- { 'id': 'FS:1_SPANs:fs:l-1_SW',
- 'desc': 'Change existing font size to new size, using CSS styling',
- 'value': '1',
- 'pad': '<span style="font-size: large">[foobarbaz]</span>',
- 'expected': '<span style="font-size: x-small">[foobarbaz]</span>' },
-
- { 'id': 'FS:large_SPANs:fs:l-1_SW',
- 'desc': 'Change existing font size to same size (should be noop)',
- 'value': 'large',
- 'pad': '<span style="font-size: large">[foobarbaz]</span>',
- 'expected': '<span style="font-size: large">[foobarbaz]</span>' },
-
- { 'id': 'FS:18px_SPANs:fs:l-1_SW',
- 'desc': 'Change existing font size to equivalent px size (should be noop, or change unit)',
- 'value': '18px',
- 'pad': '<span style="font-size: large">[foobarbaz]</span>',
- 'expected': [ '<span style="font-size: 18px">[foobarbaz]</span>',
- '<span style="font-size: large">[foobarbaz]</span>' ] },
-
- { 'id': 'FS:4_SPANs:fs:l-1_SW',
- 'desc': 'Change existing font size to equivalent numeric size (should be noop)',
- 'value': '4',
- 'pad': '<span style="font-size: large">[foobarbaz]</span>',
- 'expected': '<span style="font-size: large">[foobarbaz]</span>' },
-
- { 'id': 'FS:4_SPANs:fs:18px-1_SW',
- 'desc': 'Change existing font size to equivalent numeric size (should be noop)',
- 'value': '4',
- 'pad': '<span style="font-size: 18px">[foobarbaz]</span>',
- 'expected': '<span style="font-size: 18px">[foobarbaz]</span>' },
-
- { 'id': 'FS:larger_SPANs:fs:l-1_SI',
- 'desc': 'Change selection to use next larger font',
- 'value': 'larger',
- 'pad': '<span style="font-size: large">foo[bar]baz</span>',
- 'expected': [ '<span style="font-size: large">foo<span style="font-size: x-large">[bar]</span>baz</span>',
- '<span style="font-size: large">foo</span><span style="font-size: x-large">[bar]</span><span style="font-size: large">baz</span>' ],
- 'accept': '<span style="font-size: large">foo<font size="larger">[bar]</font>baz</span>' },
-
- { 'id': 'FS:smaller_SPANs:fs:l-1_SI',
- 'desc': 'Change selection to use next smaller font',
- 'value': 'smaller',
- 'pad': '<span style="font-size: large">foo[bar]baz</span>',
- 'expected': [ '<span style="font-size: large">foo<span style="font-size: medium">[bar]</span>baz</span>',
- '<span style="font-size: large">foo</span><span style="font-size: medium">[bar]</span><span style="font-size: large">baz</span>' ],
- 'accept': '<span style="font-size: large">foo<font size="smaller">[bar]</font>baz</span>' }
- ]
- }
- ]
-}
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/delete.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/delete.py
deleted file mode 100644
index 0cc659225..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/delete.py
+++ /dev/null
@@ -1,330 +0,0 @@
-
-DELETE_TESTS = {
- 'id': 'D',
- 'caption': 'Delete Tests',
- 'command': 'delete',
- 'checkAttrs': True,
- 'checkStyle': False,
-
- 'Proposed': [
- { 'desc': '',
- 'tests': [
- ]
- },
-
- { 'desc': 'delete single characters',
- 'tests': [
- { 'id': 'CHAR-1_SC',
- 'desc': 'Delete 1 character',
- 'pad': 'foo^barbaz',
- 'expected': 'fo^barbaz' },
-
- { 'id': 'CHAR-2_SC',
- 'desc': 'Delete 1 pre-composed character o with diaeresis',
- 'pad': 'fo&#xF6;^barbaz',
- 'expected': 'fo^barbaz' },
-
- { 'id': 'CHAR-3_SC',
- 'desc': 'Delete 1 character with combining diaeresis above',
- 'pad': 'foo&#x0308;^barbaz',
- 'expected': 'fo^barbaz' },
-
- { 'id': 'CHAR-4_SC',
- 'desc': 'Delete 1 character with combining diaeresis below',
- 'pad': 'foo&#x0324;^barbaz',
- 'expected': 'fo^barbaz' },
-
- { 'id': 'CHAR-5_SC',
- 'desc': 'Delete 1 character with combining diaeresis above and below',
- 'pad': 'foo&#x0308;&#x0324;^barbaz',
- 'expected': 'fo^barbaz' },
-
- { 'id': 'CHAR-5_SI-1',
- 'desc': 'Delete 1 character with combining diaeresis above and below, selection on diaeresis above',
- 'pad': 'foo[&#x0308;]&#x0324;barbaz',
- 'expected': 'fo^barbaz' },
-
- { 'id': 'CHAR-5_SI-2',
- 'desc': 'Delete 1 character with combining diaeresis above and below, selection on diaeresis below',
- 'pad': 'foo&#x0308;[&#x0324;]barbaz',
- 'expected': 'fo^barbaz' },
-
- { 'id': 'CHAR-5_SR',
- 'desc': 'Delete 1 character with combining diaeresis above and below, selection oblique on diaeresis and following text',
- 'pad': 'foo&#x0308;[&#x0324;bar]baz',
- 'expected': 'fo^baz' },
-
- { 'id': 'CHAR-6_SC',
- 'desc': 'Delete 1 character with enclosing square',
- 'pad': 'foo&#x20DE;^barbaz',
- 'expected': 'fo^barbaz' },
-
- { 'id': 'CHAR-7_SC',
- 'desc': 'Delete 1 character with combining long solidus overlay',
- 'pad': 'foo&#x0338;^barbaz',
- 'expected': 'fo^barbaz' }
- ]
- },
-
- { 'desc': 'delete text selection',
- 'tests': [
- { 'id': 'TEXT-1_SI',
- 'desc': 'Delete text selection',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo^baz' },
-
- { 'id': 'B-1_SS',
- 'desc': 'Delete at start of span',
- 'pad': 'foo<b>^bar</b>baz',
- 'expected': 'fo^<b>bar</b>baz' },
-
- { 'id': 'B-1_SA',
- 'desc': 'Delete from position after span',
- 'pad': 'foo<b>bar</b>^baz',
- 'expected': 'foo<b>ba^</b>baz' },
-
- { 'id': 'B-1_SW',
- 'desc': 'Delete selection that wraps the whole span content',
- 'pad': 'foo<b>[bar]</b>baz',
- 'expected': 'foo^baz' },
-
- { 'id': 'B-1_SO',
- 'desc': 'Delete selection that wraps the whole span',
- 'pad': 'foo[<b>bar</b>]baz',
- 'expected': 'foo^baz' },
-
- { 'id': 'B-1_SL',
- 'desc': 'Delete oblique selection that starts before span',
- 'pad': 'foo[bar<b>baz]quoz</b>quuz',
- 'expected': 'foo^<b>quoz</b>quuz' },
-
- { 'id': 'B-1_SR',
- 'desc': 'Delete oblique selection that ends after span',
- 'pad': 'foo<b>bar[baz</b>quoz]quuz',
- 'expected': 'foo<b>bar^</b>quuz' },
-
- { 'id': 'B.I-1_SM',
- 'desc': 'Delete oblique selection that starts and ends in different spans',
- 'pad': 'foo<b>bar[baz</b><i>qoz]quuz</i>quuuz',
- 'expected': 'foo<b>bar^</b><i>quuz</i>quuuz' },
-
- { 'id': 'GEN-1_SS',
- 'desc': 'Delete at start of span with generated content',
- 'pad': 'foo<gen>^bar</gen>baz',
- 'expected': 'fo^<gen>bar</gen>baz' },
-
- { 'id': 'GEN-1_SA',
- 'desc': 'Delete from position after span with generated content',
- 'pad': 'foo<gen>bar</gen>^baz',
- 'expected': 'foo<gen>ba^</gen>baz' }
- ]
- },
-
- { 'desc': 'delete paragraphs',
- 'tests': [
- { 'id': 'P2-1_SS2',
- 'desc': 'Delete from collapsed selection at start of paragraph - should merge with previous',
- 'pad': '<p>foobar</p><p>^bazqoz</p>',
- 'expected': '<p>foobar^bazqoz</p>' },
-
- { 'id': 'P2-1_SI2',
- 'desc': 'Delete non-collapsed selection at start of paragraph - should not merge with previous',
- 'pad': '<p>foobar</p><p>[baz]qoz</p>',
- 'expected': '<p>foobar</p><p>^qoz</p>' },
-
- { 'id': 'P2-1_SM',
- 'desc': 'Delete non-collapsed selection spanning 2 paragraphs - should merge them',
- 'pad': '<p>foo[bar</p><p>baz]qoz</p>',
- 'expected': '<p>foo^qoz</p>' }
- ]
- },
-
- { 'desc': 'delete lists and list items',
- 'tests': [
- { 'id': 'OL-LI2-1_SO1',
- 'desc': 'Delete fully wrapped list item',
- 'pad': 'foo<ol>{<li>bar</li>}<li>baz</li></ol>qoz',
- 'expected': ['foo<ol>|<li>baz</li></ol>qoz',
- 'foo<ol><li>^baz</li></ol>qoz'] },
-
- { 'id': 'OL-LI2-1_SM',
- 'desc': 'Delete oblique range between list items within same list',
- 'pad': 'foo<ol><li>ba[r</li><li>b]az</li></ol>qoz',
- 'expected': 'foo<ol><li>ba^az</li></ol>qoz' },
-
- { 'id': 'OL-LI-1_SW',
- 'desc': 'Delete contents of last list item (list should remain)',
- 'pad': 'foo<ol><li>[foo]</li></ol>qoz',
- 'expected': ['foo<ol><li>|</li></ol>qoz',
- 'foo<ol><li>^</li></ol>qoz'] },
-
- { 'id': 'OL-LI-1_SO',
- 'desc': 'Delete last list item of list (should remove entire list)',
- 'pad': 'foo<ol>{<li>foo</li>}</ol>qoz',
- 'expected': 'foo^qoz' }
- ]
- },
-
- { 'desc': 'delete with strange selections',
- 'tests': [
- { 'id': 'HR.BR-1_SM',
- 'desc': 'Delete selection that starts and ends within nodes that don\'t have children',
- 'pad': 'foo<hr {>bar<br }>baz',
- 'expected': 'foo<hr>|<br>baz' }
- ]
- },
-
- { 'desc': 'delete after table',
- 'tests': [
- { 'id': 'TABLE-1_SA',
- 'desc': 'Delete from position immediately after table (should have no effect)',
- 'pad': 'foo<table><tbody><tr><td>bar</td></tr></tbody></table>^baz',
- 'expected': 'foo<table><tbody><tr><td>bar</td></tr></tbody></table>^baz' }
- ]
- },
-
- { 'desc': 'delete within table cells',
- 'tests': [
- { 'id': 'TD-1_SS',
- 'desc': 'Delete from start of first cell (should have no effect)',
- 'pad': 'foo<table><tbody><tr><td>^bar</td></tr></tbody></table>baz',
- 'expected': 'foo<table><tbody><tr><td>^bar</td></tr></tbody></table>baz' },
-
- { 'id': 'TD2-1_SS2',
- 'desc': 'Delete from start of inner cell (should have no effect)',
- 'pad': 'foo<table><tbody><tr><td>bar</td><td>^baz</td></tr></tbody></table>quoz',
- 'expected': 'foo<table><tbody><tr><td>bar</td><td>^baz</td></tr></tbody></table>quoz' },
-
- { 'id': 'TD2-1_SM',
- 'desc': 'Delete with selection spanning 2 cells',
- 'pad': 'foo<table><tbody><tr><td>ba[r</td><td>b]az</td></tr></tbody></table>quoz',
- 'expected': 'foo<table><tbody><tr><td>ba^</td><td>az</td></tr></tbody></table>quoz' }
- ]
- },
-
- { 'desc': 'delete table rows',
- 'tests': [
- { 'id': 'TR3-1_SO1',
- 'desc': 'Delete first table row',
- 'pad': '<table><tbody>{<tr><td>A</td></tr>}<tr><td>B</td></tr><tr><td>C</td></tr></tbody></table>',
- 'expected': ['<table><tbody>|<tr><td>B</td></tr><tr><td>C</td></tr></tbody></table>',
- '<table><tbody><tr><td>^B</td></tr><tr><td>C</td></tr></tbody></table>'] },
-
- { 'id': 'TR3-1_SO2',
- 'desc': 'Delete middle table row',
- 'pad': '<table><tbody><tr><td>A</td></tr>{<tr><td>B</td></tr>}<tr><td>C</td></tr></tbody></table>',
- 'expected': ['<table><tbody><tr><td>A</td></tr>|<tr><td>C</td></tr></tbody></table>',
- '<table><tbody><tr><td>A</td></tr><tr><td>^C</td></tr></tbody></table>'] },
-
- { 'id': 'TR3-1_SO3',
- 'desc': 'Delete last table row',
- 'pad': '<table><tbody><tr><td>A</td></tr><tr><td>B</td></tr>{<tr><td>C</td></tr>}</tbody></table>',
- 'expected': ['<table><tbody><tr><td>A</td></tr><tr><td>B</td></tr>|</tbody></table>',
- '<table><tbody><tr><td>A</td></tr><tr><td>B^</td></tr></tbody></table>'] },
-
- { 'id': 'TR2rs:2-1_SO1',
- 'desc': 'Delete first table row where a cell has rowspan 2',
- 'pad': '<table><tbody>{<tr><td>A</td><td rowspan=2>R</td></tr>}<tr><td>B</td></tr></tbody></table>',
- 'expected': ['<table><tbody>|<tr><td>B</td><td>R</td></tr></tbody></table>',
- '<table><tbody><tr><td>^B</td><td>R</td></tr></tbody></table>'] },
-
- { 'id': 'TR2rs:2-1_SO2',
- 'desc': 'Delete second table row where a cell has rowspan 2',
- 'pad': '<table><tbody><tr><td>A</td><td rowspan=2>R</td></tr>{<tr><td>B</td></tr>}</tbody></table>',
- 'expected': ['<table><tbody><tr><td>A</td><td>R</td></tr>|</tbody></table>',
- '<table><tbody><tr><td>A</td><td>R^</td></tr></tbody></table>'] },
-
- { 'id': 'TR3rs:3-1_SO1',
- 'desc': 'Delete first table row where a cell has rowspan 3',
- 'pad': '<table><tbody>{<tr><td>A</td><td rowspan=3>R</td></tr>}<tr><td>B</td></tr><tr><td>C</td></tr></tbody></table>',
- 'expected': ['<table><tbody>|<tr><td>A</td><td rowspan="2">R</td></tr><tr><td>C</td></tr></tbody></table>',
- '<table><tbody><tr><td>^A</td><td rowspan="2">R</td></tr><tr><td>C</td></tr></tbody></table>'] },
-
- { 'id': 'TR3rs:3-1_SO2',
- 'desc': 'Delete middle table row where a cell has rowspan 3',
- 'pad': '<table><tbody><tr><td>A</td><td rowspan=3>R</td></tr>{<tr><td>B</td></tr>}<tr><td>C</td></tr></tbody></table>',
- 'expected': ['<table><tbody><tr><td>B</td><td rowspan="2">R</td></tr>|<tr><td>C</td></tr></tbody></table>',
- '<table><tbody><tr><td>B</td><td rowspan="2">R</td></tr><tr><td>^C</td></tr></tbody></table>'] },
-
- { 'id': 'TR3rs:3-1_SO3',
- 'desc': 'Delete last table row where a cell has rowspan 3',
- 'pad': '<table><tbody><tr><td>A</td><td rowspan=3>R</td></tr><tr><td>B</td></tr>{<tr><td>C</td></tr>}</tbody></table>',
- 'expected': ['<table><tbody><tr><td>A</td><td rowspan="2">R</td></tr><tr><td>B</td></tr>|</tbody></table>',
- '<table><tbody><tr><td>A</td><td rowspan="2">R</td></tr><tr><td>B^</td></tr></tbody></table>'] }
- ]
- },
-
- { 'desc': 'delete with non-editable nested content',
- 'tests': [
- { 'id': 'DIV:ce:false-1_SO',
- 'desc': 'Delete nested non-editable <div>',
- 'pad': 'foo[bar<div contenteditable="false">NESTED</div>baz]qoz',
- 'expected': 'foo^qoz' },
-
- { 'id': 'DIV:ce:false-1_SB',
- 'desc': 'Delete from immediately after a nested non-editable <div> (should be no-op)',
- 'pad': 'foobar<div contenteditable="false">NESTED</div>^bazqoz',
- 'expected': 'foobar<div contenteditable="false">NESTED</div>^bazqoz' },
-
- { 'id': 'DIV:ce:false-1_SL',
- 'desc': 'Delete nested non-editable <div> with oblique selection',
- 'pad': 'foo[bar<div contenteditable="false">NES]TED</div>bazqoz',
- 'expected': [ 'foo^<div contenteditable="false">NESTED</div>bazqoz',
- 'foo<div contenteditable="false">[NES]TED</div>bazqoz' ] },
-
- { 'id': 'DIV:ce:false-1_SR',
- 'desc': 'Delete nested non-editable <div> with oblique selection',
- 'pad': 'foobar<div contenteditable="false">NES[TED</div>baz]qoz',
- 'expected': [ 'foobar<div contenteditable="false">NESTED</div>^qoz',
- 'foobar<div contenteditable="false">NES[TED]</div>qoz' ] },
-
- { 'id': 'DIV:ce:false-1_SI',
- 'desc': 'Delete inside nested non-editable <div> (should be no-op)',
- 'pad': 'foobar<div contenteditable="false">NE[ST]ED</div>bazqoz',
- 'expected': 'foobar<div contenteditable="false">NE[ST]ED</div>bazqoz' }
- ]
- },
-
- { 'desc': 'Delete with display:inline-block',
- 'checkStyle': True,
- 'tests': [
- { 'id': 'SPAN:d:ib-1_SC',
- 'desc': 'Delete inside an inline-block <span>',
- 'pad': 'foo<span style="display: inline-block">bar^baz</span>qoz',
- 'expected': 'foo<span style="display: inline-block">ba^baz</span>qoz' },
-
- { 'id': 'SPAN:d:ib-1_SA',
- 'desc': 'Delete from immediately after an inline-block <span>',
- 'pad': 'foo<span style="display: inline-block">barbaz</span>^qoz',
- 'expected': 'foo<span style="display: inline-block">barba^</span>qoz' },
-
- { 'id': 'SPAN:d:ib-2_SL',
- 'desc': 'Delete with nested inline-block <span>, oblique selection',
- 'pad': 'foo[DEL<span style="display: inline-block">ETE]bar</span>baz',
- 'expected': 'foo^<span style="display: inline-block">bar</span>baz' },
-
- { 'id': 'SPAN:d:ib-3_SR',
- 'desc': 'Delete with nested inline-block <span>, oblique selection',
- 'pad': 'foo<span style="display: inline-block">bar[DEL</span>ETE]baz',
- 'expected': 'foo<span style="display: inline-block">bar^</span>baz' },
-
- { 'id': 'SPAN:d:ib-4i_SI',
- 'desc': 'Delete with nested inline-block <span>, oblique selection',
- 'pad': 'foo<span style="display: inline-block">bar[DELETE]baz</span>qoz',
- 'expected': 'foo<span style="display: inline-block">bar^baz</span>qoz' },
-
- { 'id': 'SPAN:d:ib-4l_SI',
- 'desc': 'Delete with nested inline-block <span>, oblique selection',
- 'pad': 'foo<span style="display: inline-block">[DELETE]barbaz</span>qoz',
- 'expected': 'foo<span style="display: inline-block">^barbaz</span>qoz' },
-
- { 'id': 'SPAN:d:ib-4r_SI',
- 'desc': 'Delete with nested inline-block <span>, oblique selection',
- 'pad': 'foo<span style="display: inline-block">barbaz[DELETE]</span>qoz',
- 'expected': 'foo<span style="display: inline-block">barbaz^</span>qoz' }
- ]
- }
- ]
-}
-
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/forwarddelete.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/forwarddelete.py
deleted file mode 100644
index d625a2a7d..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/forwarddelete.py
+++ /dev/null
@@ -1,315 +0,0 @@
-
-FORWARDDELETE_TESTS = {
- 'id': 'FD',
- 'caption': 'Forward-Delete Tests',
- 'command': 'forwardDelete',
- 'checkAttrs': True,
- 'checkStyle': False,
-
- 'Proposed': [
- { 'desc': '',
- 'tests': [
- ]
- },
-
- { 'desc': 'forward-delete single characters',
- 'tests': [
- { 'id': 'CHAR-1_SC',
- 'desc': 'Delete 1 character',
- 'pad': 'foo^barbaz',
- 'expected': 'foo^arbaz' },
-
- { 'id': 'CHAR-2_SC',
- 'desc': 'Delete 1 pre-composed character o with diaeresis',
- 'pad': 'fo^&#xF6;barbaz',
- 'expected': 'fo^barbaz' },
-
- { 'id': 'CHAR-3_SC',
- 'desc': 'Delete 1 character with combining diaeresis above',
- 'pad': 'fo^o&#x0308;barbaz',
- 'expected': 'fo^barbaz' },
-
- { 'id': 'CHAR-4_SC',
- 'desc': 'Delete 1 character with combining diaeresis below',
- 'pad': 'fo^o&#x0324;barbaz',
- 'expected': 'fo^barbaz' },
-
- { 'id': 'CHAR-5_SC',
- 'desc': 'Delete 1 character with combining diaeresis above and below',
- 'pad': 'fo^o&#x0308;&#x0324;barbaz',
- 'expected': 'fo^barbaz' },
-
- { 'id': 'CHAR-6_SC',
- 'desc': 'Delete 1 character with enclosing square',
- 'pad': 'fo^o&#x20DE;barbaz',
- 'expected': 'fo^barbaz' },
-
- { 'id': 'CHAR-7_SC',
- 'desc': 'Delete 1 character with combining long solidus overlay',
- 'pad': 'fo^o&#x0338;barbaz',
- 'expected': 'fo^barbaz' }
- ]
- },
-
- { 'desc': 'forward-delete text selections',
- 'tests': [
- { 'id': 'TEXT-1_SI',
- 'desc': 'Delete text selection',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo^baz' },
-
- { 'id': 'B-1_SE',
- 'desc': 'Forward-delete at end of span',
- 'pad': 'foo<b>bar^</b>baz',
- 'expected': 'foo<b>bar^</b>az' },
-
- { 'id': 'B-1_SB',
- 'desc': 'Forward-delete from position before span',
- 'pad': 'foo^<b>bar</b>baz',
- 'expected': 'foo^<b>ar</b>baz' },
-
- { 'id': 'B-1_SW',
- 'desc': 'Delete selection that wraps the whole span content',
- 'pad': 'foo<b>[bar]</b>baz',
- 'expected': 'foo^baz' },
-
- { 'id': 'B-1_SO',
- 'desc': 'Delete selection that wraps the whole span',
- 'pad': 'foo[<b>bar</b>]baz',
- 'expected': 'foo^baz' },
-
- { 'id': 'B-1_SL',
- 'desc': 'Delete oblique selection that starts before span',
- 'pad': 'foo[bar<b>baz]quoz</b>quuz',
- 'expected': 'foo^<b>quoz</b>quuz' },
-
- { 'id': 'B-1_SR',
- 'desc': 'Delete oblique selection that ends after span',
- 'pad': 'foo<b>bar[baz</b>quoz]quuz',
- 'expected': 'foo<b>bar^</b>quuz' },
-
- { 'id': 'B.I-1_SM',
- 'desc': 'Delete oblique selection that starts and ends in different spans',
- 'pad': 'foo<b>bar[baz</b><i>qoz]quuz</i>quuuz',
- 'expected': 'foo<b>bar^</b><i>quuz</i>quuuz' },
-
- { 'id': 'GEN-1_SE',
- 'desc': 'Delete at end of span with generated content',
- 'pad': 'foo<gen>bar^</gen>baz',
- 'expected': 'foo<gen>bar^</gen>az' },
-
- { 'id': 'GEN-1_SB',
- 'desc': 'Delete from position before span with generated content',
- 'pad': 'foo^<gen>bar</gen>baz',
- 'expected': 'foo^<gen>ar</gen>baz' }
- ]
- },
-
- { 'desc': 'forward-delete paragraphs',
- 'tests': [
- { 'id': 'P2-1_SE1',
- 'desc': 'Delete from collapsed selection at end of paragraph - should merge with next',
- 'pad': '<p>foobar^</p><p>bazqoz</p>',
- 'expected': '<p>foobar^bazqoz</p>' },
-
- { 'id': 'P2-1_SI1',
- 'desc': 'Delete non-collapsed selection at end of paragraph - should not merge with next',
- 'pad': '<p>foo[bar]</p><p>bazqoz</p>',
- 'expected': '<p>foo^</p><p>bazqoz</p>' },
-
- { 'id': 'P2-1_SM',
- 'desc': 'Delete non-collapsed selection spanning 2 paragraphs - should merge them',
- 'pad': '<p>foo[bar</p><p>baz]qoz</p>',
- 'expected': '<p>foo^qoz</p>' }
- ]
- },
-
- { 'desc': 'forward-delete lists and list items',
- 'tests': [
- { 'id': 'OL-LI2-1_SO1',
- 'desc': 'Delete fully wrapped list item',
- 'pad': 'foo<ol>{<li>bar</li>}<li>baz</li></ol>qoz',
- 'expected': ['foo<ol>|<li>baz</li></ol>qoz',
- 'foo<ol><li>^baz</li></ol>qoz'] },
-
- { 'id': 'OL-LI2-1_SM',
- 'desc': 'Delete oblique range between list items within same list',
- 'pad': 'foo<ol><li>ba[r</li><li>b]az</li></ol>qoz',
- 'expected': 'foo<ol><li>ba^az</li></ol>qoz' },
-
- { 'id': 'OL-LI-1_SW',
- 'desc': 'Delete contents of last list item (list should remain)',
- 'pad': 'foo<ol><li>[foo]</li></ol>qoz',
- 'expected': ['foo<ol><li>|</li></ol>qoz',
- 'foo<ol><li>^</li></ol>qoz'] },
-
- { 'id': 'OL-LI-1_SO',
- 'desc': 'Delete last list item of list (should remove entire list)',
- 'pad': 'foo<ol>{<li>foo</li>}</ol>qoz',
- 'expected': 'foo^qoz' }
- ]
- },
-
- { 'desc': 'forward-delete with strange selections',
- 'tests': [
- { 'id': 'HR.BR-1_SM',
- 'desc': 'Delete selection that starts and ends within nodes that don\'t have children',
- 'pad': 'foo<hr {>bar<br }>baz',
- 'expected': 'foo<hr>|<br>baz' }
- ]
- },
-
- { 'desc': 'forward-delete from immediately before a table',
- 'tests': [
- { 'id': 'TABLE-1_SB',
- 'desc': 'Delete from position immediately before table (should have no effect)',
- 'pad': 'foo^<table><tbody><tr><td>bar</td></tr></tbody></table>baz',
- 'expected': 'foo^<table><tbody><tr><td>bar</td></tr></tbody></table>baz' }
- ]
- },
-
- { 'desc': 'forward-delete within table cells',
- 'tests': [
- { 'id': 'TD-1_SE',
- 'desc': 'Delete from end of last cell (should have no effect)',
- 'pad': 'foo<table><tbody><tr><td>bar^</td></tr></tbody></table>baz',
- 'expected': 'foo<table><tbody><tr><td>bar^</td></tr></tbody></table>baz' },
-
- { 'id': 'TD2-1_SE1',
- 'desc': 'Delete from end of inner cell (should have no effect)',
- 'pad': 'foo<table><tbody><tr><td>bar^</td><td>baz</td></tr></tbody></table>quoz',
- 'expected': 'foo<table><tbody><tr><td>bar^</td><td>baz</td></tr></tbody></table>quoz' },
-
- { 'id': 'TD2-1_SM',
- 'desc': 'Delete with selection spanning 2 cells',
- 'pad': 'foo<table><tbody><tr><td>ba[r</td><td>b]az</td></tr></tbody></table>quoz',
- 'expected': 'foo<table><tbody><tr><td>ba^</td><td>az</td></tr></tbody></table>quoz' }
- ]
- },
-
- { 'desc': 'forward-delete table rows',
- 'tests': [
- { 'id': 'TR3-1_SO1',
- 'desc': 'Delete first table row',
- 'pad': '<table><tbody>{<tr><td>A</td></tr>}<tr><td>B</td></tr><tr><td>C</td></tr></tbody></table>',
- 'expected': ['<table><tbody>|<tr><td>B</td></tr><tr><td>C</td></tr></tbody></table>',
- '<table><tbody><tr><td>^B</td></tr><tr><td>C</td></tr></tbody></table>'] },
-
- { 'id': 'TR3-1_SO2',
- 'desc': 'Delete middle table row',
- 'pad': '<table><tbody><tr><td>A</td></tr>{<tr><td>B</td></tr>}<tr><td>C</td></tr></tbody></table>',
- 'expected': ['<table><tbody><tr><td>A</td></tr>|<tr><td>C</td></tr></tbody></table>',
- '<table><tbody><tr><td>A</td></tr><tr><td>^C</td></tr></tbody></table>'] },
-
- { 'id': 'TR3-1_SO3',
- 'desc': 'Delete last table row',
- 'pad': '<table><tbody><tr><td>A</td></tr><tr><td>B</td></tr>{<tr><td>C</td></tr>}</tbody></table>',
- 'expected': ['<table><tbody><tr><td>A</td></tr><tr><td>B</td></tr>|</tbody></table>',
- '<table><tbody><tr><td>A</td></tr><tr><td>B^</td></tr></tbody></table>'] },
-
- { 'id': 'TR2rs:2-1_SO1',
- 'desc': 'Delete first table row where a cell has rowspan 2',
- 'pad': '<table><tbody>{<tr><td>A</td><td rowspan=2>R</td></tr>}<tr><td>B</td></tr></tbody></table>',
- 'expected': ['<table><tbody>|<tr><td>B</td><td>R</td></tr></tbody></table>',
- '<table><tbody><tr><td>^B</td><td>R</td></tr></tbody></table>'] },
-
- { 'id': 'TR2rs:2-1_SO2',
- 'desc': 'Delete second table row where a cell has rowspan 2',
- 'pad': '<table><tbody><tr><td>A</td><td rowspan=2>R</td></tr>{<tr><td>B</td></tr>}</tbody></table>',
- 'expected': ['<table><tbody><tr><td>A</td><td>R</td></tr>|</tbody></table>',
- '<table><tbody><tr><td>A</td><td>R^</td></tr></tbody></table>'] },
-
- { 'id': 'TR3rs:3-1_SO1',
- 'desc': 'Delete first table row where a cell has rowspan 3',
- 'pad': '<table><tbody>{<tr><td>A</td><td rowspan=3>R</td></tr>}<tr><td>B</td></tr><tr><td>C</td></tr></tbody></table>',
- 'expected': ['<table><tbody>|<tr><td>A</td><td rowspan="2">R</td></tr><tr><td>C</td></tr></tbody></table>',
- '<table><tbody><tr><td>^A</td><td rowspan="2">R</td></tr><tr><td>C</td></tr></tbody></table>'] },
-
- { 'id': 'TR3rs:3-1_SO2',
- 'desc': 'Delete middle table row where a cell has rowspan 3',
- 'pad': '<table><tbody><tr><td>A</td><td rowspan=3>R</td></tr>{<tr><td>B</td></tr>}<tr><td>C</td></tr></tbody></table>',
- 'expected': ['<table><tbody><tr><td>B</td><td rowspan="2">R</td></tr>|<tr><td>C</td></tr></tbody></table>',
- '<table><tbody><tr><td>B</td><td rowspan="2">R</td></tr><tr><td>^C</td></tr></tbody></table>'] },
-
- { 'id': 'TR3rs:3-1_SO3',
- 'desc': 'Delete last table row where a cell has rowspan 3',
- 'pad': '<table><tbody><tr><td>A</td><td rowspan=3>R</td></tr><tr><td>B</td></tr>{<tr><td>C</td></tr>}</tbody></table>',
- 'expected': ['<table><tbody><tr><td>A</td><td rowspan="2">R</td></tr><tr><td>B</td></tr>|</tbody></table>',
- '<table><tbody><tr><td>A</td><td rowspan="2">R</td></tr><tr><td>B^</td></tr></tbody></table>'] }
- ]
- },
-
- { 'desc': 'delete with non-editable nested content',
- 'tests': [
- { 'id': 'DIV:ce:false-1_SO',
- 'desc': 'Delete nested non-editable <div>',
- 'pad': 'foo[bar<div contenteditable="false">NESTED</div>baz]qoz',
- 'expected': 'foo^qoz' },
-
- { 'id': 'DIV:ce:false-1_SB',
- 'desc': 'Delete from immediately before a nested non-editable <div> (should be no-op)',
- 'pad': 'foobar^<div contenteditable="false">NESTED</div>bazqoz',
- 'expected': 'foobar^<div contenteditable="false">NESTED</div>bazqoz' },
-
- { 'id': 'DIV:ce:false-1_SL',
- 'desc': 'Delete nested non-editable <div> with oblique selection',
- 'pad': 'foo[bar<div contenteditable="false">NES]TED</div>bazqoz',
- 'expected': [ 'foo^<div contenteditable="false">NESTED</div>bazqoz',
- 'foo<div contenteditable="false">[NES]TED</div>bazqoz' ] },
-
- { 'id': 'DIV:ce:false-1_SR',
- 'desc': 'Delete nested non-editable <div> with oblique selection',
- 'pad': 'foobar<div contenteditable="false">NES[TED</div>baz]qoz',
- 'expected': [ 'foobar<div contenteditable="false">NESTED</div>^qoz',
- 'foobar<div contenteditable="false">NES[TED]</div>qoz' ] },
-
- { 'id': 'DIV:ce:false-1_SI',
- 'desc': 'Delete inside nested non-editable <div> (should be no-op)',
- 'pad': 'foobar<div contenteditable="false">NE[ST]ED</div>bazqoz',
- 'expected': 'foobar<div contenteditable="false">NE[ST]ED</div>bazqoz' }
- ]
- },
-
- { 'desc': 'Delete with display:inline-block',
- 'checkStyle': True,
- 'tests': [
- { 'id': 'SPAN:d:ib-1_SC',
- 'desc': 'Delete inside an inline-block <span>',
- 'pad': 'foo<span style="display: inline-block">bar^baz</span>qoz',
- 'expected': 'foo<span style="display: inline-block">bar^az</span>qoz' },
-
- { 'id': 'SPAN:d:ib-1_SA',
- 'desc': 'Delete from immediately before an inline-block <span>',
- 'pad': 'foo^<span style="display: inline-block">barbaz</span>qoz',
- 'expected': 'foo^<span style="display: inline-block">arbaz</span>qoz' },
-
- { 'id': 'SPAN:d:ib-2_SL',
- 'desc': 'Delete with nested inline-block <span>, oblique selection',
- 'pad': 'foo[DEL<span style="display: inline-block">ETE]bar</span>baz',
- 'expected': 'foo^<span style="display: inline-block">bar</span>baz' },
-
- { 'id': 'SPAN:d:ib-3_SR',
- 'desc': 'Delete with nested inline-block <span>, oblique selection',
- 'pad': 'foo<span style="display: inline-block">bar[DEL</span>ETE]baz',
- 'expected': 'foo<span style="display: inline-block">bar^</span>baz' },
-
- { 'id': 'SPAN:d:ib-4i_SI',
- 'desc': 'Delete with nested inline-block <span>, oblique selection',
- 'pad': 'foo<span style="display: inline-block">bar[DELETE]baz</span>qoz',
- 'expected': 'foo<span style="display: inline-block">bar^baz</span>qoz' },
-
- { 'id': 'SPAN:d:ib-4l_SI',
- 'desc': 'Delete with nested inline-block <span>, oblique selection',
- 'pad': 'foo<span style="display: inline-block">[DELETE]barbaz</span>qoz',
- 'expected': 'foo<span style="display: inline-block">^barbaz</span>qoz' },
-
- { 'id': 'SPAN:d:ib-4r_SI',
- 'desc': 'Delete with nested inline-block <span>, oblique selection',
- 'pad': 'foo<span style="display: inline-block">barbaz[DELETE]</span>qoz',
- 'expected': 'foo<span style="display: inline-block">barbaz^</span>qoz' }
- ]
- }
- ]
-}
-
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/insert.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/insert.py
deleted file mode 100644
index a2e79c27c..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/insert.py
+++ /dev/null
@@ -1,285 +0,0 @@
-
-INSERT_TESTS = {
- 'id': 'I',
- 'caption': 'Insert Tests',
- 'checkAttrs': False,
- 'checkStyle': False,
-
- 'Proposed': [
- { 'desc': '',
- 'command': '',
- 'tests': [
- ]
- },
-
- { 'desc': 'insert <hr>',
- 'command': 'inserthorizontalrule',
- 'tests': [
- { 'id': 'IHR_TEXT-1_SC',
- 'rte1-id': 'a-inserthorizontalrule-0',
- 'desc': 'Insert <hr> into text',
- 'pad': 'foo^bar',
- 'expected': 'foo<hr>^bar',
- 'accept': 'foo<hr>|bar' },
-
- { 'id': 'IHR_TEXT-1_SI',
- 'desc': 'Insert <hr>, replacing selected text',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<hr>^baz',
- 'accept': 'foo<hr>|baz' },
-
- { 'id': 'IHR_DIV-B-1_SX',
- 'desc': 'Insert <hr> between elements',
- 'pad': '<div><b>foo</b>|<b>bar</b></div>',
- 'expected': '<div><b>foo</b><hr>|<b>bar</b></div>' },
-
- { 'id': 'IHR_DIV-B-2_SO',
- 'desc': 'Insert <hr>, replacing a fully wrapped element',
- 'pad': '<div><b>foo</b>{<b>bar</b>}<b>baz</b></div>',
- 'expected': '<div><b>foo</b><hr>|<b>baz</b></div>' },
-
- { 'id': 'IHR_B-1_SC',
- 'desc': 'Insert <hr> into a span, splitting it',
- 'pad': '<b>foo^bar</b>',
- 'expected': '<b>foo</b><hr><b>^bar</b>' },
-
- { 'id': 'IHR_B-1_SS',
- 'desc': 'Insert <hr> into a span at the start (should not create an empty span)',
- 'pad': '<b>^foobar</b>',
- 'expected': '<hr><b>^foobar</b>' },
-
- { 'id': 'IHR_B-1_SE',
- 'desc': 'Insert <hr> into a span at the end',
- 'pad': '<b>foobar^</b>',
- 'expected': [ '<b>foobar</b><hr>|',
- '<b>foobar</b><hr><b>^</b>' ] },
-
- { 'id': 'IHR_B-2_SL',
- 'desc': 'Insert <hr> with oblique selection starting outside of span',
- 'pad': 'foo[bar<b>baz]qoz</b>',
- 'expected': 'foo<hr>|<b>qoz</b>' },
-
- { 'id': 'IHR_B-2_SLR',
- 'desc': 'Insert <hr> with oblique reversed selection starting outside of span',
- 'pad': 'foo]bar<b>baz[qoz</b>',
- 'expected': [ 'foo<hr>|<b>qoz</b>',
- 'foo<hr><b>^qoz</b>' ] },
-
- { 'id': 'IHR_B-3_SR',
- 'desc': 'Insert <hr> with oblique selection ending outside of span',
- 'pad': '<b>foo[bar</b>baz]quoz',
- 'expected': [ '<b>foo</b><hr>|quoz',
- '<b>foo</b><hr><b>^</b>quoz' ] },
-
- { 'id': 'IHR_B-3_SRR',
- 'desc': 'Insert <hr> with oblique reversed selection starting outside of span',
- 'pad': '<b>foo]bar</b>baz[quoz',
- 'expected': '<b>foo</b><hr>|quoz' },
-
- { 'id': 'IHR_B-I-1_SM',
- 'desc': 'Insert <hr> with oblique selection between different spans',
- 'pad': '<b>foo[bar</b><i>baz]quoz</i>',
- 'expected': [ '<b>foo</b><hr>|<i>quoz</i>',
- '<b>foo</b><hr><b>^</b><i>quoz</i>' ] },
-
- { 'id': 'IHR_B-I-1_SMR',
- 'desc': 'Insert <hr> with reversed oblique selection between different spans',
- 'pad': '<b>foo]bar</b><i>baz[quoz</i>',
- 'expected': '<b>foo</b><hr><i>^quoz</i>' },
-
- { 'id': 'IHR_P-1_SC',
- 'desc': 'Insert <hr> into a paragraph, splitting it',
- 'pad': '<p>foo^bar</p>',
- 'expected': [ '<p>foo</p><hr>|<p>bar</p>',
- '<p>foo</p><hr><p>^bar</p>' ] },
-
- { 'id': 'IHR_P-1_SS',
- 'desc': 'Insert <hr> into a paragraph at the start (should not create an empty span)',
- 'pad': '<p>^foobar</p>',
- 'expected': [ '<hr>|<p>foobar</p>',
- '<hr><p>^foobar</p>' ] },
-
- { 'id': 'IHR_P-1_SE',
- 'desc': 'Insert <hr> into a paragraph at the end (should not create an empty span)',
- 'pad': '<p>foobar^</p>',
- 'expected': '<p>foobar</p><hr>|' }
- ]
- },
-
- { 'desc': 'insert <p>',
- 'command': 'insertparagraph',
- 'tests': [
- { 'id': 'IP_P-1_SC',
- 'desc': 'Split paragraph',
- 'pad': '<p>foo^bar</p>',
- 'expected': '<p>foo</p><p>^bar</p>' },
-
- { 'id': 'IP_UL-LI-1_SC',
- 'desc': 'Split list item',
- 'pad': '<ul><li>foo^bar</li></ul>',
- 'expected': '<ul><li>foo</li><li>^bar</li></ul>' }
- ]
- },
-
- { 'desc': 'insert text',
- 'command': 'inserttext',
- 'tests': [
- { 'id': 'ITEXT:text_TEXT-1_SC',
- 'desc': 'Insert text',
- 'value': 'text',
- 'pad': 'foo^bar',
- 'expected': 'footext^bar' },
-
- { 'id': 'ITEXT:text_TEXT-1_SI',
- 'desc': 'Insert text, replacing selected text',
- 'value': 'text',
- 'pad': 'foo[bar]baz',
- 'expected': 'footext^baz' }
- ]
- },
-
- { 'desc': 'insert <br>',
- 'command': 'insertlinebreak',
- 'tests': [
- { 'id': 'IBR_TEXT-1_SC',
- 'desc': 'Insert <br> into text',
- 'pad': 'foo^bar',
- 'expected': [ 'foo<br>|bar',
- 'foo<br>^bar' ] },
-
- { 'id': 'IBR_TEXT-1_SI',
- 'desc': 'Insert <br>, replacing selected text',
- 'pad': 'foo[bar]baz',
- 'expected': [ 'foo<br>|baz',
- 'foo<br>^baz' ] },
-
- { 'id': 'IBR_LI-1_SC',
- 'desc': 'Insert <br> within list item',
- 'pad': '<ul><li>foo^bar</li></ul>',
- 'expected': '<ul><li>foo<br>^bar</li></ul>' }
- ]
- },
-
- { 'desc': 'insert <img>',
- 'command': 'insertimage',
- 'tests': [
- { 'id': 'IIMG:url_TEXT-1_SC',
- 'rte1-id': 'a-insertimage-0',
- 'desc': 'Insert image with URL "bar.png"',
- 'value': 'bar.png',
- 'checkAttrs': True,
- 'pad': 'foo^bar',
- 'expected': [ 'foo<img src="bar.png">|bar',
- 'foo<img src="bar.png">^bar' ] },
-
- { 'id': 'IIMG:url_IMG-1_SO',
- 'desc': 'Change existing image to new URL, selection on <img>',
- 'value': 'quz.png',
- 'checkAttrs': True,
- 'pad': '<span>foo{<img src="bar.png">}bar</span>',
- 'expected': [ '<span>foo<img src="quz.png"/>|bar</span>',
- '<span>foo<img src="quz.png"/>^bar</span>' ] },
-
- { 'id': 'IIMG:url_SPAN-IMG-1_SO',
- 'desc': 'Change existing image to new URL, selection in text surrounding <img>',
- 'value': 'quz.png',
- 'checkAttrs': True,
- 'pad': 'foo[<img src="bar.png">]bar',
- 'expected': [ 'foo<img src="quz.png"/>|bar',
- 'foo<img src="quz.png"/>^bar' ] },
-
- { 'id': 'IIMG:._SPAN-IMG-1_SO',
- 'desc': 'Remove existing image or URL, selection on <img>',
- 'value': '',
- 'checkAttrs': True,
- 'pad': '<span>foo{<img src="bar.png">}bar</span>',
- 'expected': [ '<span>foo^bar</span>',
- '<span>foo<img>|bar</span>',
- '<span>foo<img>^bar</span>',
- '<span>foo<img src="">|bar</span>',
- '<span>foo<img src="">^bar</span>' ] },
-
- { 'id': 'IIMG:._IMG-1_SO',
- 'desc': 'Remove existing image or URL, selection in text surrounding <img>',
- 'value': '',
- 'checkAttrs': True,
- 'pad': 'foo[<img src="bar.png">]bar',
- 'expected': [ 'foo^bar',
- 'foo<img>|bar',
- 'foo<img>^bar',
- 'foo<img src="">|bar',
- 'foo<img src="">^bar' ] }
- ]
- },
-
- { 'desc': 'insert <ol>',
- 'command': 'insertorderedlist',
- 'tests': [
- { 'id': 'IOL_TEXT-1_SC',
- 'rte1-id': 'a-insertorderedlist-0',
- 'desc': 'Insert ordered list on collapsed selection',
- 'pad': 'foo^bar',
- 'expected': '<ol><li>foo^bar</li></ol>' },
-
- { 'id': 'IOL_TEXT-1_SI',
- 'desc': 'Insert ordered list on selected text',
- 'pad': 'foo[bar]baz',
- 'expected': '<ol><li>foo[bar]baz</li></ol>' }
- ]
- },
-
- { 'desc': 'insert <ul>',
- 'command': 'insertunorderedlist',
- 'tests': [
- { 'id': 'IUL_TEXT-1_SC',
- 'desc': 'Insert unordered list on collapsed selection',
- 'pad': 'foo^bar',
- 'expected': '<ul><li>foo^bar</li></ul>' },
-
- { 'id': 'IUL_TEXT-1_SI',
- 'rte1-id': 'a-insertunorderedlist-0',
- 'desc': 'Insert unordered list on selected text',
- 'pad': 'foo[bar]baz',
- 'expected': '<ul><li>foo[bar]baz</li></ul>' }
- ]
- },
-
- { 'desc': 'insert arbitrary HTML',
- 'command': 'inserthtml',
- 'tests': [
- { 'id': 'IHTML:BR_TEXT-1_SC',
- 'rte1-id': 'a-inserthtml-0',
- 'desc': 'InsertHTML: <br>',
- 'value': '<br>',
- 'pad': 'foo^barbaz',
- 'expected': 'foo<br>^barbaz' },
-
- { 'id': 'IHTML:text_TEXT-1_SI',
- 'desc': 'InsertHTML: "NEW"',
- 'value': 'NEW',
- 'pad': 'foo[bar]baz',
- 'expected': 'fooNEW^baz' },
-
- { 'id': 'IHTML:S_TEXT-1_SI',
- 'desc': 'InsertHTML: "<span>NEW<span>"',
- 'value': '<span>NEW</span>',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<span>NEW</span>^baz' },
-
- { 'id': 'IHTML:H1.H2_TEXT-1_SI',
- 'desc': 'InsertHTML: "<h1>NEW</h1><h2>HTML</h2>"',
- 'value': '<h1>NEW</h1><h2>HTML</h2>',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<h1>NEW</h1><h2>HTML</h2>^baz' },
-
- { 'id': 'IHTML:P-B_TEXT-1_SI',
- 'desc': 'InsertHTML: "<p>NEW<b>HTML</b>!</p>"',
- 'value': '<p>NEW<b>HTML</b>!</p>',
- 'pad': 'foo[bar]baz',
- 'expected': 'foo<p>NEW<b>HTML</b>!</p>^baz' }
- ]
- }
- ]
-}
-
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryEnabled.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryEnabled.py
deleted file mode 100644
index eb721923b..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryEnabled.py
+++ /dev/null
@@ -1,215 +0,0 @@
-
-QUERYENABLED_TESTS = {
- 'id': 'QE',
- 'caption': 'queryCommandEnabled Tests',
- 'pad': 'foo[bar]baz',
- 'checkAttrs': False,
- 'checkStyle': False,
- 'styleWithCSS': False,
- 'expected': True,
-
- 'Proposed': [
- { 'desc': '',
- 'tests': [
- ]
- },
-
- { 'desc': 'HTML5 commands',
- 'tests': [
- { 'id': 'SELECTALL_TEXT-1',
- 'desc': 'check whether the "selectall" command is enabled',
- 'qcenabled': 'selectall' },
-
- { 'id': 'UNSELECT_TEXT-1',
- 'desc': 'check whether the "unselect" command is enabled',
- 'qcenabled': 'unselect' },
-
- { 'id': 'UNDO_TEXT-1',
- 'desc': 'check whether the "undo" command is enabled',
- 'qcenabled': 'undo' },
-
- { 'id': 'REDO_TEXT-1',
- 'desc': 'check whether the "redo" command is enabled',
- 'qcenabled': 'redo' },
-
- { 'id': 'BOLD_TEXT-1',
- 'desc': 'check whether the "bold" command is enabled',
- 'qcenabled': 'bold' },
-
- { 'id': 'ITALIC_TEXT-1',
- 'desc': 'check whether the "italic" command is enabled',
- 'qcenabled': 'italic' },
-
- { 'id': 'UNDERLINE_TEXT-1',
- 'desc': 'check whether the "underline" command is enabled',
- 'qcenabled': 'underline' },
-
- { 'id': 'STRIKETHROUGH_TEXT-1',
- 'desc': 'check whether the "strikethrough" command is enabled',
- 'qcenabled': 'strikethrough' },
-
- { 'id': 'SUBSCRIPT_TEXT-1',
- 'desc': 'check whether the "subscript" command is enabled',
- 'qcenabled': 'subscript' },
-
- { 'id': 'SUPERSCRIPT_TEXT-1',
- 'desc': 'check whether the "superscript" command is enabled',
- 'qcenabled': 'superscript' },
-
- { 'id': 'FORMATBLOCK_TEXT-1',
- 'desc': 'check whether the "formatblock" command is enabled',
- 'qcenabled': 'formatblock' },
-
- { 'id': 'CREATELINK_TEXT-1',
- 'desc': 'check whether the "createlink" command is enabled',
- 'qcenabled': 'createlink' },
-
- { 'id': 'UNLINK_TEXT-1',
- 'desc': 'check whether the "unlink" command is enabled',
- 'qcenabled': 'unlink' },
-
- { 'id': 'INSERTHTML_TEXT-1',
- 'desc': 'check whether the "inserthtml" command is enabled',
- 'qcenabled': 'inserthtml' },
-
- { 'id': 'INSERTHORIZONTALRULE_TEXT-1',
- 'desc': 'check whether the "inserthorizontalrule" command is enabled',
- 'qcenabled': 'inserthorizontalrule' },
-
- { 'id': 'INSERTIMAGE_TEXT-1',
- 'desc': 'check whether the "insertimage" command is enabled',
- 'qcenabled': 'insertimage' },
-
- { 'id': 'INSERTLINEBREAK_TEXT-1',
- 'desc': 'check whether the "insertlinebreak" command is enabled',
- 'qcenabled': 'insertlinebreak' },
-
- { 'id': 'INSERTPARAGRAPH_TEXT-1',
- 'desc': 'check whether the "insertparagraph" command is enabled',
- 'qcenabled': 'insertparagraph' },
-
- { 'id': 'INSERTORDEREDLIST_TEXT-1',
- 'desc': 'check whether the "insertorderedlist" command is enabled',
- 'qcenabled': 'insertorderedlist' },
-
- { 'id': 'INSERTUNORDEREDLIST_TEXT-1',
- 'desc': 'check whether the "insertunorderedlist" command is enabled',
- 'qcenabled': 'insertunorderedlist' },
-
- { 'id': 'INSERTTEXT_TEXT-1',
- 'desc': 'check whether the "inserttext" command is enabled',
- 'qcenabled': 'inserttext' },
-
- { 'id': 'DELETE_TEXT-1',
- 'desc': 'check whether the "delete" command is enabled',
- 'qcenabled': 'delete' },
-
- { 'id': 'FORWARDDELETE_TEXT-1',
- 'desc': 'check whether the "forwarddelete" command is enabled',
- 'qcenabled': 'forwarddelete' }
- ]
- },
-
- { 'desc': 'MIDAS commands',
- 'tests': [
- { 'id': 'STYLEWITHCSS_TEXT-1',
- 'desc': 'check whether the "styleWithCSS" command is enabled',
- 'qcenabled': 'styleWithCSS' },
-
- { 'id': 'CONTENTREADONLY_TEXT-1',
- 'desc': 'check whether the "contentreadonly" command is enabled',
- 'qcenabled': 'contentreadonly' },
-
- { 'id': 'BACKCOLOR_TEXT-1',
- 'desc': 'check whether the "backcolor" command is enabled',
- 'qcenabled': 'backcolor' },
-
- { 'id': 'FORECOLOR_TEXT-1',
- 'desc': 'check whether the "forecolor" command is enabled',
- 'qcenabled': 'forecolor' },
-
- { 'id': 'HILITECOLOR_TEXT-1',
- 'desc': 'check whether the "hilitecolor" command is enabled',
- 'qcenabled': 'hilitecolor' },
-
- { 'id': 'FONTNAME_TEXT-1',
- 'desc': 'check whether the "fontname" command is enabled',
- 'qcenabled': 'fontname' },
-
- { 'id': 'FONTSIZE_TEXT-1',
- 'desc': 'check whether the "fontsize" command is enabled',
- 'qcenabled': 'fontsize' },
-
- { 'id': 'INCREASEFONTSIZE_TEXT-1',
- 'desc': 'check whether the "increasefontsize" command is enabled',
- 'qcenabled': 'increasefontsize' },
-
- { 'id': 'DECREASEFONTSIZE_TEXT-1',
- 'desc': 'check whether the "decreasefontsize" command is enabled',
- 'qcenabled': 'decreasefontsize' },
-
- { 'id': 'HEADING_TEXT-1',
- 'desc': 'check whether the "heading" command is enabled',
- 'qcenabled': 'heading' },
-
- { 'id': 'INDENT_TEXT-1',
- 'desc': 'check whether the "indent" command is enabled',
- 'qcenabled': 'indent' },
-
- { 'id': 'OUTDENT_TEXT-1',
- 'desc': 'check whether the "outdent" command is enabled',
- 'qcenabled': 'outdent' },
-
- { 'id': 'CREATEBOOKMARK_TEXT-1',
- 'desc': 'check whether the "createbookmark" command is enabled',
- 'qcenabled': 'createbookmark' },
-
- { 'id': 'UNBOOKMARK_TEXT-1',
- 'desc': 'check whether the "unbookmark" command is enabled',
- 'qcenabled': 'unbookmark' },
-
- { 'id': 'JUSTIFYCENTER_TEXT-1',
- 'desc': 'check whether the "justifycenter" command is enabled',
- 'qcenabled': 'justifycenter' },
-
- { 'id': 'JUSTIFYFULL_TEXT-1',
- 'desc': 'check whether the "justifyfull" command is enabled',
- 'qcenabled': 'justifyfull' },
-
- { 'id': 'JUSTIFYLEFT_TEXT-1',
- 'desc': 'check whether the "justifyleft" command is enabled',
- 'qcenabled': 'justifyleft' },
-
- { 'id': 'JUSTIFYRIGHT_TEXT-1',
- 'desc': 'check whether the "justifyright" command is enabled',
- 'qcenabled': 'justifyright' },
-
- { 'id': 'REMOVEFORMAT_TEXT-1',
- 'desc': 'check whether the "removeformat" command is enabled',
- 'qcenabled': 'removeformat' },
-
- { 'id': 'COPY_TEXT-1',
- 'desc': 'check whether the "copy" command is enabled',
- 'qcenabled': 'copy' },
-
- { 'id': 'CUT_TEXT-1',
- 'desc': 'check whether the "cut" command is enabled',
- 'qcenabled': 'cut' },
-
- { 'id': 'PASTE_TEXT-1',
- 'desc': 'check whether the "paste" command is enabled',
- 'qcenabled': 'paste' }
- ]
- },
-
- { 'desc': 'Other tests',
- 'tests': [
- { 'id': 'garbage-1_TEXT-1',
- 'desc': 'check correct return value with garbage input',
- 'qcenabled': '#!#@7',
- 'expected': False }
- ]
- }
- ]
-}
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryIndeterm.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryIndeterm.py
deleted file mode 100644
index d1ad8debd..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryIndeterm.py
+++ /dev/null
@@ -1,214 +0,0 @@
-
-QUERYINDETERM_TESTS = {
- 'id': 'QI',
- 'caption': 'queryCommandIndeterm Tests',
- 'pad': 'foo[bar]baz',
- 'checkAttrs': False,
- 'checkStyle': False,
- 'styleWithCSS': False,
- 'expected': False,
-
- 'Proposed': [
- { 'desc': '',
- 'tests': [
- ]
- },
-
- { 'desc': 'HTML5 commands',
- 'tests': [
- { 'id': 'SELECTALL_TEXT-1',
- 'desc': 'check whether the "selectall" command is indeterminate',
- 'qcindeterm': 'selectall' },
-
- { 'id': 'UNSELECT_TEXT-1',
- 'desc': 'check whether the "unselect" command is indeterminate',
- 'qcindeterm': 'unselect' },
-
- { 'id': 'UNDO_TEXT-1',
- 'desc': 'check whether the "undo" command is indeterminate',
- 'qcindeterm': 'undo' },
-
- { 'id': 'REDO_TEXT-1',
- 'desc': 'check whether the "redo" command is indeterminate',
- 'qcindeterm': 'redo' },
-
- { 'id': 'BOLD_TEXT-1',
- 'desc': 'check whether the "bold" command is indeterminate',
- 'qcindeterm': 'bold' },
-
- { 'id': 'ITALIC_TEXT-1',
- 'desc': 'check whether the "italic" command is indeterminate',
- 'qcindeterm': 'italic' },
-
- { 'id': 'UNDERLINE_TEXT-1',
- 'desc': 'check whether the "underline" command is indeterminate',
- 'qcindeterm': 'underline' },
-
- { 'id': 'STRIKETHROUGH_TEXT-1',
- 'desc': 'check whether the "strikethrough" command is indeterminate',
- 'qcindeterm': 'strikethrough' },
-
- { 'id': 'SUBSCRIPT_TEXT-1',
- 'desc': 'check whether the "subscript" command is indeterminate',
- 'qcindeterm': 'subscript' },
-
- { 'id': 'SUPERSCRIPT_TEXT-1',
- 'desc': 'check whether the "superscript" command is indeterminate',
- 'qcindeterm': 'superscript' },
-
- { 'id': 'FORMATBLOCK_TEXT-1',
- 'desc': 'check whether the "formatblock" command is indeterminate',
- 'qcindeterm': 'formatblock' },
-
- { 'id': 'CREATELINK_TEXT-1',
- 'desc': 'check whether the "createlink" command is indeterminate',
- 'qcindeterm': 'createlink' },
-
- { 'id': 'UNLINK_TEXT-1',
- 'desc': 'check whether the "unlink" command is indeterminate',
- 'qcindeterm': 'unlink' },
-
- { 'id': 'INSERTHTML_TEXT-1',
- 'desc': 'check whether the "inserthtml" command is indeterminate',
- 'qcindeterm': 'inserthtml' },
-
- { 'id': 'INSERTHORIZONTALRULE_TEXT-1',
- 'desc': 'check whether the "inserthorizontalrule" command is indeterminate',
- 'qcindeterm': 'inserthorizontalrule' },
-
- { 'id': 'INSERTIMAGE_TEXT-1',
- 'desc': 'check whether the "insertimage" command is indeterminate',
- 'qcindeterm': 'insertimage' },
-
- { 'id': 'INSERTLINEBREAK_TEXT-1',
- 'desc': 'check whether the "insertlinebreak" command is indeterminate',
- 'qcindeterm': 'insertlinebreak' },
-
- { 'id': 'INSERTPARAGRAPH_TEXT-1',
- 'desc': 'check whether the "insertparagraph" command is indeterminate',
- 'qcindeterm': 'insertparagraph' },
-
- { 'id': 'INSERTORDEREDLIST_TEXT-1',
- 'desc': 'check whether the "insertorderedlist" command is indeterminate',
- 'qcindeterm': 'insertorderedlist' },
-
- { 'id': 'INSERTUNORDEREDLIST_TEXT-1',
- 'desc': 'check whether the "insertunorderedlist" command is indeterminate',
- 'qcindeterm': 'insertunorderedlist' },
-
- { 'id': 'INSERTTEXT_TEXT-1',
- 'desc': 'check whether the "inserttext" command is indeterminate',
- 'qcindeterm': 'inserttext' },
-
- { 'id': 'DELETE_TEXT-1',
- 'desc': 'check whether the "delete" command is indeterminate',
- 'qcindeterm': 'delete' },
-
- { 'id': 'FORWARDDELETE_TEXT-1',
- 'desc': 'check whether the "forwarddelete" command is indeterminate',
- 'qcindeterm': 'forwarddelete' }
- ]
- },
-
- { 'desc': 'MIDAS commands',
- 'tests': [
- { 'id': 'STYLEWITHCSS_TEXT-1',
- 'desc': 'check whether the "styleWithCSS" command is indeterminate',
- 'qcindeterm': 'styleWithCSS' },
-
- { 'id': 'CONTENTREADONLY_TEXT-1',
- 'desc': 'check whether the "contentreadonly" command is indeterminate',
- 'qcindeterm': 'contentreadonly' },
-
- { 'id': 'BACKCOLOR_TEXT-1',
- 'desc': 'check whether the "backcolor" command is indeterminate',
- 'qcindeterm': 'backcolor' },
-
- { 'id': 'FORECOLOR_TEXT-1',
- 'desc': 'check whether the "forecolor" command is indeterminate',
- 'qcindeterm': 'forecolor' },
-
- { 'id': 'HILITECOLOR_TEXT-1',
- 'desc': 'check whether the "hilitecolor" command is indeterminate',
- 'qcindeterm': 'hilitecolor' },
-
- { 'id': 'FONTNAME_TEXT-1',
- 'desc': 'check whether the "fontname" command is indeterminate',
- 'qcindeterm': 'fontname' },
-
- { 'id': 'FONTSIZE_TEXT-1',
- 'desc': 'check whether the "fontsize" command is indeterminate',
- 'qcindeterm': 'fontsize' },
-
- { 'id': 'INCREASEFONTSIZE_TEXT-1',
- 'desc': 'check whether the "increasefontsize" command is indeterminate',
- 'qcindeterm': 'increasefontsize' },
-
- { 'id': 'DECREASEFONTSIZE_TEXT-1',
- 'desc': 'check whether the "decreasefontsize" command is indeterminate',
- 'qcindeterm': 'decreasefontsize' },
-
- { 'id': 'HEADING_TEXT-1',
- 'desc': 'check whether the "heading" command is indeterminate',
- 'qcindeterm': 'heading' },
-
- { 'id': 'INDENT_TEXT-1',
- 'desc': 'check whether the "indent" command is indeterminate',
- 'qcindeterm': 'indent' },
-
- { 'id': 'OUTDENT_TEXT-1',
- 'desc': 'check whether the "outdent" command is indeterminate',
- 'qcindeterm': 'outdent' },
-
- { 'id': 'CREATEBOOKMARK_TEXT-1',
- 'desc': 'check whether the "createbookmark" command is indeterminate',
- 'qcindeterm': 'createbookmark' },
-
- { 'id': 'UNBOOKMARK_TEXT-1',
- 'desc': 'check whether the "unbookmark" command is indeterminate',
- 'qcindeterm': 'unbookmark' },
-
- { 'id': 'JUSTIFYCENTER_TEXT-1',
- 'desc': 'check whether the "justifycenter" command is indeterminate',
- 'qcindeterm': 'justifycenter' },
-
- { 'id': 'JUSTIFYFULL_TEXT-1',
- 'desc': 'check whether the "justifyfull" command is indeterminate',
- 'qcindeterm': 'justifyfull' },
-
- { 'id': 'JUSTIFYLEFT_TEXT-1',
- 'desc': 'check whether the "justifyleft" command is indeterminate',
- 'qcindeterm': 'justifyleft' },
-
- { 'id': 'JUSTIFYRIGHT_TEXT-1',
- 'desc': 'check whether the "justifyright" command is indeterminate',
- 'qcindeterm': 'justifyright' },
-
- { 'id': 'REMOVEFORMAT_TEXT-1',
- 'desc': 'check whether the "removeformat" command is indeterminate',
- 'qcindeterm': 'removeformat' },
-
- { 'id': 'COPY_TEXT-1',
- 'desc': 'check whether the "copy" command is indeterminate',
- 'qcindeterm': 'copy' },
-
- { 'id': 'CUT_TEXT-1',
- 'desc': 'check whether the "cut" command is indeterminate',
- 'qcindeterm': 'cut' },
-
- { 'id': 'PASTE_TEXT-1',
- 'desc': 'check whether the "paste" command is indeterminate',
- 'qcindeterm': 'paste' }
- ]
- },
-
- { 'desc': 'Other tests',
- 'tests': [
- { 'id': 'garbage-1_TEXT-1',
- 'desc': 'check correct return value with garbage input',
- 'qcindeterm': '#!#@7' }
- ]
- }
- ]
-}
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryState.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryState.py
deleted file mode 100644
index 297559d62..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryState.py
+++ /dev/null
@@ -1,575 +0,0 @@
-
-QUERYSTATE_TESTS = {
- 'id': 'QS',
- 'caption': 'queryCommandState Tests',
- 'checkAttrs': False,
- 'checkStyle': False,
- 'styleWithCSS': False,
-
- 'Proposed': [
- { 'desc': '',
- 'qcstate': '',
- 'tests': [
- ]
- },
-
- { 'desc': 'query bold state',
- 'qcstate': 'bold',
- 'tests': [
- { 'id': 'B_TEXT_SI',
- 'rte1-id': 'q-bold-0',
- 'desc': 'query the "bold" state',
- 'pad': 'foo[bar]baz',
- 'expected': False },
-
- { 'id': 'B_B-1_SI',
- 'rte1-id': 'q-bold-1',
- 'desc': 'query the "bold" state',
- 'pad': '<b>foo[bar]baz</b>',
- 'expected': True },
-
- { 'id': 'B_STRONG-1_SI',
- 'rte1-id': 'q-bold-2',
- 'desc': 'query the "bold" state',
- 'pad': '<strong>foo[bar]baz</strong>',
- 'expected': True },
-
- { 'id': 'B_SPANs:fw:b-1_SI',
- 'rte1-id': 'q-bold-3',
- 'desc': 'query the "bold" state',
- 'pad': '<span style="font-weight: bold">foo[bar]baz</span>',
- 'expected': True },
-
- { 'id': 'B_SPANs:fw:n-1_SI',
- 'desc': 'query the "bold" state',
- 'pad': '<span style="font-weight: normal">foo[bar]baz</span>',
- 'expected': False },
-
- { 'id': 'B_Bs:fw:n-1_SI',
- 'rte1-id': 'q-bold-4',
- 'desc': 'query the "bold" state',
- 'pad': '<span style="font-weight: normal">foo[bar]baz</span>',
- 'expected': False },
-
- { 'id': 'B_B-SPANs:fw:n-1_SI',
- 'rte1-id': 'q-bold-5',
- 'desc': 'query the "bold" state',
- 'pad': '<b><span style="font-weight: normal">foo[bar]baz</span></b>',
- 'expected': False },
-
- { 'id': 'B_SPAN.b-1-SI',
- 'desc': 'query the "bold" state',
- 'pad': '<span class="b">foo[bar]baz</span>',
- 'expected': True },
-
- { 'id': 'B_MYB-1-SI',
- 'desc': 'query the "bold" state',
- 'pad': '<myb>foo[bar]baz</myb>',
- 'expected': True },
-
- { 'id': 'B_B-I-1_SC',
- 'desc': 'query the "bold" state, bold tag not immediate parent',
- 'pad': '<b>foo<i>ba^r</i>baz</b>',
- 'expected': True },
-
- { 'id': 'B_B-I-1_SL',
- 'desc': 'query the "bold" state, selection partially in child element',
- 'pad': '<b>fo[o<i>b]ar</i>baz</b>',
- 'expected': True },
-
- { 'id': 'B_B-I-1_SR',
- 'desc': 'query the "bold" state, selection partially in child element',
- 'pad': '<b>foo<i>ba[r</i>b]az</b>',
- 'expected': True },
-
- { 'id': 'B_STRONG-I-1_SC',
- 'desc': 'query the "bold" state, bold tag not immediate parent',
- 'pad': '<strong>foo<i>ba^r</i>baz</strong>',
- 'expected': True },
-
- { 'id': 'B_B-I-U-1_SC',
- 'desc': 'query the "bold" state, bold tag not immediate parent',
- 'pad': '<b>foo<i>bar<u>b^az</u></i></strong>',
- 'expected': True },
-
- { 'id': 'B_B-I-U-1_SM',
- 'desc': 'query the "bold" state, bold tag not immediate parent',
- 'pad': '<b>foo<i>ba[r<u>b]az</u></i></strong>',
- 'expected': True },
-
- { 'id': 'B_TEXT-B-1_SO-1',
- 'desc': 'query the "bold" state, selection wrapping the bold tag',
- 'pad': 'foo[<b>bar</b>]baz',
- 'expected': True },
-
- { 'id': 'B_TEXT-B-1_SO-2',
- 'desc': 'query the "bold" state, selection wrapping the bold tag',
- 'pad': 'foo{<b>bar</b>}baz',
- 'expected': True },
-
- { 'id': 'B_TEXT-B-1_SL',
- 'desc': 'query the "bold" state, selection containing non-bold text',
- 'pad': 'fo[o<b>ba]r</b>baz',
- 'expected': False },
-
- { 'id': 'B_TEXT-B-1_SR',
- 'desc': 'query the "bold" state, selection containing non-bold text',
- 'pad': 'foo<b>b[ar</b>b]az',
- 'expected': False },
-
- { 'id': 'B_TEXT-B-1_SO-3',
- 'desc': 'query the "bold" state, selection containing non-bold text',
- 'pad': 'fo[o<b>bar</b>b]az',
- 'expected': False },
-
- { 'id': 'B_B.TEXT.B-1_SM',
- 'desc': 'query the "bold" state, selection including non-bold text',
- 'pad': '<b>fo[o</b>bar<b>b]az</b>',
- 'expected': False },
-
- { 'id': 'B_B.B.B-1_SM',
- 'desc': 'query the "bold" state, selection mixed, but all bold',
- 'pad': '<b>fo[o</b><b>bar</b><b>b]az</b>',
- 'expected': True },
-
- { 'id': 'B_B.STRONG.B-1_SM',
- 'desc': 'query the "bold" state, selection mixed, but all bold',
- 'pad': '<b>fo[o</b><strong>bar</strong><b>b]az</b>',
- 'expected': True },
-
- { 'id': 'B_SPAN.b.MYB.SPANs:fw:b-1_SM',
- 'desc': 'query the "bold" state, selection mixed, but all bold',
- 'pad': '<span class="b">fo[o</span><myb>bar</myb><span style="font-weight: bold">b]az</span>',
- 'expected': True }
- ]
- },
-
- { 'desc': 'query italic state',
- 'qcstate': 'italic',
- 'tests': [
- { 'id': 'I_TEXT_SI',
- 'rte1-id': 'q-italic-0',
- 'desc': 'query the "italic" state',
- 'pad': 'foo[bar]baz',
- 'expected': False },
-
- { 'id': 'I_I-1_SI',
- 'rte1-id': 'q-italic-1',
- 'desc': 'query the "italic" state',
- 'pad': '<i>foo[bar]baz</i>',
- 'expected': True },
-
- { 'id': 'I_EM-1_SI',
- 'rte1-id': 'q-italic-2',
- 'desc': 'query the "italic" state',
- 'pad': '<em>foo[bar]baz</em>',
- 'expected': True },
-
- { 'id': 'I_SPANs:fs:i-1_SI',
- 'rte1-id': 'q-italic-3',
- 'desc': 'query the "italic" state',
- 'pad': '<span style="font-style: italic">foo[bar]baz</span>',
- 'expected': True },
-
- { 'id': 'I_SPANs:fs:n-1_SI',
- 'desc': 'query the "italic" state',
- 'pad': '<span style="font-style: normal">foo[bar]baz</span>',
- 'expected': False },
-
- { 'id': 'I_I-SPANs:fs:n-1_SI',
- 'rte1-id': 'q-italic-4',
- 'desc': 'query the "italic" state',
- 'pad': '<i><span style="font-style: normal">foo[bar]baz</span></i>',
- 'expected': False },
-
- { 'id': 'I_SPAN.i-1-SI',
- 'desc': 'query the "italic" state',
- 'pad': '<span class="i">foo[bar]baz</span>',
- 'expected': True },
-
- { 'id': 'I_MYI-1-SI',
- 'desc': 'query the "italic" state',
- 'pad': '<myi>foo[bar]baz</myi>',
- 'expected': True }
- ]
- },
-
- { 'desc': 'query underline state',
- 'qcstate': 'underline',
- 'tests': [
- { 'id': 'U_TEXT_SI',
- 'rte1-id': 'q-underline-0',
- 'desc': 'query the "underline" state',
- 'pad': 'foo[bar]baz',
- 'expected': False },
-
- { 'id': 'U_U-1_SI',
- 'rte1-id': 'q-underline-1',
- 'desc': 'query the "underline" state',
- 'pad': '<u>foo[bar]baz</u>',
- 'expected': True },
-
- { 'id': 'U_Us:td:n-1_SI',
- 'rte1-id': 'q-underline-4',
- 'desc': 'query the "underline" state',
- 'pad': '<u style="text-decoration: none">foo[bar]baz</u>',
- 'expected': False },
-
- { 'id': 'U_Ah:url-1_SI',
- 'rte1-id': 'q-underline-2',
- 'desc': 'query the "underline" state',
- 'pad': '<a href="http://www.goo.gl">foo[bar]baz</a>',
- 'expected': True },
-
- { 'id': 'U_Ah:url.s:td:n-1_SI',
- 'rte1-id': 'q-underline-5',
- 'desc': 'query the "underline" state',
- 'pad': '<a href="http://www.goo.gl" style="text-decoration: none">foo[bar]baz</a>',
- 'expected': False },
-
- { 'id': 'U_SPANs:td:u-1_SI',
- 'rte1-id': 'q-underline-3',
- 'desc': 'query the "underline" state',
- 'pad': '<span style="text-decoration: underline">foo[bar]baz</span>',
- 'expected': True },
-
- { 'id': 'U_SPAN.u-1-SI',
- 'desc': 'query the "underline" state',
- 'pad': '<span class="u">foo[bar]baz</span>',
- 'expected': True },
-
- { 'id': 'U_MYU-1-SI',
- 'desc': 'query the "underline" state',
- 'pad': '<myu>foo[bar]baz</myu>',
- 'expected': True }
- ]
- },
-
- { 'desc': 'query strike-through state',
- 'qcstate': 'strikethrough',
- 'tests': [
- { 'id': 'S_TEXT_SI',
- 'rte1-id': 'q-strikethrough-0',
- 'desc': 'query the "strikethrough" state',
- 'pad': 'foo[bar]baz',
- 'expected': False },
-
- { 'id': 'S_S-1_SI',
- 'rte1-id': 'q-strikethrough-3',
- 'desc': 'query the "strikethrough" state',
- 'pad': '<s>foo[bar]baz</s>',
- 'expected': True },
-
- { 'id': 'S_STRIKE-1_SI',
- 'rte1-id': 'q-strikethrough-1',
- 'desc': 'query the "strikethrough" state',
- 'pad': '<strike>foo[bar]baz</strike>',
- 'expected': True },
-
- { 'id': 'S_STRIKEs:td:n-1_SI',
- 'rte1-id': 'q-strikethrough-2',
- 'desc': 'query the "strikethrough" state',
- 'pad': '<strike style="text-decoration: none">foo[bar]baz</strike>',
- 'expected': False },
-
- { 'id': 'S_DEL-1_SI',
- 'rte1-id': 'q-strikethrough-4',
- 'desc': 'query the "strikethrough" state',
- 'pad': '<del>foo[bar]baz</del>',
- 'expected': True },
-
- { 'id': 'S_SPANs:td:lt-1_SI',
- 'rte1-id': 'q-strikethrough-5',
- 'desc': 'query the "strikethrough" state',
- 'pad': '<span style="text-decoration: line-through">foo[bar]baz</span>',
- 'expected': True },
-
- { 'id': 'S_SPAN.s-1-SI',
- 'desc': 'query the "strikethrough" state',
- 'pad': '<span class="s">foo[bar]baz</span>',
- 'expected': True },
-
- { 'id': 'S_MYS-1-SI',
- 'desc': 'query the "strikethrough" state',
- 'pad': '<mys>foo[bar]baz</mys>',
- 'expected': True },
-
- { 'id': 'S_S.STRIKE.DEL-1_SM',
- 'desc': 'query the "strikethrough" state, selection mixed, but all struck',
- 'pad': '<s>fo[o</s><strike>bar</strike><del>b]az</del>',
- 'expected': True }
- ]
- },
-
- { 'desc': 'query subscript state',
- 'qcstate': 'subscript',
- 'tests': [
- { 'id': 'SUB_TEXT_SI',
- 'rte1-id': 'q-subscript-0',
- 'desc': 'query the "subscript" state',
- 'pad': 'foo[bar]baz',
- 'expected': False },
-
- { 'id': 'SUB_SUB-1_SI',
- 'rte1-id': 'q-subscript-1',
- 'desc': 'query the "subscript" state',
- 'pad': '<sub>foo[bar]baz</sub>',
- 'expected': True },
-
- { 'id': 'SUB_SPAN.sub-1-SI',
- 'desc': 'query the "subscript" state',
- 'pad': '<span class="sub">foo[bar]baz</span>',
- 'expected': True },
-
- { 'id': 'SUB_MYSUB-1-SI',
- 'desc': 'query the "subscript" state',
- 'pad': '<mysub>foo[bar]baz</mysub>',
- 'expected': True }
- ]
- },
-
- { 'desc': 'query superscript state',
- 'qcstate': 'superscript',
- 'tests': [
- { 'id': 'SUP_TEXT_SI',
- 'rte1-id': 'q-superscript-0',
- 'desc': 'query the "superscript" state',
- 'pad': 'foo[bar]baz',
- 'expected': False },
-
- { 'id': 'SUP_SUP-1_SI',
- 'rte1-id': 'q-superscript-1',
- 'desc': 'query the "superscript" state',
- 'pad': '<sup>foo[bar]baz</sup>',
- 'expected': True },
-
- { 'id': 'IOL_TEXT_SI',
- 'desc': 'query the "insertorderedlist" state',
- 'pad': 'foo[bar]baz',
- 'expected': False },
-
- { 'id': 'SUP_SPAN.sup-1-SI',
- 'desc': 'query the "superscript" state',
- 'pad': '<span class="sup">foo[bar]baz</span>',
- 'expected': True },
-
- { 'id': 'SUP_MYSUP-1-SI',
- 'desc': 'query the "superscript" state',
- 'pad': '<mysup>foo[bar]baz</mysup>',
- 'expected': True }
- ]
- },
-
- { 'desc': 'query whether the selection is in an ordered list',
- 'qcstate': 'insertorderedlist',
- 'tests': [
- { 'id': 'IOL_TEXT-1_SI',
- 'rte1-id': 'q-insertorderedlist-0',
- 'desc': 'query the "insertorderedlist" state',
- 'pad': 'foo[bar]baz',
- 'expected': False },
-
- { 'id': 'IOL_OL-LI-1_SI',
- 'rte1-id': 'q-insertorderedlist-1',
- 'desc': 'query the "insertorderedlist" state',
- 'pad': '<ol><li>foo[bar]baz</li></ol>',
- 'expected': True },
-
- { 'id': 'IOL_UL_LI-1_SI',
- 'rte1-id': 'q-insertorderedlist-2',
- 'desc': 'query the "insertorderedlist" state',
- 'pad': '<ul><li>foo[bar]baz</li></ul>',
- 'expected': False }
- ]
- },
-
- { 'desc': 'query whether the selection is in an unordered list',
- 'qcstate': 'insertunorderedlist',
- 'tests': [
- { 'id': 'IUL_TEXT_SI',
- 'rte1-id': 'q-insertunorderedlist-0',
- 'desc': 'query the "insertunorderedlist" state',
- 'pad': 'foo[bar]baz',
- 'expected': False },
-
- { 'id': 'IUL_OL-LI-1_SI',
- 'rte1-id': 'q-insertunorderedlist-1',
- 'desc': 'query the "insertunorderedlist" state',
- 'pad': '<ol><li>foo[bar]baz</li></ol>',
- 'expected': False },
-
- { 'id': 'IUL_UL-LI-1_SI',
- 'rte1-id': 'q-insertunorderedlist-2',
- 'desc': 'query the "insertunorderedlist" state',
- 'pad': '<ul><li>foo[bar]baz</li></ul>',
- 'expected': True }
- ]
- },
-
- { 'desc': 'query whether the paragraph is centered',
- 'qcstate': 'justifycenter',
- 'tests': [
- { 'id': 'JC_TEXT_SI',
- 'rte1-id': 'q-justifycenter-0',
- 'desc': 'query the "justifycenter" state',
- 'pad': 'foo[bar]baz',
- 'expected': False },
-
- { 'id': 'JC_DIVa:c-1_SI',
- 'rte1-id': 'q-justifycenter-1',
- 'desc': 'query the "justifycenter" state',
- 'pad': '<div align="center">foo[bar]baz</div>',
- 'expected': True },
-
- { 'id': 'JC_Pa:c-1_SI',
- 'rte1-id': 'q-justifycenter-2',
- 'desc': 'query the "justifycenter" state',
- 'pad': '<p align="center">foo[bar]baz</p>',
- 'expected': True },
-
- { 'id': 'JC_SPANs:ta:c-1_SI',
- 'rte1-id': 'q-justifycenter-3',
- 'desc': 'query the "justifycenter" state',
- 'pad': '<div style="text-align: center">foo[bar]baz</div>',
- 'expected': True },
-
- { 'id': 'JC_SPAN.jc-1-SI',
- 'desc': 'query the "justifycenter" state',
- 'pad': '<span class="jc">foo[bar]baz</span>',
- 'expected': True },
-
- { 'id': 'JC_MYJC-1-SI',
- 'desc': 'query the "justifycenter" state',
- 'pad': '<myjc>foo[bar]baz</myjc>',
- 'expected': True }
- ]
- },
-
- { 'desc': 'query whether the paragraph is justified',
- 'qcstate': 'justifyfull',
- 'tests': [
- { 'id': 'JF_TEXT_SI',
- 'rte1-id': 'q-justifyfull-0',
- 'desc': 'query the "justifyfull" state',
- 'pad': 'foo[bar]baz',
- 'expected': False },
-
- { 'id': 'JF_DIVa:j-1_SI',
- 'rte1-id': 'q-justifyfull-1',
- 'desc': 'query the "justifyfull" state',
- 'pad': '<div align="justify">foo[bar]baz</div>',
- 'expected': True },
-
- { 'id': 'JF_Pa:j-1_SI',
- 'rte1-id': 'q-justifyfull-2',
- 'desc': 'query the "justifyfull" state',
- 'pad': '<p align="justify">foo[bar]baz</p>',
- 'expected': True },
-
- { 'id': 'JF_SPANs:ta:j-1_SI',
- 'rte1-id': 'q-justifyfull-3',
- 'desc': 'query the "justifyfull" state',
- 'pad': '<span style="text-align: justify">foo[bar]baz</span>',
- 'expected': True },
-
- { 'id': 'JF_SPAN.jf-1-SI',
- 'desc': 'query the "justifyfull" state',
- 'pad': '<span class="jf">foo[bar]baz</span>',
- 'expected': True },
-
- { 'id': 'JF_MYJF-1-SI',
- 'desc': 'query the "justifyfull" state',
- 'pad': '<myjf>foo[bar]baz</myjf>',
- 'expected': True }
- ]
- },
-
- { 'desc': 'query whether the paragraph is aligned left',
- 'qcstate': 'justifyleft',
- 'tests': [
- { 'id': 'JL_TEXT_SI',
- 'desc': 'query the "justifyleft" state',
- 'pad': 'foo[bar]baz',
- 'expected': False },
-
- { 'id': 'JL_DIVa:l-1_SI',
- 'rte1-id': 'q-justifyleft-0',
- 'desc': 'query the "justifyleft" state',
- 'pad': '<div align="left">foo[bar]baz</div>',
- 'expected': True },
-
- { 'id': 'JL_Pa:l-1_SI',
- 'rte1-id': 'q-justifyleft-1',
- 'desc': 'query the "justifyleft" state',
- 'pad': '<p align="left">foo[bar]baz</p>',
- 'expected': True },
-
- { 'id': 'JL_SPANs:ta:l-1_SI',
- 'rte1-id': 'q-justifyleft-2',
- 'desc': 'query the "justifyleft" state',
- 'pad': '<span style="text-align: left">foo[bar]baz</span>',
- 'expected': True },
-
- { 'id': 'JL_SPAN.jl-1-SI',
- 'desc': 'query the "justifyleft" state',
- 'pad': '<span class="jl">foo[bar]baz</span>',
- 'expected': True },
-
- { 'id': 'JL_MYJL-1-SI',
- 'desc': 'query the "justifyleft" state',
- 'pad': '<myjl>foo[bar]baz</myjl>',
- 'expected': True }
- ]
- },
-
- { 'desc': 'query whether the paragraph is aligned right',
- 'qcstate': 'justifyright',
- 'tests': [
- { 'id': 'JR_TEXT_SI',
- 'rte1-id': 'q-justifyright-0',
- 'desc': 'query the "justifyright" state',
- 'pad': 'foo[bar]baz',
- 'expected': False },
-
- { 'id': 'JR_DIVa:r-1_SI',
- 'rte1-id': 'q-justifyright-1',
- 'desc': 'query the "justifyright" state',
- 'pad': '<div align="right">foo[bar]baz</div>',
- 'expected': True },
-
- { 'id': 'JR_Pa:r-1_SI',
- 'rte1-id': 'q-justifyright-2',
- 'desc': 'query the "justifyright" state',
- 'pad': '<p align="right">foo[bar]baz</p>',
- 'expected': True },
-
- { 'id': 'JR_SPANs:ta:r-1_SI',
- 'rte1-id': 'q-justifyright-3',
- 'desc': 'query the "justifyright" state',
- 'pad': '<span style="text-align: right">foo[bar]baz</span>',
- 'expected': True },
-
- { 'id': 'JR_SPAN.jr-1-SI',
- 'desc': 'query the "justifyright" state',
- 'pad': '<span class="jr">foo[bar]baz</span>',
- 'expected': True },
-
- { 'id': 'JR_MYJR-1-SI',
- 'desc': 'query the "justifyright" state',
- 'pad': '<myjr>foo[bar]baz</myjr>',
- 'expected': True }
- ]
- }
- ]
-}
-
-QUERYSTATE_TESTS_CSS = {
- 'id': 'QSC',
- 'caption': 'queryCommandState Tests, using styleWithCSS',
- 'checkAttrs': False,
- 'checkStyle': False,
- 'styleWithCSS': True,
-
- 'Proposed': QUERYSTATE_TESTS['Proposed']
-}
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/querySupported.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/querySupported.py
deleted file mode 100644
index af23a428c..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/querySupported.py
+++ /dev/null
@@ -1,226 +0,0 @@
-
-QUERYSUPPORTED_TESTS = {
- 'id': 'Q',
- 'caption': 'queryCommandSupported Tests',
- 'pad': 'foo[bar]baz',
- 'checkAttrs': False,
- 'checkStyle': False,
- 'styleWithCSS': False,
- 'expected': True,
-
- 'Proposed': [
- { 'desc': '',
- 'tests': [
- ]
- },
-
- { 'desc': 'HTML5 commands',
- 'tests': [
- { 'id': 'SELECTALL_TEXT-1',
- 'desc': 'check whether the "selectall" command is supported',
- 'qcsupported': 'selectall' },
-
- { 'id': 'UNSELECT_TEXT-1',
- 'desc': 'check whether the "unselect" command is supported',
- 'qcsupported': 'unselect' },
-
- { 'id': 'UNDO_TEXT-1',
- 'desc': 'check whether the "undo" command is supported',
- 'qcsupported': 'undo' },
-
- { 'id': 'REDO_TEXT-1',
- 'desc': 'check whether the "redo" command is supported',
- 'qcsupported': 'redo' },
-
- { 'id': 'BOLD_TEXT-1',
- 'desc': 'check whether the "bold" command is supported',
- 'qcsupported': 'bold' },
-
- { 'id': 'BOLD_B',
- 'desc': 'check whether the "bold" command is supported',
- 'qcsupported': 'bold',
- 'pad': '<b>foo[bar]baz</b>' },
-
- { 'id': 'ITALIC_TEXT-1',
- 'desc': 'check whether the "italic" command is supported',
- 'qcsupported': 'italic' },
-
- { 'id': 'ITALIC_I',
- 'desc': 'check whether the "italic" command is supported',
- 'qcsupported': 'italic',
- 'pad': '<i>foo[bar]baz</i>' },
-
- { 'id': 'UNDERLINE_TEXT-1',
- 'desc': 'check whether the "underline" command is supported',
- 'qcsupported': 'underline' },
-
- { 'id': 'STRIKETHROUGH_TEXT-1',
- 'desc': 'check whether the "strikethrough" command is supported',
- 'qcsupported': 'strikethrough' },
-
- { 'id': 'SUBSCRIPT_TEXT-1',
- 'desc': 'check whether the "subscript" command is supported',
- 'qcsupported': 'subscript' },
-
- { 'id': 'SUPERSCRIPT_TEXT-1',
- 'desc': 'check whether the "superscript" command is supported',
- 'qcsupported': 'superscript' },
-
- { 'id': 'FORMATBLOCK_TEXT-1',
- 'desc': 'check whether the "formatblock" command is supported',
- 'qcsupported': 'formatblock' },
-
- { 'id': 'CREATELINK_TEXT-1',
- 'desc': 'check whether the "createlink" command is supported',
- 'qcsupported': 'createlink' },
-
- { 'id': 'UNLINK_TEXT-1',
- 'desc': 'check whether the "unlink" command is supported',
- 'qcsupported': 'unlink' },
-
- { 'id': 'INSERTHTML_TEXT-1',
- 'desc': 'check whether the "inserthtml" command is supported',
- 'qcsupported': 'inserthtml' },
-
- { 'id': 'INSERTHORIZONTALRULE_TEXT-1',
- 'desc': 'check whether the "inserthorizontalrule" command is supported',
- 'qcsupported': 'inserthorizontalrule' },
-
- { 'id': 'INSERTIMAGE_TEXT-1',
- 'desc': 'check whether the "insertimage" command is supported',
- 'qcsupported': 'insertimage' },
-
- { 'id': 'INSERTLINEBREAK_TEXT-1',
- 'desc': 'check whether the "insertlinebreak" command is supported',
- 'qcsupported': 'insertlinebreak' },
-
- { 'id': 'INSERTPARAGRAPH_TEXT-1',
- 'desc': 'check whether the "insertparagraph" command is supported',
- 'qcsupported': 'insertparagraph' },
-
- { 'id': 'INSERTORDEREDLIST_TEXT-1',
- 'desc': 'check whether the "insertorderedlist" command is supported',
- 'qcsupported': 'insertorderedlist' },
-
- { 'id': 'INSERTUNORDEREDLIST_TEXT-1',
- 'desc': 'check whether the "insertunorderedlist" command is supported',
- 'qcsupported': 'insertunorderedlist' },
-
- { 'id': 'INSERTTEXT_TEXT-1',
- 'desc': 'check whether the "inserttext" command is supported',
- 'qcsupported': 'inserttext' },
-
- { 'id': 'DELETE_TEXT-1',
- 'desc': 'check whether the "delete" command is supported',
- 'qcsupported': 'delete' },
-
- { 'id': 'FORWARDDELETE_TEXT-1',
- 'desc': 'check whether the "forwarddelete" command is supported',
- 'qcsupported': 'forwarddelete' }
- ]
- },
-
- { 'desc': 'MIDAS commands',
- 'tests': [
- { 'id': 'STYLEWITHCSS_TEXT-1',
- 'desc': 'check whether the "styleWithCSS" command is supported',
- 'qcsupported': 'styleWithCSS' },
-
- { 'id': 'CONTENTREADONLY_TEXT-1',
- 'desc': 'check whether the "contentreadonly" command is supported',
- 'qcsupported': 'contentreadonly' },
-
- { 'id': 'BACKCOLOR_TEXT-1',
- 'desc': 'check whether the "backcolor" command is supported',
- 'qcsupported': 'backcolor' },
-
- { 'id': 'FORECOLOR_TEXT-1',
- 'desc': 'check whether the "forecolor" command is supported',
- 'qcsupported': 'forecolor' },
-
- { 'id': 'HILITECOLOR_TEXT-1',
- 'desc': 'check whether the "hilitecolor" command is supported',
- 'qcsupported': 'hilitecolor' },
-
- { 'id': 'FONTNAME_TEXT-1',
- 'desc': 'check whether the "fontname" command is supported',
- 'qcsupported': 'fontname' },
-
- { 'id': 'FONTSIZE_TEXT-1',
- 'desc': 'check whether the "fontsize" command is supported',
- 'qcsupported': 'fontsize' },
-
- { 'id': 'INCREASEFONTSIZE_TEXT-1',
- 'desc': 'check whether the "increasefontsize" command is supported',
- 'qcsupported': 'increasefontsize' },
-
- { 'id': 'DECREASEFONTSIZE_TEXT-1',
- 'desc': 'check whether the "decreasefontsize" command is supported',
- 'qcsupported': 'decreasefontsize' },
-
- { 'id': 'HEADING_TEXT-1',
- 'desc': 'check whether the "heading" command is supported',
- 'qcsupported': 'heading' },
-
- { 'id': 'INDENT_TEXT-1',
- 'desc': 'check whether the "indent" command is supported',
- 'qcsupported': 'indent' },
-
- { 'id': 'OUTDENT_TEXT-1',
- 'desc': 'check whether the "outdent" command is supported',
- 'qcsupported': 'outdent' },
-
- { 'id': 'CREATEBOOKMARK_TEXT-1',
- 'desc': 'check whether the "createbookmark" command is supported',
- 'qcsupported': 'createbookmark' },
-
- { 'id': 'UNBOOKMARK_TEXT-1',
- 'desc': 'check whether the "unbookmark" command is supported',
- 'qcsupported': 'unbookmark' },
-
- { 'id': 'JUSTIFYCENTER_TEXT-1',
- 'desc': 'check whether the "justifycenter" command is supported',
- 'qcsupported': 'justifycenter' },
-
- { 'id': 'JUSTIFYFULL_TEXT-1',
- 'desc': 'check whether the "justifyfull" command is supported',
- 'qcsupported': 'justifyfull' },
-
- { 'id': 'JUSTIFYLEFT_TEXT-1',
- 'desc': 'check whether the "justifyleft" command is supported',
- 'qcsupported': 'justifyleft' },
-
- { 'id': 'JUSTIFYRIGHT_TEXT-1',
- 'desc': 'check whether the "justifyright" command is supported',
- 'qcsupported': 'justifyright' },
-
- { 'id': 'REMOVEFORMAT_TEXT-1',
- 'desc': 'check whether the "removeformat" command is supported',
- 'qcsupported': 'removeformat' },
-
- { 'id': 'COPY_TEXT-1',
- 'desc': 'check whether the "copy" command is supported',
- 'qcsupported': 'copy' },
-
- { 'id': 'CUT_TEXT-1',
- 'desc': 'check whether the "cut" command is supported',
- 'qcsupported': 'cut' },
-
- { 'id': 'PASTE_TEXT-1',
- 'desc': 'check whether the "paste" command is supported',
- 'qcsupported': 'paste' }
- ]
- },
-
- { 'desc': 'Other tests',
- 'tests': [
- { 'id': 'garbage-1_TEXT-1',
- 'desc': 'check correct return value with garbage input',
- 'qcsupported': '#!#@7',
- 'expected': False }
- ]
- }
- ]
-}
-
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryValue.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryValue.py
deleted file mode 100644
index 793b7cb6c..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryValue.py
+++ /dev/null
@@ -1,429 +0,0 @@
-
-QUERYVALUE_TESTS = {
- 'id': 'QV',
- 'caption': 'queryCommandValue Tests',
- 'checkAttrs': False,
- 'checkStyle': False,
- 'styleWithCSS': False,
-
- 'Proposed': [
- { 'desc': '',
- 'tests': [
- ]
- },
-
- { 'desc': '[HTML5] query bold value',
- 'qcvalue': 'bold',
- 'tests': [
- { 'id': 'B_TEXT_SI',
- 'desc': 'query the "bold" value',
- 'pad': 'foo[bar]baz',
- 'expected': 'false' },
-
- { 'id': 'B_B-1_SI',
- 'desc': 'query the "bold" value',
- 'pad': '<b>foo[bar]baz</b>',
- 'expected': 'true' },
-
- { 'id': 'B_STRONG-1_SI',
- 'desc': 'query the "bold" value',
- 'pad': '<strong>foo[bar]baz</strong>',
- 'expected': 'true' },
-
- { 'id': 'B_SPANs:fw:b-1_SI',
- 'desc': 'query the "bold" value',
- 'pad': '<span style="font-weight: bold">foo[bar]baz</span>',
- 'expected': 'true' },
-
- { 'id': 'B_SPANs:fw:n-1_SI',
- 'desc': 'query the "bold" value',
- 'pad': '<span style="font-weight: normal">foo[bar]baz</span>',
- 'expected': 'false' },
-
- { 'id': 'B_Bs:fw:n-1_SI',
- 'desc': 'query the "bold" value',
- 'pad': '<b><span style="font-weight: normal">foo[bar]baz</span></b>',
- 'expected': 'false' },
-
- { 'id': 'B_SPAN.b-1_SI',
- 'desc': 'query the "bold" value',
- 'pad': '<span class="b">foo[bar]baz</span>',
- 'expected': 'true' },
-
- { 'id': 'B_MYB-1-SI',
- 'desc': 'query the "bold" value',
- 'pad': '<myb>foo[bar]baz</myb>',
- 'expected': 'true' }
- ]
- },
-
- { 'desc': '[HTML5] query italic value',
- 'qcvalue': 'italic',
- 'tests': [
- { 'id': 'I_TEXT_SI',
- 'desc': 'query the "bold" value',
- 'pad': 'foo[bar]baz',
- 'expected': 'false' },
-
- { 'id': 'I_I-1_SI',
- 'desc': 'query the "bold" value',
- 'pad': '<i>foo[bar]baz</i>',
- 'expected': 'true' },
-
- { 'id': 'I_EM-1_SI',
- 'desc': 'query the "bold" value',
- 'pad': '<em>foo[bar]baz</em>',
- 'expected': 'true' },
-
- { 'id': 'I_SPANs:fs:i-1_SI',
- 'desc': 'query the "bold" value',
- 'pad': '<span style="font-style: italic">foo[bar]baz</span>',
- 'expected': 'true' },
-
- { 'id': 'I_SPANs:fs:n-1_SI',
- 'desc': 'query the "bold" value',
- 'pad': '<span style="font-style: normal">foo[bar]baz</span>',
- 'expected': 'false' },
-
- { 'id': 'I_I-SPANs:fs:n-1_SI',
- 'desc': 'query the "bold" value',
- 'pad': '<i><span style="font-style: normal">foo[bar]baz</span></i>',
- 'expected': 'false' },
-
- { 'id': 'I_SPAN.i-1_SI',
- 'desc': 'query the "italic" value',
- 'pad': '<span class="i">foo[bar]baz</span>',
- 'expected': 'true' },
-
- { 'id': 'I_MYI-1-SI',
- 'desc': 'query the "italic" value',
- 'pad': '<myi>foo[bar]baz</myi>',
- 'expected': 'true' }
- ]
- },
-
- { 'desc': '[HTML5] query block formatting value',
- 'qcvalue': 'formatblock',
- 'tests': [
- { 'id': 'FB_TEXT-1_SC',
- 'desc': 'query the "formatBlock" value',
- 'pad': 'foobar^baz',
- 'expected': '',
- 'accept': 'normal' },
-
- { 'id': 'FB_H1-1_SC',
- 'desc': 'query the "formatBlock" value',
- 'pad': '<h1>foobar^baz</h1>',
- 'expected': 'h1' },
-
- { 'id': 'FB_PRE-1_SC',
- 'desc': 'query the "formatBlock" value',
- 'pad': '<pre>foobar^baz</pre>',
- 'expected': 'pre' },
-
- { 'id': 'FB_BQ-1_SC',
- 'desc': 'query the "formatBlock" value',
- 'pad': '<blockquote>foobar^baz</blockquote>',
- 'expected': 'blockquote' },
-
- { 'id': 'FB_ADDRESS-1_SC',
- 'desc': 'query the "formatBlock" value',
- 'pad': '<address>foobar^baz</address>',
- 'expected': 'address' },
-
- { 'id': 'FB_H1-H2-1_SC',
- 'desc': 'query the "formatBlock" value',
- 'pad': '<h1>foo<h2>ba^r</h2>baz</h1>',
- 'expected': 'h2' },
-
- { 'id': 'FB_H1-H2-1_SL',
- 'desc': 'query the "formatBlock" value on oblique selection (outermost formatting expected)',
- 'pad': '<h1>fo[o<h2>ba]r</h2>baz</h1>',
- 'expected': 'h1' },
-
- { 'id': 'FB_H1-H2-1_SR',
- 'desc': 'query the "formatBlock" value on oblique selection (outermost formatting expected)',
- 'pad': '<h1>foo<h2>b[ar</h2>ba]z</h1>',
- 'expected': 'h1' },
-
- { 'id': 'FB_TEXT-ADDRESS-1_SL',
- 'desc': 'query the "formatBlock" value on oblique selection (outermost formatting expected)',
- 'pad': 'fo[o<ADDRESS>ba]r</ADDRESS>baz',
- 'expected': '',
- 'accept': 'normal' },
-
- { 'id': 'FB_TEXT-ADDRESS-1_SR',
- 'desc': 'query the "formatBlock" value on oblique selection (outermost formatting expected)',
- 'pad': 'foo<ADDRESS>b[ar</ADDRESS>ba]z',
- 'expected': '',
- 'accept': 'normal' },
-
- { 'id': 'FB_H1-H2.TEXT.H2-1_SM',
- 'desc': 'query the "formatBlock" value on oblique selection (outermost formatting expected)',
- 'pad': '<h1><h2>fo[o</h2>bar<h2>b]az</h2></h1>',
- 'expected': 'h1' }
- ]
- },
-
- { 'desc': '[MIDAS] query heading type',
- 'qcvalue': 'heading',
- 'tests': [
- { 'id': 'H_H1-1_SC',
- 'desc': 'query the "heading" type',
- 'pad': '<h1>foobar^baz</h1>',
- 'expected': 'h1',
- 'accept': '<h1>' },
-
- { 'id': 'H_H3-1_SC',
- 'desc': 'query the "heading" type',
- 'pad': '<h3>foobar^baz</h3>',
- 'expected': 'h3',
- 'accept': '<h3>' },
-
- { 'id': 'H_H1-H2-H3-H4-1_SC',
- 'desc': 'query the "heading" type within nested heading tags',
- 'pad': '<h1><h2><h3><h4>foobar^baz</h4></h3></h2></h1>',
- 'expected': 'h4',
- 'accept': '<h4>' },
-
- { 'id': 'H_P-1_SC',
- 'desc': 'query the "heading" type outside of a heading',
- 'pad': '<p>foobar^baz</p>',
- 'expected': '' }
- ]
- },
-
- { 'desc': '[MIDAS] query font name',
- 'qcvalue': 'fontname',
- 'tests': [
- { 'id': 'FN_FONTf:a-1_SI',
- 'rte1-id': 'q-fontname-0',
- 'desc': 'query the "fontname" value',
- 'pad': '<font face="arial">foo[bar]baz</font>',
- 'expected': 'arial' },
-
- { 'id': 'FN_SPANs:ff:a-1_SI',
- 'rte1-id': 'q-fontname-1',
- 'desc': 'query the "fontname" value',
- 'pad': '<span style="font-family: arial">foo[bar]baz</span>',
- 'expected': 'arial' },
-
- { 'id': 'FN_FONTf:a.s:ff:c-1_SI',
- 'rte1-id': 'q-fontname-2',
- 'desc': 'query the "fontname" value',
- 'pad': '<font face="arial" style="font-family: courier">foo[bar]baz</font>',
- 'expected': 'courier' },
-
- { 'id': 'FN_FONTf:a-FONTf:c-1_SI',
- 'rte1-id': 'q-fontname-3',
- 'desc': 'query the "fontname" value',
- 'pad': '<font face="arial"><font face="courier">foo[bar]baz</font></font>',
- 'expected': 'courier' },
-
- { 'id': 'FN_SPANs:ff:c-FONTf:a-1_SI',
- 'rte1-id': 'q-fontname-4',
- 'desc': 'query the "fontname" value',
- 'pad': '<span style="font-family: courier"><font face="arial">foo[bar]baz</font></span>',
- 'expected': 'arial' },
-
- { 'id': 'FN_SPAN.fs18px-1_SI',
- 'desc': 'query the "fontname" value',
- 'pad': '<span class="courier">foo[bar]baz</span>',
- 'expected': 'courier' },
-
- { 'id': 'FN_MYCOURIER-1-SI',
- 'desc': 'query the "fontname" value',
- 'pad': '<mycourier>foo[bar]baz</mycourier>',
- 'expected': 'courier' }
- ]
- },
-
- { 'desc': '[MIDAS] query font size',
- 'qcvalue': 'fontsize',
- 'tests': [
- { 'id': 'FS_FONTsz:4-1_SI',
- 'rte1-id': 'q-fontsize-0',
- 'desc': 'query the "fontsize" value',
- 'pad': '<font size=4>foo[bar]baz</font>',
- 'expected': '18px' },
-
- { 'id': 'FS_FONTs:fs:l-1_SI',
- 'desc': 'query the "fontsize" value',
- 'pad': '<font style="font-size: large">foo[bar]baz</font>',
- 'expected': '18px' },
-
- { 'id': 'FS_FONT.ass.s:fs:l-1_SI',
- 'rte1-id': 'q-fontsize-1',
- 'desc': 'query the "fontsize" value',
- 'pad': '<font class="Apple-style-span" style="font-size: large">foo[bar]baz</font>',
- 'expected': '18px' },
-
- { 'id': 'FS_FONTsz:1.s:fs:xl-1_SI',
- 'rte1-id': 'q-fontsize-2',
- 'desc': 'query the "fontsize" value',
- 'pad': '<font size=1 style="font-size: x-large">foo[bar]baz</font>',
- 'expected': '24px' },
-
- { 'id': 'FS_SPAN.large-1_SI',
- 'desc': 'query the "fontsize" value',
- 'pad': '<span class="large">foo[bar]baz</span>',
- 'expected': 'large' },
-
- { 'id': 'FS_SPAN.fs18px-1_SI',
- 'desc': 'query the "fontsize" value',
- 'pad': '<span class="fs18px">foo[bar]baz</span>',
- 'expected': '18px' },
-
- { 'id': 'FA_MYLARGE-1-SI',
- 'desc': 'query the "fontsize" value',
- 'pad': '<mylarge>foo[bar]baz</mylarge>',
- 'expected': 'large' },
-
- { 'id': 'FA_MYFS18PX-1-SI',
- 'desc': 'query the "fontsize" value',
- 'pad': '<myfs18px>foo[bar]baz</myfs18px>',
- 'expected': '18px' }
- ]
- },
-
- { 'desc': '[MIDAS] query background color',
- 'qcvalue': 'backcolor',
- 'tests': [
- { 'id': 'BC_FONTs:bc:fca-1_SI',
- 'rte1-id': 'q-backcolor-0',
- 'desc': 'query the "backcolor" value',
- 'pad': '<font style="background-color: #ffccaa">foo[bar]baz</font>',
- 'expected': '#ffccaa' },
-
- { 'id': 'BC_SPANs:bc:abc-1_SI',
- 'rte1-id': 'q-backcolor-2',
- 'desc': 'query the "backcolor" value',
- 'pad': '<span style="background-color: #aabbcc">foo[bar]baz</span>',
- 'expected': '#aabbcc' },
-
- { 'id': 'BC_FONTs:bc:084-SPAN-1_SI',
- 'desc': 'query the "backcolor" value, where the color was set on an ancestor',
- 'pad': '<font style="background-color: #008844"><span>foo[bar]baz</span></font>',
- 'expected': '#008844' },
-
- { 'id': 'BC_SPANs:bc:cde-SPAN-1_SI',
- 'desc': 'query the "backcolor" value, where the color was set on an ancestor',
- 'pad': '<span style="background-color: #ccddee"><span>foo[bar]baz</span></span>',
- 'expected': '#ccddee' },
-
- { 'id': 'BC_SPAN.ass.s:bc:rgb-1_SI',
- 'rte1-id': 'q-backcolor-1',
- 'desc': 'query the "backcolor" value',
- 'pad': '<span class="Apple-style-span" style="background-color: rgb(255, 0, 0)">foo[bar]baz</span>',
- 'expected': '#ff0000' },
-
- { 'id': 'BC_SPAN.bcred-1_SI',
- 'desc': 'query the "backcolor" value',
- 'pad': '<span class="bcred">foo[bar]baz</span>',
- 'expected': 'red' },
-
- { 'id': 'BC_MYBCRED-1-SI',
- 'desc': 'query the "backcolor" value',
- 'pad': '<mybcred>foo[bar]baz</mybcred>',
- 'expected': 'red' }
- ]
- },
-
- { 'desc': '[MIDAS] query text color',
- 'qcvalue': 'forecolor',
- 'tests': [
- { 'id': 'FC_FONTc:f00-1_SI',
- 'rte1-id': 'q-forecolor-0',
- 'desc': 'query the "forecolor" value',
- 'pad': '<font color="#ff0000">foo[bar]baz</font>',
- 'expected': '#ff0000' },
-
- { 'id': 'FC_SPANs:c:0f0-1_SI',
- 'rte1-id': 'q-forecolor-1',
- 'desc': 'query the "forecolor" value',
- 'pad': '<span style="color: #00ff00">foo[bar]baz</span>',
- 'expected': '#00ff00' },
-
- { 'id': 'FC_FONTc:333.s:c:999-1_SI',
- 'rte1-id': 'q-forecolor-2',
- 'desc': 'query the "forecolor" value',
- 'pad': '<font color="#333333" style="color: #999999">foo[bar]baz</font>',
- 'expected': '#999999' },
-
- { 'id': 'FC_FONTc:641-SPAN-1_SI',
- 'desc': 'query the "forecolor" value, where the color was set on an ancestor',
- 'pad': '<font color="#664411"><span>foo[bar]baz</span></font>',
- 'expected': '#664411' },
-
- { 'id': 'FC_SPANs:c:d95-SPAN-1_SI',
- 'desc': 'query the "forecolor" value, where the color was set on an ancestor',
- 'pad': '<span style="color: #dd9955"><span>foo[bar]baz</span></span>',
- 'expected': '#dd9955' },
-
- { 'id': 'FC_SPAN.red-1_SI',
- 'desc': 'query the "forecolor" value',
- 'pad': '<span class="red">foo[bar]baz</span>',
- 'expected': 'red' },
-
- { 'id': 'FC_MYRED-1-SI',
- 'desc': 'query the "forecolor" value',
- 'pad': '<myred>foo[bar]baz</myred>',
- 'expected': 'red' }
- ]
- },
-
- { 'desc': '[MIDAS] query hilight color (same as background color)',
- 'qcvalue': 'hilitecolor',
- 'tests': [
- { 'id': 'HC_FONTs:bc:fc0-1_SI',
- 'rte1-id': 'q-hilitecolor-0',
- 'desc': 'query the "hilitecolor" value',
- 'pad': '<font style="background-color: #ffcc00">foo[bar]baz</font>',
- 'expected': '#ffcc00' },
-
- { 'id': 'HC_SPANs:bc:a0c-1_SI',
- 'rte1-id': 'q-hilitecolor-2',
- 'desc': 'query the "hilitecolor" value',
- 'pad': '<span style="background-color: #aa00cc">foo[bar]baz</span>',
- 'expected': '#aa00cc' },
-
- { 'id': 'HC_SPAN.ass.s:bc:rgb-1_SI',
- 'rte1-id': 'q-hilitecolor-1',
- 'desc': 'query the "hilitecolor" value',
- 'pad': '<span class="Apple-style-span" style="background-color: rgb(255, 0, 0)">foo[bar]baz</span>',
- 'expected': '#ff0000' },
-
- { 'id': 'HC_FONTs:bc:83e-SPAN-1_SI',
- 'desc': 'query the "hilitecolor" value, where the color was set on an ancestor',
- 'pad': '<font style="background-color: #8833ee"><span>foo[bar]baz</span></font>',
- 'expected': '#8833ee' },
-
- { 'id': 'HC_SPANs:bc:b12-SPAN-1_SI',
- 'desc': 'query the "hilitecolor" value, where the color was set on an ancestor',
- 'pad': '<span style="background-color: #bb1122"><span>foo[bar]baz</span></span>',
- 'expected': '#bb1122' },
-
- { 'id': 'HC_SPAN.bcred-1_SI',
- 'desc': 'query the "hilitecolor" value',
- 'pad': '<span class="bcred">foo[bar]baz</span>',
- 'expected': 'red' },
-
- { 'id': 'HC_MYBCRED-1-SI',
- 'desc': 'query the "hilitecolor" value',
- 'pad': '<mybcred>foo[bar]baz</mybcred>',
- 'expected': 'red' }
- ]
- }
- ]
-}
-
-QUERYVALUE_TESTS_CSS = {
- 'id': 'QVC',
- 'caption': 'queryCommandValue Tests, using styleWithCSS',
- 'checkAttrs': False,
- 'checkStyle': False,
- 'styleWithCSS': True,
-
- 'Proposed': QUERYVALUE_TESTS['Proposed']
-}
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/selection.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/selection.py
deleted file mode 100644
index 35891386a..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/selection.py
+++ /dev/null
@@ -1,772 +0,0 @@
-
-SELECTION_TESTS = {
- 'id': 'S',
- 'caption': 'Selection Tests',
- 'checkAttrs': True,
- 'checkStyle': True,
- 'styleWithCSS': False,
-
- 'Proposed': [
- { 'desc': '',
- 'command': '',
- 'tests': [
- ]
- },
-
- { 'desc': 'selectall',
- 'command': 'selectall',
- 'tests': [
- { 'id': 'SELALL_TEXT-1_SI',
- 'desc': 'select all, text only',
- 'pad': 'foo [bar] baz',
- 'expected': [ '[foo bar baz]',
- '{foo bar baz}' ] },
-
- { 'id': 'SELALL_I-1_SI',
- 'desc': 'select all, with outer tags',
- 'pad': '<i>foo [bar] baz</i>',
- 'expected': '{<i>foo bar baz</i>}' }
- ]
- },
-
- { 'desc': 'unselect',
- 'command': 'unselect',
- 'tests': [
- { 'id': 'UNSEL_TEXT-1_SI',
- 'desc': 'unselect',
- 'pad': 'foo [bar] baz',
- 'expected': 'foo bar baz' }
- ]
- },
-
- { 'desc': 'sel.modify (generic)',
- 'tests': [
- { 'id': 'SM:m.f.c_TEXT-1_SC-1',
- 'desc': 'move caret 1 character forward',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': 'foo b^ar baz',
- 'expected': 'foo ba^r baz' },
-
- { 'id': 'SM:m.b.c_TEXT-1_SC-1',
- 'desc': 'move caret 1 character backward',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': 'foo b^ar baz',
- 'expected': 'foo ^bar baz' },
-
- { 'id': 'SM:m.f.c_TEXT-1_SI-1',
- 'desc': 'move caret forward (sollapse selection)',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': 'foo [bar] baz',
- 'expected': 'foo bar^ baz' },
-
- { 'id': 'SM:m.b.c_TEXT-1_SI-1',
- 'desc': 'move caret backward (collapse selection)',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': 'foo [bar] baz',
- 'expected': 'foo ^bar baz' },
-
- { 'id': 'SM:m.f.w_TEXT-1_SC-1',
- 'desc': 'move caret 1 word forward',
- 'function': 'sel.modify("move", "forward", "word");',
- 'pad': 'foo b^ar baz',
- 'expected': 'foo bar^ baz' },
-
- { 'id': 'SM:m.f.w_TEXT-1_SC-2',
- 'desc': 'move caret 1 word forward',
- 'function': 'sel.modify("move", "forward", "word");',
- 'pad': 'foo^ bar baz',
- 'expected': 'foo bar^ baz' },
-
- { 'id': 'SM:m.f.w_TEXT-1_SI-1',
- 'desc': 'move caret 1 word forward from non-collapsed selection',
- 'function': 'sel.modify("move", "forward", "word");',
- 'pad': 'foo [bar] baz',
- 'expected': 'foo bar baz^' },
-
- { 'id': 'SM:m.b.w_TEXT-1_SC-1',
- 'desc': 'move caret 1 word backward',
- 'function': 'sel.modify("move", "backward", "word");',
- 'pad': 'foo b^ar baz',
- 'expected': 'foo ^bar baz' },
-
- { 'id': 'SM:m.b.w_TEXT-1_SC-3',
- 'desc': 'move caret 1 word backward',
- 'function': 'sel.modify("move", "backward", "word");',
- 'pad': 'foo bar ^baz',
- 'expected': 'foo ^bar baz' },
-
- { 'id': 'SM:m.b.w_TEXT-1_SI-1',
- 'desc': 'move caret 1 word backward from non-collapsed selection',
- 'function': 'sel.modify("move", "backward", "word");',
- 'pad': 'foo [bar] baz',
- 'expected': '^foo bar baz' }
- ]
- },
-
- { 'desc': 'sel.modify: move forward over combining diacritics, etc.',
- 'tests': [
- { 'id': 'SM:m.f.c_CHAR-2_SC-1',
- 'desc': 'move 1 character forward over combined o with diaeresis',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': 'fo^&#xF6;barbaz',
- 'expected': 'fo&#xF6;^barbaz' },
-
- { 'id': 'SM:m.f.c_CHAR-3_SC-1',
- 'desc': 'move 1 character forward over character with combining diaeresis above',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': 'fo^o&#x0308;barbaz',
- 'expected': 'foo&#x0308;^barbaz' },
-
- { 'id': 'SM:m.f.c_CHAR-4_SC-1',
- 'desc': 'move 1 character forward over character with combining diaeresis below',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': 'fo^o&#x0324;barbaz',
- 'expected': 'foo&#x0324;^barbaz' },
-
- { 'id': 'SM:m.f.c_CHAR-5_SC-1',
- 'desc': 'move 1 character forward over character with combining diaeresis above and below',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': 'fo^o&#x0308;&#x0324;barbaz',
- 'expected': 'foo&#x0308;&#x0324;^barbaz' },
-
- { 'id': 'SM:m.f.c_CHAR-5_SI-1',
- 'desc': 'move 1 character forward over character with combining diaeresis above and below, selection on diaeresis above',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': 'foo[&#x0308;]&#x0324;barbaz',
- 'expected': 'foo&#x0308;&#x0324;^barbaz' },
-
- { 'id': 'SM:m.f.c_CHAR-5_SI-2',
- 'desc': 'move 1 character forward over character with combining diaeresis above and below, selection on diaeresis below',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': 'foo&#x0308;[&#x0324;]barbaz',
- 'expected': 'foo&#x0308;&#x0324;^barbaz' },
-
- { 'id': 'SM:m.f.c_CHAR-5_SL',
- 'desc': 'move 1 character forward over character with combining diaeresis above and below, selection oblique on diaeresis and preceding text',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': 'fo[o&#x0308;]&#x0324;barbaz',
- 'expected': 'foo&#x0308;&#x0324;^barbaz' },
-
- { 'id': 'SM:m.f.c_CHAR-5_SR',
- 'desc': 'move 1 character forward over character with combining diaeresis above and below, selection oblique on diaeresis and following text',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': 'foo&#x0308;[&#x0324;bar]baz',
- 'expected': 'foo&#x0308;&#x0324;bar^baz' },
-
- { 'id': 'SM:m.f.c_CHAR-6_SC-1',
- 'desc': 'move 1 character forward over character with enclosing square',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': 'fo^o&#x20DE;barbaz',
- 'expected': 'foo&#x20DE;^barbaz' },
-
- { 'id': 'SM:m.f.c_CHAR-7_SC-1',
- 'desc': 'move 1 character forward over character with combining long solidus overlay',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': 'fo^o&#x0338;barbaz',
- 'expected': 'foo&#x0338;^barbaz' }
- ]
- },
-
- { 'desc': 'sel.modify: move backward over combining diacritics, etc.',
- 'tests': [
- { 'id': 'SM:m.b.c_CHAR-2_SC-1',
- 'desc': 'move 1 character backward over combined o with diaeresis',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': 'fo&#xF6;^barbaz',
- 'expected': 'fo^&#xF6;barbaz' },
-
- { 'id': 'SM:m.b.c_CHAR-3_SC-1',
- 'desc': 'move 1 character backward over character with combining diaeresis above',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': 'foo&#x0308;^barbaz',
- 'expected': 'fo^o&#x0308;barbaz' },
-
- { 'id': 'SM:m.b.c_CHAR-4_SC-1',
- 'desc': 'move 1 character backward over character with combining diaeresis below',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': 'foo&#x0324;^barbaz',
- 'expected': 'fo^o&#x0324;barbaz' },
-
- { 'id': 'SM:m.b.c_CHAR-5_SC-1',
- 'desc': 'move 1 character backward over character with combining diaeresis above and below',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': 'foo&#x0308;&#x0324;^barbaz',
- 'expected': 'fo^o&#x0308;&#x0324;barbaz' },
-
- { 'id': 'SM:m.b.c_CHAR-5_SI-1',
- 'desc': 'move 1 character backward over character with combining diaeresis above and below, selection on diaeresis above',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': 'foo[&#x0308;]&#x0324;barbaz',
- 'expected': 'fo^o&#x0308;&#x0324;barbaz' },
-
- { 'id': 'SM:m.b.c_CHAR-5_SI-2',
- 'desc': 'move 1 character backward over character with combining diaeresis above and below, selection on diaeresis below',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': 'foo&#x0308;[&#x0324;]barbaz',
- 'expected': 'fo^o&#x0308;&#x0324;barbaz' },
-
- { 'id': 'SM:m.b.c_CHAR-5_SL',
- 'desc': 'move 1 character backward over character with combining diaeresis above and below, selection oblique on diaeresis and preceding text',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': 'fo[o&#x0308;]&#x0324;barbaz',
- 'expected': 'fo^o&#x0308;&#x0324;barbaz' },
-
- { 'id': 'SM:m.b.c_CHAR-5_SR',
- 'desc': 'move 1 character backward over character with combining diaeresis above and below, selection oblique on diaeresis and following text',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': 'foo&#x0308;[&#x0324;bar]baz',
- 'expected': 'fo^o&#x0308;&#x0324;barbaz' },
-
- { 'id': 'SM:m.b.c_CHAR-6_SC-1',
- 'desc': 'move 1 character backward over character with enclosing square',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': 'foo&#x20DE;^barbaz',
- 'expected': 'fo^o&#x20DE;barbaz' },
-
- { 'id': 'SM:m.b.c_CHAR-7_SC-1',
- 'desc': 'move 1 character backward over character with combining long solidus overlay',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': 'foo&#x0338;^barbaz',
- 'expected': 'fo^o&#x0338;barbaz' }
- ]
- },
-
- { 'desc': 'sel.modify: move forward/backward/left/right in RTL text',
- 'tests': [
- { 'id': 'SM:m.f.c_Pdir:rtl-1_SC-1',
- 'desc': 'move caret forward 1 character in right-to-left text',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': '<p dir="rtl">foo b^ar baz</p>',
- 'expected': '<p dir="rtl">foo ba^r baz</p>' },
-
- { 'id': 'SM:m.b.c_Pdir:rtl-1_SC-1',
- 'desc': 'move caret backward 1 character in right-to-left text',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': '<p dir="rtl">foo ba^r baz</p>',
- 'expected': '<p dir="rtl">foo b^ar baz</p>' },
-
- { 'id': 'SM:m.r.c_Pdir:rtl-1_SC-1',
- 'desc': 'move caret 1 character to the right in LTR text within RTL context',
- 'function': 'sel.modify("move", "right", "character");',
- 'pad': '<p dir="rtl">foo b^ar baz</p>',
- 'expected': '<p dir="rtl">foo ba^r baz</p>' },
-
- { 'id': 'SM:m.l.c_Pdir:rtl-1_SC-1',
- 'desc': 'move caret 1 character to the left in LTR text within RTL context',
- 'function': 'sel.modify("move", "left", "character");',
- 'pad': '<p dir="rtl">foo ba^r baz</p>',
- 'expected': '<p dir="rtl">foo b^ar baz</p>' },
-
-
- { 'id': 'SM:m.f.c_TEXT:ar-1_SC-1',
- 'desc': 'move caret forward 1 character in Arabic text',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': '&#1605;&#x0631;&#1581;^&#1576;&#x0627; &#x0627;&#1604;&#x0639;&#x0627;&#1604;&#1605;',
- 'expected': '&#1605;&#x0631;&#1581;&#1576;^&#x0627; &#x0627;&#1604;&#x0639;&#x0627;&#1604;&#1605;' },
-
- { 'id': 'SM:m.b.c_TEXT:ar-1_SC-1',
- 'desc': 'move caret backward 1 character in Arabic text',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': '&#1605;&#x0631;&#1581;^&#1576;&#x0627; &#x0627;&#1604;&#x0639;&#x0627;&#1604;&#1605;',
- 'expected': '&#1605;&#x0631;^&#1581;&#1576;&#x0627; &#x0627;&#1604;&#x0639;&#x0627;&#1604;&#1605;' },
-
- { 'id': 'SM:m.f.c_TEXT:he-1_SC-1',
- 'desc': 'move caret forward 1 character in Hebrew text',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': '&#x05E9;&#x05DC;^&#x05D5;&#x05DD; &#x05E2;&#x05D5;&#x05DC;&#x05DD;',
- 'expected': '&#x05E9;&#x05DC;&#x05D5;^&#x05DD; &#x05E2;&#x05D5;&#x05DC;&#x05DD;' },
-
- { 'id': 'SM:m.b.c_TEXT:he-1_SC-1',
- 'desc': 'move caret backward 1 character in Hebrew text',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': '&#x05E9;&#x05DC;^&#x05D5;&#x05DD; &#x05E2;&#x05D5;&#x05DC;&#x05DD;',
- 'expected': '&#x05E9;^&#x05DC;&#x05D5;&#x05DD; &#x05E2;&#x05D5;&#x05DC;&#x05DD;' },
-
-
- { 'id': 'SM:m.f.c_BDOdir:rtl-1_SC-1',
- 'desc': 'move caret forward 1 character inside <bdo>',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': 'foo <bdo dir="rtl">b^ar</bdo> baz',
- 'expected': 'foo <bdo dir="rtl">ba^r</bdo> baz' },
-
- { 'id': 'SM:m.b.c_BDOdir:rtl-1_SC-1',
- 'desc': 'move caret backward 1 character inside <bdo>',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': 'foo <bdo dir="rtl">ba^r</bdo> baz',
- 'expected': 'foo <bdo dir="rtl">b^ar</bdo> baz' },
-
- { 'id': 'SM:m.r.c_BDOdir:rtl-1_SC-1',
- 'desc': 'move caret 1 character to the right inside <bdo>',
- 'function': 'sel.modify("move", "right", "character");',
- 'pad': 'foo <bdo dir="rtl">ba^r</bdo> baz',
- 'expected': 'foo <bdo dir="rtl">b^ar</bdo> baz' },
-
- { 'id': 'SM:m.l.c_BDOdir:rtl-1_SC-1',
- 'desc': 'move caret 1 character to the left inside <bdo>',
- 'function': 'sel.modify("move", "left", "character");',
- 'pad': 'foo <bdo dir="rtl">b^ar</bdo> baz',
- 'expected': 'foo <bdo dir="rtl">ba^r</bdo> baz' },
-
-
- { 'id': 'SM:m.f.c_TEXTrle-1_SC-rtl-1',
- 'desc': 'move caret forward in RTL text within RLE-PDF marks',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': 'I said, "(RLE)&#x202B;car &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;^&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".',
- 'expected': 'I said, "(RLE)&#x202B;car &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;^&#x0631;&#x0629;&#x202C;(PDF)".' },
-
- { 'id': 'SM:m.b.c_TEXTrle-1_SC-rtl-1',
- 'desc': 'move caret backward in RTL text within RLE-PDF marks',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': 'I said, "(RLE)&#x202B;car &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;^&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".',
- 'expected': 'I said, "(RLE)&#x202B;car &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;^&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".' },
-
- { 'id': 'SM:m.r.c_TEXTrle-1_SC-rtl-1',
- 'desc': 'move caret 1 character to the right in RTL text within RLE-PDF marks',
- 'function': 'sel.modify("move", "right", "character");',
- 'pad': 'I said, "(RLE)&#x202B;car &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;^&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".',
- 'expected': 'I said, "(RLE)&#x202B;car &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;^&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".' },
-
- { 'id': 'SM:m.l.c_TEXTrle-1_SC-rtl-1',
- 'desc': 'move caret 1 character to the left in RTL text within RLE-PDF marks',
- 'function': 'sel.modify("move", "left", "character");',
- 'pad': 'I said, "(RLE)&#x202B;car &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;^&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".',
- 'expected': 'I said, "(RLE)&#x202B;car &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;^&#x0631;&#x0629;&#x202C;(PDF)".' },
-
- { 'id': 'SM:m.f.c_TEXTrle-1_SC-ltr-1',
- 'desc': 'move caret forward in LTR text within RLE-PDF marks',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': 'I said, "(RLE)&#x202B;c^ar &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".',
- 'expected': 'I said, "(RLE)&#x202B;ca^r &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".' },
-
- { 'id': 'SM:m.b.c_TEXTrle-1_SC-ltr-1',
- 'desc': 'move caret backward in LTR text within RLE-PDF marks',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': 'I said, "(RLE)&#x202B;ca^r &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".',
- 'expected': 'I said, "(RLE)&#x202B;c^ar &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".' },
-
- { 'id': 'SM:m.r.c_TEXTrle-1_SC-ltr-1',
- 'desc': 'move caret 1 character to the right in LTR text within RLE-PDF marks',
- 'function': 'sel.modify("move", "right", "character");',
- 'pad': 'I said, "(RLE)&#x202B;c^ar &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".',
- 'expected': 'I said, "(RLE)&#x202B;ca^r &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".' },
-
- { 'id': 'SM:m.l.c_TEXTrle-1_SC-ltr-1',
- 'desc': 'move caret 1 character to the left in LTR text within RLE-PDF marks',
- 'function': 'sel.modify("move", "left", "character");',
- 'pad': 'I said, "(RLE)&#x202B;ca^r &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".',
- 'expected': 'I said, "(RLE)&#x202B;c^ar &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".' },
-
-
- { 'id': 'SM:m.f.c_TEXTrlo-1_SC-rtl-1',
- 'desc': 'move caret forward in RTL text within RLO-PDF marks',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': 'I said, "(RLO)&#x202E;car &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;^&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".',
- 'expected': 'I said, "(RLO)&#x202E;car &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;^&#x0631;&#x0629;&#x202C;(PDF)".' },
-
- { 'id': 'SM:m.b.c_TEXTrlo-1_SC-rtl-1',
- 'desc': 'move caret backward in RTL text within RLO-PDF marks',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': 'I said, "(RLO)&#x202E;car &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;^&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".',
- 'expected': 'I said, "(RLO)&#x202E;car &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;^&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".' },
-
- { 'id': 'SM:m.r.c_TEXTrlo-1_SC-rtl-1',
- 'desc': 'move caret 1 character to the right in RTL text within RLO-PDF marks',
- 'function': 'sel.modify("move", "right", "character");',
- 'pad': 'I said, "(RLO)&#x202E;car &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;^&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".',
- 'expected': 'I said, "(RLO)&#x202E;car &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;^&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".' },
-
- { 'id': 'SM:m.l.c_TEXTrlo-1_SC-rtl-1',
- 'desc': 'move caret 1 character to the left in RTL text within RLO-PDF marks',
- 'function': 'sel.modify("move", "left", "character");',
- 'pad': 'I said, "(RLO)&#x202E;car &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;^&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".',
- 'expected': 'I said, "(RLO)&#x202E;car &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;^&#x0631;&#x0629;&#x202C;(PDF)".' },
-
- { 'id': 'SM:m.f.c_TEXTrlo-1_SC-ltr-1',
- 'desc': 'move caret forward in Latin text within RLO-PDF marks',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': 'I said, "(RLO)&#x202E;c^ar &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".',
- 'expected': 'I said, "(RLO)&#x202E;ca^r &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".' },
-
- { 'id': 'SM:m.b.c_TEXTrlo-1_SC-ltr-1',
- 'desc': 'move caret backward in Latin text within RLO-PDF marks',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': 'I said, "(RLO)&#x202E;ca^r &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".',
- 'expected': 'I said, "(RLO)&#x202E;c^ar &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".' },
-
- { 'id': 'SM:m.r.c_TEXTrlo-1_SC-ltr-1',
- 'desc': 'move caret 1 character to the right in Latin text within RLO-PDF marks',
- 'function': 'sel.modify("move", "right", "character");',
- 'pad': 'I said, "(RLO)&#x202E;ca^r &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".',
- 'expected': 'I said, "(RLO)&#x202E;c^ar &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".' },
-
- { 'id': 'SM:m.l.c_TEXTrlo-1_SC-ltr-1',
- 'desc': 'move caret 1 character to the left in Latin text within RLO-PDF marks',
- 'function': 'sel.modify("move", "left", "character");',
- 'pad': 'I said, "(RLO)&#x202E;c^ar &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".',
- 'expected': 'I said, "(RLO)&#x202E;ca^r &#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;&#x202C;(PDF)".' },
-
-
- { 'id': 'SM:m.f.c_TEXTrlm-1_SC-1',
- 'desc': 'move caret forward in RTL text within neutral characters followed by RLM',
- 'function': 'sel.modify("move", "forward", "character");',
- 'pad': 'I said, "&#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;!^?!&#x200F;(RLM)".',
- 'expected': 'I said, "&#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;!?^!&#x200F;(RLM)".' },
-
- { 'id': 'SM:m.b.c_TEXTrlm-1_SC-1',
- 'desc': 'move caret backward in RTL text within neutral characters followed by RLM',
- 'function': 'sel.modify("move", "backward", "character");',
- 'pad': 'I said, "&#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;!?^!&#x200F;(RLM)".',
- 'expected': 'I said, "&#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;!^?!&#x200F;(RLM)".' },
-
- { 'id': 'SM:m.r.c_TEXTrlm-1_SC-1',
- 'desc': 'move caret 1 character to the right in RTL text within neutral characters followed by RLM',
- 'function': 'sel.modify("move", "right", "character");',
- 'pad': 'I said, "&#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;!?^!&#x200F;(RLM)".',
- 'expected': 'I said, "&#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;!^?!&#x200F;(RLM)".' },
-
- { 'id': 'SM:m.l.c_TEXTrlm-1_SC-1',
- 'desc': 'move caret 1 character to the left in RTL text within neutral characters followed by RLM',
- 'function': 'sel.modify("move", "left", "character");',
- 'pad': 'I said, "&#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;!^?!&#x200F;(RLM)".',
- 'expected': 'I said, "&#x064A;&#x0639;&#x0646;&#x064A; &#x0633;&#x064A;&#x0627;&#x0631;&#x0629;!?^!&#x200F;(RLM)".' }
- ]
- },
-
- { 'desc': 'sel.modify: move forward/backward over words in Japanese text',
- 'tests': [
- { 'id': 'SM:m.f.w_TEXT-jp_SC-1',
- 'desc': 'move caret forward 1 word in Japanese text (adjective)',
- 'function': 'sel.modify("move", "forward", "word");',
- 'pad': '^&#x9762;&#x767D;&#x3044;&#x4F8B;&#x6587;&#x3092;&#x30C6;&#x30B9;&#x30C8;&#x3057;&#x307E;&#x3057;&#x3087;&#x3046;&#x3002;',
- 'expected': '&#x9762;&#x767D;&#x3044;^&#x4F8B;&#x6587;&#x3092;&#x30C6;&#x30B9;&#x30C8;&#x3057;&#x307E;&#x3057;&#x3087;&#x3046;&#x3002;' },
-
- { 'id': 'SM:m.f.w_TEXT-jp_SC-2',
- 'desc': 'move caret forward 1 word in Japanese text (in the middle of a word)',
- 'function': 'sel.modify("move", "forward", "word");',
- 'pad': '&#x9762;^&#x767D;&#x3044;&#x4F8B;&#x6587;&#x3092;&#x30C6;&#x30B9;&#x30C8;&#x3057;&#x307E;&#x3057;&#x3087;&#x3046;&#x3002;',
- 'expected': '&#x9762;&#x767D;&#x3044;^&#x4F8B;&#x6587;&#x3092;&#x30C6;&#x30B9;&#x30C8;&#x3057;&#x307E;&#x3057;&#x3087;&#x3046;&#x3002;' },
-
- { 'id': 'SM:m.f.w_TEXT-jp_SC-3',
- 'desc': 'move caret forward 1 word in Japanese text (noun)',
- 'function': 'sel.modify("move", "forward", "word");',
- 'pad': '&#x9762;&#x767D;&#x3044;^&#x4F8B;&#x6587;&#x3092;&#x30C6;&#x30B9;&#x30C8;&#x3057;&#x307E;&#x3057;&#x3087;&#x3046;&#x3002;',
- 'expected': [ '&#x9762;&#x767D;&#x3044;&#x4F8B;&#x6587;^&#x3092;&#x30C6;&#x30B9;&#x30C8;&#x3057;&#x307E;&#x3057;&#x3087;&#x3046;&#x3002;',
- '&#x9762;&#x767D;&#x3044;&#x4F8B;&#x6587;&#x3092;^&#x30C6;&#x30B9;&#x30C8;&#x3057;&#x307E;&#x3057;&#x3087;&#x3046;&#x3002;' ] },
-
- { 'id': 'SM:m.f.w_TEXT-jp_SC-4',
- 'desc': 'move caret forward 1 word in Japanese text (Katakana)',
- 'function': 'sel.modify("move", "forward", "word");',
- 'pad': '&#x9762;&#x767D;&#x3044;&#x4F8B;&#x6587;&#x3092;^&#x30C6;&#x30B9;&#x30C8;&#x3057;&#x307E;&#x3057;&#x3087;&#x3046;&#x3002;',
- 'expected': '&#x9762;&#x767D;&#x3044;&#x4F8B;&#x6587;&#x3092;&#x30C6;&#x30B9;&#x30C8;^&#x3057;&#x307E;&#x3057;&#x3087;&#x3046;&#x3002;' },
-
- { 'id': 'SM:m.f.w_TEXT-jp_SC-5',
- 'desc': 'move caret forward 1 word in Japanese text (verb)',
- 'function': 'sel.modify("move", "forward", "word");',
- 'pad': '&#x9762;&#x767D;&#x3044;&#x4F8B;&#x6587;&#x3092;&#x30C6;&#x30B9;&#x30C8;^&#x3057;&#x307E;&#x3057;&#x3087;&#x3046;&#x3002;',
- 'expected': '&#x9762;&#x767D;&#x3044;&#x4F8B;&#x6587;&#x3092;&#x30C6;&#x30B9;&#x30C8;&#x3057;&#x307E;&#x3057;&#x3087;&#x3046;^&#x3002;' }
- ]
- },
-
- { 'desc': 'sel.modify: extend selection forward',
- 'tests': [
- { 'id': 'SM:e.f.c_TEXT-1_SC-1',
- 'desc': 'extend selection 1 character forward',
- 'function': 'sel.modify("extend", "forward", "character");',
- 'pad': 'foo ^bar baz',
- 'expected': 'foo [b]ar baz' },
-
- { 'id': 'SM:e.f.c_TEXT-1_SI-1',
- 'desc': 'extend selection 1 character forward',
- 'function': 'sel.modify("extend", "forward", "character");',
- 'pad': 'foo [b]ar baz',
- 'expected': 'foo [ba]r baz' },
-
- { 'id': 'SM:e.f.w_TEXT-1_SC-1',
- 'desc': 'extend selection 1 word forward',
- 'function': 'sel.modify("extend", "forward", "word");',
- 'pad': 'foo ^bar baz',
- 'expected': 'foo [bar] baz' },
-
- { 'id': 'SM:e.f.w_TEXT-1_SI-1',
- 'desc': 'extend selection 1 word forward',
- 'function': 'sel.modify("extend", "forward", "word");',
- 'pad': 'foo [b]ar baz',
- 'expected': 'foo [bar] baz' },
-
- { 'id': 'SM:e.f.w_TEXT-1_SI-2',
- 'desc': 'extend selection 1 word forward',
- 'function': 'sel.modify("extend", "forward", "word");',
- 'pad': 'foo [bar] baz',
- 'expected': 'foo [bar baz]' }
- ]
- },
-
- { 'desc': 'sel.modify: extend selection backward, shrinking it',
- 'tests': [
- { 'id': 'SM:e.b.c_TEXT-1_SI-2',
- 'desc': 'extend selection 1 character backward',
- 'function': 'sel.modify("extend", "backward", "character");',
- 'pad': 'foo [bar] baz',
- 'expected': 'foo [ba]r baz' },
-
- { 'id': 'SM:e.b.c_TEXT-1_SI-1',
- 'desc': 'extend selection 1 character backward',
- 'function': 'sel.modify("extend", "backward", "character");',
- 'pad': 'foo [b]ar baz',
- 'expected': 'foo ^bar baz' },
-
- { 'id': 'SM:e.b.w_TEXT-1_SI-3',
- 'desc': 'extend selection 1 word backward',
- 'function': 'sel.modify("extend", "backward", "word");',
- 'pad': 'foo [bar baz]',
- 'expected': 'foo [bar] baz' },
-
- { 'id': 'SM:e.b.w_TEXT-1_SI-2',
- 'desc': 'extend selection 1 word backward',
- 'function': 'sel.modify("extend", "backward", "word");',
- 'pad': 'foo [bar] baz',
- 'expected': 'foo ^bar baz' },
-
- { 'id': 'SM:e.b.w_TEXT-1_SI-4',
- 'desc': 'extend selection 1 word backward',
- 'function': 'sel.modify("extend", "backward", "word");',
- 'pad': 'foo b[ar baz]',
- 'expected': 'foo b[ar] baz' },
-
- { 'id': 'SM:e.b.w_TEXT-1_SI-5',
- 'desc': 'extend selection 1 word backward',
- 'function': 'sel.modify("extend", "backward", "word");',
- 'pad': 'foo b[ar] baz',
- 'expected': 'foo b^ar baz' }
- ]
- },
-
- { 'desc': 'sel.modify: extend selection backward, creating or extending a reverse selections',
- 'tests': [
- { 'id': 'SM:e.b.c_TEXT-1_SC-1',
- 'desc': 'extend selection 1 character backward',
- 'function': 'sel.modify("extend", "backward", "character");',
- 'pad': 'foo b^ar baz',
- 'expected': 'foo ]b[ar baz' },
-
- { 'id': 'SM:e.b.c_TEXT-1_SIR-1',
- 'desc': 'extend selection 1 character backward',
- 'function': 'sel.modify("extend", "backward", "character");',
- 'pad': 'foo b]a[r baz',
- 'expected': 'foo ]ba[r baz' },
-
- { 'id': 'SM:e.b.w_TEXT-1_SIR-1',
- 'desc': 'extend selection 1 word backward',
- 'function': 'sel.modify("extend", "backward", "word");',
- 'pad': 'foo b]a[r baz',
- 'expected': 'foo ]ba[r baz' },
-
- { 'id': 'SM:e.b.w_TEXT-1_SIR-2',
- 'desc': 'extend selection 1 word backward',
- 'function': 'sel.modify("extend", "backward", "word");',
- 'pad': 'foo ]ba[r baz',
- 'expected': ']foo ba[r baz' }
- ]
- },
-
- { 'desc': 'sel.modify: extend selection forward, shrinking a reverse selections',
- 'tests': [
- { 'id': 'SM:e.f.c_TEXT-1_SIR-1',
- 'desc': 'extend selection 1 character forward',
- 'function': 'sel.modify("extend", "forward", "character");',
- 'pad': 'foo b]a[r baz',
- 'expected': 'foo ba^r baz' },
-
- { 'id': 'SM:e.f.c_TEXT-1_SIR-2',
- 'desc': 'extend selection 1 character forward',
- 'function': 'sel.modify("extend", "forward", "character");',
- 'pad': 'foo ]ba[r baz',
- 'expected': 'foo b]a[r baz' },
-
- { 'id': 'SM:e.f.w_TEXT-1_SIR-1',
- 'desc': 'extend selection 1 word forward',
- 'function': 'sel.modify("extend", "forward", "word");',
- 'pad': 'foo ]ba[r baz',
- 'expected': 'foo ba^r baz' },
-
- { 'id': 'SM:e.f.w_TEXT-1_SIR-3',
- 'desc': 'extend selection 1 word forward',
- 'function': 'sel.modify("extend", "forward", "word");',
- 'pad': ']foo ba[r baz',
- 'expected': 'foo ]ba[r baz' }
- ]
- },
-
- { 'desc': 'sel.modify: extend selection forward to line boundary',
- 'tests': [
- { 'id': 'SM:e.f.lb_BR.BR-1_SC-1',
- 'desc': 'extend selection forward to line boundary',
- 'function': 'sel.modify("extend", "forward", "lineboundary");',
- 'pad': 'fo^o<br>bar<br>baz',
- 'expected': 'fo[o]<br>bar<br>baz' },
-
- { 'id': 'SM:e.f.lb_BR.BR-1_SI-1',
- 'desc': 'extend selection forward to next line boundary',
- 'function': 'sel.modify("extend", "forward", "lineboundary");',
- 'pad': 'fo[o]<br>bar<br>baz',
- 'expected': 'fo[o<br>bar]<br>baz' },
-
- { 'id': 'SM:e.f.lb_BR.BR-1_SM-1',
- 'desc': 'extend selection forward to line boundary',
- 'function': 'sel.modify("extend", "forward", "lineboundary");',
- 'pad': 'fo[o<br>b]ar<br>baz',
- 'expected': 'fo[o<br>bar]<br>baz' },
-
- { 'id': 'SM:e.f.lb_P.P.P-1_SC-1',
- 'desc': 'extend selection forward to line boundary',
- 'function': 'sel.modify("extend", "forward", "lineboundary");',
- 'pad': '<p>fo^o</p><p>bar</p><p>baz</p>',
- 'expected': '<p>fo[o]</p><p>bar</p><p>baz</p>' },
-
- { 'id': 'SM:e.f.lb_P.P.P-1_SI-1',
- 'desc': 'extend selection forward to next line boundary',
- 'function': 'sel.modify("extend", "forward", "lineboundary");',
- 'pad': '<p>fo[o]</p><p>bar</p><p>baz</p>',
- 'expected': '<p>fo[o</p><p>bar]</p><p>baz</p>' },
-
- { 'id': 'SM:e.f.lb_P.P.P-1_SM-1',
- 'desc': 'extend selection forward to line boundary',
- 'function': 'sel.modify("extend", "forward", "lineboundary");',
- 'pad': '<p>fo[o</p><p>b]ar</p><p>baz</p>',
- 'expected': '<p>fo[o</p><p>bar]</p><p>baz</p>' },
-
- { 'id': 'SM:e.f.lb_P.P.P-1_SMR-1',
- 'desc': 'extend selection forward to line boundary',
- 'function': 'sel.modify("extend", "forward", "lineboundary");',
- 'pad': '<p>foo</p><p>b]a[r</p><p>baz</p>',
- 'expected': '<p>foo</p><p>ba[r]</p><p>baz</p>' }
- ]
- },
-
- { 'desc': 'sel.modify: extend selection backward to line boundary',
- 'tests': [
- { 'id': 'SM:e.b.lb_BR.BR-1_SC-2',
- 'desc': 'extend selection backward to line boundary',
- 'function': 'sel.modify("extend", "backward", "lineboundary");',
- 'pad': 'foo<br>bar<br>b^az',
- 'expected': 'foo<br>bar<br>]b[az' },
-
- { 'id': 'SM:e.b.lb_BR.BR-1_SIR-2',
- 'desc': 'extend selection backward to previous line boundary',
- 'function': 'sel.modify("extend", "backward", "lineboundary");',
- 'pad': 'foo<br>bar<br>]b[az',
- 'expected': 'foo<br>]bar<br>b[az' },
-
- { 'id': 'SM:e.b.lb_BR.BR-1_SMR-2',
- 'desc': 'extend selection backward to line boundary',
- 'function': 'sel.modify("extend", "backward", "lineboundary");',
- 'pad': 'foo<br>ba]r<br>b[az',
- 'expected': 'foo<br>]bar<br>b[az' },
-
- { 'id': 'SM:e.b.lb_P.P.P-1_SC-2',
- 'desc': 'extend selection backward to line boundary',
- 'function': 'sel.modify("extend", "backward", "lineboundary");',
- 'pad': '<p>foo</p><p>bar</p><p>b^az</p>',
- 'expected': '<p>foo</p><p>bar</p><p>]b[az</p>' },
-
- { 'id': 'SM:e.b.lb_P.P.P-1_SIR-2',
- 'desc': 'extend selection backward to previous line boundary',
- 'function': 'sel.modify("extend", "backward", "lineboundary");',
- 'pad': '<p>foo</p><p>bar</p><p>]b[az</p>',
- 'expected': '<p>foo</p><p>]bar</p><p>b[az</p>' },
-
- { 'id': 'SM:e.b.lb_P.P.P-1_SMR-2',
- 'desc': 'extend selection backward to line boundary',
- 'function': 'sel.modify("extend", "backward", "lineboundary");',
- 'pad': '<p>foo</p><p>ba]r</p><p>b[az</p>',
- 'expected': '<p>foo</p><p>]bar</p><p>b[az</p>' },
-
- { 'id': 'SM:e.b.lb_P.P.P-1_SM-2',
- 'desc': 'extend selection backward to line boundary',
- 'function': 'sel.modify("extend", "backward", "lineboundary");',
- 'pad': '<p>foo</p><p>b[a]r</p><p>baz</p>',
- 'expected': '<p>foo</p><p>]b[ar</p><p>baz</p>' }
- ]
- },
-
- { 'desc': 'sel.modify: extend selection forward to next line (NOTE: use identical text in every line!)',
- 'tests': [
- { 'id': 'SM:e.f.l_BR.BR-2_SC-1',
- 'desc': 'extend selection forward to next line',
- 'function': 'sel.modify("extend", "forward", "line");',
- 'pad': 'fo^o<br>foo<br>foo',
- 'expected': 'fo[o<br>fo]o<br>foo' },
-
- { 'id': 'SM:e.f.l_BR.BR-2_SI-1',
- 'desc': 'extend selection forward to next line',
- 'function': 'sel.modify("extend", "forward", "line");',
- 'pad': 'fo[o]<br>foo<br>foo',
- 'expected': 'fo[o<br>foo]<br>foo' },
-
- { 'id': 'SM:e.f.l_BR.BR-2_SM-1',
- 'desc': 'extend selection forward to next line',
- 'function': 'sel.modify("extend", "forward", "line");',
- 'pad': 'fo[o<br>f]oo<br>foo',
- 'expected': 'fo[o<br>foo<br>f]oo' },
-
- { 'id': 'SM:e.f.l_P.P-1_SC-1',
- 'desc': 'extend selection forward to next line over paragraph boundaries',
- 'function': 'sel.modify("extend", "forward", "line");',
- 'pad': '<p>foo^bar</p><p>foobar</p>',
- 'expected': '<p>foo[bar</p><p>foo]bar</p>' },
-
- { 'id': 'SM:e.f.l_P.P-1_SMR-1',
- 'desc': 'extend selection forward to next line over paragraph boundaries',
- 'function': 'sel.modify("extend", "forward", "line");',
- 'pad': '<p>fo]obar</p><p>foob[ar</p>',
- 'expected': '<p>foobar</p><p>fo]ob[ar</p>' }
- ]
- },
-
- { 'desc': 'sel.modify: extend selection backward to previous line (NOTE: use identical text in every line!)',
- 'tests': [
- { 'id': 'SM:e.b.l_BR.BR-2_SC-2',
- 'desc': 'extend selection backward to previous line',
- 'function': 'sel.modify("extend", "backward", "line");',
- 'pad': 'foo<br>foo<br>f^oo',
- 'expected': 'foo<br>f]oo<br>f[oo' },
-
- { 'id': 'SM:e.b.l_BR.BR-2_SIR-2',
- 'desc': 'extend selection backward to previous line',
- 'function': 'sel.modify("extend", "backward", "line");',
- 'pad': 'foo<br>foo<br>]f[oo',
- 'expected': 'foo<br>]foo<br>f[oo' },
-
- { 'id': 'SM:e.b.l_BR.BR-2_SMR-2',
- 'desc': 'extend selection backward to previous line',
- 'function': 'sel.modify("extend", "backward", "line");',
- 'pad': 'foo<br>fo]o<br>f[oo',
- 'expected': 'fo]o<br>foo<br>f[oo' },
-
- { 'id': 'SM:e.b.l_P.P-1_SC-2',
- 'desc': 'extend selection backward to next line over paragraph boundaries',
- 'function': 'sel.modify("extend", "backward", "line");',
- 'pad': '<p>foobar</p><p>foo^bar</p>',
- 'expected': '<p>foo]bar</p><p>foo[bar</p>' },
-
- { 'id': 'SM:e.b.l_P.P-1_SM-1',
- 'desc': 'extend selection backward to next line over paragraph boundaries',
- 'function': 'sel.modify("extend", "backward", "line");',
- 'pad': '<p>fo[obar</p><p>foob]ar</p>',
- 'expected': '<p>fo[ob]ar</p><p>foobar</p>' }
- ]
- },
-
- { 'desc': 'sel.selectAllChildren(<element>)',
- 'function': 'sel.selectAllChildren(doc.getElementById("div"));',
- 'tests': [
- { 'id': 'SAC:div_DIV-1_SC-1',
- 'desc': 'selectAllChildren(<div>)',
- 'pad': 'foo<div id="div">bar <span>ba^z</span></div>qoz',
- 'expected': [ 'foo<div id="div">[bar <span>baz</span>}</div>qoz',
- 'foo<div id="div">{bar <span>baz</span>}</div>qoz' ] },
- ]
- }
- ]
-}
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/unapply.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/unapply.py
deleted file mode 100644
index adad65617..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/unapply.py
+++ /dev/null
@@ -1,462 +0,0 @@
-
-UNAPPLY_TESTS = {
- 'id': 'U',
- 'caption': 'Unapply Existing Formatting Tests',
- 'checkAttrs': True,
- 'checkStyle': True,
- 'styleWithCSS': False,
- 'expected': 'foo[bar]baz',
-
- 'RFC': [
- { 'desc': '',
- 'command': '',
- 'tests': [
- ]
- },
-
- { 'desc': 'remove link',
- 'command': 'unlink',
- 'tests': [
- { 'id': 'UNLINK_A-1_SO',
- 'desc': 'unlink wrapped <a> element',
- 'pad': 'foo[<a>bar</a>]baz' },
-
- { 'id': 'UNLINK_A-1_SW',
- 'desc': 'unlink <a> element where the selection wraps the full content',
- 'pad': 'foo<a>[bar]</a>baz' },
-
- { 'id': 'UNLINK_An:a.h:id-1_SO',
- 'desc': 'unlink wrapped <a> element that has a name and href attribute',
- 'pad': 'foo[<a name="A" href="#UNLINK:An:a.h:id-1_SO">bar</a>]baz' },
-
- { 'id': 'UNLINK_A-2_SO',
- 'desc': 'unlink contained <a> element',
- 'pad': 'foo[b<a>a</a>r]baz' },
-
- { 'id': 'UNLINK_A2-1_SO',
- 'desc': 'unlink 2 contained <a> elements',
- 'pad': 'foo[<a>b</a>a<a>r</a>]baz' }
- ]
- }
- ],
-
- 'Proposed': [
- { 'desc': '',
- 'command': '',
- 'tests': [
- ]
- },
-
- { 'desc': 'remove bold',
- 'command': 'bold',
- 'tests': [
- { 'id': 'B_B-1_SW',
- 'rte1-id': 'u-bold-0',
- 'desc': 'Selection within tags; remove <b> tags',
- 'pad': 'foo<b>[bar]</b>baz' },
-
- { 'id': 'B_B-1_SO',
- 'desc': 'Selection outside of tags; remove <b> tags',
- 'pad': 'foo[<b>bar</b>]baz' },
-
- { 'id': 'B_B-1_SL',
- 'desc': 'Selection oblique left; remove <b> tags',
- 'pad': 'foo[<b>bar]</b>baz' },
-
- { 'id': 'B_B-1_SR',
- 'desc': 'Selection oblique right; remove <b> tags',
- 'pad': 'foo<b>[bar</b>]baz' },
-
- { 'id': 'B_STRONG-1_SW',
- 'rte1-id': 'u-bold-1',
- 'desc': 'Selection within tags; remove <strong> tags',
- 'pad': 'foo<strong>[bar]</strong>baz' },
-
- { 'id': 'B_STRONG-1_SO',
- 'desc': 'Selection outside of tags; remove <strong> tags',
- 'pad': 'foo[<strong>bar</strong>]baz' },
-
- { 'id': 'B_STRONG-1_SL',
- 'desc': 'Selection oblique left; remove <strong> tags',
- 'pad': 'foo[<strong>bar]</strong>baz' },
-
- { 'id': 'B_STRONG-1_SR',
- 'desc': 'Selection oblique right; remove <strong> tags',
- 'pad': 'foo<strong>[bar</strong>]baz' },
-
- { 'id': 'B_SPANs:fw:b-1_SW',
- 'rte1-id': 'u-bold-2',
- 'desc': 'Selection within tags; remove "font-weight: bold"',
- 'pad': 'foo<span style="font-weight: bold">[bar]</span>baz' },
-
- { 'id': 'B_SPANs:fw:b-1_SO',
- 'desc': 'Selection outside of tags; remove "font-weight: bold"',
- 'pad': 'foo[<span style="font-weight: bold">bar</span>]baz' },
-
- { 'id': 'B_SPANs:fw:b-1_SL',
- 'desc': 'Selection oblique left; remove "font-weight: bold"',
- 'pad': 'foo[<span style="font-weight: bold">bar]</span>baz' },
-
- { 'id': 'B_SPANs:fw:b-1_SR',
- 'desc': 'Selection oblique right; remove "font-weight: bold"',
- 'pad': 'foo<span style="font-weight: bold">[bar</span>]baz' },
-
- { 'id': 'B_B-P3-1_SO12',
- 'desc': 'Unbolding multiple paragraphs in inside bolded content with content-model violation',
- 'pad': '<b>{<p>foo</p><p>bar</p>}<p>baz</p></b>',
- 'expected': [ '<p>[foo</p><p>bar]</p><p><b>baz</b></p>',
- '<p>[foo</p><p>bar]</p><b><p>baz</p></b>' ] },
-
- { 'id': 'B_B-P-I..P-1_SO-I',
- 'desc': 'Unbolding italicized content inside bolded content with content-model violation',
- 'pad': '<b><p>foo[<i>bar</i>]</p><p>baz</p></b>',
- 'expected': [ '<p><b>foo</b><i>[bar]</i></p><p><b>baz</b></p>',
- '<b><p>foo</p></b><p><i>[bar]</i></p><b><p>baz</p></b>' ] },
-
- { 'id': 'B_B-2_SL',
- 'desc': 'Remove partially covered bold, selection extends left',
- 'pad': 'foo [bar <b>baz] qoz</b> quz sic',
- 'expected': 'foo [bar baz]<b> qoz</b> quz sic' },
-
- { 'id': 'B_B-2_SR',
- 'desc': 'Remove partially covered bold, selection extends right',
- 'pad': 'foo bar <b>baz [qoz</b> quz] sic',
- 'expected': 'foo bar <b>baz </b>[qoz quz] sic' }
- ]
- },
-
- { 'desc': 'remove italic',
- 'command': 'italic',
- 'tests': [
- { 'id': 'I_I-1_SW',
- 'rte1-id': 'u-italic-0',
- 'desc': 'Selection within tags; remove <i> tags',
- 'pad': 'foo<i>[bar]</i>baz' },
-
- { 'id': 'I_I-1_SO',
- 'desc': 'Selection outside of tags; remove <i> tags',
- 'pad': 'foo[<i>bar</i>]baz' },
-
- { 'id': 'I_I-1_SL',
- 'desc': 'Selection oblique left; remove <i> tags',
- 'pad': 'foo[<i>bar]</i>baz' },
-
- { 'id': 'I_I-1_SR',
- 'desc': 'Selection oblique right; remove <i> tags',
- 'pad': 'foo<i>[bar</i>]baz' },
-
- { 'id': 'I_EM-1_SW',
- 'rte1-id': 'u-italic-1',
- 'desc': 'Selection within tags; remove <em> tags',
- 'pad': 'foo<em>[bar]</em>baz' },
-
- { 'id': 'I_EM-1_SO',
- 'desc': 'Selection outside of tags; remove <em> tags',
- 'pad': 'foo[<em>bar</em>]baz' },
-
- { 'id': 'I_EM-1_SL',
- 'desc': 'Selection oblique left; remove <em> tags',
- 'pad': 'foo[<em>bar]</em>baz' },
-
- { 'id': 'I_EM-1_SR',
- 'desc': 'Selection oblique right; remove <em> tags',
- 'pad': 'foo<em>[bar</em>]baz' },
-
- { 'id': 'I_SPANs:fs:i-1_SW',
- 'rte1-id': 'u-italic-2',
- 'desc': 'Selection within tags; remove "font-style: italic"',
- 'pad': 'foo<span style="font-style: italic">[bar]</span>baz' },
-
- { 'id': 'I_SPANs:fs:i-1_SO',
- 'desc': 'Selection outside of tags; Italicize "font-style: italic"',
- 'pad': 'foo[<span style="font-style: italic">bar</span>]baz' },
-
- { 'id': 'I_SPANs:fs:i-1_SL',
- 'desc': 'Selection oblique left; Italicize "font-style: italic"',
- 'pad': 'foo[<span style="font-style: italic">bar]</span>baz' },
-
- { 'id': 'I_SPANs:fs:i-1_SR',
- 'desc': 'Selection oblique right; Italicize "font-style: italic"',
- 'pad': 'foo<span style="font-style: italic">[bar</span>]baz' },
-
- { 'id': 'I_I-P3-1_SO2',
- 'desc': 'Unitalicize content with content-model violation',
- 'pad': '<i><p>foo</p>{<p>bar</p>}<p>baz</p></i>',
- 'expected': [ '<p><i>foo</i></p><p>[bar]</p><p><i>baz</i></p>',
- '<i><p>foo</p></i><p>[bar]</p><i><p>baz</p></i>' ] }
- ]
- },
-
- { 'desc': 'remove underline',
- 'command': 'underline',
- 'tests': [
- { 'id': 'U_U-1_SW',
- 'rte1-id': 'u-underline-0',
- 'desc': 'Selection within tags; remove <u> tags',
- 'pad': 'foo<u>[bar]</u>baz' },
-
- { 'id': 'U_U-1_SO',
- 'desc': 'Selection outside of tags; remove <u> tags',
- 'pad': 'foo[<u>bar</u>]baz' },
-
- { 'id': 'U_U-1_SL',
- 'desc': 'Selection oblique left; remove <u> tags',
- 'pad': 'foo[<u>bar]</u>baz' },
-
- { 'id': 'U_U-1_SR',
- 'desc': 'Selection oblique right; remove <u> tags',
- 'pad': 'foo<u>[bar</u>]baz' },
-
- { 'id': 'U_SPANs:td:u-1_SW',
- 'rte1-id': 'u-underline-1',
- 'desc': 'Selection within tags; remove "text-decoration: underline"',
- 'pad': 'foo<span style="text-decoration: underline">[bar]</span>baz' },
-
- { 'id': 'U_SPANs:td:u-1_SO',
- 'desc': 'Selection outside of tags; remove "text-decoration: underline"',
- 'pad': 'foo[<span style="text-decoration: underline">bar</span>]baz' },
-
- { 'id': 'U_SPANs:td:u-1_SL',
- 'desc': 'Selection oblique left; remove "text-decoration: underline"',
- 'pad': 'foo[<span style="text-decoration: underline">bar]</span>baz' },
-
- { 'id': 'U_SPANs:td:u-1_SR',
- 'desc': 'Selection oblique right; remove "text-decoration: underline"',
- 'pad': 'foo<span style="text-decoration: underline">[bar</span>]baz' },
-
- { 'id': 'U_U-S-1_SO',
- 'desc': 'Removing underline from underlined content with striked content',
- 'pad': '<u>foo[bar<s>baz</s>quoz]</u>',
- 'expected': '<u>foo</u>[bar<s>baz</s>quoz]' },
-
- { 'id': 'U_U-S-2_SI',
- 'desc': 'Removing underline from striked content inside underlined content',
- 'pad': '<u><s>foo[bar]baz</s>quoz</u>',
- 'expected': '<s><u>foo</u>[bar]<u>baz</u>quoz</s>' },
-
- { 'id': 'U_U-P3-1_SO',
- 'desc': 'Removing underline from underlined content with content-model violation',
- 'pad': '<u><p>foo</p>{<p>bar</p>}<p>baz</p></u>',
- 'expected': [ '<p><u>foo</u></p><p>[bar]</p><p><u>baz</u></p>',
- '<u><p>foo</p></u><p>[bar]</p><u><p>baz</p></u>' ] }
- ]
- },
-
- { 'desc': 'remove strike through',
- 'command': 'strikethrough',
- 'tests': [
- { 'id': 'S_S-1_SW',
- 'rte1-id': 'u-strikethrough-1',
- 'desc': 'Selection within tags; remove <s> tags',
- 'pad': 'foo<s>[bar]</s>baz' },
-
- { 'id': 'S_S-1_SO',
- 'desc': 'Selection outside of tags; remove <s> tags',
- 'pad': 'foo[<s>bar</s>]baz' },
-
- { 'id': 'S_S-1_SL',
- 'desc': 'Selection oblique left; remove <s> tags',
- 'pad': 'foo[<s>bar]</s>baz' },
-
- { 'id': 'S_S-1_SR',
- 'desc': 'Selection oblique right; remove <s> tags',
- 'pad': 'foo<s>[bar</s>]baz' },
-
- { 'id': 'S_STRIKE-1_SW',
- 'rte1-id': 'u-strikethrough-0',
- 'desc': 'Selection within tags; remove <strike> tags',
- 'pad': 'foo<strike>[bar]</strike>baz' },
-
- { 'id': 'S_STRIKE-1_SO',
- 'desc': 'Selection outside of tags; remove <strike> tags',
- 'pad': 'foo[<strike>bar</strike>]baz' },
-
- { 'id': 'S_STRIKE-1_SL',
- 'desc': 'Selection oblique left; remove <strike> tags',
- 'pad': 'foo[<strike>bar]</strike>baz' },
-
- { 'id': 'S_STRIKE-2_SR',
- 'desc': 'Selection oblique right; remove <strike> tags',
- 'pad': 'foo<strike>[bar</strike>]baz' },
-
- { 'id': 'S_DEL-1_SW',
- 'rte1-id': 'u-strikethrough-2',
- 'desc': 'Selection within tags; remove <del> tags',
- 'pad': 'foo<del>[bar]</del>baz' },
-
- { 'id': 'S_SPANs:td:lt-1_SW',
- 'rte1-id': 'u-strikethrough-3',
- 'desc': 'Selection within tags; remove "text-decoration:line-through"',
- 'pad': 'foo<span style="text-decoration:line-through">[bar]</span>baz' },
-
- { 'id': 'S_SPANs:td:lt-1_SO',
- 'desc': 'Selection outside of tags; Italicize "text-decoration:line-through"',
- 'pad': 'foo[<span style="text-decoration:line-through">bar</span>]baz' },
-
- { 'id': 'S_SPANs:td:lt-1_SL',
- 'desc': 'Selection oblique left; Italicize "text-decoration:line-through"',
- 'pad': 'foo[<span style="text-decoration:line-through">bar]</span>baz' },
-
- { 'id': 'S_SPANs:td:lt-1_SR',
- 'desc': 'Selection oblique right; Italicize "text-decoration:line-through"',
- 'pad': 'foo<span style="text-decoration:line-through">[bar</span>]baz' },
-
- { 'id': 'S_S-U-1_SI',
- 'desc': 'Removing underline from underlined content inside striked content',
- 'pad': '<s><u>foo[bar]baz</u>quoz</s>',
- 'expected': '<s><u>foo</u></s><u>[bar]</u><s><u>baz</u>quoz</s>' },
-
- { 'id': 'S_U-S-1_SI',
- 'desc': 'Removing underline from striked content inside underlined content',
- 'pad': '<u><s>foo[bar]baz</s>quoz</u>',
- 'expected': '<u><s>foo</s>[bar]<s>baz</s>quoz</u>' }
- ]
- },
-
- { 'desc': 'remove subscript',
- 'command': 'subscript',
- 'tests': [
- { 'id': 'SUB_SUB-1_SW',
- 'rte1-id': 'u-subscript-0',
- 'desc': 'remove subscript',
- 'pad': 'foo<sub>[bar]</sub>baz' },
-
- { 'id': 'SUB_SPANs:va:sub-1_SW',
- 'rte1-id': 'u-subscript-1',
- 'desc': 'remove subscript',
- 'pad': 'foo<span style="vertical-align: sub">[bar]</span>baz' }
- ]
- },
-
- { 'desc': 'remove superscript',
- 'command': 'superscript',
- 'tests': [
- { 'id': 'SUP_SUP-1_SW',
- 'rte1-id': 'u-superscript-0',
- 'desc': 'remove superscript',
- 'pad': 'foo<sup>[bar]</sup>baz' },
-
- { 'id': 'SUP_SPANs:va:super-1_SW',
- 'rte1-id': 'u-superscript-1',
- 'desc': 'remove superscript',
- 'pad': 'foo<span style="vertical-align: super">[bar]</span>baz' }
- ]
- },
-
- { 'desc': 'remove links',
- 'command': 'unlink',
- 'tests': [
- { 'id': 'UNLINK_Ahref:url-1_SW',
- 'rte1-id': 'u-unlink-0',
- 'desc': 'unlink an <a> element with href attribute where all children are selected',
- 'pad': 'foo<a href="http://www.goo.gl">[bar]</a>baz' },
-
- { 'id': 'UNLINK_A-1_SC',
- 'desc': 'unlink an <a> element that contains the collapsed selection',
- 'pad': 'foo<a>ba^r</a>baz',
- 'expected': 'fooba^rbaz' },
-
- { 'id': 'UNLINK_A-1_SI',
- 'desc': 'unlink an <a> element that contains the whole selection',
- 'pad': 'foo<a>b[a]r</a>baz',
- 'expected': 'foob[a]rbaz' },
-
- { 'id': 'UNLINK_A-2_SL',
- 'desc': 'unlink a partially contained <a> element',
- 'pad': 'foo[ba<a>r]ba</a>z' },
-
- { 'id': 'UNLINK_A-3_SR',
- 'desc': 'unlink a partially contained <a> element',
- 'pad': 'fo<a>o[ba</a>r]baz' },
-
- { 'id': 'UNLINK_As:d:b.fw:b-1_SW',
- 'desc': 'unlink, preserving styles',
- 'pad': 'foo<a href="#" style="display: block; font-weight: bold">[bar]</a>baz',
- 'expected': 'foo<span style="display: block; font-weight: bold">[bar]</span>baz' },
-
- { 'id': 'UNLINK_A-IMG-1_SO',
- 'desc': 'unlink a linked image at the start of the content',
- 'pad': '{<a href="#"><img src="pic.jpg" align="right" height="140" width="200"></a>abc]',
- 'expected': '{<img src="pic.jpg" align="right" height="140" width="200">abc]' }
- ]
- },
-
- { 'desc': 'outdent',
- 'command': 'outdent',
- 'tests': [
- { 'id': 'OUTDENT_BQ-1_SW',
- 'rte1-id': 'u-outdent-0',
- 'desc': 'outdent (remove) a <blockquote>',
- 'pad': 'foo<blockquote>[bar]</blockquote>baz',
- 'expected': [ 'foo<p>[bar]</p>baz',
- 'foo<div>[bar]</div>baz' ],
- 'accept': 'foo<br>[bar]<br>baz' },
-
- { 'id': 'OUTDENT_BQ.wibq.s:m:00040.b:n.p:0-1_SW',
- 'rte1-id': 'u-outdent-1',
- 'desc': 'outdent (remove) a styled <blockquote>',
- 'pad': 'foo<blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px">[bar]</blockquote>baz',
- 'expected': [ 'foo<p>[bar]</p>baz',
- 'foo<div>[bar]</div>baz' ],
- 'accept': 'foo<br>[bar]<br>baz' },
-
- { 'id': 'OUTDENT_OL-LI-1_SW',
- 'rte1-id': 'u-outdent-3',
- 'desc': 'outdent (remove) an ordered list',
- 'pad': 'foo<ol><li>[bar]</li></ol>baz',
- 'expected': [ 'foo<p>[bar]</p>baz',
- 'foo<div>[bar]</div>baz' ],
- 'accept': 'foo<br>[bar]<br>baz' },
-
- { 'id': 'OUTDENT_UL-LI-1_SW',
- 'rte1-id': 'u-outdent-2',
- 'desc': 'outdent (remove) an unordered list',
- 'pad': 'foo<ul><li>[bar]</li></ul>baz',
- 'expected': [ 'foo<p>[bar]</p>baz',
- 'foo<div>[bar]</div>baz' ],
- 'accept': 'foo<br>[bar]<br>baz' },
-
- { 'id': 'OUTDENT_DIV-1_SW',
- 'rte1-id': 'u-outdent-4',
- 'desc': 'outdent (remove) a styled <div> with margin',
- 'pad': 'foo<div style="margin-left: 40px;">[bar]</div>baz',
- 'expected': [ 'foo<p>[bar]</p>baz',
- 'foo<div>[bar]</div>baz' ],
- 'accept': 'foo<br>[bar]<br>baz' }
- ]
- },
-
- { 'desc': 'remove all formatting',
- 'command': 'removeformat',
- 'tests': [
- { 'id': 'REMOVEFORMAT_B-1_SW',
- 'rte1-id': 'u-removeformat-0',
- 'desc': 'remove a <b> tag using "removeformat"',
- 'pad': 'foo<b>[bar]</b>baz' },
-
- { 'id': 'REMOVEFORMAT_Ahref:url-1_SW',
- 'rte1-id': 'u-removeformat-0',
- 'desc': 'remove a link using "removeformat"',
- 'pad': 'foo<a href="http://www.goo.gl">[bar]</a>baz' },
-
- { 'id': 'REMOVEFORMAT_TABLE-TBODY-TR-TD-1_SW',
- 'rte1-id': 'u-removeformat-2',
- 'desc': 'remove a table using "removeformat"',
- 'pad': 'foo<table><tbody><tr><td>[bar]</td></tr></tbody></table>baz',
- 'expected': [ 'foo<p>[bar]</p>baz',
- 'foo<div>[bar]</div>baz' ],
- 'accept': 'foo<br>[bar]<br>baz' }
- ]
- },
-
- { 'desc': 'remove bookmark',
- 'command': 'unbookmark',
- 'tests': [
- { 'id': 'UNBOOKMARK_An:name-1_SW',
- 'rte1-id': 'u-unbookmark-0',
- 'desc': 'unlink a bookmark (a named <a> element) where all children are selected',
- 'pad': 'foo<a name="bookmark">[bar]</a>baz' }
- ]
- }
- ]
-}
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/unapplyCSS.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/unapplyCSS.py
deleted file mode 100644
index 6f934a0f0..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/unapplyCSS.py
+++ /dev/null
@@ -1,226 +0,0 @@
-
-UNAPPLY_TESTS_CSS = {
- 'id': 'UC',
- 'caption': 'Unapply Existing Formatting Tests, using styleWithCSS',
- 'checkAttrs': True,
- 'checkStyle': True,
- 'styleWithCSS': True,
- 'expected': 'foo[bar]baz',
-
- 'Proposed': [
- { 'desc': '',
- 'id': '',
- 'command': '',
- 'tests': [
- ]
- },
-
- { 'desc': 'remove bold',
- 'command': 'bold',
- 'tests': [
- { 'id': 'B_B-1_SW',
- 'desc': 'Selection within tags; remove <b> tags',
- 'pad': 'foo<b>[bar]</b>baz' },
-
- { 'id': 'B_B-1_SO',
- 'desc': 'Selection outside of tags; remove <b> tags',
- 'pad': 'foo[<b>bar</b>]baz' },
-
- { 'id': 'B_B-1_SL',
- 'desc': 'Selection oblique left; remove <b> tags',
- 'pad': 'foo[<b>bar]</b>baz' },
-
- { 'id': 'B_B-1_SR',
- 'desc': 'Selection oblique right; remove <b> tags',
- 'pad': 'foo<b>[bar</b>]baz' },
-
- { 'id': 'B_STRONG-1_SW',
- 'desc': 'Selection within tags; remove <strong> tags',
- 'pad': 'foo<strong>[bar]</strong>baz' },
-
- { 'id': 'B_STRONG-1_SO',
- 'desc': 'Selection outside of tags; remove <strong> tags',
- 'pad': 'foo[<strong>bar</strong>]baz' },
-
- { 'id': 'B_STRONG-1_SL',
- 'desc': 'Selection oblique left; remove <strong> tags',
- 'pad': 'foo[<strong>bar]</strong>baz' },
-
- { 'id': 'B_STRONG-1_SR',
- 'desc': 'Selection oblique right; remove <strong> tags',
- 'pad': 'foo<strong>[bar</strong>]baz' },
-
- { 'id': 'B_SPANs:fw:b-1_SW',
- 'desc': 'Selection within tags; remove "font-weight: bold"',
- 'pad': 'foo<span style="font-weight: bold">[bar]</span>baz' },
-
- { 'id': 'B_SPANs:fw:b-1_SO',
- 'desc': 'Selection outside of tags; remove "font-weight: bold"',
- 'pad': 'foo[<span style="font-weight: bold">bar</span>]baz' },
-
- { 'id': 'B_SPANs:fw:b-1_SL',
- 'desc': 'Selection oblique left; remove "font-weight: bold"',
- 'pad': 'foo[<span style="font-weight: bold">bar]</span>baz' },
-
- { 'id': 'B_SPANs:fw:b-1_SR',
- 'desc': 'Selection oblique right; remove "font-weight: bold"',
- 'pad': 'foo<span style="font-weight: bold">[bar</span>]baz' }
- ]
- },
-
- { 'desc': 'remove italic',
- 'command': 'italic',
- 'tests': [
- { 'id': 'I_I-1_SW',
- 'desc': 'Selection within tags; remove <i> tags',
- 'pad': 'foo<i>[bar]</i>baz' },
-
- { 'id': 'I_I-1_SO',
- 'desc': 'Selection outside of tags; remove <i> tags',
- 'pad': 'foo[<i>bar</i>]baz' },
-
- { 'id': 'I_I-1_SL',
- 'desc': 'Selection oblique left; remove <i> tags',
- 'pad': 'foo[<i>bar]</i>baz' },
-
- { 'id': 'I_I-1_SR',
- 'desc': 'Selection oblique right; remove <i> tags',
- 'pad': 'foo<i>[bar</i>]baz' },
-
- { 'id': 'I_EM-1_SW',
- 'desc': 'Selection within tags; remove <em> tags',
- 'pad': 'foo<em>[bar]</em>baz' },
-
- { 'id': 'I_EM-1_SO',
- 'desc': 'Selection outside of tags; remove <em> tags',
- 'pad': 'foo[<em>bar</em>]baz' },
-
- { 'id': 'I_EM-1_SL',
- 'desc': 'Selection oblique left; remove <em> tags',
- 'pad': 'foo[<em>bar]</em>baz' },
-
- { 'id': 'I_EM-1_SR',
- 'desc': 'Selection oblique right; remove <em> tags',
- 'pad': 'foo<em>[bar</em>]baz' },
-
- { 'id': 'I_SPANs:fs:i-1_SW',
- 'desc': 'Selection within tags; remove "font-style: italic"',
- 'pad': 'foo<span style="font-style: italic">[bar]</span>baz' },
-
- { 'id': 'I_SPANs:fs:i-1_SO',
- 'desc': 'Selection outside of tags; Italicize "font-style: italic"',
- 'pad': 'foo[<span style="font-style: italic">bar</span>]baz' },
-
- { 'id': 'I_SPANs:fs:i-1_SL',
- 'desc': 'Selection oblique left; Italicize "font-style: italic"',
- 'pad': 'foo[<span style="font-style: italic">bar]</span>baz' },
-
- { 'id': 'I_SPANs:fs:i-1_SR',
- 'desc': 'Selection oblique right; Italicize "font-style: italic"',
- 'pad': 'foo<span style="font-style: italic">[bar</span>]baz' }
- ]
- },
-
- { 'desc': 'remove underline',
- 'command': 'underline',
- 'tests': [
- { 'id': 'U_U-1_SW',
- 'desc': 'Selection within tags; remove <u> tags',
- 'pad': 'foo<u>[bar]</u>baz' },
-
- { 'id': 'U_U-1_SO',
- 'desc': 'Selection outside of tags; remove <u> tags',
- 'pad': 'foo[<u>bar</u>]baz' },
-
- { 'id': 'U_U-1_SL',
- 'desc': 'Selection oblique left; remove <u> tags',
- 'pad': 'foo[<u>bar]</u>baz' },
-
- { 'id': 'U_U-1_SR',
- 'desc': 'Selection oblique right; remove <u> tags',
- 'pad': 'foo<u>[bar</u>]baz' },
-
- { 'id': 'U_SPANs:td:u-1_SW',
- 'desc': 'Selection within tags; remove "text-decoration: underline"',
- 'pad': 'foo<span style="text-decoration: underline">[bar]</span>baz' },
-
- { 'id': 'U_SPANs:td:u-1_SO',
- 'desc': 'Selection outside of tags; remove "text-decoration: underline"',
- 'pad': 'foo[<span style="text-decoration: underline">bar</span>]baz' },
-
- { 'id': 'U_SPANs:td:u-1_SL',
- 'desc': 'Selection oblique left; remove "text-decoration: underline"',
- 'pad': 'foo[<span style="text-decoration: underline">bar]</span>baz' },
-
- { 'id': 'U_SPANs:td:u-1_SR',
- 'desc': 'Selection oblique right; remove "text-decoration: underline"',
- 'pad': 'foo<span style="text-decoration: underline">[bar</span>]baz' }
- ]
- },
-
- { 'desc': 'remove strike-through',
- 'command': 'strikethrough',
- 'tests': [
- { 'id': 'S_S-1_SW',
- 'desc': 'Selection within tags; remove <s> tags',
- 'pad': 'foo<s>[bar]</s>baz' },
-
- { 'id': 'S_S-1_SO',
- 'desc': 'Selection outside of tags; remove <s> tags',
- 'pad': 'foo[<s>bar</s>]baz' },
-
- { 'id': 'S_S-1_SL',
- 'desc': 'Selection oblique left; remove <s> tags',
- 'pad': 'foo[<s>bar]</s>baz' },
-
- { 'id': 'S_S-1_SR',
- 'desc': 'Selection oblique right; remove <s> tags',
- 'pad': 'foo<s>[bar</s>]baz' },
-
- { 'id': 'S_STRIKE-1_SW',
- 'desc': 'Selection within tags; remove <strike> tags',
- 'pad': 'foo<strike>[bar]</strike>baz' },
-
- { 'id': 'S_STRIKE-1_SO',
- 'desc': 'Selection outside of tags; remove <strike> tags',
- 'pad': 'foo[<strike>bar</strike>]baz' },
-
- { 'id': 'S_STRIKE-1_SL',
- 'desc': 'Selection oblique left; remove <strike> tags',
- 'pad': 'foo[<strike>bar]</strike>baz' },
-
- { 'id': 'S_STRIKE-1_SR',
- 'desc': 'Selection oblique right; remove <strike> tags',
- 'pad': 'foo<strike>[bar</strike>]baz' },
-
- { 'id': 'S_SPANs:td:lt-1_SW',
- 'desc': 'Selection within tags; remove "text-decoration:line-through"',
- 'pad': 'foo<span style="text-decoration:line-through">[bar]</span>baz' },
-
- { 'id': 'S_SPANs:td:lt-1_SO',
- 'desc': 'Selection outside of tags; Italicize "text-decoration:line-through"',
- 'pad': 'foo[<span style="text-decoration:line-through">bar</span>]baz' },
-
- { 'id': 'S_SPANs:td:lt-1_SL',
- 'desc': 'Selection oblique left; Italicize "text-decoration:line-through"',
- 'pad': 'foo[<span style="text-decoration:line-through">bar]</span>baz' },
-
- { 'id': 'S_SPANs:td:lt-1_SR',
- 'desc': 'Selection oblique right; Italicize "text-decoration:line-through"',
- 'pad': 'foo<span style="text-decoration:line-through">[bar</span>]baz' },
-
- { 'id': 'S_SPANc:s-1_SW',
- 'desc': 'Unapply "strike-through" on interited CSS style',
- 'checkClass': True,
- 'pad': 'foo<span class="s">[bar]</span>baz' },
-
- { 'id': 'S_SPANc:s-2_SI',
- 'desc': 'Unapply "strike-through" on interited CSS style',
- 'pad': '<span class="s">foo[bar]baz</span>',
- 'checkClass': True,
- 'expected': '<span class="s">foo</span>[bar]<span class="s">baz</span>' }
- ]
- }
- ]
-}
-
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/unittestexample.html b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/unittestexample.html
deleted file mode 100644
index 4e27b0554..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/unittestexample.html
+++ /dev/null
@@ -1,103 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
- <meta http-equiv="content-type" content="text/html; charset=utf-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
-
- <title>Rich Text 2 Unit Test Example</title>
-
- <!-- utility scripts -->
- <script type="text/javascript" src="static/js/variables.js"></script>
- <script type="text/javascript" src="static/js/canonicalize.js"></script>
- <script type="text/javascript" src="static/js/compare.js"></script>
- <script type="text/javascript" src="static/js/pad.js"></script>
- <script type="text/javascript" src="static/js/range.js"></script>
- <script type="text/javascript" src="static/js/units.js"></script>
- <script type="text/javascript" src="static/js/run.js"></script>
- <!-- you do not need static/js/output.js -->
-
- <!--
- Tests - note that those have the extensions .py,
- but can be used as JS files directly.
- -->
- <script type="text/javascript" src="tests/selection.py"></script>
- <script type="text/javascript" src="tests/apply.py"></script>
- <script type="text/javascript" src="tests/applyCSS.py"></script>
- <script type="text/javascript" src="tests/change.py"></script>
- <script type="text/javascript" src="tests/changeCSS.py"></script>
- <script type="text/javascript" src="tests/unapply.py"></script>
- <script type="text/javascript" src="tests/unapplyCSS.py"></script>
- <script type="text/javascript" src="tests/delete.py"></script>
- <script type="text/javascript" src="tests/forwarddelete.py"></script>
- <script type="text/javascript" src="tests/insert.py"></script>
- <script type="text/javascript" src="tests/querySupported.py"></script>
- <script type="text/javascript" src="tests/queryEnabled.py"></script>
- <script type="text/javascript" src="tests/queryIndeterm.py"></script>
- <script type="text/javascript" src="tests/queryState.py"></script>
- <script type="text/javascript" src="tests/queryValue.py"></script>
-
- <!-- Do something -->
- <script type="text/javascript">
- function runTest() {
- initVariables();
- initEditorDocs();
-
- runTestSuite(UNAPPLY_TESTS);
-
- // Below alert is just a simple demonstration on how to access the test results.
- // Note that we only ran UNAPPLY tests above, so we have only results from that test set.
- //
- // The 'results' structure is as follows:
- //
- // results structure containing all results
- // [<suite ID>] structure containing the results for the given suite *)
- // .count number of tests in the given suite
- // .valscore sum of all test value results (HTML or query value)
- // .selscore sum of all selection results (HTML tests only)
- // [<class ID>] structure containing the results for the given class **)
- // .count number of tests in the given suite
- // .valscore sum of all test value results (HTML or query value)
- // .selscore sum of all selection results (HTML tests only)
- // [<test ID>] structure containing the reults for a given test ***)
- // .valscore value score (0 or 1), minimum over all containers
- // .selscore selection score (0 or 1), minimum over all containers (HTML tests only)
- // .valresult worst test value result (integer, see variables.js)
- // .selresult worst selection result (integer, see variables.js)
- // [<cont. ID>] structure containing the results of the test for a given container ****)
- // .valscore value score (0 or 1)
- // .selscore selection score (0 or 1)
- // .valresult value result (integer, see variables.js)
- // .selresult selection result (integer, see variables.js)
- // .output output string (mainly for use by the online version)
- // .innerHTML inner HTML of the testing container (<div> or <body>) after the test
- // .outerHTML outer HTML of the testing container (<div> or <body>) after the test
- // .bodyInnerHTML inner HTML of the <body> after the test
- // .bodyOuterHTML outer HTML of the <body> after the test
- //
- // *) <suite ID>: a 1-3 character ID, e.g. UNAPPLY_TESTS.id, or 'U' (both referring the same suite)
- // **) <class ID>: one of 'Proposed', 'RFC' or 'Finalized'
- // ***) <test ID>: the ID of the test, without the leading 'RTE2-<suite ID>_' part
- // ****) <container ID>: one of 'div' (test within a <div contenteditable="true">)
- // 'dM' (test with designMode = 'on')
- // 'body' (test within a <body contenteditable="true">)
-
- alert("Result of 'Apply' tests:\nOut of " +
- results[UNAPPLY_TESTS.id].count + " tests\n" +
- results[UNAPPLY_TESTS.id].valscore + " had correct HTML, and\n" +
- results[UNAPPLY_TESTS.id].selscore + " had a correct result selection\n(in all testing containers)." +
- "\n\n" +
- "Test RTE2-U_B_B-1_SW results with a contenteditable <body>:\n" +
- results['U']['Proposed']['B_B-1_SW']['body'].valscore + " points for the value result, and\n" +
- results['U']['Proposed']['B_B-1_SW']['body'].selscore + " points for the selection" +
- ""
- );
- }
- </script>
-</head>
-
-<body onload="runTest()">
- <iframe name="iframe-dM" id="iframe-dM" src="static/editable-dM.html"></iframe>
- <iframe name="iframe-body" id="iframe-body" src="static/editable-body.html"></iframe>
- <iframe name="iframe-div" id="iframe-div" src="static/editable-div.html"></iframe>
-</body>
-</html>
diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/update_from_upstream b/editor/libeditor/tests/browserscope/lib/richtext2/update_from_upstream
deleted file mode 100644
index baeb76745..000000000
--- a/editor/libeditor/tests/browserscope/lib/richtext2/update_from_upstream
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/sh
-
-set -x
-
-if test -d richtext2; then
- rm -drf richtext2;
-fi
-
-svn checkout http://browserscope.googlecode.com/svn/trunk/categories/richtext2 richtext2 | tail -1 | sed 's/[^0-9]//g' > current_revision
-
-find richtext2 -type d -name .svn -exec rm -drf \{\} \; 2> /dev/null
-
-# Remove test_set.py and other similarly named files because they confuse our mochitest runner
-find richtext2 =type f -name test_\* -exec rm -rf \{\} \; 2> /dev/null
-
-hg add current_revision richtext2
-
-hg stat .
-
diff --git a/editor/libeditor/tests/browserscope/mochitest.ini b/editor/libeditor/tests/browserscope/mochitest.ini
deleted file mode 100644
index e6e2db413..000000000
--- a/editor/libeditor/tests/browserscope/mochitest.ini
+++ /dev/null
@@ -1,59 +0,0 @@
-[default]
-support-files =
- lib/richtext2/current_revision
- lib/richtext2/richtext2/common.py
- lib/richtext2/richtext2/unittestexample.html
- lib/richtext2/richtext2/static/editable-dM.html
- lib/richtext2/richtext2/static/editable.css
- lib/richtext2/richtext2/static/editable-body.html
- lib/richtext2/richtext2/static/editable-div.html
- lib/richtext2/richtext2/static/js/variables.js
- lib/richtext2/richtext2/static/js/range-bootstrap.js
- lib/richtext2/richtext2/static/js/range.js
- lib/richtext2/richtext2/static/js/output.js
- lib/richtext2/richtext2/static/js/compare.js
- lib/richtext2/richtext2/static/js/canonicalize.js
- lib/richtext2/richtext2/static/js/pad.js
- lib/richtext2/richtext2/static/js/run.js
- lib/richtext2/richtext2/static/js/units.js
- lib/richtext2/richtext2/static/common.css
- lib/richtext2/richtext2/__init__.py
- lib/richtext2/richtext2/handlers.py
- lib/richtext2/richtext2/templates/output.html
- lib/richtext2/richtext2/templates/richtext2.html
- lib/richtext2/richtext2/tests/forwarddelete.py
- lib/richtext2/richtext2/tests/selection.py
- lib/richtext2/richtext2/tests/queryIndeterm.py
- lib/richtext2/richtext2/tests/unapplyCSS.py
- lib/richtext2/richtext2/tests/apply.py
- lib/richtext2/richtext2/tests/unapply.py
- lib/richtext2/richtext2/tests/change.py
- lib/richtext2/richtext2/tests/queryState.py
- lib/richtext2/richtext2/tests/queryValue.py
- lib/richtext2/richtext2/tests/__init__.py
- lib/richtext2/richtext2/tests/insert.py
- lib/richtext2/richtext2/tests/queryEnabled.py
- lib/richtext2/richtext2/tests/applyCSS.py
- lib/richtext2/richtext2/tests/changeCSS.py
- lib/richtext2/richtext2/tests/delete.py
- lib/richtext2/richtext2/tests/querySupported.py
- lib/richtext2/README
- lib/richtext2/update_from_upstream
- lib/richtext2/LICENSE
- lib/richtext2/README.Mozilla
- lib/richtext2/currentStatus.js
- lib/richtext/current_revision
- lib/richtext/README
- lib/richtext/update_from_upstream
- lib/richtext/LICENSE
- lib/richtext/README.Mozilla
- lib/richtext/richtext/editable.html
- lib/richtext/richtext/richtext.html
- lib/richtext/richtext/js/range.js
- lib/richtext/currentStatus.js
-
-[test_richtext2.html]
-subsuite = clipboard
-skip-if = os == 'android' && debug # Bug 1202045
-[test_richtext.html]
-
diff --git a/editor/libeditor/tests/browserscope/test_richtext.html b/editor/libeditor/tests/browserscope/test_richtext.html
deleted file mode 100644
index 45f8bef38..000000000
--- a/editor/libeditor/tests/browserscope/test_richtext.html
+++ /dev/null
@@ -1,48 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-BrowserScope richtext category tests
--->
-<head>
- <title>BrowserScope Richtext Tests</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <script type="text/javascript" src="lib/richtext/currentStatus.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=550569">Mozilla Bug 550569</a>
-<p id="display"></p>
-<div id="content">
- <iframe src="lib/richtext/richtext/richtext.html"></iframe>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-SimpleTest.waitForExplicitFinish();
-// Running all of the tests can take a long time, try to account for it
-SimpleTest.requestLongerTimeout(5);
-
-function sendScore(results, continueParams) {
- ok(results.length > 1, "At least one test should have been run");
- for (var i = 1; i < results.length; ++i) {
- var result = results[i];
- [type, command, param, success] = result.split(/[\-=]/);
- var comp = is;
- if (isKnownFailure(type, command, param)) {
- comp = todo_is;
- }
- comp(success, "1", "Browserscope richtext category=" + type +
- " test=" + command +
- " param=" + param);
- }
-}
-
-document.getElementsByTagName("iframe")[0].addEventListener("load", function() {
- SimpleTest.finish();
-}, false);
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/browserscope/test_richtext2.html b/editor/libeditor/tests/browserscope/test_richtext2.html
deleted file mode 100644
index c0ce07a8f..000000000
--- a/editor/libeditor/tests/browserscope/test_richtext2.html
+++ /dev/null
@@ -1,233 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<!--
-BrowserScope richtext2 category tests
-
-This test is originally based on the unit test example available as part of the
-RichText2 suite:
-http://code.google.com/p/browserscope/source/browse/trunk/categories/richtext2/unittestexample.html
--->
-<head>
- <meta http-equiv="content-type" content="text/html; charset=utf-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
-
- <title>BrowserScope Richtext2 Tests</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-
- <!-- utility scripts -->
- <script type="text/javascript" src="lib/richtext2/richtext2/static/js/variables.js"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/static/js/canonicalize.js"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/static/js/compare.js"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/static/js/pad.js"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/static/js/range.js"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/static/js/units.js"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/static/js/run.js"></script>
- <!-- you do not need static/js/output.js -->
-
- <!--
- Tests - note that those have the extensions .py,
- but can be used as JS files directly.
- -->
- <script type="text/javascript" src="lib/richtext2/richtext2/tests/selection.py"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/tests/apply.py"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/tests/applyCSS.py"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/tests/change.py"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/tests/changeCSS.py"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/tests/unapply.py"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/tests/unapplyCSS.py"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/tests/delete.py"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/tests/forwarddelete.py"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/tests/insert.py"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/tests/querySupported.py"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/tests/queryEnabled.py"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/tests/queryIndeterm.py"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/tests/queryState.py"></script>
- <script type="text/javascript" src="lib/richtext2/richtext2/tests/queryValue.py"></script>
-
- <script type="text/javascript" src="lib/richtext2/currentStatus.js"></script>
-
- <!-- Do something -->
- <script type="text/javascript">
- // Set this constant to true in order to get the current status of the test suite.
- // This is useful for updating the currentStatus.js file when an editor bug is fixed.
- const UPDATE_TEST_RESULTS = false;
-
- // some tests (at least RTE2-QE_PASTE_TEXT-1) require clipboard data
- function startTest() {
- SimpleTest.waitForClipboard("foo",
- function() {
- SpecialPowers.clipboardCopyString("foo");
- },
- runTest,
- function() {
- ok(false, "Failed to copy a string to the clipboard");
- SimpleTest.finish();
- }
- );
- }
-
- function runTest() {
- initVariables();
- initEditorDocs();
-
- const tests = [
- SELECTION_TESTS,
- APPLY_TESTS,
- APPLY_TESTS_CSS,
- CHANGE_TESTS,
- CHANGE_TESTS_CSS,
- UNAPPLY_TESTS,
- UNAPPLY_TESTS_CSS,
- DELETE_TESTS,
- FORWARDDELETE_TESTS,
- INSERT_TESTS,
- QUERYSUPPORTED_TESTS,
- QUERYENABLED_TESTS,
- QUERYINDETERM_TESTS,
- QUERYSTATE_TESTS,
- QUERYVALUE_TESTS,
- ];
-
- for (var i = 0; i < tests.length; ++i) {
- runTestSuite(tests[i]);
- }
-
- // Below alert is just a simple demonstration on how to access the test results.
- // Note that we only ran UNAPPLY tests above, so we have only results from that test set.
- //
- // The 'results' structure is as follows:
- //
- // results structure containing all results
- // [<suite ID>] structure containing the results for the given suite *)
- // .count number of tests in the given suite
- // .valscore sum of all test value results (HTML or query value)
- // .selscore sum of all selection results (HTML tests only)
- // [<class ID>] structure containing the results for the given class **)
- // .count number of tests in the given suite
- // .valscore sum of all test value results (HTML or query value)
- // .selscore sum of all selection results (HTML tests only)
- // [<test ID>] structure containing the reults for a given test ***)
- // .valscore value score (0 or 1), minimum over all containers
- // .selscore selection score (0 or 1), minimum over all containers (HTML tests only)
- // .valresult worst test value result (integer, see variables.js)
- // .selresult worst selection result (integer, see variables.js)
- // [<cont. ID>] structure containing the results of the test for a given container ****)
- // .valscore value score (0 or 1)
- // .selscore selection score (0 or 1)
- // .valresult value result (integer, see variables.js)
- // .selresult selection result (integer, see variables.js)
- // .output output string (mainly for use by the online version)
- // .innerHTML inner HTML of the testing container (<div> or <body>) after the test
- // .outerHTML outer HTML of the testing container (<div> or <body>) after the test
- // .bodyInnerHTML inner HTML of the <body> after the test
- // .bodyOuterHTML outer HTML of the <body> after the test
- //
- // *) <suite ID>: a 1-3 character ID, e.g. UNAPPLY_TESTS.id, or 'U' (both referring the same suite)
- // **) <class ID>: one of 'Proposed', 'RFC' or 'Finalized'
- // ***) <test ID>: the ID of the test, without the leading 'RTE2-<suite ID>_' part
- // ****) <container ID>: one of 'div' (test within a <div contenteditable="true">)
- // 'dM' (test with designMode = 'on')
- // 'body' (test within a <body contenteditable="true">)
-
- if (UPDATE_TEST_RESULTS) {
- var newKnownFailures = {value: {}, select: {}};
- for (var i = 0; i < tests.length; ++i) {
- var category = tests[i];
- for (var group in results[category.id]) {
- switch (group) {
- // Skip the known properties
- case "count":
- case "valscore":
- case "selscore":
- case "time":
- break;
- default:
- for (var test_id in results[category.id][group]) {
- switch (test_id) {
- // Skip the known properties
- case "count":
- case "valscore":
- case "selscore":
- break;
- default:
- for (var structure in results[category.id][group][test_id]) {
- switch (structure) {
- // Only look at each test structure
- case "dM":
- case "body":
- case "div":
- if (!results[category.id][group][test_id][structure].valscore) {
- newKnownFailures.value[category.id + "-" + group + "-" + test_id + "-" + structure] = true;
- }
- if (!results[category.id][group][test_id][structure].selscore) {
- newKnownFailures.select[category.id + "-" + group + "-" + test_id + "-" + structure] = true;
- }
- }
- }
- }
- }
- }
- }
- }
- var resultContainer = document.getElementById("results");
- resultContainer.style.display = "";
- resultContainer.textContent = JSON.stringify(newKnownFailures);
- } else {
- for (var i = 0; i < tests.length; ++i) {
- var category = tests[i];
- for (var group in results[category.id]) {
- switch (group) {
- // Skip the known properties
- case "count":
- case "valscore":
- case "selscore":
- case "time":
- break;
- default:
- for (var test_id in results[category.id][group]) {
- switch (test_id) {
- // Skip the known properties
- case "count":
- case "valscore":
- case "selscore":
- break;
- default:
- for (var structure in results[category.id][group][test_id]) {
- switch (structure) {
- // Only look at each test structure
- case "dM":
- case "body":
- case "div":
- var row = results[category.id][group][test_id][structure];
- var testName = [category.id, group, test_id, structure].join("-");
- (testName in knownFailures.value ? todo_is : is)(
- row.valscore, 1, "Browserscope richtext2 value: " + testName);
- (testName in knownFailures.select ? todo_is : is)(
- row.selscore, 1, "Browserscope richtext2 selection: " + testName);
- }
- }
- }
- }
- }
- }
- }
- }
-
- SimpleTest.finish();
- }
-
- SimpleTest.waitForExplicitFinish();
- // Running all of the tests can take a long time, try to account for it
- SimpleTest.requestLongerTimeout(5);
- </script>
-</head>
-
-<body onload="startTest()">
- <iframe name="iframe-dM" id="iframe-dM" src="lib/richtext2/richtext2/static/editable-dM.html"></iframe>
- <iframe name="iframe-body" id="iframe-body" src="lib/richtext2/richtext2/static/editable-body.html"></iframe>
- <iframe name="iframe-div" id="iframe-div" src="lib/richtext2/richtext2/static/editable-div.html"></iframe>
- <pre id="results" style="display: none"></pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/bug527935.html b/editor/libeditor/tests/bug527935.html
deleted file mode 100644
index 1731734d2..000000000
--- a/editor/libeditor/tests/bug527935.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<body>
-<div id="content">
- <iframe id="formTarget" name="formTarget"></iframe>
- <form action="bug527935_2.html" target="formTarget">
- <input name="test" id="initValue"><input type="submit">
- </form>
-</div>
-</body>
-</html
diff --git a/editor/libeditor/tests/bug527935_2.html b/editor/libeditor/tests/bug527935_2.html
deleted file mode 100644
index 96af0721d..000000000
--- a/editor/libeditor/tests/bug527935_2.html
+++ /dev/null
@@ -1 +0,0 @@
-<html><body>dummy page</body></html>
diff --git a/editor/libeditor/tests/bug629172.html b/editor/libeditor/tests/bug629172.html
deleted file mode 100644
index e583b2d44..000000000
--- a/editor/libeditor/tests/bug629172.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
-<style>
-textarea { resize: none }
-</style>
-</head>
-<body>
-<div id="content">
-<textarea id="ltr-ref" style="display: none">test.</textarea>
-<textarea id="rtl-ref" style="display: none; direction: rtl">test.</textarea>
-</div
-</body>
-</html>
diff --git a/editor/libeditor/tests/chrome.ini b/editor/libeditor/tests/chrome.ini
deleted file mode 100644
index dd13370a5..000000000
--- a/editor/libeditor/tests/chrome.ini
+++ /dev/null
@@ -1,15 +0,0 @@
-[DEFAULT]
-skip-if = os == 'android'
-support-files = green.png
-
-[test_bug489202.xul]
-[test_bug599983.xul]
-[test_bug607584.xul]
-[test_bug616590.xul]
-[test_bug780908.xul]
-[test_contenteditable_text_input_handling.html]
-[test_htmleditor_keyevent_handling.html]
-[test_set_document_title_transaction.html]
-[test_texteditor_keyevent_handling.html]
-skip-if = (debug && os=='win') || (os == 'linux') # Bug 1116205, leaks on windows debug, fails delete key on linux
-[test_pasteImgTextarea.xul]
diff --git a/editor/libeditor/tests/data/cfhtml-chromium.txt b/editor/libeditor/tests/data/cfhtml-chromium.txt
deleted file mode 100644
index 7e0253715..000000000
--- a/editor/libeditor/tests/data/cfhtml-chromium.txt
+++ /dev/null
Binary files differ
diff --git a/editor/libeditor/tests/data/cfhtml-firefox.txt b/editor/libeditor/tests/data/cfhtml-firefox.txt
deleted file mode 100644
index cc686d856..000000000
--- a/editor/libeditor/tests/data/cfhtml-firefox.txt
+++ /dev/null
Binary files differ
diff --git a/editor/libeditor/tests/data/cfhtml-ie.txt b/editor/libeditor/tests/data/cfhtml-ie.txt
deleted file mode 100644
index a30bc5295..000000000
--- a/editor/libeditor/tests/data/cfhtml-ie.txt
+++ /dev/null
Binary files differ
diff --git a/editor/libeditor/tests/data/cfhtml-nocontext.txt b/editor/libeditor/tests/data/cfhtml-nocontext.txt
deleted file mode 100644
index aa4882227..000000000
--- a/editor/libeditor/tests/data/cfhtml-nocontext.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-Version:0.9
-StartHTML:-1
-EndHTML:-1
-StartFragment:0000000111
-EndFragment:0000000246
-<!--StartFragment-->
-<html>
- <head>
- <title>Test</title>
-
- </head>
- <body>
- <p>
- 3.<b>1415926535897932</b>
- </p>
- </body>
-</html>
-<!--EndFragment-->
diff --git a/editor/libeditor/tests/data/cfhtml-ooo.txt b/editor/libeditor/tests/data/cfhtml-ooo.txt
deleted file mode 100644
index 0bcf7616e..000000000
--- a/editor/libeditor/tests/data/cfhtml-ooo.txt
+++ /dev/null
Binary files differ
diff --git a/editor/libeditor/tests/file_bug549262.html b/editor/libeditor/tests/file_bug549262.html
deleted file mode 100644
index 92a0c76f3..000000000
--- a/editor/libeditor/tests/file_bug549262.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <a href="">test</a>
- <div id="editor" contenteditable="true">abc</div>
- <div style="height: 20000px;"></div>
- </body>
-</html>
diff --git a/editor/libeditor/tests/file_bug586662.html b/editor/libeditor/tests/file_bug586662.html
deleted file mode 100644
index 298953197..000000000
--- a/editor/libeditor/tests/file_bug586662.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <div style="height: 20000px;"></div>
- <textarea id="editor"></textarea>
- </body>
-</html>
diff --git a/editor/libeditor/tests/file_bug635636_2.html b/editor/libeditor/tests/file_bug635636_2.html
deleted file mode 100644
index bf0c8101f..000000000
--- a/editor/libeditor/tests/file_bug635636_2.html
+++ /dev/null
@@ -1 +0,0 @@
-<html><body>2</body></html>
diff --git a/editor/libeditor/tests/file_bug674770-1.html b/editor/libeditor/tests/file_bug674770-1.html
deleted file mode 100644
index 6750bb878..000000000
--- a/editor/libeditor/tests/file_bug674770-1.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE>
-<script>
- localStorage["clicked"] = "true";
- close();
-</script>
diff --git a/editor/libeditor/tests/file_bug915962.html b/editor/libeditor/tests/file_bug915962.html
deleted file mode 100644
index 85c5139d3..000000000
--- a/editor/libeditor/tests/file_bug915962.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <button>Button</button>
- <img src="green.png" usemap="#map">
- <map name="map">
- <!-- This URL ensures that the link doesn't get clicked, since
- mochitests cannot access the outside network. -->
- <area shape="rect" coords="0,0,10,10" href="https://youtube.com/">
- </map>
- <div style="height: 20000px;" tabindex="-1"><hr></div>
- </body>
-</html>
diff --git a/editor/libeditor/tests/file_bug966155.html b/editor/libeditor/tests/file_bug966155.html
deleted file mode 100644
index 04f55a918..000000000
--- a/editor/libeditor/tests/file_bug966155.html
+++ /dev/null
@@ -1 +0,0 @@
-<input><iframe onload="contentDocument.designMode = 'on';">
diff --git a/editor/libeditor/tests/file_bug966552.html b/editor/libeditor/tests/file_bug966552.html
deleted file mode 100644
index 5061c2e40..000000000
--- a/editor/libeditor/tests/file_bug966552.html
+++ /dev/null
@@ -1 +0,0 @@
-<body onload="document.designMode='on'">test</body>
diff --git a/editor/libeditor/tests/file_select_all_without_body.html b/editor/libeditor/tests/file_select_all_without_body.html
deleted file mode 100644
index 70050a847..000000000
--- a/editor/libeditor/tests/file_select_all_without_body.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<html>
-<head>
-<script type="text/javascript">
-
-function is(aLeft, aRight, aMessage)
-{
- window.opener.SimpleTest.is(aLeft, aRight, aMessage);
-}
-
-function unload()
-{
- window.opener.SimpleTest.finish();
-}
-
-function boom()
-{
- var root = document.documentElement;
- while(root.firstChild) {
- root.removeChild(root.firstChild);
- }
- root.appendChild(document.createTextNode("Mozilla"));
- root.focus();
- cespan = document.createElementNS("http://www.w3.org/1999/xhtml", "span");
- cespan.setAttributeNS(null, "contenteditable", "true");
- root.appendChild(cespan);
- try {
- document.execCommand("selectAll", false, null);
- } catch(e) { }
-
- is(window.getSelection().toString(), "Mozilla",
- "The nodes are not selected");
-
- window.close();
-}
-
-window.opener.SimpleTest.waitForFocus(boom, window);
-
-</script></head>
-
-<body onunload="unload();"></body>
-</html>
diff --git a/editor/libeditor/tests/green.png b/editor/libeditor/tests/green.png
deleted file mode 100644
index 0aaec2093..000000000
--- a/editor/libeditor/tests/green.png
+++ /dev/null
Binary files differ
diff --git a/editor/libeditor/tests/mochitest.ini b/editor/libeditor/tests/mochitest.ini
deleted file mode 100644
index 33b164819..000000000
--- a/editor/libeditor/tests/mochitest.ini
+++ /dev/null
@@ -1,251 +0,0 @@
-[DEFAULT]
-support-files =
- data/cfhtml-chromium.txt
- data/cfhtml-firefox.txt
- data/cfhtml-ie.txt
- data/cfhtml-ooo.txt
- data/cfhtml-nocontext.txt
- file_bug549262.html
- file_bug586662.html
- file_bug674770-1.html
- file_bug915962.html
- file_select_all_without_body.html
- green.png
- spellcheck.js
-
-[test_bug46555.html]
-[test_bug200416.html]
-[test_bug289384.html]
-skip-if = os != "mac"
-[test_bug290026.html]
-[test_bug291780.html]
-[test_bug309731.html]
-[test_bug316447.html]
-[test_bug318065.html]
-[test_bug332636.html]
-support-files = test_bug332636.html^headers^
-[test_bug366682.html]
-skip-if = os == 'android'
-[test_bug372345.html]
-skip-if = toolkit == 'android'
-[test_bug404320.html]
-[test_bug408231.html]
-skip-if = toolkit == 'android'
-[test_bug410986.html]
-subsuite = clipboard
-skip-if = toolkit == 'android'
-[test_bug414526.html]
-[test_bug417418.html]
-skip-if = android_version == '18' # bug 1147989
-[test_bug432225.html]
-skip-if = toolkit == 'android'
-[test_bug439808.html]
-[test_bug442186.html]
-[test_bug449243.html]
-[test_bug455992.html]
-[test_bug456244.html]
-[test_bug460740.html]
-[test_bug468353.html]
-[test_bug471319.html]
-[test_bug471722.html]
-[test_bug478725.html]
-subsuite = clipboard
-skip-if = toolkit == 'android'
-[test_bug480647.html]
-[test_bug480972.html]
-subsuite = clipboard
-skip-if = toolkit == 'android'
-[test_bug483651.html]
-[test_bug484181.html]
-skip-if = toolkit == 'android'
-[test_bug487524.html]
-[test_bug490879.html]
-subsuite = clipboard
-skip-if = toolkit == 'android' # bug 1299578
-[test_bug502673.html]
-[test_bug514156.html]
-[test_bug520189.html]
-subsuite = clipboard
-skip-if = toolkit == 'android'
-[test_bug525389.html]
-subsuite = clipboard
-skip-if = toolkit == 'android'
-[test_bug537046.html]
-[test_bug549262.html]
-skip-if = toolkit == 'android'
-[test_bug550434.html]
-skip-if = android_version == '18' # bug 1147989
-[test_bug551704.html]
-subsuite = clipboard
-[test_bug552782.html]
-[test_bug567213.html]
-[test_bug569988.html]
-skip-if = os == 'android'
-[test_bug570144.html]
-[test_bug578771.html]
-skip-if = android_version == '18' # bug 1147989
-[test_bug586662.html]
-skip-if = toolkit == 'android'
-[test_bug587461.html]
-[test_bug590554.html]
-[test_bug592592.html]
-[test_bug596001.html]
-subsuite = clipboard
-[test_bug596333.html]
-skip-if = toolkit == 'android'
-[test_bug596506.html]
-[test_bug597331.html]
-skip-if = toolkit == 'android' || asan || (os == "win" && os_version != "5.1") # Bug 718316, Bug 1211213
-[test_bug597784.html]
-[test_bug599322.html]
-subsuite = clipboard
-skip-if = toolkit == 'android'
-[test_bug599983.html]
-[test_bug600570.html]
-subsuite = clipboard
-skip-if = toolkit == 'android' || (os == "win" && os_version != "5.1") # Bug 718316
-[test_bug602130.html]
-[test_bug603556.html]
-subsuite = clipboard
-[test_bug604532.html]
-skip-if = toolkit == 'android'
-[test_bug607584.html]
-[test_bug611182.html]
-skip-if = toolkit == 'android'
-[test_bug612128.html]
-[test_bug612447.html]
-[test_bug620906.html]
-skip-if = toolkit == 'android' #TIMED_OUT
-[test_bug622371.html]
-skip-if = toolkit == 'android' #bug 957797
-[test_bug625452.html]
-[test_bug629845.html]
-[test_bug635636.html]
-skip-if = e10s || os == 'android'
-[test_bug636465.html]
-skip-if = os == 'android'
-[test_bug638596.html]
-[test_bug640321.html]
-skip-if = android_version == '18' # bug 1147989
-[test_bug641466.html]
-[test_bug645914.html]
-[test_bug646194.html]
-[test_bug668599.html]
-[test_bug674770-1.html]
-subsuite = clipboard
-skip-if = toolkit == 'android'
-[test_bug674770-2.html]
-subsuite = clipboard
-skip-if = toolkit == 'android'
-[test_bug674861.html]
-[test_bug676401.html]
-[test_bug677752.html]
-[test_bug681229.html]
-subsuite = clipboard
-[test_bug686203.html]
-[test_bug692520.html]
-[test_bug697842.html]
-[test_bug725069.html]
-[test_bug735059.html]
-[test_bug738366.html]
-[test_bug740784.html]
-[test_bug742261.html]
-[test_bug757371.html]
-[test_bug757771.html]
-[test_bug767684.html]
-[test_bug772796.html]
-skip-if = toolkit == 'android' # bug 1309431
-[test_bug773262.html]
-[test_bug780035.html]
-[test_bug787432.html]
-[test_bug790475.html]
-[test_bug795418.html]
-[test_bug795418-2.html]
-[test_bug795418-3.html]
-[test_bug795418-4.html]
-[test_bug795418-5.html]
-[test_bug795418-6.html]
-[test_bug795785.html]
-[test_bug796839.html]
-[test_bug830600.html]
-subsuite = clipboard
-skip-if = e10s
-[test_bug832025.html]
-[test_bug850043.html]
-[test_bug857487.html]
-[test_bug858918.html]
-[test_bug915962.html]
-[test_bug974309.html]
-skip-if = toolkit == 'android'
-[test_bug966155.html]
-skip-if = os != "win"
-[test_bug966552.html]
-skip-if = os != "win"
-[test_bug998188.html]
-[test_bug1026397.html]
-[test_bug1053048.html]
-[test_bug1067255.html]
-[test_bug1068979.html]
-subsuite = clipboard
-[test_bug1094000.html]
-[test_bug1100966.html]
-skip-if = os == 'android'
-[test_bug1102906.html]
-skip-if = os == 'android'
-[test_bug1101392.html]
-subsuite = clipboard
-[test_bug1109465.html]
-[test_bug1140105.html]
-[test_bug1140617.html]
-subsuite = clipboard
-skip-if = toolkit == 'android' # bug 1299578
-[test_bug1153237.html]
-[test_bug1154791.html]
-skip-if = os == 'android'
-[test_bug1162952.html]
-[test_bug1181130-1.html]
-[test_bug1181130-2.html]
-[test_bug1186799.html]
-[test_bug1230473.html]
-[test_bug1247483.html]
-subsuite = clipboard
-skip-if = toolkit == 'android'
-[test_bug1248128.html]
-[test_bug1250010.html]
-[test_bug1257363.html]
-[test_bug1248185.html]
-[test_bug1258085.html]
-[test_bug1268736.html]
-[test_bug1270235.html]
-[test_bug1306532.html]
-subsuite = clipboard
-skip-if = toolkit == 'android'
-[test_bug1310912.html]
-skip-if = toolkit == 'android' # bug 1315898
-[test_bug1314790.html]
-[test_bug1315065.html]
-[test_bug1328023.html]
-[test_bug1330796.html]
-[test_bug1332876.html]
-[test_bug1352799.html]
-
-[test_CF_HTML_clipboard.html]
-subsuite = clipboard
-[test_composition_event_created_in_chrome.html]
-[test_contenteditable_focus.html]
-[test_dom_input_event_on_htmleditor.html]
-skip-if = toolkit == 'android' # bug 1054087
-[test_dom_input_event_on_texteditor.html]
-[test_dragdrop.html]
-skip-if = os == 'android'
-[test_keypress_untrusted_event.html]
-[test_root_element_replacement.html]
-[test_select_all_without_body.html]
-[test_spellcheck_pref.html]
-skip-if = toolkit == 'android'
-[test_backspace_vs.html]
-[test_css_chrome_load_access.html]
-skip-if = toolkit == 'android' # chrome urls not available due to packaging
-[test_selection_move_commands.html]
-[test_pasteImgTextarea.html]
-skip-if = toolkit == 'android' # bug 1299578
diff --git a/editor/libeditor/tests/spellcheck.js b/editor/libeditor/tests/spellcheck.js
deleted file mode 100644
index 9d36c3254..000000000
--- a/editor/libeditor/tests/spellcheck.js
+++ /dev/null
@@ -1,20 +0,0 @@
-function isSpellingCheckOk(aEditor, aMisspelledWords) {
- var selcon = aEditor.selectionController;
- var sel = selcon.getSelection(selcon.SELECTION_SPELLCHECK);
- var numWords = sel.rangeCount;
-
- is(numWords, aMisspelledWords.length, "Correct number of misspellings and words.");
-
- if (numWords !== aMisspelledWords.length) {
- return false;
- }
-
- for (var i = 0; i < numWords; ++i) {
- var word = String(sel.getRangeAt(i));
- is(word, aMisspelledWords[i], "Misspelling is what we think it is.");
- if (word !== aMisspelledWords[i]) {
- return false;
- }
- }
- return true;
-}
diff --git a/editor/libeditor/tests/test_CF_HTML_clipboard.html b/editor/libeditor/tests/test_CF_HTML_clipboard.html
deleted file mode 100644
index 4949f40b3..000000000
--- a/editor/libeditor/tests/test_CF_HTML_clipboard.html
+++ /dev/null
@@ -1,159 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=572642
--->
-<head>
- <title>Test for Bug 572642</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=572642">Mozilla Bug 572642</a>
-<p id="display"></p>
-<div id="content">
- <div id="editor1" contenteditable="true"></div>
- <iframe id="editor2"></iframe>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 572642 **/
-
-function copyCF_HTML(cfhtml, success, failure) {
- const Cc = SpecialPowers.Cc;
- const Ci = SpecialPowers.Ci;
- const CF_HTML = "application/x-moz-nativehtml";
-
- function getLoadContext() {
- return SpecialPowers.wrap(window).QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsILoadContext);
- }
-
- var cb = Cc["@mozilla.org/widget/clipboard;1"].
- getService(Ci.nsIClipboard);
-
- var counter = 0;
- function copyCF_HTML_worker(success, failure) {
- if (++counter > 50) {
- ok(false, "Timed out while polling clipboard for pasted data");
- failure();
- return;
- }
-
- var flavors = [CF_HTML];
- if (!cb.hasDataMatchingFlavors(flavors, flavors.length, cb.kGlobalClipboard)) {
- setTimeout(function() { copyCF_HTML_worker(success, failure); }, 100);
- return;
- }
-
- var trans = Cc["@mozilla.org/widget/transferable;1"].
- createInstance(Ci.nsITransferable);
- trans.init(getLoadContext());
- trans.addDataFlavor(CF_HTML);
- cb.getData(trans, cb.kGlobalClipboard);
- var data = SpecialPowers.createBlankObject();
- try {
- trans.getTransferData(CF_HTML, data, {});
- data = SpecialPowers.wrap(data).value.QueryInterface(Ci.nsISupportsCString).data;
- } catch (e) {
- setTimeout(function() { copyCF_HTML_worker(success, failure); }, 100);
- return;
- }
- success();
- }
-
- var trans = Cc["@mozilla.org/widget/transferable;1"].
- createInstance(Ci.nsITransferable);
- trans.init(getLoadContext());
- trans.addDataFlavor(CF_HTML);
- var data = Cc["@mozilla.org/supports-cstring;1"].
- createInstance(Ci.nsISupportsCString);
- data.data = cfhtml;
- trans.setTransferData(CF_HTML, data, cfhtml.length);
- cb.setData(trans, null, cb.kGlobalClipboard);
- copyCF_HTML_worker(success, failure);
-}
-
-function loadCF_HTMLdata(filename) {
- var req = new XMLHttpRequest();
- req.open("GET", filename, false);
- req.overrideMimeType("text/plain; charset=x-user-defined");
- req.send(null);
- ok(req.status, 200, "Could not read the binary file " + filename);
- return req.responseText;
-}
-
-var gTests = [
- // Copied from Firefox
- {fileName: "cfhtml-firefox.txt", expected: "Firefox"},
- // Copied from OpenOffice.org
- {fileName: "cfhtml-ooo.txt", expected: "hello"},
- // Copied from IE
- {fileName: "cfhtml-ie.txt", expected: "browser"},
- // Copied from Chromium
- {fileName: "cfhtml-chromium.txt", expected: "Pacific"},
- // CF_HTML with no context specified (StartHTML and EndHTML set to -1)
- {fileName: "cfhtml-nocontext.txt", expected: "3.1415926535897932"},
-];
-var gTestIndex = 0;
-
-SimpleTest.waitForExplicitFinish();
-
-for (var i = 0; i < gTests.length; ++i) {
- gTests[i].data = loadCF_HTMLdata("data/" + gTests[i].fileName);
-}
-
-function runTest() {
- var test = gTests[gTestIndex++];
-
- copyCF_HTML(test.data, function() {
- // contenteditable
- var contentEditable = document.getElementById("editor1");
- contentEditable.innerHTML = "";
- contentEditable.focus();
- synthesizeKey("v", {accelKey: true});
- isnot(contentEditable.textContent.indexOf(test.expected), -1,
- "Paste operation for " + test.fileName + " should be successful in contenteditable");
-
- // designMode
- var iframe = document.getElementById("editor2");
- iframe.addEventListener("load", function() {
- iframe.removeEventListener("load", arguments.callee, false);
- var doc = iframe.contentDocument;
- var win = doc.defaultView;
- setTimeout(function() {
- win.addEventListener("focus", function() {
- win.removeEventListener("focus", arguments.callee, false);
- doc.designMode = "on";
- synthesizeKey("v", {accelKey: true}, win);
- isnot(doc.body.textContent.indexOf(test.expected), -1,
- "Paste operation for " + test.fileName + " should be successful in designMode");
-
- if (gTestIndex == gTests.length)
- SimpleTest.finish();
- else
- runTest();
- }, false);
- win.focus();
- }, 0);
- }, false);
- iframe.src = "data:text/html,";
- }, SimpleTest.finish);
-}
-
-var isMac = ("nsILocalFileMac" in SpecialPowers.Ci);
-if (isMac)
- SimpleTest.waitForFocus(runTest);
-else {
- // This test is not yet supported on non-Mac platforms, see bug 574005.
- todo(false, "Test not supported on this platform");
- SimpleTest.finish();
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_backspace_vs.html b/editor/libeditor/tests/test_backspace_vs.html
deleted file mode 100644
index 1ee754c95..000000000
--- a/editor/libeditor/tests/test_backspace_vs.html
+++ /dev/null
@@ -1,130 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1216427
--->
-<head>
- <title>Test for Bug 1216427</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1216427">Mozilla Bug 1216427</a>
-<p id="display"></p>
-<div id="content">
- <div id="edit1" contenteditable="true">a&#x263a;&#xfe0f;b</div><!-- BMP symbol with VS16 -->
- <div id="edit2" contenteditable="true">a&#x1f310;&#xfe0e;b</div><!-- plane 1 symbol with VS15 -->
- <div id="edit3" contenteditable="true">a&#x3402;&#xE0100;b</div><!-- BMP ideograph with VS17 -->
- <div id="edit4" contenteditable="true">a&#x20000;&#xE0101;b</div><!-- SMP ideograph with VS18 -->
- <div id="edit5" contenteditable="true">a&#x263a;&#xfe01;&#xfe02;&#xfe03;b</div><!-- BMP symbol with extra VSes -->
- <div id="edit6" contenteditable="true">a&#x20000;&#xE0100;&#xE0101;&#xE0102;b</div><!-- SMP symbol with extra VSes -->
- <!-- The Regional Indicator combinations here were supported by Apple Color Emoji
- even prior to the major extension of coverage in the 10.10.5 timeframe. -->
- <div id="edit7" contenteditable="true">a&#x1F1E8;&#x1F1F3;b</div><!-- Regional Indicator flag: CN -->
- <div id="edit8" contenteditable="true">a&#x1F1E8;&#x1F1F3;&#x1F1E9;&#x1F1EA;b</div><!-- two RI flags: CN, DE -->
- <div id="edit9" contenteditable="true">a&#x1F1E8;&#x1F1F3;&#x1F1E9;&#x1F1EA;&#x1F1EA;&#x1F1F8;b</div><!-- three RI flags: CN, DE, ES -->
- <div id="edit10" contenteditable="true">a&#x1F1E8;&#x1F1F3;&#x1F1E9;&#x1F1EA;&#x1F1EA;&#x1F1F8;&#x1F1EB;&#x1F1F7;b</div><!-- four RI flags: CN, DE, ES, FR -->
- <div id="edit11" contenteditable="true">a&#x1F1E8;&#x1F1F3;&#x1F1E9;&#x1F1EA;&#x1F1EA;&#x1F1F8;&#x1F1EB;&#x1F1F7;&#x1F1EC;&#x1F1E7;b</div><!-- five RI flags: CN, DE, ES, FR, GB -->
-
- <div id="edit1b" contenteditable="true">a&#x263a;&#xfe0f;b</div><!-- BMP symbol with VS16 -->
- <div id="edit2b" contenteditable="true">a&#x1f310;&#xfe0e;b</div><!-- plane 1 symbol with VS15 -->
- <div id="edit3b" contenteditable="true">a&#x3402;&#xE0100;b</div><!-- BMP ideograph with VS17 -->
- <div id="edit4b" contenteditable="true">a&#x20000;&#xE0101;b</div><!-- SMP ideograph with VS18 -->
- <div id="edit5b" contenteditable="true">a&#x263a;&#xfe01;&#xfe02;&#xfe03;b</div><!-- BMP symbol with extra VSes -->
- <div id="edit6b" contenteditable="true">a&#x20000;&#xE0100;&#xE0101;&#xE0102;b</div><!-- SMP symbol with extra VSes -->
- <div id="edit7b" contenteditable="true">a&#x1F1E8;&#x1F1F3;b</div><!-- Regional Indicator flag: CN -->
- <div id="edit8b" contenteditable="true">a&#x1F1E8;&#x1F1F3;&#x1F1E9;&#x1F1EA;b</div><!-- two RI flags: CN, DE -->
- <div id="edit9b" contenteditable="true">a&#x1F1E8;&#x1F1F3;&#x1F1E9;&#x1F1EA;&#x1F1EA;&#x1F1F8;b</div><!-- three RI flags: CN, DE, ES -->
- <div id="edit10b" contenteditable="true">a&#x1F1E8;&#x1F1F3;&#x1F1E9;&#x1F1EA;&#x1F1EA;&#x1F1F8;&#x1F1EB;&#x1F1F7;b</div><!-- four RI flags: CN, DE, ES, FR -->
- <div id="edit11b" contenteditable="true">a&#x1F1E8;&#x1F1F3;&#x1F1E9;&#x1F1EA;&#x1F1EA;&#x1F1F8;&#x1F1EB;&#x1F1F7;&#x1F1EC;&#x1F1E7;b</div><!-- five RI flags: CN, DE, ES, FR, GB -->
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 1216427 **/
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(runTest);
-
-function test(edit, bsCount) {
- edit.focus();
- var sel = window.getSelection();
- sel.collapse(edit.childNodes[0], edit.textContent.length - 1);
- for (i = 0; i < bsCount; ++i) {
- synthesizeKey("VK_BACK_SPACE", {});
- }
- is(edit.textContent, "ab", "The backspace key should delete the characters correctly");
-}
-
-function testWithMove(edit, offset, bsCount) {
- edit.focus();
- var sel = window.getSelection();
- sel.collapse(edit.childNodes[0], 0);
- var i;
- for (i = 0; i < offset; ++i) {
- synthesizeKey("VK_RIGHT", {});
- synthesizeKey("VK_LEFT", {});
- synthesizeKey("VK_RIGHT", {});
- }
- for (i = 0; i < bsCount; ++i) {
- synthesizeKey("VK_BACK_SPACE", {});
- }
- is(edit.textContent, "ab", "The backspace key should delete the characters correctly");
-}
-
-function runTest() {
- /* test backspace-deletion of the middle character(s) */
- test(document.getElementById("edit1"), 1);
- test(document.getElementById("edit2"), 1);
- test(document.getElementById("edit3"), 1);
- test(document.getElementById("edit4"), 1);
- test(document.getElementById("edit5"), 1);
- test(document.getElementById("edit6"), 1);
-
- /*
- * Tests with Regional Indicator flags: these behave differently depending
- * whether an emoji font is present, as ligated flags are edited as single
- * characters whereas non-ligated RI characters act individually.
- *
- * For now, only rely on such an emoji font on OS X 10.7+. (Note that the
- * Segoe UI Emoji font on Win8.1 and Win10 does not implement Regional
- * Indicator flags.)
- *
- * Once the Firefox Emoji font is ready, we can load that via @font-face
- * and expect these tests to work across all platforms.
- */
- hasEmojiFont =
- (navigator.platform.indexOf("Mac") == 0 &&
- /10\.([7-9]|[1-9][0-9])/.test(navigator.oscpu));
-
- if (hasEmojiFont) {
- test(document.getElementById("edit7"), 1);
- test(document.getElementById("edit8"), 2);
- test(document.getElementById("edit9"), 3);
- test(document.getElementById("edit10"), 4);
- test(document.getElementById("edit11"), 5);
- }
-
- /* extra tests with the use of RIGHT and LEFT to get to the right place */
- testWithMove(document.getElementById("edit1b"), 2, 1);
- testWithMove(document.getElementById("edit2b"), 2, 1);
- testWithMove(document.getElementById("edit3b"), 2, 1);
- testWithMove(document.getElementById("edit4b"), 2, 1);
- testWithMove(document.getElementById("edit5b"), 2, 1);
- testWithMove(document.getElementById("edit6b"), 2, 1);
- if (hasEmojiFont) {
- testWithMove(document.getElementById("edit7b"), 2, 1);
- testWithMove(document.getElementById("edit8b"), 3, 2);
- testWithMove(document.getElementById("edit9b"), 4, 3);
- testWithMove(document.getElementById("edit10b"), 5, 4);
- testWithMove(document.getElementById("edit11b"), 6, 5);
- }
-
- SimpleTest.finish();
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1026397.html b/editor/libeditor/tests/test_bug1026397.html
deleted file mode 100644
index 487f3e87f..000000000
--- a/editor/libeditor/tests/test_bug1026397.html
+++ /dev/null
@@ -1,103 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1026397
--->
-<head>
- <title>Test for Bug 1026397</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1026397">Mozilla Bug 1026397</a>
-<p id="display"></p>
-<div id="content">
-<input id="input">
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 1026397 **/
-SimpleTest.waitForExplicitFinish();
-
-function runTests()
-{
- var input = document.getElementById("input");
- input.focus();
-
- function doTest(aMaxLength, aInitialValue, aCaretOffset,
- aInsertString, aExpectedValueDuringComposition,
- aExpectedValueAfterCompositionEnd, aAdditionalExplanation)
- {
- input.value = aInitialValue;
- var maxLengthStr = "";
- if (aMaxLength >= 0) {
- input.maxLength = aMaxLength;
- maxLengthStr = aMaxLength.toString();
- } else {
- input.removeAttribute("maxlength");
- maxLengthStr = "not specified";
- }
- input.selectionStart = input.selectionEnd = aCaretOffset;
- if (aAdditionalExplanation) {
- aAdditionalExplanation = " " + aAdditionalExplanation;
- } else {
- aAdditionalExplanation = "";
- }
-
- synthesizeCompositionChange(
- { "composition":
- { "string": aInsertString,
- "clauses":
- [
- { "length": aInsertString.length, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
- ]
- },
- "caret": { "start": aInsertString.length, "length": 0 }
- });
- is(input.value, aExpectedValueDuringComposition,
- "The value of input whose maxlength is " + maxLengthStr + " should be "
- + aExpectedValueDuringComposition + " during composition" + aAdditionalExplanation);
- synthesizeComposition({ type: "compositioncommitasis" });
- is(input.value, aExpectedValueAfterCompositionEnd,
- "The value of input whose maxlength is " + maxLengthStr + " should be "
- + aExpectedValueAfterCompositionEnd + " after compositionend" + aAdditionalExplanation);
- }
-
- // maxlength hasn't been specified yet.
- doTest(-1, "", 0, "\uD842\uDFB7\u91CE\u5BB6", "\uD842\uDFB7\u91CE\u5BB6", "\uD842\uDFB7\u91CE\u5BB6");
-
- // maxlength="1"
- doTest(1, "", 0, "\uD842\uDFB7\u91CE\u5BB6", "\uD842\uDFB7\u91CE\u5BB6", "");
-
- // maxlength="2"
- doTest(2, "", 0, "\uD842\uDFB7\u91CE\u5BB6", "\uD842\uDFB7\u91CE\u5BB6", "\uD842\uDFB7");
- doTest(2, "X", 1, "\uD842\uDFB7\u91CE\u5BB6", "X\uD842\uDFB7\u91CE\u5BB6", "X");
- doTest(2, "Y", 0, "\uD842\uDFB7\u91CE\u5BB6", "\uD842\uDFB7\u91CE\u5BB6Y", "Y");
-
- // maxlength="3"
- doTest(3, "", 0, "\uD842\uDFB7\u91CE\u5BB6", "\uD842\uDFB7\u91CE\u5BB6", "\uD842\uDFB7\u91CE");
- doTest(3, "A", 1, "\uD842\uDFB7\u91CE\u5BB6", "A\uD842\uDFB7\u91CE\u5BB6", "A\uD842\uDFB7");
- doTest(3, "B", 0, "\uD842\uDFB7\u91CE\u5BB6", "\uD842\uDFB7\u91CE\u5BB6B", "\uD842\uDFB7B");
- doTest(3, "CD", 1, "\uD842\uDFB7\u91CE\u5BB6", "C\uD842\uDFB7\u91CE\u5BB6D", "CD");
-
- // maxlength="4"
- doTest(4, "EF", 1, "\uD842\uDFB7\u91CE\u5BB6", "E\uD842\uDFB7\u91CE\u5BB6F", "E\uD842\uDFB7F");
- doTest(4, "GHI", 1, "\uD842\uDFB7\u91CE\u5BB6", "G\uD842\uDFB7\u91CE\u5BB6HI", "GHI");
-
- // maxlength="1", inputting only high surrogate
- doTest(1, "", 0, "\uD842", "\uD842", "\uD842", "even if input string is only a high surrogate");
-
- // maxlength="1", inputting only low surrogate
- doTest(1, "", 0, "\uDFB7", "\uDFB7", "\uDFB7", "even if input string is only a low surrogate");
-
- SimpleTest.finish();
-}
-
-SimpleTest.waitForFocus(runTests);
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1053048.html b/editor/libeditor/tests/test_bug1053048.html
deleted file mode 100644
index 4032d32c2..000000000
--- a/editor/libeditor/tests/test_bug1053048.html
+++ /dev/null
@@ -1,73 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1053048
--->
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 1053048</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <script src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
- <script type="application/javascript">
-
- /** Test for Bug 1053048 **/
- SimpleTest.waitForExplicitFinish();
- SimpleTest.waitForFocus(runTests);
-
- const nsISelectionPrivate = SpecialPowers.Ci.nsISelectionPrivate;
- const nsISelectionListener = SpecialPowers.Ci.nsISelectionListener;
- const nsIDOMNSEditableElement = SpecialPowers.Ci.nsIDOMNSEditableElement;
-
- function runTests()
- {
- var textarea = SpecialPowers.wrap(document.getElementById("textarea"));
- textarea.focus();
-
- var editor = textarea.QueryInterface(nsIDOMNSEditableElement).editor;
- var selectionPrivate = editor.selection.QueryInterface(nsISelectionPrivate);
-
- var selectionListener = {
- count: 0,
- notifySelectionChanged: function (aDocument, aSelection, aReason)
- {
- ok(true, "selectionStart: " + textarea.selectionStart);
- ok(true, "selectionEnd: " + textarea.selectionEnd);
- this.count++;
- }
- };
-
- // Move caret to the end of the textarea
- synthesizeMouse(textarea, 290, 10, {});
- is(textarea.selectionStart, 3, "selectionStart should be 3 (after \"foo\")");
- is(textarea.selectionEnd, 3, "selectionEnd should be 3 (after \"foo\")");
-
- selectionPrivate.addSelectionListener(selectionListener);
-
- sendKey("RETURN");
- is(selectionListener.count, 1, "nsISelectionListener.notifySelectionChanged() should be called");
- is(textarea.selectionStart, 4, "selectionStart should be 4");
- is(textarea.selectionEnd, 4, "selectionEnd should be 4");
- is(textarea.value, "foo\n", "The line break should be appended");
-
- selectionPrivate.removeSelectionListener(selectionListener);
- SimpleTest.finish();
- }
- </script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1053048">Mozilla Bug 1053048</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-
-<textarea id="textarea"
- style="height: 100px; width: 300px; -moz-appearance: none"
- spellcheck="false"
- onkeydown="this.style.display='block'; this.style.height='200px';">foo</textarea>
-
-<pre id="test">
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1067255.html b/editor/libeditor/tests/test_bug1067255.html
deleted file mode 100644
index be2d703c5..000000000
--- a/editor/libeditor/tests/test_bug1067255.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<!DOCTYPE HTML>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1067255
--->
-
-<head>
- <title>Test for Bug 1067255</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-
-<body onload="doTest();">
- <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1067255">Mozilla Bug 1067255</a>
-
- <pre id="test">
- <script type="application/javascript">
- /** Test for Bug 1067255 **/
- SimpleTest.waitForExplicitFinish();
-
- function doTest() {
- var text = $("text-field");
- var password = $("password-field");
-
- var editor1 = SpecialPowers.wrap(text).editor;
- var editor2 = SpecialPowers.wrap(password).editor;
-
- text.focus();
- text.select();
-
- ok(editor1.canCopy(), "can copy, text");
- ok(editor1.canCut(), "can cut, text");
- ok(editor1.canDelete(), "can delete, text");
-
- password.focus();
- password.select();
-
- // Copy and cut commands don't do anything on passoword fields by default,
- // but webpages can hook up event handlers to the event, and thus, we have to
- // always keep the cut and copy event enabled in HTML/XHTML documents.
- ok(editor2.canCopy(), "can copy, password");
- ok(editor2.canCut(), "can cut, password");
- ok(editor2.canDelete(), "can delete, password");
-
- SimpleTest.finish();
- }
- </script>
- </pre>
-
- <input type="text" value="Gonzo says hi" id="text-field" />
- <input type="password" value="Jan also" id="password-field" />
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1068979.html b/editor/libeditor/tests/test_bug1068979.html
deleted file mode 100644
index 126c39d27..000000000
--- a/editor/libeditor/tests/test_bug1068979.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1068979
--->
-<head>
- <title>Test for Bug 1068979</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1068979">Mozilla Bug 1068979</a>
-<p id="display"></p>
-<div id="content">
- <div id="editor1" contenteditable="true">&#x1d400;</div>
- <div id="editor2" contenteditable="true">a<u>&#x1d401;</u>b</div>
- <div id="editor3" contenteditable="true">a&#x1d402;<u>b</u></div>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 1068979 **/
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- // Test backspacing over SMP characters pasted-in to a contentEditable
- getSelection().selectAllChildren(document.getElementById("editor1"));
- var ed1 = document.getElementById("editor1");
- var ch1 = ed1.textContent;
- ed1.focus();
- synthesizeKey("C", {accelKey: true});
- synthesizeKey("V", {accelKey: true});
- synthesizeKey("V", {accelKey: true});
- synthesizeKey("V", {accelKey: true});
- synthesizeKey("V", {accelKey: true});
- is(ed1.textContent, ch1 + ch1 + ch1 + ch1, "Should have four SMP characters");
- sendKey("back_space");
- is(ed1.textContent, ch1 + ch1 + ch1, "Three complete characters should remain");
- sendKey("back_space");
- is(ed1.textContent, ch1 + ch1, "Two complete characters should remain");
- sendKey("back_space");
- is(ed1.textContent, ch1, "Only one complete SMP character should remain");
- ed1.blur();
-
- // Test backspacing across an SMP character in a sub-element
- getSelection().selectAllChildren(document.getElementById("editor2"));
- var ed2 = document.getElementById("editor2");
- ed2.focus();
- sendKey("right");
- sendKey("back_space");
- sendKey("back_space");
- is(ed2.textContent, "a", "Only the 'a' should remain");
- ed2.blur();
-
- // Test backspacing across an SMP character from a following sub-element
- getSelection().selectAllChildren(document.getElementById("editor3"));
- var ed3 = document.getElementById("editor3");
- ed3.focus();
- sendKey("right");
- sendKey("left");
- sendKey("back_space");
- is(ed3.textContent, "ab", "The letters 'ab' should remain");
- ed3.blur();
-
- SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1094000.html b/editor/libeditor/tests/test_bug1094000.html
deleted file mode 100644
index cc27cc675..000000000
--- a/editor/libeditor/tests/test_bug1094000.html
+++ /dev/null
@@ -1,104 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1094000
--->
-<head>
- <title>Test for Bug 1094000</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1094000">Mozilla Bug 1094000</a>
-<p id="display"></p>
-<div id="content">
- <div id="editor0" contenteditable></div>
- <div id="editor1" contenteditable><br></div>
- <div id="editor2" contenteditable>a</div>
- <div id="editor3" contenteditable>b</div>
- <div id="editor4" contenteditable>c</div>
- <div id="editor5" contenteditable>d</div>
- <div id="editor6" contenteditable>e</div>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 1094000 **/
-
-SimpleTest.waitForExplicitFinish();
-
-const kIsLinux = navigator.platform.indexOf("Linux") == 0;
-
-function runTests()
-{
- var editor0 = document.getElementById("editor0");
- var editor1 = document.getElementById("editor1");
- var editor2 = document.getElementById("editor2");
- var editor3 = document.getElementById("editor3");
- var editor4 = document.getElementById("editor4");
- var editor5 = document.getElementById("editor5");
- var editor6 = document.getElementById("editor6");
-
- ok(editor1.getBoundingClientRect().height - editor0.getBoundingClientRect().height > 1,
- "an editor having a <br> element and an empty editor shouldn't be same height");
- ok(Math.abs(editor1.getBoundingClientRect().height - editor2.getBoundingClientRect().height) <= 1,
- "an editor having only a <br> element and an editor having \"a\" should be same height");
-
- editor2.focus();
- synthesizeKey("VK_RIGHT", {});
- synthesizeKey("VK_BACK_SPACE", {});
- is(editor2.innerHTML, "<br>",
- "an editor which had \"a\" should have only <br> element after Backspace keypress");
- ok(Math.abs(editor2.getBoundingClientRect().height - editor1.getBoundingClientRect().height) <= 1,
- "an editor whose content was removed by Backspace key should have a place to put a caret");
-
- editor3.focus();
- synthesizeKey("VK_LEFT", {});
- synthesizeKey("VK_DELETE", {});
- is(editor3.innerHTML, "<br>",
- "an editor which had \"b\" should have only <br> element after Delete keypress");
- ok(Math.abs(editor3.getBoundingClientRect().height - editor1.getBoundingClientRect().height) <= 1,
- "an editor whose content was removed by Delete key should have a place to put a caret");
-
- editor4.focus();
- window.getSelection().selectAllChildren(editor4);
- synthesizeKey("VK_BACK_SPACE", {});
- is(editor4.innerHTML, "<br>",
- "an editor which had \"c\" should have only <br> element after removing selected text with Backspace key");
- ok(Math.abs(editor4.getBoundingClientRect().height - editor1.getBoundingClientRect().height) <= 1,
- "an editor whose content was selected and removed by Backspace key should have a place to put a caret");
-
- editor5.focus();
- window.getSelection().selectAllChildren(editor5);
- synthesizeKey("VK_DELETE", {});
- is(editor5.innerHTML, "<br>",
- "an editor which had \"d\" should have only <br> element after removing selected text with Delete key");
- ok(Math.abs(editor5.getBoundingClientRect().height - editor1.getBoundingClientRect().height) <= 1,
- "an editor whose content was selected and removed by Delete key should have a place to put a caret");
-
- editor6.focus();
- window.getSelection().selectAllChildren(editor6);
- synthesizeKey("x", { accelKey: true });
- is(editor6.innerHTML, "<br>",
- "an editor which had \"e\" should have only <br> element after removing selected text by \"Cut\"");
- ok(Math.abs(editor6.getBoundingClientRect().height - editor1.getBoundingClientRect().height) <= 1,
- "an editor whose content was selected and removed by \"Cut\" should have a place to put a caret");
-
- editor0.focus();
- synthesizeKey("VK_BACK_SPACE", {});
- is(editor0.innerHTML, "",
- "an empty editor should keep being empty even if Backspace key is pressed");
- synthesizeKey("VK_DELETE", {});
- is(editor0.innerHTML, "",
- "an empty editor should keep being empty even if Delete key is pressed");
-
- SimpleTest.finish();
-}
-
-SimpleTest.waitForFocus(runTests);
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1100966.html b/editor/libeditor/tests/test_bug1100966.html
deleted file mode 100644
index 28c30c849..000000000
--- a/editor/libeditor/tests/test_bug1100966.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1100966
--->
-<head>
- <title>Test for Bug 1100966</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
- <script src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<div id="display">
-</div>
-<div id="content" contenteditable>
-=====<br>
-correct<br>
-fivee sixx<br>
-====
-</div>
-<pre id="test">
-</pre>
-
-<script class="testbody" type="application/javascript">
-
-/** Test for Bug 1100966 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var div = document.getElementById("content");
- div.focus();
- synthesizeMouseAtCenter(div, {});
-
- synthesizeKey(" ", {});
- setTimeout(function() {
- synthesizeKey("a", {});
- setTimeout(function() {
- synthesizeKey("VK_BACK_SPACE", {});
-
- var sel = getSpellCheckSelection();
- is(sel.rangeCount, 2, "We should have two misspelled words");
- is(String(sel.getRangeAt(0)), "fivee", "Correct misspelled word");
- is(String(sel.getRangeAt(1)), "sixx", "Correct misspelled word");
-
- SimpleTest.finish();
- },0);
- },0);
-
-});
-
-function getSpellCheckSelection() {
- var Ci = SpecialPowers.Ci;
- var editingSession = SpecialPowers.wrap(window)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIEditingSession);
- var editor = editingSession.getEditorForWindow(window);
- var selcon = editor.selectionController;
- return selcon.getSelection(selcon.SELECTION_SPELLCHECK);
-}
-
-</script>
-</body>
-
-</html>
diff --git a/editor/libeditor/tests/test_bug1101392.html b/editor/libeditor/tests/test_bug1101392.html
deleted file mode 100644
index 76917203b..000000000
--- a/editor/libeditor/tests/test_bug1101392.html
+++ /dev/null
@@ -1,78 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1101392
--->
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 1101392</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
- <script type="application/javascript">
-
- /** Test for Bug 1101392 **/
- SimpleTest.waitForExplicitFinish();
- SimpleTest.waitForFocus(runTests);
-
- function runCopyCommand(element, compareText, nextTest)
- {
- element.focus();
- var expectedEndpoint, sel;
- if (element.localName == "textarea") {
- element.select();
- expectedEndpoint = element.selectionEnd;
- } else {
- sel = getSelection();
- sel.selectAllChildren(element.parentNode);
- expectedEndpoint = [sel.getRangeAt(0).endContainer,
- sel.getRangeAt(0).endOffset];
- }
-
- function checkCollapse() {
- var desc = " after cmd_copyAndCollapseToEnd for " +
- element.localName;
- if (element.localName == "textarea") {
- is(element.selectionStart, expectedEndpoint, "start offset" + desc);
- is(element.selectionEnd, expectedEndpoint, "end offset" + desc);
- } else {
- is(sel.isCollapsed, true, "collapsed" + desc);
- is(sel.anchorNode, expectedEndpoint[0], "node" + desc);
- is(sel.anchorOffset, expectedEndpoint[1], "offset" + desc);
- }
-
- nextTest();
- }
-
- SimpleTest.waitForClipboard(compareText,
- () => SpecialPowers.doCommand(window, "cmd_copyAndCollapseToEnd"),
- checkCollapse, checkCollapse);
- }
-
- function testDiv()
- {
- var content = document.getElementById("content");
- runCopyCommand(content, 'abc', testTextarea);
- }
-
- function testTextarea()
- {
- var textarea = document.getElementById("textarea");
- runCopyCommand(textarea, 'def', SimpleTest.finish);
- }
-
- function runTests()
- {
- testDiv();
- }
- </script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1101392">Mozilla Bug 1101392</a>
-<div><div id="content">abc</div></div>
-
-<textarea id="textarea">def</textarea>
-
-<pre id="test">
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1102906.html b/editor/libeditor/tests/test_bug1102906.html
deleted file mode 100644
index 36bfc8600..000000000
--- a/editor/libeditor/tests/test_bug1102906.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1102906
--->
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 1102906</title>
-
- <script src="/tests/SimpleTest/EventUtils.js"></script>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
-
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
-
- <script>
- "use strict";
-
- /* Test for Bug 1102906 */
- /* The caret should be movable by using keyboard after drag-and-drop. */
-
- SimpleTest.waitForExplicitFinish();
- SimpleTest.waitForFocus( () => {
- let content = document.getElementById("content");
- let drag = document.getElementById("drag")
- let selection = window.getSelection();
-
- /* Perform drag-and-drop for an arbitrary content. The caret should be at
- the end of the contenteditable. */
- selection.selectAllChildren(drag);
- synthesizeDrop(drag, content, {}, "copy");
-
- let textContentAfterDrop = content.textContent;
-
- /* Move the caret to the front of the contenteditable by using keyboard. */
- for (let i = 0; i < content.textContent.length; ++i) {
- sendKey("LEFT");
- }
- sendChar("!");
-
- is(content.textContent, "!" + textContentAfterDrop,
- "The exclamation mark should be inserted at the front.");
-
- SimpleTest.finish();
- });
- </script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1102906">Mozilla Bug 1102906</a>
-<div id="content" contenteditable="true"><span id="drag">Drag</span></div>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1109465.html b/editor/libeditor/tests/test_bug1109465.html
deleted file mode 100644
index dc31e9bf0..000000000
--- a/editor/libeditor/tests/test_bug1109465.html
+++ /dev/null
@@ -1,69 +0,0 @@
-<!DOCTYPE>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1109465
--->
-<head>
- <title>Test for Bug 1109465</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<div id="display">
- <textarea></textarea>
-</div>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-</pre>
-
-<script class="testbody" type="application/javascript">
-
-/** Test for Bug 1109465 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var t = document.querySelector("textarea");
- t.focus();
-
- // Type foo\nbar and place the caret at the end of the last line
- synthesizeKey("f", {});
- synthesizeKey("o", {});
- synthesizeKey("o", {});
- synthesizeKey("VK_RETURN", {});
- synthesizeKey("b", {});
- synthesizeKey("a", {});
- synthesizeKey("r", {});
- synthesizeKey("VK_UP", {});
- is(t.selectionStart, 3, "Correct start of selection");
- is(t.selectionEnd, 3, "Correct end of selection");
-
- // Compose an IME string
- synthesizeComposition({ type: "compositionstart" });
- var composingString = "\u306B";
- synthesizeCompositionChange(
- { "composition":
- { "string": composingString,
- "clauses":
- [
- { "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
- ]
- },
- "caret": { "start": 1, "length": 0 }
- });
- synthesizeComposition({ type: "compositioncommitasis" });
- is(t.value, "foo\u306B\nbar", "Correct value after composition");
-
- // Now undo to test that the transaction merger has correctly detected the
- // IMETextTxn.
- synthesizeKey("Z", {accelKey: true});
- is(t.value, "foo\nbar", "Correct value after undo");
-
- SimpleTest.finish();
-});
-
-</script>
-</body>
-
-</html>
diff --git a/editor/libeditor/tests/test_bug1140105.html b/editor/libeditor/tests/test_bug1140105.html
deleted file mode 100644
index 21d003054..000000000
--- a/editor/libeditor/tests/test_bug1140105.html
+++ /dev/null
@@ -1,71 +0,0 @@
-<!DOCTYPE>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1140105
--->
-<head>
- <title>Test for Bug 1140105</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
- <script src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<div id="display">
-</div>
-
-<div id="content" contenteditable><font face="Arial">1234567890</font></div>
-
-<pre id="test">
-</pre>
-
-<script class="testbody" type="application/javascript">
-
-/** Test for Bug 1140105 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var div = document.getElementById("content");
- div.focus();
- synthesizeMouseAtCenter(div, {});
- synthesizeKey("VK_LEFT", {});
-
- var sel = window.getSelection();
- var selRange = sel.getRangeAt(0);
- is(selRange.endContainer.nodeName, "#text", "selection should be in text node");
- is(selRange.endOffset, 9, "offset should be 9");
-
- var firstHas = {};
- var anyHas = {};
- var allHas = {};
- var editor = getEditor();
-
- var atomService = SpecialPowers.Cc["@mozilla.org/atom-service;1"].getService(SpecialPowers.Ci.nsIAtomService);
- var propAtom = atomService.getAtom("font");
- editor.getInlineProperty(propAtom, "face", "Arial", firstHas, anyHas, allHas);
- is(firstHas.value, true, "Test for Arial: firstHas: true expected");
- is(anyHas.value, true, "Test for Arial: anyHas: true expected");
- is(allHas.value, true, "Test for Arial: allHas: true expected");
- editor.getInlineProperty(propAtom, "face", "Courier", firstHas, anyHas, allHas);
- is(firstHas.value, false, "Test for Courier: firstHas: false expected");
- is(anyHas.value, false, "Test for Courier: anyHas: false expected");
- is(allHas.value, false, "Test for Courier: allHas: false expected");
-
- SimpleTest.finish();
-
-});
-
-function getEditor() {
- var Ci = SpecialPowers.Ci;
- var editingSession = SpecialPowers.wrap(window)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIEditingSession);
- var editor = editingSession.getEditorForWindow(window);
- editor.QueryInterface(Ci.nsIHTMLEditor);
- return editor;
-}
-
-</script>
-</body>
-
-</html>
diff --git a/editor/libeditor/tests/test_bug1140617.html b/editor/libeditor/tests/test_bug1140617.html
deleted file mode 100644
index 078458a3a..000000000
--- a/editor/libeditor/tests/test_bug1140617.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!doctype html>
-<title>Mozilla Bug 1140617</title>
-<link rel=stylesheet href="/tests/SimpleTest/test.css">
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1140617"
- target="_blank">Mozilla Bug 1140617</a>
-<iframe id="i1" width="200" height="100" src="about:blank"></iframe>
-<img id="i" src="green.png">
-<script>
-function runTest() {
- SpecialPowers.setCommandNode(window, document.getElementById("i"));
- SpecialPowers.doCommand(window, "cmd_copyImageContents");
-
- var e = document.getElementById('i1');
- var doc = e.contentDocument;
- doc.designMode = "on";
- doc.defaultView.focus();
- var selection = doc.defaultView.getSelection();
- selection.removeAllRanges();
- selection.selectAllChildren(doc.body);
- selection.collapseToEnd();
-
- doc.execCommand("fontname", false, "Arial");
- doc.execCommand("bold", false, null);
- doc.execCommand("insertText", false, "12345");
- doc.execCommand("paste", false, null);
- doc.execCommand("insertText", false, "a");
-
- is(doc.queryCommandValue("fontname"), "Arial", "Arial expected");
- is(doc.queryCommandState("bold"), true, "Bold expected");
-
- SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(runTest);
-</script>
diff --git a/editor/libeditor/tests/test_bug1153237.html b/editor/libeditor/tests/test_bug1153237.html
deleted file mode 100644
index 38d631326..000000000
--- a/editor/libeditor/tests/test_bug1153237.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1153237
--->
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 1153237</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
- <script type="application/javascript">
-
- SimpleTest.waitForExplicitFinish();
-
- // Avoid platform selection differences
- SimpleTest.waitForFocus(function() {
- SpecialPowers.pushPrefEnv({
- "set": [["layout.word_select.eat_space_to_next_word", true]]
- }, runTests);
- });
-
- function runTests()
- {
- var element = document.getElementById("editor");
- var sel = window.getSelection();
-
- element.focus();
- is(sel.getRangeAt(0).startOffset, 0, "offset is zero");
-
- SpecialPowers.doCommand(window, "cmd_selectRight2");
- is(sel.toString(), "Some ",
- "first word + space is selected: got '" + sel.toString() + "'");
-
- SpecialPowers.doCommand(window, "cmd_selectRight2");
- is(sel.toString(), "Some text",
- "both words are selected: got '" + sel.toString() + "'");
-
- SimpleTest.finish();
- }
- </script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1153237">Mozilla Bug 1153237</a>
-<div id="editor" contenteditable>Some text</div><span></span>
-
-<pre id="test">
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1154791.html b/editor/libeditor/tests/test_bug1154791.html
deleted file mode 100644
index 03b605e20..000000000
--- a/editor/libeditor/tests/test_bug1154791.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!DOCTYPE>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1154791
--->
-<head>
- <title>Test for Bug 1154791</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
- <script src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<div id="display">
-</div>
-
-<div id="content" contenteditable>
-<tt>thiss onee is stilll a</tt>
-</div>
-
-<pre id="test">
-</pre>
-
-<script class="testbody" type="application/javascript">
-
-/** Test for Bug 1154791 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var div = document.getElementById("content");
- div.focus();
- synthesizeMouseAtCenter(div, {});
- synthesizeKey("VK_LEFT", {});
- synthesizeKey("VK_LEFT", {});
-
- setTimeout(function() {
- synthesizeKey("VK_BACK_SPACE", {});
- setTimeout(function() {
- synthesizeKey(" ", {});
-
- setTimeout(function() {
- var sel = getSpellCheckSelection();
- is(sel.rangeCount, 2, "We should have two misspelled words");
- is(String(sel.getRangeAt(0)), "thiss", "Correct misspelled word");
- is(String(sel.getRangeAt(1)), "onee", "Correct misspelled word");
-
- SimpleTest.finish();
- },0);
- },0);
- },0);
-
-});
-
-function getSpellCheckSelection() {
- var Ci = SpecialPowers.Ci;
- var editingSession = SpecialPowers.wrap(window)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIEditingSession);
- var editor = editingSession.getEditorForWindow(window);
- var selcon = editor.selectionController;
- return selcon.getSelection(selcon.SELECTION_SPELLCHECK);
-}
-
-</script>
-</body>
-
-</html>
diff --git a/editor/libeditor/tests/test_bug1162952.html b/editor/libeditor/tests/test_bug1162952.html
deleted file mode 100644
index ad119de87..000000000
--- a/editor/libeditor/tests/test_bug1162952.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1162952
--->
-<head>
- <title>Test for Bug 1162952</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1162952">Mozilla Bug 1162952</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-/** Test for Bug 1162952 **/
-var userCallbackRun = false;
-
-document.addEventListener('keydown', function() {
- // During a user callback, the commands should be enabled
- userCallbackRun = true;
- is(true, document.queryCommandEnabled('cut'));
- is(true, document.queryCommandEnabled('copy'));
-});
-
-// Otherwise, they should be disabled
-is(false, document.queryCommandEnabled('cut'));
-is(false, document.queryCommandEnabled('copy'));
-
-// Fire a user callback
-synthesizeKey('A', {});
-
-ok(userCallbackRun, "User callback should've been run");
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1181130-1.html b/editor/libeditor/tests/test_bug1181130-1.html
deleted file mode 100644
index eb27526a3..000000000
--- a/editor/libeditor/tests/test_bug1181130-1.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1181130
--->
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 1181130</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1181130">Mozilla Bug 1181130</a>
-<p id="display"></p>
-<div id="container" contenteditable="true">
- editable div
- <div id="noneditable" contenteditable="false">
- non-editable div
- <div id="editable" contenteditable="true">nested editable div</div>
- </div>
-</div>
-<script type="application/javascript">
-/** Test for Bug 1181130 **/
-var container = document.getElementById("container");
-var noneditable = document.getElementById("noneditable");
-var editable = document.getElementById("editable");
-
-SimpleTest.waitForExplicitFinish();
-
-SimpleTest.waitForFocus(function() {
- synthesizeMouseAtCenter(noneditable, {});
- ok(!document.getSelection().toString().includes("nested editable div"),
- "Selection should not include non-editable content");
-
- synthesizeMouseAtCenter(container, {});
- ok(!document.getSelection().toString().includes("nested editable div"),
- "Selection should not include non-editable content");
-
- synthesizeMouseAtCenter(editable, {});
- ok(!document.getSelection().toString().includes("nested editable div"),
- "Selection should not include non-editable content");
-
- SimpleTest.finish();
-});
-</script>
-<pre id="test">
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1181130-2.html b/editor/libeditor/tests/test_bug1181130-2.html
deleted file mode 100644
index edb380e98..000000000
--- a/editor/libeditor/tests/test_bug1181130-2.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1181130
--->
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 1181130</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1181130">Mozilla Bug 1181130</a>
-<p id="display"></p>
-<div id="container" contenteditable="true">
- editable div
- <div id="noneditable" contenteditable="false">
- non-editable div
- </div>
-</div>
-<script type="application/javascript">
-/** Test for Bug 1181130 **/
-var container = document.getElementById("container");
-var noneditable = document.getElementById("noneditable");
-
-SimpleTest.waitForExplicitFinish();
-
-SimpleTest.waitForFocus(function() {
- var nonHTMLElement = document.createElementNS("http://www.example.com", "element");
- nonHTMLElement.innerHTML = '<div contenteditable="true">nested editable div</div>';
- noneditable.appendChild(nonHTMLElement);
-
- synthesizeMouseAtCenter(noneditable, {});
- ok(!document.getSelection().toString().includes("nested editable div"),
- "Selection should not include non-editable content");
-
- SimpleTest.finish();
-});
-</script>
-<pre id="test">
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1186799.html b/editor/libeditor/tests/test_bug1186799.html
deleted file mode 100644
index b0b583a7e..000000000
--- a/editor/libeditor/tests/test_bug1186799.html
+++ /dev/null
@@ -1,81 +0,0 @@
-<!DOCTYPE>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1186799
--->
-<head>
- <title>Test for Bug 1186799</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<div id="content">
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1186799">Mozilla Bug 1186799</a>
-<p id="display"></p>
-<div id="content">
- <span id="span">span</span>
- <div id="editor" contenteditable></div>
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-/** Test for Bug 1186799 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var span = document.getElementById("span");
- var editor = document.getElementById("editor");
- editor.focus();
-
- synthesizeCompositionChange(
- { "composition":
- { "string": "\u3042",
- "clauses":
- [
- { "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
- ]
- },
- "caret": { "start": 1, "length": 0 }
- });
-
- ok(isThereIMESelection(), "There should be IME selection");
-
- var compositionEnd = false;
- editor.addEventListener("compositionend", function () { compositionEnd = true; }, true);
-
- synthesizeMouseAtCenter(span, {});
-
- ok(compositionEnd, "composition end should be fired at clicking outside of the editor");
- ok(!isThereIMESelection(), "There should be no IME selection");
-
- SimpleTest.finish();
-});
-
-function isThereIMESelection()
-{
- var selCon = SpecialPowers.wrap(window).
- QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).
- getInterface(SpecialPowers.Ci.nsIWebNavigation).
- QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).
- getInterface(SpecialPowers.Ci.nsIEditingSession).
- getEditorForWindow(window).
- selectionController;
- const kIMESelections = [
- SpecialPowers.Ci.nsISelectionController.SELECTION_IME_RAWINPUT,
- SpecialPowers.Ci.nsISelectionController.SELECTION_IME_SELECTEDRAWTEXT,
- SpecialPowers.Ci.nsISelectionController.SELECTION_IME_CONVERTEDTEXT,
- SpecialPowers.Ci.nsISelectionController.SELECTION_IME_SELECTEDCONVERTEDTEXT
- ];
- for (var i = 0; i < kIMESelections.length; i++) {
- var sel = selCon.getSelection(kIMESelections[i]);
- if (sel && sel.rangeCount) {
- return true;
- }
- }
- return false;
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1230473.html b/editor/libeditor/tests/test_bug1230473.html
deleted file mode 100644
index bff7826d1..000000000
--- a/editor/libeditor/tests/test_bug1230473.html
+++ /dev/null
@@ -1,124 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1230473
--->
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 1230473</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1230473">Mozilla Bug 1230473</a>
-<input id="input">
-<textarea id="textarea"></textarea>
-<div id="div" contenteditable></div>
-<script type="application/javascript">
-/** Test for Bug 1230473 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(()=>{
- function runTest(aEditor) {
- function committer() {
- aEditor.blur();
- aEditor.focus();
- }
- function isNSEditableElement() {
- return aEditor.tagName.toLowerCase() == "input" || aEditor.tagName.toLowerCase() == "textarea";
- }
- function value() {
- return isNSEditableElement() ? aEditor.value : aEditor.textContent;
- }
- function isComposing() {
- return isNSEditableElement() ? SpecialPowers.wrap(aEditor)
- .QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement)
- .editor
- .QueryInterface(SpecialPowers.Ci.nsIEditorIMESupport)
- .composing :
- SpecialPowers.wrap(window)
- .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
- .getInterface(SpecialPowers.Ci.nsIWebNavigation)
- .QueryInterface(SpecialPowers.Ci.nsIDocShell)
- .editor
- .QueryInterface(SpecialPowers.Ci.nsIEditorIMESupport)
- .composing;
- }
- function clear() {
- if (isNSEditableElement()) {
- aEditor.value = "";
- } else {
- aEditor.textContent = "";
- }
- }
-
- clear();
-
- // Committing at compositionstart
- aEditor.focus();
- aEditor.addEventListener("compositionstart", committer, true);
- synthesizeCompositionChange({ composition: { string: "a", clauses: [{length: 1, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
- caret: { start: 1, length: 0 }});
- aEditor.removeEventListener("compositionstart", committer, true);
- ok(!isComposing(), "composition in " + aEditor.id + " should be committed by compositionstart event handler");
- is(value(), "", "composition in " + aEditor.id + " shouldn't insert any text since it's committed at compositionstart");
- clear();
-
- // Committing at first compositionupdate
- aEditor.focus();
- aEditor.addEventListener("compositionupdate", committer, true);
- synthesizeCompositionChange({ composition: { string: "a", clauses: [{length: 1, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
- caret: { start: 1, length: 0 }});
- aEditor.removeEventListener("compositionupdate", committer, true);
- ok(!isComposing(), "composition in " + aEditor.id + " should be committed by compositionupdate event handler");
- is(value(), "", "composition in " + aEditor.id + " shouldn't have inserted any text since it's committed at first compositionupdate");
- clear();
-
- // Committing at first text (eCompositionChange)
- aEditor.focus();
- aEditor.addEventListener("text", committer, true);
- synthesizeCompositionChange({ composition: { string: "a", clauses: [{length: 1, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
- caret: { start: 1, length: 0 }});
- aEditor.removeEventListener("text", committer, true);
- ok(!isComposing(), "composition in " + aEditor.id + " should be committed by text event handler");
- is(value(), "", "composition in " + aEditor.id + " should have inserted any text since it's committed at first text");
- clear();
-
- // Committing at second compositionupdate
- aEditor.focus();
- synthesizeComposition({ type: "compositionstart" });
- synthesizeCompositionChange({ composition: { string: "a", clauses: [{length: 1, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
- caret: { start: 1, length: 0 }});
- ok(isComposing(), "composition should be in " + aEditor.id + " before dispatching second compositionupdate");
- is(value(), "a", "composition in " + aEditor.id + " should be 'a' before dispatching second compositionupdate");
- aEditor.addEventListener("compositionupdate", committer, true);
- synthesizeCompositionChange({ composition: { string: "ab", clauses: [{length: 2, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
- caret: { start: 2, length: 0 }});
- aEditor.removeEventListener("compositionupdate", committer, true);
- ok(!isComposing(), "composition in " + aEditor.id + " should be committed by compositionupdate event handler");
- todo_is(value(), "a", "composition in " + aEditor.id + " shouldn't have been modified since it's committed at second compositionupdate");
- clear();
-
- // Committing at second text (eCompositionChange)
- aEditor.focus();
- synthesizeComposition({ type: "compositionstart" });
- synthesizeCompositionChange({ composition: { string: "a", clauses: [{length: 1, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
- caret: { start: 1, length: 0 }});
- ok(isComposing(), "composition should be in " + aEditor.id + " before dispatching second text");
- is(value(), "a", "composition in " + aEditor.id + " should be 'a' before dispatching second text");
- aEditor.addEventListener("text", committer, true);
- synthesizeCompositionChange({ composition: { string: "ab", clauses: [{length: 2, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
- caret: { start: 2, length: 0 }});
- aEditor.removeEventListener("text", committer, true);
- ok(!isComposing(), "composition in " + aEditor.id + " should be committed by text event handler");
- todo_is(value(), "a", "composition in " + aEditor.id + " shouldn't have been modified since it's committed at second text");
- clear();
- }
- runTest(document.getElementById("input"));
- runTest(document.getElementById("textarea"));
- runTest(document.getElementById("div"));
- SimpleTest.finish();
-});
-</script>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1247483.html b/editor/libeditor/tests/test_bug1247483.html
deleted file mode 100644
index 40dbc36ce..000000000
--- a/editor/libeditor/tests/test_bug1247483.html
+++ /dev/null
@@ -1,61 +0,0 @@
-<!DOCTYPE HTML>
-<html><head>
-<title>Test for bug 1247483</title>
-<style src="/tests/SimpleTest/test.css" type="text/css"></style>
-<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-
-<script class="testbody" type="application/javascript">
-
-function runTest() {
- // Copy content from table.
- var selection = getSelection();
- var startRange = document.createRange();
- startRange.setStart(document.getElementById("start"), 0);
- startRange.setEnd(document.getElementById("end"), 2);
- selection.removeAllRanges();
- selection.addRange(startRange);
- SpecialPowers.wrap(document).execCommand("copy", false, null);
-
- // Paste content into "pastecontainer"
- var pasteContainer = document.getElementById("pastecontainer");
- var pasteRange = document.createRange();
- pasteRange.selectNodeContents(pasteContainer);
- pasteRange.collapse(false);
- selection.removeAllRanges();
- selection.addRange(pasteRange);
- SpecialPowers.wrap(document).execCommand("paste", false, null);
-
- is(pasteContainer.querySelectorAll("td").length, 4, "4 <td> should be pasted.");
-
- document.execCommand("undo", false, null);
-
- is(pasteContainer.querySelectorAll("td").length, 0, "Undo should have remove the 4 pasted <td>.");
-
- SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-
-addLoadEvent(runTest);
-</script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1247483">Mozilla Bug 1247483</a>
-<p id="display"></p>
-
-<pre id="test">
-</pre>
-
-<div id="container" contenteditable="true">
-<table>
- <tr id="start"><td>1 1</td><td>1 2</td></tr>
- <tr id="end"><td>2 1</td><td>2 2</td></tr>
-</table>
-</div>
-
-<div id="pastecontainer" contenteditable="true">
-</div>
-
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1248128.html b/editor/libeditor/tests/test_bug1248128.html
deleted file mode 100644
index 08b0139c9..000000000
--- a/editor/libeditor/tests/test_bug1248128.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1248128
--->
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 1248128</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <script src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
- <script type="application/javascript">
-
- SimpleTest.waitForExplicitFinish();
-
- SimpleTest.waitForFocus(function() {
- var outer = document.querySelector("html");
- ok(outer.scrollTop == 0, "scrollTop is zero: got " + outer.scrollTop);
-
- var input = document.getElementById("testInput");
- input.focus();
-
- var scroll = outer.scrollTop;
- ok(scroll > 0, "element has scrolled: new value " + scroll);
-
- try {
- SpecialPowers.doCommand(window, "cmd_moveLeft");
- ok(false, "should not be able to do kMoveLeft");
- } catch (e) {
- ok(true, "unable to perform kMoveLeft");
- }
-
- ok(outer.scrollTop == scroll,
- "scroll is unchanged: got " + outer.scrollTop + ", expected " + scroll);
-
- // Make sure cmd_moveLeft isn't failing for some unrelated reason
- synthesizeKey("a", {});
- is(input.selectionStart, 1, "selectionStart after typing");
- SpecialPowers.doCommand(window, "cmd_moveLeft");
- is(input.selectionStart, 0, "selectionStart after move left");
-
- SimpleTest.finish();
- });
- </script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1248128">Mozilla Bug 1248128</a>
-<div style="height: 2000px;"></div>
-<input type="text" id="testInput"></input>
-<div style="height: 200px;"></div>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1248185.html b/editor/libeditor/tests/test_bug1248185.html
deleted file mode 100644
index d545cfc53..000000000
--- a/editor/libeditor/tests/test_bug1248185.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1248185
--->
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 1248185</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
- <script type="application/javascript">
-
- SimpleTest.waitForExplicitFinish();
-
- // Avoid platform selection differences
- SimpleTest.waitForFocus(function() {
- SpecialPowers.pushPrefEnv({
- "set": [["layout.word_select.eat_space_to_next_word", true]]
- }, runTests);
- });
-
- function runTests()
- {
- var editor = document.querySelector("#test");
- editor.focus();
-
- var sel = window.getSelection();
-
- SpecialPowers.doCommand(window, "cmd_moveRight2");
- SpecialPowers.doCommand(window, "cmd_moveRight2");
- SpecialPowers.doCommand(window, "cmd_moveRight2");
- SpecialPowers.doCommand(window, "cmd_selectRight2");
- ok(sel.toString() == "three ", "expected 'three ' to be selected");
-
- SpecialPowers.doCommand(window, "cmd_moveRight2");
- SpecialPowers.doCommand(window, "cmd_moveRight2");
- SpecialPowers.doCommand(window, "cmd_moveRight2");
- ok(sel.toString() == "", "expected empty selection");
-
- SpecialPowers.doCommand(window, "cmd_selectLeft2");
- ok(sel.toString() == "five", "expected 'five' to be selected");
-
- SimpleTest.finish();
- }
- </script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1248185">Mozilla Bug 1248185</a>
-<body>
-<div style="font: 12px monospace; width: 45ch;">
-<span contenteditable="" id="test">blablablablablablablablablablablablablabla one two three four five</span>
-<div>
-<span>foo</span>
-</div>
-</div>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1250010.html b/editor/libeditor/tests/test_bug1250010.html
deleted file mode 100644
index d1e0154dc..000000000
--- a/editor/libeditor/tests/test_bug1250010.html
+++ /dev/null
@@ -1,93 +0,0 @@
-<!DOCTYPE>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1250010
--->
-<head>
- <title>Test for Bug 1250010</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
- <script src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<div id="display">
-</div>
-
-<div id="test1" contenteditable><p><b><font color="red">1234567890</font></b></p></div>
-<div id="test2" contenteditable><p><tt>xyz</tt></p><p><tt><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAIAAABvrngfAAAAFklEQVQImWMwjWhCQwxECoW3oCHihAB0LyYv5/oAHwAAAABJRU5ErkJggg=="></tt></p></div>
-
-<pre id="test">
-</pre>
-
-<script class="testbody" type="application/javascript">
-
-function getImageDataURI()
-{
- return document.getElementsByTagName("img")[0].getAttribute("src");
-}
-
-/** Test for Bug 1250010 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
-
- // First test: Empty paragraph is split correctly.
- var div = document.getElementById("test1");
- div.focus();
- synthesizeMouseAtCenter(div, {});
-
- var sel = window.getSelection();
- var selRange = sel.getRangeAt(0);
- is(selRange.endContainer.nodeName, "#text", "selection should be at the end of text node");
- is(selRange.endOffset, 10, "offset should be 10");
-
- synthesizeKey("VK_RETURN", {});
- synthesizeKey("VK_RETURN", {});
- synthesizeKey("b", {});
- synthesizeKey("VK_UP", {});
- synthesizeKey("a", {});
-
- is(div.innerHTML, "<p><b><font color=\"red\">1234567890</font></b></p>" +
- "<p><b><font color=\"red\">a<br></font></b></p>" +
- "<p><b><font color=\"red\">b<br></font></b></p>",
- "unexpected HTML");
-
- // Second test: Since we modified the code path that splits non-text nodes,
- // test that this works, if the split node is not empty.
- div = document.getElementById("test2");
- div.focus();
- synthesizeMouseAtCenter(div, {});
-
- selRange = sel.getRangeAt(0);
- is(selRange.endContainer.nodeName, "#text", "selection should be at the end of text node");
- is(selRange.endOffset, 3, "offset should be 3");
-
- // Move behind the image and press enter, insert an "A".
- // That should insert a new empty paragraph with the "A" after what we have.
- synthesizeKey("VK_RIGHT", {});
- synthesizeKey("VK_RIGHT", {});
- synthesizeKey("VK_RETURN", {});
- synthesizeKey("A", {});
-
- // The resulting HTML is sadly less than optimal:
- // A <br> gets inserted after the image and the "A" is followed by an empty <tt></tt>.
- var newHTML = div.innerHTML;
- var expectedHTML;
- // Existing part with additional <br> inserted.
- expectedHTML = "<p><tt>xyz</tt></p><p><tt><img src=\"" + getImageDataURI() + "\"><br></tt></p>" +
- // New part caused by pressing enter after the image and typing an "A".
- "<p><tt>A</tt><br><tt></tt></p>";
- is(newHTML, expectedHTML, "unexpected HTML");
-
- // In case the empty tag gets deleted some day, let them know that something improved.
- expectedHTML = "<p><tt>xyz</tt></p><p><tt><img src=\"" + getImageDataURI() + "\"><br></tt></p>" +
- "<p><tt>A</tt><br></p>";
- todo_is(newHTML, expectedHTML, "unexpected HTML");
-
- SimpleTest.finish();
-
-});
-
-</script>
-</body>
-
-</html>
diff --git a/editor/libeditor/tests/test_bug1257363.html b/editor/libeditor/tests/test_bug1257363.html
deleted file mode 100644
index c1610494f..000000000
--- a/editor/libeditor/tests/test_bug1257363.html
+++ /dev/null
@@ -1,182 +0,0 @@
-<!DOCTYPE>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1257363
--->
-<head>
- <title>Test for Bug 1257363</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
- <script src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<div id="display">
-</div>
-
-<div id="backspaceCSS" contenteditable><p style="color:red;">12345</p>67</div>
-<div id="backspace" contenteditable><p><font color="red">12345</font></p>67</div>
-<div id="deleteCSS" contenteditable><p style="color:red;">x</p></div>
-<div id="delete" contenteditable><p><font color="red">y</font></p></div>
-
-<pre id="test">
-</pre>
-
-<script class="testbody" type="application/javascript">
-
-/** Test for Bug 1257363 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
-
- // ***** Backspace test *****
- var div = document.getElementById("backspaceCSS");
- div.focus();
- synthesizeMouse(div, 100, 2, {}); /* click behind and down */
-
- var sel = window.getSelection();
- var selRange = sel.getRangeAt(0);
- is(selRange.endContainer.nodeName, "#text", "selection should be at the end of text node");
- is(selRange.endOffset, 5, "offset should be 5");
-
- // Return and backspace should take us to where we started.
- synthesizeKey("VK_RETURN", {});
- synthesizeKey("VK_BACK_SPACE", {});
-
- selRange = sel.getRangeAt(0);
- is(selRange.endContainer.nodeName, "#text", "selection should be at the end of text node");
- is(selRange.endOffset, 5, "offset should be 5");
-
- // Add an "a" to the end of the paragraph.
- synthesizeKey("a", {});
-
- // Return and forward delete should take us to the following line.
- synthesizeKey("VK_RETURN", {});
- synthesizeKey("VK_DELETE", {});
-
- // Add a "b" to the start.
- synthesizeKey("b", {});
-
- is(div.innerHTML, "<p style=\"color:red;\">12345a</p>b67",
- "unexpected HTML");
-
- // Let's repeat the whole thing, but a font tag instead of CSS.
- // The behaviour is different since the font is carried over.
- div = document.getElementById("backspace");
- div.focus();
- synthesizeMouse(div, 100, 2, {}); /* click behind and down */
-
- sel = window.getSelection();
- selRange = sel.getRangeAt(0);
- is(selRange.endContainer.nodeName, "#text", "selection should be at the end of text node");
- is(selRange.endOffset, 5, "offset should be 5");
-
- // Return and backspace should take us to where we started.
- synthesizeKey("VK_RETURN", {});
- synthesizeKey("VK_BACK_SPACE", {});
-
- selRange = sel.getRangeAt(0);
- is(selRange.endContainer.nodeName, "#text", "selection should be at the end of text node");
- is(selRange.endOffset, 5, "offset should be 5");
-
- // Add an "a" to the end of the paragraph.
- synthesizeKey("a", {});
-
- // Return and forward delete should take us to the following line.
- synthesizeKey("VK_RETURN", {});
- synthesizeKey("VK_DELETE", {});
-
- // Add a "b" to the start.
- synthesizeKey("b", {});
-
- // Here we get a somewhat ugly result since the red sticks.
- is(div.innerHTML, "<p><font color=\"red\">12345a</font></p><font color=\"red\">b</font>67",
- "unexpected HTML");
-
- // ***** Delete test *****
- div = document.getElementById("deleteCSS");
- div.focus();
- synthesizeMouse(div, 100, 2, {}); /* click behind and down */
-
- var sel = window.getSelection();
- var selRange = sel.getRangeAt(0);
- is(selRange.endContainer.nodeName, "#text", "selection should be at the end of text node");
- is(selRange.endOffset, 1, "offset should be 1");
-
- // left, enter should create a new empty paragraph before
- // but leave the selection at the start of the existing paragraph.
- synthesizeKey("VK_LEFT", {});
- synthesizeKey("VK_RETURN", {});
-
- selRange = sel.getRangeAt(0);
- is(selRange.endContainer.nodeName, "#text", "selection should be at the start of text node");
- is(selRange.endOffset, 0, "offset should be 0");
- is(selRange.endContainer.nodeValue, "x", "we should be in the text node with the x");
-
- // Now moving up into the new empty paragraph.
- synthesizeKey("VK_UP", {});
-
- selRange = sel.getRangeAt(0);
- is(selRange.endContainer.nodeName, "P", "selection should be the new empty paragraph");
- is(selRange.endOffset, 0, "offset should be 0");
-
- // Forward delete should now take us to where we started.
- synthesizeKey("VK_DELETE", {});
-
- selRange = sel.getRangeAt(0);
- is(selRange.endContainer.nodeName, "#text", "selection should be at the start of text node");
- is(selRange.endOffset, 0, "offset should be 0");
-
- // Add an "a" to the start of the paragraph.
- synthesizeKey("a", {});
-
- is(div.innerHTML, "<p style=\"color:red;\">ax</p>",
- "unexpected HTML");
-
- // Let's repeat the whole thing, but a font tag instead of CSS.
- div = document.getElementById("delete");
- div.focus();
- synthesizeMouse(div, 100, 2, {}); /* click behind and down */
-
- var sel = window.getSelection();
- var selRange = sel.getRangeAt(0);
- is(selRange.endContainer.nodeName, "#text", "selection should be at the end of text node");
- is(selRange.endOffset, 1, "offset should be 1");
-
- // left, enter should create a new empty paragraph before
- // but leave the selection at the start of the existing paragraph.
- synthesizeKey("VK_LEFT", {});
- synthesizeKey("VK_RETURN", {});
-
- selRange = sel.getRangeAt(0);
- is(selRange.endContainer.nodeName, "#text", "selection should be at the start of text node");
- is(selRange.endOffset, 0, "offset should be 0");
- is(selRange.endContainer.nodeValue, "y", "we should be in the text node with the y");
-
- // Now moving up into the new empty paragraph.
- synthesizeKey("VK_UP", {});
-
- selRange = sel.getRangeAt(0);
- is(selRange.endContainer.nodeName, "FONT", "selection should be the font tag");
- is(selRange.endOffset, 0, "offset should be 0");
- is(selRange.endContainer.parentNode.nodeName, "P", "the parent of the font should be a paragraph");
-
- // Forward delete should now take us to where we started.
- synthesizeKey("VK_DELETE", {});
-
- selRange = sel.getRangeAt(0);
- is(selRange.endContainer.nodeName, "#text", "selection should be at the start of text node");
- is(selRange.endOffset, 0, "offset should be 0");
-
- // Add an "a" to the start of the paragraph.
- synthesizeKey("a", {});
-
- is(div.innerHTML, "<p><font color=\"red\">ay</font></p>",
- "unexpected HTML");
-
- SimpleTest.finish();
-
-});
-
-</script>
-</body>
-
-</html>
diff --git a/editor/libeditor/tests/test_bug1258085.html b/editor/libeditor/tests/test_bug1258085.html
deleted file mode 100644
index 342f068ee..000000000
--- a/editor/libeditor/tests/test_bug1258085.html
+++ /dev/null
@@ -1,66 +0,0 @@
-<!DOCTYPE html>
-<title>Test for Bug 1186799</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<script src="/tests/SimpleTest/EventUtils.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css">
-<div contenteditable></div>
-<script>
-var div = document.querySelector("div");
-
-function reset() {
- div.innerHTML = "x<br> y";
- div.focus();
- synthesizeKey("VK_DOWN", {});
-}
-
-function checks(msg) {
- is(div.innerHTML, "x<br><br>",
- msg + ": Should add a second <br> to prevent collapse of first");
- is(div.childNodes.length, 3, msg + ": No empty text nodes allowed");
- ok(getSelection().isCollapsed, msg + ": Selection must be collapsed");
- is(getSelection().focusNode, div, msg + ": Focus must be in div");
- is(getSelection().focusOffset, 2,
- msg + ": Focus must be between the two <br>s");
-}
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- // Put selection after the "y" and backspace
- reset();
- synthesizeKey("VK_RIGHT", {});
- synthesizeKey("VK_BACK_SPACE", {});
- checks("Collapsed backspace");
-
- // Now do the same with delete
- reset();
- synthesizeKey("VK_DELETE", {});
- checks("Collapsed delete");
-
- // Forward selection
- reset();
- synthesizeKey("VK_RIGHT", {shiftKey: true});
- synthesizeKey("VK_BACK_SPACE", {});
- checks("Forward-selected backspace");
-
- // Backward selection
- reset();
- synthesizeKey("VK_RIGHT", {});
- synthesizeKey("VK_LEFT", {shiftKey: true});
- synthesizeKey("VK_BACK_SPACE", {});
- checks("Backward-selected backspace");
-
- // Make sure we're not deleting if the whitespace isn't actually collapsed
- div.style.whiteSpace = "pre-wrap";
- reset();
- synthesizeKey("VK_RIGHT", {});
- synthesizeKey("VK_RIGHT", {});
- synthesizeKey("VK_BACK_SPACE", {});
- if (div.innerHTML, "x<br> ", "pre-wrap: Don't delete uncollapsed space");
- ok(getSelection().isCollapsed, "pre-wrap: Selection must be collapsed");
- is(getSelection().focusNode, div.lastChild,
- "pre-wrap: Focus must be in final text node");
- is(getSelection().focusOffset, 1, "pre-wrap: Focus must be at end of node");
-
- SimpleTest.finish();
-});
-</script>
diff --git a/editor/libeditor/tests/test_bug1268736.html b/editor/libeditor/tests/test_bug1268736.html
deleted file mode 100644
index fb1f341b5..000000000
--- a/editor/libeditor/tests/test_bug1268736.html
+++ /dev/null
@@ -1,64 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1268736
--->
-<head>
- <title>Test for Bug 1268736</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1268736">Mozilla Bug 1268736</a>
-<table id="table" border="1" width="100%">
- <tbody>
- <tr>
- <td>a</td>
- <td>b</td>
- <td>c</td>
- </tr>
- <tr>
- <td>d</td>
- <td id="cell_readonly">e</td>
- <td contenteditable="true" id="cell_writable">f</td>
- </tr>
- </tbody>
-</table>
-
-<script type="application/javascript">
-
-/**
- * Test for Bug 1268736
- *
- * Tests for editing a table cell's contents when the table cell is or isn't a child of a contenteditable node.
- *
- */
-
-function getEditor() {
- const Ci = SpecialPowers.Ci;
- var editingSession = SpecialPowers.wrap(window)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIEditingSession);
- return editingSession.getEditorForWindow(window).QueryInterface(Ci.nsITableEditor);
-}
-
-var table = document.getElementById("table");
-var tableHTML = table.innerHTML;
-var editor = getEditor();
-
-var cell = document.getElementById("cell_readonly");
-cell.focus();
-editor.deleteTableCellContents();
-is(table.innerHTML == tableHTML, true, "editor should not modify non-editable table cell" );
-
-cell = document.getElementById("cell_writable");
-cell.focus();
-editor.deleteTableCellContents();
-is(cell.innerHTML == "<br>", true, "editor can modify editable table cells" );
-
-</script>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1270235.html b/editor/libeditor/tests/test_bug1270235.html
deleted file mode 100644
index da7fd4e7a..000000000
--- a/editor/libeditor/tests/test_bug1270235.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1270235
--->
-<head>
- <title>Test for Bug 1270235</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1270235">Mozilla Bug 1270235</a>
-<p id="display"></p>
-<div id="content" style="display: none;"></div>
-
-<div id="edit1" contenteditable="true"><p>AB</p></div>
-<script type="application/javascript">
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(()=>{
- let element = document.getElementById('edit1');
- element.focus();
- let textNode = element.firstChild.firstChild;
- let node = textNode.splitText(0);
- node.parentNode.removeChild(node);
-
- ok(!node.parentNode, 'parent must be null');
-
- let newRange = document.createRange();
- newRange.setStart(node, 0);
- newRange.setEnd(node, 0);
- let selection = document.getSelection();
- selection.removeAllRanges();
- selection.addRange(newRange);
-
- ok(selection.isCollapsed, 'isCollapsed must be true');
-
- // Don't crash by user input
- synthesizeKey("X", {});
-
- SimpleTest.finish();
-});
-</script>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1306532.html b/editor/libeditor/tests/test_bug1306532.html
deleted file mode 100644
index 1d7b3e7af..000000000
--- a/editor/libeditor/tests/test_bug1306532.html
+++ /dev/null
@@ -1,64 +0,0 @@
-<!DOCTYPE HTML>
-<html><head>
-<title>Test for bug 1306532</title>
-<style src="/tests/SimpleTest/test.css" type="text/css"></style>
-<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-
-<script class="testbody" type="application/javascript">
-
-function runTest() {
- // Copy content from table.
- var selection = getSelection();
- var startRange = document.createRange();
- startRange.setStart(headingone, 0);
- startRange.setEnd(celltwo, 0);
- selection.removeAllRanges();
- selection.addRange(startRange);
- SpecialPowers.wrap(document).execCommand("copy", false, null);
-
- // Paste content into "pasteframe"
- var pasteContainer = pasteframe.contentDocument.body;
- var pasteRange = pasteframe.contentDocument.createRange();
- pasteRange.selectNodeContents(pasteContainer);
- pasteRange.collapse(false);
- selection.removeAllRanges();
- selection.addRange(pasteRange);
- SpecialPowers.wrap(pasteframe.contentDocument).execCommand("paste", false, null);
-
- is(pasteContainer.querySelector("#headingone").textContent, "Month", "First heading should be 'Month'.");
- is(pasteContainer.querySelector("#headingtwo").textContent, "Savings", "Second heading should be 'Savings'.");
- is(pasteContainer.querySelector("#cellone").textContent, "January", "First cell should be 'January'.");
- is(pasteContainer.querySelector("#celltwo").textContent, "$100", "Second cell should be '$100'.");
-
- SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-
-</script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1306532">Mozilla Bug 1306532</a>
-<p id="display"></p>
-
-<pre id="test">
-</pre>
-
-<div id="container">
-<table border="1">
- <tr>
- <th id="headingone">Month</th>
- <th id="headingtwo">Savings</th>
- </tr>
- <tr>
- <td id="cellone">January</td>
- <td id="celltwo">$100</td>
- </tr>
-</table>
-</div>
-
-<iframe onload="runTest();" id="pasteframe" src="data:text/html,<html><body contenteditable='true'>"></iframe>
-
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1310912.html b/editor/libeditor/tests/test_bug1310912.html
deleted file mode 100644
index d73366a63..000000000
--- a/editor/libeditor/tests/test_bug1310912.html
+++ /dev/null
@@ -1,93 +0,0 @@
-<!DOCTYPE html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1310912
--->
-<html>
-<head>
- <title>Test for Bug 1310912</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1310912">Mozilla Bug 1310912</a>
-<p id="display"></p>
-<div id="content" style="display: none;">
-
-</div>
-
-<div id="editable1" contenteditable="true">ABC</div>
-<pre id="test">
-
-<script class="testbody" type="application/javascript">
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- let elm = document.getElementById("editable1");
-
- elm.focus();
- let sel = window.getSelection();
- sel.collapse(elm.childNodes[0], elm.textContent.length);
-
- synthesizeCompositionChange({
- composition: {
- string: "DEF",
- clauses: [
- { length: 3, attr: COMPOSITION_ATTR_RAW_CLAUSE }
- ]
- },
- caret: { start: 3, length: 0 }
- });
- ok(elm.textContent == "ABCDEF", "composing text should be set");
-
- window.getSelection().getRangeAt(0).insertNode(document.createTextNode(""));
- synthesizeCompositionChange({
- composition: {
- string: "GHI",
- clauses: [
- { length: 3, attr: COMPOSITION_ATTR_CONVERTED_CLAUSE }
- ]
- },
- caret: { start: 0, length: 0 }
- });
- ok(elm.textContent == "ABCGHI", "composing text should be replaced");
-
- window.getSelection().getRangeAt(0).insertNode(document.createTextNode(""));
- synthesizeCompositionChange({
- composition: {
- string: "JKL",
- clauses: [
- { length: 3, attr: COMPOSITION_ATTR_CONVERTED_CLAUSE }
- ]
- },
- caret: { start: 0, length: 0 }
- });
- ok(elm.textContent == "ABCJKL", "composing text should be replaced");
-
- window.getSelection().getRangeAt(0).insertNode(document.createTextNode(""));
- synthesizeCompositionChange({
- composition: {
- string: "MNO",
- clauses: [
- { length: 3, attr: COMPOSITION_ATTR_CONVERTED_CLAUSE }
- ]
- },
- caret: { start: 1, length: 0 }
- });
- ok(elm.textContent == "ABCMNO", "composing text should be replaced");
-
- window.getSelection().getRangeAt(0).insertNode(document.createTextNode(""));
- synthesizeComposition({ type: "compositioncommitasis" });
- ok(elm.textContent == "ABCMNO", "composing text should be committed");
-
- synthesizeKey("Z", { accelKey: true });
- ok(elm.textContent == "ABC", "text should be undoed");
-
- synthesizeKey("Z", { accelKey: true, shiftKey: true });
- ok(elm.textContent == "ABCMNO", "text should be redoed");
-
- SimpleTest.finish();
-});
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1314790.html b/editor/libeditor/tests/test_bug1314790.html
deleted file mode 100644
index ff1487244..000000000
--- a/editor/libeditor/tests/test_bug1314790.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1314790
--->
-<html>
-<head>
- <title>Test for Bug 1314790</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1314790">Mozilla Bug 1314790</a>
-<p id="display"></p>
-<div id="content" style="display: none;">
-
-</div>
-
-<div contenteditable="true" id="contenteditable1"><p>pen pineapple</p></div>
-<pre id="test">
-
-<script class="testbody" type="application/javascript">
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- let elm = document.getElementById("contenteditable1");
- elm.focus();
- window.getSelection().collapse(elm.childNodes[0], 0);
-
- SpecialPowers.doCommand(window, "cmd_wordNext");
- SpecialPowers.doCommand(window, "cmd_wordNext");
-
- synthesizeKey("VK_RETURN", {});
- synthesizeKey("a", {});
- synthesizeKey("p", {});
- synthesizeKey("p", {});
- synthesizeKey("l", {});
- synthesizeKey("e", {});
- synthesizeKey(" ", {});
- synthesizeKey("p", {});
- synthesizeKey("e", {});
- synthesizeKey("n", {});
-
- is(elm.childNodes[0].textContent, "pen pineapple",
- "'pen pineapple' is first elment");
- is(elm.childNodes[1].textContent, "apple pen",
- "'apple pen' is second elment");
-
- SpecialPowers.doCommand(window, "cmd_deleteWordBackward");
- SpecialPowers.doCommand(window, "cmd_deleteWordBackward");
- is(elm.childNodes[0].textContent, "pen pineapple",
- "'pen pineapple' is first elment");
-
- SpecialPowers.doCommand(window, "cmd_deleteWordBackward");
- is(elm.childNodes[0].textContent, "pen pineapple",
- "'pen pineapple' is first elment");
-
- SpecialPowers.doCommand(window, "cmd_deleteWordBackward");
- is(elm.childNodes[0].textContent, "pen ", "'pen ' is first elment");
-
- SimpleTest.finish();
-});
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1315065.html b/editor/libeditor/tests/test_bug1315065.html
deleted file mode 100644
index 16f0de4e3..000000000
--- a/editor/libeditor/tests/test_bug1315065.html
+++ /dev/null
@@ -1,145 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1315065
--->
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 1315065</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1315065">Mozilla Bug 1315065</a>
-<div contenteditable><p>abc<br></p></div>
-<script type="application/javascript">
-/** Test for Bug 1315065 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(()=>{
- var editor = document.getElementsByTagName("div")[0];
- function initForBackspace(aSelectionCollapsedTo /* = 0 ~ 3 */) {
- editor.innerHTML = "<p id='p'>abc<br></p>";
- var p = document.getElementById("p");
- // FYI: We cannot inserting empty text nodes as expected with
- // Node.appendChild() nor Node.insertBefore(). Therefore, let's use
- // Range.insertNode() like actual web apps.
- var selection = window.getSelection();
- selection.collapse(p, 1);
- var range = selection.getRangeAt(0);
- var emptyTextNode3 = document.createTextNode("");
- range.insertNode(emptyTextNode3);
- var emptyTextNode2 = document.createTextNode("");
- range.insertNode(emptyTextNode2);
- var emptyTextNode1 = document.createTextNode("");
- range.insertNode(emptyTextNode1);
- is(p.childNodes.length, 5, "Failed to initialize the editor");
- is(p.childNodes.item(1), emptyTextNode1, "1st text node should be emptyTextNode1");
- is(p.childNodes.item(2), emptyTextNode2, "2nd text node should be emptyTextNode2");
- is(p.childNodes.item(3), emptyTextNode3, "3rd text node should be emptyTextNode3");
- switch (aSelectionCollapsedTo) {
- case 0:
- selection.collapse(p.firstChild, 3); // next to 'c'
- break;
- case 1:
- selection.collapse(emptyTextNode1, 0);
- break;
- case 2:
- selection.collapse(emptyTextNode2, 0);
- break;
- case 3:
- selection.collapse(emptyTextNode3, 0);
- break;
- default:
- ok(false, "aSelectionCollapsedTo is illegal value");
- }
- }
-
- for (var i = 0; i < 4; i++) {
- const kDescription = i == 0 ? "Backspace from immediately after the last character" :
- "Backspace from " + i + "th empty text node";
- editor.focus();
- initForBackspace(i);
- synthesizeKey("KEY_Backspace", { code: "Backspace" });
- var p = document.getElementById("p");
- ok(p, kDescription + ": <p> element shouldn't be removed by Backspace key press");
- is(p.tagName.toLowerCase(), "p", kDescription + ": <p> element shouldn't be removed by Backspace key press");
- // When Backspace key is pressed even in empty text nodes, Gecko should not remove empty text nodes for now
- // because we should keep our traditional behavior (same as Edge) for backward compatibility as far as possible.
- // In this case, Chromium removes all empty text nodes, but Edge doesn't remove any empty text nodes.
- is(p.childNodes.length, 5, kDescription + ": <p> should have 5 children after pressing Backspace key");
- is(p.childNodes.item(0).textContent, "ab", kDescription + ": 'c' should be removed by pressing Backspace key");
- is(p.childNodes.item(1).textContent, "", kDescription + ": 1st empty text node should not be removed by pressing Backspace key");
- is(p.childNodes.item(2).textContent, "", kDescription + ": 2nd empty text node should not be removed by pressing Backspace key");
- is(p.childNodes.item(3).textContent, "", kDescription + ": 3rd empty text node should not be removed by pressing Backspace key");
- editor.blur();
- }
-
- function initForDelete(aSelectionCollapsedTo /* = 0 ~ 3 */) {
- editor.innerHTML = "<p id='p'>abc<br></p>";
- var p = document.getElementById("p");
- // FYI: We cannot inserting empty text nodes as expected with
- // Node.appendChild() nor Node.insertBefore(). Therefore, let's use
- // Range.insertNode() like actual web apps.
- var selection = window.getSelection();
- selection.collapse(p, 0);
- var range = selection.getRangeAt(0);
- var emptyTextNode1 = document.createTextNode("");
- range.insertNode(emptyTextNode1);
- var emptyTextNode2 = document.createTextNode("");
- range.insertNode(emptyTextNode2);
- var emptyTextNode3 = document.createTextNode("");
- range.insertNode(emptyTextNode3);
- is(p.childNodes.length, 5, "Failed to initialize the editor");
- is(p.childNodes.item(0), emptyTextNode3, "1st text node should be emptyTextNode3");
- is(p.childNodes.item(1), emptyTextNode2, "2nd text node should be emptyTextNode2");
- is(p.childNodes.item(2), emptyTextNode1, "3rd text node should be emptyTextNode1");
- switch (aSelectionCollapsedTo) {
- case 0:
- selection.collapse(p.childNodes.item(3), 0); // next to 'a'
- break;
- case 1:
- selection.collapse(emptyTextNode1, 0);
- break;
- case 2:
- selection.collapse(emptyTextNode2, 0);
- break;
- case 3:
- selection.collapse(emptyTextNode3, 0);
- break;
- default:
- ok(false, "aSelectionCollapsedTo is illegal value");
- }
- }
-
- for (var i = 0; i < 4; i++) {
- const kDescription = i == 0 ? "Delete from immediately before the first character" :
- "Delete from " + i + "th empty text node";
- editor.focus();
- initForDelete(i);
- synthesizeKey("KEY_Delete", { code: "Delete" });
- var p = document.getElementById("p");
- ok(p, kDescription + ": <p> element shouldn't be removed by Delete key press");
- is(p.tagName.toLowerCase(), "p", kDescription + ": <p> element shouldn't be removed by Delete key press");
- if (i == 0) {
- // If Delete key is pressed in non-empty text node, only the text node should be modified.
- // This is same behavior as Chromium, but different from Edge. Edge removes all empty text nodes in this case.
- is(p.childNodes.length, 5, kDescription + ": <p> should have only 2 children after pressing Delete key (empty text nodes should be removed");
- is(p.childNodes.item(0).textContent, "", kDescription + ": 1st empty text node should not be removed by pressing Delete key");
- is(p.childNodes.item(1).textContent, "", kDescription + ": 2nd empty text node should not be removed by pressing Delete key");
- is(p.childNodes.item(2).textContent, "", kDescription + ": 3rd empty text node should not be removed by pressing Delete key");
- is(p.childNodes.item(3).textContent, "bc", kDescription + ": 'a' should be removed by pressing Delete key");
- } else {
- // If Delete key is pressed in an empty text node, it and following empty text nodes should be removed and the non-empty text node should be modified.
- // This is same behavior as Chromium, but different from Edge. Edge removes all empty text nodes in this case.
- var expectedEmptyTextNodes = 3 - i;
- is(p.childNodes.length, expectedEmptyTextNodes + 2, kDescription + ": <p> should have only " + i + " children after pressing Delete key (" + i + " empty text nodes should be removed");
- is(p.childNodes.item(expectedEmptyTextNodes).textContent, "bc", kDescription + ": empty text nodes and 'a' should be removed by pressing Delete key");
- }
- editor.blur();
- }
- SimpleTest.finish();
-});
-</script>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1328023.html b/editor/libeditor/tests/test_bug1328023.html
deleted file mode 100644
index 1b7fb7bf5..000000000
--- a/editor/libeditor/tests/test_bug1328023.html
+++ /dev/null
@@ -1,64 +0,0 @@
-<!DOCTYPE html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1328023
--->
-<html>
-<head>
- <title>Test for Bug 1328023</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1328023">Mozilla Bug 1328023</a>
-<p id="display"></p>
-<div id="content" style="display: none;">
-
-</div>
-
-<input type="text" id="input1"/>
-<pre id="test">
-
-<script class="testbody" type="application/javascript">
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- let elm = document.getElementById("input1");
-
- elm.focus();
- synthesizeKey("A", {});
- synthesizeKey("B", {});
- is(elm.value, "AB", "AB is input.value now");
-
- synthesizeKey("VK_BACK_SPACE", {});
- is(elm.value, "A", "A is input.value now");
-
- synthesizeKey("Z", { accelKey: true });
- is(elm.value, "AB", "AB is input.value now");
-
- synthesizeKey("C", {});
- is(elm.value, "ABC", "ABC is input.value now");
-
- synthesizeKey("VK_BACK_SPACE", {});
- synthesizeKey("VK_BACK_SPACE", {});
- synthesizeKey("VK_BACK_SPACE", {});
-
- synthesizeKey("A", {});
- synthesizeKey("B", {});
- synthesizeKey("C", {});
- is(elm.value, "ABC", "ABC is input.value now");
-
- synthesizeKey("Z", { accelKey: true });
- is(elm.value, "", "'' is input.value now");
-
- synthesizeKey("Z", { accelKey: true, shiftKey: true });
- is(elm.value, "ABC", "ABC is input.value now");
-
- synthesizeKey("D", {});
- is(elm.value, "ABCD", "ABCD is input.value now");
-
- SimpleTest.finish();
-});
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1330796.html b/editor/libeditor/tests/test_bug1330796.html
deleted file mode 100644
index f8af02087..000000000
--- a/editor/libeditor/tests/test_bug1330796.html
+++ /dev/null
@@ -1,101 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1330796
--->
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 772796</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <style> .pre { white-space: pre } </style>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=772796">Mozilla Bug 1330796</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-
-<div id="editable" contenteditable></div>
-
-<pre id="test">
-
-<script type="application/javascript">
-// We want to test what happens when the user splits a mail cite by clicking
-// at the start, the middle and the end of the cite and hitting the enter key.
-// Mail cites are spans, and since bug 1288911 they are displayed as blocks.
-// The _moz_quote attribute is used to give the cite a blue color via CSS.
-// As an internal attribute, it's not returned from the innerHTML.
-// To the user the tests look like:
-// > mailcite
-// This text is 10 characters long, so we position at 0, 5 and 10.
-// Althought since bug 1288911 those cites are displayed as block,
-// the tests are repeated also for inline display.
-// Each entry of the 'tests' array has the original HTML, the offset to click
-// at and the expected result HTML.
-var tests = [
- // With style="display: block;".
- [ "<span _moz_quote=true style=\"display: block;\">&gt; mailcite<br></span>", 0,
- "x<br><span style=\"display: block;\">&gt; mailcite<br></span>" ],
- [ "<span _moz_quote=true style=\"display: block;\">&gt; mailcite<br></span>", 5,
- "<span style=\"display: block;\">&gt; mai<br></span>x<br><span style=\"display: block;\">lcite<br></span>"],
- [ "<span _moz_quote=true style=\"display: block;\">&gt; mailcite<br></span>", 10,
- "<span style=\"display: block;\">&gt; mailcite<br></span>x<br>" ],
- // No <br> at the end to simulate prior deletion to the end of the quote.
- [ "<span _moz_quote=true style=\"display: block;\">&gt; mailcite</span>", 10,
- "<span style=\"display: block;\">&gt; mailcite<br></span>x<br>" ],
-
- // Without style="display: block;".
- [ "<span _moz_quote=true>&gt; mailcite<br></span>", 0,
- "x<br><span>&gt; mailcite<br></span>" ],
- [ "<span _moz_quote=true>&gt; mailcite<br></span>", 5,
- "<span>&gt; mai</span><br>x<br><span>lcite<br></span>" ],
- [ "<span _moz_quote=true>&gt; mailcite<br></span>", 10,
- "<span>&gt; mailcite<br></span>x<br>" ],
- // No <br> at the end to simulate prior deletion to the end of the quote.
- [ "<span _moz_quote=true>&gt; mailcite</span>", 10,
- "<span>&gt; mailcite</span><br>x<br>" ]
-];
-
-/** Test for Bug 1330796 **/
-
-SimpleTest.waitForExplicitFinish();
-
-SimpleTest.waitForFocus(function() {
-
- var sel = window.getSelection();
- var theEdit = document.getElementById("editable");
- makeMailEditor();
-
- for (i = 0; i < tests.length; i++) {
- theEdit.innerHTML = tests[i][0];
- theEdit.focus();
- var theText = theEdit.firstChild.firstChild;
- // Position set at the beginning , middle and end of the text.
- sel.collapse(theText, tests[i][1]);
-
- synthesizeKey("KEY_Enter", { code: "Enter" });
- synthesizeKey("x", { code: "KeyX" });
- is(theEdit.innerHTML, tests[i][2], "unexpected HTML for test " + i.toString());
- }
-
- SimpleTest.finish();
-
-});
-
-function makeMailEditor() {
- var Ci = SpecialPowers.Ci;
- var editingSession = SpecialPowers.wrap(window)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIEditingSession);
- var editor = editingSession.getEditorForWindow(window);
- editor.flags |= Ci.nsIPlaintextEditor.eEditorMailMask;
-}
-</script>
-
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1332876.html b/editor/libeditor/tests/test_bug1332876.html
deleted file mode 100644
index 76dfa0fc7..000000000
--- a/editor/libeditor/tests/test_bug1332876.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=795418
--->
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 1332876</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1332876">Mozilla Bug 1332876</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-
-<iframe src="data:text/html,<html><body><span>Edit me!</span>"></iframe>
-
-<pre id="test">
-
-<script type="application/javascript">
-
-/** Test for Bug 1332876 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var iframe = document.querySelector("iframe");
- iframe.contentDocument.designMode='on';
-
- iframe.contentWindow.addEventListener('keypress', function() {
- iframe.style.display='none';
- document.body.offsetHeight;
- ok(true, "did not crash");
- SimpleTest.finish();
- });
-
- iframe.contentWindow.addEventListener('click', function() {
- synthesizeKey('a', {}, iframe.contentWindow);
- });
-
- synthesizeMouse(iframe,20,20,{})
-});
-
-</script>
-
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug1352799.html b/editor/libeditor/tests/test_bug1352799.html
deleted file mode 100644
index daedc40fc..000000000
--- a/editor/libeditor/tests/test_bug1352799.html
+++ /dev/null
@@ -1,98 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1352799
--->
-<head>
- <title>Test for Bug 1352799</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1352799">Mozilla Bug 1352799</a>
-<p id="display"></p>
-<div id="content">
-<div id="input-container" style="display: none;">
-<input id="input" maxlength="1">
-</div>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 1352799 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(() => {
- var input = document.getElementById("input");
-
- var inputcontainer = document.getElementById('input-container');
- input.setAttribute('maxlength', 2);
- inputcontainer.style.display = 'block';
-
- input.focus();
-
- synthesizeKey('1', {});
- synthesizeKey('2', {});
- synthesizeKey('3', {});
-
- is(input.value, '12', 'value should be 12 with maxlength = 2');
-
- input.value = '';
- inputcontainer.style.display = 'none';
-
- window.setTimeout(() => {
- input.setAttribute('maxlength', 4);
- inputcontainer.style.display = 'block';
-
- input.focus();
-
- synthesizeKey('4', {});
- synthesizeKey('5', {});
- synthesizeKey('6', {});
- synthesizeKey('7', {});
- synthesizeKey('8', {});
-
- is(input.value, '4567', 'value should be 4567 with maxlength = 4');
-
- inputcontainer.style.display = 'none';
-
- window.setTimeout(() => {
- input.setAttribute('maxlength', 2);
- inputcontainer.style.display = 'block';
-
- input.focus();
-
- synthesizeKey('1', {});
- synthesizeKey('2', {});
-
- todo_is(input.value, '45', 'value should be 45 with maxlength = 2');
-
- input.value = '';
- inputcontainer.style.display = 'none';
-
- window.setTimeout(() => {
- input.removeAttribute('maxlength');
- inputcontainer.style.display = 'block';
-
- input.focus();
-
- synthesizeKey('1', {});
- synthesizeKey('2', {});
- synthesizeKey('3', {});
- synthesizeKey('4', {});
- synthesizeKey('5', {});
- synthesizeKey('6', {});
- synthesizeKey('7', {});
- synthesizeKey('8', {});
-
- is(input.value, '12345678', 'value should be 12345678 without maxlength');
-
- SimpleTest.finish();
- }, 0);
- }, 0);
- }, 0);
-});
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug200416.html b/editor/libeditor/tests/test_bug200416.html
deleted file mode 100644
index 9fb656425..000000000
--- a/editor/libeditor/tests/test_bug200416.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=200416
--->
-<title>Test for Bug 200416</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css">
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=200416">Mozilla Bug 200416</a>
-<div contenteditable><span>foo<p>bar</p></span></div>
-<script>
-getSelection().collapse(document.querySelector("p").firstChild, 0);
-document.execCommand("delete");
-var innerHTML = document.querySelector("div").innerHTML;
-ok(/foo.*bar/.test(innerHTML), "foo needs to still come before bar");
-</script>
diff --git a/editor/libeditor/tests/test_bug289384.html b/editor/libeditor/tests/test_bug289384.html
deleted file mode 100644
index 1d55e0c3f..000000000
--- a/editor/libeditor/tests/test_bug289384.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=289384
--->
-<head>
- <title>Test for Bug 289384</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=289384">Mozilla Bug 289384</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-SimpleTest.waitForExplicitFinish();
-
-addLoadEvent(function() {
- var win = window.open("data:text/html,<a href=\"data:text/html,<body contenteditable onload='opener.continueTest(window);'>foo bar</body>\">link</a>", "", "test-289384");
- win.addEventListener("load", function onLoad() {
- win.removeEventListener("load", onLoad);
- win.document.querySelector("a").click();
- }, false);
-});
-
-function continueTest(win) {
- SimpleTest.waitForFocus(function() {
- var doc = win.document;
- var sel = win.getSelection();
- doc.body.focus();
- sel.collapse(doc.body.firstChild, 3);
- SimpleTest.executeSoon(function() {
- synthesizeKey("VK_LEFT", {accelKey: true}, win);
- ok(sel.isCollapsed, "The selection must be collapsed");
- is(sel.anchorNode, doc.body.firstChild, "The anchor node should be the body element's text node");
- is(sel.anchorOffset, 0, "The anchor offset should be 0");
- win.close();
- SimpleTest.finish();
- });
- }, win);
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug290026.html b/editor/libeditor/tests/test_bug290026.html
deleted file mode 100644
index 9e7686e72..000000000
--- a/editor/libeditor/tests/test_bug290026.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=290026
--->
-<head>
- <title>Test for Bug 290026</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=290026">Mozilla Bug 290026</a>
-<p id="display"></p>
-<div id="editor" contenteditable></div>
-
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 290026 **/
-SimpleTest.waitForExplicitFinish();
-
-var editor = document.getElementById("editor");
-editor.innerHTML = '<p></p><ul><li>Item 1</li><li>Item 2</li></ul><p></p>';
-editor.focus();
-
-addLoadEvent(function() {
- document.execCommand("stylewithcss", false, "true");
- var sel = window.getSelection();
- sel.removeAllRanges();
- var lis = document.getElementsByTagName("li");
- var range = document.createRange();
- range.setStart(lis[0], 0);
- range.setEnd(lis[1], lis[1].childNodes.length);
- sel.addRange(range);
- document.execCommand("indent", false, false);
- var oneindent = '<p></p><ul style="margin-left: 40px;"><li>Item 1</li><li>Item 2</li></ul><p></p>';
- is(editor.innerHTML, oneindent, "a once indented bulleted list");
- document.execCommand("indent", false, false);
- var twoindent = '<p></p><ul style="margin-left: 80px;"><li>Item 1</li><li>Item 2</li></ul><p></p>';
- is(editor.innerHTML, twoindent, "a twice indented bulleted list");
- document.execCommand("outdent", false, false);
- is(editor.innerHTML, oneindent, "outdenting a twice indented bulleted list");
-
- // done
- SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug291780.html b/editor/libeditor/tests/test_bug291780.html
deleted file mode 100644
index 93f63af61..000000000
--- a/editor/libeditor/tests/test_bug291780.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=291780
--->
-<head>
- <title>Test for Bug 291780</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=291780">Mozilla Bug 291780</a>
-<p id="display"></p>
-<div id="editor" contenteditable></div>
-
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 291780 **/
-SimpleTest.waitForExplicitFinish();
-
-var original = '<ul style="margin-left: 40px;"><li>Item 1</li><li>Item 2</li><li>Item 3</li><li>Item 4</li></ul>';
-var editor = document.getElementById("editor");
-editor.innerHTML = original;
-editor.focus();
-
-addLoadEvent(function() {
-
- var sel = window.getSelection();
- sel.removeAllRanges();
- var lis = document.getElementsByTagName("li");
- var range = document.createRange();
- range.setStart(lis[1], 0);
- range.setEnd(lis[2], lis[2].childNodes.length);
- sel.addRange(range);
- document.execCommand("indent", false, false);
- var expected = '<ul style="margin-left: 40px;"><li>Item 1</li><ul><li>Item 2</li><li>Item 3</li></ul><li>Item 4</li></ul>';
- is(editor.innerHTML, expected, "indenting part of an already indented bulleted list");
- document.execCommand("outdent", false, false);
- is(editor.innerHTML, original, "outdenting the partially indented part of an already indented bulleted list");
-
- // done
- SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug309731.html b/editor/libeditor/tests/test_bug309731.html
deleted file mode 100644
index 85406905c..000000000
--- a/editor/libeditor/tests/test_bug309731.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=309731
--->
-<head>
- <title>Test for Bug 309731</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=309731">Mozilla Bug 309731</a>
-<p id="display"></p>
-
-<div id="content">
- <div id="input" contentEditable="true"></div>
-</div>
-<pre id="test">
-<script type="application/javascript">
-/** Test for Bug 309731 **/
-
-function selectNode(node) {
- getSelection().selectAllChildren(node);
-}
-
-function selectInNode(node) {
- getSelection().collapse(node, 0);
-}
-
-function doTest() {
- var input = document.getElementById("input");
-
- is(input.textContent, "", "Input node starts empty");
-
- selectInNode(input);
- ok(document.execCommand("inserthtml", false, ""), "execCommand should return true");
- is(input.textContent, "", "empty inserthtml with empty selection shouldn't change contents");
-
- selectInNode(input);
- ok(document.execCommand("inserthtml", false, "foo"), "execCommand should return true");
- is(input.textContent, "foo", "'foo'inserthtml with empty selection should add foo to contents");
-
- selectNode(input);
- ok(document.execCommand("inserthtml", false, "bar"), "execCommand should return true");
- is(input.textContent, "bar", "'bar' inserthtml with complete selection should replace contents with bar");
-
- selectNode(input);
- ok(document.execCommand("inserthtml", false, ""), "execCommand should return true");
- is(input.textContent, "", "empty inserthtml with complete selection should delete everything");
-}
-
-doTest();
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug316447.html b/editor/libeditor/tests/test_bug316447.html
deleted file mode 100644
index 76d123815..000000000
--- a/editor/libeditor/tests/test_bug316447.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!DOCTYPE html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=316447
--->
-<title>Test for Bug 316447</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=316447">Mozilla Bug 316447</a>
-<div contenteditable><br></div>
-<script>
-/** Test for Bug 316447 **/
-
-getSelection().selectAllChildren(document.querySelector("div"));
-document.execCommand("inserthorizontalrule");
-is(document.querySelector("div").innerHTML, "<hr>", "Wrong innerHTML");
-</script>
diff --git a/editor/libeditor/tests/test_bug318065.html b/editor/libeditor/tests/test_bug318065.html
deleted file mode 100644
index 541653ab1..000000000
--- a/editor/libeditor/tests/test_bug318065.html
+++ /dev/null
@@ -1,82 +0,0 @@
-<!DOCTYPE HTML>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=318065
--->
-
-<head>
- <title>Test for Bug 318065</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-
-<body>
- <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=318065">Mozilla Bug 318065</a>
- <p id="display"></p>
- <div id="content" style="display: none">
- </div>
-
- <pre id="test">
- <script type="application/javascript">
-
- /** Test for Bug 318065 **/
- SimpleTest.waitForExplicitFinish();
- SimpleTest.waitForFocus(function() {
- var expectedValues = ["A", "", "A", "", "A", "", "A"];
- var messages = ["Initial text inserted",
- "Initial text deleted",
- "Undo of deletion",
- "Redo of deletion",
- "Initial text typed",
- "Undo of typing",
- "Redo of typing"];
- var step = 0;
-
- function onInput() {
- is(this.value, expectedValues[step], messages[step]);
- step++;
- if (step == expectedValues.length) {
- this.removeEventListener("input", onInput, false);
- SimpleTest.finish();
- }
- }
-
- var input = document.getElementById("t1");
- input.addEventListener("input", onInput, false);
- var input2 = document.getElementById("t2");
- input2.addEventListener("input", onInput, false);
-
- input.focus();
-
- // Tests 0 + 1: Input letter and delete it again
- synthesizeKey("A", {});
- synthesizeKey("VK_BACK_SPACE", {});
-
- // Test 2: Undo deletion. Value of input should be "A"
- synthesizeKey("Z", {accelKey: true});
-
- // Test 3: Redo deletion. Value of input should be ""
- synthesizeKey("Z", {accelKey: true, shiftKey: true});
-
- input2.focus();
-
- // Test 4: Input letter
- synthesizeKey("A", {});
-
- // Test 5: Undo typing. Value of input should be ""
- synthesizeKey("Z", {accelKey: true});
-
- // Test 6: Redo typing. Value of input should be "A"
- synthesizeKey("Z", {accelKey: true, shiftKey: true});
- });
- </script>
- </pre>
-
- <input type="text" value="" id="t1" />
- <input type="text" value="" id="t2" />
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug332636.html b/editor/libeditor/tests/test_bug332636.html
deleted file mode 100644
index 5df386ac4..000000000
--- a/editor/libeditor/tests/test_bug332636.html
+++ /dev/null
@@ -1,75 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=332636
--->
-<head>
- <title>Test for Bug 332636</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=332636">Mozilla Bug 332636</a>
-<p id="display"></p>
-<div id="content">
- <div id="edit0" contenteditable="true">axb</div><!-- reference: plane 0 base character -->
- <div id="edit1" contenteditable="true">a&#x0308;b</div><!-- reference: plane 0 diacritic -->
- <div id="edit2" contenteditable="true">a&#x10400;b</div><!-- plane 1 base character -->
- <div id="edit3" contenteditable="true">a&#x10a0f;b</div><!-- plane 1 diacritic -->
-
- <div id="edit0b" contenteditable="true">axb</div><!-- reference: plane 0 base character -->
- <div id="edit1b" contenteditable="true">a&#x0308;b</div><!-- reference: plane 0 diacritic -->
- <div id="edit2b" contenteditable="true">a&#x10400;b</div><!-- plane 1 base character -->
- <div id="edit3b" contenteditable="true">a&#x10a0f;b</div><!-- plane 1 diacritic -->
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 332636 **/
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(runTest);
-
-function test(edit) {
- edit.focus();
- var sel = window.getSelection();
- sel.collapse(edit.childNodes[0], edit.textContent.length - 1);
- synthesizeKey("VK_BACK_SPACE", {});
- is(edit.textContent, "ab", "The backspace key should delete the UTF-16 surrogate pair correctly");
-}
-
-function testWithMove(edit, offset) {
- edit.focus();
- var sel = window.getSelection();
- sel.collapse(edit.childNodes[0], 0);
- var i;
- for (i = 0; i < offset; ++i) {
- synthesizeKey("VK_RIGHT", {});
- synthesizeKey("VK_LEFT", {});
- synthesizeKey("VK_RIGHT", {});
- }
- synthesizeKey("VK_BACK_SPACE", {});
- is(edit.textContent, "ab", "The backspace key should delete the UTF-16 surrogate pair correctly");
-}
-
-function runTest() {
- /* test backspace-deletion of the middle character */
- test(document.getElementById("edit0"));
- test(document.getElementById("edit1"));
- test(document.getElementById("edit2"));
- test(document.getElementById("edit3"));
-
- /* extra tests with the use of RIGHT and LEFT to get to the right place */
- testWithMove(document.getElementById("edit0b"), 2);
- testWithMove(document.getElementById("edit1b"), 1);
- testWithMove(document.getElementById("edit2b"), 2);
- testWithMove(document.getElementById("edit3b"), 1);
-
- SimpleTest.finish();
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug332636.html^headers^ b/editor/libeditor/tests/test_bug332636.html^headers^
deleted file mode 100644
index e853d6cee..000000000
--- a/editor/libeditor/tests/test_bug332636.html^headers^
+++ /dev/null
@@ -1 +0,0 @@
-Content-Type: text/html; charset=UTF-8
diff --git a/editor/libeditor/tests/test_bug366682.html b/editor/libeditor/tests/test_bug366682.html
deleted file mode 100644
index bac618941..000000000
--- a/editor/libeditor/tests/test_bug366682.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=366682
--->
-<head>
- <title>Test for Bug 366682</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
- <script src="/tests/SimpleTest/EventUtils.js"></script>
- <script src="spellcheck.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=366682">Mozilla Bug 366682</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 366682 **/
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(runTest);
-
-var gMisspeltWords;
-
-function getEdit() {
- return document.getElementById('edit');
-}
-
-function editDoc() {
- return getEdit().contentDocument;
-}
-
-function getEditor() {
- var Ci = SpecialPowers.Ci;
- var win = editDoc().defaultView;
- var editingSession = SpecialPowers.wrap(win)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIEditingSession);
- return editingSession.getEditorForWindow(win);
-}
-
-function runTest() {
- editDoc().body.innerHTML = "<div>errror and an other errror</div>";
- gMisspeltWords = ["errror", "errror"];
- editDoc().designMode = "on";
-
- SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm")
- .onSpellCheck(editDoc().documentElement, evalTest);
-}
-
-function evalTest() {
- ok(isSpellingCheckOk(getEditor(), gMisspeltWords),
- "All misspellings accounted for.");
- SimpleTest.finish();
-}
-</script>
-</pre>
-
-<iframe id="edit" width="200" height="100" src="about:blank"></iframe>
-
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug372345.html b/editor/libeditor/tests/test_bug372345.html
deleted file mode 100644
index e9b1ac7a9..000000000
--- a/editor/libeditor/tests/test_bug372345.html
+++ /dev/null
@@ -1,59 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=372345
--->
-<head>
- <title>Test for Bug 372345</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=372345">Mozilla Bug 372345</a>
-<p id="display"></p>
-<div id="content">
- <iframe src="data:text/html,<body>"></iframe>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 372345 **/
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(function() {
- var iframe = document.querySelector("iframe");
- var doc = iframe.contentDocument;
- var content = doc.body;
- var link = content.querySelector("a");
- function testCursor(post) {
- setTimeout(function() {
- var link = document.createElement("a");
- link.href = "http://mozilla.org/";
- link.textContent = "link";
- link.style.cursor = "pointer";
- content.appendChild(link);
- is(iframe.contentWindow.getComputedStyle(link, null).cursor, "pointer", "Make sure that the cursor is set to pointer");
- setTimeout(post, 0);
- }, 0);
- }
- testCursor(function() {
- doc.designMode = "on";
- testCursor(function() {
- doc.designMode = "off";
- testCursor(function() {
- content.setAttribute("contenteditable", "true");
- testCursor(function() {
- content.removeAttribute("contenteditable");
- testCursor(function() {
- SimpleTest.finish();
- });
- });
- });
- });
- });
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug404320.html b/editor/libeditor/tests/test_bug404320.html
deleted file mode 100644
index b8249a557..000000000
--- a/editor/libeditor/tests/test_bug404320.html
+++ /dev/null
@@ -1,91 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=404320
--->
-<head>
- <title>Test for Bug 404320</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=404320">Mozilla Bug 404320</a>
-<p id="display"></p>
-<div id="content">
- <iframe id="testIframe"></iframe>
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-/** Test for Bug 404320 **/
-
-SimpleTest.waitForExplicitFinish();
-
-function runTests() {
- var win = document.getElementById("testIframe").contentWindow;
- var doc = document.getElementById("testIframe").contentDocument;
-
- function testFormatBlock(tag, withAngleBrackets, shouldSucceed)
- {
- win.getSelection().selectAllChildren(doc.body.firstChild);
- doc.execCommand("FormatBlock", false,
- withAngleBrackets ? tag : "<" + tag + ">");
- var resultNode;
- if (shouldSucceed && (tag == "dd" || tag == "dt")) {
- is(doc.body.firstChild.tagName, "DL", "tag was changed");
- resultNode = doc.body.firstChild.firstChild;
- }
- else {
- resultNode = doc.body.firstChild;
- }
-
- is(resultNode.tagName, shouldSucceed ? tag.toUpperCase() : "P", "tag was changed");
- }
-
- function formatBlockTests(tags, shouldSucceed)
- {
- var html = "<p>Content</p>";
- for (var i = 0; i < tags.length; ++i) {
- var tag = tags[i];
- var resultTag = tag.toUpperCase();
-
- doc.body.innerHTML = html;
- testFormatBlock(tag, false, shouldSucceed);
-
- doc.body.innerHTML = html;
- testFormatBlock(tag, true, shouldSucceed);
- }
- }
-
- doc.designMode = "on";
-
- var goodTags = [ "address",
- "blockquote",
- "dd",
- "div",
- "dl",
- "dt",
- "h1",
- "h2",
- "h3",
- "h4",
- "h5",
- "h6",
- "p",
- "pre" ];
- var badTags = [ "b",
- "i",
- "span",
- "foo" ];
-
- formatBlockTests(goodTags, true);
- formatBlockTests(badTags, false);
- SimpleTest.finish();
-}
-
-addLoadEvent(runTests);
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug408231.html b/editor/libeditor/tests/test_bug408231.html
deleted file mode 100644
index d365bfa09..000000000
--- a/editor/libeditor/tests/test_bug408231.html
+++ /dev/null
@@ -1,250 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=408231
--->
-<head>
- <title>Test for Bug 408231</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=408231">Mozilla Bug 408231</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-/** Test for Bug 408231 **/
-
- var commandEnabledResults = [
- ["contentReadOnly", "true"],
- ["copy", "false"],
- ["createlink", "true"],
- ["cut", "false"],
- ["decreasefontsize", "true"],
- ["delete", "true"],
- ["fontname", "true"],
- ["fontsize", "true"],
- ["formatblock", "true"],
- ["heading", "true"],
- ["hilitecolor", "true"],
- ["increasefontsize", "true"],
- ["indent", "true"],
- ["inserthorizontalrule", "true"],
- ["inserthtml", "true"],
- ["insertimage", "true"],
- ["insertorderedlist", "true"],
- ["insertunorderedlist", "true"],
- ["insertparagraph", "true"],
- ["italic", "true"],
- ["justifycenter", "true"],
- ["justifyfull", "true"],
- ["justifyleft", "true"],
- ["justifyright", "true"],
- ["outdent", "true"],
- ["paste", "false"],
- ["redo", "false"],
- ["removeformat", "true"],
- ["selectall", "true"],
- ["strikethrough", "true"],
- ["styleWithCSS", "true"],
- ["subscript", "true"],
- ["superscript", "true"],
- ["underline", "true"],
- ["undo", "false"],
- ["unlink", "true"],
- ["not-a-command", "false"]
- ];
-
- var commandIndetermResults = [
- ["contentReadOnly", "false"],
- ["copy", "false"],
- ["createlink", "false"],
- ["cut", "false"],
- ["decreasefontsize", "false"],
- ["delete", "false"],
- ["fontname", "false"],
- ["fontsize", "false"],
- ["formatblock", "false"],
- ["heading", "false"],
- ["hilitecolor", "false"],
- ["increasefontsize", "false"],
- ["indent", "false"],
- ["inserthorizontalrule", "false"],
- ["inserthtml", "false"],
- ["insertimage", "false"],
- ["insertorderedlist", "false"],
- ["insertunorderedlist", "false"],
- ["insertparagraph", "false"],
- ["italic", "false"],
- ["justifycenter", "false"],
- ["justifyfull", "false"],
- ["justifyleft", "false"],
- ["justifyright", "false"],
- ["outdent", "false"],
- //["paste", "false"],
- ["redo", "false"],
- ["removeformat", "false"],
- ["selectall", "false"],
- ["strikethrough", "false"],
- ["styleWithCSS", "false"],
- ["subscript", "false"],
- ["superscript", "false"],
- ["underline", "false"],
- ["undo", "false"],
- ["unlink", "false"],
- ["not-a-command", "false"]
- ];
-
- var commandStateResults = [
- ["contentReadOnly", "false"],
- ["copy", "false"],
- ["createlink", "false"],
- ["cut", "false"],
- ["decreasefontsize", "false"],
- ["delete", "false"],
- ["fontname", "false"],
- ["fontsize", "false"],
- ["formatblock", "false"],
- ["heading", "false"],
- ["hilitecolor", "false"],
- ["increasefontsize", "false"],
- ["indent", "false"],
- ["inserthorizontalrule", "false"],
- ["inserthtml", "false"],
- ["insertimage", "false"],
- ["insertorderedlist", "false"],
- ["insertunorderedlist", "false"],
- ["insertparagraph", "false"],
- ["italic", "false"],
- ["justifycenter", "false"],
- ["justifyfull", "false"],
- ["justifyleft", "true"],
- ["justifyright", "false"],
- ["outdent", "false"],
- //["paste", "false"],
- ["redo", "false"],
- ["removeformat", "false"],
- ["selectall", "false"],
- ["strikethrough", "false"],
- ["styleWithCSS", "false"],
- ["subscript", "false"],
- ["superscript", "false"],
- ["underline", "false"],
- ["undo", "false"],
- ["unlink", "false"],
- ["not-a-command", "false"]
- ];
-
- var commandValueResults = [
- ["contentReadOnly", ""],
- ["copy", ""],
- ["createlink", ""],
- ["cut", ""],
- ["decreasefontsize", ""],
- ["delete", ""],
- ["fontname", "serif"],
- ["fontsize", ""],
- ["formatblock", ""],
- ["heading", ""],
- ["hilitecolor", "transparent"],
- ["increasefontsize", ""],
- ["indent", ""],
- ["inserthorizontalrule", ""],
- ["inserthtml", ""],
- ["insertimage", ""],
- ["insertorderedlist", ""],
- ["insertunorderedlist", ""],
- ["insertparagraph", ""],
- ["italic", ""],
- ["justifycenter", "left"],
- ["justifyfull", "left"],
- ["justifyleft", "left"],
- ["justifyright", "left"],
- ["outdent", ""],
- //["paste", ""],
- ["redo", ""],
- ["removeformat", ""],
- ["selectall", ""],
- ["strikethrough", ""],
- ["styleWithCSS", ""],
- ["subscript", ""],
- ["superscript", ""],
- ["underline", ""],
- ["undo", ""],
- ["unlink", ""],
- ["not-a-command", ""],
- ];
-
-
- function callQueryCommandEnabled(cmdName) {
- var result;
- try {
- result = '' + document.queryCommandEnabled( cmdName );
- } catch( error ) {
- result = 'name' in error ? error.name : 'exception';
- }
- return result;
- }
-
- function callQueryCommandIndeterm(cmdName) {
- var result;
- try {
- result = '' + document.queryCommandIndeterm( cmdName );
- } catch( error ) {
- result = 'name' in error ? error.name : 'exception';
- }
- return result;
- }
-
- function callQueryCommandState(cmdName) {
- var result;
- try {
- result = '' + document.queryCommandState( cmdName );
- } catch( error ) {
- result = 'name' in error ? error.name : 'exception';
- }
- return result;
- }
-
- function callQueryCommandValue(cmdName) {
- var result;
- try {
- result = '' + document.queryCommandValue( cmdName );
- } catch( error ) {
- result = 'name' in error ? error.name : 'exception';
- }
- return result;
- }
-
- function testQueryCommand(expectedResults, fun, funName) {
- for (i=0; i<expectedResults.length; i++) {
- var commandName = expectedResults[i][0];
- var expectedResult = expectedResults[i][1];
- var result = fun(commandName);
- ok(result == expectedResult, funName + '('+commandName+') result=' +result+ ' expected=' + expectedResult);
- }
- }
-
- function runTests() {
- document.designMode='on';
- window.getSelection().collapse(document.body, 0);
- testQueryCommand(commandEnabledResults, callQueryCommandEnabled, "queryCommandEnabled");
- testQueryCommand(commandIndetermResults, callQueryCommandIndeterm, "queryCommandIndeterm");
- testQueryCommand(commandStateResults, callQueryCommandState, "queryCommandState");
- testQueryCommand(commandValueResults, callQueryCommandValue, "queryCommandValue");
- document.designMode='off';
- SimpleTest.finish();
- }
-
- window.onload = runTests;
- SimpleTest.waitForExplicitFinish();
-
-</script>
-</pre>
-</body>
-</html>
-
diff --git a/editor/libeditor/tests/test_bug410986.html b/editor/libeditor/tests/test_bug410986.html
deleted file mode 100644
index a3f3a5602..000000000
--- a/editor/libeditor/tests/test_bug410986.html
+++ /dev/null
@@ -1,80 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=410986
--->
-<head>
- <title>Test for Bug 410986</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=410986">Mozilla Bug 410986</a>
-<p id="display"></p>
-<div id="content">
- <div id="contents"><span style="color: green;">green text</span></div>
- <div id="editor" contenteditable="true"></div>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 410986 **/
-
-var gPasteEvents = 0;
-document.getElementById("editor").addEventListener("paste", function() {
- ++gPasteEvents;
-}, false);
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- getSelection().selectAllChildren(document.getElementById("contents"));
- SimpleTest.waitForClipboard("green text",
- function() {
- synthesizeKey("C", {accelKey: true});
- },
- function() {
- var ed = document.getElementById("editor");
- ed.focus();
- if (navigator.platform.indexOf("Mac") >= 0) {
- synthesizeKey("V", {accelKey: true, shiftKey: true, altKey: true});
- } else {
- synthesizeKey("V", {accelKey: true, shiftKey: true});
- }
- is(ed.innerHTML, "green text", "Content should be pasted in plaintext format");
- is(gPasteEvents, 1, "One paste event must be fired");
-
- ed.innerHTML = "";
- ed.blur();
- getSelection().selectAllChildren(document.getElementById("contents"));
- SimpleTest.waitForClipboard("green text",
- function() {
- synthesizeKey("C", {accelKey: true});
- },
- function() {
- var ed = document.getElementById("editor");
- ed.focus();
- synthesizeKey("V", {accelKey: true});
- isnot(ed.innerHTML.indexOf("<span style=\"color: green;\">green text</span>"), -1,
- "Content should be pasted in HTML format");
- is(gPasteEvents, 2, "Two paste events must be fired");
-
- SimpleTest.finish();
- },
- function() {
- ok(false, "Failed to copy the second item to the clipboard");
- SimpleTest.finish();
- }
- );
- },
- function() {
- ok(false, "Failed to copy the first item to the clipboard");
- SimpleTest.finish();
- }
- );
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug414526.html b/editor/libeditor/tests/test_bug414526.html
deleted file mode 100644
index 0975b6a5a..000000000
--- a/editor/libeditor/tests/test_bug414526.html
+++ /dev/null
@@ -1,247 +0,0 @@
-<html>
-<head>
- <title>Test for backspace key and delete key shouldn't remove another editing host's text</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<div id="display"></div>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-</pre>
-
-<script class="testbody" type="application/javascript">
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTests);
-
-function runTests()
-{
-
- var container = document.getElementById("display");
-
- function reset()
- {
- document.execCommand("Undo", false, null);
- }
-
- var selection = window.getSelection();
- function moveCaretToStartOf(aEditor)
- {
- selection.selectAllChildren(aEditor);
- selection.collapseToStart();
- }
-
- function moveCaretToEndOf(aEditor)
- {
- selection.selectAllChildren(aEditor);
- selection.collapseToEnd();
- }
-
- /* TestCase #1
- */
- const kTestCase1 =
- "<p id=\"editor1\" contenteditable=\"true\">editor1</p>" +
- "<p id=\"editor2\" contenteditable=\"true\">editor2</p>" +
- "<div id=\"editor3\" contenteditable=\"true\"><div>editor3</div></div>" +
- "<p id=\"editor4\" contenteditable=\"true\">editor4</p>" +
- "non-editable text" +
- "<p id=\"editor5\" contenteditable=\"true\">editor5</p>";
-
- const kTestCase1_editor3_deleteAtStart =
- "<p id=\"editor1\" contenteditable=\"true\">editor1</p>" +
- "<p id=\"editor2\" contenteditable=\"true\">editor2</p>" +
- "<div id=\"editor3\" contenteditable=\"true\"><div>ditor3</div></div>" +
- "<p id=\"editor4\" contenteditable=\"true\">editor4</p>" +
- "non-editable text" +
- "<p id=\"editor5\" contenteditable=\"true\">editor5</p>";
-
- const kTestCase1_editor3_backspaceAtEnd =
- "<p id=\"editor1\" contenteditable=\"true\">editor1</p>" +
- "<p id=\"editor2\" contenteditable=\"true\">editor2</p>" +
- "<div id=\"editor3\" contenteditable=\"true\"><div>editor</div></div>" +
- "<p id=\"editor4\" contenteditable=\"true\">editor4</p>" +
- "non-editable text" +
- "<p id=\"editor5\" contenteditable=\"true\">editor5</p>";
-
- container.innerHTML = kTestCase1;
-
- var editor1 = document.getElementById("editor1");
- var editor2 = document.getElementById("editor2");
- var editor3 = document.getElementById("editor3");
- var editor4 = document.getElementById("editor4");
- var editor5 = document.getElementById("editor5");
-
- /* TestCase #1:
- * pressing backspace key at start should not change the content.
- */
- editor2.focus();
- moveCaretToStartOf(editor2);
- synthesizeKey("VK_BACK_SPACE", { });
- is(container.innerHTML, kTestCase1,
- "Pressing backspace key at start of editor2 changes the content");
- reset();
-
- editor3.focus();
- moveCaretToStartOf(editor3);
- synthesizeKey("VK_BACK_SPACE", { });
- is(container.innerHTML, kTestCase1,
- "Pressing backspace key at start of editor3 changes the content");
- reset();
-
- editor4.focus();
- moveCaretToStartOf(editor4);
- synthesizeKey("VK_BACK_SPACE", { });
- is(container.innerHTML, kTestCase1,
- "Pressing backspace key at start of editor4 changes the content");
- reset();
-
- editor5.focus();
- moveCaretToStartOf(editor5);
- synthesizeKey("VK_BACK_SPACE", { });
- is(container.innerHTML, kTestCase1,
- "Pressing backspace key at start of editor5 changes the content");
- reset();
-
- /* TestCase #1:
- * pressing delete key at end should not change the content.
- */
- editor1.focus();
- moveCaretToEndOf(editor1);
- synthesizeKey("VK_DELETE", { });
- is(container.innerHTML, kTestCase1,
- "Pressing delete key at end of editor1 changes the content");
- reset();
-
- editor2.focus();
- moveCaretToEndOf(editor2);
- synthesizeKey("VK_DELETE", { });
- is(container.innerHTML, kTestCase1,
- "Pressing delete key at end of editor2 changes the content");
- reset();
-
- editor3.focus();
- moveCaretToEndOf(editor3);
- synthesizeKey("VK_DELETE", { });
- is(container.innerHTML, kTestCase1,
- "Pressing delete key at end of editor3 changes the content");
- reset();
-
- editor4.focus();
- moveCaretToEndOf(editor4);
- synthesizeKey("VK_DELETE", { });
- is(container.innerHTML, kTestCase1,
- "Pressing delete key at end of editor4 changes the content");
- reset();
-
- /* TestCase #1: cases when the caret is not on text node.
- * - pressing delete key at start should remove the first character
- * - pressing backspace key at end should remove the first character
- * and the adjacent blocks should not be changed.
- */
- editor3.focus();
- moveCaretToStartOf(editor3);
- synthesizeKey("VK_DELETE", { });
- is(container.innerHTML, kTestCase1_editor3_deleteAtStart,
- "Pressing delete key at start of editor3 changes adjacent elements"
- + " and/or does not remove the first character.");
- reset();
-
- // Backspace doesn't work here yet.
- editor3.focus();
- moveCaretToEndOf(editor3);
- synthesizeKey("VK_BACK_SPACE", { });
- todo_is(container.innerHTML, kTestCase1_editor3_backspaceAtEnd,
- "Pressing backspace key at end of editor3 changes adjacent elements"
- + " and/or does not remove the last character.");
- reset();
- // We can still check that adjacent elements are not affected.
- editor3.focus();
- moveCaretToEndOf(editor3);
- synthesizeKey("VK_BACK_SPACE", { });
- is(container.innerHTML, kTestCase1,
- "Pressing backspace key at end of editor3 changes the content");
- reset();
-
- /* TestCase #2:
- * two adjacent editable <span> in a table cell.
- */
- const kTestCase2 = "<table><tbody><tr><td><span id=\"editor1\" contenteditable=\"true\">test</span>" +
- "<span id=\"editor2\" contenteditable=\"true\">test</span></td></tr></tbody></table>";
-
- container.innerHTML = kTestCase2;
- editor1 = document.getElementById("editor1");
- editor2 = document.getElementById("editor2");
-
- editor2.focus();
- moveCaretToStartOf(editor2);
- synthesizeKey("VK_BACK_SPACE", { });
- is(container.innerHTML, kTestCase2,
- "Pressing backspace key at the start of editor2 changes the content for kTestCase2");
- reset();
-
- editor1.focus();
- moveCaretToEndOf(editor1);
- synthesizeKey("VK_DELETE", { });
- is(container.innerHTML, kTestCase2,
- "Pressing delete key at the end of editor1 changes the content for kTestCase2");
- reset();
-
- /* TestCase #3:
- * editable <span> in two adjacent table cells.
- */
- const kTestCase3 = "<table><tbody><tr><td><span id=\"editor1\" contenteditable=\"true\">test</span></td>" +
- "<td><span id=\"editor2\" contenteditable=\"true\">test</span></td></tr></tbody></table>";
-
- container.innerHTML = kTestCase3;
- editor1 = document.getElementById("editor1");
- editor2 = document.getElementById("editor2");
-
- editor2.focus();
- moveCaretToStartOf(editor2);
- synthesizeKey("VK_BACK_SPACE", { });
- is(container.innerHTML, kTestCase3,
- "Pressing backspace key at the start of editor2 changes the content for kTestCase3");
- reset();
-
- editor1.focus();
- moveCaretToEndOf(editor1);
- synthesizeKey("VK_DELETE", { });
- is(container.innerHTML, kTestCase3,
- "Pressing delete key at the end of editor1 changes the content for kTestCase3");
- reset();
-
- /* TestCase #4:
- * editable <div> in two adjacent table cells.
- */
- const kTestCase4 = "<table><tbody><tr><td><div id=\"editor1\" contenteditable=\"true\">test</div></td>" +
- "<td><div id=\"editor2\" contenteditable=\"true\">test</div></td></tr></tbody></table>";
-
- container.innerHTML = kTestCase4;
- editor1 = document.getElementById("editor1");
- editor2 = document.getElementById("editor2");
-
- editor2.focus();
- moveCaretToStartOf(editor2);
- synthesizeKey("VK_BACK_SPACE", { });
- is(container.innerHTML, kTestCase4,
- "Pressing backspace key at the start of editor2 changes the content for kTestCase4");
- reset();
-
- editor1.focus();
- moveCaretToEndOf(editor1);
- synthesizeKey("VK_DELETE", { });
- is(container.innerHTML, kTestCase4,
- "Pressing delete key at the end of editor1 changes the content for kTestCase4");
- reset();
-
- SimpleTest.finish();
-}
-
-</script>
-</body>
-
-</html>
diff --git a/editor/libeditor/tests/test_bug417418.html b/editor/libeditor/tests/test_bug417418.html
deleted file mode 100644
index 146de0920..000000000
--- a/editor/libeditor/tests/test_bug417418.html
+++ /dev/null
@@ -1,78 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=417418
--->
-<head>
- <title>Test for Bug 417418</title>
- <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=417418">Mozilla Bug 417418</a>
-<div id="display" contenteditable="true">
-<p id="coin">first paragraph</p>
-<p>second paragraph. <img id="img" src="green.png"></p>
-</div>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-/** Test for Bug 417418 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTest);
-
-function resetSelection() {
- window.getSelection().collapse(document.getElementById("coin"), 0);
-}
-
-function runTest() {
- var rightClickDown = {type: 'mousedown', button: 2},
- rightClickUp = {type: 'mouseup', button: 2},
- singleClickDown = {type: 'mousedown', button: 0},
- singleClickUp = {type: 'mouseup', button: 0};
- var selection = window.getSelection();
-
- var div = document.getElementById('display');
- var img = document.getElementById('img');
- var divRect = div.getBoundingClientRect();
- var imgselected;
-
- resetSelection();
- synthesizeMouse(div, divRect.width - 1, divRect.height - 1, rightClickDown);
- synthesizeMouse(div, divRect.width - 1, divRect.height - 1, rightClickUp);
- ok(selection.isCollapsed, "selection is not collapsed");
-
- resetSelection();
- synthesizeMouse(div, divRect.width - 1, divRect.height - 1, singleClickDown);
- synthesizeMouse(div, divRect.width - 1, divRect.height - 1, singleClickUp);
- ok(selection.isCollapsed, "selection is not collapsed");
-
- resetSelection();
- synthesizeMouseAtCenter(img, rightClickDown);
- synthesizeMouseAtCenter(img, rightClickUp);
- imgselected = selection.anchorNode == img.parentNode &&
- selection.anchorOffset === 1 &&
- selection.rangeCount === 1;
- ok(imgselected, "image is not selected");
-
- resetSelection();
- synthesizeMouseAtCenter(img, singleClickDown);
- synthesizeMouseAtCenter(img, singleClickUp);
- imgselected = selection.anchorNode == img.parentNode &&
- selection.anchorOffset === 1 &&
- selection.rangeCount === 1;
- ok(imgselected, "image is not selected");
-
- SimpleTest.finish();
-}
-
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug432225.html b/editor/libeditor/tests/test_bug432225.html
deleted file mode 100644
index 58d158722..000000000
--- a/editor/libeditor/tests/test_bug432225.html
+++ /dev/null
@@ -1,71 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=432225
--->
-<head>
- <title>Test for Bug 432225</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <script src="spellcheck.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=432225">Mozilla Bug 432225</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 432225 **/
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(runTest);
-
-var gMisspeltWords = [];
-
-function getEdit() {
- return document.getElementById('edit');
-}
-
-function editDoc() {
- return getEdit().contentDocument;
-}
-
-function getEditor() {
- var Ci = SpecialPowers.Ci;
- var win = editDoc().defaultView;
- var editingSession = SpecialPowers.wrap(win)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIEditingSession);
- return editingSession.getEditorForWindow(win);
-}
-
-function runTest() {
- editDoc().designMode = "on";
- setTimeout(function() { addWords(100); }, 0);
-}
-
-function addWords(aLimit) {
- if (aLimit == 0) {
- ok(isSpellingCheckOk(getEditor(), gMisspeltWords),
- "All misspellings accounted for.");
- SimpleTest.finish();
- return;
- }
- getEdit().focus();
- sendString('aa OK ');
- gMisspeltWords.push("aa");
- setTimeout(function() { addWords(aLimit-1); }, 0);
-}
-</script>
-</pre>
-
-<iframe id="edit" width="200" height="100" src="about:blank"></iframe>
-
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug439808.html b/editor/libeditor/tests/test_bug439808.html
deleted file mode 100644
index a04d1d4d4..000000000
--- a/editor/libeditor/tests/test_bug439808.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=439808
--->
-<head>
- <title>Test for Bug 439808</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=439808">Mozilla Bug 439808</a>
-<p id="display"></p>
-<div id="content">
-<span><span contenteditable id="e">twest</span></span>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 439808 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var e = document.getElementById("e");
- e.focus();
- getSelection().collapse(e.firstChild, 1);
- synthesizeKey("VK_DELETE", {});
- is(e.textContent, "test", "Delete key worked");
- synthesizeKey("VK_BACK_SPACE", {});
- is(e.textContent, "est", "Backspace key worked");
- SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug442186.html b/editor/libeditor/tests/test_bug442186.html
deleted file mode 100644
index eab81e055..000000000
--- a/editor/libeditor/tests/test_bug442186.html
+++ /dev/null
@@ -1,103 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=442186
--->
-<head>
- <title>Test for Bug 442186</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=442186">Mozilla Bug 442186</a>
-<p id="display"></p>
-<div id="content">
- <h2> two &lt;div&gt; containers </h2>
- <section contenteditable id="test1">
- <div> First paragraph with some text. </div>
- <div> Second paragraph with some text. </div>
- </section>
-
- <h2> two paragraphs </h2>
- <section contenteditable id="test2">
- <p> First paragraph with some text. </p>
- <p> Second paragraph with some text. </p>
- </section>
-
- <h2> one text node, one paragraph </h2>
- <section contenteditable id="test3">
- First paragraph with some text.
- <p> Second paragraph with some text. </p>
- </section>
-</div>
-
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 442186 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTests);
-
-function justify(textNode, pos) {
- if (!pos) pos = 10;
-
- // put the caret on the requested character
- var range = document.createRange();
- var sel = window.getSelection();
- range.setStart(textNode, pos);
- range.setEnd(textNode, pos);
- sel.addRange(range);
-
- // align
- document.execCommand("justifyright", false, null);
-}
-
-function runTests() {
- document.execCommand("stylewithcss", false, "true");
-
- const test1 = document.getElementById("test1");
- const test2 = document.getElementById("test2");
- const test3 = document.getElementById("test3");
-
- // #test1: two <div> containers
- const line1 = test1.querySelector("div").firstChild;
- test1.focus();
- justify(line1);
- is(test1.querySelectorAll("*").length, 2,
- "Aligning the first child should not create nor remove any element.");
- is(line1.parentNode.nodeName.toLowerCase(), "div",
- "Aligning the first <div> should not modify its node type.");
- is(line1.parentNode.style.textAlign, "right",
- "Aligning the first <div> should set a 'text-align: right' style rule.");
-
- // #test2: two paragraphs
- const line2 = test2.querySelector("p").firstChild;
- test2.focus();
- justify(line2);
- is(test2.querySelectorAll("*").length, 2,
- "Aligning the first child should not create nor remove any element.");
- is(line2.parentNode.nodeName.toLowerCase(), "p",
- "Aligning the first paragraph should not modify its node type.");
- is(line2.parentNode.style.textAlign, "right",
- "Aligning the first paragraph should set a 'text-align: right' style rule.");
-
- // #test3: one text node, two paragraphs
- const line3 = test3.firstChild;
- test3.focus();
- justify(line3);
- is(test3.querySelectorAll("*").length, 2,
- "Aligning the first child should create a block element.");
- is(line3.parentNode.nodeName.toLowerCase(), "div",
- "Aligning the first child should create a block element.");
- is(line3.parentNode.style.textAlign, "right",
- "Aligning the first line should set a 'text-align: right' style rule.");
-
- // done
- SimpleTest.finish();
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug449243.html b/editor/libeditor/tests/test_bug449243.html
deleted file mode 100644
index 77a7c6a7d..000000000
--- a/editor/libeditor/tests/test_bug449243.html
+++ /dev/null
@@ -1,136 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=449243
--->
-<head>
- <title>Test for Bug 449243</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=449243">Mozilla Bug 449243</a>
-<p id="display"></p>
-<div id="content" contenteditable>
- <h2>This is a title</h2>
- <ul>
- <li>this is a</li>
- <li>bullet list</li>
- </ul>
- <ol>
- <li>this is a</li>
- <li>numbered list</li>
- </ol>
-</div>
-
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 449243 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTests);
-
-const CARET_BEGIN = 0;
-const CARET_MIDDLE = 1;
-const CARET_END = 2;
-
-function split(element, caretPos, nbKeyPresses) {
- // put the caret on the requested position
- var sel = window.getSelection();
- var len = element.textContent.length;
- var pos = -1;
- switch (caretPos) {
- case CARET_BEGIN:
- pos = 0;
- break;
- case CARET_MIDDLE:
- pos = Math.floor(len/2);
- break;
- case CARET_END:
- pos = len;
- break;
- }
- sel.collapse(element.firstChild, pos);
-
- // simulates a [Return] keypress
- for (var i = 0; i < nbKeyPresses; i++)
- synthesizeKey("VK_RETURN", {});
-}
-
-function undo(nbKeyPresses) {
- for (var i = 0; i < nbKeyPresses; i++)
- document.execCommand("Undo", false, null);
-}
-
-function SameTypeAsPreviousSibling(element) {
- var sibling = element.previousSibling;
- while (sibling && sibling.nodeType != 1)
- sibling = element.previousSibling;
- return (element.nodeName == sibling.nodeName);
-}
-
-function isParagraph(element) {
- return element.nodeName.toLowerCase() == "p";
-}
-
-function runTests() {
- const content = document.querySelector("[contenteditable]");
- const header = content.querySelector("h2");
- const ulItem = content.querySelector("ul > li:last-child");
- const olItem = content.querySelector("ol > li:last-child");
- content.focus();
-
- // beginning of selection: split current node
- split(header, CARET_BEGIN, 1);
- ok(SameTypeAsPreviousSibling(header),
- "Pressing [Return] at the beginning of a header " +
- "should create another header.");
- split(ulItem, CARET_BEGIN, 2);
- ok(SameTypeAsPreviousSibling(ulItem),
- "Pressing [Return] at the beginning of an unordered list item " +
- "should create another list item.");
- split(olItem, CARET_BEGIN, 2);
- ok(SameTypeAsPreviousSibling(olItem),
- "Pressing [Return] at the beginning of an ordered list item " +
- "should create another list item.");
- undo(3);
-
- // middle of selection: split current node
- split(header, CARET_MIDDLE, 1);
- ok(SameTypeAsPreviousSibling(header),
- "Pressing [Return] at the middle of a header " +
- "should create another header.");
- split(ulItem, CARET_MIDDLE, 2);
- ok(SameTypeAsPreviousSibling(ulItem),
- "Pressing [Return] at the middle of an unordered list item " +
- "should create another list item.");
- split(olItem, CARET_MIDDLE, 2);
- ok(SameTypeAsPreviousSibling(olItem),
- "Pressing [Return] at the middle of an ordered list item " +
- "should create another list item.");
- undo(3);
-
- // end of selection: create a new paragraph
- split(header, CARET_END, 1);
- ok(isParagraph(content.querySelector("h2+*")),
- "Pressing [Return] at the end of a header " +
- "should create a new paragraph.");
- split(ulItem, CARET_END, 2);
- ok(isParagraph(content.querySelector("ul+*")),
- "Pressing [Return] twice at the end of an unordered list item " +
- "should create a new paragraph.");
- split(olItem, CARET_END, 2);
- ok(isParagraph(content.querySelector("ol+*")),
- "Pressing [Return] twice at the end of an ordered list item " +
- "should create a new paragraph.");
- undo(3);
-
- // done
- SimpleTest.finish();
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug455992.html b/editor/libeditor/tests/test_bug455992.html
deleted file mode 100644
index daf362acf..000000000
--- a/editor/libeditor/tests/test_bug455992.html
+++ /dev/null
@@ -1,97 +0,0 @@
-<!DOCTYPE HTML>
-<html><head>
-<title>Test for bug 455992</title>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-
-<script class="testbody" type="application/javascript">
-function runTest() {
-
- function select(id) {
- var e = document.getElementById(id);
- e.focus();
- return e;
- }
-
- function setupIframe(id) {
- var e = document.getElementById(id);
- var doc = e.contentDocument;
- doc.body.innerHTML = String.fromCharCode(10)+'<span id="' + id + '_span" style="border:1px solid blue" contenteditable="true">X</span>'+String.fromCharCode(10);
- e = doc.getElementById(id + "_span");
- e.focus();
- return e;
- }
-
- function test_begin_bs(e) {
- const msg = "BACKSPACE at beginning of contenteditable inline element";
- var before = e.parentNode.childNodes[0].nodeValue;
- sendKey("back_space");
- is(e.parentNode.childNodes[0].nodeValue, before, msg + " with id=" + e.id);
- is(e.innerHTML, "X", msg + " with id=" + e.id);
- }
-
- function test_begin_space(e) {
- const msg = "SPACE at beginning of contenteditable inline element";
- var before = e.parentNode.childNodes[0].nodeValue;
- sendChar(" ");
- is(e.parentNode.childNodes[0].nodeValue, before, msg + " with id=" + e.id);
- is(e.innerHTML, "&nbsp;X", msg + " with id=" + e.id);
- }
-
- function test_end_delete(e) {
- const msg = "DEL at end of contenteditable inline element";
- var before = e.parentNode.childNodes[2].nodeValue;
- sendKey("right");
- sendKey("delete");
- is(e.parentNode.childNodes[2].nodeValue, before, msg + " with id=" + e.id);
- is(e.innerHTML, "X", msg + " with id=" + e.id);
- }
-
- function test_end_space(e) {
- const msg = "SPACE at end of contenteditable inline element";
- var before = e.parentNode.childNodes[2].nodeValue;
- sendKey("right");
- sendChar(" ");
- is(e.parentNode.childNodes[2].nodeValue, before, msg + " with id=" + e.id);
- is(e.innerHTML, "X" + (e.tagName=="SPAN" ? "&nbsp;" : " <br>"), msg + " with id=" + e.id);
- }
-
- test_begin_bs(select("t1"));
- test_begin_space(select("t2"));
- test_end_delete(select("t3"));
- test_end_space(select("t4"));
- test_end_space(select("t5"));
-
- test_begin_bs(setupIframe('i1'));
- test_begin_space(setupIframe('i2'));
- test_end_delete(setupIframe('i3'));
- test_end_space(setupIframe('i4'));
-
- SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(runTest);
-</script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=455992">Mozilla Bug 455992</a>
-<p id="display"></p>
-
-<pre id="test">
-</pre>
-
-<div> <span id="t1" style="border:1px solid blue" contenteditable="true">X</span> Y</div>
-<div> <span id="t2" style="border:1px solid blue" contenteditable="true">X</span> Y</div>
-<div> <span id="t3" style="border:1px solid blue" contenteditable="true">X</span> Y</div>
-<div> <span id="t4" style="border:1px solid blue" contenteditable="true">X</span> Y</div>
-<div> <div id="t5" style="border:1px solid blue" contenteditable="true">X</div> Y</div>
-
-<iframe id="i1" width="200" height="100" src="about:blank"></iframe><br>
-<iframe id="i2" width="200" height="100" src="about:blank"></iframe><br>
-<iframe id="i3" width="200" height="100" src="about:blank"></iframe><br>
-<iframe id="i4" width="200" height="100" src="about:blank"></iframe><br>
-
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug456244.html b/editor/libeditor/tests/test_bug456244.html
deleted file mode 100644
index 03cc2c9e3..000000000
--- a/editor/libeditor/tests/test_bug456244.html
+++ /dev/null
@@ -1,70 +0,0 @@
-<!DOCTYPE HTML>
-<html><head>
-<title>Test for bug 456244</title>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-
-<script class="testbody" type="application/javascript">
-function runTest() {
-
- function select(id) {
- var e = document.getElementById(id);
- e.focus();
- return e;
- }
-
- function setupIframe(id) {
- var e = document.getElementById(id);
- var doc = e.contentDocument;
- doc.body.innerHTML = String.fromCharCode(10)+'<span id="' + id + '_span" style="border:1px solid blue" contenteditable="true">X</span>'+String.fromCharCode(10);
- e = doc.getElementById(id + "_span");
- e.focus();
- return e;
- }
-
- function test_end_bs(e) {
- const msg = "Deleting all text in contenteditable inline element";
- var before = e.parentNode.childNodes[0].nodeValue;
- sendKey("right");
- sendKey("back_space");
- sendKey("back_space");
- is(e.parentNode.childNodes[0].nodeValue, before, msg + " with id=" + e.id);
- is(e.innerHTML, "", msg + " with id=" + e.id);
- }
-
- test_end_bs(select("t1"));
- test_end_bs(setupIframe('i1',0));
-
- {
- const msg = "Deleting all text in contenteditable body element";
- var e = document.getElementById('i2');
- var doc = e.contentDocument;
- doc.body.setAttribute("contenteditable", "true");
- doc.body.focus();
- sendKey("right");
- sendKey("back_space");
- is(doc.body.innerHTML, "<br>", msg + " with id=" + e.id);
- }
-
- SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(runTest);
-</script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=456244">Mozilla Bug 456244</a>
-<p id="display"></p>
-
-<pre id="test">
-</pre>
-
-<div> <span id="t1" style="border:1px solid blue" contenteditable="true">X</span> Y</div>
-
-<iframe id="i1" width="200" height="100" src="about:blank"></iframe><br>
-<iframe id="i2" width="200" height="100" src="about:blank">X</iframe><br>
-
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug460740.html b/editor/libeditor/tests/test_bug460740.html
deleted file mode 100644
index b9e79c1e0..000000000
--- a/editor/libeditor/tests/test_bug460740.html
+++ /dev/null
@@ -1,124 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=460740
--->
-<head>
- <title>Test for Bug 460740</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=460740">Mozilla Bug 460740</a>
-<p id="display"></p>
-<div id="content">
- <ul>
- <li contenteditable>
- Editable LI
- </li>
- <li>
- <div contenteditable>
- Editable DIV inside LI
- </div>
- </li>
- <li>
- <div>
- <div contenteditable>
- Editable DIV inside DIV inside LI
- </div>
- </div>
- </li>
- <li>
- <h3>
- <div contenteditable>
- Editable DIV inside H3 inside LI
- </div>
- </h3>
- </li>
- </ul>
- <div contenteditable>
- Editable DIV
- </div>
- <h3 contenteditable>
- Editable H3
- </h3>
- <p contenteditable>
- Editable P
- </p>
- <div>
- <p contenteditable>
- Editable P in a DIV
- </p>
- </div>
- <p><span contenteditable>Editable SPAN in a P</span></p>
-</div>
-
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 460740 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTests);
-
-const CARET_BEGIN = 0;
-const CARET_MIDDLE = 1;
-const CARET_END = 2;
-
-function split(element, caretPos) {
- // compute the requested position
- var len = element.textContent.length;
- var pos = -1;
- switch (caretPos) {
- case CARET_BEGIN:
- pos = 0;
- break;
- case CARET_MIDDLE:
- pos = Math.floor(len/2);
- break;
- case CARET_END:
- pos = len;
- break;
- }
-
- // put the caret on the requested position
- var range = document.createRange();
- var sel = window.getSelection();
- range.setStart(element.firstChild, pos);
- range.setEnd(element.firstChild, pos);
- sel.addRange(range);
-
- // simulates a [Return] keypress
- synthesizeKey("VK_RETURN", {});
-}
-
-// count the number of non-BR elements in #content
-function getBlockCount() {
- return document.querySelectorAll("#content *:not(br)").length;
-}
-
-// count the number of BRs in element
-function checkBR(element) {
- return element.querySelectorAll("br").length;
-}
-
-function runTests() {
- var count = getBlockCount();
- var nodes = document.querySelectorAll("#content [contenteditable]");
- for (var i = 0; i < nodes.length; i++) {
- var node = nodes[i];
- node.focus();
- is(checkBR(node), 0, node.textContent.trim() + ": This node should not have any <br> element yet.");
- for (var j = 0; j < 3; j++) { // CARET_BEGIN|MIDDLE|END
- split(node, j);
- ok(checkBR(node) > 0, node.textContent.trim() + " " + j + ": Pressing [Return] should add (at least) one <br> element.");
- is(getBlockCount(), count, node.textContent.trim() + " " + j + ": Pressing [Return] should not change the number of non-<br> elements.");
- document.execCommand("Undo", false, null);
- }
- }
- SimpleTest.finish();
-}
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug46555.html b/editor/libeditor/tests/test_bug46555.html
deleted file mode 100644
index 3838bdb3b..000000000
--- a/editor/libeditor/tests/test_bug46555.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<!DOCTYPE HTML>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=46555
--->
-
-<head>
- <title>Test for Bug 46555</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-
-<body>
- <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=46555">Mozilla Bug 46555</a>
- <p id="display"></p>
- <div id="content" style="display: none">
- </div>
-
- <input type="text" value="" id="t1" />
-
- <pre id="test">
- <script type="application/javascript">
-
- /** Test for Bug 46555 **/
- SimpleTest.waitForExplicitFinish();
- SimpleTest.waitForFocus(function() {
- const kCmd = "cmd_selectAll";
-
- var input = document.getElementById("t1");
- input.focus();
- var controller =
- SpecialPowers.wrap(input).controllers.getControllerForCommand(kCmd);
-
- // Test 1: Select All should be disabled if editor is empty
- is(controller.isCommandEnabled(kCmd), false,
- "Select All command disabled when editor is empty");
-
- SimpleTest.finish();
- });
- </script>
- </pre>
-
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug468353.html b/editor/libeditor/tests/test_bug468353.html
deleted file mode 100644
index 179c41cdc..000000000
--- a/editor/libeditor/tests/test_bug468353.html
+++ /dev/null
@@ -1,117 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=468353
--->
-<head>
- <title>Test for Bug 468353</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=468353">Mozilla Bug 468353</a>
-<p id="display"></p>
-<div id="content">
- <iframe></iframe>
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-var styleSheets = null;
-
-function checkStylesheets() {
- // Evidently RemoveStyleSheet is the only method in nsIEditorStyleSheets
- // that would throw. RemoveOverrideStyleSheet returns NS_OK even if the
- // sheet is not there
- var removed = 0;
- try
- {
- styleSheets.removeStyleSheet("resource://gre/res/designmode.css");
- removed++;
- }
- catch (ex) { }
-
- try {
- styleSheets.removeStyleSheet("resource://gre/res/contenteditable.css");
- removed++;
- }
- catch (ex) { }
-
- is(removed, 0, "Should have thrown if stylesheet was not there");
-}
-
-function runTest() {
- const Ci = SpecialPowers.Ci;
-
- /** Found while fixing bug 440614 **/
- var editframe = window.frames[0];
- var editdoc = editframe.document;
- var editor = null;
- editdoc.write('');
- editdoc.close();
-
- editdoc.designMode='on';
-
- // Hold the reference to the editor
- editor = SpecialPowers.wrap(editframe)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIEditingSession)
- .getEditorForWindow(editframe);
-
- styleSheets = editor.QueryInterface(Ci.nsIEditorStyleSheets);
-
- editdoc.designMode='off';
-
- checkStylesheets();
-
- // Let go
- editor = null;
- styleSheets = null;
-
- editdoc.body.contentEditable = true;
-
- // Hold the reference to the editor
- editor = SpecialPowers.wrap(editframe)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIEditingSession)
- .getEditorForWindow(editframe);
-
- styleSheets = editor.QueryInterface(Ci.nsIEditorStyleSheets);
-
- editdoc.body.contentEditable = false;
-
- checkStylesheets();
-
- editdoc.designMode = "on";
- editdoc.body.contentEditable = true;
- editdoc.designMode = "off";
-
- // Hold the reference to the editor
- editor = SpecialPowers.wrap(editframe)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIEditingSession)
- .getEditorForWindow(editframe);
-
- styleSheets = editor.QueryInterface(Ci.nsIEditorStyleSheets);
-
- editdoc.body.contentEditable = false;
-
- checkStylesheets();
-
- SimpleTest.finish();
-}
-
-//XXX I don't know if this is necessary, but we're dealing with iframes...
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(runTest);
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug471319.html b/editor/libeditor/tests/test_bug471319.html
deleted file mode 100644
index 399ba4611..000000000
--- a/editor/libeditor/tests/test_bug471319.html
+++ /dev/null
@@ -1,80 +0,0 @@
-<!DOCTYPE HTML>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=471319
--->
-
-<head>
- <title>Test for Bug 471319</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-
-<body onload="doTest();">
- <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=471319">Mozilla Bug 471319</a>
- <p id="display"></p>
- <div id="content" style="display: none">
- </div>
-
- <pre id="test">
- <script type="application/javascript;version=1.7">
-
- /** Test for Bug 471319 **/
-
- SimpleTest.waitForExplicitFinish();
-
- function doTest() {
- let t1 = SpecialPowers.wrap($("t1"));
- let editor = null;
-
- // Test 1: Undo on an empty editor - the editor should not forget about
- // the bogus node
- t1.QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement);
- t1Editor = t1.editor;
-
- // Did the editor recognize the new bogus node?
- t1Editor.undo(1);
- ok(!t1.value, "<br> still recognized as bogus node on undo");
-
-
- // Test 2: Redo on an empty editor - the editor should not forget about
- // the bogus node
- let t2 = SpecialPowers.wrap($("t2"));
- t2.QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement);
- t2Editor = t2.editor;
-
- // Did the editor recognize the new bogus node?
- t2Editor.redo(1);
- ok(!t2.value, "<br> still recognized as bogus node on redo");
-
-
- // Test 3: Undoing a batched transaction where both end points of the
- // transaction are the bogus node - the bogus node should still be
- // recognized as bogus
- t1Editor.transactionManager.beginBatch(null);
- t1.value = "mozilla";
- t1.value = "";
- t1Editor.transactionManager.endBatch(false);
- t1Editor.undo(1);
- ok(!t1.value,
- "recreated <br> from undo transaction recognized as bogus");
-
-
- // Test 4: Redoing a batched transaction where both end points of the
- // transaction are the bogus node - the bogus node should still be
- // recognized as bogus
- t1Editor.redo(1);
- ok(!t1.value,
- "recreated <br> from redo transaction recognized as bogus");
- SimpleTest.finish();
- }
- </script>
- </pre>
-
- <input type="text" id="t1" />
- <input type="text" id="t2" />
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug471722.html b/editor/libeditor/tests/test_bug471722.html
deleted file mode 100644
index 74ff55307..000000000
--- a/editor/libeditor/tests/test_bug471722.html
+++ /dev/null
@@ -1,81 +0,0 @@
-<!DOCTYPE HTML>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=471722
--->
-
-<head>
- <title>Test for Bug 471722</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-
-<body onload="doTest();">
- <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=471722">Mozilla Bug 471722</a>
- <p id="display"></p>
- <div id="content" style="display: none">
- </div>
-
- <pre id="test">
- <script type="application/javascript">
-
- /** Test for Bug 471722 **/
-
- SimpleTest.waitForExplicitFinish();
-
- function doTest() {
- var t1 = $("t1");
- var editor = null;
-
- if (t1 instanceof SpecialPowers.Ci.nsIDOMNSEditableElement)
- editor = SpecialPowers.wrap(t1).editor;
- ok(editor, "able to get editor for the element");
- t1.focus();
- t1.select();
-
- try {
-
- // Cut the initial text in the textbox
- ok(editor.canCut(), "can cut text");
- editor.cut();
- is(t1.value, "", "initial text was removed");
-
- // So now we will have emptied the textfield
- // and the editor will have created a bogus node
- // Check the transaction is in the undo stack...
- var t1Enabled = {};
- var t1CanUndo = {};
- editor.canUndo(t1Enabled, t1CanUndo);
- ok(t1CanUndo.value, "undo is enabled");
-
- // Undo the cut
- editor.undo(1);
- is(t1.value, "minefield", "text reinserted");
-
- // So now, the cut should be in the redo stack,
- // so executing the redo will clear the text once again
- // and reinsert the bogus node that was removed after undo.
- // This will require the editor to figure out that we have a
- // bogus node again...
- var t1CanRedo = {};
- editor.canRedo(t1Enabled, t1CanRedo);
- ok(t1CanRedo.value, "redo is enabled");
- editor.redo(1);
-
- // Did the editor notice a bogus node reappeared?
- is(t1.value, "", "editor found bogus node");
- } catch (e) {
- ok(false, "test failed with error "+e);
- }
- SimpleTest.finish();
- }
- </script>
- </pre>
-
- <input type="text" value="minefield" id="t1" />
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug478725.html b/editor/libeditor/tests/test_bug478725.html
deleted file mode 100644
index 8df85dfff..000000000
--- a/editor/libeditor/tests/test_bug478725.html
+++ /dev/null
@@ -1,131 +0,0 @@
-<!DOCTYPE HTML>
-<html><head>
-<title>Test for bug 478725</title>
-<style src="/tests/SimpleTest/test.css" type="text/css"></style>
-<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-
-<script class="testbody" type="application/javascript">
-
-function runTest() {
- function verifyContent(s) {
- var e = document.getElementById('i1');
- var doc = e.contentDocument;
- is(doc.body.innerHTML, s, "");
- }
-
- function pasteInto(html,target_id) {
- var e = document.getElementById('i1');
- var doc = e.contentDocument;
- doc.designMode = "on";
- doc.body.innerHTML = html;
- e = doc.getElementById(target_id);
- doc.defaultView.focus();
- var selection = doc.defaultView.getSelection();
- selection.removeAllRanges();
- selection.selectAllChildren(e);
- selection.collapseToEnd();
- SpecialPowers.wrap(doc).execCommand("paste", false, null);
- return e;
- }
-
- function copyToClipBoard(s,asHTML,target_id) {
- var e = document.getElementById('i2');
- var doc = e.contentDocument;
- if (asHTML) {
- doc.body.innerHTML = s;
- } else {
- var text = doc.createTextNode(s);
- doc.body.appendChild(text);
- }
- doc.designMode = "on";
- doc.defaultView.focus();
- var selection = doc.defaultView.getSelection();
- selection.removeAllRanges();
- if (!target_id) {
- selection.selectAllChildren(doc.body);
- } else {
- var range = document.createRange();
- range.selectNode(doc.getElementById(target_id));
- selection.addRange(range);
- }
- SpecialPowers.wrap(doc).execCommand("copy", false, null);
- return e;
- }
-
- copyToClipBoard("<dl><dd>Hello Kitty</dd></dl>", true);
- pasteInto('<ol><li id="paste_here">X</li></ol>',"paste_here");
- verifyContent('<ol><li id="paste_here">X<dl><dd>Hello Kitty</dd></dl></li></ol>');
-
- copyToClipBoard("<li>Hello Kitty</li>", true);
- pasteInto('<ol><li id="paste_here">X</li></ol>',"paste_here");
- verifyContent('<ol><li id="paste_here">X</li><li>Hello Kitty</li></ol>');
-
- copyToClipBoard("<ol><li>Hello Kitty</li></ol>", true);
- pasteInto('<ol><li id="paste_here">X</li></ol>',"paste_here");
- verifyContent('<ol><li id="paste_here">X</li><li>Hello Kitty</li></ol>');
-
- copyToClipBoard("<ul><li>Hello Kitty</li></ul>", true);
- pasteInto('<ol><li id="paste_here">X</li></ol>',"paste_here");
- verifyContent('<ol><li id="paste_here">X</li><li>Hello Kitty</li></ol>');
-
- copyToClipBoard("<ul><li>Hello</li><ul><li>Kitty</li></ul></ul>", true);
- pasteInto('<ol><li id="paste_here">X</li></ol>',"paste_here");
- verifyContent('<ol><li id="paste_here">X</li><li>Hello</li><ul><li>Kitty</li></ul></ol>');
-
- copyToClipBoard("<dl><dd>Hello</dd><dd>Kitty</dd></dl>", true);
- pasteInto('<dl><dd id="paste_here">X</dd></dl>',"paste_here");
- verifyContent('<dl><dd id="paste_here">X</dd><dd>Hello</dd><dd>Kitty</dd></dl>');
-
- copyToClipBoard("<dl><dd>Hello</dd><dd>Kitty</dd></dl>", true);
- pasteInto('<dl><dt id="paste_here">X</dt></dl>',"paste_here");
- verifyContent('<dl><dt id="paste_here">X</dt><dd>Hello</dd><dd>Kitty</dd></dl>');
-
- copyToClipBoard("<dl><dt>Hello</dt><dd>Kitty</dd></dl>", true);
- pasteInto('<dl><dd id="paste_here">X</dd></dl>',"paste_here");
- verifyContent('<dl><dd id="paste_here">X</dd><dt>Hello</dt><dd>Kitty</dd></dl>');
-
- copyToClipBoard("<pre>Kitty</pre>", true);
- pasteInto('<pre id="paste_here">Hello </pre>',"paste_here");
- verifyContent('<pre id="paste_here">Hello Kitty</pre>');
-
-// I was expecting these to trigger the special TABLE/TR rules in nsHTMLEditor::InsertHTMLWithContext
-// but they don't for some reason...
-// copyToClipBoard('<table><tr id="copy_here"><td>Kitty</td></tr></table>', true, "copy_here");
-// pasteInto('<table><tr id="paste_here"><td>Hello</td></tr></table>',"paste_here");
-// verifyContent('');
-//
-// copyToClipBoard('<table id="copy_here"><tr><td>Kitty</td></tr></table>', true, "copy_here");
-// pasteInto('<table><tr id="paste_here"><td>Hello</td></tr></table>',"paste_here");
-// verifyContent('');
-//
-// copyToClipBoard('<table id="copy_here"><tr><td>Kitty</td></tr></table>', true, "copy_here");
-// pasteInto('<table id="paste_here"><tr><td>Hello</td></tr></table>',"paste_here");
-// verifyContent('');
-//
-// copyToClipBoard('<table><tr id="copy_here"><td>Kitty</td></tr></table>', true, "copy_here");
-// pasteInto('<table id="paste_here"><tr><td>Hello</td></tr></table>',"paste_here");
-// verifyContent('');
-
-
- SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(runTest);
-</script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=478725">Mozilla Bug 478725</a>
-<p id="display"></p>
-
-<pre id="test">
-</pre>
-
-
-<iframe id="i1" width="200" height="100" src="about:blank"></iframe><br>
-<iframe id="i2" width="200" height="100" src="about:blank"></iframe><br>
-
-</body>
-</html>
-
diff --git a/editor/libeditor/tests/test_bug480647.html b/editor/libeditor/tests/test_bug480647.html
deleted file mode 100644
index 33f088a1b..000000000
--- a/editor/libeditor/tests/test_bug480647.html
+++ /dev/null
@@ -1,110 +0,0 @@
-<!DOCTYPE html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=480647
--->
-<title>Test for Bug 480647</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=480647">Mozilla Bug 480647</a>
-<div contenteditable></div>
-<script>
-/** Test for Bug 480647 **/
-
-var div = document.querySelector("div");
-
-function parseFontSize(input, expected) {
- parseFontSizeInner(input, expected, is);
-}
-
-function parseFontSizeTodo(input, expected) {
- parseFontSizeInner(input, expected, todo_is);
-}
-
-function parseFontSizeInner(input, expected, fn) {
- div.innerHTML = "foo";
- getSelection().selectAllChildren(div);
- document.execCommand("fontSize", false, input);
- if (expected === null) {
- fn(div.innerHTML, "foo",
- 'execCommand("fontSize", false, "' + input + '") should be no-op');
- } else {
- fn(div.innerHTML, '<font size="' + expected + '">foo</font>',
- 'execCommand("fontSize", false, "' + input + '") should parse to ' +
- expected);
- }
-}
-
-// Parse errors
-parseFontSize("", null);
-parseFontSize("abc", null);
-parseFontSize("larger", null);
-parseFontSize("smaller", null);
-parseFontSize("xx-small", null);
-parseFontSize("x-small", null);
-parseFontSize("small", null);
-parseFontSize("medium", null);
-parseFontSize("large", null);
-parseFontSize("x-large", null);
-parseFontSize("xx-large", null);
-parseFontSize("xxx-large", null);
-// Bug 747879
-parseFontSizeTodo("1.2em", null);
-parseFontSizeTodo("8px", null);
-parseFontSizeTodo("-1.2em", null);
-parseFontSizeTodo("-8px", null);
-parseFontSizeTodo("+1.2em", null);
-parseFontSizeTodo("+8px", null);
-
-// Numbers
-parseFontSize("0", 1);
-parseFontSize("1", 1);
-parseFontSize("2", 2);
-parseFontSize("3", 3);
-parseFontSize("4", 4);
-parseFontSize("5", 5);
-parseFontSize("6", 6);
-parseFontSize("7", 7);
-parseFontSize("8", 7);
-parseFontSize("9", 7);
-parseFontSize("10", 7);
-parseFontSize("1000000000000000000000", 7);
-parseFontSize("2.72", 2);
-parseFontSize("2.72e9", 2);
-
-// Minus sign
-parseFontSize("-0", 3);
-parseFontSize("-1", 2);
-parseFontSize("-2", 1);
-parseFontSize("-3", 1);
-parseFontSize("-4", 1);
-parseFontSize("-5", 1);
-parseFontSize("-6", 1);
-parseFontSize("-7", 1);
-parseFontSize("-8", 1);
-parseFontSize("-9", 1);
-parseFontSize("-10", 1);
-parseFontSize("-1000000000000000000000", 1);
-parseFontSize("-1.72", 2);
-parseFontSize("-1.72e9", 2);
-
-// Plus sign
-parseFontSize("+0", 3);
-parseFontSize("+1", 4);
-parseFontSize("+2", 5);
-parseFontSize("+3", 6);
-parseFontSize("+4", 7);
-parseFontSize("+5", 7);
-parseFontSize("+6", 7);
-parseFontSize("+7", 7);
-parseFontSize("+8", 7);
-parseFontSize("+9", 7);
-parseFontSize("+10", 7);
-parseFontSize("+1000000000000000000000", 7);
-parseFontSize("+1.72", 4);
-parseFontSize("+1.72e9", 4);
-
-// Whitespace
-parseFontSize(" \t\n\r\f5 \t\n\r\f", 5);
-parseFontSize("\u00a05", null);
-parseFontSize("\b5", null);
-</script>
diff --git a/editor/libeditor/tests/test_bug480972.html b/editor/libeditor/tests/test_bug480972.html
deleted file mode 100644
index 3eed97100..000000000
--- a/editor/libeditor/tests/test_bug480972.html
+++ /dev/null
@@ -1,98 +0,0 @@
-<!DOCTYPE HTML>
-<html><head>
-<title>Test for bug 480972</title>
-<style src="/tests/SimpleTest/test.css" type="text/css"></style>
-<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-
-<script class="testbody" type="application/javascript">
-
-function runTest() {
- function verifyContent(s) {
- var e = document.getElementById('i1');
- var doc = e.contentDocument;
- is(doc.body.innerHTML, s, "");
- }
-
- function pasteInto(html,target_id) {
- var e = document.getElementById('i1');
- var doc = e.contentDocument;
- doc.designMode = "on";
- doc.body.innerHTML = html;
- doc.defaultView.focus();
- if (target_id)
- e = doc.getElementById(target_id);
- else
- e = doc.body;
- var selection = doc.defaultView.getSelection();
- selection.removeAllRanges();
- selection.selectAllChildren(e);
- selection.collapseToEnd();
- SpecialPowers.wrap(doc).execCommand("paste", false, null);
- return e;
- }
-
- function copyToClipBoard(s,asHTML,target_id) {
- var e = document.getElementById('i2');
- var doc = e.contentDocument;
- if (asHTML) {
- doc.body.innerHTML = s;
- } else {
- var text = doc.createTextNode(s);
- doc.body.appendChild(text);
- }
- doc.designMode = "on";
- doc.defaultView.focus();
- var selection = doc.defaultView.getSelection();
- selection.removeAllRanges();
- if (!target_id) {
- selection.selectAllChildren(doc.body);
- } else {
- var range = document.createRange();
- range.selectNode(doc.getElementById(target_id));
- selection.addRange(range);
- }
- SpecialPowers.wrap(doc).execCommand("copy", false, null);
- return e;
- }
-
- copyToClipBoard('<span>Hello</span><span>Kitty</span>', true);
- pasteInto('');
- verifyContent('<span>Hello</span><span>Kitty</span>');
-
- copyToClipBoard("<dl><dd>Hello Kitty</dd></dl><span>Hello</span><span>Kitty</span>", true);
- pasteInto('<ol><li id="paste_here">X</li></ol>',"paste_here");
- verifyContent('<ol><li id="paste_here">X<dl><dd>Hello Kitty</dd></dl><span>Hello</span><span>Kitty</span></li></ol>');
-
-// The following test doesn't do what I expected, because the special handling
-// of IsList nodes in nsHTMLEditor::InsertHTMLWithContext simply removes
-// non-list/item children. See bug 481177.
-// copyToClipBoard("<ol><li>Hello Kitty</li><span>Hello</span></ol>", true);
-// pasteInto('<ol><li id="paste_here">X</li></ol>',"paste_here");
-// verifyContent('<ol><li id="paste_here">X</li><li>Hello Kitty</li><span>Hello</span></ol>');
-
- copyToClipBoard("<pre>Kitty</pre><span>Hello</span>", true);
- pasteInto('<pre id="paste_here">Hello </pre>',"paste_here");
- verifyContent('<pre id="paste_here">Hello Kitty<span>Hello</span></pre>');
-
- SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(runTest);
-</script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=480972">Mozilla Bug 480972</a>
-<p id="display"></p>
-
-<pre id="test">
-</pre>
-
-
-<iframe id="i1" width="200" height="100" src="about:blank"></iframe><br>
-<iframe id="i2" width="200" height="100" src="about:blank"></iframe><br>
-
-</body>
-</html>
-
diff --git a/editor/libeditor/tests/test_bug483651.html b/editor/libeditor/tests/test_bug483651.html
deleted file mode 100644
index ee256b807..000000000
--- a/editor/libeditor/tests/test_bug483651.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<!DOCTYPE HTML>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=483651
--->
-
-<head>
- <title>Test for Bug 483651</title>
- <script src="/MochiKit/packed.js"></script>
- <script src="/tests/SimpleTest/EventUtils.js"></script>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-
-<body onload="doTest();">
- <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=483651">Mozilla Bug 483651</a>
- <p id="display"></p>
- <div id="content" style="display: none">
- </div>
-
- <pre id="test">
- <script type="application/javascript">
-
- /** Test for Bug 483651 **/
-
- SimpleTest.waitForExplicitFinish();
-
- function doTest() {
- var t1 = $("t1");
- var editor = SpecialPowers.wrap(t1).editor;
-
- ok(editor, "able to get editor for the element");
- t1.focus();
- synthesizeKey("A", {});
- synthesizeKey("VK_BACK_SPACE", {});
-
- try {
- // Was the trailing br removed?
- is(editor.documentIsEmpty, true, "trailing <br> correctly removed");
- } catch (e) {
- ok(false, "test failed with error "+e);
- }
- SimpleTest.finish();
- }
- </script>
- </pre>
-
- <textarea id="t1" rows="2" columns="80"></textarea>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug484181.html b/editor/libeditor/tests/test_bug484181.html
deleted file mode 100644
index 55cd8e806..000000000
--- a/editor/libeditor/tests/test_bug484181.html
+++ /dev/null
@@ -1,78 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=484181
--->
-<head>
- <title>Test for Bug 484181</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <script src="spellcheck.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=484181">Mozilla Bug 484181</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 484181 **/
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(runTest);
-
-var gMisspeltWords;
-
-function getEditor() {
- var Ci = SpecialPowers.Ci;
- var win = window;
- var editingSession = SpecialPowers.wrap(win).QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIEditingSession);
- return editingSession.getEditorForWindow(win);
-}
-
-function append(str) {
- var edit = document.getElementById("edit");
- var editor = getEditor();
- var sel = editor.selection;
- sel.selectAllChildren(edit);
- sel.collapseToEnd();
-
- for (var i = 0; i < str.length; ++i) {
- synthesizeKey(str[i], {});
- }
-}
-
-function runTest() {
- gMisspeltWords = ["haz", "cheezburger"];
- var edit = document.getElementById("edit");
- edit.focus();
-
- SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm", window);
- onSpellCheck(edit, function () {
- ok(isSpellingCheckOk(getEditor(), gMisspeltWords),
- "All misspellings before editing are accounted for.");
-
- append(" becaz I'm a lulcat!");
- onSpellCheck(edit, function () {
- gMisspeltWords.push("becaz");
- gMisspeltWords.push("lulcat");
- ok(isSpellingCheckOk(getEditor(), gMisspeltWords),
- "All misspellings after typing are accounted for.");
-
- SimpleTest.finish();
- });
- });
-}
-</script>
-</pre>
-
-<div><div></div><div id="edit" contenteditable="true">I can haz cheezburger</div></div>
-
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug487524.html b/editor/libeditor/tests/test_bug487524.html
deleted file mode 100644
index d4972ba91..000000000
--- a/editor/libeditor/tests/test_bug487524.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE HTML>
-<html><head>
-<title>Test for bug 487524</title>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-
-<script class="testbody" type="application/javascript">
-function runTest() {
-
- function setupIframe(e,html,focus_id) {
- var doc = e.contentDocument;
- doc.body.innerHTML = html;
- doc.designMode = "on";
- e = doc.getElementById(focus_id);
- doc.defaultView.focus();
- if (e) e.focus();
- return e;
- }
-
- var i1 = document.getElementById('i1')
- var li1 = setupIframe(i1,'<ul><li id="li1">one</li><li>two</li><ul><li>a</li></ul></ul>','li1')
- var doc = li1.ownerDocument;
-
- var selection = doc.defaultView.getSelection();
- selection.removeAllRanges();
-
- var range = doc.createRange();
- range.setStart(li1,0);
- range.setEnd(li1.nextSibling,0);
- selection.addRange(range);
-
- sendKey('delete');
- is(doc.body.innerHTML,'<ul><li>two</li><ul><li>a</li></ul></ul>','delete 1st LI');
-
- var li2 = setupIframe(i1,'<ul><li id="li2">two</li><ul><li>a</li></ul></ul>','li2')
- selection = doc.defaultView.getSelection();
- selection.removeAllRanges();
-
- range = doc.createRange();
- range.setStart(li2,0);
- range.setEnd(li2.nextSibling.firstChild,0);
- selection.addRange(range);
-
- sendKey('delete');
- is(doc.body.innerHTML,'<ul><ul><li>a</li></ul></ul>','delete 2nd LI');
-
- SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(runTest);
-</script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=487524">Mozilla Bug 487524</a>
-<p id="display"></p>
-
-<pre id="test">
-</pre>
-
-<iframe id="i1" width="200" height="100" src="about:blank"></iframe><br>
-
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug489202.xul b/editor/libeditor/tests/test_bug489202.xul
deleted file mode 100644
index 30e2a730d..000000000
--- a/editor/libeditor/tests/test_bug489202.xul
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin"
- type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
- type="text/css"?>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=489202
--->
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- title="Mozilla Bug 489202" onload="runTest();">
- <script type="application/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
- <script type="application/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
-
- <body xmlns="http://www.w3.org/1999/xhtml">
- <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=489202"
- target="_blank">Mozilla Bug 489202</a>
- <p/>
- <editor xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- id="i1"
- type="content"
- editortype="htmlmail"
- style="width: 400px; height: 100px;"/>
- <p/>
- <pre id="test">
- </pre>
- </body>
- <script class="testbody" type="application/javascript">
- <![CDATA[
- var utils = SpecialPowers.getDOMWindowUtils(window);
- var Cc = Components.classes;
- var Ci = Components.interfaces;
-
-function getLoadContext() {
- return window.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsILoadContext);
-}
-
-function runTest() {
- var trans = Cc["@mozilla.org/widget/transferable;1"]
- .createInstance(Ci.nsITransferable);
- trans.init(getLoadContext());
- trans.addDataFlavor("text/html");
- var test_data = '<meta/><a href="http://mozilla.org/">mozilla.org</a>';
- var cstr = Cc["@mozilla.org/supports-string;1"]
- .createInstance(Ci.nsISupportsString);
- cstr.data = test_data;
- trans.setTransferData("text/html", cstr, test_data.length*2);
-
- window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
- .getInterface(Components.interfaces.nsIWebNavigation)
- .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
- .rootTreeItem
- .QueryInterface(Components.interfaces.nsIDocShell)
- .appType = Components.interfaces.nsIDocShell.APP_TYPE_EDITOR;
- var e = document.getElementById('i1');
- var doc = e.contentDocument;
- doc.designMode = "on";
- doc.body.innerHTML = "";
- doc.defaultView.focus();
- var selection = doc.defaultView.getSelection();
- selection.removeAllRanges();
- selection.selectAllChildren(doc.body);
- selection.collapseToEnd();
-
- var point = doc.defaultView.getSelection().getRangeAt(0).startOffset;
- ok(point==0, "Cursor should be at editor start before paste");
-
- utils.sendContentCommandEvent("pasteTransferable", trans);
-
- point = doc.defaultView.getSelection().getRangeAt(0).startOffset;
- ok(point>0, "Cursor should not be at editor start after paste");
- SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-]]>
-</script>
-</window>
diff --git a/editor/libeditor/tests/test_bug490879.html b/editor/libeditor/tests/test_bug490879.html
deleted file mode 100644
index 1e412a7d6..000000000
--- a/editor/libeditor/tests/test_bug490879.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<!doctype html>
-<title>Mozilla Bug 490879</title>
-<link rel=stylesheet href="/tests/SimpleTest/test.css">
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=490879"
- target="_blank">Mozilla Bug 490879</a>
-<iframe id="i1" width="200" height="100" src="about:blank"></iframe>
-<img id="i" src="green.png">
-<script>
-function runTest() {
- function verifyContent() {
- const kExpectedImgSpec = "data:image/png;base64,";
- var e = document.getElementById('i1');
- var doc = e.contentDocument;
- is(doc.getElementsByTagName("img")[0].src.substring(0, kExpectedImgSpec.length),
- kExpectedImgSpec, "The pasted image is a base64-encoded data: URI");
- }
-
- function pasteInto() {
- var e = document.getElementById('i1');
- var doc = e.contentDocument;
- doc.designMode = "on";
- doc.defaultView.focus();
- var selection = doc.defaultView.getSelection();
- selection.removeAllRanges();
- selection.selectAllChildren(doc.body);
- selection.collapseToEnd();
- SpecialPowers.doCommand(window, "cmd_paste");
- }
-
- function copyToClipBoard() {
- SpecialPowers.setCommandNode(window, document.getElementById("i"));
- SpecialPowers.doCommand(window, "cmd_copyImageContents");
- }
-
- copyToClipBoard();
- pasteInto();
- verifyContent();
-
- SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(runTest);
-</script>
diff --git a/editor/libeditor/tests/test_bug502673.html b/editor/libeditor/tests/test_bug502673.html
deleted file mode 100644
index 3bee4554a..000000000
--- a/editor/libeditor/tests/test_bug502673.html
+++ /dev/null
@@ -1,108 +0,0 @@
-<!DOCTYPE HTML>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=502673
--->
-
-<head>
- <title>Test for Bug 502673</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-
-<body onload="doTest();">
- <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=502673">Mozilla Bug 502673</a>
- <p id="display"></p>
- <div id="content" style="display: none">
- </div>
-
- <pre id="test">
- <script type="application/javascript">
-
- /** Test for Bug 502673 **/
-
- SimpleTest.waitForExplicitFinish();
-
- function listener() {
- }
-
- listener.prototype =
- {
- NotifyDocumentWillBeDestroyed: function () {
- if (this.input instanceof SpecialPowers.Ci.nsIDOMNSEditableElement) {
- var editor = SpecialPowers.wrap(this.input).editor;
- editor.removeDocumentStateListener(this);
- }
- },
-
- NotifyDocumentCreated: function () {
- },
-
- NotifyDocumentStateChanged: function (aNowDirty) {
- if (this.input instanceof SpecialPowers.Ci.nsIDOMNSEditableElement) {
- var editor = SpecialPowers.wrap(this.input).editor;
- editor.removeDocumentStateListener(this);
- }
- },
-
- QueryInterface: SpecialPowers.wrapCallback(function(iid) {
- if (iid.equals(SpecialPowers.Ci.nsIDocumentStateListener) ||
- iid.equals(SpecialPowers.Ci.nsISupports))
- return this;
- throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE;
- }),
- };
-
- function doTest() {
- var input = document.getElementById("ip");
- if (input instanceof SpecialPowers.Ci.nsIDOMNSEditableElement) {
- // Add multiple listeners to the same editor
- var editor = SpecialPowers.wrap(input).editor;
- var listener1 = new listener();
- listener1.input = input;
- var listener2 = new listener();
- listener2.input = input;
- var listener3 = new listener();
- listener3.input = input;
- editor.addDocumentStateListener(listener1);
- editor.addDocumentStateListener(listener2);
- editor.addDocumentStateListener(listener3);
-
- // Test 1. Fire NotifyDocumentStateChanged notifications where the
- // listeners remove themselves
- input.value = "mozilla";
- editor.undo(1);
-
- // Report success if we get here - clearly we didn't crash
- ok(true, "Multiple listeners removed themselves after " +
- "NotifyDocumentStateChanged notifications - didn't crash");
-
- // Add the listeners again for the next test
- editor.addDocumentStateListener(listener1);
- editor.addDocumentStateListener(listener2);
- editor.addDocumentStateListener(listener3);
-
- }
-
- // Test 2. Fire NotifyDocumentWillBeDestroyed notifications where the
- // listeners remove themselves (though in the real world, listeners
- // shouldn't do this as nsEditor::PreDestroy removes them as
- // listeners anyway)
- document.body.removeChild(input);
- ok(true, "Multiple listeners removed themselves after " +
- "NotifyDocumentWillBeDestroyed notifications - didn't crash");
-
- // TODO: Test for NotifyDocumentCreated
-
- SimpleTest.finish();
- }
- </script>
- </pre>
-
- <input type="text" id="ip" />
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug514156.html b/editor/libeditor/tests/test_bug514156.html
deleted file mode 100644
index 3594d1c8d..000000000
--- a/editor/libeditor/tests/test_bug514156.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=514156
--->
-<head>
- <title>Test for Bug 514156</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body onload="test()">
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=514156">Mozilla Bug 514156</a>
-<p id="display"></p>
-<div id="content">
-<input type="text" id="input1">
-<input type="text" id="input2">
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-/** Test for Bug 514156 **/
-
-SimpleTest.waitForExplicitFinish();
-
-function test() {
- var input1 = $("input1");
- input1.focus();
- synthesizeKey("\u200e", { });
- synthesizeKey("\u05d0", { });
- synthesizeKey("\u05d1", { });
- is(escape(input1.value), escape("\u200e\u05d0\u05d1"), "non-spacing character and direction change shouldn't change content");
-
- var input2 = $("input2");
- input2.focus();
- synthesizeKey("\u05b6", { });
- synthesizeKey("a", { });
- synthesizeKey("b", { });
- synthesizeKey("c", { });
- is(escape(input2.value), escape("\u05b6abc"), "non-spacing character and direction change shouldn't change content");
-
- SimpleTest.finish();
-}
-
-</script>
-</pre>
-</body>
-</html>
-
diff --git a/editor/libeditor/tests/test_bug520189.html b/editor/libeditor/tests/test_bug520189.html
deleted file mode 100644
index d1b429000..000000000
--- a/editor/libeditor/tests/test_bug520189.html
+++ /dev/null
@@ -1,621 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=520182
--->
-<head>
- <title>Test for Bug 520182</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=520182">Mozilla Bug 520182</a>
-<p id="display"></p>
-<div id="content">
- <iframe id="a" src="about:blank"></iframe>
- <iframe id="b" src="about:blank"></iframe>
- <iframe id="c" src="about:blank"></iframe>
- <div id="d" contenteditable="true"></div>
- <div id="e" contenteditable="true"></div>
- <div id="f" contenteditable="true"></div>
- <iframe id="g" src="about:blank"></iframe>
- <iframe id="h" src="about:blank"></iframe>
- <div id="i" contenteditable="true"></div>
- <div id="j" contenteditable="true"></div>
- <iframe id="k" src="about:blank"></iframe>
- <div id="l" contenteditable="true"></div>
- <iframe id="m" src="about:blank"></iframe>
- <div id="n" contenteditable="true"></div>
- <iframe id="o" src="about:blank"></iframe>
- <div id="p" contenteditable="true"></div>
- <iframe id="q" src="about:blank"></iframe>
- <div id="r" contenteditable="true"></div>
- <iframe id="s" src="about:blank"></iframe>
- <div id="t" contenteditable="true"></div>
- <iframe id="u" src="about:blank"></iframe>
- <div id="v" contenteditable="true"></div>
- <iframe id="w" src="about:blank"></iframe>
- <div id="x" contenteditable="true"></div>
- <iframe id="y" src="about:blank"></iframe>
- <div id="z" contenteditable="true"></div>
- <iframe id="aa" src="about:blank"></iframe>
- <div id="bb" contenteditable="true"></div>
- <iframe id="cc" src="about:blank"></iframe>
- <div id="dd" contenteditable="true"></div>
- <iframe id="ee" src="about:blank"></iframe>
- <div id="ff" contenteditable="true"></div>
- <iframe id="gg" src="about:blank"></iframe>
- <div id="hh" contenteditable="true"></div>
- <iframe id="ii" src="about:blank"></iframe>
- <div id="jj" contenteditable="true"></div>
- <iframe id="kk" src="about:blank"></iframe>
- <div id="ll" contenteditable="true"></div>
- <iframe id="mm" src="about:blank"></iframe>
- <div id="nn" contenteditable="true"></div>
- <iframe id="oo" src="about:blank"></iframe>
- <div id="pp" contenteditable="true"></div>
- <iframe id="qq" src="about:blank"></iframe>
- <div id="rr" contenteditable="true"></div>
- <iframe id="ss" src="about:blank"></iframe>
- <div id="tt" contenteditable="true"></div>
- <iframe id="uu" src="about:blank"></iframe>
- <div id="vv" contenteditable="true"></div>
- <div id="sss" contenteditable="true"></div>
- <iframe id="ssss" src="about:blank"></iframe>
- <div id="ttt" contenteditable="true"></div>
- <iframe id="tttt" src="about:blank"></iframe>
- <div id="uuu" contenteditable="true"></div>
- <iframe id="uuuu" src="about:blank"></iframe>
- <div id="vvv" contenteditable="true"></div>
- <iframe id="vvvv" src="about:blank"></iframe>
- <div id="www" contenteditable="true"></div>
- <iframe id="wwww" src="about:blank"></iframe>
- <div id="xxx" contenteditable="true"></div>
- <iframe id="xxxx" src="about:blank"></iframe>
- <div id="yyy" contenteditable="true"></div>
- <iframe id="yyyy" src="about:blank"></iframe>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 520182 **/
-
-const dataPayload = "foo<iframe src=\"data:text/html,bar\"></iframe>baz";
-const jsPayload = "foo<iframe src=\"javascript:void('bar');\"></iframe>baz";
-const httpPayload = "foo<iframe src=\"http://mochi.test:8888/\"></iframe>baz";
-const scriptPayload ="foo<script>document.write(\"<iframe></iframe>\");</sc" + "ript>baz";
-const scriptExternalPayload = "foo<script src=\"data:text/javascript,document.write('<iframe></iframe>');\"></sc" + "ript>baz";
-const validStyle1Payload = "foo<style>#bar{color:red;}</style>baz";
-const validStyle2Payload = "foo<span style=\"color:red\">bar</span>baz";
-const validStyle3Payload = "foo<style>@font-face{font-family:xxx;src:'xxx.ttf';}</style>baz";
-const validStyle4Payload = "foo<style>@namespace xxx url(http://example.com/);</style>baz";
-const invalidStyle1Payload = "foo<style>#bar{-moz-binding:url('data:text/xml,<?xml version=\"1.0\"><binding xmlns=\"http://www.mozilla.org/xbl\"/>');}</style>baz";
-const invalidStyle2Payload = "foo<span style=\"-moz-binding:url('data:text/xml,<?xml version=&quot;1.0&quot;><binding xmlns=&quot;http://www.mozilla.org/xbl&quot;/>');\">bar</span>baz";
-const invalidStyle3Payload = "foo<style>@import 'xxx.css';</style>baz";
-const invalidStyle4Payload = "foo<span style=\"@import 'xxx.css';\">bar</span>baz";
-const invalidStyle5Payload = "foo<span style=\"@font-face{font-family:xxx;src:'xxx.ttf';}\">bar</span>baz";
-const invalidStyle6Payload = "foo<span style=\"@namespace xxx url(http://example.com/);\">bar</span>baz";
-const invalidStyle7Payload = "<html><head><title>xxx</title></head><body>foo</body></html>";
-const invalidStyle8Payload = "foo<style>@-moz-document url(http://example.com/) {};</style>baz";
-const invalidStyle9Payload = "foo<style>@-moz-keyframes bar {};</style>baz";
-const nestedStylePayload = "foo<style>#bar1{-moz-binding:url('data:text/xml,<?xml version=&quot;1.0&quot;><binding xmlns=&quot;http://www.mozilla.org/xbl&quot; id=&quot;binding-1&quot;/>');<style></style>#bar2{-moz-binding:url('data:text/xml,<?xml version=&quot;1.0&quot;><binding xmlns=&quot;http://www.mozilla.org/xbl&quot; id=&quot;binding-2&quot;/>');</style>baz";
-const validImgSrc1Payload = "foo<img src=\"data:image/png,bar\">baz";
-const validImgSrc2Payload = "foo<img src=\"javascript:void('bar');\">baz";
-const validImgSrc3Payload = "foo<img src=\"file:///bar.png\">baz";
-const validDataFooPayload = "foo<span data-bar=\"value\">baz</span>";
-const validDataFoo2Payload = "foo<span _bar=\"value\">baz</span>";
-const svgPayload = "foo<svg><title>svgtitle</title></svg>bar";
-const svg2Payload = "foo<svg><bogussvg/></svg>bar";
-const mathPayload = "foo<math><bogusmath/></math>bar";
-const math2Payload = "foo<math><style>@import \"yyy.css\";</style</math>bar";
-const math3Payload = "foo<math><mi></mi></math>bar";
-const videoPayload = "foo<video></video>bar";
-const microdataPayload = "<head><meta name=foo content=bar><link rel=stylesheet href=url></head><body><meta itemprop=foo content=bar><link itemprop=bar href=url></body>";
-
-var tests = [
- {
- id: "a",
- isIFrame: true,
- payload: dataPayload,
- iframeCount: 0,
- rootElement() { return document.getElementById("a").contentDocument.documentElement; },
- },
- {
- id: "b",
- isIFrame: true,
- payload: jsPayload,
- iframeCount: 0,
- rootElement() { return document.getElementById("b").contentDocument.documentElement; },
- },
- {
- id: "c",
- isIFrame: true,
- payload: httpPayload,
- iframeCount: 0,
- rootElement() { return document.getElementById("c").contentDocument.documentElement; },
- },
- {
- id: "g",
- isIFrame: true,
- payload: scriptPayload,
- rootElement() { return document.getElementById("g").contentDocument.documentElement; },
- iframeCount: 0
- },
- {
- id: "h",
- isIFrame: true,
- payload: scriptExternalPayload,
- rootElement() { return document.getElementById("h").contentDocument.documentElement; },
- iframeCount: 0
- },
- {
- id: "d",
- payload: dataPayload,
- iframeCount: 0,
- rootElement() { return document.getElementById("d"); },
- },
- {
- id: "e",
- payload: jsPayload,
- iframeCount: 0,
- rootElement() { return document.getElementById("e"); },
- },
- {
- id: "f",
- payload: httpPayload,
- iframeCount: 0,
- rootElement() { return document.getElementById("f"); },
- },
- {
- id: "i",
- payload: scriptPayload,
- rootElement() { return document.getElementById("i"); },
- iframeCount: 0
- },
- {
- id: "j",
- payload: scriptExternalPayload,
- rootElement() { return document.getElementById("j"); },
- iframeCount: 0
- },
- {
- id: "k",
- isIFrame: true,
- payload: validStyle1Payload,
- rootElement() { return document.getElementById("k").contentDocument.documentElement; },
- checkResult(html) { isnot(html.indexOf("style"), -1, "Should have retained style"); },
- },
- {
- id: "l",
- payload: validStyle1Payload,
- rootElement() { return document.getElementById("l"); },
- checkResult(html) { isnot(html.indexOf("style"), -1, "Should have retained style"); },
- },
- {
- id: "m",
- isIFrame: true,
- payload: validStyle2Payload,
- rootElement() { return document.getElementById("m").contentDocument.documentElement; },
- checkResult(html) { isnot(html.indexOf("style"), -1, "Should have retained style"); },
- },
- {
- id: "n",
- payload: validStyle2Payload,
- rootElement() { return document.getElementById("n"); },
- checkResult(html) { isnot(html.indexOf("style"), -1, "Should have retained style"); },
- },
- {
- id: "o",
- isIFrame: true,
- payload: invalidStyle1Payload,
- rootElement() { return document.getElementById("o").contentDocument.documentElement; },
- checkResult(html) { is(html.indexOf("binding"), -1, "Should not have retained the binding style"); },
- },
- {
- id: "p",
- payload: invalidStyle1Payload,
- rootElement() { return document.getElementById("p"); },
- checkResult(html) { is(html.indexOf("binding"), -1, "Should not have retained the binding style"); },
- },
- {
- id: "q",
- isIFrame: true,
- payload: invalidStyle2Payload,
- rootElement() { return document.getElementById("q").contentDocument.documentElement; },
- checkResult(html) { is(html.indexOf("binding"), -1, "Should not have retained the binding style"); },
- },
- {
- id: "r",
- payload: invalidStyle2Payload,
- rootElement() { return document.getElementById("r"); },
- checkResult(html) { is(html.indexOf("binding"), -1, "Should not have retained the binding style"); },
- },
- {
- id: "s",
- isIFrame: true,
- payload: invalidStyle1Payload,
- rootElement() { return document.getElementById("s").contentDocument.documentElement; },
- checkResult(html) { is(html.indexOf("xxx"), -1, "Should not have retained the import style"); },
- },
- {
- id: "t",
- payload: invalidStyle1Payload,
- rootElement() { return document.getElementById("t"); },
- checkResult(html) { is(html.indexOf("xxx"), -1, "Should not have retained the import style"); },
- },
- {
- id: "u",
- isIFrame: true,
- payload: invalidStyle2Payload,
- rootElement() { return document.getElementById("u").contentDocument.documentElement; },
- checkResult(html) { is(html.indexOf("xxx"), -1, "Should not have retained the import style"); },
- },
- {
- id: "v",
- payload: invalidStyle2Payload,
- rootElement() { return document.getElementById("v"); },
- checkResult(html) { is(html.indexOf("xxx"), -1, "Should not have retained the import style"); },
- },
- {
- id: "w",
- isIFrame: true,
- payload: validStyle3Payload,
- rootElement() { return document.getElementById("w").contentDocument.documentElement; },
- checkResult(html) { isnot(html.indexOf("xxx"), -1, "Should have retained the font-face style"); },
- },
- {
- id: "x",
- payload: validStyle3Payload,
- rootElement() { return document.getElementById("x"); },
- checkResult(html) { isnot(html.indexOf("xxx"), -1, "Should have retained the font-face style"); },
- },
- {
- id: "y",
- isIFrame: true,
- payload: invalidStyle5Payload,
- rootElement() { return document.getElementById("y").contentDocument.documentElement; },
- checkResult(html) { isnot(html.indexOf("xxx"), -1, "Should not have retained the font-face style"); },
- },
- {
- id: "z",
- payload: invalidStyle5Payload,
- rootElement() { return document.getElementById("z"); },
- checkResult(html) { isnot(html.indexOf("xxx"), -1, "Should not have retained the font-face style"); },
- },
- {
- id: "aa",
- isIFrame: true,
- payload: nestedStylePayload,
- rootElement() { return document.getElementById("aa").contentDocument.documentElement; },
- checkResult: function(html, text) {
- is(html.indexOf("binding-1"), -1, "Should not have retained the binding-1 style");
- isnot(text.indexOf("#bar2"), -1, "Should have retained binding-2 as text content");
- is(text.indexOf("binding-2"), -1, "Should not have retained binding-2 as a tag");
- }
- },
- {
- id: "bb",
- payload: nestedStylePayload,
- rootElement() { return document.getElementById("bb"); },
- checkResult: function(html, text) {
- is(html.indexOf("binding-1"), -1, "Should not have retained the binding-1 style");
- isnot(text.indexOf("#bar2"), -1, "Should have retained binding-2 as text content");
- is(text.indexOf("binding-2"), -1, "Should not have retained binding-2 as a tag");
- }
- },
- {
- id: "cc",
- isIFrame: true,
- payload: validStyle4Payload,
- rootElement() { return document.getElementById("cc").contentDocument.documentElement; },
- checkResult(html) { isnot(html.indexOf("xxx"), -1, "Should have retained the namespace style"); },
- },
- {
- id: "dd",
- payload: validStyle4Payload,
- rootElement() { return document.getElementById("dd"); },
- checkResult(html) { isnot(html.indexOf("xxx"), -1, "Should have retained the namespace style"); },
- },
- {
- id: "ee",
- isIFrame: true,
- payload: invalidStyle6Payload,
- rootElement() { return document.getElementById("ee").contentDocument.documentElement; },
- checkResult(html) { isnot(html.indexOf("xxx"), -1, "Should not have retained the namespace style"); },
- },
- {
- id: "ff",
- payload: invalidStyle6Payload,
- rootElement() { return document.getElementById("ff"); },
- checkResult(html) { isnot(html.indexOf("xxx"), -1, "Should not have retained the namespace style"); },
- },
- {
- id: "gg",
- isIFrame: true,
- payload: invalidStyle6Payload,
- rootElement() { return document.getElementById("gg").contentDocument.documentElement; },
- checkResult(html) { isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image"); },
- },
- {
- id: "hh",
- payload: invalidStyle6Payload,
- rootElement() { return document.getElementById("hh"); },
- checkResult(html) { isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image"); },
- },
- {
- id: "ii",
- isIFrame: true,
- payload: invalidStyle6Payload,
- rootElement() { return document.getElementById("ii").contentDocument.documentElement; },
- checkResult(html) { isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image"); },
- },
- {
- id: "jj",
- payload: invalidStyle6Payload,
- rootElement() { return document.getElementById("jj"); },
- checkResult(html) { isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image"); },
- },
- {
- id: "kk",
- isIFrame: true,
- payload: invalidStyle6Payload,
- rootElement() { return document.getElementById("kk").contentDocument.documentElement; },
- checkResult(html) { isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image"); },
- },
- {
- id: "ll",
- payload: invalidStyle6Payload,
- rootElement() { return document.getElementById("ll"); },
- checkResult(html) { isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image"); },
- },
- {
- id: "mm",
- isIFrame: true,
- indirectPaste: true,
- payload: invalidStyle7Payload,
- rootElement() { return document.getElementById("mm").contentDocument.documentElement; },
- checkResult: function(html) {
- is(html.indexOf("xxx"), -1, "Should not have retained the title text");
- isnot(html.indexOf("foo"), -1, "Should have retained the body text");
- }
- },
- {
- id: "nn",
- indirectPaste: true,
- payload: invalidStyle7Payload,
- rootElement() { return document.getElementById("nn"); },
- checkResult: function(html) {
- is(html.indexOf("xxx"), -1, "Should not have retained the title text");
- isnot(html.indexOf("foo"), -1, "Should have retained the body text");
- }
- },
- {
- id: "oo",
- isIFrame: true,
- payload: validDataFooPayload,
- rootElement() { return document.getElementById("oo").contentDocument.documentElement; },
- checkResult(html) { isnot(html.indexOf("bar"), -1, "Should have retained the data-bar attribute"); },
- },
- {
- id: "pp",
- payload: validDataFooPayload,
- rootElement() { return document.getElementById("pp"); },
- checkResult(html) { isnot(html.indexOf("bar"), -1, "Should have retained the data-bar attribute"); },
- },
- {
- id: "qq",
- isIFrame: true,
- payload: validDataFoo2Payload,
- rootElement() { return document.getElementById("qq").contentDocument.documentElement; },
- checkResult(html) { isnot(html.indexOf("bar"), -1, "Should have retained the _bar attribute"); },
- },
- {
- id: "rr",
- payload: validDataFoo2Payload,
- rootElement() { return document.getElementById("rr"); },
- checkResult(html) { isnot(html.indexOf("bar"), -1, "Should have retained the _bar attribute"); },
- },
- {
- id: "ss",
- isIFrame: true,
- payload: invalidStyle8Payload,
- rootElement() { return document.getElementById("ss").contentDocument.documentElement; },
- checkResult(html) { is(html.indexOf("@-moz-document"), -1, "Should not have retained the @-moz-document rule"); },
- },
- {
- id: "tt",
- payload: invalidStyle8Payload,
- rootElement() { return document.getElementById("tt"); },
- checkResult(html) { is(html.indexOf("@-moz-document"), -1, "Should not have retained the @-moz-document rule"); },
- },
- {
- id: "uu",
- isIFrame: true,
- payload: invalidStyle9Payload,
- rootElement() { return document.getElementById("uu").contentDocument.documentElement; },
- checkResult(html) { is(html.indexOf("@-moz-keyframes"), -1, "Should not have retained the @-moz-keyframes rule"); },
- },
- {
- id: "vv",
- payload: invalidStyle9Payload,
- rootElement() { return document.getElementById("vv"); },
- checkResult(html) { is(html.indexOf("@-moz-keyframes"), -1, "Should not have retained the @-moz-keyframes rule"); },
- },
- {
- id: "sss",
- payload: svgPayload,
- rootElement() { return document.getElementById("sss"); },
- checkResult(html) { isnot(html.indexOf("svgtitle"), -1, "Should have retained SVG title"); },
- },
- {
- id: "ssss",
- isIFrame: true,
- payload: svgPayload,
- rootElement() { return document.getElementById("ssss").contentDocument.documentElement; },
- checkResult(html) { isnot(html.indexOf("svgtitle"), -1, "Should have retained SVG title"); },
- },
- {
- id: "ttt",
- payload: svg2Payload,
- rootElement() { return document.getElementById("ttt"); },
- checkResult(html) { is(html.indexOf("bogussvg"), -1, "Should have dropped bogussvg element"); },
- },
- {
- id: "tttt",
- isIFrame: true,
- payload: svg2Payload,
- rootElement() { return document.getElementById("tttt").contentDocument.documentElement; },
- checkResult(html) { is(html.indexOf("bogussvg"), -1, "Should have dropped bogussvg element"); },
- },
- {
- id: "uuu",
- payload: mathPayload,
- rootElement() { return document.getElementById("uuu"); },
- checkResult(html) { is(html.indexOf("bogusmath"), -1, "Should have dropped bogusmath element"); },
- },
- {
- id: "uuuu",
- isIFrame: true,
- payload: mathPayload,
- rootElement() { return document.getElementById("uuuu").contentDocument.documentElement; },
- checkResult(html) { is(html.indexOf("bogusmath"), -1, "Should have dropped bogusmath element"); },
- },
- {
- id: "vvv",
- payload: math2Payload,
- rootElement() { return document.getElementById("vvv"); },
- checkResult(html) { is(html.indexOf("yyy.css"), -1, "Should have dropped MathML style element"); },
- },
- {
- id: "vvvv",
- isIFrame: true,
- payload: math2Payload,
- rootElement() { return document.getElementById("vvvv").contentDocument.documentElement; },
- checkResult(html) { is(html.indexOf("yyy.css"), -1, "Should have dropped MathML style element"); },
- },
- {
- id: "www",
- payload: math3Payload,
- rootElement() { return document.getElementById("www"); },
- checkResult(html) { isnot(html.indexOf("<mi"), -1, "Should not have dropped MathML mi element"); },
- },
- {
- id: "wwww",
- isIFrame: true,
- payload: math3Payload,
- rootElement() { return document.getElementById("wwww").contentDocument.documentElement; },
- checkResult(html) { isnot(html.indexOf("<mi"), -1, "Should not have dropped MathML mi element"); },
- },
- {
- id: "xxx",
- payload: videoPayload,
- rootElement() { return document.getElementById("xxx"); },
- checkResult(html) { isnot(html.indexOf("controls="), -1, "Should have added the controls attribute"); },
- },
- {
- id: "xxxx",
- isIFrame: true,
- payload: videoPayload,
- rootElement() { return document.getElementById("xxxx").contentDocument.documentElement; },
- checkResult(html) { isnot(html.indexOf("controls="), -1, "Should have added the controls attribute"); },
- },
- {
- id: "yyy",
- payload: microdataPayload,
- rootElement() { return document.getElementById("yyy"); },
- checkResult: function(html) { is(html.indexOf("name"), -1, "Should have dropped name."); is(html.indexOf("rel"), -1, "Should have dropped rel."); isnot(html.indexOf("itemprop"), -1, "Should not have dropped itemprop."); }
- },
- {
- id: "yyyy",
- isIFrame: true,
- payload: microdataPayload,
- rootElement() { return document.getElementById("yyyy").contentDocument.documentElement; },
- checkResult: function(html) { is(html.indexOf("name"), -1, "Should have dropped name."); is(html.indexOf("rel"), -1, "Should have dropped rel."); isnot(html.indexOf("itemprop"), -1, "Should not have dropped itemprop."); }
- }
-];
-
-function doNextTest() {
- if (typeof testCounter == "undefined")
- testCounter = 0;
- else if (++testCounter == tests.length) {
- SimpleTest.finish();
- return;
- }
-
- runTest(tests[testCounter]);
-
- doNextTest();
-}
-
-function getLoadContext() {
- const Ci = SpecialPowers.Ci;
- return SpecialPowers.wrap(window)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsILoadContext);
-}
-
-function runTest(test) {
- var elem = document.getElementById(test.id);
- if ("isIFrame" in test) {
- elem.contentDocument.designMode = "on";
- elem.contentWindow.focus();
- } else
- elem.focus();
-
- var trans = SpecialPowers.Cc["@mozilla.org/widget/transferable;1"]
- .createInstance(SpecialPowers.Ci.nsITransferable);
- trans.init(getLoadContext());
- var data = SpecialPowers.Cc["@mozilla.org/supports-string;1"]
- .createInstance(SpecialPowers.Ci.nsISupportsString);
- data.data = test.payload;
- trans.addDataFlavor("text/html");
- trans.setTransferData("text/html", data, data.data.length * 2);
-
- if ("indirectPaste" in test) {
- var editor, win;
- if ("isIFrame" in test) {
- win = elem.contentDocument.defaultView;
- } else {
- getSelection().collapse(elem, 0);
- win = window;
- }
- editor = SpecialPowers.wrap(win).QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
- .getInterface(SpecialPowers.Ci.nsIWebNavigation)
- .QueryInterface(SpecialPowers.Ci.nsIDocShell)
- .editor;
- editor.pasteTransferable(trans);
- } else {
- var clipboard = SpecialPowers.Cc["@mozilla.org/widget/clipboard;1"]
- .getService(SpecialPowers.Ci.nsIClipboard);
-
- clipboard.setData(trans, null, SpecialPowers.Ci.nsIClipboard.kGlobalClipboard);
-
- synthesizeKey("V", {accelKey: true});
- }
-
- if ("checkResult" in test) {
- if ("isIFrame" in test) {
- test.checkResult(elem.contentDocument.documentElement.innerHTML,
- elem.contentDocument.documentElement.textContent);
- } else {
- test.checkResult(elem.innerHTML, elem.textContent);
- }
- } else {
- var iframes = test.rootElement().querySelectorAll("iframe");
- var expectedIFrameCount = ("iframeCount" in test) ? test.iframeCount : 1;
- is(iframes.length, expectedIFrameCount, "Only " + expectedIFrameCount + " iframe should be pasted");
- if (expectedIFrameCount > 0) {
- ok(!iframes[0].hasAttribute("src"), "iframe should not have a src attrib");
- }
- }
-}
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(doNextTest);
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug525389.html b/editor/libeditor/tests/test_bug525389.html
deleted file mode 100644
index 43916eb51..000000000
--- a/editor/libeditor/tests/test_bug525389.html
+++ /dev/null
@@ -1,198 +0,0 @@
-<!DOCTYPE HTML>
-<html><head>
-<title>Test for bug 525389</title>
-<style src="/tests/SimpleTest/test.css" type="text/css"></style>
-<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-
-<script class="testbody" type="application/javascript">
-
- var utils = SpecialPowers.wrap(window)
- .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).getInterface(SpecialPowers.Ci.nsIDOMWindowUtils);
- var Cc = SpecialPowers.Cc;
- var Ci = SpecialPowers.Ci;
-
-function getLoadContext() {
- return SpecialPowers.wrap(window)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsILoadContext);
-}
-
-function runTest() {
- var pasteCount = 0;
- var pasteFunc = function (event) { pasteCount++; };
-
- function verifyContent(s) {
- var e = document.getElementById('i1');
- var doc = e.contentDocument;
- if (navigator.platform.indexOf("Win") >= 0) {
- // On Windows ignore \n which got left over from the removal of the fragment tags
- // <html><body>\n<!--StartFragment--> and <!--EndFragment-->\n</body>\n</html>.
- is(doc.body.innerHTML.replace(/\n/g, ""), s, "");
- } else {
- is(doc.body.innerHTML, s, "");
- }
- }
-
- function pasteInto(trans, html, target_id) {
- var e = document.getElementById('i1');
- var doc = e.contentDocument;
- doc.designMode = "on";
- doc.body.innerHTML = html;
- doc.defaultView.focus();
- if (target_id)
- e = doc.getElementById(target_id);
- else
- e = doc.body;
- var selection = doc.defaultView.getSelection();
- selection.removeAllRanges();
- selection.selectAllChildren(e);
- selection.collapseToEnd();
-
- pasteCount = 0;
- e.addEventListener("paste", pasteFunc, false);
- utils.sendContentCommandEvent("pasteTransferable", trans);
- e.removeEventListener("paste", pasteFunc, false);
-
- return e;
- }
-
- function getTransferableFromClipboard(asHTML) {
- var trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable);
- trans.init(getLoadContext());
- if (asHTML) {
- trans.addDataFlavor("text/html");
- } else {
- trans.addDataFlavor("text/unicode");
- }
- var clip = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard);
- clip.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
- return trans;
- }
-
- function makeTransferable(s,asHTML,target_id) {
- var e = document.getElementById('i2');
- var doc = e.contentDocument;
- if (asHTML) {
- doc.body.innerHTML = s;
- } else {
- var text = doc.createTextNode(s);
- doc.body.appendChild(text);
- }
- doc.designMode = "on";
- doc.defaultView.focus();
- var selection = doc.defaultView.getSelection();
- selection.removeAllRanges();
- if (!target_id) {
- selection.selectAllChildren(doc.body);
- } else {
- var range = document.createRange();
- range.selectNode(doc.getElementById(target_id));
- selection.addRange(range);
- }
-
- // We cannot use plain strings, we have to use nsSupportsString.
- var supportsStringClass = SpecialPowers.Components.classes["@mozilla.org/supports-string;1"];
- var ssData = supportsStringClass.createInstance(Ci.nsISupportsString);
-
- // Create the transferable.
- var trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable);
- trans.init(getLoadContext());
-
- // Add the data to the transferable.
- if (asHTML) {
- trans.addDataFlavor("text/html");
- ssData.data = doc.body.innerHTML;
- trans.setTransferData("text/html", ssData, ssData.length * 2);
- } else {
- trans.addDataFlavor("text/unicode");
- ssData.data = doc.body.innerHTML;
- trans.setTransferData("text/unicode", ssData, ssData.length * 2);
- }
-
- return trans;
- }
-
- function copyToClipBoard(s,asHTML,target_id) {
- var e = document.getElementById('i2');
- var doc = e.contentDocument;
- if (asHTML) {
- doc.body.innerHTML = s;
- } else {
- var text = doc.createTextNode(s);
- doc.body.appendChild(text);
- }
- doc.designMode = "on";
- doc.defaultView.focus();
- var selection = doc.defaultView.getSelection();
- selection.removeAllRanges();
- if (!target_id) {
- selection.selectAllChildren(doc.body);
- } else {
- var range = document.createRange();
- range.selectNode(doc.getElementById(target_id));
- selection.addRange(range);
- }
- SpecialPowers.wrap(doc).execCommand("copy", false, null);
- return e;
- }
-
- copyToClipBoard('<span>Hello</span><span>Kitty</span>', true);
- var trans = getTransferableFromClipboard(true);
- pasteInto(trans, '');
- verifyContent('<span>Hello</span><span>Kitty</span>');
- is(pasteCount, 1, "paste event was not triggered");
-
- // this test is not working out exactly like the clipboard test
- // has to do with generating the nsITransferable above
- //trans = makeTransferable('<span>Hello</span><span>Kitty</span>', true);
- //pasteInto(trans, '');
- //verifyContent('<span>Hello</span><span>Kitty</span>');
-
- copyToClipBoard("<dl><dd>Hello Kitty</dd></dl><span>Hello</span><span>Kitty</span>", true);
- trans = getTransferableFromClipboard(true);
- pasteInto(trans, '<ol><li id="paste_here">X</li></ol>',"paste_here");
- verifyContent('<ol><li id="paste_here">X<dl><dd>Hello Kitty</dd></dl><span>Hello</span><span>Kitty</span></li></ol>');
- is(pasteCount, 1, "paste event was not triggered");
-
-// The following test doesn't do what I expected, because the special handling
-// of IsList nodes in nsHTMLEditor::InsertHTMLWithContext simply removes
-// non-list/item children. See bug 481177.
-// copyToClipBoard("<ol><li>Hello Kitty</li><span>Hello</span></ol>", true);
-// pasteInto('<ol><li id="paste_here">X</li></ol>',"paste_here");
-// verifyContent('<ol><li id="paste_here">X</li><li>Hello Kitty</li><span>Hello</span></ol>');
-
- copyToClipBoard("<pre>Kitty</pre><span>Hello</span>", true);
- trans = getTransferableFromClipboard(true);
- pasteInto(trans, '<pre id="paste_here">Hello </pre>',"paste_here");
- verifyContent('<pre id="paste_here">Hello Kitty<span>Hello</span></pre>');
- is(pasteCount, 1, "paste event was not triggered");
-
- // test that we can preventDefault pastes
- pasteFunc = function (event) { event.preventDefault(); return false; };
- copyToClipBoard("<pre>Kitty</pre><span>Hello</span>", true);
- trans = getTransferableFromClipboard(true);
- pasteInto(trans, '<pre id="paste_here">Hello </pre>',"paste_here");
- verifyContent('<pre id="paste_here">Hello </pre>');
- is(pasteCount, 0, "paste event was triggered");
-
- SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(runTest);
-</script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=525389">Mozilla Bug 525389</a>
-<p id="display"></p>
-
-<pre id="test">
-</pre>
-
-<iframe id="i1" width="200" height="100" src="about:blank"></iframe><br>
-<iframe id="i2" width="200" height="100" src="about:blank"></iframe><br>
-
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug537046.html b/editor/libeditor/tests/test_bug537046.html
deleted file mode 100644
index 6c3c07b29..000000000
--- a/editor/libeditor/tests/test_bug537046.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=537046
--->
-<head>
- <title>Test for Bug 537046</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=537046">Mozilla Bug 537046</a>
-<p id="display"></p>
-<div id="content">
- <div id="editor" contenteditable="true">
- Some editable content
- </div>
- <div id="source" contenteditable="true">
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 537046 **/
-
-SimpleTest.expectAssertions(1);
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(function() {
- var ed = document.getElementById("editor");
- var src = document.getElementById("source");
- ed.addEventListener("DOMSubtreeModified", function() {
- src.textContent = ed.innerHTML;
- }, false);
- src.addEventListener("DOMSubtreeModified", function() {
- ed.innerHTML = ed.textContent;
- }, false);
-
- // Simulate pressing Enter twice
- ed.focus();
- synthesizeKey("VK_RETURN", {});
- synthesizeKey("VK_RETURN", {});
-
- ok(true, "Didn't crash!");
- SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug549262.html b/editor/libeditor/tests/test_bug549262.html
deleted file mode 100644
index fa1cbabc4..000000000
--- a/editor/libeditor/tests/test_bug549262.html
+++ /dev/null
@@ -1,132 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=549262
--->
-<head>
- <title>Test for Bug 549262</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=549262">Mozilla Bug 549262</a>
-<p id="display"></p>
-<div id="content">
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 549262 **/
-
-var smoothScrollPref = "general.smoothScroll";
-SimpleTest.waitForExplicitFinish();
-var win = window.open("file_bug549262.html", "_blank",
- "width=600,height=600,scrollbars=yes");
-
-// grab the timer right at the start
-var cwu = SpecialPowers.getDOMWindowUtils(win);
-function step() {
- cwu.advanceTimeAndRefresh(100);
-}
-SimpleTest.waitForFocus(function() {
- SpecialPowers.pushPrefEnv({"set":[[smoothScrollPref, false]]}, startTest);
-}, win);
-function startTest() {
- // Make sure that pressing Space when a contenteditable element is not focused
- // will scroll the page.
- var ed = win.document.getElementById("editor");
- var sc = win.document.querySelector("a");
- sc.focus();
- is(win.scrollY, 0, "Sanity check");
- synthesizeKey(" ", {}, win);
-
- step();
-
- isnot(win.scrollY, 0, "Page is scrolled down");
- is(ed.textContent, "abc", "The content of the editable element has not changed");
- var oldY = win.scrollY;
- synthesizeKey(" ", {shiftKey: true}, win);
-
- step();
-
- ok(win.scrollY < oldY, "Page is scrolled up");
- is(ed.textContent, "abc", "The content of the editable element has not changed");
-
- // Make sure that pressing Space when a contenteditable element is focused
- // will not scroll the page, and will edit the element.
- ed.focus();
- win.getSelection().collapse(ed.firstChild, 1);
- oldY = win.scrollY;
- synthesizeKey(" ", {}, win);
-
- step();
-
- ok(win.scrollY <= oldY, "Page is not scrolled down");
- is(ed.textContent, "a bc", "The content of the editable element has changed");
- sc.focus();
- synthesizeKey(" ", {}, win);
-
- step();
-
- isnot(win.scrollY, 0, "Page is scrolled down");
- is(ed.textContent, "a bc", "The content of the editable element has not changed");
- ed.focus();
- win.getSelection().collapse(ed.firstChild, 3);
- synthesizeKey(" ", {shiftKey: true}, win);
-
- step();
-
- isnot(win.scrollY, 0, "Page is not scrolled up");
- is(ed.textContent, "a b c", "The content of the editable element has changed");
-
- // Now let's test the down/up keys
- sc = document.body;
-
- step();
-
- ed.blur();
- sc.focus();
- oldY = win.scrollY;
- synthesizeKey("VK_UP", {}, win);
-
- step();
-
- ok(win.scrollY < oldY, "Page is scrolled up");
- oldY = win.scrollY;
- ed.focus();
- win.getSelection().collapse(ed.firstChild, 3);
- synthesizeKey("VK_UP", {}, win);
-
- step();
-
- is(win.scrollY, oldY, "Page is not scrolled up");
- is(win.getSelection().focusNode, ed.firstChild, "Correct element selected");
- is(win.getSelection().focusOffset, 0, "Selection should be moved to the beginning");
- win.getSelection().removeAllRanges();
- synthesizeMouse(sc, 300, 300, {}, win);
- synthesizeKey("VK_DOWN", {}, win);
-
- step();
-
- ok(win.scrollY > oldY, "Page is scrolled down");
- ed.focus();
- win.getSelection().collapse(ed.firstChild, 3);
- oldY = win.scrollY;
- synthesizeKey("VK_DOWN", {}, win);
-
- step();
-
- is(win.scrollY, oldY, "Page is not scrolled down");
- is(win.getSelection().focusNode, ed.firstChild, "Correct element selected");
- is(win.getSelection().focusOffset, ed.textContent.length, "Selection should be moved to the end");
-
- win.close();
- cwu.restoreNormalRefresh();
-
- SimpleTest.finish();
-}
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug550434.html b/editor/libeditor/tests/test_bug550434.html
deleted file mode 100644
index 0fa3ad159..000000000
--- a/editor/libeditor/tests/test_bug550434.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=550434
--->
-<head>
- <title>Test for Bug 550434</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=550434">Mozilla Bug 550434</a>
-<p id="display"></p>
-<div id="content">
- <div id="editor" contenteditable="true"
- style="height: 250px; height: 200px; border: 4px solid red; outline: none;"></div>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 550434 **/
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var ed = document.getElementById("editor");
-
- // Simulate click twice
- synthesizeMouse(ed, 10, 10, {});
- synthesizeMouse(ed, 50, 50, {});
- setTimeout(function() {
- synthesizeKey("x", {});
-
- is(ed.innerHTML, "x", "Editor should work after being clicked twice");
- SimpleTest.finish();
- }, 0);
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug551704.html b/editor/libeditor/tests/test_bug551704.html
deleted file mode 100644
index 8f335276f..000000000
--- a/editor/libeditor/tests/test_bug551704.html
+++ /dev/null
@@ -1,125 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=551704
--->
-<head>
- <title>Test for Bug 551704</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=551704">Mozilla Bug 551704</a>
-<p id="display"></p>
-<div id="content">
- <div id="preformatted" style="white-space: pre" contenteditable>a&#10;b</div>
- <div id="test1" contenteditable><br></div>
- <div id="test2" contenteditable>a<br></div>
- <div id="test3" contenteditable style="white-space: pre"><br></div>
- <div id="test4" contenteditable style="white-space: pre">a<br></div>
- <div id="test5" contenteditable></div>
- <div id="test6" contenteditable>a</div>
- <div id="test7" contenteditable style="white-space: pre"></div>
- <div id="test8" contenteditable style="white-space: pre">a</div>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-function testLineBreak(div, type, expectedText, expectedHTML, callback)
-{
- div.focus();
- getSelection().collapse(div, 0);
- type();
- is(div.innerHTML, expectedHTML, "The expected HTML after editing should be correct");
- SimpleTest.waitForClipboard(expectedText,
- function() {
- getSelection().selectAllChildren(div);
- synthesizeKey("C", {accelKey: true});
- },
- function() {
- var t = document.createElement("textarea");
- document.body.appendChild(t);
- t.focus();
- synthesizeKey("V", {accelKey: true});
- is(t.value, expectedText, "The expected text should be copied to the clipboard");
- callback();
- },
- function() {
- SimpleTest.finish();
- }
- );
-}
-
-function typeABCDEF() {
- synthesizeKey("a", {});
- typeBCDEF_chars();
-}
-
-function typeBCDEF() {
- synthesizeKey("VK_RIGHT", {});
- typeBCDEF_chars();
-}
-
-function typeBCDEF_chars() {
- synthesizeKey("b", {});
- synthesizeKey("c", {});
- synthesizeKey("VK_RETURN", {});
- synthesizeKey("d", {});
- synthesizeKey("e", {});
- synthesizeKey("f", {});
-}
-
-/** Test for Bug 551704 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var preformatted = document.getElementById("preformatted");
- is(preformatted.innerHTML, "a\nb", "No BR node should be injected for preformatted editable fields");
-
- var iframe = document.createElement("iframe");
- iframe.addEventListener("load", function() {
- var sel = iframe.contentWindow.getSelection();
- is(sel.rangeCount, 0, "There should be no range in the selection initially");
- iframe.contentDocument.designMode = "on";
- sel = iframe.contentWindow.getSelection();
- is(sel.rangeCount, 1, "There should be a single range in the selection after setting designMode");
- var range = sel.getRangeAt(0);
- ok(range.collapsed, "The range should be collapsed");
- is(range.startContainer, iframe.contentDocument.body.firstChild, "The range should start on the text");
- is(range.startOffset, 0, "The start offset should be zero");
-
- continueTest();
- }, false);
- iframe.src = "data:text/html,foo";
- document.getElementById("content").appendChild(iframe);
-});
-
-function continueTest() {
- var divs = [];
- for (var i = 0; i < 8; ++i) {
- divs[i] = document.getElementById("test" + (i+1));
- }
- var current = 0;
- function doNextTest() {
- if (current == divs.length) {
- SimpleTest.finish();
- return;
- }
- var div = divs[current++];
- if (div.textContent == "a") {
- var type = typeBCDEF;
- } else {
- var type = typeABCDEF;
- }
- var expectedHTML = "abc<br>def<br>";
- var expectedText = "abc\ndef";
- testLineBreak(div, type, expectedText, expectedHTML, doNextTest);
- }
-
- doNextTest();
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug552782.html b/editor/libeditor/tests/test_bug552782.html
deleted file mode 100644
index 5c53e92c1..000000000
--- a/editor/libeditor/tests/test_bug552782.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=552782
--->
-<head>
- <title>Test for Bug 552782</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=290026">Mozilla Bug 552782</a>
-<p id="display"></p>
-<div id="editor" contenteditable></div>
-
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 552782 **/
-SimpleTest.waitForExplicitFinish();
-
-var original = '<ol><li>Item 1</li><ol><li>Item 2</li><li>Item 3</li><li>Item 4</li></ol></ol>';
-var editor = document.getElementById("editor");
-editor.innerHTML = original;
-editor.focus();
-
-addLoadEvent(function() {
-
- var sel = window.getSelection();
- sel.removeAllRanges();
- var lis = document.getElementsByTagName("li");
- sel.selectAllChildren(lis[2]);
- document.execCommand("outdent", false, false);
- var expected = '<ol><li>Item 1</li><ol><li>Item 2</li></ol><li>Item 3</li><ol><li>Item 4</li></ol></ol>';
- is(editor.innerHTML, expected, "outdenting third item in a partially indented numbered list");
- document.execCommand("indent", false, false);
- todo_is(editor.innerHTML, original, "re-indenting third item in a partially indented numbered list");
-
- // done
- SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug567213.html b/editor/libeditor/tests/test_bug567213.html
deleted file mode 100644
index 22418f9e2..000000000
--- a/editor/libeditor/tests/test_bug567213.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=567213
--->
-
-<head>
- <title>Test for Bug 567213</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-
-<body>
- <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=567213">Mozilla Bug 567213</a>
- <p id="display"></p>
- <div id="content">
- <div id="target" contenteditable="true">test</div>
- <button id="thief">theif</button>
- </div>
-
- <pre id="test">
- <script type="application/javascript">
-
- /** Test for Bug 567213 **/
-
- SimpleTest.waitForExplicitFinish();
-
- addLoadEvent(function() {
- var target = document.getElementById("target");
- var thief = document.getElementById("thief");
- var sel = window.getSelection();
-
- // select the contents of the editable area
- sel.removeAllRanges();
- sel.selectAllChildren(target);
- target.focus();
-
- // press some key
- synthesizeKey("X", {});
- is(target.textContent, "X", "Text input should work (sanity check)");
-
- // select the contents of the editable area again
- sel.removeAllRanges();
- sel.selectAllChildren(target);
- thief.focus();
-
- // press some key with the thief having focus
- synthesizeKey("Y", {});
- is(target.textContent, "X", "Text entry should not work with another element focused");
-
- SimpleTest.finish();
- });
-
- </script>
- </pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug569988.html b/editor/libeditor/tests/test_bug569988.html
deleted file mode 100644
index e42bbb985..000000000
--- a/editor/libeditor/tests/test_bug569988.html
+++ /dev/null
@@ -1,99 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=569988
--->
-<head>
- <title>Test for Bug 569988</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <script src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=569988">Mozilla Bug 569988</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 569988 **/
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTest);
-
-
-function runTest()
-{
- var script = SpecialPowers.loadChromeScript(function() {
- var gPromptInput = null;
- var os = Components.classes["@mozilla.org/observer-service;1"]
- .getService(Components.interfaces.nsIObserverService);
-
- os.addObserver(onPromptLoad, "common-dialog-loaded", false);
- os.addObserver(onPromptLoad, "tabmodal-dialog-loaded", false);
-
- function onPromptLoad(subject, topic, data) {
- sendAsyncMessage("ok", [true, "onPromptLoad is called"]);
- gPromptInput = subject.Dialog.ui.loginTextbox;
- gPromptInput.addEventListener("focus", onPromptFocus, false);
- // shift focus to ensure it fires.
- subject.Dialog.ui.button0.focus();
- gPromptInput.focus();
- }
-
- function onPromptFocus() {
- sendAsyncMessage("ok", [true, "onPromptFocus is called"]);
- gPromptInput.removeEventListener("focus", onPromptFocus, false);
-
- var listenerService =
- Components.classes["@mozilla.org/eventlistenerservice;1"]
- .getService(Components.interfaces.nsIEventListenerService);
-
- var listener = {
- handleEvent: function _hv(aEvent) {
- var isPrevented = aEvent.defaultPrevented;
- sendAsyncMessage("ok", [!isPrevented,
- "ESC key event is prevented by editor"]);
- listenerService.removeSystemEventListener(gPromptInput, "keypress",
- listener, false);
- }
- };
- listenerService.addSystemEventListener(gPromptInput, "keypress",
- listener, false);
-
- sendAsyncMessage("info", "sending key");
- var EventUtils = {};
- EventUtils.window = {};
- EventUtils._EU_Ci = Components.interfaces;
- EventUtils._EU_Cc = Components.classes;
- Components.classes['@mozilla.org/moz/jssubscript-loader;1']
- .getService(Components.interfaces.mozIJSSubScriptLoader)
- .loadSubScript("chrome://mochikit/content/tests/SimpleTest/EventUtils.js",
- EventUtils);
- EventUtils.synthesizeKey("VK_ESCAPE", {},
- gPromptInput.ownerDocument.defaultView);
- }
-
- addMessageListener("destroy", function() {
- os.removeObserver(onPromptLoad, "tabmodal-dialog-loaded");
- os.removeObserver(onPromptLoad, "common-dialog-loaded");
- });
- });
- script.addMessageListener("ok", ([val, msg]) => ok(val, msg));
- script.addMessageListener("info", msg => info(msg));
-
- info("opening prompt...");
- prompt("summary", "text");
- info("prompt is closed");
-
- script.sendSyncMessage("destroy");
-
- SimpleTest.finish();
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug570144.html b/editor/libeditor/tests/test_bug570144.html
deleted file mode 100644
index e3b98b8d6..000000000
--- a/editor/libeditor/tests/test_bug570144.html
+++ /dev/null
@@ -1,123 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=570144
--->
-<head>
- <title>Test for Bug 570144</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=570144">Mozilla Bug 570144</a>
-<p id="display"></p>
-<div id="content">
- <!-- editable paragraphs in list item -->
- <section id="test1">
- <ol>
- <li><p contenteditable>foo</p></li>
- </ol>
- <ul>
- <li><p contenteditable>foo</p></li>
- </ul>
- <dl>
- <dt>foo</dt>
- <dd><p contenteditable>bar</p></dd>
- </dl>
- </section>
- <!-- paragraphs in editable list item -->
- <section id="test2">
- <ol>
- <li contenteditable><p>foo</p></li>
- </ol>
- <ul>
- <li contenteditable><p>foo</p></li>
- </ul>
- <dl>
- <dt>foo</dt>
- <dd contenteditable><p>bar</p></dd>
- </dl>
- </section>
- <!-- paragraphs in editable list -->
- <section id="test3">
- <ol contenteditable>
- <li><p>foo</p></li>
- </ol>
- <ul contenteditable>
- <li><p>foo</p></li>
- </ul>
- <dl contenteditable>
- <dt>foo</dt>
- <dd><p>bar</p></dd>
- </dl>
- </section>
-</div>
-
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 570144 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTests);
-
-function try2split(list) {
- var editor = list.hasAttribute("contenteditable")
- ? list : list.querySelector("*[contenteditable]");
- editor.focus();
- // put the caret at the end of the paragraph
- var selection = window.getSelection();
- if (editor.nodeName.toLowerCase() == "p")
- selection.selectAllChildren(editor);
- else
- selection.selectAllChildren(editor.querySelector("p"));
- selection.collapseToEnd();
- // simulate a [Return] keypress
- synthesizeKey("VK_RETURN", {});
-}
-
-function testSection(element, context, shouldCreateLI, shouldCreateP) {
- var nbLI = shouldCreateLI ? 2 : 1; // number of expected list items
- var nbP = shouldCreateP ? 2 : 1; // number of expected paragraphs
-
- function message(nodeName, dup) {
- return context + ":[Return] should " + (dup ? "" : "not ")
- + "create another <" + nodeName + ">."
- }
- var msgP = message("p", shouldCreateP);
- var msgLI = message("li", shouldCreateLI);
- var msgDT = message("dt", shouldCreateLI);
- var msgDD = message("dd", false);
-
- const ol = element.querySelector("ol");
- try2split(ol);
- is(ol.querySelectorAll("li").length, nbLI, msgLI);
- is(ol.querySelectorAll("p").length, nbP, msgP);
-
- const ul = element.querySelector("ul");
- try2split(ul);
- is(ul.querySelectorAll("li").length, nbLI, msgLI);
- is(ul.querySelectorAll("p").length, nbP, msgP);
-
- const dl = element.querySelector("dl");
- try2split(dl);
- is(dl.querySelectorAll("dt").length, nbLI, msgDT);
- is(dl.querySelectorAll("dd").length, 1, msgDD);
- is(dl.querySelectorAll("p").length, nbP, msgP);
-}
-
-function runTests() {
- testSection(document.getElementById("test1"), "editable paragraph in list item", false, false);
- testSection(document.getElementById("test2"), "paragraph in editable list item", false, true);
- testSection(document.getElementById("test3"), "paragraph in editable list", true, false);
- /* Note: concerning #test3, it would be preferrable that [Return] creates
- * another paragraph in another list item (i.e. last argument = 'true').
- * Currently it just creates an empty list item, which is acceptable.
- */
- SimpleTest.finish();
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug578771.html b/editor/libeditor/tests/test_bug578771.html
deleted file mode 100644
index 09f163c51..000000000
--- a/editor/libeditor/tests/test_bug578771.html
+++ /dev/null
@@ -1,63 +0,0 @@
-<!DOCTYPE HTML>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this file,
- - You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=578771
--->
-
-<head>
- <title>Test for Bug 578771</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-
-<body>
- <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=578771">Mozilla Bug 578771</a>
- <p id="display"></p>
- <div id="content" style="display: none">
- </div>
-
- <pre id="test">
- <script type="application/javascript">
-
- /** Test for Bug 578771 **/
- SimpleTest.waitForExplicitFinish();
-
- function testElem(elem, elemTag) {
- var ce = document.getElementById("ce");
- ce.focus();
-
- synthesizeMouse(elem, 5, 5, {clickCount: 2 });
- ok(elem.selectionStart == 0 && elem.selectionEnd == 7,
- " Double-clicking on another " + elemTag + " works correctly");
-
- ce.focus();
- synthesizeMouse(elem, 5, 5, {clickCount: 3 });
- ok(elem.selectionStart == 0 && elem.selectionEnd == 14,
- "Triple-clicking on another " + elemTag + " works correctly");
- }
- // Avoid platform selection differences
- SimpleTest.waitForFocus(function() {
- SpecialPowers.pushPrefEnv({"set":[["layout.word_select.eat_space_to_next_word", false]]}, startTest);
- });
-
- function startTest() {
- var input = document.getElementById("ip");
- testElem(input, "input");
-
- var textarea = document.getElementById("ta");
- testElem(textarea, "textarea");
-
- SimpleTest.finish();
- }
- </script>
- </pre>
-
- <input id="ip" type="text" value="Mozilla editor" />
- <textarea id="ta">Mozilla editor</textarea>
- <div id="ce" contenteditable="true">Contenteditable div that could interfere with focus</div>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug586662.html b/editor/libeditor/tests/test_bug586662.html
deleted file mode 100644
index 36c56d759..000000000
--- a/editor/libeditor/tests/test_bug586662.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=586662
--->
-
-<head>
- <title>Test for Bug 586662</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-
-<body>
- <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=586662">Mozilla Bug 586662</a>
- <p id="display"><textarea onkeypress="this.style.overflow = 'hidden'"></textarea></p>
- <div id="content" style="display: none">
- </div>
-
- <pre id="test">
- <script type="application/javascript">
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var t = document.querySelector("textarea");
- t.focus();
- synthesizeKey("a", {});
- is(getComputedStyle(t, null).overflow, "hidden", "The event handler should be executed");
- is(t.value, "a", "The key entry should result in a character being added to the field");
-
- var win = window.open("file_bug586662.html", "_blank",
- "width=600,height=600,scrollbars=yes");
- SimpleTest.waitForFocus(function() {
- // Make sure that focusing the textarea will cause the page to scroll
- var ed = win.document.getElementById("editor");
- ed.focus();
- setTimeout(function() {
- isnot(win.scrollY, 0, "Page is scrolled down");
- // Scroll back up
- win.scrollTo(0, 0);
- setTimeout(function() {
- is(win.scrollY, 0, "Page is scrolled back up");
- // Make sure that typing something into the textarea will cause the
- // page to scroll down
- synthesizeKey("a", {}, win);
- setTimeout(function() {
- isnot(win.scrollY, 0, "Page is scrolled down again");
-
- win.close();
- SimpleTest.finish();
- }, 0);
- }, 0);
- }, 0);
- }, win);
-});
-
- </script>
- </pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug587461.html b/editor/libeditor/tests/test_bug587461.html
deleted file mode 100644
index 2cf9f29fc..000000000
--- a/editor/libeditor/tests/test_bug587461.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!DOCTYPE html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=587461
--->
-<title>Test for Bug 587461</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
-<script src="/tests/SimpleTest/EventUtils.js"></script>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=587461">Mozilla Bug 587461</a>
-<div contenteditable><b>foobar</b></div>
-<script>
-var div = document.querySelector("div");
-getSelection().collapse(div.firstChild.firstChild, 3);
-document.execCommand("inserthtml", false, "a");
-is(div.innerHTML, "<b>fooabar</b>", "innerHTML");
-</script>
diff --git a/editor/libeditor/tests/test_bug590554.html b/editor/libeditor/tests/test_bug590554.html
deleted file mode 100644
index bc98503ed..000000000
--- a/editor/libeditor/tests/test_bug590554.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=590554
--->
-
-<head>
- <title>Test for Bug 590554</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-
-<body>
-
- <script type="application/javascript">
-
- /** Test for Bug 590554 **/
-
- SimpleTest.waitForExplicitFinish();
-
- SimpleTest.waitForFocus(function() {
- var t = document.querySelector("textarea");
- t.focus();
- synthesizeKey("VK_RETURN", {});
- is(t.value, "\n", "Pressing enter should work the first time");
- synthesizeKey("VK_RETURN", {});
- is(t.value, "\n", "Pressing enter should not work the second time");
- SimpleTest.finish();
- });
-
- </script>
-
- <textarea maxlength="1"></textarea>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug592592.html b/editor/libeditor/tests/test_bug592592.html
deleted file mode 100644
index 834ecbe1d..000000000
--- a/editor/libeditor/tests/test_bug592592.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=592592
--->
-<head>
- <title>Test for Bug 592592</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=592592">Mozilla Bug 592592</a>
-<p id="display"></p>
-<div id="content">
- <div id="editor" contenteditable="true" style="white-space:pre-wrap">a b</div>
- <div id="editor2" contenteditable="true" style="white-space:pre-wrap">a b</div>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 592592 **/
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var ed = document.getElementById("editor");
-
- // Put the selection right after "a"
- ed.focus();
- window.getSelection().collapse(ed.firstChild, 1);
-
- // Press space
- synthesizeKey(" ", {});
-
- // Make sure we haven't added an nbsp
- is(ed.innerHTML, "a b", "We should not be adding an &nbsp; for preformatted text");
-
- // Remove the preformatted style
- ed.removeAttribute("style");
-
- // Reset the DOM
- ed.innerHTML = "a b";
-
- // Reset the selection
- ed.focus();
- window.getSelection().collapse(ed.firstChild, 1);
-
- // Press space
- synthesizeKey(" ", {});
-
- // Make sure that we have added an nbsp
- is(ed.innerHTML, "a&nbsp; b", "We should add an &nbsp; for non-preformatted text");
-
- ed = document.getElementById("editor2");
-
- // Put the selection after the second space in the second editable field
- ed.focus();
- window.getSelection().collapse(ed.firstChild, 3);
-
- // Press the back-space key
- synthesizeKey("VK_BACK_SPACE", {});
-
- // Make sure that we've only deleted a single space
- is(ed.innerHTML, "a b", "We should only be deleting a single space");
-
- SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug596001.html b/editor/libeditor/tests/test_bug596001.html
deleted file mode 100644
index c677df359..000000000
--- a/editor/libeditor/tests/test_bug596001.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=596001
--->
-<head>
- <title>Test for Bug 596001</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=596001">Mozilla Bug 596001</a>
-<p id="display"></p>
-<div id="content">
-<textarea id="src">a&#9;b</textarea>
-<textarea id="dst"></textarea>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 596001 **/
-
-function testTab(prefix, callback) {
- var src = document.getElementById("src");
- var dst = document.getElementById("dst");
- dst.value = prefix;
- src.focus();
- src.select();
- SimpleTest.waitForClipboard("a\tb",
- function() {
- synthesizeKey("c", {accelKey: true});
- },
- function() {
- dst.focus();
- var inputReceived = false;
- dst.addEventListener("input", function() { inputReceived = true; }, false);
- synthesizeKey("v", {accelKey: true});
- ok(inputReceived, "An input event should be raised");
- is(dst.value, prefix + src.value, "The value should be pasted verbatim");
- callback();
- },
- callback
- );
-}
-
-testTab("", function() {
- testTab("foo", function() {
- });
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug596333.html b/editor/libeditor/tests/test_bug596333.html
deleted file mode 100644
index a94726325..000000000
--- a/editor/libeditor/tests/test_bug596333.html
+++ /dev/null
@@ -1,124 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=596333
--->
-<head>
- <title>Test for Bug 596333</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <script src="spellcheck.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=596333">Mozilla Bug 596333</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 596333 **/
-const Ci = SpecialPowers.Ci;
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(runTest);
-
-var gMisspeltWords;
-
-function getEditor() {
- return SpecialPowers.wrap(document.getElementById("edit")).editor;
-}
-
-function append(str) {
- var edit = document.getElementById("edit");
- edit.focus();
- edit.selectionStart = edit.selectionEnd = edit.value.length;
- var editor = getEditor();
-
- for (var i = 0; i < str.length; ++i) {
- synthesizeKey(str[i], {});
- }
-}
-
-function getLoadContext() {
- return SpecialPowers.wrap(window)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsILoadContext);
-}
-
-function paste(str) {
- var edit = document.getElementById("edit");
- var Cc = SpecialPowers.Cc, Ci = SpecialPowers.Ci;
- var trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable);
- trans.init(getLoadContext());
- var s = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
- s.data = str;
- trans.setTransferData("text/unicode", s, str.length * 2);
-
- getEditor().pasteTransferable(trans);
-}
-
-function runOnFocus() {
- var edit = document.getElementById("edit");
-
- gMisspeltWords = ["haz", "cheezburger"];
- ok(isSpellingCheckOk(getEditor(), gMisspeltWords),
- "All misspellings before editing are accounted for.");
- append(" becaz I'm a lulcat!");
- onSpellCheck(edit, function () {
- gMisspeltWords.push("becaz");
- gMisspeltWords.push("lulcat");
- ok(isSpellingCheckOk(getEditor(), gMisspeltWords),
- "All misspellings after typing are accounted for.");
-
- // Now, type an invalid word, and instead of hitting "space" at the end, just blur
- // the textarea and see if the spell check after the blur event catches it.
- append(" workd");
- edit.blur();
- onSpellCheck(edit, function () {
- gMisspeltWords.push("workd");
- ok(isSpellingCheckOk(getEditor(), gMisspeltWords),
- "All misspellings after blur are accounted for.");
-
- // Also, test the case when we're entering the first word in a textarea
- gMisspeltWords = ["workd"];
- edit.value = "";
- append("workd ");
- onSpellCheck(edit, function () {
- ok(isSpellingCheckOk(getEditor(), gMisspeltWords),
- "Misspelling in the first entered word is accounted for.");
-
- // Make sure that pasting would also trigger spell checking for the previous word
- gMisspeltWords = ["workd"];
- edit.value = "";
- append("workd");
- paste(" x");
- onSpellCheck(edit, function () {
- ok(isSpellingCheckOk(getEditor(), gMisspeltWords),
- "Misspelling is accounted for after pasting.");
-
- SimpleTest.finish();
- });
- });
- });
- });
-}
-
-function runTest()
-{
- var edit = document.getElementById("edit");
- edit.focus();
-
- SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm", window);
- onSpellCheck(edit, runOnFocus);
-}
-</script>
-</pre>
-
-<textarea id="edit">I can haz cheezburger</textarea>
-
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug596506.html b/editor/libeditor/tests/test_bug596506.html
deleted file mode 100644
index 0fc1adabf..000000000
--- a/editor/libeditor/tests/test_bug596506.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=596506
--->
-<head>
- <title>Test for Bug 596506</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=596506">Mozilla Bug 596506</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 596506 **/
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTest);
-
-const kIsMac = navigator.platform.indexOf("Mac") == 0;
-
-function append(str) {
- for (var i = 0; i < str.length; ++i) {
- synthesizeKey(str[i], {});
- }
-}
-
-function runTest() {
- var edit = document.getElementById("edit");
- edit.focus();
-
- append("First");
- synthesizeKey("VK_RETURN", {});
- append("Second");
- synthesizeKey("VK_UP", {});
- synthesizeKey("VK_UP", {});
- if (kIsMac) {
- synthesizeKey("VK_RIGHT", {accelKey: true});
- } else {
- synthesizeKey("VK_END", {});
- }
- append("ly");
- is(edit.value, "Firstly\nSecond",
- "Pressing end should position the cursor before the terminating newline");
- SimpleTest.finish();
-}
-
-</script>
-</pre>
-
-<textarea id="edit"></textarea>
-
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug597331.html b/editor/libeditor/tests/test_bug597331.html
deleted file mode 100644
index f35413cb6..000000000
--- a/editor/libeditor/tests/test_bug597331.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=597331
--->
-<head>
- <title>Test for Bug 597331</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=597331">Mozilla Bug 597331</a>
-<p id="display"></p>
-<div id="content">
-<textarea>line1
-line2
-line3
-</textarea>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 597331 **/
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(function() {
- SimpleTest.executeSoon(function() {
- var t = document.querySelector("textarea");
- t.focus();
- t.selectionStart = 4;
- t.selectionEnd = 4;
- SimpleTest.executeSoon(function() {
- t.getBoundingClientRect(); // flush layout
- var before = snapshotWindow(window, true);
- t.selectionStart = 5;
- t.selectionEnd = 5;
- t.addEventListener("keydown", function() {
- t.removeEventListener("keydown", arguments.callee, false);
-
- SimpleTest.executeSoon(function() {
- t.style.display = 'block';
- document.body.offsetWidth;
- t.style.display = '';
- document.body.offsetWidth;
-
- is(t.selectionStart, 4, "Cursor should be moved correctly");
- is(t.selectionEnd, 4, "Cursor should be moved correctly");
-
- var after = snapshotWindow(window, true);
-
- var result = compareSnapshots(before, after, true);
- var msg = "The caret should be displayed correctly after reframing";
- if (!result[0]) {
- msg += "\nRESULT:\n" + result[2];
- msg += "\nREFERENCE:\n" + result[1];
- }
- ok(result[0], msg);
-
- SimpleTest.finish();
- });
- }, false);
- synthesizeKey("VK_LEFT", {});
- });
- });
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug597784.html b/editor/libeditor/tests/test_bug597784.html
deleted file mode 100644
index 321f2ad1c..000000000
--- a/editor/libeditor/tests/test_bug597784.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=597784
--->
-<head>
- <title>Test for Bug 597784</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=597784">Mozilla Bug 597784</a>
-<p id="display"></p>
-<div id="content"></div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 597784 **/
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(function() {
- document.designMode = "on";
- var content = document.getElementById("content");
- getSelection().collapse(content, 0);
- var html = "<test:tag>test:tag</test:tag>" +
- "<a href=\"http://mozilla.org/\" test:attr=\"test:attr\" custom=\"value\">link</a>";
- document.execCommand("insertHTML", false, html);
- is(content.innerHTML, html,
- "The custom tags and attributes should be inserted into the document using the insertHTML command");
- SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug599322.html b/editor/libeditor/tests/test_bug599322.html
deleted file mode 100644
index 578bcb11a..000000000
--- a/editor/libeditor/tests/test_bug599322.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=599322.patch
--->
-<head>
- <title>Test for Bug 599322.patch</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=599322.patch">Mozilla Bug 599322.patch</a>
-<p id="display"></p>
-<div id="content">
-<div id="src">src<img src="/tests/editor/libeditor/tests/green.png"></div>
-<iframe id="dst" src="javascript:;"></iframe>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 599322.patch **/
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(function() {
- var src = document.getElementById("src");
- var dst = document.getElementById("dst");
- var doc = dst.contentDocument;
- doc.open();
- doc.write("<html><head><base href='http://mochi.test:8888/'></head><body></body></html>");
- doc.close();
- SimpleTest.waitForFocus(function() {
- getSelection().selectAllChildren(src);
- SimpleTest.waitForClipboard("src",
- function() {
- synthesizeKey("c", {accelKey: true});
- },
- function() {
- dst.contentDocument.designMode = "on";
- dst.focus();
- dst.contentDocument.body.focus();
- synthesizeKey("v", {accelKey: true});
- is(dst.contentDocument.querySelector("img").src,
- document.querySelector("img").src,
- "The source should be correctly set based on the base URI");
- SimpleTest.finish();
- },
- function() {
- SimpleTest.finish();
- }
- );
- });
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug599983.html b/editor/libeditor/tests/test_bug599983.html
deleted file mode 100644
index 08fc9a228..000000000
--- a/editor/libeditor/tests/test_bug599983.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!doctype html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=599983
--->
-<title>Test for Bug 599983</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css">
-<script src="/tests/SimpleTest/EventUtils.js"></script>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=599983">Mozilla Bug 599983</a>
-<div contenteditable>foo</div>
-<script>
-getSelection().selectAllChildren(document.querySelector("div"));
-document.execCommand("bold");
-is(document.querySelector("[_moz_dirty]"), null,
- "No _moz_dirty allowed in webpages");
-</script>
diff --git a/editor/libeditor/tests/test_bug599983.xul b/editor/libeditor/tests/test_bug599983.xul
deleted file mode 100644
index 8b5d52a8c..000000000
--- a/editor/libeditor/tests/test_bug599983.xul
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin"
- type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
- type="text/css"?>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=599983
--->
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- title="Mozilla Bug 599983" onload="runTest()">
- <script type="application/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
- <script type="application/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
-
- <body xmlns="http://www.w3.org/1999/xhtml">
- <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=599983"
- target="_blank">Mozilla Bug 599983</a>
- <editor xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- id="editor"
- editortype="html"
- src="about:blank" />
- </body>
- <script type="application/javascript">
- <![CDATA[
-
- SimpleTest.waitForExplicitFinish();
-
- const kAllowInteraction = Components.interfaces.nsIPlaintextEditor
- .eEditorAllowInteraction;
- const kMailMask = Components.interfaces.nsIPlaintextEditor.eEditorMailMask;
-
- function runTest() {
- testEditor(false, false);
- testEditor(false, true);
- testEditor(true, false);
- testEditor(true, true);
-
- SimpleTest.finish();
- }
-
- function testEditor(setAllowInteraction, setMailMask) {
- var desc = " with " + (setAllowInteraction ? "" : "no ") +
- "eEditorAllowInteraction and " +
- (setMailMask ? "" : "no ") + "eEditorMailMask";
-
- var editorElem = document.getElementById("editor");
-
- var editorObj = editorElem.getEditor(editorElem.contentWindow);
- editorObj.flags = (setAllowInteraction ? kAllowInteraction : 0) |
- (setMailMask ? kMailMask : 0);
-
- var editorDoc = editorElem.contentDocument;
- editorDoc.body.innerHTML = "<p>foo<p>bar";
- editorDoc.getSelection().selectAllChildren(editorDoc.body.firstChild);
- editorDoc.execCommand("bold");
-
- var createsDirty = !setAllowInteraction || setMailMask;
-
- (createsDirty ? isnot : is)(editorDoc.querySelector("[_moz_dirty]"), null,
- "Elements with _moz_dirty" + desc);
-
- // Even if we do create _moz_dirty, we should strip it for innerHTML.
- is(editorDoc.body.innerHTML, "<p><b>foo</b></p><p>bar</p>",
- "innerHTML" + desc);
- }
-
- ]]>
- </script>
-</window>
diff --git a/editor/libeditor/tests/test_bug600570.html b/editor/libeditor/tests/test_bug600570.html
deleted file mode 100644
index 0a5a814f8..000000000
--- a/editor/libeditor/tests/test_bug600570.html
+++ /dev/null
@@ -1,80 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=600570
--->
-<head>
- <title>Test for Bug 600570</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=600570">Mozilla Bug 600570</a>
-<p id="display"></p>
-<div id="content">
-<textarea spellcheck="false">
-aaa
-[bbb]</textarea>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 600570 **/
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var t = document.querySelector("textarea");
- t.value = "[aaa\nbbb]";
- t.focus();
- synthesizeKey("A", {accelKey: true});
-
- SimpleTest.executeSoon(function() {
- t.getBoundingClientRect(); // flush layout
- var afterSetValue = snapshotWindow(window);
-
- t.value = t.defaultValue;
-
- t.selectionStart = 0;
- t.selectionEnd = 4;
- SimpleTest.waitForClipboard("aaa\n",
- function() {
- synthesizeKey("X", {accelKey: true});
- },
- function() {
- t.addEventListener("input", function() {
- t.removeEventListener("input", arguments.callee, false);
-
- setTimeout(function() { // Avoid the assertion in bug 649797
- is(t.value, "[aaa\nbbb]", "The value of the textarea should be correct");
- synthesizeKey("A", {accelKey: true});
- is(t.selectionStart, 0, "Select all should set the selection start to the beginning of textarea");
- is(t.selectionEnd, 9, "Select all should set the selection end to the end of textarea");
-
- var afterPaste = snapshotWindow(window);
-
- var res = compareSnapshots(afterSetValue, afterPaste, true);
- var msg = "Pasting and setting the value directly should result in the same rendering";
- if (!res[0]) {
- msg += "\nRESULT:\n" + res[2] + "\nREFERENCE:\n" + res[1];
- }
- ok(res[0], msg);
-
- SimpleTest.finish();
- }, 0);
- }, false);
- synthesizeKey("VK_RIGHT", {});
- synthesizeKey("V", {accelKey: true});
- },
- function() {
- SimpleTest.finish();
- }
- );
- });
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug602130.html b/editor/libeditor/tests/test_bug602130.html
deleted file mode 100644
index a61e5c9c3..000000000
--- a/editor/libeditor/tests/test_bug602130.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=602130
--->
-<head>
- <title>Test for Bug 602130</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=602130">Mozilla Bug 602130</a>
-<p id="display"></p>
-<div id="content">
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 602130 **/
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(function() {
- var i = document.createElement("input");
- document.body.appendChild(i);
- SpecialPowers.wrap(i).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement);
- i.select();
- i.focus();
- is(SpecialPowers.wrap(i).editor.transactionManager.numberOfUndoItems, 0,
- "The number of undo items should be 0 after initing the editor");
- i.style.display = "none";
- document.offsetWidth;
- i.style.display = "";
- document.offsetWidth;
- i.select();
- i.focus();
- is(SpecialPowers.wrap(i).editor.transactionManager.numberOfUndoItems, 0,
- "The number of undo items should be 0 after re-initing the editor");
- SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug603556.html b/editor/libeditor/tests/test_bug603556.html
deleted file mode 100644
index 0e0a70464..000000000
--- a/editor/libeditor/tests/test_bug603556.html
+++ /dev/null
@@ -1,48 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=603556
--->
-<head>
- <title>Test for Bug 603556</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=603556">Mozilla Bug 603556</a>
-<p id="display"></p>
-<div id="content">
- <div id="src">testing</div>
- <input maxlength="4">
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 603556 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var i = document.querySelector("input");
- var src = document.getElementById("src");
- SimpleTest.waitForClipboard(src.textContent,
- function() {
- getSelection().selectAllChildren(src);
- synthesizeKey("C", {accelKey: true});
- },
- function() {
- i.focus();
- synthesizeKey("V", {accelKey: true});
- is(i.value, src.textContent.substr(0, i.maxLength),
- "Pasting should paste maxlength chars worth of the clipboard contents");
- SimpleTest.finish();
- },
- function() {
- SimpleTest.finish();
- }
- );
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug604532.html b/editor/libeditor/tests/test_bug604532.html
deleted file mode 100644
index 519a179b1..000000000
--- a/editor/libeditor/tests/test_bug604532.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=604532
--->
-<head>
- <title>Test for Bug 604532</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=604532">Mozilla Bug 604532</a>
-<p id="display"></p>
-<div id="content">
-<input>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 604532 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var i = document.querySelector("input");
- i.focus();
- i.value = "foo";
- synthesizeKey("A", {accelKey: true});
- is(i.selectionStart, 0, "Selection should start at 0 before appending");
- is(i.selectionEnd, 3, "Selection should end at 3 before appending");
- synthesizeKey("VK_RIGHT", {});
- synthesizeKey("x", {});
- is(i.value, "foox", "The text should be appended correctly");
- synthesizeKey("A", {accelKey: true});
- is(i.selectionStart, 0, "Selection should start at 0 after appending");
- is(i.selectionEnd, 4, "Selection should end at 4 after appending");
- SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug607584.html b/editor/libeditor/tests/test_bug607584.html
deleted file mode 100644
index aa22b6f30..000000000
--- a/editor/libeditor/tests/test_bug607584.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=607584
--->
-<head>
- <title>Test for Bug 607584</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=607584">Mozilla Bug 607584</a>
-<p id="display"></p>
-<div id="content" contenteditable>
-<p id="foo">Hello world</p>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 607584 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var content = document.getElementById("content");
- content.focus();
- var sel = getSelection();
- sel.collapse(document.getElementById("foo").firstChild, 5);
- synthesizeKey("VK_RETURN", {});
- var paragraphs = content.querySelectorAll("p");
- is(paragraphs.length, 2, "The paragraph should be split in two");
- is(paragraphs[0].textContent, "Hello", "The first paragraph should have the correct content");
- is(paragraphs[1].textContent, " world", "The second paragraph should have the correct content");
- is(paragraphs[0].getAttribute("id"), "foo", "The id of the first paragraph should be retained");
- is(paragraphs[1].hasAttribute("id"), false, "The second paragraph shouldn't have an ID");
- SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug607584.xul b/editor/libeditor/tests/test_bug607584.xul
deleted file mode 100644
index fb16cee83..000000000
--- a/editor/libeditor/tests/test_bug607584.xul
+++ /dev/null
@@ -1,115 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin"
- type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
- type="text/css"?>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=607584
--->
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- title="Mozilla Bug 607584" onload="runTest();">
- <script type="application/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
- <script type="application/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
-
- <body xmlns="http://www.w3.org/1999/xhtml">
- <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=607584"
- target="_blank">Mozilla Bug 607584</a>
- <p/>
- <editor xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- id="editor"
- type="content-primary"
- editortype="html"
- style="width: 400px; height: 100px; border: thin solid black"/>
- <p/>
- <pre id="test">
- </pre>
- </body>
- <script class="testbody" type="application/javascript">
- <![CDATA[
-
- SimpleTest.waitForExplicitFinish();
-
- function EditorContentListener(aEditor)
- {
- this.init(aEditor);
- }
-
- EditorContentListener.prototype = {
- init : function(aEditor)
- {
- this.mEditor = aEditor;
- },
-
- QueryInterface : function(aIID)
- {
- if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
- aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
- aIID.equals(Components.interfaces.nsISupports))
- return this;
- throw Components.results.NS_NOINTERFACE;
- },
-
- onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus)
- {
- if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP)
- {
- var editor = this.mEditor.getEditor(this.mEditor.contentWindow);
- if (editor) {
- this.mEditor.focus();
- editor instanceof Components.interfaces.nsIHTMLEditor;
- editor.returnInParagraphCreatesNewParagraph = true;
- editor.insertHTML("<p id='foo'>this is a paragraph carrying id 'foo'</p>");
- var p = editor.document.getElementById('foo')
- editor.beginningOfDocument();
- sendKey("return");
- var firstP = p.parentNode.firstElementChild;
- var lastP = p.parentNode.lastElementChild;
- var isOk = firstP.nodeName.toLowerCase() == "p" &&
- firstP.id == "foo" &&
- lastP.id == "";
- ok(isOk, "CR in a paragraph with an ID should not create two paragraphs of same ID");
- progress.removeProgressListener(this);
- SimpleTest.finish();
- }
- }
-
- },
-
-
- onProgressChange : function(aWebProgress, aRequest,
- aCurSelfProgress, aMaxSelfProgress,
- aCurTotalProgress, aMaxTotalProgress)
- {
- },
-
- onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags)
- {
- },
-
- onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
- {
- },
-
- onSecurityChange : function(aWebProgress, aRequest, aState)
- {
- },
-
- mEditor: null
- };
-
- var progress, progressListener;
-
- function runTest() {
- var newEditorElement = document.getElementById("editor");
- newEditorElement.makeEditable("html", true);
- var docShell = newEditorElement.boxObject.docShell;
- progress = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebProgress);
- progressListener = new EditorContentListener(newEditorElement);
- progress.addProgressListener(progressListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
- newEditorElement.setAttribute("src", "data:text/html,");
- }
-]]>
-</script>
-</window>
diff --git a/editor/libeditor/tests/test_bug611182.html b/editor/libeditor/tests/test_bug611182.html
deleted file mode 100644
index e6ecc6716..000000000
--- a/editor/libeditor/tests/test_bug611182.html
+++ /dev/null
@@ -1,239 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=611182
--->
-<head>
- <title>Test for Bug 611182</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=611182">Mozilla Bug 611182</a>
-<p id="display"></p>
-<div id="content">
- <iframe></iframe>
- <iframe id="ref" src="data:text/html,foo bar"></iframe>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 611182 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var iframe = document.querySelector("iframe");
- var refElem = document.querySelector("#ref");
- var ref = snapshotWindow(refElem.contentWindow, false);
-
- function findTextNode(doc) {
- var body = doc.documentElement;
- var result = findTextNodeWorker(body);
- ok(result, "Failed to find the text node");
- return result;
- }
-
- function findTextNodeWorker(root) {
- if (root.isContentEditable) {
- root.focus();
- }
- for (var i = 0; i < root.childNodes.length; ++i) {
- var node = root.childNodes[i];
- if (node.nodeType == node.TEXT_NODE &&
- node.nodeValue == "fooz bar") {
- return node;
- }
- if (node.nodeType == node.ELEMENT_NODE) {
- node = findTextNodeWorker(node);
- if (node) {
- return node;
- }
- }
- }
- return null;
- }
-
- function testBackspace(src, callback) {
- ok(true, "Testing " + src);
- iframe.addEventListener("load", function() {
- iframe.removeEventListener("load", arguments.callee, false);
-
- var doc = iframe.contentDocument;
- var win = iframe.contentWindow;
- doc.body.setAttribute("spellcheck", "false");
-
- iframe.focus();
- var textNode = findTextNode(doc);
- var sel = win.getSelection();
- sel.collapse(textNode, 4);
- synthesizeKey("VK_BACK_SPACE", {});
- is(textNode.textContent, "foo bar", "Backspace should work correctly");
-
- var snapshot = snapshotWindow(win, false);
- ok(compareSnapshots(snapshot, ref, true)[0], "No bogus node should exist in the document");
-
- callback();
- }, false);
- iframe.src = src;
- }
-
- const TEST_URIS = [
- "data:text/html,<html contenteditable>fooz bar</html>",
- "data:text/html,<html contenteditable><body>fooz bar</body></html>",
- "data:text/html,<body contenteditable>fooz bar</body>",
- "data:text/html,<body contenteditable><p>fooz bar</p></body>",
- "data:text/html,<body contenteditable><div>fooz bar</div></body>",
- "data:text/html,<body contenteditable><span>fooz bar</span></body>",
- "data:text/html,<p contenteditable style='outline:none'>fooz bar</p>",
- "data:text/html,<!DOCTYPE html><html><body contenteditable>fooz bar</body></html>",
- "data:text/html,<!DOCTYPE html><html contenteditable><body>fooz bar</body></html>",
- 'data:application/xhtml+xml,<html xmlns="http://www.w3.org/1999/xhtml"><body contenteditable="true">fooz bar</body></html>',
- 'data:application/xhtml+xml,<html xmlns="http://www.w3.org/1999/xhtml" contenteditable="true"><body>fooz bar</body></html>',
- "data:text/html,<body onload=\"document.designMode='on'\">fooz bar</body>",
- 'data:text/html,<html><script>' +
- 'onload = function() {' +
- 'var old = document.body;' +
- 'old.parentNode.removeChild(old);' +
- 'var r = document.documentElement;' +
- 'var b = document.createElement("body");' +
- 'r.appendChild(b);' +
- 'b.appendChild(document.createTextNode("fooz bar"));' +
- 'b.contentEditable = "true";' +
- '};' +
- '<\/script><body></body></html>',
- 'data:text/html,<html><script>' +
- 'onload = function() {' +
- 'var old = document.body;' +
- 'old.parentNode.removeChild(old);' +
- 'var r = document.documentElement;' +
- 'var b = document.createElement("body");' +
- 'b.appendChild(document.createTextNode("fooz bar"));' +
- 'b.contentEditable = "true";' +
- 'r.appendChild(b);' +
- '};' +
- '<\/script><body></body></html>',
- 'data:text/html,<html><script>' +
- 'onload = function() {' +
- 'var old = document.body;' +
- 'old.parentNode.removeChild(old);' +
- 'var r = document.documentElement;' +
- 'var b = document.createElement("body");' +
- 'r.appendChild(b);' +
- 'b.appendChild(document.createTextNode("fooz bar"));' +
- 'b.setAttribute("contenteditable", "true");' +
- '};' +
- '<\/script><body></body></html>',
- 'data:text/html,<html><script>' +
- 'onload = function() {' +
- 'var old = document.body;' +
- 'old.parentNode.removeChild(old);' +
- 'var r = document.documentElement;' +
- 'var b = document.createElement("body");' +
- 'b.appendChild(document.createTextNode("fooz bar"));' +
- 'b.setAttribute("contenteditable", "true");' +
- 'r.appendChild(b);' +
- '};' +
- '<\/script><body></body></html>',
- 'data:text/html,<html><script>' +
- 'onload = function() {' +
- 'var old = document.body;' +
- 'old.parentNode.removeChild(old);' +
- 'var r = document.documentElement;' +
- 'var b = document.createElement("body");' +
- 'r.appendChild(b);' +
- 'b.contentEditable = "true";' +
- 'b.appendChild(document.createTextNode("fooz bar"));' +
- '};' +
- '<\/script><body></body></html>',
- 'data:text/html,<html><script>' +
- 'onload = function() {' +
- 'var old = document.body;' +
- 'old.parentNode.removeChild(old);' +
- 'var r = document.documentElement;' +
- 'var b = document.createElement("body");' +
- 'b.contentEditable = "true";' +
- 'r.appendChild(b);' +
- 'b.appendChild(document.createTextNode("fooz bar"));' +
- '};' +
- '<\/script><body></body></html>',
- 'data:text/html,<html><script>' +
- 'onload = function() {' +
- 'var old = document.body;' +
- 'old.parentNode.removeChild(old);' +
- 'var r = document.documentElement;' +
- 'var b = document.createElement("body");' +
- 'r.appendChild(b);' +
- 'b.setAttribute("contenteditable", "true");' +
- 'b.appendChild(document.createTextNode("fooz bar"));' +
- '};' +
- '<\/script><body></body></html>',
- 'data:text/html,<html><script>' +
- 'onload = function() {' +
- 'var old = document.body;' +
- 'old.parentNode.removeChild(old);' +
- 'var r = document.documentElement;' +
- 'var b = document.createElement("body");' +
- 'b.setAttribute("contenteditable", "true");' +
- 'r.appendChild(b);' +
- 'b.appendChild(document.createTextNode("fooz bar"));' +
- '};' +
- '<\/script><body></body></html>',
- 'data:text/html,<html><script>' +
- 'onload = function() {' +
- 'document.open();' +
- 'document.write("<body contenteditable>fooz bar</body>");' +
- 'document.close();' +
- '};' +
- '<\/script><body></body></html>',
- 'data:text/html,<html><script>' +
- 'onload = function() {' +
- 'document.open();' +
- 'document.write("<body contenteditable><div>fooz bar</div></body>");' +
- 'document.close();' +
- '};' +
- '<\/script><body></body></html>',
- 'data:text/html,<html><script>' +
- 'onload = function() {' +
- 'document.open();' +
- 'document.write("<body contenteditable><span>fooz bar</span></body>");' +
- 'document.close();' +
- '};' +
- '<\/script><body></body></html>',
- 'data:text/html,<html><script>' +
- 'onload = function() {' +
- 'document.open();' +
- 'document.write("<p contenteditable style=\\"outline: none\\">fooz bar</p>");' +
- 'document.close();' +
- '};' +
- '<\/script><body></body></html>',
- 'data:text/html,<html><script>' +
- 'onload = function() {' +
- 'document.open();' +
- 'document.write("<html contenteditable>fooz bar</html>");' +
- 'document.close();' +
- '};' +
- '<\/script><body></body></html>',
- 'data:text/html,<html><script>' +
- 'onload = function() {' +
- 'document.open();' +
- 'document.write("<html contenteditable><body>fooz bar</body></html>");' +
- 'document.close();' +
- '};' +
- '<\/script><body></body></html>',
- ];
- var currentTest = 0;
- function runAllTests() {
- if (currentTest == TEST_URIS.length) {
- SimpleTest.finish();
- return;
- }
- testBackspace(TEST_URIS[currentTest++], runAllTests);
- }
- runAllTests();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug612128.html b/editor/libeditor/tests/test_bug612128.html
deleted file mode 100644
index b23d6f12a..000000000
--- a/editor/libeditor/tests/test_bug612128.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=612128
--->
-<head>
- <title>Test for Bug 612128</title>
- <script type="application/javascript" src="/MochiKit/packed.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=612128">Mozilla Bug 612128</a>
-<p id="display"></p>
-<div id="content">
-<input>
-<div contenteditable></div>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 612128 **/
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(function() {
- document.querySelector("input").focus();
- var threw = false;
- try {
- is(document.execCommand("inserthtml", null, "<span>f" + "oo</span>"),
- false, "The insertHTML command should return false");
- } catch (e) {
- ok(false, "insertHTML should not throw here");
- }
- is(document.querySelectorAll("span").length, 0, "No span element should be injected inside the page");
- is(document.body.innerHTML.indexOf("f" + "oo"), -1, "No text should be injected inside the page");
- SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug612447.html b/editor/libeditor/tests/test_bug612447.html
deleted file mode 100644
index b06739288..000000000
--- a/editor/libeditor/tests/test_bug612447.html
+++ /dev/null
@@ -1,74 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=612447
--->
-<head>
- <title>Test for Bug 612447</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=612447">Mozilla Bug 612447</a>
-<p id="display"></p>
-<div id="content">
-<iframe></iframe>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 612447 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- function editorCommandsEnabled() {
- var caught = false;
- try {
- doc.execCommand("justifyfull", false, null);
- } catch (e) {
- caught = true;
- }
- return !caught;
- }
-
- var i = document.querySelector("iframe");
- var doc = i.contentDocument;
- var win = i.contentWindow;
- var b = doc.body;
- doc.designMode = "on";
- i.focus();
- b.focus();
- var beforeA = snapshotWindow(win, true);
- synthesizeKey("X", {});
- var beforeB = snapshotWindow(win, true);
- is(b.textContent, "X", "Typing should work");
- while (b.firstChild) {
- b.removeChild(b.firstChild);
- }
- ok(editorCommandsEnabled(), "The editor commands should work");
-
- i.style.display = "block";
- document.clientWidth;
-
- i.focus();
- b.focus();
- var afterA = snapshotWindow(win, true);
- synthesizeKey("X", {});
- var afterB = snapshotWindow(win, true);
- is(b.textContent, "X", "Typing should work");
- while (b.firstChild) {
- b.removeChild(b.firstChild);
- }
- ok(editorCommandsEnabled(), "The editor commands should work");
-
- ok(compareSnapshots(beforeA, afterA, true)[0], "The iframes should look the same before typing");
- ok(compareSnapshots(beforeB, afterB, true)[0], "The iframes should look the same after typing");
-
- SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug616590.xul b/editor/libeditor/tests/test_bug616590.xul
deleted file mode 100644
index 57c29a028..000000000
--- a/editor/libeditor/tests/test_bug616590.xul
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin"
- type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
- type="text/css"?>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=616590
--->
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- title="Mozilla Bug 616590" onload="runTest();">
- <script type="application/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
- <script type="application/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
-
- <body xmlns="http://www.w3.org/1999/xhtml">
- <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=616590"
- target="_blank">Mozilla Bug 616590</a>
- <p/>
- <editor xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- id="editor"
- type="content"
- editortype="htmlmail"
- style="width: 400px; height: 100px;"/>
- <p/>
- <pre id="test">
- </pre>
- </body>
- <script class="testbody" type="application/javascript">
- <![CDATA[
-
- SimpleTest.waitForExplicitFinish();
-
- function EditorContentListener(aEditor)
- {
- this.init(aEditor);
- }
-
- EditorContentListener.prototype = {
- init : function(aEditor)
- {
- this.mEditor = aEditor;
- },
-
- QueryInterface : function(aIID)
- {
- if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
- aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
- aIID.equals(Components.interfaces.nsISupports))
- return this;
- throw Components.results.NS_NOINTERFACE;
- },
-
- onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus)
- {
- if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP)
- {
- var editor = this.mEditor.getEditor(this.mEditor.contentWindow);
- if (editor) {
- editor.QueryInterface(Components.interfaces.nsIEditorMailSupport);
- editor.insertAsCitedQuotation("<html><body><div contenteditable>foo</div></body></html>", "", true);
- document.documentElement.clientWidth;
- progress.removeProgressListener(this);
- ok(true, "Test complete");
- SimpleTest.finish();
- }
- }
- },
-
-
- onProgressChange : function(aWebProgress, aRequest,
- aCurSelfProgress, aMaxSelfProgress,
- aCurTotalProgress, aMaxTotalProgress)
- {
- },
-
- onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags)
- {
- },
-
- onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
- {
- },
-
- onSecurityChange : function(aWebProgress, aRequest, aState)
- {
- },
-
- mEditor: null
- };
-
- var progress, progressListener;
-
- function runTest() {
- var editorElement = document.getElementById("editor");
- editorElement.makeEditable("htmlmail", true);
- var docShell = editorElement.boxObject.docShell;
- progress = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebProgress);
- progressListener = new EditorContentListener(editorElement);
- progress.addProgressListener(progressListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
- editorElement.setAttribute("src", "data:text/html,");
- }
-]]>
-</script>
-</window>
diff --git a/editor/libeditor/tests/test_bug620906.html b/editor/libeditor/tests/test_bug620906.html
deleted file mode 100644
index 208bdfd28..000000000
--- a/editor/libeditor/tests/test_bug620906.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=620906
--->
-<head>
- <title>Test for Bug 620906</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=620906">Mozilla Bug 620906</a>
-<p id="display"></p>
-<div id="content">
- <iframe src="data:text/html,
- <body contenteditable
- onmousedown='
- document.designMode=&quot;on&quot;;
- document.designMode=&quot;off&quot;;
- '
- >
- <div style='height: 1000px;'></div>
- </body>">
- </iframe>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 620906 **/
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(function() {
- var iframe = document.querySelector("iframe");
- is(iframe.contentWindow.scrollY, 0, "Sanity check");
- var rect = iframe.getBoundingClientRect();
- setTimeout(function() {
- var onscroll = function () {
- iframe.contentWindow.removeEventListener("scroll", onscroll, false);
- isnot(iframe.contentWindow.scrollY, 0, "The scrollbar should work");
- SimpleTest.finish();
- }
- iframe.contentWindow.addEventListener("scroll", onscroll, false);
- synthesizeMouse(iframe, rect.width - 5, rect.height / 2, {});
- }, 0);
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug622371.html b/editor/libeditor/tests/test_bug622371.html
deleted file mode 100644
index d08ba8214..000000000
--- a/editor/libeditor/tests/test_bug622371.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=622371
--->
-<head>
- <title>Test for Bug 622371</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=622371">Mozilla Bug 622371</a>
-<p id="display"></p>
-<div id="content">
- <iframe src="data:text/html,<body contenteditable>abc</body>"></iframe>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 622371 **/
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(function() {
- var i = document.querySelector("iframe");
- var sel = i.contentWindow.getSelection();
- var doc = i.contentDocument;
- var body = doc.body;
- i.focus();
- sel.collapse(body, 1);
- doc.designMode = "on";
- doc.designMode = "off";
- is(sel.getRangeAt(0).startOffset, 1, "The start offset of the selection shouldn't change");
- is(sel.getRangeAt(0).endOffset, 1, "The end offset of the selection shouldn't change");
- SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug625452.html b/editor/libeditor/tests/test_bug625452.html
deleted file mode 100644
index e2292d753..000000000
--- a/editor/libeditor/tests/test_bug625452.html
+++ /dev/null
@@ -1,66 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=625452
--->
-<head>
- <title>Test for Bug 625452</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=625452">Mozilla Bug 625452</a>
-<p id="display"></p>
-<div id="content">
-<input>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 625452 **/
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(function() {
- var i = document.querySelector("input");
- var inputCount = 0;
- i.addEventListener("input", function() { inputCount++; }, false);
-
- // test cut
- i.focus();
- i.value = "foo bar";
- i.selectionStart = 0;
- i.selectionEnd = 4;
- synthesizeKey("X", {accelKey: true});
- is(i.value, "bar", "Cut should work correctly");
- is(inputCount, 1, "input event should be raised correctly");
-
- // test undo
- synthesizeKey("Z", {accelKey: true});
- is(i.value, "foo bar", "Undo should work correctly");
- is(inputCount, 2, "input event should be raised correctly");
-
- // test redo
- synthesizeKey("Z", {accelKey: true, shiftKey: true});
- is(i.value, "bar", "Redo should work correctly");
- is(inputCount, 3, "input event should be raised correctly");
-
- // test delete
- i.selectionStart = 0;
- i.selectionEnd = 2;
- synthesizeKey("VK_DELETE", {});
- is(i.value, "r", "Delete should work correctly");
- is(inputCount, 4, "input event should be raised correctly");
-
- // test DeleteSelection(eNone)
- i.value = "retest"; // the "r" common prefix is crucial here
- is(inputCount, 4, "input event should not have been raised");
-
- // paste is tested in test_bug596001.html
-
- SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug629845.html b/editor/libeditor/tests/test_bug629845.html
deleted file mode 100644
index 9eb24f904..000000000
--- a/editor/libeditor/tests/test_bug629845.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=629845
--->
-<head>
- <title>Test for Bug 629845</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=629845">Mozilla Bug 629845</a>
-<p id="display"></p>
-
-<script>
-function initFrame(frame)
-{
- frame.contentWindow.document.designMode="on";
- frame.contentWindow.document.writeln("<body></body>");
-
- document.getElementsByTagName('button')[0].click();
-}
-
-function command(aName)
-{
- var frame = document.getElementsByTagName('iframe')[0];
-
- is(frame.contentDocument.designMode, "on", "design mode should be on!");
- var caught = false;
- try {
- frame.contentDocument.execCommand(aName, false, null);
- } catch (e) {
- ok(false, "exception " + e + " was thrown");
- caught = true;
- }
-
- ok(!caught, "No exception should have been thrown.");
-
- // Stop the document load before finishing, just to be clean.
- document.getElementsByTagName('iframe')[0].contentWindow.document.close();
- SimpleTest.finish();
-}
-</script>
-
-<div id="content">
- <button type="button" onclick="command('bold');">Bold</button>
- <iframe onload="initFrame(this);"></iframe>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 629845 **/
-
-SimpleTest.waitForExplicitFinish();
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug635636.html b/editor/libeditor/tests/test_bug635636.html
deleted file mode 100644
index e5bbb5322..000000000
--- a/editor/libeditor/tests/test_bug635636.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=635636
--->
-<head>
- <title>Test for Bug 635636</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <script src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=635636">Mozilla Bug 635636</a>
-<p id="display"></p>
-<div id="content">
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 635636 **/
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(function() {
- var w, d;
-
- function b1()
- {
- w = window.open('data:application/xhtml+xml,<html xmlns="http://www.w3.org/1999/xhtml"><div>1</div></html>');
- SimpleTest.waitForFocus(b2, w);
- }
-
- function b2()
- {
- w.document.designMode = 'on';
- w.location = "data:text/plain,2";
- d = w.document.getElementsByTagName("div")[0];
- const Ci = SpecialPowers.Ci;
- var mainWindow = SpecialPowers.wrap(w)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShellTreeItem)
- .rootTreeItem
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindow);
- var browser = mainWindow.gBrowser.selectedBrowser;
- browser.addEventListener("pageshow", function() {
- setTimeout(b3, 0);
- }, false);
- }
-
- function b3()
- {
- d.parentNode.removeChild(d);
- ok(true, "Should not crash");
- // Not needed for the crash
- w.close();
- SimpleTest.finish();
- }
-
- b1();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug636465.html b/editor/libeditor/tests/test_bug636465.html
deleted file mode 100644
index 37ceebe5a..000000000
--- a/editor/libeditor/tests/test_bug636465.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!doctype html>
-<title>Mozilla bug 636465</title>
-<link rel=stylesheet href="/tests/SimpleTest/test.css">
-<script src="/tests/SimpleTest/EventUtils.js"></script>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<script src="/tests/SimpleTest/WindowSnapshot.js"></script>
-<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=636465"
- target="_blank">Mozilla Bug 636465</a>
-<input id="x" value="foobarbaz" spellcheck="true" style="background-color: transparent; border: transparent;">
-<script>
-SimpleTest.waitForExplicitFinish();
-
-function runTest() {
- SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm",
- window);
- var x = document.getElementById("x");
- x.focus();
- onSpellCheck(x, function () {
- x.blur();
- var spellCheckTrue = snapshotWindow(window);
- x.setAttribute("spellcheck", "false");
- var spellCheckFalse = snapshotWindow(window);
- x.setAttribute("spellcheck", "true");
- x.focus();
- onSpellCheck(x, function () {
- x.blur();
- var spellCheckTrueAgain = snapshotWindow(window);
- x.removeAttribute("spellcheck");
- var spellCheckNone = snapshotWindow(window);
- var after = snapshotWindow(window);
- var ret = compareSnapshots(spellCheckTrue, spellCheckFalse, false)[0];
- ok(ret,
- "Setting the spellcheck attribute to false should work");
- if (!ret) {
- ok(false, "\nspellCheckTrue: " + spellCheckTrue.toDataURL() + "\nspellCheckFalse: " + spellCheckFalse.toDataURL());
- }
- ret = compareSnapshots(spellCheckTrue, spellCheckTrueAgain, true)[0];
- ok(ret,
- "Setting the spellcheck attribute back to true should work");
- if (!ret) {
- ok(false, "\nspellCheckTrue: " + spellCheckTrue.toDataURL() + "\nspellCheckTrueAgain: " + spellCheckTrueAgain.toDataURL());
- }
- ret = compareSnapshots(spellCheckNone, spellCheckFalse, true)[0];
- ok(ret,
- "Unsetting the spellcheck attribute should work");
- if (!ret) {
- ok(false, "\spellCheckNone: " + spellCheckNone.toDataURL() + "\nspellCheckFalse: " + spellCheckFalse.toDataURL());
- }
- SimpleTest.finish();
- });
- });
-}
-addLoadEvent(runTest);
-</script>
diff --git a/editor/libeditor/tests/test_bug638596.html b/editor/libeditor/tests/test_bug638596.html
deleted file mode 100644
index 62ef103f0..000000000
--- a/editor/libeditor/tests/test_bug638596.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=638596
--->
-<head>
- <title>Test for Bug 638596</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=638596">Mozilla Bug 638596</a>
-<p id="display"></p>
-<div id="content">
- <input type="password" style="font-size: 0">
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 638596 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var i = document.querySelector("input");
- i.focus();
- synthesizeKey("t", {});
- synthesizeKey("e", {});
- synthesizeKey("s", {});
- synthesizeKey("t", {});
- is(i.value, "test", "The correct value should be stored in the field");
- SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug640321.html b/editor/libeditor/tests/test_bug640321.html
deleted file mode 100644
index 984ea295a..000000000
--- a/editor/libeditor/tests/test_bug640321.html
+++ /dev/null
@@ -1,190 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=640321
--->
-<head>
- <title>Test for Bug 640321</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=640321">Mozilla Bug 640321</a>
-<p id="display"></p>
-<div id="content" contenteditable style="text-align: center">
- <img src="green.png">
-</div>
-<div id="clickaway" style="width: 10px; height: 10px"></div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 640321 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var img = document.querySelector("img");
-
- function cancel(e) { e.stopPropagation(); }
- var content = document.getElementById("content");
- content.addEventListener("mousedown", cancel, false);
- content.addEventListener("mousemove", cancel, false);
- content.addEventListener("mouseup", cancel, false);
-
- /**
- * This function is a generic resizer test.
- * We have 8 resizers that we'd like to test, and each can be moved in 8 different directions.
- * In specifying baseX, W can be considered to be the width of the image, and for baseY, H
- * can be considered to be the height of the image. deltaX and deltaY are regular pixel values
- * which can be positive or negative.
- */
- const W = 1;
- const H = 1;
- function testResizer(baseX, baseY, deltaX, deltaY, expectedDeltaX, expectedDeltaY) {
- ok(true, "testResizer(" + [baseX, baseY, deltaX, deltaY, expectedDeltaX, expectedDeltaY].join(", ") + ")");
-
- // Reset the dimensions of the image
- img.style.width = "100px";
- img.style.height = "100px";
- var rect = img.getBoundingClientRect();
- is(rect.width, 100, "Sanity check the length");
- is(rect.height, 100, "Sanity check the height");
-
- // Click on the image to show the resizers
- synthesizeMouseAtCenter(img, {});
-
- // Determine which resizer we're dealing with
- var basePosX = rect.width * baseX;
- var basePosY = rect.height * baseY;
-
- // Click on the correct resizer
- synthesizeMouse(img, basePosX, basePosY, {type: "mousedown"});
- // Drag it delta pixels to the right and bottom (or maybe left and top!)
- synthesizeMouse(img, basePosX + deltaX, basePosY + deltaY, {type: "mousemove"});
- // Release the mouse button
- synthesizeMouse(img, basePosX + deltaX, basePosY + deltaY, {type: "mouseup"});
- // Move the mouse delta more pixels to the same direction to make sure that the
- // resize operation has stopped.
- synthesizeMouse(img, basePosX + deltaX * 2, basePosY + deltaY * 2, {type: "mousemove"});
- // Click outside of the image to hide the resizers
- synthesizeMouseAtCenter(document.getElementById("clickaway"), {});
-
- // Get the new dimensions for the image
- var newRect = img.getBoundingClientRect();
- is(newRect.width, rect.width + expectedDeltaX, "The width should be increased by " + expectedDeltaX + " pixels");
- is(newRect.height, rect.height + expectedDeltaY, "The height should be increased by " + expectedDeltaY + "pixels");
- }
-
- function runTests(preserveRatio) {
- // Account for changes in the resizing behavior when we're trying to preserve
- // the aspect ration.
- // ignoredGrowth means we don't change the size of a dimension because otherwise
- // the aspect ratio would change undesirably.
- // needlessGrowth means that we change the size of a dimension perpendecular to
- // the mouse movement axis in order to preserve the aspect ratio.
- // reversedGrowth means that we change the size of a dimension in the opposite
- // direction to the mouse movement in order to maintain the aspect ratio.
- const ignoredGrowth = preserveRatio ? 0 : 1;
- const needlessGrowth = preserveRatio ? 1 : 0;
- const reversedGrowth = preserveRatio ? -1 : 1;
-
- // top resizer
- testResizer(W/2, 0, -10, -10, 0, 10);
- testResizer(W/2, 0, -10, 0, 0, 0);
- testResizer(W/2, 0, -10, 10, 0, -10);
- testResizer(W/2, 0, 0, -10, 0, 10);
- testResizer(W/2, 0, 0, 0, 0, 0);
- testResizer(W/2, 0, 0, 10, 0, -10);
- testResizer(W/2, 0, 10, -10, 0, 10);
- testResizer(W/2, 0, 10, 0, 0, 0);
- testResizer(W/2, 0, 10, 10, 0, -10);
-
- // top right resizer
- testResizer( W, 0, -10, -10, -10 * reversedGrowth, 10);
- testResizer( W, 0, -10, 0, -10 * ignoredGrowth, 0);
- testResizer( W, 0, -10, 10, -10, -10);
- testResizer( W, 0, 0, -10, 10 * needlessGrowth, 10);
- testResizer( W, 0, 0, 0, 0, 0);
- testResizer( W, 0, 0, 10, 0, -10 * ignoredGrowth);
- testResizer( W, 0, 10, -10, 10, 10);
- testResizer( W, 0, 10, 0, 10, 10 * needlessGrowth);
- testResizer( W, 0, 10, 10, 10, -10 * reversedGrowth);
-
- // right resizer
- testResizer( W, H/2, -10, -10, -10, 0);
- testResizer( W, H/2, -10, 0, -10, 0);
- testResizer( W, H/2, -10, 10, -10, 0);
- testResizer( W, H/2, 0, -10, 0, 0);
- testResizer( W, H/2, 0, 0, 0, 0);
- testResizer( W, H/2, 0, 10, 0, 0);
- testResizer( W, H/2, 10, -10, 10, 0);
- testResizer( W, H/2, 10, 0, 10, 0);
- testResizer( W, H/2, 10, 10, 10, 0);
-
- // bottom right resizer
- testResizer( W, H, -10, -10, -10, -10);
- testResizer( W, H, -10, 0, -10 * ignoredGrowth, 0);
- testResizer( W, H, -10, 10, -10 * reversedGrowth, 10);
- testResizer( W, H, 0, -10, 0, -10 * ignoredGrowth);
- testResizer( W, H, 0, 0, 0, 0);
- testResizer( W, H, 0, 10, 10 * needlessGrowth, 10);
- testResizer( W, H, 10, -10, 10, -10 * reversedGrowth);
- testResizer( W, H, 10, 0, 10, 10 * needlessGrowth);
- testResizer( W, H, 10, 10, 10, 10);
-
- // bottom resizer
- testResizer(W/2, H, -10, -10, 0, -10);
- testResizer(W/2, H, -10, 0, 0, 0);
- testResizer(W/2, H, -10, 10, 0, 10);
- testResizer(W/2, H, 0, -10, 0, -10);
- testResizer(W/2, H, 0, 0, 0, 0);
- testResizer(W/2, H, 0, 10, 0, 10);
- testResizer(W/2, H, 10, -10, 0, -10);
- testResizer(W/2, H, 10, 0, 0, 0);
- testResizer(W/2, H, 10, 10, 0, 10);
-
- // bottom left resizer
- testResizer( 0, H, -10, -10, 10, -10 * reversedGrowth);
- testResizer( 0, H, -10, 0, 10, 10 * needlessGrowth);
- testResizer( 0, H, -10, 10, 10, 10);
- testResizer( 0, H, 0, -10, 0, -10 * ignoredGrowth);
- testResizer( 0, H, 0, 0, 0, 0);
- testResizer( 0, H, 0, 10, 10 * needlessGrowth, 10);
- testResizer( 0, H, 10, -10, -10, -10);
- testResizer( 0, H, 10, 0, -10 * ignoredGrowth, 0);
- testResizer( 0, H, 10, 10, -10 * reversedGrowth, 10);
-
- // left resizer
- testResizer( 0, H/2, -10, -10, 10, 0);
- testResizer( 0, H/2, -10, 0, 10, 0);
- testResizer( 0, H/2, -10, 10, 10, 0);
- testResizer( 0, H/2, 0, -10, 0, 0);
- testResizer( 0, H/2, 0, 0, 0, 0);
- testResizer( 0, H/2, 0, 10, 0, 0);
- testResizer( 0, H/2, 10, -10, -10, 0);
- testResizer( 0, H/2, 10, 0, -10, 0);
- testResizer( 0, H/2, 10, 10, -10, 0);
-
- // top left resizer
- testResizer( 0, 0, -10, -10, 10, 10);
- testResizer( 0, 0, -10, 0, 10, 10 * needlessGrowth);
- testResizer( 0, 0, -10, 10, 10, -10 * reversedGrowth);
- testResizer( 0, 0, 0, -10, 10 * needlessGrowth, 10);
- testResizer( 0, 0, 0, 0, 0, 0);
- testResizer( 0, 0, 0, 10, 0, -10 * ignoredGrowth);
- testResizer( 0, 0, 10, -10, -10 * reversedGrowth, 10);
- testResizer( 0, 0, 10, 0, -10 * ignoredGrowth, 0);
- testResizer( 0, 0, 10, 10, -10, -10);
- }
- SpecialPowers.pushPrefEnv({"set": [["editor.resizing.preserve_ratio", false]]}, function() {
- runTests(false);
- SpecialPowers.pushPrefEnv({"set": [["editor.resizing.preserve_ratio", true]]}, function() {
- runTests(true);
- SimpleTest.finish();
- });
- });
- });
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug641466.html b/editor/libeditor/tests/test_bug641466.html
deleted file mode 100644
index 4a77b0b89..000000000
--- a/editor/libeditor/tests/test_bug641466.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=641466
--->
-<head>
- <title>Test for Bug 641466</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=641466">Mozilla Bug 641466</a>
-<p id="display"></p>
-<div id="content">
-<input value="&#x10451;&#x10467;&#x10455;&#x10451;">
-<textarea>&#x10451;&#x10467;&#x10455;&#x10451;</textarea>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 641466 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- function doTest(element) {
- element.focus();
- element.selectionStart = 4;
- element.selectionEnd = 4;
- synthesizeKey("VK_BACK_SPACE", {});
- synthesizeKey("VK_BACK_SPACE", {});
- synthesizeKey("VK_BACK_SPACE", {});
- synthesizeKey("VK_BACK_SPACE", {});
-
- ok(element.value, "", "4 backspaces should delete all of the characters in the " + element.localName);
- }
-
- doTest(document.querySelector("input"));
- doTest(document.querySelector("textarea"));
-
- SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug645914.html b/editor/libeditor/tests/test_bug645914.html
deleted file mode 100644
index cdf799e56..000000000
--- a/editor/libeditor/tests/test_bug645914.html
+++ /dev/null
@@ -1,63 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=645914
--->
-<head>
- <title>Test for Bug 645914</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=645914">Mozilla Bug 645914</a>
-<p id="display"></p>
-<div id="content">
-<textarea>foo
-bar</textarea>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 645914 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- SpecialPowers.pushPrefEnv({"set":[["layout.word_select.eat_space_to_next_word", true],
- ["browser.triple_click_selects_paragraph", false]]}, startTest);
-});
-function startTest() {
- var textarea = document.querySelector("textarea");
- textarea.selectionStart = textarea.selectionEnd = 0;
-
- // Simulate a double click on foo
- synthesizeMouse(textarea, 5, 5, {clickCount: 2});
-
- ok(true, "Testing word selection");
- is(textarea.selectionStart, 0, "The start of the selection should be at the beginning of the text");
- is(textarea.selectionEnd, 3, "The end of the selection should not include a newline character");
-
- textarea.selectionStart = textarea.selectionEnd = 0;
-
- // Simulate a triple click on foo
- synthesizeMouse(textarea, 5, 5, {clickCount: 3});
-
- ok(true, "Testing line selection");
- is(textarea.selectionStart, 0, "The start of the selection should be at the beginning of the text");
- is(textarea.selectionEnd, 3, "The end of the selection should not include a newline character");
-
- textarea.selectionStart = textarea.selectionEnd = 0;
- textarea.value = "Very very long value which would eventually overflow the visible section of the textarea";
-
- // Simulate a quadruple click on Very
- synthesizeMouse(textarea, 5, 5, {clickCount: 4});
-
- ok(true, "Testing paragraph selection");
- is(textarea.selectionStart, 0, "The start of the selection should be at the beginning of the text");
- is(textarea.selectionEnd, textarea.value.length, "The end of the selection should be the end of the paragraph");
-
- SimpleTest.finish();
-}
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug646194.html b/editor/libeditor/tests/test_bug646194.html
deleted file mode 100644
index 8a0e4a829..000000000
--- a/editor/libeditor/tests/test_bug646194.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!doctype html>
-<title>Mozilla Bug 646194</title>
-<link rel=stylesheet href="/tests/SimpleTest/test.css">
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=646194"
- target="_blank">Mozilla Bug 646194</a>
-<iframe id="i" src="data:text/html,&lt;div contenteditable=true id=t&gt;test me now&lt;/div&gt;"></iframe>
-<script>
-SimpleTest.expectAssertions(1);
-
-function runTest() {
- var i = document.getElementById("i");
- i.focus();
- var win = i.contentWindow;
- var doc = i.contentDocument;
- var t = doc.getElementById("t");
- t.focus();
- // put the caret at the end
- win.getSelection().collapse(t.firstChild, 11);
-
- // Simulate pression Option+Delete on Mac
- // We do things this way because not every platform can invoke this
- // command using the available key bindings.
- SpecialPowers.doCommand(window, "cmd_wordPrevious");
- SpecialPowers.doCommand(window, "cmd_wordPrevious");
- SpecialPowers.doCommand(window, "cmd_deleteWordBackward");
- SpecialPowers.doCommand(window, "cmd_deleteWordBackward");
-
- // If we reach here, we haven't crashed. Phew!
- // But let's check the value too, now that we're here.
- is(t.textContent, "me now", "The command has worked correctly");
-
- SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(runTest);
-</script>
diff --git a/editor/libeditor/tests/test_bug668599.html b/editor/libeditor/tests/test_bug668599.html
deleted file mode 100644
index 8405d08ab..000000000
--- a/editor/libeditor/tests/test_bug668599.html
+++ /dev/null
@@ -1,73 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=668599
--->
-<head>
- <title>Test for Bug 668599</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=668599">Mozilla Bug 668599</a>
-<p id="display"></p>
-<div id="content">
- <div id="test1">
- block <span contenteditable>type here</span> block
- </div>
- <div id="test2">
- <p contenteditable>
- block <span>type here</span> block
- </p>
- </div>
-</div>
-
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 668599 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTests);
-
-function select(element) {
- // select the element text content
- var userSelection = window.getSelection();
- window.getSelection().removeAllRanges();
- var range = document.createRange();
- range.setStart(element.firstChild, 0);
- range.setEnd(element.firstChild, element.textContent.length);
- userSelection.addRange(range);
-};
-
-function runTests() {
- var span = document.querySelector("#test1 span");
-
- // editable <span> => the <span> *content* should be deleted
- select(span);
- span.focus();
- synthesizeKey("x", {});
- is(span.textContent, "x", "The <span> content should have been replaced by 'x'.");
-
- // same thing, but using [Del] instead of typing some text
- document.execCommand("Undo", false, null);
- select(span);
- span.focus();
- synthesizeKey("VK_DELETE", {});
- is(span.textContent, "", "The <span> content should have been deleted.");
-
- // <span> in editable block => the <span> *element* should be deleted
- select(document.querySelector("#test2 span"));
- document.querySelector("#test2 [contenteditable]").focus();
- synthesizeKey("VK_DELETE", {});
- is(document.querySelector("#test2 span"), null,
- "The <span> element should have been deleted.");
-
- // done
- SimpleTest.finish();
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug674770-1.html b/editor/libeditor/tests/test_bug674770-1.html
deleted file mode 100644
index 4ba65f507..000000000
--- a/editor/libeditor/tests/test_bug674770-1.html
+++ /dev/null
@@ -1,86 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=674770
--->
-<head>
- <title>Test for Bug 674770</title>
- <script type="application/javascript" src="/MochiKit/packed.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=674770">Mozilla Bug 674770</a>
-<p id="display"></p>
-<div id="content">
-<a href="file_bug674770-1.html" id="link1">test</a>
-<div contenteditable>
-<a href="file_bug674770-1.html" id="link2">test</a>
-</div>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- SpecialPowers.pushPrefEnv({"set":[["middlemouse.paste", true], ["dom.ipc.processCount", 1]]}, startTests);
-});
-
-function startTests() {
- var tests = [
- { description: "Testing link in <div>: ",
- target: function () { return document.querySelector("#link1"); },
- linkShouldWork: true },
- { description: "Testing link in <div contenteditable>: ",
- target: function () { return document.querySelector("#link2"); },
- linkShouldWork: false },
- ];
- var currentTest;
- function runNextTest() {
- localStorage.removeItem("clicked");
- currentTest = tests.shift();
- if (!currentTest) {
- SimpleTest.finish();
- return;
- }
- ok(true, currentTest.description + "Starting to test...");
- synthesizeMouseAtCenter(currentTest.target(), { button: 1 });
- }
-
-
- addEventListener("storage", function(e) {
- is(e.key, "clicked", currentTest.description + "Key should always be 'clicked'");
- is(e.newValue, "true", currentTest.description + "Value should always be 'true'");
- ok(currentTest.linkShouldWork, currentTest.description + "The click operation on the link " + (currentTest.linkShouldWork ? "should work" : "shouldn't work"));
- SimpleTest.executeSoon(runNextTest);
- }, false);
-
- SpecialPowers.addSystemEventListener(window, "click", function (aEvent) {
- // When the click event should cause default action, e.g., opening the link,
- // the event shouldn't have been consumed except the link handler.
- // However, in e10s mode, it's not consumed during propagating the event but
- // in non-e10s mode, it's consumed during the propagation. Therefore,
- // we cannot check defaultPrevented value when the link should work as is
- // if there is no way to detect if it's running in e10s mode or not.
- // So, let's skip checking Event.defaultPrevented value when the link should
- // work. In such case, we should receive "storage" event later.
- if (currentTest.linkShouldWork) {
- return;
- }
-
- ok(SpecialPowers.defaultPreventedInAnyGroup(aEvent),
- currentTest.description + "The default action should be consumed because the link should work as is");
- if (SpecialPowers.defaultPreventedInAnyGroup(aEvent)) {
- // In this case, "storage" event won't be fired.
- SimpleTest.executeSoon(runNextTest);
- }
- }, false);
-
- SimpleTest.executeSoon(runNextTest);
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug674770-2.html b/editor/libeditor/tests/test_bug674770-2.html
deleted file mode 100644
index c69311e95..000000000
--- a/editor/libeditor/tests/test_bug674770-2.html
+++ /dev/null
@@ -1,395 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=674770
--->
-<head>
- <title>Test for Bug 674770</title>
- <script type="application/javascript" src="/MochiKit/packed.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=674770">Mozilla Bug 674770</a>
-<p id="display"></p>
-<div id="content">
-<iframe id="iframe" style="display: block; height: 14em;"
- src="data:text/html,<input id='text' value='pasted'><input id='input' style='display: block;'><p id='editor1' contenteditable>editor1:</p><p id='editor2' contenteditable>editor2:</p>"></iframe>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 674770 **/
-SimpleTest.waitForExplicitFinish();
-
-var iframe = document.getElementById("iframe");
-var frameWindow, frameDocument;
-
-var gClicked = false;
-var gClicking = null;
-var gDoPreventDefault1 = null;
-var gDoPreventDefault2 = null;
-
-function clickEventHandler(aEvent)
-{
- if (aEvent.button == 1 && aEvent.target == gClicking) {
- gClicked = true;
- }
- if (gDoPreventDefault1 == aEvent.target) {
- aEvent.preventDefault();
- }
- if (gDoPreventDefault2 == aEvent.target) {
- aEvent.preventDefault();
- }
-}
-
-// NOTE: tests need to check the result *after* the content is actually
-// modified. Sometimes, the modification is delayed. Therefore, there
-// are a lot of functions and SimpleTest.executeSoon()s.
-SimpleTest.waitForFocus(function() {
- SpecialPowers.pushPrefEnv({"set":[["middlemouse.contentLoadURL", false],
- ["middlemouse.paste", true]]}, startTest);
-});
-function startTest() {
- frameWindow = iframe.contentWindow;
- frameDocument = iframe.contentDocument;
-
- frameDocument.getElementById("input").addEventListener("click", clickEventHandler, false);
- frameDocument.getElementById("editor1").addEventListener("click", clickEventHandler, false);
- frameDocument.getElementById("editor2").addEventListener("click", clickEventHandler, false);
-
- var text = frameDocument.getElementById("text");
-
- text.focus();
- if (navigator.platform.indexOf("Linux") == 0) {
- synthesizeKey("a", { altKey: true }, frameWindow);
- } else {
- synthesizeKey("a", { accelKey: true }, frameWindow);
- }
- // Windows and Mac don't have primary selection, we should copy the text to
- // the global clipboard.
- if (!SpecialPowers.supportsSelectionClipboard()) {
- SimpleTest.waitForClipboard("pasted",
- function() { synthesizeKey("c", { accelKey: true }, frameWindow); },
- function() { SimpleTest.executeSoon(runInputTests1) },
- cleanup);
- } else {
- // Otherwise, don't call waitForClipboard since it breaks primary
- // selection.
- runInputTests1();
- }
-}
-
-function runInputTests1()
-{
- var input = frameDocument.getElementById("input");
-
- // first, copy text.
-
- // when middle clicked in focused input element, text should be pasted.
- input.value = "";
- input.focus();
-
- SimpleTest.executeSoon(function() {
- gClicked = false;
- gClicking = input;
- gDoPreventDefault1 = null;
- gDoPreventDefault2 = null;
-
- synthesizeMouseAtCenter(input, {button: 1}, frameWindow);
-
- SimpleTest.executeSoon(function() {
- todo(gClicked, "click event hasn't been fired for runInputTests1");
- is(input.value, "pasted", "failed to paste in input element");
-
- SimpleTest.executeSoon(runInputTests2);
- });
- });
-}
-
-function runInputTests2()
-{
- var input = frameDocument.getElementById("input");
-
- // even if the input element hasn't had focus, middle click should set focus
- // to it and paste the text.
- input.value = "";
- input.blur();
-
- SimpleTest.executeSoon(function() {
- gClicked = false;
- gClicking = input;
- gDoPreventDefault1 = null;
- gDoPreventDefault2 = null;
-
- synthesizeMouseAtCenter(input, {button: 1}, frameWindow);
-
- SimpleTest.executeSoon(function() {
- todo(gClicked, "click event hasn't been fired for runInputTests2");
- is(input.value, "pasted",
- "failed to paste in input element when it hasn't had focus yet");
-
- SimpleTest.executeSoon(runInputTests3);
- });
- });
-}
-
-function runInputTests3()
-{
- var input = frameDocument.getElementById("input");
- var editor1 = frameDocument.getElementById("editor1");
-
- // preventDefault() of HTML editor's click event handler shouldn't prevent
- // middle click pasting in input element.
- input.value = "";
- input.focus();
-
- SimpleTest.executeSoon(function() {
- gClicked = false;
- gClicking = input;
- gDoPreventDefault1 = editor1;
- gDoPreventDefault2 = null;
-
- synthesizeMouseAtCenter(input, {button: 1}, frameWindow);
-
- SimpleTest.executeSoon(function() {
- todo(gClicked, "click event hasn't been fired for runInputTests3");
- is(input.value, "pasted",
- "failed to paste in input element when editor1 does preventDefault()");
-
- SimpleTest.executeSoon(runInputTests4);
- });
- });
-}
-
-function runInputTests4()
-{
- var input = frameDocument.getElementById("input");
- var editor1 = frameDocument.getElementById("editor1");
-
- // preventDefault() of input element's click event handler should prevent
- // middle click pasting in it.
- input.value = "";
- input.focus();
-
- SimpleTest.executeSoon(function() {
- gClicked = false;
- gClicking = input;
- gDoPreventDefault1 = input;
- gDoPreventDefault2 = null;
-
- synthesizeMouseAtCenter(input, {button: 1}, frameWindow);
-
- SimpleTest.executeSoon(function() {
- todo(gClicked, "click event hasn't been fired for runInputTests4");
- todo_is(input.value, "",
- "pasted in input element when it does preventDefault()");
-
- SimpleTest.executeSoon(runContentEditableTests1);
- });
- });
-}
-
-function runContentEditableTests1()
-{
- var editor1 = frameDocument.getElementById("editor1");
-
- // when middle clicked in focused contentediable editor, text should be
- // pasted.
- editor1.innerHTML = "editor1:";
- editor1.focus();
-
- SimpleTest.executeSoon(function() {
- gClicked = false;
- gClicking = editor1;
- gDoPreventDefault1 = null;
- gDoPreventDefault2 = null;
-
- synthesizeMouseAtCenter(editor1, {button: 1}, frameWindow);
-
- SimpleTest.executeSoon(function() {
- todo(gClicked, "click event hasn't been fired for runContentEditableTests1");
- is(editor1.innerHTML, "editor1:pasted",
- "failed to paste text in contenteditable editor");
- SimpleTest.executeSoon(runContentEditableTests2);
- });
- });
-}
-
-function runContentEditableTests2()
-{
- var editor1 = frameDocument.getElementById("editor1");
-
- // even if the contenteditable editor hasn't had focus, middle click should
- // set focus to it and paste the text.
- editor1.innerHTML = "editor1:";
- editor1.blur();
-
- SimpleTest.executeSoon(function() {
- gClicked = false;
- gClicking = editor1;
- gDoPreventDefault1 = null;
- gDoPreventDefault2 = null;
-
- synthesizeMouseAtCenter(editor1, {button: 1}, frameWindow);
-
- SimpleTest.executeSoon(function() {
- todo(gClicked, "click event hasn't been fired for runContentEditableTests2");
- is(editor1.innerHTML, "editor1:pasted",
- "failed to paste in contenteditable editor #1 when it hasn't had focus yet");
- SimpleTest.executeSoon(runContentEditableTests3);
- });
- });
-}
-
-function runContentEditableTests3()
-{
- var editor1 = frameDocument.getElementById("editor1");
- var editor2 = frameDocument.getElementById("editor2");
-
- // When editor1 has focus but editor2 is middle clicked, should be pasted
- // in the editor2.
- editor1.innerHTML = "editor1:";
- editor2.innerHTML = "editor2:";
- editor1.focus();
-
- SimpleTest.executeSoon(function() {
- gClicked = false;
- gClicking = editor2;
- gDoPreventDefault1 = null;
- gDoPreventDefault2 = null;
-
- synthesizeMouseAtCenter(editor2, {button: 1}, frameWindow);
-
- SimpleTest.executeSoon(function() {
- todo(gClicked, "click event hasn't been fired for runContentEditableTests3");
- is(editor1.innerHTML, "editor1:",
- "pasted in contenteditable editor #1 when editor2 is clicked");
- is(editor2.innerHTML, "editor2:pasted",
- "failed to paste in contenteditable editor #2 when editor2 is clicked");
- SimpleTest.executeSoon(runContentEditableTests4);
- });
- });
-}
-
-function runContentEditableTests4()
-{
- var editor1 = frameDocument.getElementById("editor1");
-
- // preventDefault() of editor1's click event handler should prevent
- // middle click pasting in it.
- editor1.innerHTML = "editor1:";
- editor1.focus();
-
- SimpleTest.executeSoon(function() {
- gClicked = false;
- gClicking = editor1;
- gDoPreventDefault1 = editor1;
- gDoPreventDefault2 = null;
-
- synthesizeMouseAtCenter(editor1, {button: 1}, frameWindow);
-
- SimpleTest.executeSoon(function() {
- todo(gClicked, "click event hasn't been fired for runContentEditableTests4");
- todo_is(editor1.innerHTML, "editor1:",
- "pasted in contenteditable editor #1 when it does preventDefault()");
- SimpleTest.executeSoon(runContentEditableTests5);
- });
- });
-}
-
-function runContentEditableTests5()
-{
- var editor1 = frameDocument.getElementById("editor1");
- var editor2 = frameDocument.getElementById("editor2");
-
- // preventDefault() of editor1's click event handler shouldn't prevent
- // middle click pasting in editor2.
- editor1.innerHTML = "editor1:";
- editor2.innerHTML = "editor2:";
- editor2.focus();
-
- SimpleTest.executeSoon(function() {
- gClicked = false;
- gClicking = editor2;
- gDoPreventDefault1 = editor1;
- gDoPreventDefault2 = null;
-
- synthesizeMouseAtCenter(editor2, {button: 1}, frameWindow);
-
- SimpleTest.executeSoon(function() {
- todo(gClicked, "click event hasn't been fired for runContentEditableTests5");
- is(editor1.innerHTML, "editor1:",
- "pasted in contenteditable editor #1?");
- is(editor2.innerHTML, "editor2:pasted",
- "failed to paste in contenteditable editor #2");
-
- SimpleTest.executeSoon(initForBodyEditableDocumentTests);
- });
- });
-}
-
-function initForBodyEditableDocumentTests()
-{
- frameDocument.getElementById("input").removeEventListener("click", clickEventHandler, false);
- frameDocument.getElementById("editor1").removeEventListener("click", clickEventHandler, false);
- frameDocument.getElementById("editor2").removeEventListener("click", clickEventHandler, false);
-
- iframe.onload =
- function (aEvent) { SimpleTest.executeSoon(runBodyEditableDocumentTests1); };
- iframe.src =
- "data:text/html,<body contenteditable>body:</body>";
-}
-
-function runBodyEditableDocumentTests1()
-{
- frameWindow = iframe.contentWindow;
- frameDocument = iframe.contentDocument;
-
- var body = frameDocument.body;
-
- is(body.innerHTML, "body:",
- "failed to initialize at runBodyEditableDocumentTests1");
-
- // middle click on html element should cause pasting text in its body.
- synthesizeMouseAtCenter(frameDocument.documentElement, {button: 1}, frameWindow);
-
- SimpleTest.executeSoon(function() {
- is(body.innerHTML,
- "body:pasted",
- "failed to paste in editable body element when clicked on html element");
-
- SimpleTest.executeSoon(runBodyEditableDocumentTests2);
- });
-}
-
-function runBodyEditableDocumentTests2()
-{
- frameDocument.body.innerHTML = "body:<span id='span' contenteditable='false'>non-editable</span>";
-
- var body = frameDocument.body;
-
- is(body.innerHTML, "body:<span id=\"span\" contenteditable=\"false\">non-editable</span>",
- "failed to initialize at runBodyEditableDocumentTests2");
-
- synthesizeMouseAtCenter(frameDocument.getElementById("span"), {button: 1}, frameWindow);
-
- SimpleTest.executeSoon(function() {
- is(body.innerHTML,
- "body:<span id=\"span\" contenteditable=\"false\">non-editable</span>",
- "pasted when middle clicked in non-editable element");
-
- SimpleTest.executeSoon(cleanup);
- });
-}
-
-function cleanup()
-{
- SimpleTest.finish();
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug674861.html b/editor/libeditor/tests/test_bug674861.html
deleted file mode 100644
index 5974b4aed..000000000
--- a/editor/libeditor/tests/test_bug674861.html
+++ /dev/null
@@ -1,185 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=674861
--->
-<head>
- <title>Test for Bug 674861</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=674861">Mozilla Bug 674861</a>
-<p id="display"></p>
-<div id="content">
- <section id="test1">
- <h2> Editable Bullet List </h2>
- <ul contenteditable>
- <li> item A </li>
- <li> item B </li>
- <li> item C </li>
- </ul>
-
- <h2> Editable Ordered List </h2>
- <ol contenteditable>
- <li> item A </li>
- <li> item B </li>
- <li> item C </li>
- </ol>
-
- <h2> Editable Definition List </h2>
- <dl contenteditable>
- <dt> term A </dt>
- <dd> definition A </dd>
- <dt> term B </dt>
- <dd> definition B </dd>
- <dt> term C </dt>
- <dd> definition C </dd>
- </dl>
- </section>
-
- <section id="test2" contenteditable>
- <h2> Bullet List In Editable Section </h2>
- <ul>
- <li> item A </li>
- <li> item B </li>
- <li> item C </li>
- </ul>
-
- <h2> Ordered List In Editable Section </h2>
- <ol>
- <li> item A </li>
- <li> item B </li>
- <li> item C </li>
- </ol>
-
- <h2> Definition List In Editable Section </h2>
- <dl>
- <dt> term A </dt>
- <dd> definition A </dd>
- <dt> term B </dt>
- <dd> definition B </dd>
- <dt> term C </dt>
- <dd> definition C </dd>
- </dl>
- </section>
-</div>
-
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 674861 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTests);
-
-const CARET_BEGIN = 0;
-const CARET_MIDDLE = 1;
-const CARET_END = 2;
-
-function try2split(element, caretPos) {
- // compute the requested position
- var len = element.textContent.length;
- var pos = -1;
- switch (caretPos) {
- case CARET_BEGIN:
- pos = 0;
- break;
- case CARET_MIDDLE:
- pos = Math.floor(len/2);
- break;
- case CARET_END:
- pos = len;
- break;
- }
-
- // put the caret on the requested position
- var sel = window.getSelection();
- for (var i = 0; i < sel.rangeCount; i++) {
- var range = sel.getRangeAt(i);
- sel.removeRange(range);
- }
- range = document.createRange();
- range.setStart(element.firstChild, pos);
- range.setEnd(element.firstChild, pos);
- sel.addRange(range);
-
- // simulates two [Return] keypresses
- synthesizeKey("VK_RETURN", {});
- synthesizeKey("VK_RETURN", {});
-}
-
-function runTests() {
- const test1 = document.getElementById("test1");
- const test2 = document.getElementById("test2");
-
- // -----------------------------------------------------------------------
- // #test1: editable lists should NOT be splittable
- // -----------------------------------------------------------------------
- const ul = test1.querySelector("ul");
- const ol = test1.querySelector("ol");
- const dl = test1.querySelector("dl");
-
- // bullet list
- ul.focus();
- try2split(ul.querySelector("li"), CARET_END);
- is(test1.querySelectorAll("ul").length, 1,
- "The <ul contenteditable> list should not be splittable.");
- is(ul.querySelectorAll("li").length, 5,
- "Two new <li> elements should have been created.");
-
- // ordered list
- ol.focus();
- try2split(ol.querySelector("li"), CARET_END);
- is(test1.querySelectorAll("ol").length, 1,
- "The <ol contenteditable> list should not be splittable.");
- is(ol.querySelectorAll("li").length, 5,
- "Two new <li> elements should have been created.");
-
- // definition list
- dl.focus();
- try2split(dl.querySelector("dd"), CARET_END);
- is(test1.querySelectorAll("dl").length, 1,
- "The <dl contenteditable> list should not be splittable.");
- is(dl.querySelectorAll("dt").length, 5,
- "Two new <dt> elements should have been created.");
-
- // -----------------------------------------------------------------------
- // #test2: lists in editable blocks should be splittable
- // -----------------------------------------------------------------------
- test2.focus();
-
- // bullet list
- try2split(test2.querySelector("ul li"), CARET_END);
- is(test2.querySelectorAll("ul").length, 2,
- "The <ul> list should have been splitted.");
- is(test2.querySelectorAll("ul li").length, 3,
- "No new <li> element should have been created.");
- is(test2.querySelectorAll("ul+p").length, 1,
- "A new paragraph should have been created.");
-
- // ordered list
- try2split(test2.querySelector("ol li"), CARET_END);
- is(test2.querySelectorAll("ol").length, 2,
- "The <ol> list should have been splitted.");
- is(test2.querySelectorAll("ol li").length, 3,
- "No new <li> element should have been created.");
- is(test2.querySelectorAll("ol+p").length, 1,
- "A new paragraph should have been created.");
-
- // definition list
- try2split(test2.querySelector("dl dd"), CARET_END);
- is(test2.querySelectorAll("dl").length, 2,
- "The <dl> list should have been splitted.");
- is(test2.querySelectorAll("dt").length, 3,
- "No new <dt> element should have been created.");
- is(test2.querySelectorAll("dl+p").length, 1,
- "A new paragraph should have been created.");
-
- // done
- SimpleTest.finish();
-}
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug676401.html b/editor/libeditor/tests/test_bug676401.html
deleted file mode 100644
index aa468fdc6..000000000
--- a/editor/libeditor/tests/test_bug676401.html
+++ /dev/null
@@ -1,119 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=676401
--->
-<head>
- <title>Test for Bug 676401</title>
- <script type="application/javascript" src="/MochiKit/packed.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=676401">Mozilla Bug 676401</a>
-<p id="display"></p>
-<div id="content">
- <!-- we need a blockquote to test the "outdent" command -->
- <section>
- <blockquote> not editable </blockquote>
- </section>
- <section contenteditable>
- <blockquote> editable </blockquote>
- </section>
-</div>
-
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 676401 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTests);
-
-var gBlock1, gBlock2;
-
-var alwaysEnabledCommands = [
- "contentReadOnly",
- "copy",
- "cut",
- "enableInlineTableEditing",
- "enableObjectResizing",
- "insertBrOnReturn",
- "selectAll",
- "styleWithCSS",
-];
-
-function IsCommandEnabled(command) {
- var enabled;
-
- // non-editable div: should return false unless alwaysEnabled
- window.getSelection().selectAllChildren(gBlock1);
- enabled = document.queryCommandEnabled(command);
- is(enabled, alwaysEnabledCommands.indexOf(command) != -1,
- "'" + command + "' should not be enabled on a non-editable block.");
-
- // editable div: should return true
- window.getSelection().selectAllChildren(gBlock2);
- enabled = document.queryCommandEnabled(command);
- is(enabled, true, "'" + command + "' should be enabled on an editable block.");
-}
-
-function runTests() {
- var i, commands;
- gBlock1 = document.querySelector("#content section blockquote");
- gBlock2 = document.querySelector("#content [contenteditable] blockquote");
-
- // common commands: test with and without "styleWithCSS"
- commands = [
- "bold", "italic", "underline", "strikeThrough",
- "subscript", "superscript", "foreColor", "backColor", "hiliteColor",
- "fontName", "fontSize",
- "justifyLeft", "justifyCenter", "justifyRight", "justifyFull",
- "indent", "outdent",
- "insertOrderedList", "insertUnorderedList", "insertParagraph",
- "heading", "formatBlock",
- "contentReadOnly", "createLink",
- "decreaseFontSize", "increaseFontSize",
- "insertHTML", "insertHorizontalRule", "insertImage",
- "removeFormat", "selectAll", "styleWithCSS"
- ];
- document.execCommand("styleWithCSS", false, false);
- for (i = 0; i < commands.length; i++)
- IsCommandEnabled(commands[i]);
- document.execCommand("styleWithCSS", false, true);
- for (i = 0; i < commands.length; i++)
- IsCommandEnabled(commands[i]);
-
- // Mozilla-specific stuff
- commands = ["enableInlineTableEditing", "enableObjectResizing", "insertBrOnReturn"];
- for (i = 0; i < commands.length; i++)
- IsCommandEnabled(commands[i]);
-
- // These are privileged, and available only to chrome.
- commands = ["paste"];
- for (i = 0; i < commands.length; i++) {
- is(document.queryCommandEnabled(commands[i]), false,
- "Command should not be enabled for non-privileged code");
- is(SpecialPowers.wrap(document).queryCommandEnabled(commands[i]), true,
- "Command should be enabled for privileged code");
- is(document.execCommand(commands[i], false, false), false, "Should return false: " + commands[i]);
- is(SpecialPowers.wrap(document).execCommand(commands[i], false, false), true, "Should return true: " + commands[i]);
- }
-
- // delete/undo/redo -- we have to execute this commands because:
- // * there's nothing to undo if we haven't modified the selection first
- // * there's nothing to redo if we haven't undone something first
- commands = ["delete", "undo", "redo"];
- for (i = 0; i < commands.length; i++) {
- IsCommandEnabled(commands[i]);
- document.execCommand(commands[i], false, false);
- }
-
- // done
- SimpleTest.finish();
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug677752.html b/editor/libeditor/tests/test_bug677752.html
deleted file mode 100644
index 8809c1ead..000000000
--- a/editor/libeditor/tests/test_bug677752.html
+++ /dev/null
@@ -1,107 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=677752
--->
-<head>
- <title>Test for Bug 677752</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677752">Mozilla Bug 677752</a>
-<p id="display"></p>
-<div id="content">
- <section contenteditable> foo bar </section>
- <div contenteditable> foo bar </div>
- <p contenteditable> foo bar </p>
-</div>
-
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 677752 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTests);
-
-function selectEditor(aEditor) {
- aEditor.focus();
- var selection = window.getSelection();
- selection.selectAllChildren(aEditor);
- selection.collapseToStart();
-}
-
-function runTests() {
- var editor, node, initialHTML;
- document.execCommand('styleWithCSS', false, true);
-
- // editable <section>
- editor = document.querySelector("section[contenteditable]");
- initialHTML = editor.innerHTML;
- selectEditor(editor);
- // editable <section>: justify
- document.execCommand("justifyright", false, null);
- node = editor.querySelector("*");
- is(node.nodeName.toLowerCase(), "div", "'justifyright' should create a <div> in the editable <section>.");
- is(node.style.textAlign, "right", "'justifyright' should create a 'text-align: right' CSS rule.");
- document.execCommand("undo", false, null);
- // editable <section>: indent
- document.execCommand("indent", false, null);
- node = editor.querySelector("*");
- is(node.nodeName.toLowerCase(), "div", "'indent' should create a <div> in the editable <section>.");
- is(node.style.marginLeft, "40px", "'indent' should create a 'margin-left: 40px' CSS rule.");
- // editable <section>: undo with outdent
- // this should remove the whole <div> but only removing the CSS rule would be acceptable, too
- document.execCommand("outdent", false, null);
- is(editor.innerHTML, initialHTML, "'outdent' should undo the 'indent' action.");
- // editable <section>: outdent again
- document.execCommand("outdent", false, null);
- is(editor.innerHTML, initialHTML, "another 'outdent' should not modify the <section> element.");
-
- // editable <div>
- editor = document.querySelector("div[contenteditable]");
- initialHTML = editor.innerHTML;
- selectEditor(editor);
- // editable <div>: justify
- document.execCommand("justifyright", false, null);
- node = editor.querySelector("*");
- is(node.nodeName.toLowerCase(), "div", "'justifyright' should create a <div> in the editable <div>.");
- is(node.style.textAlign, "right", "'justifyright' should create a 'text-align: right' CSS rule.");
- document.execCommand("undo", false, null);
- // editable <div>: indent
- document.execCommand("indent", false, null);
- node = editor.querySelector("*");
- is(node.nodeName.toLowerCase(), "div", "'indent' should create a <div> in the editable <div>.");
- is(node.style.marginLeft, "40px", "'indent' should create a 'margin-left: 40px' CSS rule.");
- // editable <div>: undo with outdent
- // this should remove the whole <div> but only removing the CSS rule would be acceptable, too
- document.execCommand("outdent", false, null);
- is(editor.innerHTML, initialHTML, "'outdent' should undo the 'indent' action.");
- // editable <div>: outdent again
- document.execCommand("outdent", false, null);
- is(editor.innerHTML, initialHTML, "another 'outdent' should not modify the <div> element.");
-
- // editable <p>
- // all block-level commands should be ignored (<p><div/></p> is not valid)
- editor = document.querySelector("p[contenteditable]");
- initialHTML = editor.innerHTML;
- selectEditor(editor);
- // editable <p>: justify
- document.execCommand("justifyright", false, null);
- is(editor.innerHTML, initialHTML, "'justifyright' should have no effect on <p>.");
- // editable <p>: indent
- document.execCommand("indent", false, null);
- is(editor.innerHTML, initialHTML, "'indent' should have no effect on <p>.");
- // editable <p>: outdent
- document.execCommand("outdent", false, null);
- is(editor.innerHTML, initialHTML, "'outdent' should have no effect on <p>.");
-
- // done
- SimpleTest.finish();
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug681229.html b/editor/libeditor/tests/test_bug681229.html
deleted file mode 100644
index 6debcfde7..000000000
--- a/editor/libeditor/tests/test_bug681229.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=681229
--->
-<head>
- <title>Test for Bug 681229</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=681229">Mozilla Bug 681229</a>
-<p id="display"></p>
-<div id="content">
-<textarea spellcheck="false"></textarea>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 681229 **/
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var t = document.querySelector("textarea");
- t.focus();
-
- const kValue = "a\r\nb";
- const kExpectedValue = (navigator.platform.indexOf("Win") == 0) ?
- "a\nb" : kValue;
-
- SimpleTest.waitForClipboard(kExpectedValue,
- function() {
- SpecialPowers.clipboardCopyString(kValue);
- },
- function() {
- synthesizeKey("V", {accelKey: true});
- is(t.value, "a\nb", "The carriage return has been correctly sanitized");
- SimpleTest.finish();
- },
- function() {
- SimpleTest.finish();
- }
- );
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug686203.html b/editor/libeditor/tests/test_bug686203.html
deleted file mode 100644
index c1a856aae..000000000
--- a/editor/libeditor/tests/test_bug686203.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE HTML>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this file,
- - You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=686203
--->
-
-<head>
- <title>Test for Bug 686203</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-
-<body>
- <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=686203">Mozilla Bug 686203</a>
- <p id="display"></p>
- <div id="content" style="display: none">
- </div>
-
- <pre id="test">
- <script type="application/javascript">
-
- /** Test for Bug 686203 **/
- SimpleTest.waitForExplicitFinish();
- SimpleTest.waitForFocus(function() {
- var ce = document.getElementById("ce");
- var input = document.getElementById("input");
- ce.focus();
-
- var eventDetails = { button : 2 };
- synthesizeMouseAtCenter(input, eventDetails);
-
- synthesizeKey("Z", {});
-
- /* check values */
- is(input.value, "Z", "input correctly focused after right-click");
- is(ce.textContent, "abc", "contenteditable correctly blurred after right-click on input");
-
- SimpleTest.finish();
- });
- </script>
- </pre>
-
- <input type="text" value="" id="input" />
- <div id="ce" contenteditable="true">abc</div>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug692520.html b/editor/libeditor/tests/test_bug692520.html
deleted file mode 100644
index 6dfefd8db..000000000
--- a/editor/libeditor/tests/test_bug692520.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=692520
--->
-<head>
- <title>Test for Bug 692520</title>
- <script type="application/javascript" src="/MochiKit/packed.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=692520">Mozilla Bug 692520</a>
-<p id="display"></p>
-<div id="content">
-<textarea></textarea>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 692520 **/
-function test(prop, value) {
- var t = document.querySelector("textarea");
- t.value = "testing";
- t.selectionStart = 1;
- t.selectionEnd = 3;
- t.selectionDirection = "backward";
- t.style.display = "";
- document.body.clientWidth;
- t.style.display = "none";
- is(t[prop], value, "Correct value for the " + prop + " property");
-}
-
-test("selectionStart", 1);
-test("selectionEnd", 3);
-test("selectionDirection", "backward");
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug697842.html b/editor/libeditor/tests/test_bug697842.html
deleted file mode 100644
index 463ff76dc..000000000
--- a/editor/libeditor/tests/test_bug697842.html
+++ /dev/null
@@ -1,117 +0,0 @@
-<!DOCTYPE>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=697842
--->
-<head>
- <title>Test for Bug 697842</title>
- <script type="application/javascript" src="/MochiKit/packed.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css"
- href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-</head>
-<body>
-<div id="display">
- <p id="editor" contenteditable style="min-height: 1.5em;"></p>
-</div>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-</pre>
-
-<script class="testbody" type="application/javascript">
-
-/** Test for Bug 697842 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTests);
-
-function runTests()
-{
- var editor = document.getElementById("editor");
- editor.focus();
-
- SimpleTest.executeSoon(function() {
- var composingString = "";
-
- function handler(aEvent) {
- switch (aEvent.type) {
- case "compositionstart":
- // Selected string at starting composition must be empty in this test.
- is(aEvent.data, "", "mismatch selected string");
- break;
- case "compositionupdate":
- case "compositionend":
- is(aEvent.data, composingString, "mismatch composition string");
- break;
- default:
- break;
- }
- aEvent.stopPropagation();
- aEvent.preventDefault();
- }
-
- editor.addEventListener("compositionstart", handler, true);
- editor.addEventListener("compositionend", handler, true);
- editor.addEventListener("compositionupdate", handler, true);
- editor.addEventListener("text", handler, true);
-
- // input first character
- composingString = "\u306B";
- synthesizeCompositionChange(
- { "composition":
- { "string": composingString,
- "clauses":
- [
- { "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
- ]
- },
- "caret": { "start": 1, "length": 0 }
- });
-
- // input second character
- composingString = "\u306B\u3085";
- synthesizeCompositionChange(
- { "composition":
- { "string": composingString,
- "clauses":
- [
- { "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
- ]
- },
- "caret": { "start": 2, "length": 0 }
- });
-
- // convert them
- synthesizeCompositionChange(
- { "composition":
- { "string": composingString,
- "clauses":
- [
- { "length": 2,
- "attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
- ]
- },
- "caret": { "start": 2, "length": 0 }
- });
-
- synthesizeComposition({ type: "compositioncommitasis" });
-
- is(editor.innerHTML, composingString,
- "editor has unexpected result");
-
- editor.removeEventListener("compositionstart", handler, true);
- editor.removeEventListener("compositionend", handler, true);
- editor.removeEventListener("compositionupdate", handler, true);
- editor.removeEventListener("text", handler, true);
-
- SimpleTest.finish();
- });
-}
-
-
-</script>
-</body>
-
-</html>
diff --git a/editor/libeditor/tests/test_bug725069.html b/editor/libeditor/tests/test_bug725069.html
deleted file mode 100644
index 5096ede3c..000000000
--- a/editor/libeditor/tests/test_bug725069.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=725069
--->
-<head>
- <title>Test for Bug 725069</title>
- <script type="application/javascript" src="/MochiKit/packed.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body contenteditable>abc<!-- XXX -->def<span></span>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=725069">Mozilla Bug 725069</a>
-<p id="display"></p>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 725069 **/
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(function() {
- var body = document.querySelector("body");
- is(body.firstChild.nodeType, body.TEXT_NODE, "The first node is a text node");
- is(body.firstChild.nodeValue, "abc", "The first text node is there");
- is(body.firstChild.nextSibling.nodeType, body.COMMENT_NODE, "The second node is a comment node");
- is(body.firstChild.nextSibling.nodeValue, " XXX ", "The value of the comment node is not changed");
- is(body.firstChild.nextSibling.nextSibling.nodeType, body.TEXT_NODE, "The last text node is a text node");
- is(body.firstChild.nextSibling.nextSibling.nodeValue, "def", "The last next node is there");
- SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug735059.html b/editor/libeditor/tests/test_bug735059.html
deleted file mode 100644
index 3b81ce48b..000000000
--- a/editor/libeditor/tests/test_bug735059.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=735059
--->
-<title>Test for Bug 735059</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=735059">Mozilla Bug 735059</a>
-<div id="display" contenteditable>foo</div>
-<pre id="test">
-<script>
-/** Test for Bug 735059 **/
-
-// Value defaults to the empty string, which evaluates to true, so this
-// disables CSS styling
-document.execCommand("usecss");
-getSelection().selectAllChildren(document.getElementById("display"));
-document.execCommand("bold");
-is(document.getElementById("display").innerHTML, "<b>foo</b>",
- "execCommand() needs to work with only one parameter");
-</script>
-</pre>
diff --git a/editor/libeditor/tests/test_bug738366.html b/editor/libeditor/tests/test_bug738366.html
deleted file mode 100644
index a54aec7a2..000000000
--- a/editor/libeditor/tests/test_bug738366.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=738366
--->
-<title>Test for Bug 738366</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=738366">Mozilla Bug 738366</a>
-<div id="display" contenteditable>foobarbaz</div>
-<script>
-/** Test for Bug 738366 **/
-
-getSelection().collapse(document.getElementById("display").firstChild, 3);
-getSelection().extend(document.getElementById("display").firstChild, 6);
-document.execCommand("bold");
-is(document.getElementById("display").innerHTML, "foo<b>bar</b>baz",
- "styleWithCSS must default to false");
-document.execCommand("stylewithcss", false, "true");
-document.execCommand("bold");
-document.execCommand("bold");
-is(document.getElementById("display").innerHTML,
- 'foo<span style="font-weight: bold;">bar</span>baz',
- "styleWithCSS must be settable to true");
-</script>
diff --git a/editor/libeditor/tests/test_bug740784.html b/editor/libeditor/tests/test_bug740784.html
deleted file mode 100644
index 26c918241..000000000
--- a/editor/libeditor/tests/test_bug740784.html
+++ /dev/null
@@ -1,48 +0,0 @@
-<!DOCTYPE HTML>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this file,
- - You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=740784
--->
-
-<head>
- <title>Test for Bug 740784</title>
- <script type="application/javascript" src="/MochiKit/packed.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
-</head>
-
-<body>
- <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=740784">Mozilla Bug 740784</a>
- <p id="display"></p>
- <div id="content" style="display: none">
- </div>
-
- <pre id="test">
- <script type="application/javascript">
-
- /** Test for Bug 740784 **/
-
- SimpleTest.waitForExplicitFinish();
- SimpleTest.waitForFocus(function() {
- var t1 = $("t1");
-
- t1.focus();
- synthesizeKey("VK_END", {});
- synthesizeKey("VK_BACK_SPACE", {});
- synthesizeKey("Z", {accelKey: true});
-
- // Was the former bogus node changed to a mozBR?
- is(t1.value, "a", "trailing <br> correctly ignored");
-
- SimpleTest.finish();
- });
- </script>
- </pre>
-
- <textarea id="t1" rows="2" columns="80">a</textarea>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug742261.html b/editor/libeditor/tests/test_bug742261.html
deleted file mode 100644
index 9ad41dd52..000000000
--- a/editor/libeditor/tests/test_bug742261.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!doctype html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=742261
--->
-<title>Test for Bug 742261</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
-<body>
-<script>
-is(document.execCommandShowHelp, undefined,
- "execCommandShowHelp shouldn't exist");
-is(document.queryCommandText, undefined,
- "queryCommandText shouldn't exist");
-</script>
diff --git a/editor/libeditor/tests/test_bug757371.html b/editor/libeditor/tests/test_bug757371.html
deleted file mode 100644
index 5ca41a595..000000000
--- a/editor/libeditor/tests/test_bug757371.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=757371
--->
-<title>Test for Bug 757371</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<script src="/tests/SimpleTest/EventUtils.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=757371">Mozilla Bug 757371</a>
-<div contenteditable></div>
-<script>
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var div = document.querySelector("div");
- div.focus();
- getSelection().collapse(div, 0);
- document.execCommand("bold");
- sendString("ab");
- sendKey("BACK_SPACE");
- sendChar("b");
-
- is(div.innerHTML, "<b>ab</b>");
-
- SimpleTest.finish();
-});
-</script>
diff --git a/editor/libeditor/tests/test_bug757771.html b/editor/libeditor/tests/test_bug757771.html
deleted file mode 100644
index 9ef980b66..000000000
--- a/editor/libeditor/tests/test_bug757771.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=757771
--->
-<title>Test for Bug 757771</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<script src="/tests/SimpleTest/EventUtils.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css">
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=757771">Mozilla Bug 757771</a>
-<input value=foo maxlength=4>
-<input type=password value=password>
-<script>
-/** Test for Bug 757771 **/
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var textInput = document.querySelector("input");
- textInput.focus();
- textInput.select();
- sendString("abcde");
-
- var passwordInput = document.querySelector("input + input");
- passwordInput.focus();
- passwordInput.select();
- sendString("hunter2");
-
- ok(true, "No real tests, just crashes/asserts");
-
- SimpleTest.finish();
-});
-</script>
diff --git a/editor/libeditor/tests/test_bug767684.html b/editor/libeditor/tests/test_bug767684.html
deleted file mode 100644
index 0e65a88a7..000000000
--- a/editor/libeditor/tests/test_bug767684.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=767684
--->
-<title>Test for Bug 767684</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css">
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=767684">Mozilla Bug 767684</a>
-<div contenteditable>foo<b>bar</b>baz</div>
-<script>
-getSelection().selectAllChildren(document.querySelector("div"));
-document.execCommand("increaseFontSize");
-is(document.querySelector("div").innerHTML, "<big>foo<b>bar</b>baz</big>",
- "All selected text must be embiggened");
-</script>
diff --git a/editor/libeditor/tests/test_bug772796.html b/editor/libeditor/tests/test_bug772796.html
deleted file mode 100644
index 9a15dccd2..000000000
--- a/editor/libeditor/tests/test_bug772796.html
+++ /dev/null
@@ -1,223 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=772796
--->
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 772796</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <style> .pre { white-space: pre } </style>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=772796">Mozilla Bug 772796</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-
-<div id="editable" contenteditable></div>
-
-<pre id="test">
-
- <script type="application/javascript">
- var tests = [
-/*00*/[ "<div>test</div><pre>foobar\nbaz</pre>", "<div>testfoobar\n</div><pre>baz</pre>" ],
-/*01*/[ "<div>test</div><pre><b>foobar\nbaz</b></pre>", "<div>test<b>foobar\n</b></div><pre><b>baz</b></pre>" ],
-/*02*/[ "<div>test</div><pre><b>foo</b>bar\nbaz</pre>", "<div>test<b>foo</b>bar\n</div><pre>baz</pre>" ],
-/*03*/[ "<div>test</div><pre><b>foo</b>\nbar</pre>", "<div>test<b>foo</b>\n</div><pre>bar</pre>" ],
-/*04*/[ "<div>test</div><pre><b>foo\n</b>bar\nbaz</pre>", "<div>test<b>foo\n</b></div><pre>bar\nbaz</pre>" ],
- /* The <br> after the foobar is unfortunate but is behaviour that hasn't changed in bug 772796. */
-/*05*/[ "<div>test</div><pre>foobar<br>baz</pre>", "<div>testfoobar<br></div><pre>baz</pre>" ],
-/*06*/[ "<div>test</div><pre><b>foobar<br>baz</b></pre>", "<div>test<b>foobar</b><br></div><pre><b>baz</b></pre>" ],
-
- /*
- * Some tests with block elements.
- * Tests 07, 09 and 11 don't use "MoveBlock", they use "JoinNodesSmart".
- * Test 11 is a pain: <div>foo\bar</div> is be joined to "test", losing the visible line break.
- */
-/*07*/[ "<div>test</div><pre><div>foobar</div>baz</pre>", "<div>testfoobar</div><pre>baz</pre>" ],
-/*08*/[ "<div>test</div><pre>foobar<div>baz</div></pre>", "<div>testfoobar</div><pre><div>baz</div></pre>" ],
-/*09*/[ "<div>test</div><pre><div>foobar</div>baz\nfred</pre>", "<div>testfoobar</div><pre>baz\nfred</pre>" ],
-/*10*/[ "<div>test</div><pre>foobar<div>baz</div>\nfred</pre>", "<div>testfoobar</div><pre><div>baz</div>\nfred</pre>" ],
-/*11*/[ "<div>test</div><pre><div>foo\nbar</div>baz\nfred</pre>", "<div>testfoo\nbar</div><pre>baz\nfred</pre>" ], // BAD
-/*12*/[ "<div>test</div><pre>foo<div>bar</div>baz\nfred</pre>", "<div>testfoo</div><pre><div>bar</div>baz\nfred</pre>" ],
-
- /*
- * Repeating all tests above with the <pre> on a new line.
- * We know that backspace doesn't work (bug 1190161). Third argument shows the current outcome.
- */
-/*13-00*/[ "<div>test</div>\n<pre>foobar\nbaz</pre>", "<div>testfoobar\n</div><pre>baz</pre>",
- "<div>test</div>foobar\n<pre>baz</pre>" ],
-/*14-01*/[ "<div>test</div>\n<pre><b>foobar\nbaz</b></pre>", "<div>test<b>foobar\n</b></div><pre><b>baz</b></pre>",
- "<div>test</div><b>foobar\n</b><pre><b>baz</b></pre>" ],
-/*15-02*/[ "<div>test</div>\n<pre><b>foo</b>bar\nbaz</pre>", "<div>test<b>foo</b>bar\n</div><pre>baz</pre>",
- "<div>test</div><b>foo</b>bar\n<pre>baz</pre>" ],
-/*16-03*/[ "<div>test</div>\n<pre><b>foo</b>\nbar</pre>", "<div>test<b>foo</b>\n</div><pre>bar</pre>",
- "<div>test</div><b>foo</b>\n<pre>bar</pre>" ],
-/*17-04*/[ "<div>test</div>\n<pre><b>foo\n</b>bar\nbaz</pre>", "<div>test<b>foo\n</b></div><pre>bar\nbaz</pre>",
- "<div>test</div><b>foo\n</b><pre>bar\nbaz</pre>" ],
-/*18-05*/[ "<div>test</div>\n<pre>foobar<br>baz</pre>", "<div>testfoobar<br></div><pre>baz</pre>",
- "<div>test</div>foobar<br><pre>baz</pre>" ],
-/*19-06*/[ "<div>test</div>\n<pre><b>foobar<br>baz</b></pre>", "<div>test<b>foobar</b><br></div><pre><b>baz</b></pre>",
- "<div>test</div><b>foobar</b><br><pre><b>baz</b></pre>" ],
-/*20-07*/[ "<div>test</div>\n<pre><div>foobar</div>baz</pre>", "<div>testfoobar</div><pre>baz</pre>",
- "<div>test</div>foobar<pre>baz</pre>" ],
-/*21-08*/[ "<div>test</div>\n<pre>foobar<div>baz</div></pre>", "<div>testfoobar</div><pre><div>baz</div></pre>",
- "<div>test</div>foobar<pre><div>baz</div></pre>" ],
-/*22-09*/[ "<div>test</div>\n<pre><div>foobar</div>baz\nfred</pre>", "<div>testfoobar</div><pre>baz\nfred</pre>",
- "<div>test</div>foobar<pre>baz\nfred</pre>" ],
-/*23-10*/[ "<div>test</div>\n<pre>foobar<div>baz</div>\nfred</pre>", "<div>testfoobar</div><pre><div>baz</div>\nfred</pre>",
- "<div>test</div>foobar<pre><div>baz</div>\nfred</pre>" ],
-/*24-11*/[ "<div>test</div>\n<pre><div>foo\nbar</div>baz\nfred</pre>", "<div>testfoo\nbar</div><pre>baz\nfred</pre>", // BAD
- "<div>test</div>foo\n<pre><div>bar</div>baz\nfred</pre>" ],
-/*25-12*/[ "<div>test</div>\n<pre>foo<div>bar</div>baz\nfred</pre>", "<div>testfoo</div><pre><div>bar</div>baz\nfred</pre>",
- "<div>test</div>foo<pre><div>bar</div>baz\nfred</pre>" ],
-
- /* Some tests without <div>. These exercise the MoveBlock "right in left" */
-/*26-00*/[ "test<pre>foobar\nbaz</pre>", "testfoobar\n<pre>baz</pre>" ],
-/*27-01*/[ "test<pre><b>foobar\nbaz</b></pre>", "test<b>foobar\n</b><pre><b>baz</b></pre>" ],
-/*28-02*/[ "test<pre><b>foo</b>bar\nbaz</pre>", "test<b>foo</b>bar\n<pre>baz</pre>" ],
-/*29-03*/[ "test<pre><b>foo</b>\nbar</pre>", "test<b>foo</b>\n<pre>bar</pre>" ],
-/*30-04*/[ "test<pre><b>foo\n</b>bar\nbaz</pre>", "test<b>foo\n</b><pre>bar\nbaz</pre>" ],
-/*31-05*/[ "test<pre>foobar<br>baz</pre>", "testfoobar<br><pre>baz</pre>" ],
-/*32-06*/[ "test<pre><b>foobar<br>baz</b></pre>", "test<b>foobar</b><br><pre><b>baz</b></pre>" ],
-/*33-07*/[ "test<pre><div>foobar</div>baz</pre>", "testfoobar<pre>baz</pre>" ],
-/*34-08*/[ "test<pre>foobar<div>baz</div></pre>", "testfoobar<pre><div>baz</div></pre>" ],
-/*35-09*/[ "test<pre><div>foobar</div>baz\nfred</pre>", "testfoobar<pre>baz\nfred</pre>" ],
-/*36-10*/[ "test<pre>foobar<div>baz</div>\nfred</pre>", "testfoobar<pre><div>baz</div>\nfred</pre>" ],
-/*37-11*/[ "test<pre><div>foo\nbar</div>baz\nfred</pre>", "testfoo\n<pre><div>bar</div>baz\nfred</pre>" ],
-/*38-12*/[ "test<pre>foo<div>bar</div>baz\nfred</pre>", "testfoo<pre><div>bar</div>baz\nfred</pre>" ],
-
- /*
- * Some tests with <span class="pre">. Again 07, 09 and 11 use "JoinNodesSmart".
- * All these exercise MoveBlock "left in right". The "right" is the surrounding "contenteditable" div.
- */
-/*39-00*/[ "<div>test</div><span class=\"pre\">foobar\nbaz</span>", "<div>test<span class=\"pre\">foobar\n</span></div><span class=\"pre\">baz</span>" ],
-/*40-01*/[ "<div>test</div><span class=\"pre\"><b>foobar\nbaz</b></span>", "<div>test<span class=\"pre\"><b>foobar\n</b></span></div><span class=\"pre\"><b>baz</b></span>" ],
-/*41-02*/[ "<div>test</div><span class=\"pre\"><b>foo</b>bar\nbaz</span>", "<div>test<span class=\"pre\"><b>foo</b>bar\n</span></div><span class=\"pre\">baz</span>" ],
-/*42-03*/[ "<div>test</div><span class=\"pre\"><b>foo</b>\nbar</span>", "<div>test<span class=\"pre\"><b>foo</b>\n</span></div><span class=\"pre\">bar</span>" ],
-/*43-04*/[ "<div>test</div><span class=\"pre\"><b>foo\n</b>bar\nbaz</span>", "<div>test<span class=\"pre\"><b>foo\n</b></span></div><span class=\"pre\">bar\nbaz</span>" ],
-/*44-05*/[ "<div>test</div><span class=\"pre\">foobar<br>baz</span>", "<div>test<span class=\"pre\">foobar</span><br><span class=\"pre\"></span></div><span class=\"pre\">baz</span>" ],
-/*45-06*/[ "<div>test</div><span class=\"pre\"><b>foobar<br>baz</b></span>", "<div>test<span class=\"pre\"><b>foobar</b></span><br><span class=\"pre\"></span></div><span class=\"pre\"><b>baz</b></span>" ],
-/*46-07*/[ "<div>test</div><span class=\"pre\"><div>foobar</div>baz</span>", "<div>testfoobar</div><span class=\"pre\">baz</span>" ],
-/*47-08*/[ "<div>test</div><span class=\"pre\">foobar<div>baz</div></span>", "<div>test<span class=\"pre\">foobar</span></div><span class=\"pre\"><div>baz</div></span>" ],
-/*48-09*/[ "<div>test</div><span class=\"pre\"><div>foobar</div>baz\nfred</span>", "<div>testfoobar</div><span class=\"pre\">baz\nfred</span>" ],
-/*49-10*/[ "<div>test</div><span class=\"pre\">foobar<div>baz</div>\nfred</span>", "<div>test<span class=\"pre\">foobar</span></div><span class=\"pre\"><div>baz</div>\nfred</span>" ],
-/*50-11*/[ "<div>test</div><span class=\"pre\"><div>foo\nbar</div>baz\nfred</span>", "<div>testfoo\nbar</div><span class=\"pre\">baz\nfred</span>" ], // BAD
-/*51-12*/[ "<div>test</div><span class=\"pre\">foo<div>bar</div>baz\nfred</span>", "<div>test<span class=\"pre\">foo</span></div><span class=\"pre\"><div>bar</div>baz\nfred</span>" ],
-
- /* Some tests with <div class="pre">. */
- /*
- * The results are pretty ugly, since joining two <divs> sadly carrys the properties of the right to the left,
- * but not in all cases: 07, 09, 11 are actually right. All cases use "JoinNodesSmart".
- * Here we merely document the ugly behaviour. See bug 1191875 for more information.
- */
-/*52-00*/[ "<div>test</div><div class=\"pre\">foobar\nbaz</div>", "<div class=\"pre\">testfoobar\nbaz</div>" ],
-/*53-01*/[ "<div>test</div><div class=\"pre\"><b>foobar\nbaz</b></div>", "<div class=\"pre\">test<b>foobar\nbaz</b></div>" ],
-/*54-02*/[ "<div>test</div><div class=\"pre\"><b>foo</b>bar\nbaz</div>", "<div class=\"pre\">test<b>foo</b>bar\nbaz</div>" ],
-/*55-03*/[ "<div>test</div><div class=\"pre\"><b>foo</b>\nbar</div>", "<div class=\"pre\">test<b>foo</b>\nbar</div>" ],
-/*56-04*/[ "<div>test</div><div class=\"pre\"><b>foo\n</b>bar\nbaz</div>", "<div class=\"pre\">test<b>foo\n</b>bar\nbaz</div>" ],
-/*57-05*/[ "<div>test</div><div class=\"pre\">foobar<br>baz</div>", "<div class=\"pre\">testfoobar<br>baz</div>" ],
-/*58-06*/[ "<div>test</div><div class=\"pre\"><b>foobar<br>baz</b></div>", "<div class=\"pre\">test<b>foobar<br>baz</b></div>" ],
-/*59-07*/[ "<div>test</div><div class=\"pre\"><div>foobar</div>baz</div>", "<div>testfoobar</div><div class=\"pre\">baz</div>" ],
-/*60-08*/[ "<div>test</div><div class=\"pre\">foobar<div>baz</div></div>", "<div class=\"pre\">testfoobar<div>baz</div></div>" ],
-/*61-09*/[ "<div>test</div><div class=\"pre\"><div>foobar</div>baz\nfred</div>", "<div>testfoobar</div><div class=\"pre\">baz\nfred</div>" ],
-/*62-10*/[ "<div>test</div><div class=\"pre\">foobar<div>baz</div>\nfred</div>", "<div class=\"pre\">testfoobar<div>baz</div>\nfred</div>" ],
-/*63-11*/[ "<div>test</div><div class=\"pre\"><div>foo\nbar</div>baz\nfred</div>", "<div>testfoo\nbar</div><div class=\"pre\">baz\nfred</div>" ], // BAD
-/*64-12*/[ "<div>test</div><div class=\"pre\">foo<div>bar</div>baz\nfred</div>", "<div class=\"pre\">testfoo<div>bar</div>baz\nfred</div>" ],
-
- /* Some tests with lists. These exercise the MoveBlock "left in right". */
-/*65*/[ "<ul><pre><li>test</li>foobar\nbaz</pre></ul>", "<ul><pre><li>testfoobar\n</li>baz</pre></ul>" ],
-/*66*/[ "<ul><pre><li>test</li><b>foobar\nbaz</b></pre></ul>", "<ul><pre><li>test<b>foobar\n</b></li><b>baz</b></pre></ul>" ],
-/*67*/[ "<ul><pre><li>test</li><b>foo</b>bar\nbaz</pre></ul>", "<ul><pre><li>test<b>foo</b>bar\n</li>baz</pre></ul>" ],
-/*68*/[ "<ul><pre><li>test</li><b>foo</b>\nbar</pre></ul>", "<ul><pre><li>test<b>foo</b>\n</li>bar</pre></ul>" ],
-/*69*/[ "<ul><pre><li>test</li><b>foo\n</b>bar\nbaz</pre></ul>", "<ul><pre><li>test<b>foo\n</b></li>bar\nbaz</pre></ul>" ],
-
- /* Last not least, some simple edge case tests. */
-/*70*/[ "<div>test</div><pre>foobar\n</pre>baz", "<div>testfoobar\n</div>baz" ],
-/*71*/[ "<div>test</div><pre>\nfoo\nbar</pre>", "<div>testfoo\n</div><pre>bar</pre>" ],
-/*72*/[ "<div>test</div><pre>\n\nfoo\nbar</pre>", "<div>test</div><pre>foo\nbar</pre>", "<div>test\n</div><pre>foo\nbar</pre>" ],
- ];
-
- /** Test for Bug 772796 **/
-
- SimpleTest.waitForExplicitFinish();
-
- SimpleTest.waitForFocus(function() {
-
- var sel = window.getSelection();
- var theEdit = document.getElementById("editable");
- var testName;
- var theDiv;
-
- for (i = 0; i < tests.length; i++) {
- testName = "test" + i.toString();
- dump (testName+"\n");
- dump (tests[i][0]+"\n");
-
- /* Set up the selection. */
- theEdit.innerHTML = "<div id=\"" + testName + "\">" + tests[i][0] + "</div>";
- theDiv = document.getElementById(testName);
- theDiv.focus();
- sel.collapse(theDiv, 0);
- synthesizeMouse(theDiv, 100, 2, {}); /* click behind and down */
-
- /** First round: Forward delete. **/
- synthesizeKey("VK_DELETE", {});
- is(theDiv.innerHTML, tests[i][1], "delete(collapsed): inner HTML for " + testName);
-
- /* Set up the selection. */
- theEdit.innerHTML = "<div id=\"" + testName + "\">" + tests[i][0] + "</div>";
- theDiv = document.getElementById(testName);
- theDiv.focus();
- sel.collapse(theDiv, 0);
- synthesizeMouse(theDiv, 100, 2, {}); /* click behind and down */
-
- /** Second round: Backspace. **/
- synthesizeKey("VK_RIGHT", {});
- synthesizeKey("VK_BACK_SPACE", {});
- if (tests[i].length == 2) {
- is(theDiv.innerHTML, tests[i][1], "backspace: inner HTML for " + testName);
- } else {
- todo_is(theDiv.innerHTML, tests[i][1], "backspace(should be): inner HTML for " + testName);
- is(theDiv.innerHTML, tests[i][2], "backspace(currently is): inner HTML for " + testName);
- }
-
- /* Set up the selection. */
- theEdit.innerHTML = "<div id=\"" + testName + "\">" + tests[i][0] + "</div>";
- theDiv = document.getElementById(testName);
- theDiv.focus();
- sel.collapse(theDiv, 0);
- synthesizeMouse(theDiv, 100, 2, {}); /* click behind and down */
-
- /** Third round: Delete with non-collapsed selection. **/
- if (i == 72) {
- // This test doesn't work, since we can't select only one newline using the right arrow key.
- continue;
- }
- synthesizeKey("VK_LEFT", {});
- /* Strangely enough we need to hit "right arrow" three times to select two characters. */
- synthesizeKey("VK_RIGHT", {shiftKey:true});
- synthesizeKey("VK_RIGHT", {shiftKey:true});
- synthesizeKey("VK_RIGHT", {shiftKey:true});
- synthesizeKey("VK_DELETE", {});
-
- /* We always expect to the delete the "tf" in "testfoo". */
- var expected = tests[i][1].replace("testfoo", "tesoo")
- .replace("test<b>foo", "tes<b>oo")
- .replace("test<span class=\"pre\">foo", "tes<span class=\"pre\">oo")
- .replace("test<span class=\"pre\"><b>foo", "tes<span class=\"pre\"><b>oo");
- is(theDiv.innerHTML, expected, "delete(non-collapsed): inner HTML for " + testName);
- }
-
- SimpleTest.finish();
-
- });
-
- </script>
-
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug773262.html b/editor/libeditor/tests/test_bug773262.html
deleted file mode 100644
index b0dc82755..000000000
--- a/editor/libeditor/tests/test_bug773262.html
+++ /dev/null
@@ -1,63 +0,0 @@
-<!doctype html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=773262
--->
-<title>Test for Bug 773262</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css">
-<p><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=773262">Mozilla Bug 773262</a></p>
-<iframe></iframe>
-<script>
-function runTest(doc, desc) {
- is(doc.queryCommandEnabled("undo"), false,
- desc + ": Undo shouldn't be enabled yet");
- is(doc.queryCommandEnabled("redo"), false,
- desc + ": Redo shouldn't be enabled yet");
- is(doc.body.innerHTML, "<p>Hello</p>", desc + ": Wrong initial innerHTML");
-
- doc.getSelection().selectAllChildren(doc.body.firstChild);
- doc.execCommand("bold");
- is(doc.queryCommandEnabled("undo"), true,
- desc + ": Undo should be enabled after bold");
- is(doc.queryCommandEnabled("redo"), false,
- desc + ": Redo still shouldn't be enabled");
- is(doc.body.innerHTML, "<p><b>Hello</b></p>",
- desc + ": Wrong innerHTML after bold");
-
- doc.execCommand("undo");
- is(doc.queryCommandEnabled("undo"), false,
- desc + ": Undo should be disabled again");
- is(doc.queryCommandEnabled("redo"), true,
- desc + ": Redo should be enabled now");
- is(doc.body.innerHTML, "<p>Hello</p>",
- desc + ": Wrong innerHTML after undo");
-
- doc.execCommand("redo");
- is(doc.queryCommandEnabled("undo"), true,
- desc + ": Undo should be enabled after redo");
- is(doc.queryCommandEnabled("redo"), false,
- desc + ": Redo should be disabled again");
- is(doc.body.innerHTML, "<p><b>Hello</b></p>",
- desc + ": Wrong innerHTML after redo");
-}
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(function() {
- var doc = document.querySelector("iframe").contentDocument;
-
- // First turn on designMode and run the test like that, as a sanity check.
- doc.body.innerHTML = "<p>Hello</p>";
- doc.designMode = "on";
- runTest(doc, "1");
-
- // Now to test the actual bug: repeat all the above, but with designMode
- // toggled. This should clear the undo history, so everything should be
- // exactly as before.
- doc.designMode = "off";
- doc.body.innerHTML = "<p>Hello</p>";
- doc.designMode = "on";
- runTest(doc, "2");
-
- SimpleTest.finish();
-});
-</script>
diff --git a/editor/libeditor/tests/test_bug780035.html b/editor/libeditor/tests/test_bug780035.html
deleted file mode 100644
index 7c99b9ff5..000000000
--- a/editor/libeditor/tests/test_bug780035.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=780035
--->
-<title>Test for Bug 780035</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<script src="/tests/SimpleTest/EventUtils.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css">
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=780035">Mozilla Bug 780035</a>
-<div contenteditable style="font-size: 13.3333px"></div>
-<script>
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- document.querySelector("div").focus();
- document.execCommand("stylewithcss", false, true);
- sendKey("RETURN");
- sendChar("x");
- is(document.querySelector("div").innerHTML, "x<br>",
- "No <font> tag should be generated");
- SimpleTest.finish();
-});
-</script>
diff --git a/editor/libeditor/tests/test_bug780908.xul b/editor/libeditor/tests/test_bug780908.xul
deleted file mode 100644
index 312f02787..000000000
--- a/editor/libeditor/tests/test_bug780908.xul
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin"
- type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
- type="text/css"?>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=780908
-
-adapted from test_bug607584.xul by Kent James <kent@caspia.com>
--->
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- title="Mozilla Bug 780908" onload="runTest();">
- <script type="application/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
- <script type="application/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
-
- <body xmlns="http://www.w3.org/1999/xhtml">
- <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=780908"
- target="_blank">Mozilla Bug 780908</a>
- <p/>
- <editor xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- id="editor"
- type="content-primary"
- editortype="html"
- style="width: 400px; height: 100px; border: thin solid black"/>
- <p/>
- <pre id="test">
- </pre>
- </body>
- <script class="testbody" type="application/javascript">
- <![CDATA[
-
- SimpleTest.waitForExplicitFinish();
-
- function EditorContentListener(aEditor)
- {
- this.init(aEditor);
- }
-
- EditorContentListener.prototype = {
- init : function(aEditor)
- {
- this.mEditor = aEditor;
- },
-
- QueryInterface : function(aIID)
- {
- if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
- aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
- aIID.equals(Components.interfaces.nsISupports))
- return this;
- throw Components.results.NS_NOINTERFACE;
- },
-
- onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus)
- {
- if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP)
- {
- var editor = this.mEditor.getEditor(this.mEditor.contentWindow);
- if (editor) {
- this.mEditor.focus();
- editor instanceof Components.interfaces.nsIHTMLEditor;
- editor.returnInParagraphCreatesNewParagraph = true;
- source = "<html><body><table><head></table></body></html>";
- editor.rebuildDocumentFromSource(source);
- ok(true, "Don't crash when head appears after body");
- source = "<html></head><head><body></body></html>";
- editor.rebuildDocumentFromSource(source);
- ok(true, "Don't crash when /head appears before head");
- SimpleTest.finish();
- progress.removeProgressListener(this);
- }
- }
-
- },
-
-
- onProgressChange : function(aWebProgress, aRequest,
- aCurSelfProgress, aMaxSelfProgress,
- aCurTotalProgress, aMaxTotalProgress)
- {
- },
-
- onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags)
- {
- },
-
- onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
- {
- },
-
- onSecurityChange : function(aWebProgress, aRequest, aState)
- {
- },
-
- mEditor: null
- };
-
- var progress, progressListener;
-
- function runTest() {
- var newEditorElement = document.getElementById("editor");
- newEditorElement.makeEditable("html", true);
- var docShell = newEditorElement.boxObject.docShell;
- progress = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebProgress);
- progressListener = new EditorContentListener(newEditorElement);
- progress.addProgressListener(progressListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
- newEditorElement.setAttribute("src", "data:text/html,");
- }
-]]>
-</script>
-</window>
diff --git a/editor/libeditor/tests/test_bug787432.html b/editor/libeditor/tests/test_bug787432.html
deleted file mode 100644
index c73bb3c7e..000000000
--- a/editor/libeditor/tests/test_bug787432.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=787432
--->
-<title>Test for Bug 787432</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css">
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=787432">Mozilla Bug 787432</a>
-<div id="test" contenteditable><span class="insert">%</span><br></div>
-<script>
-var div = document.getElementById("test");
-getSelection().collapse(div.firstChild, 0);
-getSelection().extend(div.firstChild, 1);
-document.execCommand("inserttext", false, "x");
-is(div.innerHTML, '<span class="insert">x</span><br>',
- "Empty <span> needs to not be removed");
-</script>
diff --git a/editor/libeditor/tests/test_bug790475.html b/editor/libeditor/tests/test_bug790475.html
deleted file mode 100644
index d7685458b..000000000
--- a/editor/libeditor/tests/test_bug790475.html
+++ /dev/null
@@ -1,95 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=790475
--->
-<head>
- <title>Test for Bug 790475</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=790475">Mozilla Bug 790475</a>
-<p id="display"></p>
-<div id="content" style="display: none"></div>
-<pre id="test">
-<script type="application/javascript">
-
-/**
- * Test for Bug 790475
- *
- * Tests that inline spell checking works properly through adjacent text nodes.
- */
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(runTest);
-
-var gMisspeltWords;
-
-function getEditor() {
- const Ci = SpecialPowers.Ci;
- var editingSession = SpecialPowers.wrap(window)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIEditingSession);
- return editingSession.getEditorForWindow(window);
-}
-
-function getSpellCheckSelection() {
- var editor = getEditor();
- var selcon = editor.selectionController;
- return selcon.getSelection(selcon.SELECTION_SPELLCHECK);
-}
-
-function runTest() {
- gMisspeltWords = [];
- var edit = document.getElementById("edit");
- edit.focus();
-
- SimpleTest.executeSoon(function() {
- gMisspeltWords = [];
- is(isSpellingCheckOk(), true, "Should not find any misspellings yet.");
-
- var newTextNode = document.createTextNode("ing string");
- edit.appendChild(newTextNode);
- var editor = getEditor();
- var sel = editor.selection;
- sel.collapse(newTextNode, newTextNode.textContent.length);
- synthesizeKey("!", {});
-
- edit.blur();
-
- SimpleTest.executeSoon(function() {
- is(isSpellingCheckOk(), true, "Should not have found any misspellings. ");
- SimpleTest.finish();
- });
- });
-}
-
-function isSpellingCheckOk() {
- var sel = getSpellCheckSelection();
- var numWords = sel.rangeCount;
-
- is(numWords, gMisspeltWords.length, "Correct number of misspellings and words.");
-
- if (numWords != gMisspeltWords.length)
- return false;
-
- for (var i = 0; i < numWords; i++) {
- var word = sel.getRangeAt(i);
- is (word, gMisspeltWords[i], "Misspelling is what we think it is.");
- if (word != gMisspeltWords[i])
- return false;
- }
- return true;
-}
-
-</script>
-</pre>
-
-<div id="edit" contenteditable="true">This is a test</div>
-
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug795418-2.html b/editor/libeditor/tests/test_bug795418-2.html
deleted file mode 100644
index 3f44900ee..000000000
--- a/editor/libeditor/tests/test_bug795418-2.html
+++ /dev/null
@@ -1,88 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=795418
--->
-<head>
- <meta charset="utf-8">
- <title>Test #2 for Bug 772796</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=772796">Mozilla Bug 795418</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-
-<div id="copySource">Copy this</div>
-<iframe src="data:application/xhtml+xml,<html contenteditable='' xmlns='http://www.w3.org/1999/xhtml'><span>AB</span></html>"></iframe>
-
-<pre id="test">
-
-<script type="application/javascript">
-
-/** Test for Bug 795418 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var div = document.getElementById("copySource");
- var sel = window.getSelection();
- sel.removeAllRanges();
-
- // Select the text from the text node in div.
- var r = document.createRange();
- r.setStart(div.firstChild, 0);
- r.setEnd(div.firstChild, 9);
- sel.addRange(r);
-
- function checkResult() {
- var iframe = document.querySelector("iframe");
- var iframeWindow = iframe.contentWindow;
- var theEdit = iframe.contentDocument.firstChild;
- theEdit.offsetHeight;
- is(theEdit.innerHTML,
- "<blockquote xmlns=\"http://www.w3.org/1999/xhtml\" type=\"cite\">Copy this</blockquote><span xmlns=\"http://www.w3.org/1999/xhtml\">AB</span>",
- "unexpected HTML for test");
- SimpleTest.finish();
- }
-
- function pasteQuote() {
- var iframe = document.querySelector("iframe");
- var iframeWindow = iframe.contentWindow;
- var theEdit = iframe.contentDocument.firstChild;
- theEdit.offsetHeight;
- iframeWindow.focus();
- SimpleTest.waitForFocus(function() {
- var iframeSel = iframeWindow.getSelection();
- iframeSel.removeAllRanges();
- let span = iframe.contentDocument.querySelector('span');
- iframeSel.collapse(span, 1);
-
- SpecialPowers.doCommand(iframeWindow, "cmd_pasteQuote");
- setTimeout(checkResult, 0);
- }, iframeWindow);
- }
-
- SimpleTest.waitForClipboard(
- function compare(value) {
- return true;
- },
- function setup() {
- synthesizeKey("C", {accelKey: true});
- },
- function onSuccess() {
- setTimeout(pasteQuote, 0);
- },
- function onFailure() {
- SimpleTest.finish();
- },
- "text/html"
- );
-});
-
-</script>
-
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug795418-3.html b/editor/libeditor/tests/test_bug795418-3.html
deleted file mode 100644
index bbe1a58b3..000000000
--- a/editor/libeditor/tests/test_bug795418-3.html
+++ /dev/null
@@ -1,88 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=795418
--->
-<head>
- <meta charset="utf-8">
- <title>Test #3 for Bug 772796</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=772796">Mozilla Bug 795418</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-
-<div id="copySource">Copy this</div>
-<iframe src="data:text/html,<html><body><span>AB</span>"></iframe>
-
-<pre id="test">
-
-<script type="application/javascript">
-
-/** Test for Bug 795418 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var div = document.getElementById("copySource");
- var sel = window.getSelection();
- sel.removeAllRanges();
-
- // Select the text from the text node in div.
- var r = document.createRange();
- r.setStart(div.firstChild, 0);
- r.setEnd(div.firstChild, 9);
- sel.addRange(r);
-
- function checkResult() {
- var iframe = document.querySelector("iframe");
- var iframeWindow = iframe.contentWindow;
- var theEdit = iframe.contentDocument.body;
- theEdit.offsetHeight;
- is(theEdit.innerHTML,
- "<span>AB<blockquote type=\"cite\">Copy this</blockquote></span>",
- "unexpected HTML for test");
- SimpleTest.finish();
- }
-
- function pasteQuote() {
- var iframe = document.querySelector("iframe");
- var iframeWindow = iframe.contentWindow;
- var theEdit = iframe.contentDocument.body;
- iframe.contentDocument.designMode='on';
- iframe.contentDocument.body.offsetHeight;
- iframeWindow.focus();
- SimpleTest.waitForFocus(function() {
- var iframeSel = iframeWindow.getSelection();
- iframeSel.removeAllRanges();
- iframeSel.collapse(theEdit.firstChild, 1);
-
- SpecialPowers.doCommand(iframeWindow, "cmd_pasteQuote");
- setTimeout(checkResult, 0);
- }, iframeWindow);
- }
-
- SimpleTest.waitForClipboard(
- function compare(value) {
- return true;
- },
- function setup() {
- synthesizeKey("C", {accelKey: true});
- },
- function onSuccess() {
- setTimeout(pasteQuote, 0);
- },
- function onFailure() {
- SimpleTest.finish();
- },
- "text/html"
- );
-});
-
-</script>
-
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug795418-4.html b/editor/libeditor/tests/test_bug795418-4.html
deleted file mode 100644
index 6c1ae05d1..000000000
--- a/editor/libeditor/tests/test_bug795418-4.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=795418
--->
-<head>
- <meta charset="utf-8">
- <title>Test #4 for Bug 795418</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=795418">Mozilla Bug 795418</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-
-<div id="copySource">Copy this</div>
-<div id="editable" contenteditable style="display:grid">AB</div>
-
-<pre id="test">
-
-<script type="application/javascript">
-
-/** Test for Bug 795418 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var div = document.getElementById("copySource");
- var sel = window.getSelection();
- sel.removeAllRanges();
-
- // Select the text from the text node in div.
- var r = document.createRange();
- r.setStart(div.firstChild, 0);
- r.setEnd(div.firstChild, 9);
- sel.addRange(r);
-
- SimpleTest.waitForClipboard(
- function compare(value) {
- var theEdit = document.getElementById("editable");
- sel.collapse(theEdit.firstChild, 2);
-
- SpecialPowers.doCommand(window, "cmd_paste");
- is(theEdit.innerHTML,
- "ABCopy this",
- "unexpected HTML for test");
- return true;
- },
- function setup() {
- synthesizeKey("C", {accelKey: true});
- },
- function onSuccess() {
- SimpleTest.finish();
- },
- function onFailure() {
- SimpleTest.finish();
- },
- "text/html"
- );
-});
-
-</script>
-
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug795418-5.html b/editor/libeditor/tests/test_bug795418-5.html
deleted file mode 100644
index 5ff90b15a..000000000
--- a/editor/libeditor/tests/test_bug795418-5.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=795418
--->
-<head>
- <meta charset="utf-8">
- <title>Test #5 for Bug 795418</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=795418">Mozilla Bug 795418</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-
-<div id="copySource">Copy this</div>
-<div id="editable" contenteditable style="display:ruby">AB</div>
-
-<pre id="test">
-
-<script type="application/javascript">
-
-/** Test for Bug 795418 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var div = document.getElementById("copySource");
- var sel = window.getSelection();
- sel.removeAllRanges();
-
- // Select the text from the text node in div.
- var r = document.createRange();
- r.setStart(div.firstChild, 0);
- r.setEnd(div.firstChild, 9);
- sel.addRange(r);
-
- SimpleTest.waitForClipboard(
- function compare(value) {
- var theEdit = document.getElementById("editable");
- sel.collapse(theEdit.firstChild, 2);
-
- SpecialPowers.doCommand(window, "cmd_paste");
- is(theEdit.innerHTML,
- "ABCopy this",
- "unexpected HTML for test");
- return true;
- },
- function setup() {
- synthesizeKey("C", {accelKey: true});
- },
- function onSuccess() {
- SimpleTest.finish();
- },
- function onFailure() {
- SimpleTest.finish();
- },
- "text/html"
- );
-});
-
-</script>
-
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug795418-6.html b/editor/libeditor/tests/test_bug795418-6.html
deleted file mode 100644
index 798a6534b..000000000
--- a/editor/libeditor/tests/test_bug795418-6.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=795418
--->
-<head>
- <meta charset="utf-8">
- <title>Test #5 for Bug 795418</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=795418">Mozilla Bug 795418</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-
-<div id="copySource">Copy this</div>
-<div id="editable" contenteditable style="display:table">AB</div>
-
-<pre id="test">
-
-<script type="application/javascript">
-
-/** Test for Bug 795418 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var div = document.getElementById("copySource");
- var sel = window.getSelection();
- sel.removeAllRanges();
-
- // Select the text from the text node in div.
- var r = document.createRange();
- r.setStart(div.firstChild, 0);
- r.setEnd(div.firstChild, 9);
- sel.addRange(r);
-
- SimpleTest.waitForClipboard(
- function compare(value) {
- var theEdit = document.getElementById("editable");
- sel.collapse(theEdit.firstChild, 2);
-
- SpecialPowers.doCommand(window, "cmd_pasteQuote");
- is(theEdit.innerHTML,
- "AB<blockquote type=\"cite\">Copy this</blockquote>",
- "unexpected HTML for test");
- return true;
- },
- function setup() {
- synthesizeKey("C", {accelKey: true});
- },
- function onSuccess() {
- SimpleTest.finish();
- },
- function onFailure() {
- SimpleTest.finish();
- },
- "text/html"
- );
-});
-
-</script>
-
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug795418.html b/editor/libeditor/tests/test_bug795418.html
deleted file mode 100644
index 1db8cf026..000000000
--- a/editor/libeditor/tests/test_bug795418.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=795418
--->
-<head>
- <meta charset="utf-8">
- <title>Test for Bug 795418</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=795418">Mozilla Bug 795418</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-
-<div id="copySource">Copy this</div>
-<div id="editable" contenteditable><span>AB</span></div>
-
-<pre id="test">
-
-<script type="application/javascript">
-
-/** Test for Bug 795418 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
- var div = document.getElementById("copySource");
- var sel = window.getSelection();
- sel.removeAllRanges();
-
- // Select the text from the text node in div.
- var r = document.createRange();
- r.setStart(div.firstChild, 0);
- r.setEnd(div.firstChild, 9);
- sel.addRange(r);
-
- SimpleTest.waitForClipboard(
- function compare(value) {
- var theEdit = document.getElementById("editable");
- sel.collapse(theEdit.firstChild, 1);
-
- SpecialPowers.doCommand(window, "cmd_pasteQuote");
- is(theEdit.innerHTML,
- "<span>AB<blockquote type=\"cite\">Copy this</blockquote></span>",
- "unexpected HTML for test");
- return true;
- },
- function setup() {
- synthesizeKey("C", {accelKey: true});
- },
- function onSuccess() {
- SimpleTest.finish();
- },
- function onFailure() {
- SimpleTest.finish();
- },
- "text/html"
- );
-});
-
-</script>
-
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug795785.html b/editor/libeditor/tests/test_bug795785.html
deleted file mode 100644
index 5f93d5142..000000000
--- a/editor/libeditor/tests/test_bug795785.html
+++ /dev/null
@@ -1,168 +0,0 @@
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=795785
--->
-<head>
- <title>Test for Bug 795785</title>
- <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=795785">Mozilla Bug 795785</a>
-<div id="display">
- <textarea id="textarea" style="overflow: hidden; height: 3em; width: 5em; word-wrap: normal;"></textarea>
- <div id="div" contenteditable style="overflow: hidden; height: 3em; width: 5em;"></div>
-</div>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-</pre>
-
-<script class="testbody" type="application/javascript">
-
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.requestFlakyTimeout("This test uses setTimeouts in order to fix an intermittent failure.");
-
-// Turn off spatial navigation because it hijacks arrow key events and VK_RETURN
-// events.
-SimpleTest.waitForFocus(function() {
- SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, runTests);
-});
-var textarea = document.getElementById("textarea");
-var div = document.getElementById("div");
-
-function hitEventLoop(aFunc, aTimes)
-{
- if (--aTimes) {
- setTimeout(hitEventLoop, 0, aFunc, aTimes);
- } else {
- setTimeout(aFunc, 100);
- }
-}
-
-function doKeyEventTest(aElement, aElementDescription, aCallback)
-{
- aElement.focus();
- aElement.scrollTop = 0;
- hitEventLoop(function () {
- is(aElement.scrollTop, 0,
- aElementDescription + "'s scrollTop isn't 0");
- synthesizeKey("VK_RETURN", { });
- synthesizeKey("VK_RETURN", { });
- synthesizeKey("VK_RETURN", { });
- synthesizeKey("VK_RETURN", { });
- synthesizeKey("VK_RETURN", { });
- synthesizeKey("VK_RETURN", { });
- hitEventLoop(function () {
- isnot(aElement.scrollTop, 0,
- aElementDescription + " was not scrolled by inserting line breaks");
- var scrollTop = aElement.scrollTop;
- synthesizeKey("VK_UP", { });
- synthesizeKey("VK_UP", { });
- synthesizeKey("VK_UP", { });
- synthesizeKey("VK_UP", { });
- synthesizeKey("VK_UP", { });
- hitEventLoop(function () {
- isnot(aElement.scrollTop, scrollTop,
- aElementDescription + " was not scrolled by up key events");
- synthesizeKey("VK_DOWN", { });
- synthesizeKey("VK_DOWN", { });
- synthesizeKey("VK_DOWN", { });
- synthesizeKey("VK_DOWN", { });
- synthesizeKey("VK_DOWN", { });
- hitEventLoop(function () {
- is(aElement.scrollTop, scrollTop,
- aElementDescription + " was not scrolled by down key events");
- var longWord = "aaaaaaaaaaaaaaaaaaaa";
- sendString(longWord);
- hitEventLoop(function () {
- isnot(aElement.scrollLeft, 0,
- aElementDescription + " was not scrolled by typing long word");
- var scrollLeft = aElement.scrollLeft;
- var i;
- for (i = 0; i < longWord.length; i++) {
- synthesizeKey("VK_LEFT", { });
- }
- hitEventLoop(function () {
- isnot(aElement.scrollLeft, scrollLeft,
- aElementDescription + " was not scrolled by left key events");
- for (i = 0; i < longWord.length; i++) {
- synthesizeKey("VK_RIGHT", { });
- }
- hitEventLoop(function () {
- is(aElement.scrollLeft, scrollLeft,
- aElementDescription + " was not scrolled by right key events");
- aCallback();
- }, 20);
- }, 20);
- }, 20);
- }, 20);
- }, 20);
- }, 20);
- }, 20);
-}
-
-function doCompositionTest(aElement, aElementDescription, aCallback)
-{
- aElement.focus();
- aElement.scrollTop = 0;
- hitEventLoop(function () {
- is(aElement.scrollTop, 0,
- aElementDescription + "'s scrollTop isn't 0");
- var str = "Web \u958b\u767a\u8005\u306e\u7686\u3055\u3093\u306f\u3001" +
- "Firefox \u306b\u5b9f\u88c5\u3055\u308c\u3066\u3044\u308b HTML5" +
- " \u3084 CSS \u306e\u65b0\u6a5f\u80fd\u3092\u6d3b\u7528\u3059" +
- "\u308b\u3053\u3068\u3067\u3001\u9b45\u529b\u3042\u308b Web " +
- "\u30b5\u30a4\u30c8\u3084\u9769\u65b0\u7684\u306a Web \u30a2" +
- "\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u3088\u308a" +
- "\u77ed\u6642\u9593\u3067\u7c21\u5358\u306b\u4f5c\u6210\u3067" +
- "\u304d\u307e\u3059\u3002";
- synthesizeCompositionChange({
- composition: {
- string: str,
- clauses: [
- { length: str.length, attr: COMPOSITION_ATTR_RAW_CLAUSE }
- ]
- },
- caret: { start: str.length, length: 0 }
- });
- hitEventLoop(function () {
- isnot(aElement.scrollTop, 0,
- aElementDescription + " was not scrolled by composition");
- synthesizeComposition({ type: "compositioncommit", data: "" });
- hitEventLoop(function () {
- is(aElement.scrollTop, 0,
- aElementDescription + " was not scrolled back to the top by canceling composition");
- aCallback();
- }, 20);
- }, 20);
- }, 20);
-}
-
-function runTests()
-{
- doKeyEventTest(textarea, "textarea",
- function () {
- textarea.value = "";
- doKeyEventTest(div, "div (contenteditable)",
- function () {
- div.innerHTML = "";
- doCompositionTest(textarea, "textarea",
- function () {
- doCompositionTest(div, "div (contenteditable)",
- function () {
- SimpleTest.finish();
- });
- });
- });
- });
-}
-
-</script>
-</body>
-
-</html>
diff --git a/editor/libeditor/tests/test_bug796839.html b/editor/libeditor/tests/test_bug796839.html
deleted file mode 100644
index be4be316c..000000000
--- a/editor/libeditor/tests/test_bug796839.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=796839
--->
-<title>Test for Bug 796839</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css">
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=796839">Mozilla Bug 796839</a>
-<div id="test" contenteditable><br></div>
-<script>
-var div = document.getElementById("test");
-var text = document.createTextNode("");
-div.insertBefore(text, div.firstChild);
-getSelection().collapse(text, 0);
-document.execCommand("inserthtml", false, "x");
-is(div.textContent, 'x', "Empty textnodes should be editable");
-</script>
diff --git a/editor/libeditor/tests/test_bug830600.html b/editor/libeditor/tests/test_bug830600.html
deleted file mode 100644
index 39ced297a..000000000
--- a/editor/libeditor/tests/test_bug830600.html
+++ /dev/null
@@ -1,100 +0,0 @@
-<!DOCTYPE HTML>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=830600
--->
-<head>
- <title>Test for Bug 830600</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <script src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-
-<body>
- <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=830600">Mozilla Bug 830600</a>
- <p id="display"></p>
- <div id="content" style="display: none">
- </div>
- <input type="text" id="t1" />
- <pre id="test">
- <script type="application/javascript;version=1.7">
-
- /** Test for Bug 830600 **/
- SimpleTest.waitForExplicitFinish();
- SimpleTest.waitForFocus(function() {
- const Ci = SpecialPowers.Ci;
- function test(str, expected, callback) {
- var t = document.getElementById("t1");
- SpecialPowers.wrap(t).QueryInterface(Ci.nsIDOMNSEditableElement);
- t.focus();
- t.value = "";
- var editor = SpecialPowers.wrap(t).editor;
- editor.QueryInterface(Ci.nsIPlaintextEditor);
- var origNewlineHandling = editor.newlineHandling;
- editor.newlineHandling = Ci.nsIPlaintextEditor.eNewlinesStripSurroundingWhitespace
- SimpleTest.waitForClipboard(str,
- function() {
- SpecialPowers.Cc["@mozilla.org/widget/clipboardhelper;1"]
- .getService(Ci.nsIClipboardHelper)
- .copyString(str);
- },
- function() {
- synthesizeKey("V", {accelKey: true});
- is(t.value, expected, "New line handling works correctly");
- t.value = "";
- callback();
- },
- function() {
- ok(false, "Failed to copy the string");
- SimpleTest.finish();
- }
- );
- }
-
- function runNextTest() {
- if (tests.length) {
- var currentTest = tests.shift();
- test(currentTest[0], currentTest[1], runNextTest);
- } else {
- SimpleTest.finish();
- }
- }
-
- var tests = [
- ["abc", "abc"],
- ["\n", ""],
- [" \n", ""],
- ["\n ", ""],
- [" \n ", ""],
- [" a", " a"],
- ["a ", "a "],
- [" a ", " a "],
- [" \nabc", "abc"],
- ["\n abc", "abc"],
- [" \n abc", "abc"],
- [" \nabc ", "abc "],
- ["\n abc ", "abc "],
- [" \n abc ", "abc "],
- ["abc\n ", "abc"],
- ["abc \n", "abc"],
- ["abc \n ", "abc"],
- [" abc\n ", " abc"],
- [" abc \n", " abc"],
- [" abc \n ", " abc"],
- [" abc \n def \n ", " abcdef"],
- ["\n abc \n def \n ", "abcdef"],
- [" \n abc \n def ", "abcdef "],
- [" abc\n\ndef ", " abcdef "],
- [" abc \n\n def ", " abcdef "],
- ];
-
- runNextTest();
- });
-
- </script>
- </pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug832025.html b/editor/libeditor/tests/test_bug832025.html
deleted file mode 100644
index 40f4f4734..000000000
--- a/editor/libeditor/tests/test_bug832025.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=832025
--->
-<head>
- <title>Test for Bug 832025</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=832025">Mozilla Bug 832025</a>
-<div id="test" contenteditable="true">header1</div>
-<script type="application/javascript">
-
-/**
- * Test for Bug 832025
- *
- */
-
-document.execCommand("stylewithcss", false, "true");
-var test = document.getElementById("test");
-test.focus();
-
-// place caret at end of editable area
-var sel = getSelection();
-sel.collapse(test, test.childNodes.length);
-
-// make it a H1
-document.execCommand("heading", false, "H1");
-// simulate a CR key
-sendKey("return");
-// insert some text
-document.execCommand("insertText", false, "abc");
-
-is(test.innerHTML == '<h1>header1</h1><p>abc<br></p>',
- true, "A paragraph automatically created after a CR at the end of an H1 should not be bold");
-
-</script>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug850043.html b/editor/libeditor/tests/test_bug850043.html
deleted file mode 100644
index b811c86a6..000000000
--- a/editor/libeditor/tests/test_bug850043.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=850043
--->
-<head>
- <title>Test for Bug 850043</title>
- <script type="application/javascript" src="/MochiKit/packed.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=850043">Mozilla Bug 850043</a>
-<div id="display">
-<textarea id="textarea">b&#x9080;&#xe010f;&#x8fba;&#xe0101;</textarea>
-<div contenteditable id="edit">b&#x9080;&#xe010f;&#x8fba;&#xe0101;</div>
-</div>
-<div id="content" style="display: none">
-</div>
-
-<pre id="test">
-</pre>
-<script>
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(() => {
- let fm = SpecialPowers.Cc["@mozilla.org/focus-manager;1"].
- getService(SpecialPowers.Ci.nsIFocusManager);
-
- let element = document.getElementById("textarea");
- element.setSelectionRange(element.value.length, element.value.length);
- element.focus();
- is(SpecialPowers.unwrap(fm.focusedElement), element, "failed to move focus");
-
- synthesizeKey("VK_END", { });
- synthesizeKey("a", { });
- is(element.value, "b\u{9080}\u{e010f}\u{8fba}\u{e0101}a", "a isn't last character");
-
- synthesizeKey("VK_BACK_SPACE", { });
- synthesizeKey("VK_BACK_SPACE", { });
- synthesizeKey("VK_BACK_SPACE", { });
- is(element.value, 'b', "cannot remove all IVS characters");
-
- element = document.getElementById("edit");
- element.focus();
- is(SpecialPowers.unwrap(fm.focusedElement), element, "failed to move focus");
-
- let sel = window.getSelection();
- sel.collapse(element.childNodes[0], element.textContent.length);
-
- synthesizeKey("a", { });
- is(element.textContent, "b\u{9080}\u{e010f}\u{8fba}\u{e0101}a", "a isn't last character");
-
- synthesizeKey("VK_BACK_SPACE", { });
- synthesizeKey("VK_BACK_SPACE", { });
- synthesizeKey("VK_BACK_SPACE", { });
- is(element.textContent, 'b', "cannot remove all IVS characters");
-
- SimpleTest.finish();
-});
-</script>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug857487.html b/editor/libeditor/tests/test_bug857487.html
deleted file mode 100644
index a3746d44c..000000000
--- a/editor/libeditor/tests/test_bug857487.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=857487
--->
-<head>
- <title>Test for Bug 857487</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=857487">Mozilla Bug 857487</a>
-<div id="edit" contenteditable="true">
- <table id="table" border="1" width="100%">
- <tbody>
- <tr>
- <td>a</td>
- <td>b</td>
- <td>c</td>
- </tr>
- <tr>
- <td>d</td>
- <td id="cell">e</td>
- <td>f</td>
- </tr>
- <tr>
- <td>g</td>
- <td>h</td>
- <td>i</td>
- </tr>
- </tbody>
- </table>
-</div>
-<script type="application/javascript">
-
-/**
- * Test for Bug 857487
- *
- * Tests that removing a table row through nsIHTMLEditor works
- */
-
-function getEditor() {
- const Ci = SpecialPowers.Ci;
- var editingSession = SpecialPowers.wrap(window)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIEditingSession);
- return editingSession.getEditorForWindow(window).QueryInterface(Ci.nsITableEditor);
-}
-
-var cell = document.getElementById("cell");
-cell.focus();
-
-// place caret at end of center cell
-var sel = getSelection();
-sel.collapse(cell, cell.childNodes.length);
-
-var editor = getEditor();
-editor.deleteTableRow(1);
-
-var table = document.getElementById("table");
-
-is(table.innerHTML == "\n <tbody>\n <tr>\n <td>a</td>\n <td>b</td>\n <td>c</td>\n </tr>\n \n <tr>\n <td>g</td>\n <td>h</td>\n <td>i</td>\n </tr>\n </tbody>\n ",
- true, "editor.deleteTableRow(1) should delete the row containing the selection");
-
-</script>
-
-
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug858918.html b/editor/libeditor/tests/test_bug858918.html
deleted file mode 100644
index 46f841bbc..000000000
--- a/editor/libeditor/tests/test_bug858918.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!DOCTYPE html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=858918
--->
-<title>Test for Bug 858918</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<script src="/tests/SimpleTest/EventUtils.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=858918">Mozilla Bug 858918</a>
-<span contenteditable style="display:block;min-height:1em"></span>
-<script>
-var span = document.querySelector("span");
-getSelection().collapse(span, 0);
-document.execCommand("inserthtml", false, "<div>doesn't go in span</div>");
-is(span.innerHTML, "<div>doesn't go in span</div>");
-</script>
diff --git a/editor/libeditor/tests/test_bug915962.html b/editor/libeditor/tests/test_bug915962.html
deleted file mode 100644
index 32968b310..000000000
--- a/editor/libeditor/tests/test_bug915962.html
+++ /dev/null
@@ -1,100 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=915962
--->
-<head>
- <title>Test for Bug 915962</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=915962">Mozilla Bug 915962</a>
-<p id="display"></p>
-<div id="content">
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 915962 **/
-
-var smoothScrollPref = "general.smoothScroll";
-SimpleTest.waitForExplicitFinish();
-var win = window.open("file_bug915962.html", "_blank",
- "width=600,height=600,scrollbars=yes");
-
-// grab the timer right at the start
-var cwu = SpecialPowers.getDOMWindowUtils(win);
-function step() {
- cwu.advanceTimeAndRefresh(100);
-}
-SimpleTest.waitForFocus(function() {
- SpecialPowers.pushPrefEnv({"set":[[smoothScrollPref, false]]}, startTest);
-}, win);
-function startTest() {
- // Make sure that pressing Space when a tabindex=-1 element is focused
- // will scroll the page.
- var button = win.document.querySelector("button");
- var sc = win.document.querySelector("div");
- sc.focus();
- is(win.scrollY, 0, "Sanity check");
- synthesizeKey(" ", {}, win);
-
- step();
-
- isnot(win.scrollY, 0, "Page is scrolled down");
- var oldY = win.scrollY;
- synthesizeKey(" ", {shiftKey: true}, win);
-
- step();
-
- ok(win.scrollY < oldY, "Page is scrolled up");
-
- // Make sure that pressing Space when a tabindex=-1 element is focused
- // will not scroll the page, and will activate the element.
- button.focus();
- var clicked = false;
- button.onclick = () => clicked = true;
- oldY = win.scrollY;
- synthesizeKey(" ", {}, win);
-
- step();
-
- ok(win.scrollY <= oldY, "Page is not scrolled down");
- ok(clicked, "The button should be clicked");
- synthesizeKey("VK_TAB", {}, win);
-
- step();
-
- oldY = win.scrollY;
- synthesizeKey(" ", {}, win);
-
- step()
-
- ok(win.scrollY >= oldY, "Page is scrolled down");
-
- win.close();
- cwu.restoreNormalRefresh();
-
- win = window.open("file_bug915962.html", "_blank",
- "width=600,height=600,scrollbars=yes");
- cwu = SpecialPowers.getDOMWindowUtils(win);
- SimpleTest.waitForFocus(function() {
- is(win.scrollY, 0, "Sanity check");
- synthesizeKey(" ", {}, win);
-
- step();
-
- isnot(win.scrollY, 0, "Page is scrolled down without crashing");
-
- win.close();
- cwu.restoreNormalRefresh();
-
- SimpleTest.finish();
- }, win);
-}
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug966155.html b/editor/libeditor/tests/test_bug966155.html
deleted file mode 100644
index 1e7ed67f3..000000000
--- a/editor/libeditor/tests/test_bug966155.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=966155
--->
-<head>
- <title>Test for Bug 966155</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=966155">Mozilla Bug 966155</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-SimpleTest.waitForExplicitFinish();
-
-var win = window.open("file_bug966155.html", "", "test-966155");
-win.addEventListener("load", function() {
- runTest(win);
-}, {once: true});
-
-function runTest(win) {
- SimpleTest.waitForFocus(function() {
- var doc = win.document;
- var iframe = doc.querySelector("iframe");
- var iframeDoc = iframe.contentDocument;
- var input = doc.querySelector("input");
- iframe.focus();
- iframeDoc.body.focus();
- // Type some text
- "test".split("").forEach(function(letter) {
- synthesizeKey(letter, {}, win);
- });
- is(iframeDoc.body.textContent.trim(), "test", "entered the text");
- // focus the input box
- input.focus();
- // press tab
- synthesizeKey("VK_TAB", {}, win);
- // Now press Ctrl+Backspace
- synthesizeKey("VK_BACK_SPACE", {ctrlKey: true}, win);
- is(iframeDoc.body.textContent.trim(), "", "deleted the text");
- win.close();
- SimpleTest.finish();
- }, win);
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug966552.html b/editor/libeditor/tests/test_bug966552.html
deleted file mode 100644
index e18883aad..000000000
--- a/editor/libeditor/tests/test_bug966552.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=966552
--->
-<head>
- <title>Test for Bug 966552</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=966552">Mozilla Bug 966552</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-SimpleTest.waitForExplicitFinish();
-
-var win = window.open("file_bug966552.html", "", "test-966552");
-win.addEventListener("load", function() {
- runTest(win);
-}, {once: true});
-
-function runTest(win) {
- SimpleTest.waitForFocus(function() {
- var doc = win.document;
- var sel = win.getSelection();
- doc.body.focus();
- sel.collapse(doc.body.firstChild, 2);
- synthesizeKey("VK_BACK_SPACE", {ctrlKey: true}, win);
- is(doc.body.textContent.trim(), "st");
- win.close();
- SimpleTest.finish();
- }, win);
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug974309.html b/editor/libeditor/tests/test_bug974309.html
deleted file mode 100644
index e3caa87fb..000000000
--- a/editor/libeditor/tests/test_bug974309.html
+++ /dev/null
@@ -1,78 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=974309
--->
-<head>
- <title>Test for Bug 974309</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=974309">Mozilla Bug 974309</a>
-<div id="edit_not_table_parent" contenteditable="true"></div>
-<div>
- <table id="table" border="1" width="100%">
- <tbody>
- <tr>
- <td>a</td>
- <td>b</td>
- <td>c</td>
- </tr>
- <tr>
- <td>d</td>
- <td id="cell">e</td>
- <td>f</td>
- </tr>
- <tr>
- <td>g</td>
- <td>h</td>
- <td>i</td>
- </tr>
- </tbody>
- </table>
-</div>
-<script type="application/javascript">
-
-/**
- * Test for Bug 974309
- *
- * Tests that editing a table row fails when the table or row is _not_ a child of a contenteditable node.
- * See bug 857487 for tests that cover when the table or row _is_ a child of a contenteditable node.
- */
-
-function getEditor() {
- const Ci = SpecialPowers.Ci;
- var editingSession = SpecialPowers.wrap(window)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIEditingSession);
- return editingSession.getEditorForWindow(window).QueryInterface(Ci.nsITableEditor);
-}
-
-var cell = document.getElementById("cell");
-cell.focus();
-
-// place caret at end of center cell
-var sel = getSelection();
-sel.collapse(cell, cell.childNodes.length);
-
-var table = document.getElementById("table");
-
-var tableHTML = table.innerHTML;
-
-var editor = getEditor();
-editor.deleteTableRow(1);
-
-is(table.innerHTML == tableHTML, true, "editor should not modify non-editable table" );
-
-isnot(table.innerHTML == "\n <tbody>\n <tr>\n <td>a</td>\n <td>b</td>\n <td>c</td>\n </tr>\n \n <tr>\n <td>g</td>\n <td>h</td>\n <td>i</td>\n </tr>\n </tbody>\n ",
- true, "editor.deleteTableRow(1) should not delete a non-editable row containing the selection");
-
-</script>
-
-
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_bug998188.html b/editor/libeditor/tests/test_bug998188.html
deleted file mode 100644
index 2d167f0bd..000000000
--- a/editor/libeditor/tests/test_bug998188.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=565392
--->
-<head>
- <title>Test for Bug 998188</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=998188">Mozilla Bug 998188</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<div id="editor" contenteditable>abc</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 998188 **/
-
-SimpleTest.waitForExplicitFinish();
-
-function runTests()
-{
- var editor = document.getElementById("editor");
- editor.focus();
-
- var textNode1 = document.createTextNode("def");
- var textNode2 = document.createTextNode("ghi");
-
- editor.appendChild(textNode1);
- editor.appendChild(textNode2);
-
- window.getSelection().collapse(textNode2, 3);
-
- for (var i = 0; i < 9; i++) {
- var caretRect = synthesizeQueryCaretRect(i);
- ok(caretRect.succeeded, "QueryCaretRect should succeeded (" + i + ")");
- }
-
- SimpleTest.finish();
-}
-
-SimpleTest.waitForFocus(runTests);
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_composition_event_created_in_chrome.html b/editor/libeditor/tests/test_composition_event_created_in_chrome.html
deleted file mode 100644
index 18b72ccd4..000000000
--- a/editor/libeditor/tests/test_composition_event_created_in_chrome.html
+++ /dev/null
@@ -1,82 +0,0 @@
-<!doctype html>
-<html>
-
-<head>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
-
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <script src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-
-<body>
-
-<input id="input">
-
-<script type="application/javascript">
-
-// In nsEditorEventListener, when listening event is not created with proper
-// event interface, it asserts the fact.
-SimpleTest.waitForExplicitFinish();
-
-var gInputElement = document.getElementById("input");
-
-function getEditorIMESupport(aInputElement)
-{
- var editableElement = SpecialPowers.wrap(aInputElement).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement);
- ok(editableElement, "The input element doesn't have nsIDOMNSEditableElement interface");
- ok(editableElement.editor, "There is no editor for the input element");
- var editorIMESupport = SpecialPowers.wrap(editableElement).editor.QueryInterface(SpecialPowers.Ci.nsIEditorIMESupport);
- ok(editorIMESupport, "The input element doesn't have nsIEditorIMESupport interface");
- return editorIMESupport;
-}
-
-var gEditorIMESupport;
-
-function testNotGenerateCompositionByCreatedEvents(aEventInterface)
-{
- var compositionEvent = document.createEvent(aEventInterface);
- if (compositionEvent.initCompositionEvent) {
- compositionEvent.initCompositionEvent("compositionstart", true, true, window, "", "");
- } else if (compositionEvent.initMouseEvent) {
- compositionEvent.initMouseEvent("compositionstart", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
- }
- gInputElement.dispatchEvent(compositionEvent);
- ok(!gEditorIMESupport.composing, "Composition shouldn't be started with a created compositionstart event (" + aEventInterface + ")");
-
- compositionEvent = document.createEvent(aEventInterface);
- if (compositionEvent.initCompositionEvent) {
- compositionEvent.initCompositionEvent("compositionupdate", true, false, window, "abc", "");
- } else if (compositionEvent.initMouseEvent) {
- compositionEvent.initMouseEvent("compositionupdate", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
- }
- gInputElement.dispatchEvent(compositionEvent);
- ok(!gEditorIMESupport.composing, "Composition shouldn't be started with a created compositionupdate event (" + aEventInterface + ")");
- is(gInputElement.value, "", "Input element shouldn't be modified with a created compositionupdate event (" + aEventInterface + ")");
-
- compositionEvent = document.createEvent(aEventInterface);
- if (compositionEvent.initCompositionEvent) {
- compositionEvent.initCompositionEvent("compositionend", true, false, window, "abc", "");
- } else if (compositionEvent.initMouseEvent) {
- compositionEvent.initMouseEvent("compositionend", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
- }
- gInputElement.dispatchEvent(compositionEvent);
- ok(!gEditorIMESupport.composing, "Composition shouldn't be committed with a created compositionend event (" + aEventInterface + ")");
- is(gInputElement.value, "", "Input element shouldn't be committed with a created compositionend event (" + aEventInterface + ")");
-}
-
-function doTests()
-{
- gInputElement.focus();
- gEditorIMESupport = getEditorIMESupport(gInputElement);
-
- testNotGenerateCompositionByCreatedEvents("CompositionEvent");
- testNotGenerateCompositionByCreatedEvents("MouseEvent");
-
- SimpleTest.finish();
-}
-
-SimpleTest.waitForFocus(doTests);
-
-</script>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_contenteditable_focus.html b/editor/libeditor/tests/test_contenteditable_focus.html
deleted file mode 100644
index 051ac7b2f..000000000
--- a/editor/libeditor/tests/test_contenteditable_focus.html
+++ /dev/null
@@ -1,209 +0,0 @@
-<html>
-<head>
- <title>Test for contenteditable focus</title>
- <script type="text/javascript"
- src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css"
- href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<div id="display">
- First text in this document.<br>
- <input id="inputText" type="text"><br>
- <input id="inputTextReadonly" type="text" readonly><br>
- <input id="inputButton" type="button" value="input[type=button]"><br>
- <button id="button">button</button><br>
- <div id="editor" contenteditable="true">
- editable contents.<br>
- <input id="inputTextInEditor" type="text"><br>
- <input id="inputTextReadonlyInEditor" type="text" readonly><br>
- <input id="inputButtonInEditor" type="button" value="input[type=button]"><br>
- <button id="buttonInEditor">button</button><br>
- <div id="noeditableInEditor" contenteditable="false">
- <span id="spanInNoneditableInEditor">span element in noneditable in editor</span><br>
- <input id="inputTextInNoneditableInEditor" type="text"><br>
- <input id="inputTextReadonlyInNoneditableInEditor" type="text" readonly><br>
- <input id="inputButtonInNoneditableInEditor" type="button" value="input[type=button]"><br>
- <button id="buttonInNoneditableInEditor">button</button><br>
- </div>
- <span id="spanInEditor">span element in editor</span><br>
- </div>
- <div id="otherEditor" contenteditable="true">
- other editor.
- </div>
-</div>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-</pre>
-
-<script class="testbody" type="application/javascript">
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTests, window);
-
-function runTests()
-{
- runTestsInternal();
- SimpleTest.finish();
-}
-
-function runTestsInternal()
-{
- var fm = SpecialPowers.Cc["@mozilla.org/focus-manager;1"].
- getService(SpecialPowers.Ci.nsIFocusManager);
- // XXX using selCon for checking the visibility of the caret, however,
- // selCon is shared in document, cannot get the element of owner of the
- // caret from javascript?
- var selCon = SpecialPowers.wrap(window).
- QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).
- getInterface(SpecialPowers.Ci.nsIWebNavigation).
- QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).
- getInterface(SpecialPowers.Ci.nsISelectionDisplay).
- QueryInterface(SpecialPowers.Ci.nsISelectionController);
- var selection = window.getSelection();
-
- var inputText = document.getElementById("inputText");
- var inputTextReadonly = document.getElementById("inputTextReadonly");
- var inputButton = document.getElementById("inputButton");
- var button = document.getElementById("button");
- var editor = document.getElementById("editor");
- var inputTextInEditor = document.getElementById("inputTextInEditor");
- var inputTextReadonlyInEditor = document.getElementById("inputTextReadonlyInEditor");
- var inputButtonInEditor = document.getElementById("inputButtonInEditor");
- var noeditableInEditor = document.getElementById("noeditableInEditor");
- var spanInNoneditableInEditor = document.getElementById("spanInNoneditableInEditor");
- var inputTextInNoneditableInEditor = document.getElementById("inputTextInNoneditableInEditor");
- var inputTextReadonlyInNoneditableInEditor = document.getElementById("inputTextReadonlyInNoneditableInEditor");
- var inputButtonInNoneditableInEditor = document.getElementById("inputButtonInNoneditableInEditor");
- var buttonInNoneditableInEditor = document.getElementById("buttonInNoneditableInEditor");
- var spanInEditor = document.getElementById("spanInEditor");
- var otherEditor = document.getElementById("otherEditor");
-
- // XXX if there is a contenteditable element, HTML editor sets dom selection
- // to first editable node, but this makes inconsistency with normal document
- // behavior.
- todo_is(selection.rangeCount, 0, "unexpected selection range is there");
- ok(!selCon.caretVisible, "caret is visible in the document");
- // Move focus to inputTextInEditor
- inputTextInEditor.focus();
- is(SpecialPowers.unwrap(fm.focusedElement), inputTextInEditor,
- "inputTextInEditor didn't get focus");
- todo_is(selection.rangeCount, 0, "unexpected selection range is there");
- ok(selCon.caretVisible, "caret isn't visible in the inputTextInEditor");
- // Move focus to the editor
- editor.focus();
- is(SpecialPowers.unwrap(fm.focusedElement), editor,
- "editor didn't get focus");
- is(selection.rangeCount, 1,
- "there is no selection range when editor has focus");
- var range = selection.getRangeAt(0);
- ok(range.collapsed, "the selection range isn't collapsed");
- var startNode = range.startContainer;
- is(startNode.nodeType, 1, "the caret isn't set to the div node");
- is(startNode, editor, "the caret isn't set to the editor");
- ok(selCon.caretVisible, "caret isn't visible in the editor");
- // Move focus to other editor
- otherEditor.focus();
- is(SpecialPowers.unwrap(fm.focusedElement), otherEditor,
- "the other editor didn't get focus");
- is(selection.rangeCount, 1,
- "there is no selection range when the other editor has focus");
- range = selection.getRangeAt(0);
- ok(range.collapsed, "the selection range isn't collapsed");
- var startNode = range.startContainer;
- is(startNode.nodeType, 1, "the caret isn't set to the div node");
- is(startNode, otherEditor, "the caret isn't set to the other editor");
- ok(selCon.caretVisible, "caret isn't visible in the other editor");
- // Move focus to inputTextInEditor
- inputTextInEditor.focus();
- is(SpecialPowers.unwrap(fm.focusedElement), inputTextInEditor,
- "inputTextInEditor didn't get focus #2");
- is(selection.rangeCount, 1, "selection range is lost from the document");
- range = selection.getRangeAt(0);
- ok(range.collapsed, "the selection range isn't collapsed");
- var startNode = range.startContainer;
- is(startNode.nodeType, 1, "the caret isn't set to the div node");
- // XXX maybe, the caret can stay on the other editor if it's better.
- is(startNode, editor,
- "the caret should stay on the other editor");
- ok(selCon.caretVisible,
- "caret isn't visible in the inputTextInEditor");
- // Move focus to the other editor again
- otherEditor.focus();
- is(SpecialPowers.unwrap(fm.focusedElement), otherEditor,
- "the other editor didn't get focus #2");
- // Set selection to the span element in the editor (unfocused)
- range = document.createRange();
- range.setStart(spanInEditor.firstChild, 5);
- selection.removeAllRanges();
- selection.addRange(range);
- is(selection.rangeCount, 1, "selection range is lost from the document");
- is(SpecialPowers.unwrap(fm.focusedElement), otherEditor,
- "the other editor shouldn't lose focus by selection range change");
- ok(selCon.caretVisible, "caret isn't visible in inputTextInEditor");
- // Move focus to the editor
- editor.focus();
- is(SpecialPowers.unwrap(fm.focusedElement), editor,
- "the editor didn't get focus #2");
- is(selection.rangeCount, 1, "selection range is lost from the document");
- range = selection.getRangeAt(0);
- ok(range.collapsed, "the selection range isn't collapsed");
- is(range.startOffset, 5,
- "the caret is moved when the editor was focused (offset)");
- var startNode = range.startContainer;
- is(startNode.nodeType, 3, "the caret isn't in text node");
- is(startNode.parentNode, spanInEditor,
- "the caret is moved when the editor was focused (node)");
- ok(selCon.caretVisible, "caret isn't visible in the editor (spanInEditor)");
-
- // Move focus to each focusable element in the editor.
- function testFocusMove(aSetFocusElementID, aFocusable, aCaretVisible)
- {
- editor.focus();
- is(SpecialPowers.unwrap(fm.focusedElement), editor,
- "testFocusMove: the editor didn't get focus at initializing (" +
- aSetFocusElementID + ")");
- var setFocusElement = document.getElementById(aSetFocusElementID);
- setFocusElement.focus();
- if (aFocusable) {
- is(SpecialPowers.unwrap(fm.focusedElement), setFocusElement,
- "testFocusMove: the " + aSetFocusElementID +
- " didn't get focus");
- } else {
- is(SpecialPowers.unwrap(fm.focusedElement), editor,
- "testFocusMove: the editor lost focus by focus() of the " +
- aSetFocusElementID);
- }
- if (aCaretVisible) {
- ok(selCon.caretVisible,
- "testFocusMove: caret isn't visible when the " +
- aSetFocusElementID + " has focus");
- } else {
- ok(!selCon.caretVisible,
- "testFocusMove: caret is visible when the " +
- aSetFocusElementID + " has focus");
- }
- }
- testFocusMove("inputTextInEditor", true, true);
- testFocusMove("inputTextReadonlyInEditor", true, true);
- // XXX shouldn't the caret become invisible?
- testFocusMove("inputButtonInEditor", true, true);
- testFocusMove("noeditableInEditor", false, true);
- testFocusMove("spanInNoneditableInEditor", false, true);
- testFocusMove("inputTextInNoneditableInEditor", true, true);
- testFocusMove("inputTextReadonlyInNoneditableInEditor", true, true);
- testFocusMove("inputButtonInNoneditableInEditor", true, false);
- testFocusMove("buttonInNoneditableInEditor", true, false);
- testFocusMove("spanInEditor", false, true);
- testFocusMove("inputText", true, true);
- testFocusMove("inputTextReadonly", true, true);
- testFocusMove("inputButton", true, false);
- testFocusMove("button", true, false);
-}
-
-</script>
-</body>
-
-</html>
diff --git a/editor/libeditor/tests/test_contenteditable_text_input_handling.html b/editor/libeditor/tests/test_contenteditable_text_input_handling.html
deleted file mode 100644
index 06b95fbb8..000000000
--- a/editor/libeditor/tests/test_contenteditable_text_input_handling.html
+++ /dev/null
@@ -1,329 +0,0 @@
-<html>
-<head>
- <title>Test for text input event handling on contenteditable editor</title>
- <script type="text/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css"
- href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-</head>
-<body>
-<div id="display">
- <p id="static">static content<input id="inputInStatic"><textarea id="textareaInStatic"></textarea></p>
- <p id="editor"contenteditable="true">content editable<input id="inputInEditor"><textarea id="textareaInEditor"></textarea></p>
-</div>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-</pre>
-
-<script class="testbody" type="application/javascript">
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTests);
-
-const kLF = !navigator.platform.indexOf("Win") ? "\r\n" : "\n";
-
-function runTests()
-{
- var fm = Components.classes["@mozilla.org/focus-manager;1"].
- getService(Components.interfaces.nsIFocusManager);
-
- var listener = {
- handleEvent: function _hv(aEvent)
- {
- aEvent.preventDefault(); // prevent the browser default behavior
- }
- };
- var els = Components.classes["@mozilla.org/eventlistenerservice;1"].
- getService(Components.interfaces.nsIEventListenerService);
- els.addSystemEventListener(window, "keypress", listener, false);
-
- var staticContent = document.getElementById("static");
- staticContent._defaultValue = getTextValue(staticContent);
- staticContent._isFocusable = false;
- staticContent._isEditable = false;
- staticContent._isContentEditable = false;
- staticContent._description = "non-editable p element";
- var inputInStatic = document.getElementById("inputInStatic");
- inputInStatic._defaultValue = getTextValue(inputInStatic);
- inputInStatic._isFocusable = true;
- inputInStatic._isEditable = true;
- inputInStatic._isContentEditable = false;
- inputInStatic._description = "input element in static content";
- var textareaInStatic = document.getElementById("textareaInStatic");
- textareaInStatic._defaultValue = getTextValue(textareaInStatic);
- textareaInStatic._isFocusable = true;
- textareaInStatic._isEditable = true;
- textareaInStatic._isContentEditable = false;
- textareaInStatic._description = "textarea element in static content";
- var editor = document.getElementById("editor");
- editor._defaultValue = getTextValue(editor);
- editor._isFocusable = true;
- editor._isEditable = true;
- editor._isContentEditable = true;
- editor._description = "contenteditable editor";
- var inputInEditor = document.getElementById("inputInEditor");
- inputInEditor._defaultValue = getTextValue(inputInEditor);
- inputInEditor._isFocusable = true;
- inputInEditor._isEditable = true;
- inputInEditor._isContentEditable = false;
- inputInEditor._description = "input element in contenteditable editor";
- var textareaInEditor = document.getElementById("textareaInEditor");
- textareaInEditor._defaultValue = getTextValue(textareaInEditor);
- textareaInEditor._isFocusable = true;
- textareaInEditor._isEditable = true;
- textareaInEditor._isContentEditable = false;
- textareaInEditor._description = "textarea element in contenteditable editor";
-
- function getTextValue(aElement)
- {
- if (aElement == editor) {
- var value = "";
- for (var node = aElement.firstChild; node; node = node.nextSibling) {
- if (node.nodeType == Node.TEXT_NODE) {
- value += node.data;
- } else if (node.nodeType == Node.ELEMENT_NODE) {
- var tagName = node.tagName.toLowerCase();
- switch (tagName) {
- case "input":
- case "textarea":
- value += kLF;
- break;
- default:
- ok(false, "Undefined tag is used in the editor: " + tagName);
- break;
- }
- }
- }
- return value;
- }
- return aElement.value;
- }
-
- function testTextInput(aFocus)
- {
- var when = " when " +
- ((aFocus && aFocus._isFocusable) ? aFocus._description + " has focus" :
- "nobody has focus");
-
- function checkValue(aElement, aInsertedText)
- {
- if (aElement == aFocus && aElement._isEditable) {
- is(getTextValue(aElement), aInsertedText + aElement._defaultValue,
- aElement._description +
- " wasn't edited by synthesized key events" + when);
- return;
- }
- is(getTextValue(aElement), aElement._defaultValue,
- aElement._description +
- " was edited by synthesized key events" + when);
- }
-
- if (aFocus && aFocus._isFocusable) {
- aFocus.focus();
- is(fm.focusedElement, aFocus,
- aFocus._description + " didn't get focus at preparing tests" + when);
- } else {
- var focusedElement = fm.focusedElement;
- if (focusedElement) {
- focusedElement.blur();
- }
- ok(!fm.focusedElement,
- "Failed to blur at preparing tests" + when);
- }
-
- if (aFocus && aFocus._isFocusable) {
- synthesizeKey("A", { });
- synthesizeKey("B", { });
- synthesizeKey("C", { });
- checkValue(staticContent, "ABC");
- checkValue(inputInStatic, "ABC");
- checkValue(textareaInStatic, "ABC");
- checkValue(editor, "ABC");
- checkValue(inputInEditor, "ABC");
- checkValue(textareaInEditor, "ABC");
-
- if (aFocus._isEditable) {
- synthesizeKey("VK_BACK_SPACE", { });
- synthesizeKey("VK_BACK_SPACE", { });
- synthesizeKey("VK_BACK_SPACE", { });
- checkValue(staticContent, "");
- checkValue(inputInStatic, "");
- checkValue(textareaInStatic, "");
- checkValue(editor, "");
- checkValue(inputInEditor, "");
- checkValue(textareaInEditor, "");
- }
- }
-
- // When key events are fired on unfocused editor.
- function testDispatchedKeyEvent(aTarget)
- {
- var targetDescription = " (dispatched to " + aTarget._description + ")";
- function dispatchKeyEvent(aKeyCode, aChar, aTarget)
- {
- var keyEvent = document.createEvent("KeyboardEvent");
- keyEvent.initKeyEvent("keypress", true, true, null, false, false,
- false, false, aKeyCode,
- aChar ? aChar.charCodeAt(0) : 0);
- aTarget.dispatchEvent(keyEvent);
- }
-
- function checkValueForDispatchedKeyEvent(aElement, aInsertedText)
- {
- if (aElement == aTarget && aElement._isEditable &&
- (!aElement._isContentEditable || aElement == aFocus)) {
- is(getTextValue(aElement), aInsertedText + aElement._defaultValue,
- aElement._description +
- " wasn't edited by dispatched key events" +
- when + targetDescription);
- return;
- }
- if (aElement == aTarget) {
- is(getTextValue(aElement), aElement._defaultValue,
- aElement._description +
- " was edited by dispatched key events" +
- when + targetDescription);
- return;
- }
- is(getTextValue(aElement), aElement._defaultValue,
- aElement._description +
- " was edited by key events unexpectedly" +
- when + targetDescription);
- }
-
- dispatchKeyEvent(0, "A", aTarget);
- dispatchKeyEvent(0, "B", aTarget);
- dispatchKeyEvent(0, "C", aTarget);
-
- checkValueForDispatchedKeyEvent(staticContent, "ABC");
- checkValueForDispatchedKeyEvent(inputInStatic, "ABC");
- checkValueForDispatchedKeyEvent(textareaInStatic, "ABC");
- checkValueForDispatchedKeyEvent(editor, "ABC");
- checkValueForDispatchedKeyEvent(inputInEditor, "ABC");
- checkValueForDispatchedKeyEvent(textareaInEditor, "ABC");
-
- const nsIDOMKeyEvent = Components.interfaces.nsIDOMKeyEvent;
- dispatchKeyEvent(nsIDOMKeyEvent.DOM_VK_BACK_SPACE, 0, aTarget);
- dispatchKeyEvent(nsIDOMKeyEvent.DOM_VK_BACK_SPACE, 0, aTarget);
- dispatchKeyEvent(nsIDOMKeyEvent.DOM_VK_BACK_SPACE, 0, aTarget);
-
- checkValueForDispatchedKeyEvent(staticContent, "");
- checkValueForDispatchedKeyEvent(inputInStatic, "");
- checkValueForDispatchedKeyEvent(textareaInStatic, "");
- checkValueForDispatchedKeyEvent(editor, "");
- checkValueForDispatchedKeyEvent(inputInEditor, "");
- checkValueForDispatchedKeyEvent(textareaInEditor, "");
- }
-
- testDispatchedKeyEvent(staticContent);
- testDispatchedKeyEvent(inputInStatic);
- testDispatchedKeyEvent(textareaInStatic);
- testDispatchedKeyEvent(editor);
- testDispatchedKeyEvent(inputInEditor);
- testDispatchedKeyEvent(textareaInEditor);
-
- if (!aFocus._isEditable) {
- return;
- }
-
- // IME
- // input first character
- synthesizeCompositionChange(
- { "composition":
- { "string": "\u3089",
- "clauses":
- [
- { "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
- ]
- },
- "caret": { "start": 1, "length": 0 }
- });
- var queryText = synthesizeQueryTextContent(0, 100);
- ok(queryText, "query text event result is null" + when);
- if (!queryText) {
- return;
- }
- ok(queryText.succeeded, "query text event failed" + when);
- if (!queryText.succeeded) {
- return;
- }
- is(queryText.text, "\u3089" + aFocus._defaultValue,
- "composing text is incorrect" + when);
- var querySelectedText = synthesizeQuerySelectedText();
- ok(querySelectedText, "query selected text event result is null" + when);
- if (!querySelectedText) {
- return;
- }
- ok(querySelectedText.succeeded, "query selected text event failed" + when);
- if (!querySelectedText.succeeded) {
- return;
- }
- is(querySelectedText.offset, 1,
- "query selected text event returns wrong offset" + when);
- is(querySelectedText.text, "",
- "query selected text event returns wrong selected text" + when);
- // commit composition
- synthesizeComposition({ type: "compositioncommitasis" });
- queryText = synthesizeQueryTextContent(0, 100);
- ok(queryText, "query text event result is null after commit" + when);
- if (!queryText) {
- return;
- }
- ok(queryText.succeeded, "query text event failed after commit" + when);
- if (!queryText.succeeded) {
- return;
- }
- is(queryText.text, "\u3089" + aFocus._defaultValue,
- "composing text is incorrect after commit" + when);
- querySelectedText = synthesizeQuerySelectedText();
- ok(querySelectedText,
- "query selected text event result is null after commit" + when);
- if (!querySelectedText) {
- return;
- }
- ok(querySelectedText.succeeded,
- "query selected text event failed after commit" + when);
- if (!querySelectedText.succeeded) {
- return;
- }
- is(querySelectedText.offset, 1,
- "query selected text event returns wrong offset after commit" + when);
- is(querySelectedText.text, "",
- "query selected text event returns wrong selected text after commit" +
- when);
-
- checkValue(staticContent, "\u3089");
- checkValue(inputInStatic, "\u3089");
- checkValue(textareaInStatic, "\u3089");
- checkValue(editor, "\u3089");
- checkValue(inputInEditor, "\u3089");
- checkValue(textareaInEditor, "\u3089");
-
- synthesizeKey("VK_BACK_SPACE", { });
- checkValue(staticContent, "");
- checkValue(inputInStatic, "");
- checkValue(textareaInStatic, "");
- checkValue(editor, "");
- checkValue(inputInEditor, "");
- checkValue(textareaInEditor, "");
- }
-
- testTextInput(inputInStatic);
- testTextInput(textareaInStatic);
- testTextInput(editor);
- testTextInput(inputInEditor);
- testTextInput(textareaInEditor);
-
- els.removeSystemEventListener(window, "keypress", listener, false);
-
- SimpleTest.finish();
-}
-
-</script>
-</body>
-
-</html>
diff --git a/editor/libeditor/tests/test_css_chrome_load_access.html b/editor/libeditor/tests/test_css_chrome_load_access.html
deleted file mode 100644
index b6bb3fb46..000000000
--- a/editor/libeditor/tests/test_css_chrome_load_access.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1245681
--->
-<head>
- <title>Test for Bug 1245681</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1245681">Mozilla Bug 1245681</a>
-<p id="display"></p>
-<div id="content">
- <iframe></iframe>
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-const Ci = SpecialPowers.Ci;
-var styleSheets = null;
-
-function runTest() {
-
- var editframe = window.frames[0];
- var editdoc = editframe.document;
- editdoc.designMode = 'on';
- var editor = SpecialPowers.wrap(editframe)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIEditingSession)
- .getEditorForWindow(editframe);
-
- styleSheets = editor.QueryInterface(Ci.nsIEditorStyleSheets);
-
- // test 1: try to access chrome:// url that is accessible to content
- try
- {
- styleSheets.addOverrideStyleSheet("chrome://browser/content/pageinfo/pageInfo.css");
- ok(true, "should be allowed to access chrome://*.css if contentaccessible");
- }
- catch (ex) {
- ok(false, "should be allowed to access chrome://*.css if contentaccessible");
- }
-
- // test 2: try to access chrome:// url that is *not* accessible to content
- // please note that addOverrideStyleSheet() is triggered by the system,
- // so the load should also *always* succeed.
- try
- {
- styleSheets.addOverrideStyleSheet("chrome://mozapps/skin/aboutNetworking.css");
- ok(true, "should be allowed to access chrome://*.css even if *not* contentaccessible");
- }
- catch (ex) {
- ok(false, "should be allowed to access chrome://*.css even if *not* contentaccessible");
- }
- SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-addLoadEvent(runTest);
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_dom_input_event_on_htmleditor.html b/editor/libeditor/tests/test_dom_input_event_on_htmleditor.html
deleted file mode 100644
index dc8790750..000000000
--- a/editor/libeditor/tests/test_dom_input_event_on_htmleditor.html
+++ /dev/null
@@ -1,172 +0,0 @@
-<html>
-<head>
- <title>Test for input event of text editor</title>
- <script type="text/javascript"
- src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript"
- src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css"
- href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<div id="display">
- <iframe id="editor1" src="data:text/html,<html><body contenteditable id='eventTarget'></body></html>"></iframe>
- <iframe id="editor2" src="data:text/html,<html contenteditable id='eventTarget'><body></body></html>"></iframe>
- <iframe id="editor3" src="data:text/html,<html><body><div contenteditable id='eventTarget'></div></body></html>"></iframe>
- <iframe id="editor4" src="data:text/html,<html contenteditable id='eventTarget'><body><div contenteditable id='editTarget'></div></body></html>"></iframe>
- <iframe id="editor5" src="data:text/html,<html><body id='eventTarget'></body><script>document.designMode='on';</script></html>"></iframe>
-</div>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-</pre>
-
-<script class="testbody" type="application/javascript">
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTests, window);
-
-const kIsMac = navigator.platform.indexOf("Mac") == 0;
-
-function runTests()
-{
- function doTests(aDocument, aWindow, aDescription)
- {
- aDescription += ": ";
- aWindow.focus();
-
- var body = aDocument.body;
-
- var eventTarget = aDocument.getElementById("eventTarget");
- // The event target must be focusable because it's the editing host.
- eventTarget.focus();
-
- var editTarget = aDocument.getElementById("editTarget");
- if (!editTarget) {
- editTarget = eventTarget;
- }
-
- // Root element never can be edit target. If the editTarget is the root
- // element, replace with its body.
- if (editTarget == aDocument.documentElement) {
- editTarget = body;
- }
-
- editTarget.innerHTML = "";
-
- // If the editTarget isn't its editing host, move caret to the start of it.
- if (eventTarget != editTarget) {
- aDocument.getSelection().collapse(editTarget, 0);
- }
-
- var inputEvent = null;
-
- var handler = function (aEvent) {
- is(aEvent.target, eventTarget,
- "input event is fired on unexpected element: " + aEvent.target.tagName);
- ok(!aEvent.cancelable, "input event must not be cancelable");
- ok(aEvent.bubbles, "input event must be bubbles");
- var duration = Math.abs(window.performance.now() - aEvent.timeStamp);
- ok(duration < 30 * 1000,
- "perhaps, timestamp wasn't set correctly :" + aEvent.timeStamp +
- " (expected it to be within 30s of the current time but it " +
- "differed by " + duration + "ms)");
- inputEvent = aEvent;
- };
-
- aWindow.addEventListener("input", handler, true);
-
- inputEvent = null;
- synthesizeKey("a", { }, aWindow);
- is(editTarget.innerHTML, "a", aDescription + "wrong element was edited");
- ok(inputEvent, aDescription + "input event wasn't fired by 'a' key");
- ok(inputEvent.isTrusted, aDescription + "input event by 'a' key wasn't trusted event");
-
- inputEvent = null;
- synthesizeKey("VK_BACK_SPACE", { }, aWindow);
- ok(inputEvent, aDescription + "input event wasn't fired by BackSpace key");
- ok(inputEvent.isTrusted, aDescription + "input event by BackSpace key wasn't trusted event");
-
- inputEvent = null;
- synthesizeKey("B", { shiftKey: true }, aWindow);
- ok(inputEvent, aDescription + "input event wasn't fired by 'B' key");
- ok(inputEvent.isTrusted, aDescription + "input event by 'B' key wasn't trusted event");
-
- inputEvent = null;
- synthesizeKey("VK_RETURN", { }, aWindow);
- ok(inputEvent, aDescription + "input event wasn't fired by Enter key");
- ok(inputEvent.isTrusted, aDescription + "input event by Enter key wasn't trusted event");
-
- inputEvent = null;
- synthesizeKey("C", { shiftKey: true }, aWindow);
- ok(inputEvent, aDescription + "input event wasn't fired by 'C' key");
- ok(inputEvent.isTrusted, aDescription + "input event by 'C' key wasn't trusted event");
-
- inputEvent = null;
- synthesizeKey("VK_RETURN", { }, aWindow);
- ok(inputEvent, aDescription + "input event wasn't fired by Enter key (again)");
- ok(inputEvent.isTrusted, aDescription + "input event by Enter key (again) wasn't trusted event");
-
- inputEvent = null;
- editTarget.innerHTML = "foo-bar";
- ok(!inputEvent, aDescription + "input event was fired by setting value");
-
- inputEvent = null;
- editTarget.innerHTML = "";
- ok(!inputEvent, aDescription + "input event was fired by setting empty value");
-
- inputEvent = null;
- synthesizeKey(" ", { }, aWindow);
- ok(inputEvent, aDescription + "input event wasn't fired by Space key");
- ok(inputEvent.isTrusted, aDescription + "input event by Space key wasn't trusted event");
-
- inputEvent = null;
- synthesizeKey("VK_DELETE", { }, aWindow);
- ok(!inputEvent, aDescription + "input event was fired by Delete key at the end");
-
- inputEvent = null;
- synthesizeKey("VK_LEFT", { }, aWindow);
- ok(!inputEvent, aDescription + "input event was fired by Left key");
-
- inputEvent = null;
- synthesizeKey("VK_DELETE", { }, aWindow);
- ok(inputEvent, aDescription + "input event wasn't fired by Delete key at the start");
- ok(inputEvent.isTrusted, aDescription + "input event by Delete key wasn't trusted event");
-
- inputEvent = null;
- synthesizeKey("z", { accelKey: true }, aWindow);
- ok(inputEvent, aDescription + "input event wasn't fired by Undo");
- ok(inputEvent.isTrusted, aDescription + "input event by Undo wasn't trusted event");
-
- inputEvent = null;
- synthesizeKey("z", { accelKey: true, shiftKey: true }, aWindow);
- ok(inputEvent, aDescription + "input event wasn't fired by Redo");
- ok(inputEvent.isTrusted, aDescription + "input event by Redo wasn't trusted event");
-
- aWindow.removeEventListener("input", handler, true);
- }
-
- doTests(document.getElementById("editor1").contentDocument,
- document.getElementById("editor1").contentWindow,
- "Editor1, body has contenteditable attribute");
- doTests(document.getElementById("editor2").contentDocument,
- document.getElementById("editor2").contentWindow,
- "Editor2, html has contenteditable attribute");
- doTests(document.getElementById("editor3").contentDocument,
- document.getElementById("editor3").contentWindow,
- "Editor3, div has contenteditable attribute");
- doTests(document.getElementById("editor4").contentDocument,
- document.getElementById("editor4").contentWindow,
- "Editor4, html and div has contenteditable attribute");
- doTests(document.getElementById("editor5").contentDocument,
- document.getElementById("editor5").contentWindow,
- "Editor5, html and div has contenteditable attribute");
-
- SimpleTest.finish();
-}
-
-</script>
-</body>
-
-</html>
diff --git a/editor/libeditor/tests/test_dom_input_event_on_texteditor.html b/editor/libeditor/tests/test_dom_input_event_on_texteditor.html
deleted file mode 100644
index abdd5f5d0..000000000
--- a/editor/libeditor/tests/test_dom_input_event_on_texteditor.html
+++ /dev/null
@@ -1,130 +0,0 @@
-<html>
-<head>
- <title>Test for input event of text editor</title>
- <script type="text/javascript"
- src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript"
- src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css"
- href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<div id="display">
- <input type="text" id="input">
- <textarea id="textarea"></textarea>
-</div>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-</pre>
-
-<script class="testbody" type="application/javascript">
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTests, window);
-
-const kIsMac = navigator.platform.indexOf("Mac") == 0;
-
-function runTests()
-{
- function doTests(aElement, aDescription, aIsTextarea)
- {
- aDescription += ": ";
- aElement.focus();
- aElement.value = "";
-
- var inputEvent = null;
-
- var handler = function (aEvent) {
- is(aEvent.target, aElement,
- "input event is fired on unexpected element: " + aEvent.target.tagName);
- ok(!aEvent.cancelable, "input event must not be cancelable");
- ok(aEvent.bubbles, "input event must be bubbles");
- var duration = Math.abs(window.performance.now() - aEvent.timeStamp);
- ok(duration < 30 * 1000,
- "perhaps, timestamp wasn't set correctly :" + aEvent.timeStamp +
- " (expected it to be within 30s of the current time but it " +
- "differed by " + duration + "ms)");
- inputEvent = aEvent;
- };
-
- aElement.addEventListener("input", handler, true);
-
- inputEvent = null;
- synthesizeKey("a", { });
- is(aElement.value, "a", aDescription + "'a' key didn't change the value");
- ok(inputEvent, aDescription + "input event wasn't fired by 'a' key");
- ok(inputEvent.isTrusted, aDescription + "input event by 'a' key wasn't trusted event");
-
- inputEvent = null;
- synthesizeKey("VK_BACK_SPACE", { });
- is(aElement.value, "", aDescription + "BackSpace key didn't remove the value");
- ok(inputEvent, aDescription + "input event wasn't fired by BackSpace key");
- ok(inputEvent.isTrusted, aDescription + "input event by BackSpace key wasn't trusted event");
-
- if (aIsTextarea) {
- inputEvent = null;
- synthesizeKey("VK_RETURN", { });
- is(aElement.value, "\n", aDescription + "Enter key didn't change the value");
- ok(inputEvent, aDescription + "input event wasn't fired by Enter key");
- ok(inputEvent.isTrusted, aDescription + "input event by Enter key wasn't trusted event");
- }
-
- inputEvent = null;
- aElement.value = "foo-bar";
- is(aElement.value, "foo-bar", aDescription + "value wasn't set");
- ok(!inputEvent, aDescription + "input event was fired by setting value");
-
- inputEvent = null;
- aElement.value = "";
- is(aElement.value, "", aDescription + "value wasn't set (empty)");
- ok(!inputEvent, aDescription + "input event was fired by setting empty value");
-
- inputEvent = null;
- synthesizeKey(" ", { });
- is(aElement.value, " ", aDescription + "Space key didn't change the value");
- ok(inputEvent, aDescription + "input event wasn't fired by Space key");
- ok(inputEvent.isTrusted, aDescription + "input event by Space key wasn't trusted event");
-
- inputEvent = null;
- synthesizeKey("VK_DELETE", { });
- is(aElement.value, " ", aDescription + "Delete key removed the value");
- ok(!inputEvent, aDescription + "input event was fired by Delete key at the end");
-
- inputEvent = null;
- synthesizeKey("VK_LEFT", { });
- is(aElement.value, " ", aDescription + "Left key removed the value");
- ok(!inputEvent, aDescription + "input event was fired by Left key");
-
- inputEvent = null;
- synthesizeKey("VK_DELETE", { });
- is(aElement.value, "", aDescription + "Delete key didn't remove the value");
- ok(inputEvent, aDescription + "input event wasn't fired by Delete key at the start");
- ok(inputEvent.isTrusted, aDescription + "input event by Delete key wasn't trusted event");
-
- inputEvent = null;
- synthesizeKey("z", { accelKey: true });
- is(aElement.value, " ", aDescription + "Accel+Z key didn't undo the value");
- ok(inputEvent, aDescription + "input event wasn't fired by Undo");
- ok(inputEvent.isTrusted, aDescription + "input event by Undo wasn't trusted event");
-
- inputEvent = null;
- synthesizeKey("z", { accelKey: true, shiftKey: true });
- is(aElement.value, "", aDescription + "Accel+Y key didn't redo the value");
- ok(inputEvent, aDescription + "input event wasn't fired by Redo");
- ok(inputEvent.isTrusted, aDescription + "input event by Redo wasn't trusted event");
-
- aElement.removeEventListener("input", handler, true);
- }
-
- doTests(document.getElementById("input"), "<input type=\"text\">", false);
- doTests(document.getElementById("textarea"), "<textarea>", true);
-
- SimpleTest.finish();
-}
-
-</script>
-</body>
-
-</html>
diff --git a/editor/libeditor/tests/test_dragdrop.html b/editor/libeditor/tests/test_dragdrop.html
deleted file mode 100644
index c992b7142..000000000
--- a/editor/libeditor/tests/test_dragdrop.html
+++ /dev/null
@@ -1,178 +0,0 @@
-<!doctype html>
-<html>
-
-<head>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css">
-
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <script src="/tests/SimpleTest/EventUtils.js"></script>
-</head>
-
-<body>
- <span id="text" style="font-size: 40px;">Some Text</span>
-
- <input id="input" value="Drag Me">
- <textarea id="textarea">Some Text To Drag</textarea>
- <p id="contenteditable" contenteditable="true">This is some <b id="bold">editable</b> text.</p>
- <p id="nestedce" contenteditable="true"><span id="first"> </span>First letter <span id="noneditable" contenteditable="false">Middle</span> Last part</p>
-
-<script type="application/javascript">
-
-SimpleTest.waitForExplicitFinish();
-
-// This listener allows us to clear the default data for the selection added for the drag.
-var shouldClear = false;
-window.addEventListener("dragstart", function (event) { if (shouldClear) event.dataTransfer.clearData() }, true);
-
-function doTest()
-{
- const htmlContextData = { type: 'text/_moz_htmlcontext',
- data: '<html><body></body></html>' };
- const htmlInfoData = { type: 'text/_moz_htmlinfo', data: '0,0' };
- const htmlData = { type: 'text/html', data: '<span id="text" style="font-size: 40px;">Some Text</span>' };
-
- const htmlContextDataEditable = { type: 'text/_moz_htmlcontext',
- data: '<html><body><p id="contenteditable" contenteditable="true"></p></body></html>' };
-
- var text = document.getElementById("text");
- var input = document.getElementById("input");
- var contenteditable = document.getElementById("contenteditable");
-
- var selection = window.getSelection();
-
- // -------- Test dragging regular text
- selection.selectAllChildren(text);
- var result = synthesizeDragStart(text, [[htmlContextData, htmlInfoData, htmlData,
- {type: "text/plain", data: "Some Text"}]], window, 40, 10);
- is(result, null, "Test dragging regular text");
-
- // -------- Test dragging text from an <input>
- input.setSelectionRange(1, 4);
- result = synthesizeDragStart(input, [[{type: "text/plain", data: "rag"}]], window, 25, 6);
- is(result, null, "Test dragging input");
-
- // -------- Test dragging text from a <textarea>
- textarea.setSelectionRange(1, 7);
- result = synthesizeDragStart(textarea, [[{type: "text/plain", data: "ome Te"}]], window, 25, 6);
- is(result, null, "Test dragging textarea");
- textarea.blur();
-
- // -------- Test dragging text from a contenteditable
- selection.selectAllChildren(contenteditable.childNodes[1]);
- result = synthesizeDragStart(contenteditable.childNodes[1],
- [[htmlContextDataEditable, htmlInfoData,
- {type: 'text/html', data: '<b id="bold">editable</b>' },
- {type: "text/plain", data: "editable"}]], window, 5, 6);
- is(result, null, "Test dragging contenteditable");
- contenteditable.blur();
-
- // -------- Test dragging regular text of text/html to <input>
-
- selection.selectAllChildren(text);
- input.value = "";
- synthesizeDrop(text, input, [], "copy");
- is(input.value, "Some Text", "Drag text/html onto input");
-
- // -------- Test dragging regular text of text/html to disabled <input>
-
- selection.selectAllChildren(text);
- input.value = "";
- input.disabled = true;
- synthesizeDrop(text, input, [], "copy");
- is(input.value, "", "Drag text/html onto disabled input");
- input.disabled = false;
-
- // -------- Test dragging regular text of text/html to readonly <input>
-
- selection.selectAllChildren(text);
- input.readOnly = true;
- synthesizeDrop(text, input, [], "copy");
- is(input.value, "", "Drag text/html onto readonly input");
- input.readOnly = false;
-
- // -------- Test dragging regular text of text/html to <input>. This sets
- // shouldClear to true so that the default drag data is not present
- // and we can use the data passed to synthesizeDrop. This allows
- // testing of a drop with just text/html.
- shouldClear = true;
- selection.selectAllChildren(text);
- input.value = "";
- synthesizeDrop(text, input, [[{type: "text/html", data: "Some <b>Bold<b> Text"}]], "copy");
- is(input.value, "", "Drag text/html onto input");
-
- // -------- Test dragging regular text of text/plain and text/html to <input>
-
- selection.selectAllChildren(text);
- input.value = "";
- synthesizeDrop(text, input, [[{type: "text/html", data: "Some <b>Bold<b> Text"},
- {type: "text/plain", data: "Some Plain Text"}]], "copy");
- is(input.value, "Some Plain Text", "Drag text/html and text/plain onto input");
-
- // -------- Test dragging regular text of text/plain to <textarea>
-
-// XXXndeakin Can't test textareas due to some event handling issue
-// selection.selectAllChildren(text);
-// synthesizeDrop(text, textarea, [[{type: "text/plain", data: "Somewhat Longer Text"}]], "copy");
-// is(textarea.value, "Somewhat Longer Text", "Drag text/plain onto textarea");
-
- // -------- Test dragging special text type of text/plain to contenteditable
-
- selection.selectAllChildren(text);
- synthesizeDrop(text, input, [[{type: "text/x-moz-text-internal", data: "Some Special Text"}]], "copy");
- is(input.value, "Some Plain Text", "Drag text/x-moz-text-internal onto input");
-
- // -------- Test dragging regular text of text/plain to contenteditable
-
- selection.selectAllChildren(text);
- synthesizeDrop(text, contenteditable, [[{type: "text/plain", data: "Sample Text"}]], "copy");
- is(contenteditable.childNodes.length, 3, "Drag text/plain onto contenteditable child nodes");
- is(contenteditable.textContent, "This is some editable text.Sample Text",
- "Drag text/plain onto contenteditable text");
-
- // -------- Test dragging regular text of text/html to contenteditable
-
- selection.selectAllChildren(text);
- synthesizeDrop(text, contenteditable, [[{type: "text/html", data: "Sample <i>Italic</i> Text"}]], "copy");
- is(contenteditable.childNodes.length, 6, "Drag text/html onto contenteditable child nodes");
- is(contenteditable.childNodes[4].tagName, "I", "Drag text/html onto contenteditable italic");
- is(contenteditable.childNodes[4].textContent, "Italic", "Drag text/html onto contenteditable italic text");
-
- // -------- Test dragging contenteditable to <input>
-
- selection.selectAllChildren(document.getElementById("bold"));
- synthesizeDrop(bold, input, [[{type: "text/html", data: "<b>editable</b>"},
- {type: "text/plain", data: "editable"}]], "copy");
- is(input.value, "Some Plain Texteditable", "Move text/html and text/plain from contenteditable onto input");
-
- // -------- Test dragging contenteditable to contenteditable
-
- shouldClear = false;
-
- selection.selectAllChildren(contenteditable.childNodes[4]);
- synthesizeDrop(contenteditable.childNodes[4], contenteditable, [], "copy");
- is(contenteditable.childNodes.length, 7, "Move text/html and text/plain from contenteditable onto itself child nodes");
- is(contenteditable.childNodes[6].tagName, "I", "Move text/html and text/plain from contenteditable onto itself italic");
- is(contenteditable.childNodes[6].textContent, "Italic", "Move text/html and text/plain from contenteditable onto itself text");
-
- // We'd test 'move' here as well as 'copy', but that requires knowledge of
- // the source of the drag which drag simulation doesn't provide.
-
- // -------- Test dragging non-editable nested inside contenteditable to contenteditable
-
- input.focus(); // this resets some state in the selection otherwise an inexplicable error occurs calling selectAllChildren.
- input.blur();
-
- var nonEditable = document.getElementById("noneditable");
- selection.selectAllChildren(nonEditable);
- synthesizeDrop(nonEditable, document.getElementById("first"), [], "copy");
- is(document.getElementById("nestedce").textContent, " MiddleFirst letter Middle Last part",
- "Drag non-editable text/html onto contenteditable text");
-
- SimpleTest.finish();
-}
-
-SimpleTest.waitForFocus(doTest);
-
-</script>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_htmleditor_keyevent_handling.html b/editor/libeditor/tests/test_htmleditor_keyevent_handling.html
deleted file mode 100644
index bfec290a5..000000000
--- a/editor/libeditor/tests/test_htmleditor_keyevent_handling.html
+++ /dev/null
@@ -1,664 +0,0 @@
-<html>
-<head>
- <title>Test for key event handler of HTML editor</title>
- <script type="text/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css"
- href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-</head>
-<body>
-<div id="display">
- <div id="htmlEditor" contenteditable="true"><br></div>
-</div>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-</pre>
-
-<script class="testbody" type="application/javascript">
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTests, window);
-
-var htmlEditor = document.getElementById("htmlEditor");
-
-const kIsMac = navigator.platform.indexOf("Mac") == 0;
-const kIsWin = navigator.platform.indexOf("Win") == 0;
-const kIsLinux = navigator.platform.indexOf("Linux") == 0 || navigator.platform.indexOf("SunOS") == 0 ;
-
-function runTests()
-{
- document.execCommand("stylewithcss", false, "true");
-
- var fm = SpecialPowers.Cc["@mozilla.org/focus-manager;1"].
- getService(SpecialPowers.Ci.nsIFocusManager);
-
- var capturingPhase = { fired: false, prevented: false };
- var bubblingPhase = { fired: false, prevented: false };
-
- var listener = {
- handleEvent: function _hv(aEvent)
- {
- is(aEvent.type, "keypress", "unexpected event is handled");
- switch (aEvent.eventPhase) {
- case aEvent.CAPTURING_PHASE:
- capturingPhase.fired = true;
- capturingPhase.prevented = aEvent.defaultPrevented;
- break;
- case aEvent.BUBBLING_PHASE:
- bubblingPhase.fired = true;
- bubblingPhase.prevented = aEvent.defaultPrevented;
- aEvent.preventDefault(); // prevent the browser default behavior
- break;
- default:
- ok(false, "event is handled in unexpected phase");
- }
- }
- };
-
- function check(aDescription,
- aFiredOnCapture, aFiredOnBubbling, aPreventedOnBubbling)
- {
- function getDesciption(aExpected)
- {
- return aDescription + (aExpected ? " wasn't " : " was ");
- }
- is(capturingPhase.fired, aFiredOnCapture,
- getDesciption(aFiredOnCapture) + "fired on capture phase");
- is(bubblingPhase.fired, aFiredOnBubbling,
- getDesciption(aFiredOnBubbling) + "fired on bubbling phase");
-
- // If the event is fired on bubbling phase and it was already prevented
- // on capture phase, it must be prevented on bubbling phase too.
- if (capturingPhase.prevented) {
- todo(false, aDescription +
- " was consumed already, so, we cannot test the editor behavior actually");
- aPreventedOnBubbling = true;
- }
-
- is(bubblingPhase.prevented, aPreventedOnBubbling,
- getDesciption(aPreventedOnBubbling) + "prevented on bubbling phase");
- }
-
- SpecialPowers.addSystemEventListener(window, "keypress", listener, true);
- SpecialPowers.addSystemEventListener(window, "keypress", listener, false);
-
- function doTest(aElement, aDescription,
- aIsReadonly, aIsTabbable, aIsPlaintext)
- {
- function reset(aText)
- {
- capturingPhase.fired = false;
- capturingPhase.prevented = false;
- bubblingPhase.fired = false;
- bubblingPhase.prevented = false;
- aElement.innerHTML = aText;
- var sel = window.getSelection();
- var range = document.createRange();
- range.setStart(aElement, aElement.childNodes.length);
- sel.removeAllRanges();
- sel.addRange(range);
- }
-
- function resetForIndent(aText)
- {
- capturingPhase.fired = false;
- capturingPhase.prevented = false;
- bubblingPhase.fired = false;
- bubblingPhase.prevented = false;
- aElement.innerHTML = aText;
- var sel = window.getSelection();
- var range = document.createRange();
- var target = document.getElementById("target").firstChild;
- range.setStart(target, target.length);
- sel.removeAllRanges();
- sel.addRange(range);
- }
-
- if (document.activeElement) {
- document.activeElement.blur();
- }
-
- aDescription += ": "
-
- aElement.focus();
- is(SpecialPowers.unwrap(fm.focusedElement), aElement, aDescription + "failed to move focus");
-
- // Backspace key:
- // If editor is readonly, it doesn't consume.
- // If editor is editable, it consumes backspace and shift+backspace.
- // Otherwise, editor doesn't consume the event.
- reset("");
- synthesizeKey("VK_BACK_SPACE", { });
- check(aDescription + "Backspace", true, true, true);
-
- reset("");
- synthesizeKey("VK_BACK_SPACE", { shiftKey: true });
- check(aDescription + "Shift+Backspace", true, true, true);
-
- reset("");
- synthesizeKey("VK_BACK_SPACE", { ctrlKey: true });
- check(aDescription + "Ctrl+Backspace", true, true, aIsReadonly);
-
- reset("");
- synthesizeKey("VK_BACK_SPACE", { altKey: true });
- check(aDescription + "Alt+Backspace", true, true, aIsReadonly || kIsMac);
-
- reset("");
- synthesizeKey("VK_BACK_SPACE", { metaKey: true });
- check(aDescription + "Meta+Backspace", true, true, aIsReadonly);
-
- reset("");
- synthesizeKey("VK_BACK_SPACE", { osKey: true });
- check(aDescription + "OS+Backspace", true, true, aIsReadonly);
-
- // Delete key:
- // If editor is readonly, it doesn't consume.
- // If editor is editable, delete is consumed.
- // Otherwise, editor doesn't consume the event.
- reset("");
- synthesizeKey("VK_DELETE", { });
- check(aDescription + "Delete", true, true, !aIsReadonly || kIsMac);
-
- reset("");
- synthesizeKey("VK_DELETE", { shiftKey: true });
- check(aDescription + "Shift+Delete", true, true, kIsMac);
-
- reset("");
- synthesizeKey("VK_DELETE", { ctrlKey: true });
- check(aDescription + "Ctrl+Delete", true, true, false);
-
- reset("");
- synthesizeKey("VK_DELETE", { altKey: true });
- check(aDescription + "Alt+Delete", true, true, kIsMac);
-
- reset("");
- synthesizeKey("VK_DELETE", { metaKey: true });
- check(aDescription + "Meta+Delete", true, true, false);
-
- reset("");
- synthesizeKey("VK_DELETE", { osKey: true });
- check(aDescription + "OS+Delete", true, true, false);
-
- // Return key:
- // If editor is readonly, it doesn't consume.
- // If editor is editable and not single line editor, it consumes Return
- // and Shift+Return.
- // Otherwise, editor doesn't consume the event.
- reset("a");
- synthesizeKey("VK_RETURN", { });
- check(aDescription + "Return",
- true, true, !aIsReadonly);
- is(aElement.innerHTML, aIsReadonly ? "a" : "a<br><br>",
- aDescription + "Return");
-
- reset("a");
- synthesizeKey("VK_RETURN", { shiftKey: true });
- check(aDescription + "Shift+Return",
- true, true, !aIsReadonly);
- is(aElement.innerHTML, aIsReadonly ? "a" : "a<br><br>",
- aDescription + "Shift+Return");
-
- reset("a");
- synthesizeKey("VK_RETURN", { ctrlKey: true });
- check(aDescription + "Ctrl+Return", true, true, false);
- is(aElement.innerHTML, "a", aDescription + "Ctrl+Return");
-
- reset("a");
- synthesizeKey("VK_RETURN", { altKey: true });
- check(aDescription + "Alt+Return", true, true, false);
- is(aElement.innerHTML, "a", aDescription + "Alt+Return");
-
- reset("a");
- synthesizeKey("VK_RETURN", { metaKey: true });
- check(aDescription + "Meta+Return", true, true, false);
- is(aElement.innerHTML, "a", aDescription + "Meta+Return");
-
- reset("a");
- synthesizeKey("VK_RETURN", { osKey: true });
- check(aDescription + "OS+Return", true, true, false);
- is(aElement.innerHTML, "a", aDescription + "OS+Return");
-
- // Tab key:
- // If editor is tabbable, editor doesn't consume all tab key events.
- // Otherwise, editor consumes tab key event without any modifier keys.
- reset("a");
- synthesizeKey("VK_TAB", { });
- check(aDescription + "Tab",
- true, true, !aIsTabbable && !aIsReadonly);
- is(aElement.innerHTML,
- aIsTabbable || aIsReadonly ? "a" :
- aIsPlaintext ? "a\t" : "a&nbsp;&nbsp;&nbsp; <br>",
- aDescription + "Tab");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Tab)");
-
- reset("a");
- synthesizeKey("VK_TAB", { shiftKey: true });
- check(aDescription + "Shift+Tab", true, true, false);
- is(aElement.innerHTML, "a", aDescription + "Shift+Tab");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Shift+Tab)");
-
- // Ctrl+Tab should be consumed by tabbrowser at keydown, so, keypress
- // event should never be fired.
- reset("a");
- synthesizeKey("VK_TAB", { ctrlKey: true });
- check(aDescription + "Ctrl+Tab", false, false, false);
- is(aElement.innerHTML, "a", aDescription + "Ctrl+Tab");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Ctrl+Tab)");
-
- reset("a");
- synthesizeKey("VK_TAB", { altKey: true });
- check(aDescription + "Alt+Tab", true, true, false);
- is(aElement.innerHTML, "a", aDescription + "Alt+Tab");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Alt+Tab)");
-
- reset("a");
- synthesizeKey("VK_TAB", { metaKey: true });
- check(aDescription + "Meta+Tab", true, true, false);
- is(aElement.innerHTML, "a", aDescription + "Meta+Tab");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Meta+Tab)");
-
- reset("a");
- synthesizeKey("VK_TAB", { osKey: true });
- check(aDescription + "OS+Tab", true, true, false);
- is(aElement.innerHTML, "a", aDescription + "OS+Tab");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (OS+Tab)");
-
- // Indent/Outdent tests:
- // UL
- resetForIndent("<ul><li id=\"target\">ul list item</li></ul>");
- synthesizeKey("VK_TAB", { });
- check(aDescription + "Tab on UL",
- true, true, !aIsTabbable && !aIsReadonly);
- is(aElement.innerHTML,
- aIsReadonly || aIsTabbable ?
- "<ul><li id=\"target\">ul list item</li></ul>" :
- aIsPlaintext ? "<ul><li id=\"target\">ul list item\t</li></ul>" :
- "<ul><ul><li id=\"target\">ul list item</li></ul></ul>",
- aDescription + "Tab on UL");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Tab on UL)");
- synthesizeKey("VK_TAB", { shiftKey: true });
- check(aDescription + "Shift+Tab after Tab on UL",
- true, true, !aIsTabbable && !aIsReadonly && !aIsPlaintext);
- is(aElement.innerHTML,
- aIsReadonly || aIsTabbable || (!aIsPlaintext) ?
- "<ul><li id=\"target\">ul list item</li></ul>" :
- "<ul><li id=\"target\">ul list item\t</li></ul>",
- aDescription + "Shift+Tab after Tab on UL");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Shift+Tab after Tab on UL)");
-
- resetForIndent("<ul><li id=\"target\">ul list item</li></ul>");
- synthesizeKey("VK_TAB", { shiftKey: true });
- check(aDescription + "Shift+Tab on UL",
- true, true, !aIsTabbable && !aIsReadonly && !aIsPlaintext);
- is(aElement.innerHTML,
- aIsReadonly || aIsTabbable || aIsPlaintext ?
- "<ul><li id=\"target\">ul list item</li></ul>" : "ul list item",
- aDescription + "Shift+Tab on UL");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Shift+Tab on UL)");
-
- // Ctrl+Tab should be consumed by tabbrowser at keydown, so, keypress
- // event should never be fired.
- resetForIndent("<ul><li id=\"target\">ul list item</li></ul>");
- synthesizeKey("VK_TAB", { ctrlKey: true });
- check(aDescription + "Ctrl+Tab on UL", false, false, false);
- is(aElement.innerHTML, "<ul><li id=\"target\">ul list item</li></ul>",
- aDescription + "Ctrl+Tab on UL");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Ctrl+Tab on UL)");
-
- resetForIndent("<ul><li id=\"target\">ul list item</li></ul>");
- synthesizeKey("VK_TAB", { altKey: true });
- check(aDescription + "Alt+Tab on UL", true, true, false);
- is(aElement.innerHTML, "<ul><li id=\"target\">ul list item</li></ul>",
- aDescription + "Alt+Tab on UL");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Alt+Tab on UL)");
-
- resetForIndent("<ul><li id=\"target\">ul list item</li></ul>");
- synthesizeKey("VK_TAB", { metaKey: true });
- check(aDescription + "Meta+Tab on UL", true, true, false);
- is(aElement.innerHTML, "<ul><li id=\"target\">ul list item</li></ul>",
- aDescription + "Meta+Tab on UL");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Meta+Tab on UL)");
-
- resetForIndent("<ul><li id=\"target\">ul list item</li></ul>");
- synthesizeKey("VK_TAB", { osKey: true });
- check(aDescription + "OS+Tab on UL", true, true, false);
- is(aElement.innerHTML, "<ul><li id=\"target\">ul list item</li></ul>",
- aDescription + "OS+Tab on UL");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (OS+Tab on UL)");
-
- // OL
- resetForIndent("<ol><li id=\"target\">ol list item</li></ol>");
- synthesizeKey("VK_TAB", { });
- check(aDescription + "Tab on OL",
- true, true, !aIsTabbable && !aIsReadonly);
- is(aElement.innerHTML,
- aIsReadonly || aIsTabbable ?
- "<ol><li id=\"target\">ol list item</li></ol>" :
- aIsPlaintext ? "<ol><li id=\"target\">ol list item\t</li></ol>" :
- "<ol><ol><li id=\"target\">ol list item</li></ol></ol>",
- aDescription + "Tab on OL");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Tab on OL)");
- synthesizeKey("VK_TAB", { shiftKey: true });
- check(aDescription + "Shift+Tab after Tab on OL",
- true, true, !aIsTabbable && !aIsReadonly && !aIsPlaintext);
- is(aElement.innerHTML,
- aIsReadonly || aIsTabbable || (!aIsPlaintext) ?
- "<ol><li id=\"target\">ol list item</li></ol>" :
- "<ol><li id=\"target\">ol list item\t</li></ol>",
- aDescription + "Shift+Tab after Tab on OL");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Shift+Tab after Tab on OL)");
-
- resetForIndent("<ol><li id=\"target\">ol list item</li></ol>");
- synthesizeKey("VK_TAB", { shiftKey: true });
- check(aDescription + "Shift+Tab on OL",
- true, true, !aIsTabbable && !aIsReadonly && !aIsPlaintext);
- is(aElement.innerHTML,
- aIsReadonly || aIsTabbable || aIsPlaintext ?
- "<ol><li id=\"target\">ol list item</li></ol>" : "ol list item",
- aDescription + "Shfit+Tab on OL");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Shift+Tab on OL)");
-
- // Ctrl+Tab should be consumed by tabbrowser at keydown, so, keypress
- // event should never be fired.
- resetForIndent("<ol><li id=\"target\">ol list item</li></ol>");
- synthesizeKey("VK_TAB", { ctrlKey: true });
- check(aDescription + "Ctrl+Tab on OL", false, false, false);
- is(aElement.innerHTML, "<ol><li id=\"target\">ol list item</li></ol>",
- aDescription + "Ctrl+Tab on OL");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Ctrl+Tab on OL)");
-
- resetForIndent("<ol><li id=\"target\">ol list item</li></ol>");
- synthesizeKey("VK_TAB", { altKey: true });
- check(aDescription + "Alt+Tab on OL", true, true, false);
- is(aElement.innerHTML, "<ol><li id=\"target\">ol list item</li></ol>",
- aDescription + "Alt+Tab on OL");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Alt+Tab on OL)");
-
- resetForIndent("<ol><li id=\"target\">ol list item</li></ol>");
- synthesizeKey("VK_TAB", { metaKey: true });
- check(aDescription + "Meta+Tab on OL", true, true, false);
- is(aElement.innerHTML, "<ol><li id=\"target\">ol list item</li></ol>",
- aDescription + "Meta+Tab on OL");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Meta+Tab on OL)");
-
- resetForIndent("<ol><li id=\"target\">ol list item</li></ol>");
- synthesizeKey("VK_TAB", { osKey: true });
- check(aDescription + "OS+Tab on OL", true, true, false);
- is(aElement.innerHTML, "<ol><li id=\"target\">ol list item</li></ol>",
- aDescription + "OS+Tab on OL");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (OS+Tab on OL)");
-
- // TD
- resetForIndent("<table><tr><td id=\"target\">td</td></tr></table>");
- synthesizeKey("VK_TAB", { });
- check(aDescription + "Tab on TD",
- true, true, !aIsTabbable && !aIsReadonly);
- is(aElement.innerHTML,
- aIsTabbable || aIsReadonly ?
- "<table><tbody><tr><td id=\"target\">td</td></tr></tbody></table>" :
- aIsPlaintext ? "<table><tbody><tr><td id=\"target\">td\t</td></tr></tbody></table>" :
- "<table><tbody><tr><td id=\"target\">td</td></tr><tr><td style=\"vertical-align: top;\"><br></td></tr></tbody></table>",
- aDescription + "Tab on TD");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Tab on TD)");
- synthesizeKey("VK_TAB", { shiftKey: true });
- check(aDescription + "Shift+Tab after Tab on TD",
- true, true, !aIsTabbable && !aIsReadonly && !aIsPlaintext);
- is(aElement.innerHTML,
- aIsTabbable || aIsReadonly ?
- "<table><tbody><tr><td id=\"target\">td</td></tr></tbody></table>" :
- aIsPlaintext ? "<table><tbody><tr><td id=\"target\">td\t</td></tr></tbody></table>" :
- "<table><tbody><tr><td id=\"target\">td</td></tr><tr><td style=\"vertical-align: top;\"><br></td></tr></tbody></table>",
- aDescription + "Shift+Tab after Tab on TD");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Shift+Tab after Tab on TD)");
-
- resetForIndent("<table><tr><td id=\"target\">td</td></tr></table>");
- synthesizeKey("VK_TAB", { shiftKey: true });
- check(aDescription + "Shift+Tab on TD", true, true, false);
- is(aElement.innerHTML,
- "<table><tbody><tr><td id=\"target\">td</td></tr></tbody></table>",
- aDescription + "Shift+Tab on TD");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Shift+Tab on TD)");
-
- // Ctrl+Tab should be consumed by tabbrowser at keydown, so, keypress
- // event should never be fired.
- resetForIndent("<table><tr><td id=\"target\">td</td></tr></table>");
- synthesizeKey("VK_TAB", { ctrlKey: true });
- check(aDescription + "Ctrl+Tab on TD", false, false, false);
- is(aElement.innerHTML,
- "<table><tbody><tr><td id=\"target\">td</td></tr></tbody></table>",
- aDescription + "Ctrl+Tab on TD");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Ctrl+Tab on TD)");
-
- resetForIndent("<table><tr><td id=\"target\">td</td></tr></table>");
- synthesizeKey("VK_TAB", { altKey: true });
- check(aDescription + "Alt+Tab on TD", true, true, false);
- is(aElement.innerHTML,
- "<table><tbody><tr><td id=\"target\">td</td></tr></tbody></table>",
- aDescription + "Alt+Tab on TD");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Alt+Tab on TD)");
-
- resetForIndent("<table><tr><td id=\"target\">td</td></tr></table>");
- synthesizeKey("VK_TAB", { metaKey: true });
- check(aDescription + "Meta+Tab on TD", true, true, false);
- is(aElement.innerHTML,
- "<table><tbody><tr><td id=\"target\">td</td></tr></tbody></table>",
- aDescription + "Meta+Tab on TD");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Meta+Tab on TD)");
-
- resetForIndent("<table><tr><td id=\"target\">td</td></tr></table>");
- synthesizeKey("VK_TAB", { osKey: true });
- check(aDescription + "OS+Tab on TD", true, true, false);
- is(aElement.innerHTML,
- "<table><tbody><tr><td id=\"target\">td</td></tr></tbody></table>",
- aDescription + "OS+Tab on TD");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (OS+Tab on TD)");
-
- // TH
- resetForIndent("<table><tr><th id=\"target\">th</th></tr></table>");
- synthesizeKey("VK_TAB", { });
- check(aDescription + "Tab on TH",
- true, true, !aIsTabbable && !aIsReadonly);
- is(aElement.innerHTML,
- aIsTabbable || aIsReadonly ?
- "<table><tbody><tr><th id=\"target\">th</th></tr></tbody></table>" :
- aIsPlaintext ? "<table><tbody><tr><th id=\"target\">th\t</th></tr></tbody></table>" :
- "<table><tbody><tr><th id=\"target\">th</th></tr><tr><td style=\"vertical-align: top;\"><br></td></tr></tbody></table>",
- aDescription + "Tab on TH");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Tab on TH)");
- synthesizeKey("VK_TAB", { shiftKey: true });
- check(aDescription + "Shift+Tab after Tab on TH",
- true, true, !aIsTabbable && !aIsReadonly && !aIsPlaintext);
- is(aElement.innerHTML,
- aIsTabbable || aIsReadonly ?
- "<table><tbody><tr><th id=\"target\">th</th></tr></tbody></table>" :
- aIsPlaintext ? "<table><tbody><tr><th id=\"target\">th\t</th></tr></tbody></table>" :
- "<table><tbody><tr><th id=\"target\">th</th></tr><tr><td style=\"vertical-align: top;\"><br></td></tr></tbody></table>",
- aDescription + "Shift+Tab after Tab on TH");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Shift+Tab after Tab on TH)");
-
- resetForIndent("<table><tr><th id=\"target\">th</th></tr></table>");
- synthesizeKey("VK_TAB", { shiftKey: true });
- check(aDescription + "Shift+Tab on TH", true, true, false);
- is(aElement.innerHTML,
- "<table><tbody><tr><th id=\"target\">th</th></tr></tbody></table>",
- aDescription + "Shift+Tab on TH");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Shift+Tab on TH)");
-
- // Ctrl+Tab should be consumed by tabbrowser at keydown, so, keypress
- // event should never be fired.
- resetForIndent("<table><tr><th id=\"target\">th</th></tr></table>");
- synthesizeKey("VK_TAB", { ctrlKey: true });
- check(aDescription + "Ctrl+Tab on TH", false, false, false);
- is(aElement.innerHTML,
- "<table><tbody><tr><th id=\"target\">th</th></tr></tbody></table>",
- aDescription + "Ctrl+Tab on TH");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Ctrl+Tab on TH)");
-
- resetForIndent("<table><tr><th id=\"target\">th</th></tr></table>");
- synthesizeKey("VK_TAB", { altKey: true });
- check(aDescription + "Alt+Tab on TH", true, true, false);
- is(aElement.innerHTML,
- "<table><tbody><tr><th id=\"target\">th</th></tr></tbody></table>",
- aDescription + "Alt+Tab on TH");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Alt+Tab on TH)");
-
- resetForIndent("<table><tr><th id=\"target\">th</th></tr></table>");
- synthesizeKey("VK_TAB", { metaKey: true });
- check(aDescription + "Meta+Tab on TH", true, true, false);
- is(aElement.innerHTML,
- "<table><tbody><tr><th id=\"target\">th</th></tr></tbody></table>",
- aDescription + "Meta+Tab on TH");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Meta+Tab on TH)");
-
- resetForIndent("<table><tr><th id=\"target\">th</th></tr></table>");
- synthesizeKey("VK_TAB", { osKey: true });
- check(aDescription + "OS+Tab on TH", true, true, false);
- is(aElement.innerHTML,
- "<table><tbody><tr><th id=\"target\">th</th></tr></tbody></table>",
- aDescription + "OS+Tab on TH");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (OS+Tab on TH)");
-
- // Esc key:
- // In all cases, esc key events are not consumed
- reset("abc");
- synthesizeKey("VK_ESCAPE", { });
- check(aDescription + "Esc", true, true, false);
-
- reset("abc");
- synthesizeKey("VK_ESCAPE", { shiftKey: true });
- check(aDescription + "Shift+Esc", true, true, false);
-
- reset("abc");
- synthesizeKey("VK_ESCAPE", { ctrlKey: true });
- check(aDescription + "Ctrl+Esc", true, true, false);
-
- reset("abc");
- synthesizeKey("VK_ESCAPE", { altKey: true });
- check(aDescription + "Alt+Esc", true, true, false);
-
- reset("abc");
- synthesizeKey("VK_ESCAPE", { metaKey: true });
- check(aDescription + "Meta+Esc", true, true, false);
-
- reset("abc");
- synthesizeKey("VK_ESCAPE", { osKey: true });
- check(aDescription + "OS+Esc", true, true, false);
-
- // typical typing tests:
- reset("");
- synthesizeKey("M", { shiftKey: true });
- check(aDescription + "M", true, true, !aIsReadonly);
- synthesizeKey("o", { });
- check(aDescription + "o", true, true, !aIsReadonly);
- synthesizeKey("z", { });
- check(aDescription + "z", true, true, !aIsReadonly);
- synthesizeKey("i", { });
- check(aDescription + "i", true, true, !aIsReadonly);
- synthesizeKey("l", { });
- check(aDescription + "l", true, true, !aIsReadonly);
- synthesizeKey("l", { });
- check(aDescription + "l", true, true, !aIsReadonly);
- synthesizeKey("a", { });
- check(aDescription + "a", true, true, !aIsReadonly);
- synthesizeKey(" ", { });
- check(aDescription + "' '", true, true, !aIsReadonly);
- is(aElement.innerHTML,
- aIsReadonly ? "" : aIsPlaintext ? "Mozilla " : "Mozilla <br>",
- aDescription + "typed \"Mozilla \"");
- }
-
- doTest(htmlEditor, "contenteditable=\"true\"", false, true, false);
-
- const nsIPlaintextEditor = SpecialPowers.Ci.nsIPlaintextEditor;
- var editor = SpecialPowers.wrap(window).
- QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).
- getInterface(SpecialPowers.Ci.nsIWebNavigation).
- QueryInterface(SpecialPowers.Ci.nsIDocShell).editor;
- var flags = editor.flags;
- // readonly
- editor.flags = flags | nsIPlaintextEditor.eEditorReadonlyMask;
- doTest(htmlEditor, "readonly HTML editor", true, true, false);
-
- // non-tabbable
- editor.flags = flags & ~(nsIPlaintextEditor.eEditorAllowInteraction);
- doTest(htmlEditor, "non-tabbable HTML editor", false, false, false);
-
- // readonly and non-tabbable
- editor.flags =
- (flags | nsIPlaintextEditor.eEditorReadonlyMask) &
- ~(nsIPlaintextEditor.eEditorAllowInteraction);
- doTest(htmlEditor, "readonly and non-tabbable HTML editor",
- true, false, false);
-
- // plaintext
- editor.flags = flags | nsIPlaintextEditor.eEditorPlaintextMask;
- doTest(htmlEditor, "HTML editor but plaintext mode", false, true, true);
-
- // plaintext and non-tabbable
- editor.flags = (flags | nsIPlaintextEditor.eEditorPlaintextMask) &
- ~(nsIPlaintextEditor.eEditorAllowInteraction);
- doTest(htmlEditor, "non-tabbable HTML editor but plaintext mode",
- false, false, true);
-
-
- // readonly and plaintext
- editor.flags = flags | nsIPlaintextEditor.eEditorPlaintextMask |
- nsIPlaintextEditor.eEditorReadonlyMask;
- doTest(htmlEditor, "readonly HTML editor but plaintext mode",
- true, true, true);
-
- // readonly, plaintext and non-tabbable
- editor.flags = (flags | nsIPlaintextEditor.eEditorPlaintextMask |
- nsIPlaintextEditor.eEditorReadonlyMask) &
- ~(nsIPlaintextEditor.eEditorAllowInteraction);
- doTest(htmlEditor, "readonly and non-tabbable HTML editor but plaintext mode",
- true, false, true);
-
- SpecialPowers.removeSystemEventListener(window, "keypress", listener, true);
- SpecialPowers.removeSystemEventListener(window, "keypress", listener, false);
-
- SimpleTest.finish();
-}
-
-</script>
-</body>
-
-</html>
diff --git a/editor/libeditor/tests/test_keypress_untrusted_event.html b/editor/libeditor/tests/test_keypress_untrusted_event.html
deleted file mode 100644
index 6875c5a33..000000000
--- a/editor/libeditor/tests/test_keypress_untrusted_event.html
+++ /dev/null
@@ -1,99 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=622245
--->
-<head>
- <title>Test for untrusted keypress events</title>
- <script type="application/javascript" src="/MochiKit/packed.js"></script>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=622245">Mozilla Bug 622245</a>
-<p id="display"></p>
-<div id="content">
-<input id="i"><br>
-<textarea id="t"></textarea><br>
-<div id="d" contenteditable style="min-height: 1em;"></div>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 674770 **/
-SimpleTest.waitForExplicitFinish();
-
-var input = document.getElementById("i");
-var textarea = document.getElementById("t");
-var div = document.getElementById("d");
-
-addLoadEvent(function() {
- input.focus();
-
- SimpleTest.executeSoon(function() {
- input.addEventListener("keypress",
- function(aEvent) {
- input.removeEventListener("keypress", arguments.callee, false);
- is(aEvent.target, input,
- "The keypress event target isn't the input element");
-
- SimpleTest.executeSoon(function() {
- is(input.value, "",
- "Did keypress event cause modifying the input element?");
- textarea.focus();
- SimpleTest.executeSoon(runTextareaTest);
- });
- }, false);
- var keypress = document.createEvent("KeyboardEvent");
- keypress.initKeyEvent("keypress", true, true, document.defaultView,
- false, false, false, false, 0, "a".charCodeAt(0));
- input.dispatchEvent(keypress);
- });
-});
-
-function runTextareaTest()
-{
- textarea.addEventListener("keypress",
- function(aEvent) {
- textarea.removeEventListener("keypress", arguments.callee, false);
- is(aEvent.target, textarea,
- "The keypress event target isn't the textarea element");
-
- SimpleTest.executeSoon(function() {
- is(textarea.value, "",
- "Did keypress event cause modifying the textarea element?");
- div.focus();
- SimpleTest.executeSoon(runContentediableTest);
- });
- }, false);
- var keypress = document.createEvent("KeyboardEvent");
- keypress.initKeyEvent("keypress", true, true, document.defaultView,
- false, false, false, false, 0, "b".charCodeAt(0));
- textarea.dispatchEvent(keypress);
-}
-
-function runContentediableTest()
-{
- div.addEventListener("keypress",
- function(aEvent) {
- div.removeEventListener("keypress", arguments.callee, false);
- is(aEvent.target, div,
- "The keypress event target isn't the div element");
-
- SimpleTest.executeSoon(function() {
- is(div.innerHTML, "",
- "Did keypress event cause modifying the div element?");
-
- SimpleTest.finish();
- });
- }, false);
- var keypress = document.createEvent("KeyboardEvent");
- keypress.initKeyEvent("keypress", true, true, document.defaultView,
- false, false, false, false, 0, "c".charCodeAt(0));
- div.dispatchEvent(keypress);
-}
-
-</script>
-</pre>
-</body>
-</html>
diff --git a/editor/libeditor/tests/test_pasteImgTextarea.html b/editor/libeditor/tests/test_pasteImgTextarea.html
deleted file mode 100644
index 3168ae729..000000000
--- a/editor/libeditor/tests/test_pasteImgTextarea.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!doctype html>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<script src="/tests/SimpleTest/SpawnTask.js"></script>
-<img id="i" src="green.png">
-<textarea id="t"></textarea>
-
-<script>
-let loaded = new Promise(resolve => addLoadEvent(resolve));
- add_task(function*() {
- yield loaded;
- SpecialPowers.setCommandNode(window, document.getElementById("i"));
- SpecialPowers.doCommand(window, "cmd_copyImageContents");
- let input = document.getElementById("t");
- input.focus();
- var controller =
- SpecialPowers.wrap(input).controllers.getControllerForCommand("cmd_paste");
- is(controller.isCommandEnabled("cmd_paste"), true,
- "paste should be enabled in html textareas when an image is on the clipboard");
- });
-</script>
diff --git a/editor/libeditor/tests/test_pasteImgTextarea.xul b/editor/libeditor/tests/test_pasteImgTextarea.xul
deleted file mode 100644
index 545027aa3..000000000
--- a/editor/libeditor/tests/test_pasteImgTextarea.xul
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
-<window xmlns:html="http://www.w3.org/1999/xhtml"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
- <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
- <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
-
- <body xmlns="http://www.w3.org/1999/xhtml">
- <html:img id="i" src="green.png" />
- <html:textarea id="t"></html:textarea>
- </body>
- <script type="text/javascript"><![CDATA[
- let loaded = new Promise(resolve => addLoadEvent(resolve));
- add_task(function*() {
- yield loaded;
- SpecialPowers.setCommandNode(window, document.getElementById("i"));
- SpecialPowers.doCommand(window, "cmd_copyImageContents");
- let input = document.getElementById("t");
- input.focus();
- var controller =
- SpecialPowers.wrap(input).controllers.getControllerForCommand("cmd_paste");
- is(controller.isCommandEnabled("cmd_paste"), false,
- "paste should not be enabled in xul textareas when an image is on the clipboard");
- });
- ]]></script>
-</window>
diff --git a/editor/libeditor/tests/test_root_element_replacement.html b/editor/libeditor/tests/test_root_element_replacement.html
deleted file mode 100644
index f8b6f4336..000000000
--- a/editor/libeditor/tests/test_root_element_replacement.html
+++ /dev/null
@@ -1,148 +0,0 @@
-<html>
-<head>
- <title>Test for root element replacement</title>
- <script type="text/javascript"
- src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript"
- src="/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css"
- href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<p id="display">
-</p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-</pre>
-
-<script class="testbody" type="application/javascript">
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTest);
-
-function runDesignModeTest(aDoc, aFocus, aNewSource)
-{
- aDoc.designMode = "on";
-
- if (aFocus) {
- aDoc.documentElement.focus();
- }
-
- aDoc.open();
- aDoc.write(aNewSource);
- aDoc.close();
- aDoc.documentElement.focus();
-}
-
-function runContentEditableTest(aDoc, aFocus, aNewSource)
-{
- if (aFocus) {
- aDoc.body.setAttribute("contenteditable", "true");
- aDoc.body.focus();
- }
-
- aDoc.open();
- aDoc.write(aNewSource);
- aDoc.close();
- aDoc.getElementById("focus").focus();
-}
-
-var gTestIndex = 0;
-
-const kTests = [
- { description: "Replace to '<body></body>', designMode",
- initializer: runDesignModeTest,
- args: [ "<body></body>" ] },
- { description: "Replace to '<html><body></body></html>', designMode",
- initializer: runDesignModeTest,
- args: [ "<html><body></body></html>" ] },
- { description: "Replace to '<html>&nbsp;<body></body></html>', designMode",
- initializer: runDesignModeTest,
- args: [ "<html> <body></body></html>" ] },
- { description: "Replace to '&nbsp;<html>&nbsp;<body></body></html>', designMode",
- initializer: runDesignModeTest,
- args: [ " <html> <body></body></html>" ] },
-
- { description: "Replace to '<html contenteditable='true'><body></body></html>",
- initializer: runContentEditableTest,
- args: [ "<html contenteditable='true' id='focus'><body></body></html>" ] },
- { description: "Replace to '<html><body contenteditable='true'></body></html>",
- initializer: runContentEditableTest,
- args: [ "<html><body contenteditable='true' id='focus'></body></html>" ] },
- { description: "Replace to '<body contenteditable='true'></body>",
- initializer: runContentEditableTest,
- args: [ "<body contenteditable='true' id='focus'></body>" ] },
-];
-
-var gIFrame;
-var gSetFocusToIFrame = false;
-
-function onLoadIFrame()
-{
- var frameDoc = gIFrame.contentWindow.document;
-
- var selCon = SpecialPowers.wrap(gIFrame).contentWindow.
- QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).
- getInterface(SpecialPowers.Ci.nsIWebNavigation).
- QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).
- getInterface(SpecialPowers.Ci.nsISelectionDisplay).
- QueryInterface(SpecialPowers.Ci.nsISelectionController);
- var utils = SpecialPowers.getDOMWindowUtils(window);
- const nsIDOMNode = SpecialPowers.Ci.nsIDOMNode;
-
- // move focus to the HTML editor
- const kTest = kTests[gTestIndex];
- ok(true, "Running " + kTest.description);
- if (kTest.args.length == 1) {
- kTest.initializer(frameDoc, gSetFocusToIFrame, kTest.args[0]);
- ok(selCon.caretVisible, "caret isn't visible -- " + kTest.description);
- } else {
- ok(false, "kTests is broken at index=" + gTestIndex);
- }
-
- is(utils.IMEStatus, utils.IME_STATUS_ENABLED,
- "IME isn't enabled -- " + kTest.description);
- synthesizeKey("A", { }, gIFrame.contentWindow);
- synthesizeKey("B", { }, gIFrame.contentWindow);
- synthesizeKey("C", { }, gIFrame.contentWindow);
- var content = frameDoc.body.firstChild;
- ok(content, "body doesn't have contents -- " + kTest.description);
- if (content) {
- is(content.nodeType, nsIDOMNode.TEXT_NODE,
- "the content of body isn't text node -- " + kTest.description);
- if (content.nodeType == nsIDOMNode.TEXT_NODE) {
- is(content.data, "ABC",
- "the content of body text isn't 'ABC' -- " + kTest.description);
- is(frameDoc.body.innerHTML, "ABC",
- "the innerHTML of body isn't 'ABC' -- " + kTest.description);
- }
- }
-
- document.getElementById("display").removeChild(gIFrame);
-
- // Do next test or finish the tests.
- if (++gTestIndex < kTests.length) {
- setTimeout(runTest, 0);
- } else if (!gSetFocusToIFrame) {
- gSetFocusToIFrame = true;
- gTestIndex = 0;
- setTimeout(runTest, 0);
- } else {
- SimpleTest.finish();
- }
-}
-
-function runTest()
-{
- gIFrame = document.createElement("iframe");
- document.getElementById("display").appendChild(gIFrame);
- gIFrame.src = "about:blank";
- gIFrame.onload = onLoadIFrame;
-}
-
-</script>
-</body>
-
-</html>
diff --git a/editor/libeditor/tests/test_select_all_without_body.html b/editor/libeditor/tests/test_select_all_without_body.html
deleted file mode 100644
index d947400c4..000000000
--- a/editor/libeditor/tests/test_select_all_without_body.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<html>
-<head>
- <title>Test select all in HTML editor without body element</title>
- <script type="text/javascript"
- src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css"
- href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<p id="display">
-</p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-</pre>
-
-<script class="testbody" type="application/javascript">
-
-SimpleTest.waitForExplicitFinish();
-window.open("file_select_all_without_body.html", "_blank",
- "width=600,height=600");
-
-</script>
-</body>
-
-</html>
diff --git a/editor/libeditor/tests/test_selection_move_commands.html b/editor/libeditor/tests/test_selection_move_commands.html
deleted file mode 100644
index e217f8fdf..000000000
--- a/editor/libeditor/tests/test_selection_move_commands.html
+++ /dev/null
@@ -1,219 +0,0 @@
-<!doctype html>
-<title>Test for nsSelectionMoveCommands</title>
-<link rel=stylesheet href="/tests/SimpleTest/test.css">
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<script src="/tests/SimpleTest/SpawnTask.js"></script>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=454004">Mozilla Bug 454004</a>
-
-<iframe id="edit" width="200" height="100" src="about:blank"></iframe>
-
-<script>
-SimpleTest.waitForExplicitFinish();
-SimpleTest.requestFlakyTimeout("Legacy test, possibly no good reason");
-
-var winUtils = SpecialPowers.getDOMWindowUtils(window);
-
-function* setup() {
- yield SpecialPowers.pushPrefEnv({set: [["general.smoothScroll", false]]});
- winUtils.advanceTimeAndRefresh(100);
-}
-
-function* runTests() {
- var e = document.getElementById("edit");
- var doc = e.contentDocument;
- var win = e.contentWindow;
- var root = doc.documentElement;
- var body = doc.body;
-
- body.style.fontSize='16px';
- body.style.lineHeight='16px';
- body.style.height='400px';
- body.style.padding='0px';
- body.style.margin='0px';
- body.style.borderWidth='0px';
-
- var sel = win.getSelection();
- doc.designMode='on';
- body.innerHTML = "1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10<br>11<br>12<br>";
- win.focus();
- // Flush out layout to make sure that the subdocument will be the size we
- // expect by the time we try to scroll it.
- is(body.getBoundingClientRect().height, 400,
- "Body height should be what we set it to");
- yield;
-
- function testScrollCommand(cmd, expectTop) {
- // http://dev.w3.org/csswg/cssom-view/#dom-element-getboundingclientrect
- // doesn't explicitly rule out -0 here, but for now assume that only
- // positive zeroes are permitted.
- if (navigator.appVersion.indexOf("Android") != -1 && expectTop != 0) {
- // Android doesn't get the values exactly correct for some reason
- todo_is(root.getBoundingClientRect().top, -expectTop + 0, cmd);
- ok(Math.abs(root.getBoundingClientRect().top + expectTop) < 0.2,
- cmd + " (approximately)");
- } else {
- is(root.getBoundingClientRect().top, -expectTop + 0, cmd);
- }
- }
-
- function testMoveCommand(cmd, expectNode, expectOffset) {
- SpecialPowers.doCommand(window, cmd);
- is(sel.isCollapsed, true, "collapsed after " + cmd);
- is(sel.anchorNode, expectNode, "node after " + cmd);
- is(sel.anchorOffset, expectOffset, "offset after " + cmd);
- }
-
- function findChildNum(e, child) {
- var i = 0;
- var n = e.firstChild;
- while (n && n != child) {
- n = n.nextSibling;
- ++i;
- }
- if (!n)
- return -1;
- return i;
- }
-
- function testPageMoveCommand(cmd, expectOffset) {
- SpecialPowers.doCommand(window, cmd);
- is(sel.isCollapsed, true, "collapsed after " + cmd);
- is(sel.anchorOffset, expectOffset, "offset after " + cmd);
- return findChildNum(body, sel.anchorNode);
- }
-
- function testSelectCommand(cmd, expectNode, expectOffset) {
- var anchorNode = sel.anchorNode;
- var anchorOffset = sel.anchorOffset;
- SpecialPowers.doCommand(window, cmd);
- is(sel.isCollapsed, false, "not collapsed after " + cmd);
- is(sel.anchorNode, anchorNode, "anchor not moved after " + cmd);
- is(sel.anchorOffset, anchorOffset, "anchor not moved after " + cmd);
- is(sel.focusNode, expectNode, "node after " + cmd);
- is(sel.focusOffset, expectOffset, "offset after " + cmd);
- }
-
- function testPageSelectCommand(cmd, expectOffset) {
- var anchorNode = sel.anchorNode;
- var anchorOffset = sel.anchorOffset;
- SpecialPowers.doCommand(window, cmd);
- is(sel.isCollapsed, false, "not collapsed after " + cmd);
- is(sel.anchorNode, anchorNode, "anchor not moved after " + cmd);
- is(sel.anchorOffset, anchorOffset, "anchor not moved after " + cmd);
- is(sel.focusOffset, expectOffset, "offset after " + cmd);
- return findChildNum(body, sel.focusNode);
- }
-
- function node(i) {
- var n = body.firstChild;
- while (i > 0) {
- n = n.nextSibling;
- --i;
- }
- return n;
- }
-
- SpecialPowers.doCommand(window, "cmd_scrollBottom");
- yield;
- testScrollCommand("cmd_scrollBottom", root.scrollHeight - 100);
- SpecialPowers.doCommand(window, "cmd_scrollTop");
- yield;
- testScrollCommand("cmd_scrollTop", 0);
-
- SpecialPowers.doCommand(window, "cmd_scrollPageDown");
- yield;
- var pageHeight = -root.getBoundingClientRect().top;
- ok(pageHeight > 0, "cmd_scrollPageDown works");
- ok(pageHeight <= 100, "cmd_scrollPageDown doesn't scroll too much");
- SpecialPowers.doCommand(window, "cmd_scrollBottom");
- SpecialPowers.doCommand(window, "cmd_scrollPageUp");
- yield;
- testScrollCommand("cmd_scrollPageUp", root.scrollHeight - 100 - pageHeight);
-
- SpecialPowers.doCommand(window, "cmd_scrollTop");
- SpecialPowers.doCommand(window, "cmd_scrollLineDown");
- yield;
- var lineHeight = -root.getBoundingClientRect().top;
- ok(lineHeight > 0, "Can scroll by lines");
- SpecialPowers.doCommand(window, "cmd_scrollBottom");
- SpecialPowers.doCommand(window, "cmd_scrollLineUp");
- yield;
- testScrollCommand("cmd_scrollLineUp", root.scrollHeight - 100 - lineHeight);
-
- var runSelectionTests = function(selectWordNextNode, selectWordNextOffset) {
- testMoveCommand("cmd_moveBottom", body, 23);
- testMoveCommand("cmd_moveTop", node(0), 0);
- testSelectCommand("cmd_selectBottom", body, 23);
- SpecialPowers.doCommand(window, "cmd_moveBottom");
- testSelectCommand("cmd_selectTop", node(0), 0);
-
- SpecialPowers.doCommand(window, "cmd_moveTop");
- testMoveCommand("cmd_lineNext", node(2), 0);
- testMoveCommand("cmd_linePrevious", node(0), 0);
- testSelectCommand("cmd_selectLineNext", node(2), 0);
- SpecialPowers.doCommand(window, "cmd_moveBottom");
- testSelectCommand("cmd_selectLinePrevious", node(20), 2);
-
- SpecialPowers.doCommand(window, "cmd_moveBottom");
- testMoveCommand("cmd_charPrevious", node(22), 1);
- testMoveCommand("cmd_charNext", node(22), 2);
- testSelectCommand("cmd_selectCharPrevious", node(22), 1);
- SpecialPowers.doCommand(window, "cmd_moveTop");
- testSelectCommand("cmd_selectCharNext", node(0), 1);
-
- SpecialPowers.doCommand(window, "cmd_moveTop");
- testMoveCommand("cmd_endLine", node(0), 1);
- testMoveCommand("cmd_beginLine", node(0), 0);
- testSelectCommand("cmd_selectEndLine", node(0), 1);
- SpecialPowers.doCommand(window, "cmd_moveBottom");
- testSelectCommand("cmd_selectBeginLine", node(22), 0);
-
- SpecialPowers.doCommand(window, "cmd_moveBottom");
- testMoveCommand("cmd_wordPrevious", node(22), 0);
- testMoveCommand("cmd_wordNext", body, 23);
- testSelectCommand("cmd_selectWordPrevious", node(22), 0);
- SpecialPowers.doCommand(window, "cmd_moveTop");
- testSelectCommand("cmd_selectWordNext", selectWordNextNode, selectWordNextOffset);
-
- SpecialPowers.doCommand(window, "cmd_moveTop");
- var lineNum = testPageMoveCommand("cmd_movePageDown", 0);
- ok(lineNum > 0, "cmd_movePageDown works");
- SpecialPowers.doCommand(window, "cmd_moveBottom");
- SpecialPowers.doCommand(window, "cmd_beginLine");
- is(testPageMoveCommand("cmd_movePageUp", 0), 22 - lineNum, "cmd_movePageUp");
-
- SpecialPowers.doCommand(window, "cmd_moveTop");
- is(testPageSelectCommand("cmd_selectPageDown", 0), lineNum, "cmd_selectPageDown");
- SpecialPowers.doCommand(window, "cmd_moveBottom");
- SpecialPowers.doCommand(window, "cmd_beginLine");
- is(testPageSelectCommand("cmd_selectPageUp", 0), 22 - lineNum, "cmd_selectPageUp");
- }
-
- yield SpecialPowers.pushPrefEnv({set: [["layout.word_select.eat_space_to_next_word", false]]});
- runSelectionTests(body, 1);
- yield SpecialPowers.pushPrefEnv({set: [["layout.word_select.eat_space_to_next_word", true]]});
- runSelectionTests(node(2), 0);
-}
-
-function cleanup() {
- winUtils.restoreNormalRefresh();
- SimpleTest.finish();
-}
-
-function* testRunner() {
- let curTest = runTests();
- while (true) {
- winUtils.advanceTimeAndRefresh(100);
- if (curTest.next().done) {
- break;
- }
- winUtils.advanceTimeAndRefresh(100);
- yield new Promise(resolve => setTimeout(resolve, 20));
- }
-}
-
-spawn_task(setup)
- .then(() => spawn_task(testRunner))
- .then(() => spawn_task(cleanup))
- .catch(err => ok(false, err));
-</script>
diff --git a/editor/libeditor/tests/test_set_document_title_transaction.html b/editor/libeditor/tests/test_set_document_title_transaction.html
deleted file mode 100644
index d745d4f13..000000000
--- a/editor/libeditor/tests/test_set_document_title_transaction.html
+++ /dev/null
@@ -1,79 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <title>Test for SetDocumentTitleTransaction</title>
- <script type="text/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css"
- href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-</head>
-<body onload="runTests()">
-<div id="display">
- <iframe src="data:text/html,<!DOCTYPE html><html><head><title>first title</title></head><body></body></html>"></iframe>
-</div>
-<div id="content" style="display: none">
-</div>
-<pre id="test">
-</pre>
-
-<script class="testbody" type="application/javascript">
-function runTests() {
- var iframe = document.getElementsByTagName("iframe")[0];
- function isDocumentTitleEquals(aDescription, aExpectedTitle) {
- is(iframe.contentDocument.title, aExpectedTitle, aDescription + ": document.title should be " + aExpectedTitle);
- is(iframe.contentDocument.getElementsByTagName("title")[0].textContent, aExpectedTitle, aDescription + ": The text in the title element should be " + aExpectedTitle);
- }
-
- isDocumentTitleEquals("Checking isDocumentTitleEquals()", "first title");
-
- const kTests = [
- { description: "designMode=\"on\"",
- init: function () {
- iframe.contentDocument.designMode = "on";
- },
- cleanUp: function () {
- iframe.contentDocument.designMode = "off";
- }
- },
- { description: "html element has contenteditable attribute",
- init: function () {
- iframe.contentDocument.documentElement.setAttribute("contenteditable", "true");
- },
- cleanUp: function () {
- iframe.contentDocument.documentElement.removeAttribute("contenteditable");
- }
- },
- ];
-
- for (var i = 0; i < kTests.length; i++) {
- const kTest = kTests[i];
- kTest.init();
-
- var editor = SpecialPowers.wrap(iframe.contentWindow).
- QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).
- getInterface(SpecialPowers.Ci.nsIWebNavigation).
- QueryInterface(SpecialPowers.Ci.nsIDocShell).editor;
- ok(editor, kTest.description + ": The docshell should have editor");
- var htmlEditor = editor.QueryInterface(SpecialPowers.Ci.nsIHTMLEditor);
- ok(htmlEditor, kTest.description + ": The editor should have nsIHTMLEditor interface");
-
- // Replace existing title.
- htmlEditor.setDocumentTitle("Modified title");
- isDocumentTitleEquals(kTest.description, "Modified title");
-
- // When the document doesn't have <title> element, title element should be created automatically.
- iframe.contentDocument.head.removeChild(iframe.contentDocument.getElementsByTagName("title")[0]);
- is(iframe.contentDocument.getElementsByTagName("title").length, 0, kTest.description + ": There should be no title element");
- htmlEditor.setDocumentTitle("new title");
- is(iframe.contentDocument.getElementsByTagName("title").length, 1, kTest.description + ": There should be a title element");
- isDocumentTitleEquals(kTest.description, "new title");
-
- kTest.cleanUp();
- }
-
- SimpleTest.finish();
-}
-</script>
-</body>
-
-</html>
diff --git a/editor/libeditor/tests/test_spellcheck_pref.html b/editor/libeditor/tests/test_spellcheck_pref.html
deleted file mode 100644
index 9faff45f3..000000000
--- a/editor/libeditor/tests/test_spellcheck_pref.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<html>
-<head>
- <title>Test if spellcheck is turned on</title>
- <script type="text/javascript"
- src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css"
- href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-
-<div id="content" style="display: none">
-</div>
-<pre id="test">
-</pre>
-
-<script class="testbody" type="application/javascript">
-
- is(SpecialPowers.getIntPref("layout.spellcheckDefault"), 1, "Check if the layout.spellcheckDefault pref is turned on");
-
-</script>
-</body>
-
-</html>
diff --git a/editor/libeditor/tests/test_texteditor_keyevent_handling.html b/editor/libeditor/tests/test_texteditor_keyevent_handling.html
deleted file mode 100644
index 5c4a8d1c2..000000000
--- a/editor/libeditor/tests/test_texteditor_keyevent_handling.html
+++ /dev/null
@@ -1,386 +0,0 @@
-<html>
-<head>
- <title>Test for key event handler of text editor</title>
- <script type="text/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript"
- src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" type="text/css"
- href="chrome://mochikit/content/tests/SimpleTest/test.css" />
-</head>
-<body>
-<div id="display">
- <input type="text" id="inputField">
- <input type="password" id="passwordField">
- <textarea id="textarea"></textarea>
-</div>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-</pre>
-
-<script class="testbody" type="application/javascript">
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTests, window);
-
-var inputField = document.getElementById("inputField");
-var passwordField = document.getElementById("passwordField");
-var textarea = document.getElementById("textarea");
-
-const kIsMac = navigator.platform.indexOf("Mac") == 0;
-const kIsWin = navigator.platform.indexOf("Win") == 0;
-const kIsLinux = navigator.platform.indexOf("Linux") == 0;
-
-function runTests()
-{
- var fm = SpecialPowers.Cc["@mozilla.org/focus-manager;1"].
- getService(SpecialPowers.Ci.nsIFocusManager);
-
- var capturingPhase = { fired: false, prevented: false };
- var bubblingPhase = { fired: false, prevented: false };
-
- var listener = {
- handleEvent: function _hv(aEvent)
- {
- is(aEvent.type, "keypress", "unexpected event is handled");
- switch (aEvent.eventPhase) {
- case aEvent.CAPTURING_PHASE:
- capturingPhase.fired = true;
- capturingPhase.prevented = aEvent.defaultPrevented;
- break;
- case aEvent.BUBBLING_PHASE:
- bubblingPhase.fired = true;
- bubblingPhase.prevented = aEvent.defaultPrevented;
- aEvent.preventDefault(); // prevent the browser default behavior
- break;
- default:
- ok(false, "event is handled in unexpected phase");
- }
- }
- };
-
- function check(aDescription,
- aFiredOnCapture, aFiredOnBubbling, aPreventedOnBubbling)
- {
- function getDesciption(aExpected)
- {
- return aDescription + (aExpected ? " wasn't " : " was ");
- }
-
- is(capturingPhase.fired, aFiredOnCapture,
- getDesciption(aFiredOnCapture) + "fired on capture phase");
- is(bubblingPhase.fired, aFiredOnBubbling,
- getDesciption(aFiredOnBubbling) + "fired on bubbling phase");
-
- // If the event is fired on bubbling phase and it was already prevented
- // on capture phase, it must be prevented on bubbling phase too.
- if (capturingPhase.prevented) {
- todo(false, aDescription +
- " was consumed already, so, we cannot test the editor behavior actually");
- aPreventedOnBubbling = true;
- }
-
- is(bubblingPhase.prevented, aPreventedOnBubbling,
- getDesciption(aPreventedOnBubbling) + "prevented on bubbling phase");
- }
-
- var parentElement = document.getElementById("display");
- SpecialPowers.addSystemEventListener(parentElement, "keypress", listener,
- true);
- SpecialPowers.addSystemEventListener(parentElement, "keypress", listener,
- false);
-
- function doTest(aElement, aDescription, aIsSingleLine, aIsReadonly,
- aIsTabbable)
- {
- function reset(aText)
- {
- capturingPhase.fired = false;
- capturingPhase.prevented = false;
- bubblingPhase.fired = false;
- bubblingPhase.prevented = false;
- aElement.value = aText;
- }
-
- if (document.activeElement) {
- document.activeElement.blur();
- }
-
- aDescription += ": "
-
- aElement.focus();
- is(SpecialPowers.unwrap(fm.focusedElement), aElement, aDescription + "failed to move focus");
-
- // Backspace key:
- // If editor is readonly, it doesn't consume.
- // If editor is editable, it consumes backspace and shift+backspace.
- // Otherwise, editor doesn't consume the event but the native key
- // bindings on nsTextControlFrame may consume it.
- reset("");
- synthesizeKey("VK_BACK_SPACE", { });
- check(aDescription + "Backspace", true, true, true);
-
- reset("");
- synthesizeKey("VK_BACK_SPACE", { shiftKey: true });
- check(aDescription + "Shift+Backspace", true, true, true);
-
- reset("");
- synthesizeKey("VK_BACK_SPACE", { ctrlKey: true });
- // Win: cmd_deleteWordBackward
- check(aDescription + "Ctrl+Backspace",
- true, true, aIsReadonly || kIsWin);
-
- reset("");
- synthesizeKey("VK_BACK_SPACE", { altKey: true });
- // Win: cmd_undo
- // Mac: cmd_deleteWordBackward
- check(aDescription + "Alt+Backspace",
- true, true, aIsReadonly || kIsWin || kIsMac);
-
- reset("");
- synthesizeKey("VK_BACK_SPACE", { metaKey: true });
- check(aDescription + "Meta+Backspace", true, true, aIsReadonly);
-
- reset("");
- synthesizeKey("VK_BACK_SPACE", { osKey: true });
- check(aDescription + "OS+Backspace", true, true, aIsReadonly);
-
- // Delete key:
- // If editor is readonly, it doesn't consume.
- // If editor is editable, delete is consumed.
- // Otherwise, editor doesn't consume the event but the native key
- // bindings on nsTextControlFrame may consume it.
- reset("");
- synthesizeKey("VK_DELETE", { });
- // Linux: native handler
- // Mac: cmd_deleteCharForward
- check(aDescription + "Delete",
- true, true, !aIsReadonly || kIsLinux || kIsMac);
-
- reset("");
- // Win: cmd_cutOrDelete
- // Linux: cmd_cut
- // Mac: cmd_deleteCharForward
- synthesizeKey("VK_DELETE", { shiftKey: true });
- check(aDescription + "Shift+Delete",
- true, true, true);
-
- reset("");
- synthesizeKey("VK_DELETE", { ctrlKey: true });
- // Win: cmd_deleteWordForward
- // Linux: cmd_copy
- check(aDescription + "Ctrl+Delete",
- true, true, kIsWin || kIsLinux);
-
- reset("");
- synthesizeKey("VK_DELETE", { altKey: true });
- // Mac: cmd_deleteWordForward
- check(aDescription + "Alt+Delete",
- true, true, kIsMac);
-
- reset("");
- synthesizeKey("VK_DELETE", { metaKey: true });
- // Linux: native handler consumed.
- check(aDescription + "Meta+Delete",
- true, true, kIsLinux);
-
- reset("");
- synthesizeKey("VK_DELETE", { osKey: true });
- check(aDescription + "OS+Delete",
- true, true, false);
-
- // XXX input.value returns "\n" when it's empty, so, we should use dummy
- // value ("a") for the following tests.
-
- // Return key:
- // If editor is readonly, it doesn't consume.
- // If editor is editable and not single line editor, it consumes Return
- // and Shift+Return.
- // Otherwise, editor doesn't consume the event.
- reset("a");
- synthesizeKey("VK_RETURN", { });
- check(aDescription + "Return",
- true, true, !aIsSingleLine && !aIsReadonly);
- is(aElement.value, !aIsSingleLine && !aIsReadonly ? "a\n" : "a",
- aDescription + "Return");
-
- reset("a");
- synthesizeKey("VK_RETURN", { shiftKey: true });
- check(aDescription + "Shift+Return",
- true, true, !aIsSingleLine && !aIsReadonly);
- is(aElement.value, !aIsSingleLine && !aIsReadonly ? "a\n" : "a",
- aDescription + "Shift+Return");
-
- reset("a");
- synthesizeKey("VK_RETURN", { ctrlKey: true });
- check(aDescription + "Ctrl+Return", true, true, false);
- is(aElement.value, "a", aDescription + "Ctrl+Return");
-
- reset("a");
- synthesizeKey("VK_RETURN", { altKey: true });
- check(aDescription + "Alt+Return", true, true, false);
- is(aElement.value, "a", aDescription + "Alt+Return");
-
- reset("a");
- synthesizeKey("VK_RETURN", { metaKey: true });
- check(aDescription + "Meta+Return", true, true, false);
- is(aElement.value, "a", aDescription + "Meta+Return");
-
- reset("a");
- synthesizeKey("VK_RETURN", { osKey: true });
- check(aDescription + "OS+Return", true, true, false);
- is(aElement.value, "a", aDescription + "OS+Return");
-
- // Tab key:
- // If editor is tabbable, editor doesn't consume all tab key events.
- // Otherwise, editor consumes tab key event without any modifier keys.
- reset("a");
- synthesizeKey("VK_TAB", { });
- check(aDescription + "Tab",
- true, true, !aIsTabbable && !aIsReadonly);
- is(aElement.value, !aIsTabbable && !aIsReadonly ? "a\t" : "a",
- aDescription + "Tab");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Tab)");
-
- // If the editor is not tabbable, make sure that it accepts tab characters
- // even if it's empty.
- if (!aIsTabbable && !aIsReadonly) {
- reset("");
- synthesizeKey("VK_TAB", {});
- check(aDescription + "Tab on empty textarea",
- true, true, !aIsReadonly);
- is(aElement.value, "\t", aDescription + "Tab on empty textarea");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Tab on empty textarea");
- }
-
- reset("a");
- synthesizeKey("VK_TAB", { shiftKey: true });
- check(aDescription + "Shift+Tab", true, true, false);
- is(aElement.value, "a", aDescription + "Shift+Tab");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Shift+Tab)");
-
- // Ctrl+Tab should be consumed by tabbrowser at keydown, so, keypress
- // event should never be fired.
- reset("a");
- synthesizeKey("VK_TAB", { ctrlKey: true });
- check(aDescription + "Ctrl+Tab", false, false, false);
- is(aElement.value, "a", aDescription + "Ctrl+Tab");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Ctrl+Tab)");
-
- reset("a");
- synthesizeKey("VK_TAB", { altKey: true });
- check(aDescription + "Alt+Tab", true, true, false);
- is(aElement.value, "a", aDescription + "Alt+Tab");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Alt+Tab)");
-
- reset("a");
- synthesizeKey("VK_TAB", { metaKey: true });
- check(aDescription + "Meta+Tab", true, true, false);
- is(aElement.value, "a", aDescription + "Meta+Tab");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (Meta+Tab)");
-
- reset("a");
- synthesizeKey("VK_TAB", { osKey: true });
- check(aDescription + "OS+Tab", true, true, false);
- is(aElement.value, "a", aDescription + "OS+Tab");
- is(SpecialPowers.unwrap(fm.focusedElement), aElement,
- aDescription + "focus moved unexpectedly (OS+Tab)");
-
- // Esc key:
- // In all cases, esc key events are not consumed
- reset("abc");
- synthesizeKey("VK_ESCAPE", { });
- check(aDescription + "Esc", true, true, false);
-
- reset("abc");
- synthesizeKey("VK_ESCAPE", { shiftKey: true });
- check(aDescription + "Shift+Esc", true, true, false);
-
- reset("abc");
- synthesizeKey("VK_ESCAPE", { ctrlKey: true });
- check(aDescription + "Ctrl+Esc", true, true, false);
-
- reset("abc");
- synthesizeKey("VK_ESCAPE", { altKey: true });
- check(aDescription + "Alt+Esc", true, true, false);
-
- reset("abc");
- synthesizeKey("VK_ESCAPE", { metaKey: true });
- check(aDescription + "Meta+Esc", true, true, false);
-
- reset("abc");
- synthesizeKey("VK_ESCAPE", { osKey: true });
- check(aDescription + "OS+Esc", true, true, false);
-
- // typical typing tests:
- reset("");
- synthesizeKey("M", { shiftKey: true });
- check(aDescription + "M", true, true, !aIsReadonly);
- synthesizeKey("o", { });
- check(aDescription + "o", true, true, !aIsReadonly);
- synthesizeKey("z", { });
- check(aDescription + "z", true, true, !aIsReadonly);
- synthesizeKey("i", { });
- check(aDescription + "i", true, true, !aIsReadonly);
- synthesizeKey("l", { });
- check(aDescription + "l", true, true, !aIsReadonly);
- synthesizeKey("l", { });
- check(aDescription + "l", true, true, !aIsReadonly);
- synthesizeKey("a", { });
- check(aDescription + "a", true, true, !aIsReadonly);
- synthesizeKey(" ", { });
- check(aDescription + "' '", true, true, !aIsReadonly);
- is(aElement.value, !aIsReadonly ? "Mozilla " : "",
- aDescription + "typed \"Mozilla \"");
- }
-
- doTest(inputField, "<input type=\"text\">", true, false, true);
-
- inputField.setAttribute("readonly", "readonly");
- doTest(inputField, "<input type=\"text\" readonly>", true, true, true);
-
- doTest(passwordField, "<input type=\"password\">", true, false, true);
-
- passwordField.setAttribute("readonly", "readonly");
- doTest(passwordField, "<input type=\"password\" readonly>", true, true, true);
-
- doTest(textarea, "<textarea>", false, false, true);
-
- textarea.setAttribute("readonly", "readonly");
- doTest(textarea, "<textarea readonly>", false, true, true);
-
- // make non-tabbable plaintext editor
- textarea.removeAttribute("readonly");
- const nsIPlaintextEditor = SpecialPowers.Ci.nsIPlaintextEditor;
- const nsIDOMNSEditableElement = SpecialPowers.Ci.nsIDOMNSEditableElement;
- var editor = SpecialPowers.wrap(textarea).editor;
- var flags = editor.flags;
- editor.flags = flags & ~(nsIPlaintextEditor.eEditorWidgetMask |
- nsIPlaintextEditor.eEditorAllowInteraction);
- doTest(textarea, "non-tabbable <textarea>", false, false, false);
-
- textarea.setAttribute("readonly", "readonly");
- doTest(textarea, "non-tabbable <textarea readonly>", false, true, false);
-
- editor.flags = flags;
-
- SpecialPowers.removeSystemEventListener(parentElement, "keypress", listener,
- true);
- SpecialPowers.removeSystemEventListener(parentElement, "keypress", listener,
- false);
-
- SimpleTest.finish();
-}
-
-</script>
-</body>
-
-</html>
diff --git a/editor/moz.build b/editor/moz.build
deleted file mode 100644
index daeba2d10..000000000
--- a/editor/moz.build
+++ /dev/null
@@ -1,40 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DIRS += [
- 'txtsvc',
- 'libeditor',
- 'txmgr',
- 'composer',
-]
-
-if CONFIG['MOZ_COMPOSER']:
- DIRS += ['ui']
-
-XPIDL_SOURCES += [
- 'nsIContentFilter.idl',
- 'nsIDocumentStateListener.idl',
- 'nsIEditActionListener.idl',
- 'nsIEditor.idl',
- 'nsIEditorIMESupport.idl',
- 'nsIEditorMailSupport.idl',
- 'nsIEditorObserver.idl',
- 'nsIEditorSpellCheck.idl',
- 'nsIEditorStyleSheets.idl',
- 'nsIEditorUtils.idl',
- 'nsIHTMLAbsPosEditor.idl',
- 'nsIHTMLEditor.idl',
- 'nsIHTMLInlineTableEditor.idl',
- 'nsIHTMLObjectResizeListener.idl',
- 'nsIHTMLObjectResizer.idl',
- 'nsIPlaintextEditor.idl',
- 'nsITableEditor.idl',
- 'nsIURIRefObject.idl',
- 'nsPIEditorTransaction.idl',
-]
-
-EXPORTS += ['nsEditorCID.h']
-EXTRA_JS_MODULES += ['AsyncSpellCheckTestHelper.jsm']
-XPIDL_MODULE = 'editor' \ No newline at end of file
diff --git a/editor/nsEditorCID.h b/editor/nsEditorCID.h
deleted file mode 100644
index 4b288771e..000000000
--- a/editor/nsEditorCID.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef NSEDITORCID_H___
-
-#define NS_EDITOR_CID \
-{/* {D3DE3431-8A75-11d2-918C-0080C8E44DB5}*/ \
-0xd3de3431, 0x8a75, 0x11d2, \
-{ 0x91, 0x8c, 0x0, 0x80, 0xc8, 0xe4, 0x4d, 0xb5 } }
-
-#define NS_TEXTEDITOR_CID \
-{/* {e197cc01-cfe1-11d4-8eb0-87ae406dfd3f}*/ \
-0xe197cc01, 0xcfe1, 0x11d4, \
-{ 0x8e, 0xb0, 0x87, 0xae, 0x40, 0x6d, 0xfd, 0x3f } }
-
-#define NS_HTMLEDITOR_CID \
-{/* {ed0244e0-c144-11d2-8f4c-006008159b0c}*/ \
-0xed0244e0, 0xc144, 0x11d2, \
-{ 0x8f, 0x4c, 0x0, 0x60, 0x08, 0x15, 0x9b, 0x0c } }
-
-#endif //NSEDITORCID_H___
-
-
-
diff --git a/editor/nsIContentFilter.idl b/editor/nsIContentFilter.idl
deleted file mode 100644
index 585901ec1..000000000
--- a/editor/nsIContentFilter.idl
+++ /dev/null
@@ -1,85 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "domstubs.idl"
-
-interface nsIURL;
-
-[scriptable, uuid(c18c49a8-62f0-4045-9884-4aa91e388f14)]
-interface nsIContentFilter : nsISupports
-{
- /**
- * This notification occurs in an editor during these events:
- * * open of document (once rendered in window but before editable)
- * * paste from clipboard
- * * drop from mouse
- * * insertion of html (such as with "cmd_insertHTML")
- * It provides a hook so the above actions can be canceled or the data
- * can be modified (using standard DOM APIs) or left untouched. The data
- * that results (if any) from all filter callbacks is what will be used
- * for transaction purposes (undo/redo) except for the open event.
- *
- * The willDeleteSelection parameter is offered for filters who want to
- * handle the insertion themselves and need to handle drag/drop correctly.
- * The flag is true when the editor intends to delete the selection.
- *
- * Callers who want to cancel all insertion can simply set
- * continueWithInsertion to PR_FALSE and return.
- * Note: If cancellation occurs during the "open" event, the editor will
- * still be available but will be empty.
- *
- * Callers who want to allow insertion of the data with no changes
- * can simply set continueWithInsertion to PR_TRUE and return.
- *
- * Callers who want to modify the content (docFragment) being inserted are
- * responsible for updating contentStartNode, contentStartOffset,
- * contentEndNode, and contentEndOffset (if necessary).
- * Callers are responsible for freeing and addref'ing if they want to
- * completely replace any of the DOM nodes passed in.
- *
- * The location where insertion will occur should be considered an
- * approximation since the editor may need to adjust it if it deletes
- * the selection as part of the event and later determines that insertion
- * point is an empty container which should also be removed (or in other
- * scenarios such as -moz-user-select:none).
- *
- * In some scenarios the selection will be deleted. If callers choose
- * to adjust the insertion point, they should be careful that the insertion
- * point is not in the current selection.
- *
- * The contentStartNode and contentEndNode are not necessarily
- * immediate children of the docFragment. Any nodes outside of the range
- * set by contentStartNode and contentEndNode are for context from the
- * source document.
- *
- * @param mimeType the mimetype used for retrieving data
- * @param contentSourceURL location where docFragment came from
- * @param sourceDocument document where content came from (can be null)
- * @param willDeleteSelection tells hook if selection will/should be deleted
- * @param docFragment fragment of node to be inserted
- * @param contentStartNode node under which content to be inserted begins
- * @param contentStartOffset start offset within contentStartNode
- * @param contentEndNode node under which content to be inserted ends
- * @param contentEndOffset ending offset withing contentEndNode
- * @param insertionPointNode location where insertion will occur
- * @param insertionPointOffset offset within node where insertion occurs
- * @param continueWithInsertion flag to cancel insertion (if desired)
- */
-
- void notifyOfInsertion(in AString mimeType,
- in nsIURL contentSourceURL,
- in nsIDOMDocument sourceDocument,
- in boolean willDeleteSelection,
- inout nsIDOMNode docFragment,
- inout nsIDOMNode contentStartNode,
- inout long contentStartOffset,
- inout nsIDOMNode contentEndNode,
- inout long contentEndOffset,
- inout nsIDOMNode insertionPointNode,
- inout long insertionPointOffset,
- out boolean continueWithInsertion);
-
-};
diff --git a/editor/nsIDocumentStateListener.idl b/editor/nsIDocumentStateListener.idl
deleted file mode 100644
index bf8dce051..000000000
--- a/editor/nsIDocumentStateListener.idl
+++ /dev/null
@@ -1,16 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(050cdc00-3b8e-11d3-9ce4-a458f454fcbc)]
-interface nsIDocumentStateListener : nsISupports
-{
-
- void NotifyDocumentCreated();
- void NotifyDocumentWillBeDestroyed();
- void NotifyDocumentStateChanged(in boolean nowDirty);
-
-};
diff --git a/editor/nsIEditActionListener.idl b/editor/nsIEditActionListener.idl
deleted file mode 100644
index bd2085405..000000000
--- a/editor/nsIEditActionListener.idl
+++ /dev/null
@@ -1,199 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "domstubs.idl"
-
-interface nsISelection;
-
-
-/*
-Editor Action Listener interface to outside world
-*/
-
-
-/**
- * A generic editor action listener interface.
- * <P>
- * nsIEditActionListener is the interface used by applications wishing to be notified
- * when the editor modifies the DOM tree.
- *
- * Note: this is the wrong class to implement if you are interested in generic
- * change notifications. For generic notifications, you should implement
- * nsIDocumentObserver.
- */
-[scriptable, uuid(b22907b1-ee93-11d2-8d50-000064657374)]
-
-interface nsIEditActionListener : nsISupports{
-
- /**
- * Called before the editor creates a node.
- * @param aTag The tag name of the DOM Node to create.
- * @param aParent The node to insert the new object into
- * @param aPosition The place in aParent to insert the new node
- * 0=first child, 1=second child, etc.
- * any number > number of current children = last child
- */
- void WillCreateNode(in DOMString aTag,
- in nsIDOMNode aParent,
- in long aPosition);
-
- /**
- * Called after the editor creates a node.
- * @param aTag The tag name of the DOM Node to create.
- * @param aNode The DOM Node that was created.
- * @param aParent The node to insert the new object into
- * @param aPosition The place in aParent to insert the new node
- * 0=first child, 1=second child, etc.
- * any number > number of current children = last child
- * @param aResult The result of the create node operation.
- */
- void DidCreateNode(in DOMString aTag,
- in nsIDOMNode aNode,
- in nsIDOMNode aParent,
- in long aPosition,
- in nsresult aResult);
-
- /**
- * Called before the editor inserts a node.
- * @param aNode The DOM Node to insert.
- * @param aParent The node to insert the new object into
- * @param aPosition The place in aParent to insert the new node
- * 0=first child, 1=second child, etc.
- * any number > number of current children = last child
- */
- void WillInsertNode(in nsIDOMNode aNode,
- in nsIDOMNode aParent,
- in long aPosition);
-
- /**
- * Called after the editor inserts a node.
- * @param aNode The DOM Node to insert.
- * @param aParent The node to insert the new object into
- * @param aPosition The place in aParent to insert the new node
- * 0=first child, 1=second child, etc.
- * any number > number of current children = last child
- * @param aResult The result of the insert node operation.
- */
- void DidInsertNode(in nsIDOMNode aNode,
- in nsIDOMNode aParent,
- in long aPosition,
- in nsresult aResult);
-
- /**
- * Called before the editor deletes a node.
- * @param aChild The node to delete
- */
- void WillDeleteNode(in nsIDOMNode aChild);
-
- /**
- * Called after the editor deletes a node.
- * @param aChild The node to delete
- * @param aResult The result of the delete node operation.
- */
- void DidDeleteNode(in nsIDOMNode aChild, in nsresult aResult);
-
- /**
- * Called before the editor splits a node.
- * @param aExistingRightNode the node to split. It will become the new node's next sibling.
- * @param aOffset the offset of aExistingRightNode's content|children to do the split at
- * @param aNewLeftNode [OUT] the new node resulting from the split, becomes aExistingRightNode's previous sibling.
- */
- void WillSplitNode(in nsIDOMNode aExistingRightNode,
- in long aOffset);
-
- /**
- * Called after the editor splits a node.
- * @param aExistingRightNode the node to split. It will become the new node's next sibling.
- * @param aOffset the offset of aExistingRightNode's content|children to do the split at
- * @param aNewLeftNode [OUT] the new node resulting from the split, becomes aExistingRightNode's previous sibling.
- */
- void DidSplitNode(in nsIDOMNode aExistingRightNode,
- in long aOffset,
- in nsIDOMNode aNewLeftNode,
- in nsresult aResult);
-
- /**
- * Called before the editor joins 2 nodes.
- * @param aLeftNode This node will be merged into the right node
- * @param aRightNode The node that will be merged into.
- * There is no requirement that the two nodes be of
- * the same type.
- * @param aParent The parent of aRightNode
- */
- void WillJoinNodes(in nsIDOMNode aLeftNode,
- in nsIDOMNode aRightNode,
- in nsIDOMNode aParent);
-
- /**
- * Called after the editor joins 2 nodes.
- * @param aLeftNode This node will be merged into the right node
- * @param aRightNode The node that will be merged into.
- * There is no requirement that the two nodes be of
- * the same type.
- * @param aParent The parent of aRightNode
- * @param aResult The result of the join operation.
- */
- void DidJoinNodes(in nsIDOMNode aLeftNode,
- in nsIDOMNode aRightNode,
- in nsIDOMNode aParent,
- in nsresult aResult);
-
- /**
- * Called before the editor inserts text.
- * @param aTextNode This node getting inserted text
- * @param aOffset The offset in aTextNode to insert at.
- * @param aString The string that gets inserted.
- */
- void WillInsertText(in nsIDOMCharacterData aTextNode,
- in long aOffset,
- in DOMString aString);
-
- /**
- * Called after the editor inserts text.
- * @param aTextNode This node getting inserted text
- * @param aOffset The offset in aTextNode to insert at.
- * @param aString The string that gets inserted.
- * @param aResult The result of the insert text operation.
- */
- void DidInsertText(in nsIDOMCharacterData aTextNode,
- in long aOffset,
- in DOMString aString,
- in nsresult aResult);
-
- /**
- * Called before the editor deletes text.
- * @param aTextNode This node getting text deleted
- * @param aOffset The offset in aTextNode to delete at.
- * @param aLength The amount of text to delete.
- */
- void WillDeleteText(in nsIDOMCharacterData aTextNode,
- in long aOffset,
- in long aLength);
-
- /**
- * Called before the editor deletes text.
- * @param aTextNode This node getting text deleted
- * @param aOffset The offset in aTextNode to delete at.
- * @param aLength The amount of text to delete.
- * @param aResult The result of the delete text operation.
- */
- void DidDeleteText(in nsIDOMCharacterData aTextNode,
- in long aOffset,
- in long aLength,
- in nsresult aResult);
-
- /**
- * Called before the editor deletes the selection.
- * @param aSelection The selection to be deleted
- */
- void WillDeleteSelection(in nsISelection aSelection);
-
- /**
- * Called after the editor deletes the selection.
- * @param aSelection The selection, after deletion
- */
- void DidDeleteSelection(in nsISelection aSelection);
-};
diff --git a/editor/nsIEditor.idl b/editor/nsIEditor.idl
deleted file mode 100644
index bb9026d0e..000000000
--- a/editor/nsIEditor.idl
+++ /dev/null
@@ -1,567 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "domstubs.idl"
-
-interface nsIURI;
-interface nsIAtom;
-interface nsIContent;
-interface nsISelection;
-interface nsISelectionController;
-interface nsIDocumentStateListener;
-interface nsIOutputStream;
-interface nsITransactionManager;
-interface nsITransaction;
-interface nsIEditorObserver;
-interface nsIEditActionListener;
-interface nsIInlineSpellChecker;
-interface nsITransferable;
-
-[scriptable, uuid(094be624-f0bf-400f-89e2-6a84baab9474)]
-interface nsIEditor : nsISupports
-{
-%{C++
- typedef short EDirection;
- typedef short EStripWrappers;
-%}
- const short eNone = 0;
- const short eNext = 1;
- const short ePrevious = 2;
- const short eNextWord = 3;
- const short ePreviousWord = 4;
- const short eToBeginningOfLine = 5;
- const short eToEndOfLine = 6;
-
- const short eStrip = 0;
- const short eNoStrip = 1;
-
- readonly attribute nsISelection selection;
-
- /**
- * Finalizes selection and caret for the editor.
- */
- [noscript] void finalizeSelection();
-
- /**
- * Init is to tell the implementation of nsIEditor to begin its services
- * @param aDoc The dom document interface being observed
- * @param aRoot This is the root of the editable section of this
- * document. If it is null then we get root
- * from document body.
- * @param aSelCon this should be used to get the selection location
- * (will be null for HTML editors)
- * @param aFlags A bitmask of flags for specifying the behavior
- * of the editor.
- */
- [noscript] void init(in nsIDOMDocument doc,
- in nsIContent aRoot,
- in nsISelectionController aSelCon,
- in unsigned long aFlags,
- in AString initialValue);
-
- void setAttributeOrEquivalent(in nsIDOMElement element,
- in AString sourceAttrName,
- in AString sourceAttrValue,
- in boolean aSuppressTransaction);
- void removeAttributeOrEquivalent(in nsIDOMElement element,
- in DOMString sourceAttrName,
- in boolean aSuppressTransaction);
-
- /**
- * postCreate should be called after Init, and is the time that the editor
- * tells its documentStateObservers that the document has been created.
- */
- void postCreate();
-
- /**
- * preDestroy is called before the editor goes away, and gives the editor a
- * chance to tell its documentStateObservers that the document is going away.
- * @param aDestroyingFrames set to true when the frames being edited
- * are being destroyed (so there is no need to modify any nsISelections,
- * nor is it safe to do so)
- */
- void preDestroy(in boolean aDestroyingFrames);
-
- /** edit flags for this editor. May be set at any time. */
- attribute unsigned long flags;
-
- /**
- * the MimeType of the document
- */
- attribute string contentsMIMEType;
-
- /** Returns true if we have a document that is not marked read-only */
- readonly attribute boolean isDocumentEditable;
-
- /** Returns true if the current selection anchor is editable */
- readonly attribute boolean isSelectionEditable;
-
- /**
- * the DOM Document this editor is associated with, refcounted.
- */
- readonly attribute nsIDOMDocument document;
-
- /** the body element, i.e. the root of the editable document.
- */
- readonly attribute nsIDOMElement rootElement;
-
- /**
- * the selection controller for the current presentation, refcounted.
- */
- readonly attribute nsISelectionController selectionController;
-
-
- /* ------------ Selected content removal -------------- */
-
- /**
- * DeleteSelection removes all nodes in the current selection.
- * @param aDir if eNext, delete to the right (for example, the DEL key)
- * if ePrevious, delete to the left (for example, the BACKSPACE key)
- * @param stripWrappers If eStrip, strip any empty inline elements left
- * behind after the deletion; if eNoStrip, don't. If in
- * doubt, pass eStrip -- eNoStrip is only for if you're
- * about to insert text or similar right after.
- */
- void deleteSelection(in short action, in short stripWrappers);
-
-
- /* ------------ Document info and file methods -------------- */
-
- /** Returns true if the document has no *meaningful* content */
- readonly attribute boolean documentIsEmpty;
-
- /** Returns true if the document is modifed and needs saving */
- readonly attribute boolean documentModified;
-
- /** Sets the current 'Save' document character set */
- attribute ACString documentCharacterSet;
-
- /** to be used ONLY when we need to override the doc's modification
- * state (such as when it's saved).
- */
- void resetModificationCount();
-
- /** Gets the modification count of the document we are editing.
- * @return the modification count of the document being edited.
- * Zero means unchanged.
- */
- long getModificationCount();
-
- /** called each time we modify the document.
- * Increments the modification count of the document.
- * @param aModCount the number of modifications by which
- * to increase or decrease the count
- */
- void incrementModificationCount(in long aModCount);
-
- /* ------------ Transaction methods -------------- */
-
- /** transactionManager Get the transaction manager the editor is using.
- */
- attribute nsITransactionManager transactionManager;
-
- /** doTransaction() fires a transaction.
- * It is provided here so clients can create their own transactions.
- * If a transaction manager is present, it is used.
- * Otherwise, the transaction is just executed directly.
- *
- * @param aTxn the transaction to execute
- */
- void doTransaction(in nsITransaction txn);
-
-
- /** turn the undo system on or off
- * @param aEnable if PR_TRUE, the undo system is turned on if available
- * if PR_FALSE the undo system is turned off if it
- * was previously on
- * @return if aEnable is PR_TRUE, returns NS_OK if
- * the undo system could be initialized properly
- * if aEnable is PR_FALSE, returns NS_OK.
- */
- void enableUndo(in boolean enable);
-
- /**
- * The number of items on the undo stack.
- */
- readonly attribute long numberOfUndoItems;
-
- /**
- * The number of items on the redo stack.
- */
- readonly attribute long numberOfRedoItems;
-
- /** undo reverses the effects of the last Do operation,
- * if Undo is enabled in the editor.
- * It is provided here so clients need no knowledge of whether
- * the editor has a transaction manager or not.
- * If a transaction manager is present, it is told to undo,
- * and the result of that undo is returned.
- * Otherwise, the Undo request is ignored and an
- * error NS_ERROR_NOT_AVAILABLE is returned.
- *
- */
- void undo(in unsigned long count);
-
- /** returns state information about the undo system.
- * @param aIsEnabled [OUT] PR_TRUE if undo is enabled
- * @param aCanUndo [OUT] PR_TRUE if at least one transaction is
- * currently ready to be undone.
- */
- void canUndo(out boolean isEnabled, out boolean canUndo);
-
- /** redo reverses the effects of the last Undo operation
- * It is provided here so clients need no knowledge of whether
- * the editor has a transaction manager or not.
- * If a transaction manager is present, it is told to redo and the
- * result of the previously undone transaction is reapplied to the document.
- * If no transaction is available for Redo, or if the document
- * has no transaction manager, the Redo request is ignored and an
- * error NS_ERROR_NOT_AVAILABLE is returned.
- *
- */
- void redo(in unsigned long count);
-
- /** returns state information about the redo system.
- * @param aIsEnabled [OUT] PR_TRUE if redo is enabled
- * @param aCanRedo [OUT] PR_TRUE if at least one transaction is
- currently ready to be redone.
- */
- void canRedo(out boolean isEnabled, out boolean canRedo);
-
- /** beginTransaction is a signal from the caller to the editor that
- * the caller will execute multiple updates to the content tree
- * that should be treated as a single logical operation,
- * in the most efficient way possible.<br>
- * All transactions executed between a call to beginTransaction and
- * endTransaction will be undoable as an atomic action.<br>
- * endTransaction must be called after beginTransaction.<br>
- * Calls to beginTransaction can be nested, as long as endTransaction
- * is called once per beginUpdate.
- */
- void beginTransaction();
-
- /** endTransaction is a signal to the editor that the caller is
- * finished updating the content model.<br>
- * beginUpdate must be called before endTransaction is called.<br>
- * Calls to beginTransaction can be nested, as long as endTransaction
- * is called once per beginTransaction.
- */
- void endTransaction();
-
- void beginPlaceHolderTransaction(in nsIAtom name);
- void endPlaceHolderTransaction();
- boolean shouldTxnSetSelection();
-
- /** Set the flag that prevents insertElementTxn from changing the selection
- * @param should Set false to suppress changing the selection;
- * i.e., before using InsertElement() to insert
- * under <head> element
- * WARNING: You must be very careful to reset back to PR_TRUE after
- * setting PR_FALSE, else selection/caret is trashed
- * for further editing.
- */
- void setShouldTxnSetSelection(in boolean should);
-
- /* ------------ Inline Spell Checking methods -------------- */
-
- /** Returns the inline spell checker associated with this object. The spell
- * checker is lazily created, so this function may create the object for
- * you during this call.
- * @param autoCreate If true, this will create a spell checker object
- * if one does not exist yet for this editor. If false
- * and the object has not been created, this function
- * WILL RETURN NULL.
- */
- nsIInlineSpellChecker getInlineSpellChecker(in boolean autoCreate);
-
- /** Resyncs spellchecking state (enabled/disabled). This should be called
- * when anything that affects spellchecking state changes, such as the
- * spellcheck attribute value.
- */
- void syncRealTimeSpell();
-
- /** Called when the user manually overrides the spellchecking state for this
- * editor.
- * @param enable The new state of spellchecking in this editor, as
- * requested by the user.
- */
- void setSpellcheckUserOverride(in boolean enable);
-
- /* ------------ Clipboard methods -------------- */
-
- /** cut the currently selected text, putting it into the OS clipboard
- * What if no text is selected?
- * What about mixed selections?
- * What are the clipboard formats?
- */
- void cut();
-
- /** Can we cut? True if the doc is modifiable, and we have a non-
- * collapsed selection.
- */
- boolean canCut();
-
- /** copy the currently selected text, putting it into the OS clipboard
- * What if no text is selected?
- * What about mixed selections?
- * What are the clipboard formats?
- */
- void copy();
-
- /** Can we copy? True if we have a non-collapsed selection.
- */
- boolean canCopy();
-
- /** Can we delete? True if we have a non-collapsed selection.
- */
- boolean canDelete();
-
- /** paste the text in the OS clipboard at the cursor position, replacing
- * the selected text (if any)
- */
- void paste(in long aSelectionType);
-
- /** Paste the text in |aTransferable| at the cursor position, replacing the
- * selected text (if any).
- */
- void pasteTransferable(in nsITransferable aTransferable);
-
- /** Can we paste? True if the doc is modifiable, and we have
- * pasteable data in the clipboard.
- */
- boolean canPaste(in long aSelectionType);
-
- /** Can we paste |aTransferable| or, if |aTransferable| is null, will a call
- * to pasteTransferable later possibly succeed if given an instance of
- * nsITransferable then? True if the doc is modifiable, and, if
- * |aTransfeable| is non-null, we have pasteable data in |aTransfeable|.
- */
- boolean canPasteTransferable([optional] in nsITransferable aTransferable);
-
- /* ------------ Selection methods -------------- */
-
- /** sets the document selection to the entire contents of the document */
- void selectAll();
-
- /** sets the document selection to the beginning of the document */
- void beginningOfDocument();
-
- /** sets the document selection to the end of the document */
- void endOfDocument();
-
- /* ------------ Node manipulation methods -------------- */
-
- /**
- * setAttribute() sets the attribute of aElement.
- * No checking is done to see if aAttribute is a legal attribute of the node,
- * or if aValue is a legal value of aAttribute.
- *
- * @param aElement the content element to operate on
- * @param aAttribute the string representation of the attribute to set
- * @param aValue the value to set aAttribute to
- */
- void setAttribute(in nsIDOMElement aElement, in AString attributestr,
- in AString attvalue);
-
- /**
- * getAttributeValue() retrieves the attribute's value for aElement.
- *
- * @param aElement the content element to operate on
- * @param aAttribute the string representation of the attribute to get
- * @param aResultValue [OUT] the value of aAttribute.
- * Only valid if aResultIsSet is PR_TRUE
- * @return PR_TRUE if aAttribute is set on the current node,
- * PR_FALSE if it is not.
- */
- boolean getAttributeValue(in nsIDOMElement aElement,
- in AString attributestr,
- out AString resultValue);
-
- /**
- * removeAttribute() deletes aAttribute from the attribute list of aElement.
- * If aAttribute is not an attribute of aElement, nothing is done.
- *
- * @param aElement the content element to operate on
- * @param aAttribute the string representation of the attribute to get
- */
- void removeAttribute(in nsIDOMElement aElement,
- in AString aAttribute);
-
- /**
- * cloneAttribute() copies the attribute from the source node to
- * the destination node and delete those not in the source.
- *
- * The supplied nodes MUST BE ELEMENTS (most callers are working with nodes)
- * @param aAttribute the name of the attribute to copy
- * @param aDestNode the destination element to operate on
- * @param aSourceNode the source element to copy attributes from
- * @exception NS_ERROR_NULL_POINTER at least one of the nodes is null
- * @exception NS_ERROR_NO_INTERFACE at least one of the nodes is not an
- * element
- */
- void cloneAttribute(in AString aAttribute,
- in nsIDOMNode aDestNode, in nsIDOMNode aSourceNode);
-
- /**
- * cloneAttributes() is similar to nsIDOMNode::cloneNode(),
- * it assures the attribute nodes of the destination are identical
- * with the source node by copying all existing attributes from the
- * source and deleting those not in the source.
- * This is used when the destination node (element) already exists
- *
- * The supplied nodes MUST BE ELEMENTS (most callers are working with nodes)
- * @param aDestNode the destination element to operate on
- * @param aSourceNode the source element to copy attributes from
- */
- void cloneAttributes(in nsIDOMNode destNode, in nsIDOMNode sourceNode);
-
- /**
- * createNode instantiates a new element of type aTag and inserts it
- * into aParent at aPosition.
- * @param aTag The type of object to create
- * @param aParent The node to insert the new object into
- * @param aPosition The place in aParent to insert the new node
- * @return The node created. Caller must release aNewNode.
- */
- nsIDOMNode createNode(in AString tag,
- in nsIDOMNode parent,
- in long position);
-
- /**
- * insertNode inserts aNode into aParent at aPosition.
- * No checking is done to verify the legality of the insertion.
- * That is the responsibility of the caller.
- * @param aNode The DOM Node to insert.
- * @param aParent The node to insert the new object into
- * @param aPosition The place in aParent to insert the new node
- * 0=first child, 1=second child, etc.
- * any number > number of current children = last child
- */
- void insertNode(in nsIDOMNode node,
- in nsIDOMNode parent,
- in long aPosition);
-
-
- /**
- * splitNode() creates a new node identical to an existing node,
- * and split the contents between the two nodes
- * @param aExistingRightNode the node to split.
- * It will become the new node's next sibling.
- * @param aOffset the offset of aExistingRightNode's
- * content|children to do the split at
- * @param aNewLeftNode [OUT] the new node resulting from the split,
- * becomes aExistingRightNode's previous sibling.
- */
- void splitNode(in nsIDOMNode existingRightNode,
- in long offset,
- out nsIDOMNode newLeftNode);
-
- /**
- * joinNodes() takes 2 nodes and merge their content|children.
- * @param aLeftNode The left node. It will be deleted.
- * @param aRightNode The right node. It will remain after the join.
- * @param aParent The parent of aExistingRightNode
- *
- * There is no requirement that the two nodes be
- * of the same type. However, a text node can be
- * merged only with another text node.
- */
- void joinNodes(in nsIDOMNode leftNode,
- in nsIDOMNode rightNode,
- in nsIDOMNode parent);
-
- /**
- * deleteNode removes aChild from aParent.
- * @param aChild The node to delete
- */
- void deleteNode(in nsIDOMNode child);
-
- /**
- * Returns true if markNodeDirty() has any effect. Returns false if
- * markNodeDirty() is a no-op.
- */
- [notxpcom] boolean outputsMozDirty();
-
- /**
- * markNodeDirty() sets a special dirty attribute on the node.
- * Usually this will be called immediately after creating a new node.
- * @param aNode The node for which to insert formatting.
- */
- void markNodeDirty(in nsIDOMNode node);
-
-/* ---------- direction controller ---------- */
-
- /**
- * Switches the editor element direction; from "Left-to-Right" to
- * "Right-to-Left", and vice versa.
- */
- void switchTextDirection();
-
-/* ------------ Output methods -------------- */
-
- /**
- * Output methods:
- * aFormatType is a mime type, like text/plain.
- */
- AString outputToString(in AString formatType,
- in unsigned long flags);
- void outputToStream(in nsIOutputStream aStream,
- in AString formatType,
- in ACString charsetOverride,
- in unsigned long flags);
-
-
- /* ------------ Various listeners methods --------------
- * nsIEditor holds strong references to the editor observers, action listeners
- * and document state listeners.
- */
-
- /** add an EditorObserver to the editors list of observers. */
- void addEditorObserver(in nsIEditorObserver observer);
-
- /** Remove an EditorObserver from the editor's list of observers. */
- void removeEditorObserver(in nsIEditorObserver observer);
-
- /** add an EditActionListener to the editors list of listeners. */
- void addEditActionListener(in nsIEditActionListener listener);
-
- /** Remove an EditActionListener from the editor's list of listeners. */
- void removeEditActionListener(in nsIEditActionListener listener);
-
- /** Add a DocumentStateListener to the editors list of doc state listeners. */
- void addDocumentStateListener(in nsIDocumentStateListener listener);
-
- /** Remove a DocumentStateListener to the editors list of doc state listeners. */
- void removeDocumentStateListener(in nsIDocumentStateListener listener);
-
-
- /* ------------ Debug methods -------------- */
-
- /**
- * And a debug method -- show us what the tree looks like right now
- */
- void dumpContentTree();
-
- /** Dumps a text representation of the content tree to standard out */
- void debugDumpContent() ;
-
- /* Run unit tests. Noop in optimized builds */
- void debugUnitTests(out long outNumTests, out long outNumTestsFailed);
-
- /* checks if a node is read-only or not */
- [notxpcom] boolean isModifiableNode(in nsIDOMNode aNode);
-
- /* Set true if you want to suppress dispatching input event. */
- attribute boolean suppressDispatchingInputEvent;
-
- /**
- * True if an edit action is being handled (in other words, between calls of
- * nsIEditorObserver::BeforeEditAction() and nsIEditorObserver::EditAction()
- * or nsIEditorObserver::CancelEditAction(). Otherwise, false.
- */
- [noscript] readonly attribute boolean isInEditAction;
-};
diff --git a/editor/nsIEditorIMESupport.idl b/editor/nsIEditorIMESupport.idl
deleted file mode 100644
index 4e4e4a50a..000000000
--- a/editor/nsIEditorIMESupport.idl
+++ /dev/null
@@ -1,40 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "domstubs.idl"
-
-%{C++
-namespace mozilla {
-namespace widget {
-struct IMEState;
-} // namespace widget
-} // namespace mozilla
-%}
-
-native IMEState(mozilla::widget::IMEState);
-
-[scriptable, uuid(0ba7f490-afb8-46dd-87fc-bc6137fbc899)]
-
-interface nsIEditorIMESupport : nsISupports
-{
- /**
- * forceCompositionEnd() force the composition end
- */
-
- void forceCompositionEnd();
-
- /**
- * Get preferred IME status of current widget.
- */
-
- [noscript] IMEState getPreferredIMEState();
-
- /**
- * whether this editor has active IME transaction
- */
- readonly attribute boolean composing;
-};
-
diff --git a/editor/nsIEditorMailSupport.idl b/editor/nsIEditorMailSupport.idl
deleted file mode 100644
index 3616bceee..000000000
--- a/editor/nsIEditorMailSupport.idl
+++ /dev/null
@@ -1,81 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsIArray;
-interface nsIDOMNode;
-
-[scriptable, uuid(fdf23301-4a94-11d3-9ce4-9960496c41bc)]
-
-interface nsIEditorMailSupport : nsISupports
-{
- /** Paste the text in the OS clipboard at the cursor position,
- * as a quotation (whose representation is dependant on the editor type),
- * replacing the selected text (if any).
- * @param aSelectionType Text or html?
- */
- void pasteAsQuotation(in long aSelectionType);
-
- /** Insert a string as quoted text
- * (whose representation is dependant on the editor type),
- * replacing the selected text (if any).
- * @param aQuotedText The actual text to be quoted
- * @return The node which was inserted
- */
- nsIDOMNode insertAsQuotation(in AString aQuotedText);
-
- /**
- * Inserts a plaintext string at the current location,
- * with special processing for lines beginning with ">",
- * which will be treated as mail quotes and inserted
- * as plaintext quoted blocks.
- * If the selection is not collapsed, the selection is deleted
- * and the insertion takes place at the resulting collapsed selection.
- *
- * @param aString the string to be inserted
- */
- void insertTextWithQuotations(in DOMString aStringToInsert);
-
- /** Paste a string as quoted text,
- * whose representation is dependant on the editor type,
- * replacing the selected text (if any)
- * @param aCitation The "mid" URL of the source message
- * @param aSelectionType Text or html?
- */
- void pasteAsCitedQuotation(in AString aCitation,
- in long aSelectionType);
-
- /** Insert a string as quoted text
- * (whose representation is dependant on the editor type),
- * replacing the selected text (if any),
- * including, if possible, a "cite" attribute.
- * @param aQuotedText The actual text to be quoted
- * @param aCitation The "mid" URL of the source message
- * @param aInsertHTML Insert as html? (vs plaintext)
- * @return The node which was inserted
- */
- nsIDOMNode insertAsCitedQuotation(in AString aQuotedText,
- in AString aCitation,
- in boolean aInsertHTML);
-
- /**
- * Rewrap the selected part of the document, re-quoting if necessary.
- * @param aRespectNewlines Try to maintain newlines in the original?
- */
- void rewrap(in boolean aRespectNewlines);
-
- /**
- * Strip any citations in the selected part of the document.
- */
- void stripCites();
-
-
- /**
- * Get a list of IMG and OBJECT tags in the current document.
- */
- nsIArray getEmbeddedObjects();
-};
-
diff --git a/editor/nsIEditorObserver.idl b/editor/nsIEditorObserver.idl
deleted file mode 100644
index c916b4c13..000000000
--- a/editor/nsIEditorObserver.idl
+++ /dev/null
@@ -1,36 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-/*
-Editor Observer interface to outside world
-*/
-
-[scriptable, uuid(f3ee57a6-890c-4ce0-a584-8a84bba0292e)]
-
-/**
- * A generic editor observer interface.
- * <P>
- * nsIEditorObserver is the interface used by applications wishing to be notified
- * when the editor has completed a user action.
- *
- */
-interface nsIEditorObserver : nsISupports {
- /**
- * Called after the editor completes a user action.
- */
- void EditAction();
- /**
- * Called when editor starts to handle a user action. I.e., This must be
- * called before the first DOM change.
- */
- void BeforeEditAction();
- /**
- * Called after BeforeEditAction() is called but EditorAction() won't be
- * called.
- */
- void CancelEditAction();
-};
diff --git a/editor/nsIEditorSpellCheck.idl b/editor/nsIEditorSpellCheck.idl
deleted file mode 100644
index adf4a0a03..000000000
--- a/editor/nsIEditorSpellCheck.idl
+++ /dev/null
@@ -1,166 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsIEditor;
-interface nsITextServicesFilter;
-interface nsIEditorSpellCheckCallback;
-
-[scriptable, uuid(a171c25f-e4a8-4d08-adef-b797e6377bdc)]
-interface nsIEditorSpellCheck : nsISupports
-{
-
- /**
- * Returns true if we can enable spellchecking. If there are no available
- * dictionaries, this will return false.
- */
- boolean canSpellCheck();
-
- /**
- * Turns on the spell checker for the given editor. enableSelectionChecking
- * set means that we only want to check the current selection in the editor,
- * (this controls the behavior of GetNextMisspelledWord). For spellchecking
- * clients with no modal UI (such as inline spellcheckers), this flag doesn't
- * matter. Initialization is asynchronous and is not complete until the given
- * callback is called.
- */
- void InitSpellChecker(in nsIEditor editor, in boolean enableSelectionChecking,
- [optional] in nsIEditorSpellCheckCallback callback);
-
- /**
- * When interactively spell checking the document, this will return the
- * value of the next word that is misspelled. This also computes the
- * suggestions which you can get by calling GetSuggestedWord.
- *
- * @see nsISpellChecker::GetNextMisspelledWord
- */
- wstring GetNextMisspelledWord();
-
- /**
- * Used to get suggestions for the last word that was checked and found to
- * be misspelled. The first call will give you the first (best) suggestion.
- * Subsequent calls will iterate through all the suggestions, allowing you
- * to build a list. When there are no more suggestions, an empty string
- * (not a null pointer) will be returned.
- *
- * @see nsISpellChecker::GetSuggestedWord
- */
- wstring GetSuggestedWord();
-
- /**
- * Check a given word. In spite of the name, this function checks the word
- * you give it, returning true if the word is misspelled. If the word is
- * misspelled, it will compute the suggestions which you can get from
- * GetSuggestedWord().
- *
- * @see nsISpellChecker::CheckCurrentWord
- */
- boolean CheckCurrentWord(in wstring suggestedWord);
-
- /**
- * Use when modally checking the document to replace a word.
- *
- * @see nsISpellChecker::CheckCurrentWord
- */
- void ReplaceWord(in wstring misspelledWord, in wstring replaceWord, in boolean allOccurrences);
-
- /**
- * @see nsISpellChecker::IgnoreAll
- */
- void IgnoreWordAllOccurrences(in wstring word);
-
- /**
- * Fills an internal list of words added to the personal dictionary. These
- * words can be retrieved using GetPersonalDictionaryWord()
- *
- * @see nsISpellChecker::GetPersonalDictionary
- * @see GetPersonalDictionaryWord
- */
- void GetPersonalDictionary();
-
- /**
- * Used after you call GetPersonalDictionary() to iterate through all the
- * words added to the personal dictionary. Will return the empty string when
- * there are no more words.
- */
- wstring GetPersonalDictionaryWord();
-
- /**
- * Adds a word to the current personal dictionary.
- *
- * @see nsISpellChecker::AddWordToDictionary
- */
- void AddWordToDictionary(in wstring word);
-
- /**
- * Removes a word from the current personal dictionary.
- *
- * @see nsISpellChecker::RemoveWordFromPersonalDictionary
- */
- void RemoveWordFromDictionary(in wstring word);
-
- /**
- * Retrieves a list of the currently available dictionaries. The strings will
- * typically be language IDs, like "en-US".
- *
- * @see mozISpellCheckingEngine::GetDictionaryList
- */
- void GetDictionaryList([array, size_is(count)] out wstring dictionaryList, out uint32_t count);
-
- /**
- * @see nsISpellChecker::GetCurrentDictionary
- */
- AString GetCurrentDictionary();
-
- /**
- * @see nsISpellChecker::SetCurrentDictionary
- */
- void SetCurrentDictionary(in AString dictionary);
-
- /**
- * Call this to free up the spell checking object. It will also save the
- * current selected language as the default for future use.
- *
- * If you have called CanSpellCheck but not InitSpellChecker, you can still
- * call this function to clear the cached spell check object, and no
- * preference saving will happen.
- */
- void UninitSpellChecker();
-
- /**
- * Used to filter the content (for example, to skip blockquotes in email from
- * spellchecking. Call this before calling InitSpellChecker; calling it
- * after initialization will have no effect.
- *
- * @see nsITextServicesDocument::setFilter
- */
- void setFilter(in nsITextServicesFilter filter);
-
- /**
- * Like CheckCurrentWord, checks the word you give it, returning true if it's
- * misspelled. This is faster than CheckCurrentWord because it does not
- * compute any suggestions.
- *
- * Watch out: this does not clear any suggestions left over from previous
- * calls to CheckCurrentWord, so there may be suggestions, but they will be
- * invalid.
- */
- boolean CheckCurrentWordNoSuggest(in wstring suggestedWord);
-
- /**
- * Update the dictionary in use to be sure it corresponds to what the editor
- * needs. The update is asynchronous and is not complete until the given
- * callback is called.
- */
- void UpdateCurrentDictionary([optional] in nsIEditorSpellCheckCallback callback);
-
-};
-
-[scriptable, function, uuid(5f0a4bab-8538-4074-89d3-2f0e866a1c0b)]
-interface nsIEditorSpellCheckCallback : nsISupports
-{
- void editorSpellCheckDone();
-};
diff --git a/editor/nsIEditorStyleSheets.idl b/editor/nsIEditorStyleSheets.idl
deleted file mode 100644
index 7f8c365e6..000000000
--- a/editor/nsIEditorStyleSheets.idl
+++ /dev/null
@@ -1,71 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(4805e682-49b9-11d3-9ce4-ed60bd6cb5bc)]
-
-interface nsIEditorStyleSheets : nsISupports
-{
- /** Load and apply the style sheet, specified by aURL, to the
- * editor's document, replacing the last style sheet added (if any).
- * This is always asynchronous, and may cause network I/O.
- *
- * @param aURL The style sheet to be loaded and applied.
- */
- void replaceStyleSheet(in AString aURL);
-
- /** Add the given style sheet to the editor's document,
- * on top of any that are already there.
- * This is always asynchronous, and may cause network I/O.
- *
- * @param aURL The style sheet to be loaded and applied.
- */
- void addStyleSheet(in AString aURL);
-
- /** Load and apply the override style sheet, specified by aURL, to the
- * editor's document, replacing the last override style sheet added (if any).
- * This is always synchronous, so aURL should be a local file with only
- * local @imports. This action is not undoable. It is not intended for
- * "user" style sheets, only for editor developers to add sheets to change
- * display behavior for editing (like showing special cursors) that will
- * not be affected by loading "document" style sheets with addStyleSheet or
- * especially replaceStyleSheet.
- *
- * @param aURL The style sheet to be loaded and applied.
- */
- void replaceOverrideStyleSheet(in AString aURL);
-
- /** Load and apply an override style sheet, specified by aURL, to
- * the editor's document, on top of any that are already there.
- * This is always synchronous, so the same caveats about local files and no
- * non-local @import as replaceOverrideStyleSheet apply here, too.
- *
- * @param aURL The style sheet to be loaded and applied.
- */
- void addOverrideStyleSheet(in AString aURL);
-
- /** Remove the given style sheet from the editor's document
- * This is always synchronous
- *
- * @param aURL The style sheet to be removed
- */
- void removeStyleSheet(in AString aURL);
-
- /** Remove the given override style sheet from the editor's document
- * This is always synchronous
- *
- * @param aURL The style sheet to be removed.
- */
- void removeOverrideStyleSheet(in AString aURL);
-
- /** Enable or disable the given style sheet from the editor's document
- * This is always synchronous
- *
- * @param aURL The style sheet to be enabled or disabled
- * @param aEnable true to enable, or false to disable the style sheet
- */
- void enableStyleSheet(in AString aURL, in boolean aEnable);
-};
diff --git a/editor/nsIEditorUtils.idl b/editor/nsIEditorUtils.idl
deleted file mode 100644
index 95637d281..000000000
--- a/editor/nsIEditorUtils.idl
+++ /dev/null
@@ -1,32 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "domstubs.idl"
-
-interface nsIDOMBlob;
-interface mozIDOMWindowProxy;
-
-[scriptable, uuid(eb8b8ad9-5d8f-43bd-8ce5-5b943c180d56)]
-interface nsIEditorBlobListener : nsISupports
-{
- void onResult(in ACString aResult);
- void onError(in AString aErrorName);
-};
-
-/**
- * A collection of utility functions that editors can use that are more easily
- * done in JavaScript.
- */
-[scriptable, uuid(4bf94928-575e-4bd1-8321-a2c4b3d0119e)]
-interface nsIEditorUtils : nsISupports
-{
- /**
- * Given a blob, returns the data from that blob, asynchronously.
- */
- void slurpBlob(in nsIDOMBlob aBlob, in mozIDOMWindowProxy aScope,
- in nsIEditorBlobListener aListener);
-};
diff --git a/editor/nsIHTMLAbsPosEditor.idl b/editor/nsIHTMLAbsPosEditor.idl
deleted file mode 100644
index 7ecffac60..000000000
--- a/editor/nsIHTMLAbsPosEditor.idl
+++ /dev/null
@@ -1,132 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "domstubs.idl"
-
-[scriptable, uuid(91375f52-20e6-4757-9835-eb04fabe5498)]
-
-interface nsIHTMLAbsPosEditor : nsISupports
-{
- /**
- * true if the selection container is absolutely positioned
- */
- readonly attribute boolean selectionContainerAbsolutelyPositioned;
-
- /**
- * this contains the absolutely positioned element currently edited
- * or null
- */
- readonly attribute nsIDOMElement positionedElement;
-
- /**
- * true if Absolute Positioning handling is enabled in the editor
- */
- attribute boolean absolutePositioningEnabled;
-
-
- /* Utility methods */
-
- /**
- * true if Snap To Grid is enabled in the editor.
- */
- attribute boolean snapToGridEnabled;
-
- /**
- * sets the grid size in pixels.
- * @param aSizeInPixels [IN] the size of the grid in pixels
- */
- attribute unsigned long gridSize;
-
- /* Selection-based methods */
-
- /**
- * returns the deepest absolutely positioned container of the selection
- * if it exists or null.
- */
- readonly attribute nsIDOMElement absolutelyPositionedSelectionContainer;
-
- /**
- * extracts the selection from the normal flow of the document and
- * positions it.
- * @param aEnabled [IN] true to absolutely position the selection,
- * false to put it back in the normal flow
- */
- void absolutePositionSelection(in boolean aEnabled);
-
- /**
- * adds aChange to the z-index of the currently positioned element.
- * @param aChange [IN] relative change to apply to current z-index
- */
- void relativeChangeZIndex(in long aChange);
-
- /* Element-based methods */
-
- /**
- * extracts an element from the normal flow of the document and
- * positions it, and puts it back in the normal flow.
- * @param aElement [IN] the element
- * @param aEnabled [IN] true to absolutely position the element,
- * false to put it back in the normal flow
- */
- void absolutelyPositionElement(in nsIDOMElement aElement,
- in boolean aEnabled);
-
- /**
- * sets the position of an element; warning it does NOT check if the
- * element is already positioned or not and that's on purpose.
- * @param aElement [IN] the element
- * @param aX [IN] the x position in pixels.
- * @param aY [IN] the y position in pixels.
- */
- void setElementPosition(in nsIDOMElement aElement, in long aX, in long aY);
-
- /**
- * returns the absolute z-index of a positioned element. Never returns 'auto'.
- * @return the z-index of the element
- * @param aElement [IN] the element.
- */
- long getElementZIndex(in nsIDOMElement aElement);
-
- /**
- * sets the z-index of an element.
- * @param aElement [IN] the element
- * @param aZorder [IN] the z-index
- */
- void setElementZIndex(in nsIDOMElement aElement, in long aZorder);
-
- /**
- * adds aChange to the z-index of an arbitrary element.
- * @return the new z-index of the element
- * @param aElement [IN] the element
- * @param aChange [IN] relative change to apply to current z-index of
- * the element
- */
- long relativeChangeElementZIndex(in nsIDOMElement aElement, in long aChange);
-
- /* Other */
-
- /**
- * shows a grabber attached to an arbitrary element. The grabber is an image
- * positioned on the left hand side of the top border of the element. Dragging
- * and dropping it allows to change the element's absolute position in the
- * document. See chrome://editor/content/images/grabber.gif
- * @param aElement [IN] the element
- */
- void showGrabberOnElement(in nsIDOMElement aElement);
-
- /**
- * hide the grabber if it shown.
- */
- void hideGrabber();
-
- /**
- * refreshes the grabber if it shown, possibly updating its position or
- * even hiding it.
- */
- void refreshGrabber();
-
-};
-
diff --git a/editor/nsIHTMLEditor.idl b/editor/nsIHTMLEditor.idl
deleted file mode 100644
index 27bca9dbe..000000000
--- a/editor/nsIHTMLEditor.idl
+++ /dev/null
@@ -1,559 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "domstubs.idl"
-
-interface nsIAtom;
-interface nsIContent;
-interface nsIArray;
-interface nsISelection;
-interface nsIContentFilter;
-
-%{C++
-namespace mozilla {
-namespace dom {
-class Element;
-}
-}
-%}
-
-[ptr] native Element (mozilla::dom::Element);
-
-[scriptable, uuid(87ee993e-985f-4a43-a974-0d9512da2fb0)]
-interface nsIHTMLEditor : nsISupports
-{
-%{C++
- typedef short EAlignment;
-%}
-
- // used by GetAlignment()
- const short eLeft = 0;
- const short eCenter = 1;
- const short eRight = 2;
- const short eJustify = 3;
-
-
- /* ------------ Inline property methods -------------- */
-
-
- /**
- * AddDefaultProperty() registers a default style property with the editor
- *
- * @param aProperty the property to set by default
- * @param aAttribute the attribute of the property, if applicable.
- * May be null.
- * Example: aProperty="font", aAttribute="color"
- * @param aValue if aAttribute is not null, the value of the attribute.
- * Example: aProperty="font", aAttribute="color",
- * aValue="0x00FFFF"
- */
- void addDefaultProperty(in nsIAtom aProperty,
- in AString aAttribute,
- in AString aValue);
-
- /**
- * RemoveDefaultProperty() unregisters a default style property with the editor
- *
- * @param aProperty the property to remove from defaults
- * @param aAttribute the attribute of the property, if applicable.
- * May be null.
- * Example: aProperty="font", aAttribute="color"
- * @param aValue if aAttribute is not null, the value of the attribute.
- * Example: aProperty="font", aAttribute="color",
- * aValue="0x00FFFF"
- */
- void removeDefaultProperty(in nsIAtom aProperty,
- in AString aAttribute,
- in AString aValue);
-
- /**
- * RemoveAllDefaultProperties() unregisters all default style properties with the editor
- *
- */
- void removeAllDefaultProperties();
-
- /**
- * SetInlineProperty() sets the aggregate properties on the current selection
- *
- * @param aProperty the property to set on the selection
- * @param aAttribute the attribute of the property, if applicable.
- * May be null.
- * Example: aProperty="font", aAttribute="color"
- * @param aValue if aAttribute is not null, the value of the attribute.
- * May be null.
- * Example: aProperty="font", aAttribute="color",
- * aValue="0x00FFFF"
- */
- void setInlineProperty(in nsIAtom aProperty,
- in AString aAttribute,
- in AString aValue);
-
- /**
- * getInlineProperty() gets aggregate properties of the current selection.
- * All object in the current selection are scanned and their attributes are
- * represented in a list of Property object.
- *
- * @param aProperty the property to get on the selection
- * @param aAttribute the attribute of the property, if applicable.
- * May be null.
- * Example: aProperty="font", aAttribute="color"
- * @param aValue if aAttribute is not null, the value of the attribute.
- * May be null.
- * Example: aProperty="font", aAttribute="color",
- * aValue="0x00FFFF"
- * @param aFirst [OUT] PR_TRUE if the first text node in the
- * selection has the property
- * @param aAny [OUT] PR_TRUE if any of the text nodes in the
- * selection have the property
- * @param aAll [OUT] PR_TRUE if all of the text nodes in the
- * selection have the property
- */
- void getInlineProperty(in nsIAtom aProperty,
- in AString aAttribute,
- in AString aValue,
- out boolean aFirst,
- out boolean aAny,
- out boolean aAll);
-
- AString getInlinePropertyWithAttrValue(in nsIAtom aProperty,
- in AString aAttribute,
- in AString aValue,
- out boolean aFirst,
- out boolean aAny,
- out boolean aAll);
-
- /**
- * removeAllInlineProperties() deletes all the inline properties from all
- * text in the current selection.
- */
- void removeAllInlineProperties();
-
-
- /**
- * removeInlineProperty() deletes the properties from all text in the current
- * selection. If aProperty is not set on the selection, nothing is done.
- *
- * @param aProperty the property to remove from the selection
- * All atoms are for normal HTML tags (e.g.:
- * nsIEditorProperty::font) except when you want to
- * remove just links and not named anchors.
- * For that, use nsIEditorProperty::href
- * @param aAttribute the attribute of the property, if applicable.
- * May be null.
- * Example: aProperty=nsIEditorProptery::font,
- * aAttribute="color"
- * nsIEditProperty::allAttributes is special.
- * It indicates that all content-based text properties
- * are to be removed from the selection.
- */
- void removeInlineProperty(in nsIAtom aProperty, in AString aAttribute);
-
- /**
- * Increase font size for text in selection by 1 HTML unit
- * All existing text is scanned for existing <FONT SIZE> attributes
- * so they will be incremented instead of inserting new <FONT> tag
- */
- void increaseFontSize();
-
- /**
- * Decrease font size for text in selection by 1 HTML unit
- * All existing text is scanned for existing <FONT SIZE> attributes
- * so they will be decreased instead of inserting new <FONT> tag
- */
- void decreaseFontSize();
-
- /* ------------ HTML content methods -------------- */
-
- /**
- * Tests if a node is a BLOCK element according the the HTML 4.0 DTD.
- * This does NOT consider CSS effect on display type
- *
- * @param aNode the node to test
- */
- boolean nodeIsBlock(in nsIDOMNode node);
-
- /**
- * Insert some HTML source at the current location
- *
- * @param aInputString the string to be inserted
- */
- void insertHTML(in AString aInputString);
-
-
- /**
- * Paste the text in the OS clipboard at the cursor position, replacing
- * the selected text (if any), but strip out any HTML styles and formatting
- */
- void pasteNoFormatting(in long aSelectionType);
-
- /**
- * Rebuild the entire document from source HTML
- * Needed to be able to edit HEAD and other outside-of-BODY content
- *
- * @param aSourceString HTML source string of the entire new document
- */
- void rebuildDocumentFromSource(in AString aSourceString);
-
- /**
- * Insert some HTML source, interpreting
- * the string argument according to the given context.
- *
- * @param aInputString the string to be inserted
- * @param aContextStr Context of insertion
- * @param aInfoStr Related info to aInputString
- * @param aFlavor Transferable flavor, can be ""
- * @param aSourceDoc document where input was dragged from (may be null)
- * @param aDestinationNode location for insertion (such as when dropped)
- * @param aDestinationOffset used with aDestNode to determine insert location
- * @param aDeleteSelection used with aDestNode during drag&drop
- * @param aCollapseSelection used with aDestNode during drag&drop
- */
- void insertHTMLWithContext(in AString aInputString,
- in AString aContextStr,
- in AString aInfoStr,
- in AString aFlavor,
- in nsIDOMDocument aSourceDoc,
- in nsIDOMNode aDestinationNode,
- in long aDestinationOffset,
- in boolean aDeleteSelection);
-
-
- /**
- * Insert an element, which may have child nodes, at the selection
- * Used primarily to insert a new element for various insert element dialogs,
- * but it enforces the HTML 4.0 DTD "CanContain" rules, so it should
- * be useful for other elements.
- *
- * @param aElement The element to insert
- * @param aDeleteSelection Delete the selection before inserting
- * If aDeleteSelection is PR_FALSE, then the element is inserted
- * after the end of the selection for all element except
- * Named Anchors, which insert before the selection
- */
- void insertElementAtSelection(in nsIDOMElement aElement,
- in boolean aDeleteSelection);
-
- /**
- * Set the documents title.
- */
- void setDocumentTitle(in AString aTitle);
-
- /**
- * Set the BaseURL for the document to the current URL
- * but only if the page doesn't have a <base> tag
- * This should be done after the document URL has changed,
- * such as after saving a file
- * This is used as base for relativizing link and image urls
- */
- void updateBaseURL();
-
-
- /* ------------ Selection manipulation -------------- */
- /* Should these be moved to nsISelection? */
-
- /**
- * Set the selection at the suppled element
- *
- * @param aElement An element in the document
- */
- void selectElement(in nsIDOMElement aElement);
-
- /**
- * Create a collapsed selection just after aElement
- *
- * XXX could we parameterize SelectElement(before/select/after>?
- *
- * The selection is set to parent-of-aElement with an
- * offset 1 greater than aElement's offset
- * but it enforces the HTML 4.0 DTD "CanContain" rules, so it should
- * be useful for other elements.
- *
- * @param aElement An element in the document
- */
- void setCaretAfterElement(in nsIDOMElement aElement);
-
- /**
- * SetParagraphFormat Insert a block paragraph tag around selection
- * @param aParagraphFormat "p", "h1" to "h6", "address", "pre", or "blockquote"
- */
- void setParagraphFormat(in AString aParagraphFormat);
-
- /**
- * getParagraphState returns what block tag paragraph format is in
- * the selection.
- * @param aMixed True if there is more than one format
- * @return Name of block tag. "" is returned for none.
- */
- AString getParagraphState(out boolean aMixed);
-
- /**
- * getFontFaceState returns what font face is in the selection.
- * @param aMixed True if there is more than one font face
- * @return Name of face. Note: "tt" is returned for
- * tt tag. "" is returned for none.
- */
- AString getFontFaceState(out boolean aMixed);
-
- /**
- * getFontColorState returns what font face is in the selection.
- * @param aMixed True if there is more than one font color
- * @return Color string. "" is returned for none.
- */
- AString getFontColorState(out boolean aMixed);
-
- /**
- * getFontColorState returns what font face is in the selection.
- * @param aMixed True if there is more than one font color
- * @return Color string. "" is returned for none.
- */
- AString getBackgroundColorState(out boolean aMixed);
-
- /**
- * getHighlightColorState returns what the highlight color of the selection.
- * @param aMixed True if there is more than one font color
- * @return Color string. "" is returned for none.
- */
- AString getHighlightColorState(out boolean aMixed);
-
- /**
- * getListState returns what list type is in the selection.
- * @param aMixed True if there is more than one type of list, or
- * if there is some list and non-list
- * @param aOL The company that employs me. No, really, it's
- * true if an "ol" list is selected.
- * @param aUL true if an "ul" list is selected.
- * @param aDL true if a "dl" list is selected.
- */
- void getListState(out boolean aMixed, out boolean aOL, out boolean aUL,
- out boolean aDL);
-
- /**
- * getListItemState returns what list item type is in the selection.
- * @param aMixed True if there is more than one type of list item, or
- * if there is some list and non-list
- * @param aLI true if "li" list items are selected.
- * @param aDT true if "dt" list items are selected.
- * @param aDD true if "dd" list items are selected.
- */
- void getListItemState(out boolean aMixed, out boolean aLI,
- out boolean aDT, out boolean aDD);
-
- /**
- * getAlignment returns what alignment is in the selection.
- * @param aMixed True if there is more than one type of list item, or
- * if there is some list and non-list
- * @param aAlign enum value for first encountered alignment
- * (left/center/right)
- */
- void getAlignment(out boolean aMixed, out short aAlign);
-
- /**
- * Document me!
- *
- */
- void getIndentState(out boolean aCanIndent, out boolean aCanOutdent);
-
- /**
- * Document me!
- *
- */
- void makeOrChangeList(in AString aListType, in boolean entireList,
- in AString aBulletType);
-
- /**
- * Document me!
- *
- */
- void removeList(in AString aListType);
-
- /**
- * Document me!
- *
- */
- void indent(in AString aIndent);
-
- /**
- * Document me!
- *
- */
- void align(in AString aAlign);
-
- /**
- * Return the input node or a parent matching the given aTagName,
- * starting the search at the supplied node.
- * An example of use is for testing if a node is in a table cell
- * given a selection anchor node.
- *
- * @param aTagName The HTML tagname
- * Special input values:
- * Use "href" to get a link node
- * (an "A" tag with the "href" attribute set)
- * Use "anchor" or "namedanchor" to get a named anchor node
- * (an "A" tag with the "name" attribute set)
- * Use "list" to get an OL, UL, or DL list node
- * Use "td" to get either a TD or TH cell node
- *
- * @param aNode The node in the document to start the search.
- * If it is null, the anchor node of the current selection is used.
- * @return NS_EDITOR_ELEMENT_NOT_FOUND if an element is not found
- * (passes NS_SUCCEEDED macro)
- */
- nsIDOMElement getElementOrParentByTagName(in AString aTagName,
- in nsIDOMNode aNode);
-
- /**
- * Return an element only if it is the only node selected,
- * such as an image, horizontal rule, etc.
- * The exception is a link, which is more like a text attribute:
- * The Anchor tag is returned if the selection is within the textnode(s)
- * that are children of the "A" node.
- * This could be a collapsed selection, i.e., a caret
- * within the link text.
- *
- * @param aTagName The HTML tagname or and empty string
- * to get any element (but only if it is the only element selected)
- * Special input values for Links and Named anchors:
- * Use "href" to get a link node
- * (an "A" tag with the "href" attribute set)
- * Use "anchor" or "namedanchor" to get a named anchor node
- * (an "A" tag with the "name" attribute set)
- * @return NS_EDITOR_ELEMENT_NOT_FOUND if an element is not found
- * (passes NS_SUCCEEDED macro)
- */
- nsIDOMElement getSelectedElement(in AString aTagName);
-
- /**
- * Output the contents of the <HEAD> section as text/HTML format
- */
- AString getHeadContentsAsHTML();
-
- /**
- * Replace all children of <HEAD> with string of HTML source
- */
- void replaceHeadContentsWithHTML(in AString aSourceToInsert);
-
- /**
- * Return a new element with default attribute values
- *
- * This does not rely on the selection, and is not sensitive to context.
- *
- * Used primarily to supply new element for various insert element dialogs
- * (Image, Link, NamedAnchor, Table, and HorizontalRule
- * are the only returned elements as of 7/25/99)
- *
- * @param aTagName The HTML tagname
- * Special input values for Links and Named anchors:
- * Use "href" to get a link node
- * (an "A" tag with the "href" attribute set)
- * Use "anchor" or "namedanchor" to get a named anchor node
- * (an "A" tag with the "name" attribute set)
- * @return The new element created.
- */
- nsIDOMElement createElementWithDefaults(in AString aTagName);
-
- /**
- * Insert an link element as the parent of the current selection
- *
- * @param aElement An "A" element with a non-empty "href" attribute
- */
- void insertLinkAroundSelection(in nsIDOMElement aAnchorElement);
-
- /**
- * Set the value of the "bgcolor" attribute on the document's <body> element
- *
- * @param aColor The HTML color string, such as "#ffccff" or "yellow"
- */
- void setBackgroundColor(in AString aColor);
-
-
- /**
- * Set an attribute on the document's <body> element
- * such as text, link, background colors
- *
- * 8/31/00 THIS ISN'T BEING USED? SHOULD WE DROP IT?
- *
- * @param aAttr The attribute to be set
- * @param aValue The value of the attribute
- */
- void setBodyAttribute(in AString aAttr, in AString aValue);
-
- /**
- * Find all the nodes in the document which contain references
- * to outside URIs (e.g. a href, img src, script src, etc.)
- * The objects in the array will be type nsIURIRefObject.
- *
- * @return aNodeList the linked nodes found
- */
- nsIArray getLinkedObjects();
-
- /**
- * A boolean which is true is the HTMLEditor has been instantiated
- * with CSS knowledge and if the CSS pref is currently checked
- *
- * @return true if CSS handled and enabled
- */
- attribute boolean isCSSEnabled;
-
- /**
- * Add listener for insertion override
- * @param inFilter function which callers want called during insertion
- */
- void addInsertionListener(in nsIContentFilter inFilter);
-
- /**
- * Remove listener for insertion override
- * @param inFilter function which callers do not want called during insertion
- */
- void removeInsertionListener(in nsIContentFilter inFilter);
-
- /**
- * Returns an anonymous nsDOMElement of type aTag,
- * child of aParentNode. If aIsCreatedHidden is true, the class
- * "hidden" is added to the created element. If aAnonClass is not
- * the empty string, it becomes the value of the attribute "_moz_anonclass"
- * @return a DOM Element
- * @param aTag [IN] a string representing the desired type of
- * the element to create
- * @param aParentNode [IN] the parent node of the created anonymous
- * element
- * @param aAnonClass [IN] contents of the _moz_anonclass attribute
- * @param aIsCreatedHidden [IN] a boolean specifying if the class "hidden"
- * is to be added to the created anonymous
- * element
- */
- nsIDOMElement createAnonymousElement(in AString aTag, in nsIDOMNode aParentNode,
- in AString aAnonClass, in boolean aIsCreatedHidden);
-
- /**
- * returns the deepest container of the selection
- * @return a DOM Element
- */
- nsIDOMElement getSelectionContainer();
-
- /**
- * Checks if the anonymous nodes created by the HTML editor have to be
- * refreshed or hidden depending on a possible new state of the selection
- * @param aSelection [IN] a selection
- */
- void checkSelectionStateForAnonymousButtons(in nsISelection aSelection);
-
- boolean isAnonymousElement(in nsIDOMElement aElement);
-
- /**
- * A boolean indicating if a return key pressed in a paragraph creates
- * another paragraph or just inserts a <br> at the caret
- *
- * @return true if CR in a paragraph creates a new paragraph
- */
- attribute boolean returnInParagraphCreatesNewParagraph;
-
- /**
- * Get an active editor's editing host in DOM window. If this editor isn't
- * active in the DOM window, this returns NULL.
- */
- [noscript, notxpcom] Element GetActiveEditingHost();
-};
-
diff --git a/editor/nsIHTMLInlineTableEditor.idl b/editor/nsIHTMLInlineTableEditor.idl
deleted file mode 100644
index f7b83b8d8..000000000
--- a/editor/nsIHTMLInlineTableEditor.idl
+++ /dev/null
@@ -1,44 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "domstubs.idl"
-
-[scriptable, uuid(eda2e65c-a758-451f-9b05-77cb8de74ed2)]
-
-interface nsIHTMLInlineTableEditor : nsISupports
-{
- /**
- * boolean indicating if inline table editing is enabled in the editor.
- * When inline table editing is enabled, and when the selection is
- * contained in a table cell, special buttons allowing to add/remove
- * a line/column are available on the cell's border.
- */
- attribute boolean inlineTableEditingEnabled;
-
- /**
- * Shows inline table editing UI around a table cell
- * @param aCell [IN] a DOM Element being a table cell, td or th
- */
- void showInlineTableEditingUI(in nsIDOMElement aCell);
-
- /**
- * Hide all inline table editing UI
- */
- void hideInlineTableEditingUI();
-
- /**
- * Modifies the table containing the selection according to the
- * activation of an inline table editing UI element
- * @param aUIAnonymousElement [IN] the inline table editing UI element
- */
- void doInlineTableEditingAction(in nsIDOMElement aUIAnonymousElement);
-
- /**
- * Refresh already visible inline table editing UI
- */
- void refreshInlineTableEditingUI();
-};
-
diff --git a/editor/nsIHTMLObjectResizeListener.idl b/editor/nsIHTMLObjectResizeListener.idl
deleted file mode 100644
index 42e1c15f1..000000000
--- a/editor/nsIHTMLObjectResizeListener.idl
+++ /dev/null
@@ -1,33 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "domstubs.idl"
-
-[scriptable, uuid(27b00295-349c-429f-ad0c-87b859e77130)]
-
-interface nsIHTMLObjectResizeListener : nsISupports
-{
- /**
- * Listener's callback called by the editor when the user
- * starts resizing an element
- * @param aElement [IN] the element
- */
- void onStartResizing(in nsIDOMElement aElement);
-
- /**
- * Listener's callback called by the editor when the user
- * has finalized the resizing of an element
- * @param aElement [IN] the element that was resized
- * @param aOldWidth [IN] the width of the element before resizing
- * @param aOldHeight [IN] the height of the element before resizing
- * @param aNewWidth [IN] the width of the element after resizing
- * @param aNewHeight [IN] the height of the element after resizing
- */
- void onEndResizing(in nsIDOMElement aElement,
- in long aOldWidth, in long aOldHeight,
- in long aNewWidth, in long aNewHeight);
-
-};
diff --git a/editor/nsIHTMLObjectResizer.idl b/editor/nsIHTMLObjectResizer.idl
deleted file mode 100644
index 50201b34e..000000000
--- a/editor/nsIHTMLObjectResizer.idl
+++ /dev/null
@@ -1,93 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "domstubs.idl"
-
-interface nsIHTMLObjectResizeListener;
-
-[scriptable, uuid(8b396020-69d3-451f-80c1-1a96a7da25a9)]
-
-interface nsIHTMLObjectResizer : nsISupports
-{
-%{C++
- typedef short EResizerLocation;
-%}
- const short eTopLeft = 0;
- const short eTop = 1;
- const short eTopRight = 2;
- const short eLeft = 3;
- const short eRight = 4;
- const short eBottomLeft = 5;
- const short eBottom = 6;
- const short eBottomRight = 7;
-
- /**
- * the element currently displaying resizers
- */
- readonly attribute nsIDOMElement resizedObject;
-
- /**
- * a boolean indicating if object resizing is enabled in the editor
- */
- attribute boolean objectResizingEnabled;
-
- /**
- * Shows active resizers around an element's frame
- * @param aResizedElement [IN] a DOM Element
- */
- void showResizers(in nsIDOMElement aResizedElement);
-
- /**
- * Hide resizers if they are visible
- */
- void hideResizers();
-
- /**
- * Refresh visible resizers
- */
- void refreshResizers();
-
- /**
- * event callback when a mouse button is pressed
- * @param aX [IN] horizontal position of the pointer
- * @param aY [IN] vertical position of the pointer
- * @param aTarget [IN] the element triggering the event
- * @param aMouseEvent [IN] the event
- */
- void mouseDown(in long aX, in long aY,
- in nsIDOMElement aTarget, in nsIDOMEvent aMouseEvent);
-
- /**
- * event callback when a mouse button is released
- * @param aX [IN] horizontal position of the pointer
- * @param aY [IN] vertical position of the pointer
- * @param aTarget [IN] the element triggering the event
- */
- void mouseUp(in long aX, in long aY,
- in nsIDOMElement aTarget);
-
- /**
- * event callback when the mouse pointer is moved
- * @param aMouseEvent [IN] the event
- */
- void mouseMove(in nsIDOMEvent aMouseEvent);
-
- /* Event Listeners */
-
- /**
- * Creates a resize listener that can be used to get notifications
- * that the user started to resize an object or finalized such an operation
- * @param aListener [IN] an instance of nsIHTMLObjectResizeListener
- */
- void addObjectResizeEventListener(in nsIHTMLObjectResizeListener aListener);
-
- /**
- * Deletes a resize listener
- * @param aListener [IN] an instance of nsIHTMLObjectResizeListener
- */
- void removeObjectResizeEventListener(in nsIHTMLObjectResizeListener aListener);
-};
-
diff --git a/editor/nsIPlaintextEditor.idl b/editor/nsIPlaintextEditor.idl
deleted file mode 100644
index d823a4632..000000000
--- a/editor/nsIPlaintextEditor.idl
+++ /dev/null
@@ -1,112 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(b74fb158-1265-4102-91eb-edd0136b49f8)]
-interface nsIPlaintextEditor : nsISupports
-{
-
- // XXX Why aren't these in nsIEditor?
- // only plain text entry is allowed via events
- const long eEditorPlaintextMask = 0x0001;
- // enter key and CR-LF handled specially
- const long eEditorSingleLineMask = 0x0002;
- // text is not entered into content, only a representative character
- const long eEditorPasswordMask = 0x0004;
- // editing events are disabled. Editor may still accept focus.
- const long eEditorReadonlyMask = 0x0008;
- // all events are disabled (like scrolling). Editor will not accept focus.
- const long eEditorDisabledMask = 0x0010;
- // text input is limited to certain character types, use mFilter
- const long eEditorFilterInputMask = 0x0020;
- // use mail-compose editing rules
- const long eEditorMailMask = 0x0040;
- // allow the editor to set font: monospace on the root node
- const long eEditorEnableWrapHackMask = 0x0080;
- // bit for widgets (form elements)
- const long eEditorWidgetMask = 0x0100;
- // this HTML editor should not create css styles
- const long eEditorNoCSSMask = 0x0200;
- // whether HTML document specific actions are executed or not.
- // e.g., if this flag is set, the editor doesn't handle Tab key.
- // besides, anchors of HTML are not clickable.
- const long eEditorAllowInteraction = 0x0400;
- // when this is set, the characters in password editor are always masked.
- // see bug 530367 for the detail.
- const long eEditorDontEchoPassword = 0x0800;
- // when this flag is set, the internal direction of the editor is RTL.
- // if neither of the direction flags are set, the direction is determined
- // from the text control's content node.
- const long eEditorRightToLeft = 0x1000;
- // when this flag is set, the internal direction of the editor is LTR.
- const long eEditorLeftToRight = 0x2000;
- // when this flag is set, the editor's text content is not spell checked.
- const long eEditorSkipSpellCheck = 0x4000;
-
- /*
- * The valid values for newlines handling.
- * Can't change the values unless we remove
- * use of the pref.
- */
- const long eNewlinesPasteIntact = 0;
- const long eNewlinesPasteToFirst = 1;
- const long eNewlinesReplaceWithSpaces = 2;
- const long eNewlinesStrip = 3;
- const long eNewlinesReplaceWithCommas = 4;
- const long eNewlinesStripSurroundingWhitespace = 5;
-
- /**
- * The length of the contents in characters.
- * XXX change this type to 'unsigned long'
- */
- readonly attribute long textLength;
-
- /**
- * The maximum number of characters allowed.
- * default: -1 (unlimited).
- */
- attribute long maxTextLength;
-
- /** Get and set the body wrap width.
- *
- * Special values:
- * 0 = wrap to window width
- * -1 = no wrap at all
- */
- attribute long wrapWidth;
-
- /**
- * Similar to the setter for wrapWidth, but just sets the editor
- * internal state without actually changing the content being edited
- * to wrap at that column. This should only be used by callers who
- * are sure that their content is already set up correctly.
- */
- void setWrapColumn(in long aWrapColumn);
-
- /** Get and set newline handling.
- *
- * Values are the constants defined above.
- */
- attribute long newlineHandling;
-
- /**
- * Inserts a string at the current location,
- * given by the selection.
- * If the selection is not collapsed, the selection is deleted
- * and the insertion takes place at the resulting collapsed selection.
- *
- * @param aString the string to be inserted
- */
- void insertText(in DOMString aStringToInsert);
-
- /**
- * Insert a line break into the content model.
- * The interpretation of a break is up to the implementation:
- * it may enter a character, split a node in the tree, etc.
- * This may be more efficient than calling InsertText with a newline.
- */
- void insertLineBreak();
-};
diff --git a/editor/nsITableEditor.idl b/editor/nsITableEditor.idl
deleted file mode 100644
index e48062af2..000000000
--- a/editor/nsITableEditor.idl
+++ /dev/null
@@ -1,337 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-#include "nsISupports.idl"
-
-interface nsIDOMNode;
-interface nsIDOMElement;
-interface nsIDOMRange;
-
-[scriptable, uuid(4805e684-49b9-11d3-9ce4-ed60bd6cb5bc)]
-
-interface nsITableEditor : nsISupports
-{
- const short eNoSearch = 0;
- const short ePreviousColumn = 1;
- const short ePreviousRow = 2;
-
- /* ------------ Table editing Methods -------------- */
-
- /** Insert table methods
- * Insert relative to the selected cell or the
- * cell enclosing the selection anchor
- * The selection is collapsed and is left in the new cell
- * at the same row,col location as the original anchor cell
- *
- * @param aNumber Number of items to insert
- * @param aAfter If TRUE, insert after the current cell,
- * else insert before current cell
- */
- void insertTableCell(in long aNumber, in boolean aAfter);
- void insertTableColumn(in long aNumber, in boolean aAfter);
- void insertTableRow(in long aNumber, in boolean aAfter);
-
- /** Delete table methods
- * Delete starting at the selected cell or the
- * cell (or table) enclosing the selection anchor
- * The selection is collapsed and is left in the
- * cell at the same row,col location as
- * the previous selection anchor, if possible,
- * else in the closest neigboring cell
- *
- * @param aNumber Number of items to insert/delete
- */
- void deleteTable();
-
- /** Delete just the cell contents
- * This is what should happen when Delete key is used
- * for selected cells, to minimize upsetting the table layout
- */
- void deleteTableCellContents();
-
- /** Delete cell elements as well as contents
- * @param aNumber Number of contiguous cells, rows, or columns
- *
- * When there are more than 1 selected cells, aNumber is ignored.
- * For Delete Rows or Columns, the complete columns or rows are
- * determined by the selected cells. E.g., to delete 2 complete rows,
- * user simply selects a cell in each, and they don't
- * have to be contiguous.
- */
- void deleteTableCell(in long aNumber);
- void deleteTableColumn(in long aNumber);
- void deleteTableRow(in long aNumber);
-
- /** Table Selection methods
- * Selecting a row or column actually
- * selects all cells (not TR in the case of rows)
- */
- void selectTableCell();
-
- /** Select a rectangular block of cells:
- * all cells falling within the row/column index of aStartCell
- * to through the row/column index of the aEndCell
- * aStartCell can be any location relative to aEndCell,
- * as long as they are in the same table
- * @param aStartCell starting cell in block
- * @param aEndCell ending cell in block
- */
- void selectBlockOfCells(in nsIDOMElement aStartCell,
- in nsIDOMElement aEndCell);
-
- void selectTableRow();
- void selectTableColumn();
- void selectTable();
- void selectAllTableCells();
-
- /** Create a new TD or TH element, the opposite type of the supplied aSourceCell
- * 1. Copy all attributes from aSourceCell to the new cell
- * 2. Move all contents of aSourceCell to the new cell
- * 3. Replace aSourceCell in the table with the new cell
- *
- * @param aSourceCell The cell to be replaced
- * @return The new cell that replaces aSourceCell
- */
- nsIDOMElement switchTableCellHeaderType(in nsIDOMElement aSourceCell);
-
- /** Merges contents of all selected cells
- * for selected cells that are adjacent,
- * this will result in a larger cell with appropriate
- * rowspan and colspan, and original cells are deleted
- * The resulting cell is in the location of the
- * cell at the upper-left corner of the adjacent
- * block of selected cells
- *
- * @param aMergeNonContiguousContents:
- * If true:
- * Non-contiguous cells are not deleted,
- * but their contents are still moved
- * to the upper-left cell
- * If false: contiguous cells are ignored
- *
- * If there are no selected cells,
- * and selection or caret is in a cell,
- * that cell and the one to the right
- * are merged
- */
- void joinTableCells(in boolean aMergeNonContiguousContents);
-
- /** Split a cell that has rowspan and/or colspan > 0
- * into cells such that all new cells have
- * rowspan = 1 and colspan = 1
- * All of the contents are not touched --
- * they will appear to be in the upper-left cell
- */
- void splitTableCell();
-
- /** Scan through all rows and add cells as needed so
- * all locations in the cellmap are occupied.
- * Used after inserting single cells or pasting
- * a collection of cells that extend past the
- * previous size of the table
- * If aTable is null, it uses table enclosing the selection anchor
- * This doesn't doesn't change the selection,
- * thus it can be used to fixup all tables
- * in a page independent of the selection
- */
- void normalizeTable(in nsIDOMElement aTable);
-
- /** Get the row an column index from the layout's cellmap
- * If aCell is null, it will try to find enclosing table of selection anchor
- *
- */
- void getCellIndexes(in nsIDOMElement aCell,
- out long aRowIndex, out long aColIndex);
-
- /** Get the number of rows and columns in a table from the layout's cellmap
- * If aTable is null, it will try to find enclosing table of selection ancho
- * Note that all rows in table will not have this many because of
- * ROWSPAN effects or if table is not "rectangular" (has short rows)
- */
- void getTableSize(in nsIDOMElement aTable,
- out long aRowCount, out long aColCount);
-
- /** Get a cell element at cellmap grid coordinates
- * A cell that spans across multiple cellmap locations will
- * be returned multiple times, once for each location it occupies
- *
- * @param aTable A table in the document
- * @param aRowIndex, aColIndex The 0-based cellmap indexes
- *
- * (in C++ returns: NS_EDITOR_ELEMENT_NOT_FOUND if an element is not found
- * passes NS_SUCCEEDED macro)
- *
- * You can scan for all cells in a row or column
- * by iterating through the appropriate indexes
- * until the returned aCell is null
- */
- nsIDOMElement getCellAt(in nsIDOMElement aTable,
- in long aRowIndex, in long aColIndex);
-
- /** Get a cell at cellmap grid coordinates and associated data
- * A cell that spans across multiple cellmap locations will
- * be returned multiple times, once for each location it occupies
- * Examine the returned aStartRowIndex and aStartColIndex to see
- * if it is in the same layout column or layout row:
- * A "layout row" is all cells sharing the same top edge
- * A "layout column" is all cells sharing the same left edge
- * This is important to determine what to do when inserting or deleting a column or row
- *
- * @param aTable A table in the document
- * @param aRowIndex, aColIndex The 0-based cellmap indexes
- * returns values:
- * @param aCell The cell at this cellmap location
- * @param aStartRowIndex The row index where cell starts
- * @param aStartColIndex The col index where cell starts
- * @param aRowSpan May be 0 (to span down entire table) or number of cells spanned
- * @param aColSpan May be 0 (to span across entire table) or number of cells spanned
- * @param aActualRowSpan The actual number of cellmap locations (rows) spanned by the cell
- * @param aActualColSpan The actual number of cellmap locations (columns) spanned by the cell
- * @param aIsSelected
- * @param
- *
- * (in C++ returns: NS_EDITOR_ELEMENT_NOT_FOUND if an element is not found
- * passes NS_SUCCEEDED macro)
- */
- void getCellDataAt(in nsIDOMElement aTable,
- in long aRowIndex, in long aColIndex,
- out nsIDOMElement aCell,
- out long aStartRowIndex, out long aStartColIndex,
- out long aRowSpan, out long aColSpan,
- out long aActualRowSpan, out long aActualColSpan,
- out boolean aIsSelected);
-
- /** Get the first row element in a table
- *
- * @return The row at the requested index
- * Returns null if there are no rows in table
- * (in C++ returns: NS_EDITOR_ELEMENT_NOT_FOUND if an element is not found
- * passes NS_SUCCEEDED macro)
- */
- nsIDOMNode getFirstRow(in nsIDOMElement aTableElement);
-
- /** Get the next row element starting the search from aTableElement
- *
- * @param aTableElement Any TR or child-of-TR element in the document
- *
- * @return The row to start search from
- * and the row returned from the search
- * Returns null if there isn't another row
- * (in C++ returns: NS_EDITOR_ELEMENT_NOT_FOUND if an element is not found
- * passes NS_SUCCEEDED macro)
- */
- nsIDOMNode getNextRow(in nsIDOMNode aTableElement);
-
- /** Preferred direction to search for neighboring cell
- * when trying to locate a cell to place caret in after
- * a table editing action.
- * Used for aDirection param in SetSelectionAfterTableEdit
- */
-
- /** Reset a selected cell or collapsed selection (the caret) after table editing
- *
- * @param aTable A table in the document
- * @param aRow The row ...
- * @param aCol ... and column defining the cell
- * where we will try to place the caret
- * @param aSelected If true, we select the whole cell instead of setting caret
- * @param aDirection If cell at (aCol, aRow) is not found,
- * search for previous cell in the same
- * column (aPreviousColumn) or row (ePreviousRow)
- * or don't search for another cell (aNoSearch)
- * If no cell is found, caret is place just before table;
- * and if that fails, at beginning of document.
- * Thus we generally don't worry about the return value
- * and can use the nsSetSelectionAfterTableEdit stack-based
- * object to insure we reset the caret in a table-editing method.
- */
- void setSelectionAfterTableEdit(in nsIDOMElement aTable,
- in long aRow, in long aCol,
- in long aDirection, in boolean aSelected);
-
- /** Examine the current selection and find
- * a selected TABLE, TD or TH, or TR element.
- * or return the parent TD or TH if selection is inside a table cell
- * Returns null if no table element is found.
- *
- * @param aTagName The tagname of returned element
- * Note that "td" will be returned if name
- * is actually "th"
- * @param aCount How many table elements were selected
- * This tells us if we have multiple cells selected
- * (0 if element is a parent cell of selection)
- * @return The table element (table, row, or first selected cell)
- *
- */
- nsIDOMElement getSelectedOrParentTableElement(out AString aTagName, out long aCount);
-
- /** Generally used after GetSelectedOrParentTableElement
- * to test if selected cells are complete rows or columns
- *
- * @param aElement Any table or cell element or any element
- * inside a table
- * Used to get enclosing table.
- * If null, selection's anchorNode is used
- *
- * @return
- * 0 aCellElement was not a cell
- * (returned result = NS_ERROR_FAILURE)
- * TABLESELECTION_CELL There are 1 or more cells selected but
- * complete rows or columns are not selected
- * TABLESELECTION_ROW All cells are in 1 or more rows
- * and in each row, all cells selected
- * Note: This is the value if all rows
- * (thus all cells) are selected
- * TABLESELECTION_COLUMN All cells are in 1 or more columns
- * and in each column, all cells are selected
- */
- uint32_t getSelectedCellsType(in nsIDOMElement aElement);
-
- /** Get first selected element from first selection range.
- * (If multiple cells were selected this is the first in the order they were selected)
- * Assumes cell-selection model where each cell
- * is in a separate range (selection parent node is table row)
- * @param aCell [OUT] Selected cell or null if ranges don't contain
- * cell selections
- * @param aRange [OUT] Optional: if not null, return the selection range
- * associated with the cell
- * Returns the DOM cell element
- * (in C++: returns NS_EDITOR_ELEMENT_NOT_FOUND if an element is not found
- * passes NS_SUCCEEDED macro)
- */
- nsIDOMElement getFirstSelectedCell(out nsIDOMRange aRange);
-
- /** Get first selected element in the table
- * This is the upper-left-most selected cell in table,
- * ignoring the order that the user selected them (order in the selection ranges)
- * Assumes cell-selection model where each cell
- * is in a separate range (selection parent node is table row)
- * @param aCell Selected cell or null if ranges don't contain
- * cell selections
- * @param aRowIndex Optional: if not null, return row index of 1st cell
- * @param aColIndex Optional: if not null, return column index of 1st cell
- *
- * Returns the DOM cell element
- * (in C++: returns NS_EDITOR_ELEMENT_NOT_FOUND if an element is not found
- * passes NS_SUCCEEDED macro)
- */
- nsIDOMElement getFirstSelectedCellInTable(out long aRowIndex, out long aColIndex);
-
- /** Get next selected cell element from first selection range.
- * Assumes cell-selection model where each cell
- * is in a separate range (selection parent node is table row)
- * Always call GetFirstSelectedCell() to initialize stored index of "next" cell
- * @param aCell Selected cell or null if no more selected cells
- * or ranges don't contain cell selections
- * @param aRange Optional: if not null, return the selection range
- * associated with the cell
- *
- * Returns the DOM cell element
- * (in C++: returns NS_EDITOR_ELEMENT_NOT_FOUND if an element is not found
- * passes NS_SUCCEEDED macro)
- */
- nsIDOMElement getNextSelectedCell(out nsIDOMRange aRange);
-};
diff --git a/editor/nsIURIRefObject.idl b/editor/nsIURIRefObject.idl
deleted file mode 100644
index da53dd74d..000000000
--- a/editor/nsIURIRefObject.idl
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "domstubs.idl"
-
-interface nsIDOMNode;
-
-/** A class which can represent any node which points to an
- * external URI, e.g. <a>, <img>, <script> etc,
- * and has the capability to rewrite URLs to be
- * relative or absolute.
- * Used by the editor but not dependant on it.
- */
-
-[scriptable, uuid(2226927e-1dd2-11b2-b57f-faab47288563)]
-
-interface nsIURIRefObject : nsISupports
-{
- attribute nsIDOMNode node;
-
- /**
- * Go back to the beginning of the attribute list.
- */
- void Reset();
-
- /**
- * Return the next rewritable URI.
- */
- DOMString GetNextURI();
-
- /**
- * Go back to the beginning of the attribute list
- *
- * @param aOldPat Old pattern to be replaced, e.g. file:///a/b/
- * @param aNewPat New pattern to be replaced, e.g. http://mypage.aol.com/
- * @param aMakeRel Rewrite links as relative vs. absolute
- */
- void RewriteAllURIs(in DOMString aOldPat, in DOMString aNewPat,
- in boolean aMakeRel);
-};
diff --git a/editor/nsPIEditorTransaction.idl b/editor/nsPIEditorTransaction.idl
deleted file mode 100644
index 99ecdb891..000000000
--- a/editor/nsPIEditorTransaction.idl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-/*
- * The nsPIEditorTransaction interface.
- * <P>
- * This interface is implemented by every transaction created by this
- * editor implementation. It is used to help us distinguish our internal
- * transactions from those generated by 3rd party extensions.
- */
-[scriptable, uuid(4f18ada2-0ddc-11d5-9d3a-0060b0f8baff)]
-interface nsPIEditorTransaction : nsISupports
-{
- readonly attribute DOMString txnDescription;
-};
-
diff --git a/editor/reftests/1088158-ref.html b/editor/reftests/1088158-ref.html
deleted file mode 100644
index be4592e69..000000000
--- a/editor/reftests/1088158-ref.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<!DOCTYPE html>
-<textarea placeholder="placeholder"></textarea>
diff --git a/editor/reftests/1088158.html b/editor/reftests/1088158.html
deleted file mode 100644
index 435aa3f63..000000000
--- a/editor/reftests/1088158.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE html>
-<script>
- onload = function() {
- var t = document.createElement('textarea');
- t.placeholder = "placeholder";
- document.body.appendChild(t.cloneNode(true));
- }
-</script>
diff --git a/editor/reftests/338427-1-ref.html b/editor/reftests/338427-1-ref.html
deleted file mode 100644
index d645ad9fb..000000000
--- a/editor/reftests/338427-1-ref.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <textarea spellcheck="false" lang="testing-XX">strangeimpossibleword</textarea>
-</body>
-</html>
-
diff --git a/editor/reftests/338427-1.html b/editor/reftests/338427-1.html
deleted file mode 100644
index 7a645a224..000000000
--- a/editor/reftests/338427-1.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <!-- invalid language will default to en-US, but no spell check since element is not focussed -->
- <textarea lang="testing-XX">strangeimpossibleword</textarea>
-</body>
-</html>
diff --git a/editor/reftests/338427-2-ref.html b/editor/reftests/338427-2-ref.html
deleted file mode 100644
index 30a468c3e..000000000
--- a/editor/reftests/338427-2-ref.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-<script>
-function init() {
- var editor = document.getElementById('editor');
- editor.addEventListener("focus", function() {
- window.setTimeout(function() {
- document.documentElement.className = '';
- }, 0);
- }, false);
- editor.focus();
-}
-</script>
-<body onload="init()">
- <!-- invalid language will default to en-US -->
- <div id="editor" lang="testing-XX" contenteditable="true" spellcheck="false">good possible word</div>
-</body>
-</html>
-
diff --git a/editor/reftests/338427-2.html b/editor/reftests/338427-2.html
deleted file mode 100644
index 7f29e91fb..000000000
--- a/editor/reftests/338427-2.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-<script>
-function init() {
- var editor = document.getElementById('editor');
- editor.addEventListener("focus", function() {
- window.setTimeout(function() {
- document.documentElement.className = '';
- }, 0);
- }, false);
- editor.focus();
-}
-</script>
-<body onload="init()">
- <!-- invalid language will default to en-US -->
- <div id="editor" lang="testing-XX" contenteditable="true">good possible word</div>
-</body>
-</html>
diff --git a/editor/reftests/338427-3-ref.html b/editor/reftests/338427-3-ref.html
deleted file mode 100644
index b72ccc997..000000000
--- a/editor/reftests/338427-3-ref.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-<script>
-function init() {
- var editor = document.getElementById('editor');
- // invalid language will default to en-US
- editor.setAttribute('lang', 'testing-XX');
- editor.addEventListener("focus", function() {
- window.setTimeout(function() {
- document.documentElement.className = '';
- }, 0);
- }, false);
- editor.focus();
-}
-</script>
-<body onload="init()">
- <textarea id="editor" spellcheck="false" lang="en-US">good possible word</textarea>
-</body>
-</html>
diff --git a/editor/reftests/338427-3.html b/editor/reftests/338427-3.html
deleted file mode 100644
index 6aead81da..000000000
--- a/editor/reftests/338427-3.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-<script>
-function init() {
- var editor = document.getElementById('editor');
- // invalid language will default to en-US
- editor.setAttribute('lang', 'testing-XX');
- editor.addEventListener("focus", function() {
- window.setTimeout(function() {
- document.documentElement.className = '';
- }, 0);
- }, false);
- editor.focus();
-}
-</script>
-<body onload="init()">
- <textarea id="editor" lang="en-US">good possible word</textarea>
-</body>
-</html>
diff --git a/editor/reftests/388980-1-ref.html b/editor/reftests/388980-1-ref.html
deleted file mode 100644
index 8b14d7e18..000000000
--- a/editor/reftests/388980-1-ref.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<html>
-<head>
-<title>Reftest for bug 388980</title></html>
-<script type="text/javascript">
-
-var text = '<html><head></head><body style="font-size:16px;">'
- + '<p><span style="background-color:red;">This paragraph should be red</span></p>'
- + '<p><span style="background-color:blue;">This paragraph should be blue</span></p>'
- + '<p>This paragraph should not be colored</p>'
- + '</body></html>';
-
-function initIFrame() {
- var doc = document.getElementById('theIFrame').contentDocument;
- doc.designMode = 'on';
- doc.open('text/html');
- doc.write(text);
- doc.close();
-}
-</script>
-</head>
-<body onload="initIFrame()" >
-<iframe id="theIFrame">
-</iframe>
-</body>
-</html>
diff --git a/editor/reftests/388980-1.html b/editor/reftests/388980-1.html
deleted file mode 100644
index f2e7d0de0..000000000
--- a/editor/reftests/388980-1.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<html>
-<head>
-<title>Reftest for bug 388980</title></html>
-<script type="text/javascript">
-
-var text = '<html><head></head><body style="font-size:16px;">'
- + '<p id="redpar">This paragraph should be red</p>'
- + '<p id="bluepar">This paragraph should be blue</p>'
- + '<p>This paragraph should not be colored</p>'
- +'</body></html>';
-
-
-function colorPar(par, color) {
- var doc = document.getElementById('theIFrame').contentDocument;
- var win = document.getElementById('theIFrame').contentWindow;
- win.getSelection().selectAllChildren(doc.getElementById(par));
- doc.execCommand("hilitecolor", false, color);
- win.getSelection().removeAllRanges();
-}
-
-function initIFrame() {
- var doc = document.getElementById('theIFrame').contentDocument;
- doc.designMode = 'on';
- doc.open('text/html');
- doc.write(text);
- doc.close();
-
- // Test hilighting with styleWithCSS, should hilight the text...
- doc.execCommand("styleWithCSS", false, true);
- colorPar("redpar", "red");
-
- // Test highlighting without styleWithCSS, should also work.
- doc.execCommand("styleWithCSS", false, false);
- colorPar("bluepar", "blue");
-
-}
-</script>
-</head>
-<body>
-<iframe id="theIFrame" onload="initIFrame()">
-</iframe>
-</body>
-</html>
diff --git a/editor/reftests/462758-grabbers-resizers-ref.html b/editor/reftests/462758-grabbers-resizers-ref.html
deleted file mode 100644
index 5627cde74..000000000
--- a/editor/reftests/462758-grabbers-resizers-ref.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-<head>
- <script type="text/javascript">
- function init() {
- var editor = document.querySelector("div[contenteditable]");
- editor.addEventListener("focus", function() {
- setTimeout(function() {
- document.documentElement.className = "";
- }, 0);
- }, false);
- editor.focus();
- }
- </script>
- <style type="text/css">
- html, body, div {
- margin: 0;
- padding: 0;
- }
- div {
- border: 1px solid black;
- margin: 50px;
- height: 200px;
- width: 200px;
- }
- </style>
-</head>
-<body onload="init()">
- <div contenteditable>
- this editable container should be neither draggable nor resizable.
- </div>
-</body>
-</html>
-
diff --git a/editor/reftests/462758-grabbers-resizers.html b/editor/reftests/462758-grabbers-resizers.html
deleted file mode 100644
index 66a8d8482..000000000
--- a/editor/reftests/462758-grabbers-resizers.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-<head>
- <script type="text/javascript">
- function init() {
- var editor = document.querySelector("div[contenteditable]");
- editor.addEventListener("focus", function() {
- setTimeout(function() {
- document.documentElement.className = "";
- }, 0);
- }, false);
- editor.focus();
- }
- </script>
- <style type="text/css">
- html, body, div {
- margin: 0;
- padding: 0;
- }
- div {
- border: 1px solid black;
- margin: 50px;
- height: 200px;
- width: 200px;
- }
- </style>
-</head>
-<body onload="init()">
- <div contenteditable style="position: absolute">
- this editable container should be neither draggable nor resizable.
- </div>
-</body>
-</html>
diff --git a/editor/reftests/642800-iframe.html b/editor/reftests/642800-iframe.html
deleted file mode 100644
index bb1ab6397..000000000
--- a/editor/reftests/642800-iframe.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <style>
- @media only screen and (max-width: 480px) {
- .overflow-hidden
- {
- overflow: hidden;
- }
-
- .float-left
- {
- float: left;
- background: #f0f;
- }
- }
- </style>
-</head>
-<body>
- <h1>Iframe content</h1>
- <div class="float-left">
- <textarea>This text should be visible when window is resized </textarea>
-
- </div>
- <div class="overflow-hidden">
- <textarea>This text should be visible when window is resized </textarea>
- </div>
-</body>
-</html>
diff --git a/editor/reftests/642800-ref.html b/editor/reftests/642800-ref.html
deleted file mode 100644
index f062b145b..000000000
--- a/editor/reftests/642800-ref.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-<body>
- <iframe onload="document.documentElement.className=''" src="642800-iframe.html" id="iframe" style="width: 500px; height: 200px"></iframe>
-</body>
-</html>
-
diff --git a/editor/reftests/642800.html b/editor/reftests/642800.html
deleted file mode 100644
index f2af58923..000000000
--- a/editor/reftests/642800.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-<head>
- <script type="text/javascript">
- function reframe(node) {
- node.style.display = "none";
- document.body.offsetWidth;
- node.style.display = "block";
- document.documentElement.className='';
- }
- </script>
-</head>
-<body>
- <iframe onload="reframe(this)" src="642800-iframe.html" id="iframe" style="width: 500px; height: 200px"></iframe>
-
-</body>
-</html>
-
diff --git a/editor/reftests/672709-ref.html b/editor/reftests/672709-ref.html
deleted file mode 100644
index b9fc369b0..000000000
--- a/editor/reftests/672709-ref.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
- <body>
- <style>
- :-moz-read-only { color: red; }
- :-moz-read-write { color: green; }
- </style>
- <script>
- onload = function() {
- document.designMode = "on";
- var p = document.createElement("p");
- p.textContent = "test";
- document.getElementById("x").appendChild(p);
- getSelection().removeAllRanges(); // don't need a caret
- document.documentElement.removeAttribute("class");
- };
- </script>
- <div contenteditable id="x">
- </div>
- more test
- </body>
-</html>
diff --git a/editor/reftests/672709.html b/editor/reftests/672709.html
deleted file mode 100644
index d42c54b0c..000000000
--- a/editor/reftests/672709.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <style>
- body { color: green; }
- </style>
- <div>
- <p>test</p>
- </div>
- more test
- </body>
-</html>
diff --git a/editor/reftests/674212-spellcheck-ref.html b/editor/reftests/674212-spellcheck-ref.html
deleted file mode 100644
index 2b2a6dfc6..000000000
--- a/editor/reftests/674212-spellcheck-ref.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<html lang="en-US" class="reftest-wait">
-<head>
- <script type="text/javascript">
- function init() {
- var editor = document.querySelector("div[contenteditable]");
- editor.addEventListener("focus", function() {
- setTimeout(function() {
- document.documentElement.className = "";
- }, 0);
- }, false);
- editor.focus();
- }
- </script>
-</head>
-<body onload="init()">
- <div contenteditable spellcheck>This is another misspellored word.</div>
-</body>
-</html>
-
diff --git a/editor/reftests/674212-spellcheck.html b/editor/reftests/674212-spellcheck.html
deleted file mode 100644
index f22f5c453..000000000
--- a/editor/reftests/674212-spellcheck.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<html lang="en-US" class="reftest-wait">
-<head>
- <script type="text/javascript">
- function init() {
- var editor = document.querySelector("div[contenteditable]");
- editor.addEventListener("focus", function() {
- editor.textContent = "This is another misspellored word.";
- setTimeout(function() {
- document.documentElement.className = "";
- }, 0);
- }, false);
- editor.focus();
- }
- </script>
-</head>
-<body onload="init()">
- <div contenteditable spellcheck>This is a misspellored word.</div>
-</body>
-</html>
diff --git a/editor/reftests/694880-1.html b/editor/reftests/694880-1.html
deleted file mode 100644
index 373c3070a..000000000
--- a/editor/reftests/694880-1.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<html>
- <style>
- :-moz-read-only { color: green; }
- :-moz-read-write { color: red; }
- </style>
- <body onload="document.designMode='on';document.designMode='off'">
- <div>test</div>
- </body>
-</html>
diff --git a/editor/reftests/694880-2.html b/editor/reftests/694880-2.html
deleted file mode 100644
index 9f2617883..000000000
--- a/editor/reftests/694880-2.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
- <style>
- :-moz-read-only { color: green; }
- :-moz-read-write { color: red; }
- </style>
- <body onload="document.designMode='on';document.designMode='off'">
- <div>test</div>
- <div contenteditable></div>
- </body>
-</html>
diff --git a/editor/reftests/694880-3.html b/editor/reftests/694880-3.html
deleted file mode 100644
index c6d7837f7..000000000
--- a/editor/reftests/694880-3.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<html>
- <style>
- :-moz-read-only { color: red; }
- :-moz-read-write { color: green; }
- </style>
- <body onload="document.designMode='on';document.designMode='off'">
- <div contenteditable>test</div>
- </body>
-</html>
diff --git a/editor/reftests/694880-ref.html b/editor/reftests/694880-ref.html
deleted file mode 100644
index d5c40547e..000000000
--- a/editor/reftests/694880-ref.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
- <style>
- div { color: green; }
- </style>
- <body>
- <div>test</div>
- </body>
-</html>
diff --git a/editor/reftests/824080-1-ref.html b/editor/reftests/824080-1-ref.html
deleted file mode 100644
index 8a8786472..000000000
--- a/editor/reftests/824080-1-ref.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <script type="text/javascript">
- function doTest()
- {
- var editor = document.getElementById("editor");
- document.getSelection().selectAllChildren(document.body);
- }
- </script>
-</head>
-<body onload="doTest();">
-<p>normal text</p>
-<div id="editor">editable text</div>
-</body>
-</html>
-
diff --git a/editor/reftests/824080-1.html b/editor/reftests/824080-1.html
deleted file mode 100644
index 2dfe7e2c6..000000000
--- a/editor/reftests/824080-1.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <script type="text/javascript">
- function doTest()
- {
- var editor = document.getElementById("editor");
- editor.focus();
- editor.blur();
- document.getSelection().selectAllChildren(document.body);
- }
- </script>
-</head>
-<body onload="doTest();">
-<p>normal text</p>
-<div id="editor" contenteditable>editable text</div>
-</body>
-</html>
-
diff --git a/editor/reftests/824080-2-ref.html b/editor/reftests/824080-2-ref.html
deleted file mode 100644
index 597e09fdc..000000000
--- a/editor/reftests/824080-2-ref.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <script type="text/javascript">
- function doTest()
- {
- document.getSelection().selectAllChildren(document.getElementById("text"));
- var editor = document.getElementById("editor");
- var editorBody = editor.contentDocument.body;
- editor.contentDocument.getSelection().selectAllChildren(editorBody);
- editor.focus();
- editor.blur();
- }
- </script>
-</head>
-<body>
-<p id="text">normal text</p>
-<iframe id="editor" onload="doTest();"
- src="data:text/html,<body>editable text</body>"></iframe>
-</body>
-</html>
-
diff --git a/editor/reftests/824080-2.html b/editor/reftests/824080-2.html
deleted file mode 100644
index c4dc9afc6..000000000
--- a/editor/reftests/824080-2.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <script type="text/javascript">
- function doTest()
- {
- document.getSelection().selectAllChildren(document.getElementById("text"));
- var editor = document.getElementById("editor");
- var editorBody = editor.contentDocument.body;
- editor.contentDocument.getSelection().selectAllChildren(editorBody);
- editor.focus();
- editor.blur();
- }
- </script>
-</head>
-<body>
-<p id="text">normal text</p>
-<iframe id="editor" onload="doTest();"
- src="data:text/html,<script>document.designMode='on';</script><body>editable text</body>"></iframe>
-</body>
-</html>
-
diff --git a/editor/reftests/824080-3-ref.html b/editor/reftests/824080-3-ref.html
deleted file mode 100644
index 8849fc383..000000000
--- a/editor/reftests/824080-3-ref.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <script type="text/javascript">
- function doTest()
- {
- document.getSelection().selectAllChildren(document.getElementById("text"));
- var editor = document.getElementById("editor");
- var editorBody = editor.contentDocument.body;
- editor.contentDocument.getSelection().selectAllChildren(editorBody);
- editor.focus();
- }
- </script>
-</head>
-<body>
-<p id="text">normal text</p>
-<iframe id="editor" onload="doTest();"
- src="data:text/html,<body>editable text</body>"></iframe>
-</body>
-</html>
-
diff --git a/editor/reftests/824080-3.html b/editor/reftests/824080-3.html
deleted file mode 100644
index b9882e5bb..000000000
--- a/editor/reftests/824080-3.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <script type="text/javascript">
- function doTest()
- {
- document.getSelection().selectAllChildren(document.getElementById("text"));
- var editor = document.getElementById("editor");
- var editorBody = editor.contentDocument.body;
- editor.contentDocument.getSelection().selectAllChildren(editorBody);
- editor.focus();
- }
- </script>
-</head>
-<body>
-<p id="text">normal text</p>
-<iframe id="editor" onload="doTest();"
- src="data:text/html,<script>document.designMode='on';</script><body>editable text</body>"></iframe>
-</body>
-</html>
-
diff --git a/editor/reftests/824080-4-ref.html b/editor/reftests/824080-4-ref.html
deleted file mode 100644
index 3bee66458..000000000
--- a/editor/reftests/824080-4-ref.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <script type="text/javascript">
- function doTest()
- {
- document.getSelection().selectAllChildren(document.body);
- var editor = document.getElementById("editor");
- var editorBody = editor.contentDocument.body;
- editor.contentDocument.getSelection().selectAllChildren(editorBody);
- }
- </script>
-</head>
-<body>
-<p id="text">normal text</p>
-<div>content editable</div>
-<iframe id="editor" onload="doTest();"
- src="data:text/html,<body>editable text</body>"></iframe>
-</body>
-</html>
-
diff --git a/editor/reftests/824080-4.html b/editor/reftests/824080-4.html
deleted file mode 100644
index 14cf4eedf..000000000
--- a/editor/reftests/824080-4.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <script type="text/javascript">
- function doTest()
- {
- var editor1 = document.getElementById("editor1");
- editor1.focus();
- editor1.blur();
- document.getSelection().selectAllChildren(document.body);
- var editor2 = document.getElementById("editor2");
- var editorBody = editor2.contentDocument.body;
- editor2.contentDocument.getSelection().selectAllChildren(editorBody);
- editor2.focus();
- editor2.blur();
- }
- </script>
-</head>
-<body>
-<p>normal text</p>
-<div id="editor1" contenteditable>content editable</div>
-<iframe id="editor2" onload="doTest();"
- src="data:text/html,<script>document.designMode='on';</script><body>editable text</body>"></iframe>
-</body>
-</html>
-
diff --git a/editor/reftests/824080-5-ref.html b/editor/reftests/824080-5-ref.html
deleted file mode 100644
index 237fea213..000000000
--- a/editor/reftests/824080-5-ref.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <script type="text/javascript">
- function doTest()
- {
- document.getSelection().selectAllChildren(document.body);
- var editor = document.getElementById("editor");
- var editorBody = editor.contentDocument.body;
- editor.contentDocument.getSelection().selectAllChildren(editorBody);
- editor.focus();
- }
- </script>
-</head>
-<body>
-<p id="text">normal text</p>
-<div>content editable</div>
-<iframe id="editor" onload="doTest();"
- src="data:text/html,<body>editable text</body>"></iframe>
-</body>
-</html>
-
diff --git a/editor/reftests/824080-5.html b/editor/reftests/824080-5.html
deleted file mode 100644
index 30771d63f..000000000
--- a/editor/reftests/824080-5.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <script type="text/javascript">
- function doTest()
- {
- var editor1 = document.getElementById("editor1");
- editor1.focus();
- editor1.blur();
- document.getSelection().selectAllChildren(document.body);
- var editor2 = document.getElementById("editor2");
- var editorBody = editor2.contentDocument.body;
- editor2.contentDocument.getSelection().selectAllChildren(editorBody);
- editor2.focus();
- }
- </script>
-</head>
-<body>
-<p>normal text</p>
-<div id="editor1" contenteditable>content editable</div>
-<iframe id="editor2" onload="doTest();"
- src="data:text/html,<script>document.designMode='on';</script><body>editable text</body>"></iframe>
-</body>
-</html>
-
diff --git a/editor/reftests/824080-6-ref.html b/editor/reftests/824080-6-ref.html
deleted file mode 100644
index 7813c74f1..000000000
--- a/editor/reftests/824080-6-ref.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <script type="text/javascript">
- function doTest()
- {
- var editor = document.getElementById("editor");
- editor.focus();
- editor.blur();
- }
- </script>
-</head>
-<body onload="doTest()">
-<p>normal text</p>
-<textarea id="editor">textarea</textarea>
-</body>
-</html>
-
diff --git a/editor/reftests/824080-6.html b/editor/reftests/824080-6.html
deleted file mode 100644
index 54bafd680..000000000
--- a/editor/reftests/824080-6.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <script type="text/javascript">
- function doTest()
- {
- document.getSelection().selectAllChildren(document.body);
- var editor = document.getElementById("editor");
- editor.focus();
- editor.select();
- editor.blur();
- }
- </script>
-</head>
-<body onload="doTest()">
-<p>normal text</p>
-<textarea id="editor">textarea</textarea>
-</body>
-</html>
-
diff --git a/editor/reftests/824080-7-ref.html b/editor/reftests/824080-7-ref.html
deleted file mode 100644
index 10162cb1f..000000000
--- a/editor/reftests/824080-7-ref.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <script type="text/javascript">
- function doTest()
- {
- var editor = document.getElementById("editor");
- editor.focus();
- editor.selectionStart = 2;
- editor.selectionEnd = 4;
- }
- </script>
-</head>
-<body onload="doTest()">
-<p>normal text</p>
-<textarea id="editor">textarea</textarea>
-</body>
-</html>
-
diff --git a/editor/reftests/824080-7.html b/editor/reftests/824080-7.html
deleted file mode 100644
index d09e1b5ba..000000000
--- a/editor/reftests/824080-7.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <script type="text/javascript">
- function doTest()
- {
- document.getSelection().selectAllChildren(document.body);
- var editor = document.getElementById("editor");
- editor.focus();
- editor.selectionStart = 2;
- editor.selectionEnd = 4;
- editor.blur();
- editor.focus();
- }
- </script>
-</head>
-<body onload="doTest()">
-<p>normal text</p>
-<textarea id="editor">textarea</textarea>
-</body>
-</html>
-
diff --git a/editor/reftests/911201-ref.html b/editor/reftests/911201-ref.html
deleted file mode 100644
index 323613ca2..000000000
--- a/editor/reftests/911201-ref.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<!DOCTYPE html>
-<body contenteditable><div contenteditable=false>foo</div></body>
diff --git a/editor/reftests/911201.html b/editor/reftests/911201.html
deleted file mode 100644
index 6b78e1cd2..000000000
--- a/editor/reftests/911201.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<!DOCTYPE html>
-<body contenteditable onload="document.body.innerHTML='<div contenteditable=false>foo</div>';"></body>
diff --git a/editor/reftests/969773-ref.html b/editor/reftests/969773-ref.html
deleted file mode 100644
index 888ed5186..000000000
--- a/editor/reftests/969773-ref.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-<head>
- <meta charset="utf-8">
- <title>Contenteditable Selection Test Case</title>
- <script>
- function runTests() {
- var text = document.getElementById("text");
-
- text.focus();
-
- setTimeout(function () {
- document.body.offsetHeight;
- document.documentElement.removeAttribute('class');
- }, 0);
- }
- document.addEventListener('MozReftestInvalidate', runTests, false);
- </script>
-</head>
-<body>
- <div>This is a contenteditable.</div>
- <div id="text" tabindex="0">This is focusable text</div>
-</body>
-</html>
diff --git a/editor/reftests/969773.html b/editor/reftests/969773.html
deleted file mode 100644
index 1202c1555..000000000
--- a/editor/reftests/969773.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-<head>
- <meta charset="utf-8">
- <title>Contenteditable Selection Test Case</title>
- <script>
- function runTests() {
- var editable = document.getElementById("editable");
- var text = document.getElementById("text");
-
- editable.focus();
-
- setTimeout(function () {
- editable.setAttribute("contenteditable", "false");
- text.focus();
- setTimeout(function () {
- document.body.offsetHeight;
- document.documentElement.removeAttribute('class');
- }, 0);
- }, 0);
- }
- document.addEventListener('MozReftestInvalidate', runTests, false);
- </script>
-</head>
-<body>
- <div id="editable" contenteditable="true" tabindex="0" spellcheck="false">This is a contenteditable.</div>
- <div id="text" tabindex="0">This is focusable text</div>
-</body>
-</html>
diff --git a/editor/reftests/997805-ref.html b/editor/reftests/997805-ref.html
deleted file mode 100644
index be4592e69..000000000
--- a/editor/reftests/997805-ref.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<!DOCTYPE html>
-<textarea placeholder="placeholder"></textarea>
diff --git a/editor/reftests/997805.html b/editor/reftests/997805.html
deleted file mode 100644
index 91750138b..000000000
--- a/editor/reftests/997805.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-<textarea placeholder="placeholder"></textarea>
-<script>
-onload = function() {
- var t = document.querySelector("textarea");
- t.style.display = "none";
- t.value = "test";
- setTimeout(function() {
- t.style.display = "";
- t.value = "";
- document.documentElement.className = "";
- }, 0);
-};
-</script>
-</html>
diff --git a/editor/reftests/caret_after_reframe-ref.html b/editor/reftests/caret_after_reframe-ref.html
deleted file mode 100644
index 63c49f66c..000000000
--- a/editor/reftests/caret_after_reframe-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <input autofocus style="display:block">
- </body>
-</html>
diff --git a/editor/reftests/caret_after_reframe.html b/editor/reftests/caret_after_reframe.html
deleted file mode 100644
index 5e9c0f133..000000000
--- a/editor/reftests/caret_after_reframe.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
- <body>
- <input onfocus="focused()" autofocus>
- <script>
- function focused() {
- var i = document.querySelector("input");
- i.style.display = "block";
- document.offsetWidth;
- document.documentElement.removeAttribute("class");
- }
- </script>
- </body>
-</html>
diff --git a/editor/reftests/caret_on_focus-ref.html b/editor/reftests/caret_on_focus-ref.html
deleted file mode 100644
index 4282ac7f5..000000000
--- a/editor/reftests/caret_on_focus-ref.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <style>
- div { min-height: 20px; }
- </style>
- </head>
- <body onload="document.querySelector('div').focus();">
- <div contenteditable="true"></div>
- </body>
-</html>
diff --git a/editor/reftests/caret_on_focus.html b/editor/reftests/caret_on_focus.html
deleted file mode 100644
index 6dcedb4a4..000000000
--- a/editor/reftests/caret_on_focus.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <style>
- div { min-height: 20px; }
- </style>
- </head>
- <body onload="document.querySelector('div').focus();">
- <div contenteditable="true"> </div>
- </body>
-</html>
diff --git a/editor/reftests/caret_on_positioned-ref.html b/editor/reftests/caret_on_positioned-ref.html
deleted file mode 100644
index 04773979d..000000000
--- a/editor/reftests/caret_on_positioned-ref.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<html><head>
-<title>caret should be visible on stack context contents</title>
-</head><body>
-<div id="d" style="width: 100px; height: 100px; background: none repeat scroll 0% 0% cyan;" contenteditable=""></div>
-<script>
-document.getElementById("d").focus();
-</script>
-</body></html> \ No newline at end of file
diff --git a/editor/reftests/caret_on_positioned.html b/editor/reftests/caret_on_positioned.html
deleted file mode 100644
index 8a4a3c2f3..000000000
--- a/editor/reftests/caret_on_positioned.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<html><head>
-<title>caret should be visible on stack context contents</title>
-</head><body>
-<div id="d" style="position: absolute; width: 100px; height: 100px; background: none repeat scroll 0% 0% cyan;" contenteditable=""></div>
-<script>
-document.getElementById("d").focus();
-</script>
-</body></html> \ No newline at end of file
diff --git a/editor/reftests/caret_on_presshell_reinit-2.html b/editor/reftests/caret_on_presshell_reinit-2.html
deleted file mode 100644
index 5acf3c97b..000000000
--- a/editor/reftests/caret_on_presshell_reinit-2.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
- <body>
- <iframe src="data:text/html,<body><div></div></body>"></iframe>
- <script type="text/javascript">
- onload = function() {
- var i = document.querySelector("iframe");
- var win = i.contentWindow;
- var doc = win.document;
- var div = doc.querySelector("div");
- win.getSelection().collapse(div, 0);
- i.focus();
- div.contentEditable = true;
- div.focus();
- setTimeout(function() {
- var span = doc.createElement("span");
- span.appendChild(doc.createTextNode("foo"));
- div.appendChild(span);
- div.style.outlineWidth = 0; // remove the focus outline
- i.style.position = "absolute";
- document.body.clientWidth;
- document.documentElement.removeAttribute("class");
- }, 0);
- };
- </script>
- </body>
-</html>
diff --git a/editor/reftests/caret_on_presshell_reinit-ref.html b/editor/reftests/caret_on_presshell_reinit-ref.html
deleted file mode 100644
index db5b8d620..000000000
--- a/editor/reftests/caret_on_presshell_reinit-ref.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <div style="position: absolute">
- <iframe src="data:text/html,<body contenteditable>foo</body>"></iframe>
- </div>
- <script type="text/javascript">
- onload = function() {
- var iframe = document.querySelector("iframe");
- var win = iframe.contentWindow;
- var body = win.document.body;
- iframe.focus();
- body.focus();
- var sel = win.getSelection();
- sel.collapse(body.firstChild, 0);
- };
- </script>
- </body>
-</html>
diff --git a/editor/reftests/caret_on_presshell_reinit.html b/editor/reftests/caret_on_presshell_reinit.html
deleted file mode 100644
index 2d872383a..000000000
--- a/editor/reftests/caret_on_presshell_reinit.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <div>
- <iframe src="data:text/html,<body contenteditable>foo</body>"></iframe>
- </div>
- <script type="text/javascript">
- onload = function() {
- var div = document.querySelector("div");
- div.style.position = "absolute";
- document.body.clientWidth;
- var iframe = document.querySelector("iframe");
- var win = iframe.contentWindow;
- var body = win.document.body;
- iframe.focus();
- body.focus();
- var sel = win.getSelection();
- sel.collapse(body.firstChild, 0);
- };
- </script>
- </body>
-</html>
diff --git a/editor/reftests/caret_on_textarea_lastline-ref.html b/editor/reftests/caret_on_textarea_lastline-ref.html
deleted file mode 100644
index 9c1040255..000000000
--- a/editor/reftests/caret_on_textarea_lastline-ref.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="loaded()">
-<script>
- function loaded() {
- var t = document.querySelector('textarea');
- t.selectionStart = t.selectionEnd = t.value.length;
- t.focus();
- }
-</script>
-<textarea>foo</textarea>
-</body>
-</html>
diff --git a/editor/reftests/caret_on_textarea_lastline.html b/editor/reftests/caret_on_textarea_lastline.html
deleted file mode 100644
index 24a53bd7d..000000000
--- a/editor/reftests/caret_on_textarea_lastline.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="loaded()">
-<script>
- function loaded() {
- var t = document.querySelector('textarea');
- t.selectionStart = t.selectionEnd = t.value.length;
- t.focus();
- }
-</script>
-<textarea>foo
-</textarea>
-</body>
-</html>
diff --git a/editor/reftests/dynamic-1.html b/editor/reftests/dynamic-1.html
deleted file mode 100644
index 5f2b8b7dc..000000000
--- a/editor/reftests/dynamic-1.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="text">
- <script>
- document.getElementsByTagName("input")[0].value = "abcdef";
- </script>
-</body>
-</html>
diff --git a/editor/reftests/dynamic-overflow-change-ref.html b/editor/reftests/dynamic-overflow-change-ref.html
deleted file mode 100644
index 52e5f5bb0..000000000
--- a/editor/reftests/dynamic-overflow-change-ref.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea rows="2" style="overflow: hidden;">
- this
- is
- a
- textarea
- with
- overflow
- </textarea>
- </body>
-</html>
diff --git a/editor/reftests/dynamic-overflow-change.html b/editor/reftests/dynamic-overflow-change.html
deleted file mode 100644
index 57a1b8f74..000000000
--- a/editor/reftests/dynamic-overflow-change.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body onload="document.querySelector('textarea').style.overflow='hidden'">
- <textarea rows="2">
- this
- is
- a
- textarea
- with
- overflow
- </textarea>
- </body>
-</html>
diff --git a/editor/reftests/dynamic-ref.html b/editor/reftests/dynamic-ref.html
deleted file mode 100644
index 07882ee7a..000000000
--- a/editor/reftests/dynamic-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="text" value="abcdef">
-</body>
-</html>
diff --git a/editor/reftests/dynamic-type-1.html b/editor/reftests/dynamic-type-1.html
deleted file mode 100644
index fb0c3ec68..000000000
--- a/editor/reftests/dynamic-type-1.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="checkbox">
- <script>
- var i = document.getElementsByTagName("input")[0];
- i.type = "text";
- i.value = "abcdef";
- </script>
-</body>
-</html>
diff --git a/editor/reftests/dynamic-type-2.html b/editor/reftests/dynamic-type-2.html
deleted file mode 100644
index 4d99ac06e..000000000
--- a/editor/reftests/dynamic-type-2.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="checkbox">
- <script>
- var i = document.getElementsByTagName("input")[0];
- i.value = "abcdef";
- i.type = "text";
- </script>
-</body>
-</html>
diff --git a/editor/reftests/dynamic-type-3.html b/editor/reftests/dynamic-type-3.html
deleted file mode 100644
index 7cf5be6ab..000000000
--- a/editor/reftests/dynamic-type-3.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="checkbox" value="foo">
- <script>
- var i = document.getElementsByTagName("input")[0];
- i.type = "text";
- i.value = "abcdef";
- </script>
-</body>
-</html>
diff --git a/editor/reftests/dynamic-type-4.html b/editor/reftests/dynamic-type-4.html
deleted file mode 100644
index 7cf5be6ab..000000000
--- a/editor/reftests/dynamic-type-4.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="checkbox" value="foo">
- <script>
- var i = document.getElementsByTagName("input")[0];
- i.type = "text";
- i.value = "abcdef";
- </script>
-</body>
-</html>
diff --git a/editor/reftests/emptypasswd-1.html b/editor/reftests/emptypasswd-1.html
deleted file mode 100644
index 86775633b..000000000
--- a/editor/reftests/emptypasswd-1.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="password">
-</body>
-</html>
diff --git a/editor/reftests/emptypasswd-2.html b/editor/reftests/emptypasswd-2.html
deleted file mode 100644
index 6e33f46b1..000000000
--- a/editor/reftests/emptypasswd-2.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="password" value="abcdef">
- <script>
- document.getElementsByTagName("input")[0].value = "";
- </script>
-</body>
-</html>
diff --git a/editor/reftests/emptypasswd-ref.html b/editor/reftests/emptypasswd-ref.html
deleted file mode 100644
index 7f09f6e8b..000000000
--- a/editor/reftests/emptypasswd-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="text">
-</body>
-</html>
diff --git a/editor/reftests/input-text-notheme-onfocus-reframe-ref.html b/editor/reftests/input-text-notheme-onfocus-reframe-ref.html
deleted file mode 100644
index e97f55f16..000000000
--- a/editor/reftests/input-text-notheme-onfocus-reframe-ref.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE HTML>
-<html class="reftest-wait">
-<head>
- <title>bug 536421</title>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<style>
-input { border:1px solid blue; }
-</style>
-</head>
-<body onload="doTest()">
- <input value="test" id="textbox" onfocus="triggerBug();" type="text">
- <script type="text/javascript">
- function finishTest()
- {
- document.documentElement.removeAttribute("class");
- }
- function triggerBug()
- {
- finishTest();
- }
- function doTest()
- {
- var t = document.getElementById("textbox");
- t.focus();
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/input-text-notheme-onfocus-reframe.html b/editor/reftests/input-text-notheme-onfocus-reframe.html
deleted file mode 100644
index 19bc273d1..000000000
--- a/editor/reftests/input-text-notheme-onfocus-reframe.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE HTML>
-<html class="reftest-wait">
-<head>
- <title>bug 536421</title>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<style>
-input { border:1px solid blue; }
-</style>
-</head>
-<body onload="doTest()">
- <input value="test" id="textbox" onfocus="triggerBug();" type="text">
- <script type="text/javascript">
- function finishTest()
- {
- document.documentElement.removeAttribute("class");
- }
- function triggerBug()
- {
- var t = document.getElementById("textbox");
- t.style.display = "none";
- document.body.offsetWidth;
- t.style.display = "";
- finishTest();
- }
- function doTest()
- {
- var t = document.getElementById("textbox");
- t.focus();
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/input-text-onfocus-reframe-ref.html b/editor/reftests/input-text-onfocus-reframe-ref.html
deleted file mode 100644
index e17757897..000000000
--- a/editor/reftests/input-text-onfocus-reframe-ref.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE HTML>
-<html class="reftest-wait">
-<head>
- <title>bug 536421</title>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-</head>
-<body onload="doTest()">
- <input value="test" id="textbox" onfocus="triggerBug();" type="text">
- <script type="text/javascript">
- function finishTest()
- {
- document.documentElement.removeAttribute("class");
- }
- function triggerBug()
- {
- finishTest();
- }
- function doTest()
- {
- var t = document.getElementById("textbox");
- t.focus();
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/input-text-onfocus-reframe.html b/editor/reftests/input-text-onfocus-reframe.html
deleted file mode 100644
index 339ef95c6..000000000
--- a/editor/reftests/input-text-onfocus-reframe.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE HTML>
-<html class="reftest-wait">
-<head>
- <title>bug 536421</title>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-</head>
-<body onload="doTest()">
- <input value="test" id="textbox" onfocus="triggerBug();" type="text">
- <script type="text/javascript">
- function finishTest()
- {
- document.documentElement.removeAttribute("class");
- }
- function triggerBug()
- {
- var t = document.getElementById("textbox");
- t.style.display = "none";
- document.body.offsetWidth;
- t.style.display = "";
- finishTest();
- }
- function doTest()
- {
- var t = document.getElementById("textbox");
- t.focus();
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/newline-1.html b/editor/reftests/newline-1.html
deleted file mode 100644
index 5a7ce8c19..000000000
--- a/editor/reftests/newline-1.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="text" value="aaa&#10;bbb">
-</body>
-</html>
diff --git a/editor/reftests/newline-2.html b/editor/reftests/newline-2.html
deleted file mode 100644
index 7965bc860..000000000
--- a/editor/reftests/newline-2.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="text" value="&#10;aaa bbb">
-</body>
-</html>
diff --git a/editor/reftests/newline-3.html b/editor/reftests/newline-3.html
deleted file mode 100644
index 18760df4c..000000000
--- a/editor/reftests/newline-3.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="text" value="aaa bbb&#10;">
-</body>
-</html>
diff --git a/editor/reftests/newline-4.html b/editor/reftests/newline-4.html
deleted file mode 100644
index 2f51eaa20..000000000
--- a/editor/reftests/newline-4.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="text" value="a&#10;a&#10;a&#10; &#10;b&#10;b&#10;b">
-</body>
-</html>
diff --git a/editor/reftests/newline-ref.html b/editor/reftests/newline-ref.html
deleted file mode 100644
index 3630626dd..000000000
--- a/editor/reftests/newline-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="text" value="aaa bbb">
-</body>
-</html>
diff --git a/editor/reftests/nobogusnode-1.html b/editor/reftests/nobogusnode-1.html
deleted file mode 100644
index 450d6b1e5..000000000
--- a/editor/reftests/nobogusnode-1.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body contenteditable>
- This is a test.
-</body>
-</html>
diff --git a/editor/reftests/nobogusnode-2.html b/editor/reftests/nobogusnode-2.html
deleted file mode 100644
index 532e59740..000000000
--- a/editor/reftests/nobogusnode-2.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<body contenteditable="true">
- This is a test.
-</body>
-</html>
diff --git a/editor/reftests/nobogusnode-ref.html b/editor/reftests/nobogusnode-ref.html
deleted file mode 100644
index 052a53b51..000000000
--- a/editor/reftests/nobogusnode-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- This is a test.
-</body>
-</html>
diff --git a/editor/reftests/passwd-1.html b/editor/reftests/passwd-1.html
deleted file mode 100644
index f6f21d84f..000000000
--- a/editor/reftests/passwd-1.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="password" value="123456">
-</body>
-</html>
diff --git a/editor/reftests/passwd-2.html b/editor/reftests/passwd-2.html
deleted file mode 100644
index 07882ee7a..000000000
--- a/editor/reftests/passwd-2.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="text" value="abcdef">
-</body>
-</html>
diff --git a/editor/reftests/passwd-3.html b/editor/reftests/passwd-3.html
deleted file mode 100644
index 3e1e715eb..000000000
--- a/editor/reftests/passwd-3.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="password">
- <script>
- document.getElementsByTagName("input")[0].value = "abcdef";
- </script>
-</body>
-</html>
diff --git a/editor/reftests/passwd-4.html b/editor/reftests/passwd-4.html
deleted file mode 100644
index 607a22ae4..000000000
--- a/editor/reftests/passwd-4.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<!--
-Make sure that focusing a password text element does not
-cause a non-breaking space character to show up.
--->
-<html class="reftest-wait">
-<body onload="loaded()">
- <input type="password">
- <script>
- function loaded() {
- var i = document.getElementsByTagName("input")[0];
- i.focus();
- i.value += "abcdef";
- i.blur();
- document.documentElement.className = "";
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/passwd-ref.html b/editor/reftests/passwd-ref.html
deleted file mode 100644
index b203fa7d5..000000000
--- a/editor/reftests/passwd-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="password" value="abcdef">
-</body>
-</html>
diff --git a/editor/reftests/readonly-editable-ref.html b/editor/reftests/readonly-editable-ref.html
deleted file mode 100644
index 99f1e5101..000000000
--- a/editor/reftests/readonly-editable-ref.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <input>
- <input readonly>
- <input type=password>
- <input type=password readonly>
- <input type=email>
- <input type=email readonly>
- <textarea></textarea>
- <textarea readonly></textarea>
- </body>
-</html>
diff --git a/editor/reftests/readonly-editable.html b/editor/reftests/readonly-editable.html
deleted file mode 100644
index 49210e581..000000000
--- a/editor/reftests/readonly-editable.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <style>
- :-moz-read-write + span {
- display: none;
- }
- span {
- color: transparent; /* workaround for bug 617524 */
- outline: 1px solid green;
- }
- </style>
- </head>
- <body contenteditable>
- <input><span>hide me</span>
- <input readonly><span>hide me</span>
- <input type=password><span>hide me</span>
- <input type=password readonly><span>hide me</span>
- <input type=email><span>hide me</span>
- <input type=email readonly><span>hide me</span>
- <textarea></textarea><span>hide me</span>
- <textarea readonly></textarea><span>hide me</span>
- </body>
-</html>
diff --git a/editor/reftests/readonly-non-editable-ref.html b/editor/reftests/readonly-non-editable-ref.html
deleted file mode 100644
index a91071e42..000000000
--- a/editor/reftests/readonly-non-editable-ref.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <style>
- span {
- color: transparent; /* workaround for bug 617524 */
- outline: 1px solid green;
- }
- </style>
- </head>
- <body>
- <input><span>hide me</span>
- <input readonly>
- <input type=password><span>hide me</span>
- <input type=password readonly>
- <input type=email><span>hide me</span>
- <input type=email readonly>
- <textarea></textarea><span>hide me</span>
- <textarea readonly></textarea>
- </body>
-</html>
diff --git a/editor/reftests/readonly-non-editable.html b/editor/reftests/readonly-non-editable.html
deleted file mode 100644
index 9766045ed..000000000
--- a/editor/reftests/readonly-non-editable.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <style>
- :-moz-read-only + span {
- display: none;
- }
- span {
- color: transparent; /* workaround for bug 617524 */
- outline: 1px solid green;
- }
- </style>
- </head>
- <body>
- <input><span>hide me</span>
- <input readonly><span>hide me</span>
- <input type=password><span>hide me</span>
- <input type=password readonly><span>hide me</span>
- <input type=email><span>hide me</span>
- <input type=email readonly><span>hide me</span>
- <textarea></textarea><span>hide me</span>
- <textarea readonly></textarea><span>hide me</span>
- </body>
-</html>
diff --git a/editor/reftests/readwrite-editable-ref.html b/editor/reftests/readwrite-editable-ref.html
deleted file mode 100644
index 99f1e5101..000000000
--- a/editor/reftests/readwrite-editable-ref.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <input>
- <input readonly>
- <input type=password>
- <input type=password readonly>
- <input type=email>
- <input type=email readonly>
- <textarea></textarea>
- <textarea readonly></textarea>
- </body>
-</html>
diff --git a/editor/reftests/readwrite-editable.html b/editor/reftests/readwrite-editable.html
deleted file mode 100644
index 49210e581..000000000
--- a/editor/reftests/readwrite-editable.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <style>
- :-moz-read-write + span {
- display: none;
- }
- span {
- color: transparent; /* workaround for bug 617524 */
- outline: 1px solid green;
- }
- </style>
- </head>
- <body contenteditable>
- <input><span>hide me</span>
- <input readonly><span>hide me</span>
- <input type=password><span>hide me</span>
- <input type=password readonly><span>hide me</span>
- <input type=email><span>hide me</span>
- <input type=email readonly><span>hide me</span>
- <textarea></textarea><span>hide me</span>
- <textarea readonly></textarea><span>hide me</span>
- </body>
-</html>
diff --git a/editor/reftests/readwrite-non-editable-ref.html b/editor/reftests/readwrite-non-editable-ref.html
deleted file mode 100644
index 12e1c46c0..000000000
--- a/editor/reftests/readwrite-non-editable-ref.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <style>
- span {
- color: transparent; /* workaround for bug 617524 */
- outline: 1px solid green;
- }
- </style>
- </head>
- <body>
- <input>
- <input readonly><span>hide me</span>
- <input type=password>
- <input type=password readonly><span>hide me</span>
- <input type=email>
- <input type=email readonly><span>hide me</span>
- <textarea></textarea>
- <textarea readonly></textarea><span>hide me</span>
- </body>
-</html>
diff --git a/editor/reftests/readwrite-non-editable.html b/editor/reftests/readwrite-non-editable.html
deleted file mode 100644
index 535f21f1a..000000000
--- a/editor/reftests/readwrite-non-editable.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <style>
- :-moz-read-write + span {
- display: none;
- }
- span {
- color: transparent; /* workaround for bug 617524 */
- outline: 1px solid green;
- }
- </style>
- </head>
- <body>
- <input><span>hide me</span>
- <input readonly><span>hide me</span>
- <input type=password><span>hide me</span>
- <input type=password readonly><span>hide me</span>
- <input type=email><span>hide me</span>
- <input type=email readonly><span>hide me</span>
- <textarea></textarea><span>hide me</span>
- <textarea readonly></textarea><span>hide me</span>
- </body>
-</html>
diff --git a/editor/reftests/reftest-stylo.list b/editor/reftests/reftest-stylo.list
deleted file mode 100644
index ce42a4d40..000000000
--- a/editor/reftests/reftest-stylo.list
+++ /dev/null
@@ -1,177 +0,0 @@
-# DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
-# include the XUL reftests
-include xul/reftest-stylo.list
-
-== newline-1.html newline-1.html
-== newline-2.html newline-2.html
-== newline-3.html newline-3.html
-== newline-4.html newline-4.html
-== dynamic-1.html dynamic-1.html
-== dynamic-type-1.html dynamic-type-1.html
-== dynamic-type-2.html dynamic-type-2.html
-== dynamic-type-3.html dynamic-type-3.html
-== dynamic-type-4.html dynamic-type-4.html
-== passwd-1.html passwd-1.html
-== passwd-2.html passwd-2.html
-== passwd-3.html passwd-3.html
-needs-focus == passwd-4.html passwd-4.html
-== emptypasswd-1.html emptypasswd-1.html
-== emptypasswd-2.html emptypasswd-2.html
-== caret_on_positioned.html caret_on_positioned.html
-skip-if(B2G||Mulet) fails-if(Android) needs-focus == spellcheck-input-disabled.html spellcheck-input-disabled.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-== spellcheck-input-attr-before.html spellcheck-input-attr-before.html
-skip-if(B2G||Mulet) fails-if(Android) needs-focus == spellcheck-input-attr-before.html spellcheck-input-attr-before.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-== spellcheck-input-attr-after.html spellcheck-input-attr-after.html
-skip-if(B2G||Mulet) fails-if(Android) needs-focus == spellcheck-input-attr-after.html spellcheck-input-attr-after.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-== spellcheck-input-attr-inherit.html spellcheck-input-attr-inherit.html
-skip-if(B2G||Mulet) fails-if(Android) needs-focus == spellcheck-input-attr-inherit.html spellcheck-input-attr-inherit.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-== spellcheck-input-attr-dynamic.html spellcheck-input-attr-dynamic.html
-skip-if(B2G||Mulet) fails-if(Android) needs-focus == spellcheck-input-attr-dynamic.html spellcheck-input-attr-dynamic.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-== spellcheck-input-attr-dynamic-inherit.html spellcheck-input-attr-dynamic-inherit.html
-skip-if(B2G||Mulet) fails-if(Android) needs-focus == spellcheck-input-attr-dynamic-inherit.html spellcheck-input-attr-dynamic-inherit.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-== spellcheck-input-property-dynamic.html spellcheck-input-property-dynamic.html
-skip-if(B2G||Mulet) fails-if(Android) needs-focus == spellcheck-input-property-dynamic.html spellcheck-input-property-dynamic.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-== spellcheck-input-property-dynamic-inherit.html spellcheck-input-property-dynamic-inherit.html
-skip-if(B2G||Mulet) fails-if(Android) needs-focus == spellcheck-input-property-dynamic-inherit.html spellcheck-input-property-dynamic-inherit.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-== spellcheck-input-attr-dynamic-override.html spellcheck-input-attr-dynamic-override.html
-skip-if(B2G||Mulet) fails-if(Android) needs-focus == spellcheck-input-attr-dynamic-override.html spellcheck-input-attr-dynamic-override.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-== spellcheck-input-attr-dynamic-override-inherit.html spellcheck-input-attr-dynamic-override-inherit.html
-skip-if(B2G||Mulet) fails-if(Android) needs-focus == spellcheck-input-attr-dynamic-override-inherit.html spellcheck-input-attr-dynamic-override-inherit.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-== spellcheck-input-property-dynamic-override.html spellcheck-input-property-dynamic-override.html
-skip-if(B2G||Mulet) fails-if(Android) needs-focus == spellcheck-input-property-dynamic-override.html spellcheck-input-property-dynamic-override.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-== spellcheck-input-property-dynamic-override-inherit.html spellcheck-input-property-dynamic-override-inherit.html
-skip-if(B2G||Mulet) fails-if(Android) needs-focus == spellcheck-input-property-dynamic-override-inherit.html spellcheck-input-property-dynamic-override-inherit.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-== spellcheck-textarea-attr.html spellcheck-textarea-attr.html
-#the random-if(Android) tests pass on android native, but fail on android-xul, see bug 728942
-skip-if(B2G||Mulet) random-if(Android) needs-focus == spellcheck-textarea-attr.html spellcheck-textarea-attr.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-needs-focus == spellcheck-textarea-focused.html spellcheck-textarea-focused.html
-needs-focus == spellcheck-textarea-focused-reframe.html spellcheck-textarea-focused-reframe.html
-needs-focus == spellcheck-textarea-focused-notreadonly.html spellcheck-textarea-focused-notreadonly.html
-skip-if(B2G||Mulet) random-if(Android) needs-focus == spellcheck-textarea-nofocus.html spellcheck-textarea-nofocus.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(Android) needs-focus == spellcheck-textarea-disabled.html spellcheck-textarea-disabled.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(Android) needs-focus == spellcheck-textarea-attr-inherit.html spellcheck-textarea-attr-inherit.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(Android) needs-focus == spellcheck-textarea-attr-dynamic.html spellcheck-textarea-attr-dynamic.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(Android) needs-focus == spellcheck-textarea-attr-dynamic-inherit.html spellcheck-textarea-attr-dynamic-inherit.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(Android) needs-focus == spellcheck-textarea-property-dynamic.html spellcheck-textarea-property-dynamic.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(Android) needs-focus == spellcheck-textarea-property-dynamic-inherit.html spellcheck-textarea-property-dynamic-inherit.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(Android) needs-focus == spellcheck-textarea-attr-dynamic-override.html spellcheck-textarea-attr-dynamic-override.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(Android) needs-focus == spellcheck-textarea-attr-dynamic-override-inherit.html spellcheck-textarea-attr-dynamic-override-inherit.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(Android) needs-focus == spellcheck-textarea-property-dynamic-override.html spellcheck-textarea-property-dynamic-override.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(Android) needs-focus == spellcheck-textarea-property-dynamic-override-inherit.html spellcheck-textarea-property-dynamic-override-inherit.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-needs-focus == caret_on_focus.html caret_on_focus.html
-needs-focus == caret_on_textarea_lastline.html caret_on_textarea_lastline.html
-needs-focus == input-text-onfocus-reframe.html input-text-onfocus-reframe.html
-needs-focus == input-text-notheme-onfocus-reframe.html input-text-notheme-onfocus-reframe.html
-skip-if(B2G||Mulet) needs-focus == caret_after_reframe.html caret_after_reframe.html
-# B2G timed out waiting for reftest-wait to be removed
-# Initial mulet triage: parity with B2G/B2G Desktop
-== nobogusnode-1.html nobogusnode-1.html
-== nobogusnode-2.html nobogusnode-2.html
-== spellcheck-hyphen-valid.html spellcheck-hyphen-valid.html
-skip-if(B2G||Mulet) fails-if(Android) needs-focus == spellcheck-hyphen-invalid.html spellcheck-hyphen-invalid.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-== spellcheck-slash-valid.html spellcheck-slash-valid.html
-== spellcheck-period-valid.html spellcheck-period-valid.html
-== spellcheck-space-valid.html spellcheck-space-valid.html
-== spellcheck-comma-valid.html spellcheck-comma-valid.html
-== spellcheck-hyphen-multiple-valid.html spellcheck-hyphen-multiple-valid.html
-skip-if(B2G||Mulet) fails-if(Android) needs-focus == spellcheck-hyphen-multiple-invalid.html spellcheck-hyphen-multiple-invalid.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-== spellcheck-dotafterquote-valid.html spellcheck-dotafterquote-valid.html
-== spellcheck-url-valid.html spellcheck-url-valid.html
-needs-focus == spellcheck-non-latin-arabic.html spellcheck-non-latin-arabic.html
-needs-focus == spellcheck-non-latin-chinese-simplified.html spellcheck-non-latin-chinese-simplified.html
-needs-focus == spellcheck-non-latin-chinese-traditional.html spellcheck-non-latin-chinese-traditional.html
-needs-focus == spellcheck-non-latin-hebrew.html spellcheck-non-latin-hebrew.html
-needs-focus == spellcheck-non-latin-japanese.html spellcheck-non-latin-japanese.html
-needs-focus == spellcheck-non-latin-korean.html spellcheck-non-latin-korean.html
-== unneeded_scroll.html unneeded_scroll.html
-skip-if(B2G||Mulet) == caret_on_presshell_reinit.html caret_on_presshell_reinit.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-fuzzy-if(browserIsRemote,255,3) asserts-if(browserIsRemote,0-1) skip-if(B2G||Mulet) fuzzy-if(skiaContent,1,5) == caret_on_presshell_reinit-2.html caret_on_presshell_reinit-2.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,2824) == 642800.html 642800.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-== selection_visibility_after_reframe.html selection_visibility_after_reframe.html
-== selection_visibility_after_reframe-2.html selection_visibility_after_reframe-2.html
-== selection_visibility_after_reframe-3.html selection_visibility_after_reframe-3.html
-== 672709.html 672709.html
-== 338427-1.html 338427-1.html
-skip-if(Android||B2G||Mulet) needs-focus == 674212-spellcheck.html 674212-spellcheck.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(Android||B2G||Mulet) needs-focus == 338427-2.html 338427-2.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(Android||B2G||Mulet) needs-focus == 338427-3.html 338427-3.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(Android||B2G||Mulet) needs-focus == 462758-grabbers-resizers.html 462758-grabbers-resizers.html
-# Initial mulet triage: parity with B2G/B2G Desktop
-== readwrite-non-editable.html readwrite-non-editable.html
-== readwrite-editable.html readwrite-editable.html
-== readonly-non-editable.html readonly-non-editable.html
-== readonly-editable.html readonly-editable.html
-== dynamic-overflow-change.html dynamic-overflow-change.html
-== 694880-1.html 694880-1.html
-== 694880-2.html 694880-2.html
-== 694880-3.html 694880-3.html
-skip == 388980-1.html 388980-1.html
-needs-focus == spellcheck-superscript-1.html spellcheck-superscript-1.html
-skip-if(B2G||Mulet) fails-if(Android) needs-focus == spellcheck-superscript-2.html spellcheck-superscript-2.html
-# bug 783658
-# Initial mulet triage: parity with B2G/B2G Desktop
-fuzzy-if(skiaContent,1,3400) needs-focus pref(layout.accessiblecaret.enabled,false) == 824080-1.html 824080-1.html
-needs-focus pref(layout.accessiblecaret.enabled,false) == 824080-2.html 824080-2.html
-needs-focus pref(layout.accessiblecaret.enabled,false) == 824080-3.html 824080-3.html
-needs-focus == 824080-2.html 824080-2.html
-fuzzy-if(skiaContent,1,3200) needs-focus pref(layout.accessiblecaret.enabled,false) == 824080-4.html 824080-4.html
-fails fuzzy-if(skiaContent,2,1800) needs-focus pref(layout.accessiblecaret.enabled,false) == 824080-5.html 824080-5.html
-needs-focus == 824080-4.html 824080-4.html
-needs-focus == 824080-6.html 824080-6.html
-needs-focus pref(layout.accessiblecaret.enabled,false) == 824080-7.html 824080-7.html
-needs-focus == 824080-6.html 824080-6.html
-# Bug 674927: copy spellcheck-textarea tests to contenteditable
-== spellcheck-contenteditable-attr.html spellcheck-contenteditable-attr.html
-fails-if(Android||B2G||Mulet) needs-focus == spellcheck-contenteditable-attr.html spellcheck-contenteditable-attr.html
-# B2G no spellcheck underline
-# Initial mulet triage: parity with B2G/B2G Desktop
-needs-focus == spellcheck-contenteditable-focused.html spellcheck-contenteditable-focused.html
-needs-focus == spellcheck-contenteditable-focused-reframe.html spellcheck-contenteditable-focused-reframe.html
-== spellcheck-contenteditable-nofocus.html spellcheck-contenteditable-nofocus.html
-== spellcheck-contenteditable-disabled.html spellcheck-contenteditable-disabled.html
-== spellcheck-contenteditable-disabled-partial.html spellcheck-contenteditable-disabled-partial.html
-== spellcheck-contenteditable-attr-inherit.html spellcheck-contenteditable-attr-inherit.html
-== spellcheck-contenteditable-attr-dynamic.html spellcheck-contenteditable-attr-dynamic.html
-== spellcheck-contenteditable-attr-dynamic-inherit.html spellcheck-contenteditable-attr-dynamic-inherit.html
-== spellcheck-contenteditable-property-dynamic.html spellcheck-contenteditable-property-dynamic.html
-== spellcheck-contenteditable-property-dynamic-inherit.html spellcheck-contenteditable-property-dynamic-inherit.html
-== spellcheck-contenteditable-attr-dynamic-override.html spellcheck-contenteditable-attr-dynamic-override.html
-== spellcheck-contenteditable-attr-dynamic-override-inherit.html spellcheck-contenteditable-attr-dynamic-override-inherit.html
-== spellcheck-contenteditable-property-dynamic-override.html spellcheck-contenteditable-property-dynamic-override.html
-== spellcheck-contenteditable-property-dynamic-override-inherit.html spellcheck-contenteditable-property-dynamic-override-inherit.html
-== 911201.html 911201.html
-needs-focus == 969773.html 969773.html
-fails fuzzy-if(skiaContent,1,220) == 997805.html 997805.html
-fails fuzzy-if(skiaContent,1,220) == 1088158.html 1088158.html
diff --git a/editor/reftests/reftest.list b/editor/reftests/reftest.list
deleted file mode 100644
index 5664f6dc4..000000000
--- a/editor/reftests/reftest.list
+++ /dev/null
@@ -1,137 +0,0 @@
-# include the XUL reftests
-include xul/reftest.list
-
-!= newline-1.html newline-ref.html
-== newline-2.html newline-ref.html
-== newline-3.html newline-ref.html
-== newline-4.html newline-ref.html
-== dynamic-1.html dynamic-ref.html
-== dynamic-type-1.html dynamic-ref.html
-== dynamic-type-2.html dynamic-ref.html
-== dynamic-type-3.html dynamic-ref.html
-== dynamic-type-4.html dynamic-ref.html
-== passwd-1.html passwd-ref.html
-!= passwd-2.html passwd-ref.html
-== passwd-3.html passwd-ref.html
-needs-focus == passwd-4.html passwd-ref.html
-== emptypasswd-1.html emptypasswd-ref.html
-== emptypasswd-2.html emptypasswd-ref.html
-== caret_on_positioned.html caret_on_positioned-ref.html
-fails-if(Android) needs-focus != spellcheck-input-disabled.html spellcheck-input-ref.html
-== spellcheck-input-attr-before.html spellcheck-input-nofocus-ref.html
-fails-if(Android) needs-focus != spellcheck-input-attr-before.html spellcheck-input-ref.html
-== spellcheck-input-attr-after.html spellcheck-input-nofocus-ref.html
-fails-if(Android) needs-focus != spellcheck-input-attr-after.html spellcheck-input-ref.html
-== spellcheck-input-attr-inherit.html spellcheck-input-nofocus-ref.html
-fails-if(Android) needs-focus != spellcheck-input-attr-inherit.html spellcheck-input-ref.html
-== spellcheck-input-attr-dynamic.html spellcheck-input-nofocus-ref.html
-fails-if(Android) needs-focus != spellcheck-input-attr-dynamic.html spellcheck-input-ref.html
-== spellcheck-input-attr-dynamic-inherit.html spellcheck-input-nofocus-ref.html
-fails-if(Android) needs-focus != spellcheck-input-attr-dynamic-inherit.html spellcheck-input-ref.html
-== spellcheck-input-property-dynamic.html spellcheck-input-nofocus-ref.html
-fails-if(Android) needs-focus != spellcheck-input-property-dynamic.html spellcheck-input-ref.html
-== spellcheck-input-property-dynamic-inherit.html spellcheck-input-nofocus-ref.html
-fails-if(Android) needs-focus != spellcheck-input-property-dynamic-inherit.html spellcheck-input-ref.html
-== spellcheck-input-attr-dynamic-override.html spellcheck-input-nofocus-ref.html
-fails-if(Android) needs-focus != spellcheck-input-attr-dynamic-override.html spellcheck-input-ref.html
-== spellcheck-input-attr-dynamic-override-inherit.html spellcheck-input-nofocus-ref.html
-fails-if(Android) needs-focus != spellcheck-input-attr-dynamic-override-inherit.html spellcheck-input-ref.html
-== spellcheck-input-property-dynamic-override.html spellcheck-input-nofocus-ref.html
-fails-if(Android) needs-focus != spellcheck-input-property-dynamic-override.html spellcheck-input-ref.html
-== spellcheck-input-property-dynamic-override-inherit.html spellcheck-input-nofocus-ref.html
-fails-if(Android) needs-focus != spellcheck-input-property-dynamic-override-inherit.html spellcheck-input-ref.html
-== spellcheck-textarea-attr.html spellcheck-textarea-nofocus-ref.html
-#the random-if(Android) tests pass on android native, but fail on android-xul, see bug 728942
-random-if(Android) needs-focus != spellcheck-textarea-attr.html spellcheck-textarea-ref.html
-needs-focus == spellcheck-textarea-focused.html spellcheck-textarea-ref.html
-needs-focus == spellcheck-textarea-focused-reframe.html spellcheck-textarea-ref.html
-needs-focus == spellcheck-textarea-focused-notreadonly.html spellcheck-textarea-ref2.html
-random-if(Android) needs-focus != spellcheck-textarea-nofocus.html spellcheck-textarea-ref.html
-random-if(Android) needs-focus != spellcheck-textarea-disabled.html spellcheck-textarea-ref.html
-random-if(Android) needs-focus != spellcheck-textarea-attr-inherit.html spellcheck-textarea-ref.html
-random-if(Android) needs-focus != spellcheck-textarea-attr-dynamic.html spellcheck-textarea-ref.html
-random-if(Android) needs-focus != spellcheck-textarea-attr-dynamic-inherit.html spellcheck-textarea-ref.html
-random-if(Android) needs-focus != spellcheck-textarea-property-dynamic.html spellcheck-textarea-ref.html
-random-if(Android) needs-focus != spellcheck-textarea-property-dynamic-inherit.html spellcheck-textarea-ref.html
-random-if(Android) needs-focus != spellcheck-textarea-attr-dynamic-override.html spellcheck-textarea-ref.html
-random-if(Android) needs-focus != spellcheck-textarea-attr-dynamic-override-inherit.html spellcheck-textarea-ref.html
-random-if(Android) needs-focus != spellcheck-textarea-property-dynamic-override.html spellcheck-textarea-ref.html
-random-if(Android) needs-focus != spellcheck-textarea-property-dynamic-override-inherit.html spellcheck-textarea-ref.html
-needs-focus == caret_on_focus.html caret_on_focus-ref.html
-needs-focus != caret_on_textarea_lastline.html caret_on_textarea_lastline-ref.html
-needs-focus == input-text-onfocus-reframe.html input-text-onfocus-reframe-ref.html
-needs-focus == input-text-notheme-onfocus-reframe.html input-text-notheme-onfocus-reframe-ref.html
-needs-focus == caret_after_reframe.html caret_after_reframe-ref.html
-== nobogusnode-1.html nobogusnode-ref.html
-== nobogusnode-2.html nobogusnode-ref.html
-== spellcheck-hyphen-valid.html spellcheck-hyphen-valid-ref.html
-fails-if(Android) needs-focus != spellcheck-hyphen-invalid.html spellcheck-hyphen-invalid-ref.html
-== spellcheck-slash-valid.html spellcheck-slash-valid-ref.html
-== spellcheck-period-valid.html spellcheck-period-valid-ref.html
-== spellcheck-space-valid.html spellcheck-space-valid-ref.html
-== spellcheck-comma-valid.html spellcheck-comma-valid-ref.html
-== spellcheck-hyphen-multiple-valid.html spellcheck-hyphen-multiple-valid-ref.html
-fails-if(Android) needs-focus != spellcheck-hyphen-multiple-invalid.html spellcheck-hyphen-multiple-invalid-ref.html
-== spellcheck-dotafterquote-valid.html spellcheck-dotafterquote-valid-ref.html
-== spellcheck-url-valid.html spellcheck-url-valid-ref.html
-needs-focus == spellcheck-non-latin-arabic.html spellcheck-non-latin-arabic-ref.html
-needs-focus == spellcheck-non-latin-chinese-simplified.html spellcheck-non-latin-chinese-simplified-ref.html
-needs-focus == spellcheck-non-latin-chinese-traditional.html spellcheck-non-latin-chinese-traditional-ref.html
-needs-focus == spellcheck-non-latin-hebrew.html spellcheck-non-latin-hebrew-ref.html
-needs-focus == spellcheck-non-latin-japanese.html spellcheck-non-latin-japanese-ref.html
-needs-focus == spellcheck-non-latin-korean.html spellcheck-non-latin-korean-ref.html
-== unneeded_scroll.html unneeded_scroll-ref.html
-== caret_on_presshell_reinit.html caret_on_presshell_reinit-ref.html
-fuzzy-if(browserIsRemote,255,3) asserts-if(browserIsRemote,0-1) == caret_on_presshell_reinit-2.html caret_on_presshell_reinit-ref.html
-fuzzy-if(asyncPan&&!layersGPUAccelerated,102,2824) == 642800.html 642800-ref.html
-== selection_visibility_after_reframe.html selection_visibility_after_reframe-ref.html
-!= selection_visibility_after_reframe-2.html selection_visibility_after_reframe-ref.html
-!= selection_visibility_after_reframe-3.html selection_visibility_after_reframe-ref.html
-== 672709.html 672709-ref.html
-== 338427-1.html 338427-1-ref.html
-skip-if(Android) needs-focus == 674212-spellcheck.html 674212-spellcheck-ref.html
-skip-if(Android) needs-focus == 338427-2.html 338427-2-ref.html
-skip-if(Android) needs-focus == 338427-3.html 338427-3-ref.html
-skip-if(Android) needs-focus == 462758-grabbers-resizers.html 462758-grabbers-resizers-ref.html
-== readwrite-non-editable.html readwrite-non-editable-ref.html
-== readwrite-editable.html readwrite-editable-ref.html
-== readonly-non-editable.html readonly-non-editable-ref.html
-== readonly-editable.html readonly-editable-ref.html
-== dynamic-overflow-change.html dynamic-overflow-change-ref.html
-== 694880-1.html 694880-ref.html
-== 694880-2.html 694880-ref.html
-== 694880-3.html 694880-ref.html
-== 388980-1.html 388980-1-ref.html
-needs-focus == spellcheck-superscript-1.html spellcheck-superscript-1-ref.html
-fails-if(Android) needs-focus != spellcheck-superscript-2.html spellcheck-superscript-2-ref.html # bug 783658
-fuzzy-if(skiaContent,1,3400) needs-focus pref(layout.accessiblecaret.enabled,false) pref(layout.accessiblecaret.enabled_on_touch,false) == 824080-1.html 824080-1-ref.html
-fuzzy-if(OSX,1,1) needs-focus pref(layout.accessiblecaret.enabled,false) pref(layout.accessiblecaret.enabled_on_touch,false) == 824080-2.html 824080-2-ref.html #Bug 1313253
-fuzzy-if(OSX,1,1) needs-focus pref(layout.accessiblecaret.enabled,false) pref(layout.accessiblecaret.enabled_on_touch,false) == 824080-3.html 824080-3-ref.html #Bug 1312951
-needs-focus != 824080-2.html 824080-3.html
-fuzzy-if(skiaContent,1,3200) needs-focus pref(layout.accessiblecaret.enabled,false) pref(layout.accessiblecaret.enabled_on_touch,false) == 824080-4.html 824080-4-ref.html
-fuzzy-if(skiaContent,2,1800) needs-focus pref(layout.accessiblecaret.enabled,false) pref(layout.accessiblecaret.enabled_on_touch,false) == 824080-5.html 824080-5-ref.html
-needs-focus != 824080-4.html 824080-5.html
-needs-focus == 824080-6.html 824080-6-ref.html
-needs-focus pref(layout.accessiblecaret.enabled,false) pref(layout.accessiblecaret.enabled_on_touch,false) == 824080-7.html 824080-7-ref.html
-needs-focus != 824080-6.html 824080-7.html
-# Bug 674927: copy spellcheck-textarea tests to contenteditable
-== spellcheck-contenteditable-attr.html spellcheck-contenteditable-nofocus-ref.html
-fails-if(Android) needs-focus != spellcheck-contenteditable-attr.html spellcheck-contenteditable-ref.html
-needs-focus == spellcheck-contenteditable-focused.html spellcheck-contenteditable-ref.html
-needs-focus == spellcheck-contenteditable-focused-reframe.html spellcheck-contenteditable-ref.html
-== spellcheck-contenteditable-nofocus.html spellcheck-contenteditable-disabled-ref.html
-== spellcheck-contenteditable-disabled.html spellcheck-contenteditable-disabled-ref.html
-== spellcheck-contenteditable-disabled-partial.html spellcheck-contenteditable-disabled-partial-ref.html
-== spellcheck-contenteditable-attr-inherit.html spellcheck-contenteditable-disabled-ref.html
-== spellcheck-contenteditable-attr-dynamic.html spellcheck-contenteditable-disabled-ref.html
-== spellcheck-contenteditable-attr-dynamic-inherit.html spellcheck-contenteditable-disabled-ref.html
-== spellcheck-contenteditable-property-dynamic.html spellcheck-contenteditable-disabled-ref.html
-== spellcheck-contenteditable-property-dynamic-inherit.html spellcheck-contenteditable-disabled-ref.html
-== spellcheck-contenteditable-attr-dynamic-override.html spellcheck-contenteditable-disabled-ref.html
-== spellcheck-contenteditable-attr-dynamic-override-inherit.html spellcheck-contenteditable-disabled-ref.html
-== spellcheck-contenteditable-property-dynamic-override.html spellcheck-contenteditable-disabled-ref.html
-== spellcheck-contenteditable-property-dynamic-override-inherit.html spellcheck-contenteditable-disabled-ref.html
-== 911201.html 911201-ref.html
-needs-focus == 969773.html 969773-ref.html
-fuzzy-if(skiaContent,1,220) == 997805.html 997805-ref.html
-fuzzy-if(skiaContent,1,220) == 1088158.html 1088158-ref.html
diff --git a/editor/reftests/selection_visibility_after_reframe-2.html b/editor/reftests/selection_visibility_after_reframe-2.html
deleted file mode 100644
index fb705cc36..000000000
--- a/editor/reftests/selection_visibility_after_reframe-2.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <input value="foo">
- <script>
- var i = document.querySelector("input");
- i.selectionStart = 1;
- i.selectionEnd = 2;
- </script>
- </body>
-</html>
diff --git a/editor/reftests/selection_visibility_after_reframe-3.html b/editor/reftests/selection_visibility_after_reframe-3.html
deleted file mode 100644
index b05f130a1..000000000
--- a/editor/reftests/selection_visibility_after_reframe-3.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <input value="foo">
- <script>
- var i = document.querySelector("input");
- i.selectionStart = 1;
- i.selectionEnd = 2;
- i.style.display = "none";
- document.body.clientHeight;
- i.style.display = "";
- </script>
- </body>
-</html>
diff --git a/editor/reftests/selection_visibility_after_reframe-ref.html b/editor/reftests/selection_visibility_after_reframe-ref.html
deleted file mode 100644
index c227b39c8..000000000
--- a/editor/reftests/selection_visibility_after_reframe-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <input value="foo">
- </body>
-</html>
diff --git a/editor/reftests/selection_visibility_after_reframe.html b/editor/reftests/selection_visibility_after_reframe.html
deleted file mode 100644
index b72cec829..000000000
--- a/editor/reftests/selection_visibility_after_reframe.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <input value="foo">
- <script>
- var i = document.querySelector("input");
- i.selectionStart = 1;
- i.selectionEnd = 2;
- document.body.clientHeight;
- i.style.display = "none";
- document.body.clientHeight;
- i.style.display = "";
- </script>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-comma-valid-ref.html b/editor/reftests/spellcheck-comma-valid-ref.html
deleted file mode 100644
index d5856e06f..000000000
--- a/editor/reftests/spellcheck-comma-valid-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea autofocus spellcheck="false">good,nice</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-comma-valid.html b/editor/reftests/spellcheck-comma-valid.html
deleted file mode 100644
index 768cdbcf2..000000000
--- a/editor/reftests/spellcheck-comma-valid.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea autofocus>good,nice</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-contenteditable-attr-dynamic-inherit.html b/editor/reftests/spellcheck-contenteditable-attr-dynamic-inherit.html
deleted file mode 100644
index aa4e47c2c..000000000
--- a/editor/reftests/spellcheck-contenteditable-attr-dynamic-inherit.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()">
- <div contenteditable>blahblahblah</div>
- <script>
- function init() {
- document.body.setAttribute("spellcheck", "false");
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-contenteditable-attr-dynamic-override-inherit.html b/editor/reftests/spellcheck-contenteditable-attr-dynamic-override-inherit.html
deleted file mode 100644
index 1b4a0ab3b..000000000
--- a/editor/reftests/spellcheck-contenteditable-attr-dynamic-override-inherit.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()" spellcheck="true">
- <div contenteditable>blahblahblah</div>
- <script>
- function init() {
- document.body.setAttribute("spellcheck", "false");
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-contenteditable-attr-dynamic-override.html b/editor/reftests/spellcheck-contenteditable-attr-dynamic-override.html
deleted file mode 100644
index e3a4d9077..000000000
--- a/editor/reftests/spellcheck-contenteditable-attr-dynamic-override.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()">
- <div contenteditable spellcheck="true">blahblahblah</div>
- <script>
- function init() {
- document.querySelector("div").setAttribute("spellcheck", "false");
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-contenteditable-attr-dynamic.html b/editor/reftests/spellcheck-contenteditable-attr-dynamic.html
deleted file mode 100644
index 37ba9f651..000000000
--- a/editor/reftests/spellcheck-contenteditable-attr-dynamic.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()">
- <div contenteditable>blahblahblah</div>
- <script>
- function init() {
- document.querySelector("div").setAttribute("spellcheck", "false");
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-contenteditable-attr-inherit.html b/editor/reftests/spellcheck-contenteditable-attr-inherit.html
deleted file mode 100644
index 6cbfcb3da..000000000
--- a/editor/reftests/spellcheck-contenteditable-attr-inherit.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <span spellcheck="false"><div contenteditable>blahblahblah</div></span>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-contenteditable-attr.html b/editor/reftests/spellcheck-contenteditable-attr.html
deleted file mode 100644
index df119a997..000000000
--- a/editor/reftests/spellcheck-contenteditable-attr.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <div contenteditable>blahblahblah</div>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-contenteditable-disabled-partial-ref.html b/editor/reftests/spellcheck-contenteditable-disabled-partial-ref.html
deleted file mode 100644
index 30fe7a6bf..000000000
--- a/editor/reftests/spellcheck-contenteditable-disabled-partial-ref.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <span contenteditable>sakde</span> kreid <span contenteditable>slodv</span>
- <script>
- // Adding focus to the textbox should trigger a spellcheck
- document.querySelector("span").focus();
- document.querySelector("span + span").focus();
- document.querySelector("span + span").blur();
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-contenteditable-disabled-partial.html b/editor/reftests/spellcheck-contenteditable-disabled-partial.html
deleted file mode 100644
index c7b6c427c..000000000
--- a/editor/reftests/spellcheck-contenteditable-disabled-partial.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <div contenteditable>sakde <span spellcheck=false>kreid</span> slodv</div>
- <script>
- // Adding focus to the textbox should trigger a spellcheck
- document.querySelector("div").focus();
- document.querySelector("div").blur();
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-contenteditable-disabled-ref.html b/editor/reftests/spellcheck-contenteditable-disabled-ref.html
deleted file mode 100644
index 23571fa5e..000000000
--- a/editor/reftests/spellcheck-contenteditable-disabled-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <div>blahblahblah</div>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-contenteditable-disabled.html b/editor/reftests/spellcheck-contenteditable-disabled.html
deleted file mode 100644
index 3794f5767..000000000
--- a/editor/reftests/spellcheck-contenteditable-disabled.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <div contenteditable spellcheck="false">blahblahblah</div>
- <script>
- // Adding focus to the textbox should trigger a spellcheck
- document.querySelector("div").focus();
- document.querySelector("div").blur();
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-contenteditable-focused-reframe.html b/editor/reftests/spellcheck-contenteditable-focused-reframe.html
deleted file mode 100644
index 733ee05bb..000000000
--- a/editor/reftests/spellcheck-contenteditable-focused-reframe.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
-
- <div contenteditable id="testBox" onfocus="reframe(this);">blahblahblah</div>
- <script type="text/javascript">
- function reframe(textbox) {
- textbox.style.display = "none";
- textbox.style.display = "";
- textbox.clientWidth;
- }
- //Adding focus to the textbox should trigger a spellcheck
- document.getElementById("testBox").focus();
- document.getElementById("testBox").blur();
- </script>
-
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-contenteditable-focused.html b/editor/reftests/spellcheck-contenteditable-focused.html
deleted file mode 100644
index 808667399..000000000
--- a/editor/reftests/spellcheck-contenteditable-focused.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
-
- <div contenteditable id="testBox">blahblahblah</div>
- <script type="text/javascript">
- //Adding focus to the textbox should trigger a spellcheck
- document.getElementById("testBox").focus();
- document.getElementById("testBox").blur();
- </script>
-
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-contenteditable-nofocus-ref.html b/editor/reftests/spellcheck-contenteditable-nofocus-ref.html
deleted file mode 100644
index 67241fb7f..000000000
--- a/editor/reftests/spellcheck-contenteditable-nofocus-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <div contenteditable spellcheck="true">blahblahblah</div>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-contenteditable-nofocus.html b/editor/reftests/spellcheck-contenteditable-nofocus.html
deleted file mode 100644
index 7e88dc3e1..000000000
--- a/editor/reftests/spellcheck-contenteditable-nofocus.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <div contenteditable>blahblahblah</div>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-contenteditable-property-dynamic-inherit.html b/editor/reftests/spellcheck-contenteditable-property-dynamic-inherit.html
deleted file mode 100644
index feb623dbb..000000000
--- a/editor/reftests/spellcheck-contenteditable-property-dynamic-inherit.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()">
- <div contenteditable>blahblahblah</div>
- <script>
- function init() {
- document.body.spellcheck = false;
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-contenteditable-property-dynamic-override-inherit.html b/editor/reftests/spellcheck-contenteditable-property-dynamic-override-inherit.html
deleted file mode 100644
index 26c5a4223..000000000
--- a/editor/reftests/spellcheck-contenteditable-property-dynamic-override-inherit.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()" spellcheck="true">
- <div contenteditable>blahblahblah</div>
- <script>
- function init() {
- document.body.spellcheck = false;
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-contenteditable-property-dynamic-override.html b/editor/reftests/spellcheck-contenteditable-property-dynamic-override.html
deleted file mode 100644
index dd16894b8..000000000
--- a/editor/reftests/spellcheck-contenteditable-property-dynamic-override.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()">
- <div contenteditable spellcheck="true">blahblahblah</div>
- <script>
- function init() {
- document.querySelector("div").spellcheck = false;
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-contenteditable-property-dynamic.html b/editor/reftests/spellcheck-contenteditable-property-dynamic.html
deleted file mode 100644
index eaf2db29a..000000000
--- a/editor/reftests/spellcheck-contenteditable-property-dynamic.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()">
- <div contenteditable>blahblahblah</div>
- <script>
- function init() {
- document.querySelector("div").spellcheck = false;
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-contenteditable-ref.html b/editor/reftests/spellcheck-contenteditable-ref.html
deleted file mode 100644
index d28dbcf96..000000000
--- a/editor/reftests/spellcheck-contenteditable-ref.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <div contenteditable spellcheck="true">blahblahblah</div>
- <script type="text/javascript">
- var box = document.getElementsByTagName("div")[0];
- box.focus(); //Bring the textbox into focus, triggering a spellcheck
- box.blur(); //Blur in order to make things similar to other tests otherwise
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-dotafterquote-valid-ref.html b/editor/reftests/spellcheck-dotafterquote-valid-ref.html
deleted file mode 100644
index b61904400..000000000
--- a/editor/reftests/spellcheck-dotafterquote-valid-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea autofocus spellcheck="false">'Apple'.</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-dotafterquote-valid.html b/editor/reftests/spellcheck-dotafterquote-valid.html
deleted file mode 100644
index 1d3a605bb..000000000
--- a/editor/reftests/spellcheck-dotafterquote-valid.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea autofocus>'Apple'.</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-hyphen-invalid-ref.html b/editor/reftests/spellcheck-hyphen-invalid-ref.html
deleted file mode 100644
index 856fd840e..000000000
--- a/editor/reftests/spellcheck-hyphen-invalid-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea autofocus spellcheck="false">dddf-gggy</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-hyphen-invalid.html b/editor/reftests/spellcheck-hyphen-invalid.html
deleted file mode 100644
index bc4e4e240..000000000
--- a/editor/reftests/spellcheck-hyphen-invalid.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea autofocus>dddf-gggy</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-hyphen-multiple-invalid-ref.html b/editor/reftests/spellcheck-hyphen-multiple-invalid-ref.html
deleted file mode 100644
index ab4cbd05a..000000000
--- a/editor/reftests/spellcheck-hyphen-multiple-invalid-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea style="width: 400px; height: 200px;" autofocus spellcheck="false">-hlloe hlloe- --hlloe --hlloe ---hlloe hlloe--- ---hlloe----</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-hyphen-multiple-invalid.html b/editor/reftests/spellcheck-hyphen-multiple-invalid.html
deleted file mode 100644
index bcc3f7113..000000000
--- a/editor/reftests/spellcheck-hyphen-multiple-invalid.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea style="width: 400px; height: 200px;" autofocus>-hlloe hlloe- --hlloe --hlloe ---hlloe hlloe--- ---hlloe----</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-hyphen-multiple-valid-ref.html b/editor/reftests/spellcheck-hyphen-multiple-valid-ref.html
deleted file mode 100644
index 324a566c4..000000000
--- a/editor/reftests/spellcheck-hyphen-multiple-valid-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea style="width: 400px; height: 200px;" autofocus spellcheck="false">- -- --- -hello hello- --hello --hello ---hello hello--- ---hello----</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-hyphen-multiple-valid.html b/editor/reftests/spellcheck-hyphen-multiple-valid.html
deleted file mode 100644
index 7f0ce681c..000000000
--- a/editor/reftests/spellcheck-hyphen-multiple-valid.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea style="width: 400px; height: 200px;" autofocus>- -- --- -hello hello- --hello --hello ---hello hello--- ---hello----</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-hyphen-valid-ref.html b/editor/reftests/spellcheck-hyphen-valid-ref.html
deleted file mode 100644
index 73b507a3d..000000000
--- a/editor/reftests/spellcheck-hyphen-valid-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea autofocus spellcheck="false">scot-free</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-hyphen-valid.html b/editor/reftests/spellcheck-hyphen-valid.html
deleted file mode 100644
index 2b56a6e24..000000000
--- a/editor/reftests/spellcheck-hyphen-valid.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea autofocus>scot-free</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-input-attr-after.html b/editor/reftests/spellcheck-input-attr-after.html
deleted file mode 100644
index 1e878b5d1..000000000
--- a/editor/reftests/spellcheck-input-attr-after.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="text" value="blahblahblah" spellcheck="true">
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-input-attr-before.html b/editor/reftests/spellcheck-input-attr-before.html
deleted file mode 100644
index 8456e6c8c..000000000
--- a/editor/reftests/spellcheck-input-attr-before.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="text" spellcheck="true" value="blahblahblah">
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-input-attr-dynamic-inherit.html b/editor/reftests/spellcheck-input-attr-dynamic-inherit.html
deleted file mode 100644
index c87be7c3e..000000000
--- a/editor/reftests/spellcheck-input-attr-dynamic-inherit.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()">
- <input class="spell-checked" type="text" value="blahblahblah">
- <script>
- function init() {
- document.body.setAttribute("spellcheck", "true");
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-input-attr-dynamic-override-inherit.html b/editor/reftests/spellcheck-input-attr-dynamic-override-inherit.html
deleted file mode 100644
index d7d12b78d..000000000
--- a/editor/reftests/spellcheck-input-attr-dynamic-override-inherit.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()" spellcheck="false">
- <input class="spell-checked" type="text" value="blahblahblah">
- <script>
- function init() {
- document.body.setAttribute("spellcheck", "true");
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-input-attr-dynamic-override.html b/editor/reftests/spellcheck-input-attr-dynamic-override.html
deleted file mode 100644
index 0f6095bd0..000000000
--- a/editor/reftests/spellcheck-input-attr-dynamic-override.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()">
- <input class="spell-checked" type="text" spellcheck="false" value="blahblahblah">
- <script>
- function init() {
- document.querySelector("input").setAttribute("spellcheck", "true");
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-input-attr-dynamic.html b/editor/reftests/spellcheck-input-attr-dynamic.html
deleted file mode 100644
index 27c8281fa..000000000
--- a/editor/reftests/spellcheck-input-attr-dynamic.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()">
- <input class="spell-checked" type="text" value="blahblahblah">
- <script>
- function init() {
- document.querySelector("input").setAttribute("spellcheck", "true");
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-input-attr-inherit.html b/editor/reftests/spellcheck-input-attr-inherit.html
deleted file mode 100644
index c851bd189..000000000
--- a/editor/reftests/spellcheck-input-attr-inherit.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <span spellcheck="true"><input class="spell-checked" type="text" value="blahblahblah"></span>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-input-disabled.html b/editor/reftests/spellcheck-input-disabled.html
deleted file mode 100644
index f3b2f2ba9..000000000
--- a/editor/reftests/spellcheck-input-disabled.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="text" value="blahblahblah">
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-input-nofocus-ref.html b/editor/reftests/spellcheck-input-nofocus-ref.html
deleted file mode 100644
index 1e878b5d1..000000000
--- a/editor/reftests/spellcheck-input-nofocus-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="text" value="blahblahblah" spellcheck="true">
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-input-property-dynamic-inherit.html b/editor/reftests/spellcheck-input-property-dynamic-inherit.html
deleted file mode 100644
index 1cf839bae..000000000
--- a/editor/reftests/spellcheck-input-property-dynamic-inherit.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()">
- <input class="spell-checked" type="text" value="blahblahblah">
- <script>
- function init() {
- document.body.spellcheck = true;
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-input-property-dynamic-override-inherit.html b/editor/reftests/spellcheck-input-property-dynamic-override-inherit.html
deleted file mode 100644
index eb380dc96..000000000
--- a/editor/reftests/spellcheck-input-property-dynamic-override-inherit.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()" spellcheck="false">
- <input class="spell-checked" type="text" value="blahblahblah">
- <script>
- function init() {
- document.body.spellcheck = true;
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-input-property-dynamic-override.html b/editor/reftests/spellcheck-input-property-dynamic-override.html
deleted file mode 100644
index fad2fb3ed..000000000
--- a/editor/reftests/spellcheck-input-property-dynamic-override.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()">
- <input class="spell-checked" type="text" spellcheck="false" value="blahblahblah">
- <script>
- function init() {
- document.querySelector("input").spellcheck = true;
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-input-property-dynamic.html b/editor/reftests/spellcheck-input-property-dynamic.html
deleted file mode 100644
index dd59ec6ea..000000000
--- a/editor/reftests/spellcheck-input-property-dynamic.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()">
- <input class="spell-checked" type="text" value="blahblahblah">
- <script>
- function init() {
- document.querySelector("input").spellcheck = true;
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-input-ref.html b/editor/reftests/spellcheck-input-ref.html
deleted file mode 100644
index 8dde5e6f1..000000000
--- a/editor/reftests/spellcheck-input-ref.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <input type="text" value="blahblahblah" spellcheck="true">
- <script>
- var i = document.getElementsByTagName("input")[0];
- i.focus(); // init the editor
- i.blur(); // we actually don't need the focus
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-non-latin-arabic-ref.html b/editor/reftests/spellcheck-non-latin-arabic-ref.html
deleted file mode 100644
index 67850b46c..000000000
--- a/editor/reftests/spellcheck-non-latin-arabic-ref.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <meta charset="utf-8">
- </head>
- <body>
- <textarea autofocus spellcheck="false">سلام</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-non-latin-arabic.html b/editor/reftests/spellcheck-non-latin-arabic.html
deleted file mode 100644
index fbbe19388..000000000
--- a/editor/reftests/spellcheck-non-latin-arabic.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <meta charset="utf-8">
- </head>
- <body>
- <textarea autofocus>سلام</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-non-latin-chinese-simplified-ref.html b/editor/reftests/spellcheck-non-latin-chinese-simplified-ref.html
deleted file mode 100644
index 83ad79c26..000000000
--- a/editor/reftests/spellcheck-non-latin-chinese-simplified-ref.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <meta charset="utf-8">
- </head>
- <body>
- <textarea autofocus spellcheck="false">你好</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-non-latin-chinese-simplified.html b/editor/reftests/spellcheck-non-latin-chinese-simplified.html
deleted file mode 100644
index 8db16489a..000000000
--- a/editor/reftests/spellcheck-non-latin-chinese-simplified.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <meta charset="utf-8">
- </head>
- <body>
- <textarea autofocus>你好</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-non-latin-chinese-traditional-ref.html b/editor/reftests/spellcheck-non-latin-chinese-traditional-ref.html
deleted file mode 100644
index 83ad79c26..000000000
--- a/editor/reftests/spellcheck-non-latin-chinese-traditional-ref.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <meta charset="utf-8">
- </head>
- <body>
- <textarea autofocus spellcheck="false">你好</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-non-latin-chinese-traditional.html b/editor/reftests/spellcheck-non-latin-chinese-traditional.html
deleted file mode 100644
index 8db16489a..000000000
--- a/editor/reftests/spellcheck-non-latin-chinese-traditional.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <meta charset="utf-8">
- </head>
- <body>
- <textarea autofocus>你好</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-non-latin-hebrew-ref.html b/editor/reftests/spellcheck-non-latin-hebrew-ref.html
deleted file mode 100644
index e2bd7c6d2..000000000
--- a/editor/reftests/spellcheck-non-latin-hebrew-ref.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <meta charset="utf-8">
- </head>
- <body>
- <textarea autofocus spellcheck="false">שלום</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-non-latin-hebrew.html b/editor/reftests/spellcheck-non-latin-hebrew.html
deleted file mode 100644
index 9372c4e9a..000000000
--- a/editor/reftests/spellcheck-non-latin-hebrew.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <meta charset="utf-8">
- </head>
- <body>
- <textarea autofocus>שלום</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-non-latin-japanese-ref.html b/editor/reftests/spellcheck-non-latin-japanese-ref.html
deleted file mode 100644
index a978cd3ce..000000000
--- a/editor/reftests/spellcheck-non-latin-japanese-ref.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <meta charset="utf-8">
- </head>
- <body>
- <textarea autofocus spellcheck="false">こんにちは</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-non-latin-japanese.html b/editor/reftests/spellcheck-non-latin-japanese.html
deleted file mode 100644
index d79bb0e5e..000000000
--- a/editor/reftests/spellcheck-non-latin-japanese.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <meta charset="utf-8">
- </head>
- <body>
- <textarea autofocus>こんにちは</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-non-latin-korean-ref.html b/editor/reftests/spellcheck-non-latin-korean-ref.html
deleted file mode 100644
index 53d1909f3..000000000
--- a/editor/reftests/spellcheck-non-latin-korean-ref.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <meta charset="utf-8">
- </head>
- <body>
- <textarea autofocus spellcheck="false">안녕하세요</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-non-latin-korean.html b/editor/reftests/spellcheck-non-latin-korean.html
deleted file mode 100644
index f0f65e82e..000000000
--- a/editor/reftests/spellcheck-non-latin-korean.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <meta charset="utf-8">
- </head>
- <body>
- <textarea autofocus>안녕하세요</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-period-valid-ref.html b/editor/reftests/spellcheck-period-valid-ref.html
deleted file mode 100644
index 5ee87992b..000000000
--- a/editor/reftests/spellcheck-period-valid-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea autofocus spellcheck="false">good.nice</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-period-valid.html b/editor/reftests/spellcheck-period-valid.html
deleted file mode 100644
index aaa5aa468..000000000
--- a/editor/reftests/spellcheck-period-valid.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea autofocus>good.nice</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-slash-valid-ref.html b/editor/reftests/spellcheck-slash-valid-ref.html
deleted file mode 100644
index fddc03252..000000000
--- a/editor/reftests/spellcheck-slash-valid-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea autofocus spellcheck="false">good/nice</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-slash-valid.html b/editor/reftests/spellcheck-slash-valid.html
deleted file mode 100644
index 37e8d1bf4..000000000
--- a/editor/reftests/spellcheck-slash-valid.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea autofocus>good/nice</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-space-valid-ref.html b/editor/reftests/spellcheck-space-valid-ref.html
deleted file mode 100644
index 9fea33e96..000000000
--- a/editor/reftests/spellcheck-space-valid-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea autofocus spellcheck="false">good nice</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-space-valid.html b/editor/reftests/spellcheck-space-valid.html
deleted file mode 100644
index 575426d47..000000000
--- a/editor/reftests/spellcheck-space-valid.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea autofocus>good nice</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-superscript-1-ref.html b/editor/reftests/spellcheck-superscript-1-ref.html
deleted file mode 100644
index 35df20d70..000000000
--- a/editor/reftests/spellcheck-superscript-1-ref.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<!doctype html>
-<textarea spellcheck=false>&sup1; &sup2; &sup3;</textarea>
-<script>document.body.firstChild.focus()</script>
diff --git a/editor/reftests/spellcheck-superscript-1.html b/editor/reftests/spellcheck-superscript-1.html
deleted file mode 100644
index b7b317295..000000000
--- a/editor/reftests/spellcheck-superscript-1.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<!doctype html>
-<textarea>&sup1; &sup2; &sup3;</textarea>
-<script>document.body.firstChild.focus()</script>
diff --git a/editor/reftests/spellcheck-superscript-2-ref.html b/editor/reftests/spellcheck-superscript-2-ref.html
deleted file mode 100644
index 19276bd71..000000000
--- a/editor/reftests/spellcheck-superscript-2-ref.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<!doctype html>
-<textarea>&sup1; &sup2; &sup3; mispeled</textarea>
-<script>document.body.firstChild.focus()</script>
diff --git a/editor/reftests/spellcheck-superscript-2.html b/editor/reftests/spellcheck-superscript-2.html
deleted file mode 100644
index 350d2bc8c..000000000
--- a/editor/reftests/spellcheck-superscript-2.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<!doctype html>
-<textarea spellcheck=false>&sup1; &sup2; &sup3; mispeled</textarea>
-<script>document.body.firstChild.focus()</script>
diff --git a/editor/reftests/spellcheck-textarea-attr-dynamic-inherit.html b/editor/reftests/spellcheck-textarea-attr-dynamic-inherit.html
deleted file mode 100644
index a4a938494..000000000
--- a/editor/reftests/spellcheck-textarea-attr-dynamic-inherit.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()">
- <textarea>blahblahblah</textarea>
- <script>
- function init() {
- document.body.setAttribute("spellcheck", "false");
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-textarea-attr-dynamic-override-inherit.html b/editor/reftests/spellcheck-textarea-attr-dynamic-override-inherit.html
deleted file mode 100644
index a6ae716b5..000000000
--- a/editor/reftests/spellcheck-textarea-attr-dynamic-override-inherit.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()" spellcheck="true">
- <textarea>blahblahblah</textarea>
- <script>
- function init() {
- document.body.setAttribute("spellcheck", "false");
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-textarea-attr-dynamic-override.html b/editor/reftests/spellcheck-textarea-attr-dynamic-override.html
deleted file mode 100644
index 96e956608..000000000
--- a/editor/reftests/spellcheck-textarea-attr-dynamic-override.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()">
- <textarea spellcheck="true">blahblahblah</textarea>
- <script>
- function init() {
- document.querySelector("textarea").setAttribute("spellcheck", "false");
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-textarea-attr-dynamic.html b/editor/reftests/spellcheck-textarea-attr-dynamic.html
deleted file mode 100644
index 745e66c7c..000000000
--- a/editor/reftests/spellcheck-textarea-attr-dynamic.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()">
- <textarea>blahblahblah</textarea>
- <script>
- function init() {
- document.querySelector("textarea").setAttribute("spellcheck", "false");
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-textarea-attr-inherit.html b/editor/reftests/spellcheck-textarea-attr-inherit.html
deleted file mode 100644
index c261fec5a..000000000
--- a/editor/reftests/spellcheck-textarea-attr-inherit.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <span spellcheck="false"><textarea>blahblahblah</textarea></span>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-textarea-attr.html b/editor/reftests/spellcheck-textarea-attr.html
deleted file mode 100644
index 223f948dc..000000000
--- a/editor/reftests/spellcheck-textarea-attr.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <textarea>blahblahblah</textarea>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-textarea-disabled.html b/editor/reftests/spellcheck-textarea-disabled.html
deleted file mode 100644
index cfaf3ed53..000000000
--- a/editor/reftests/spellcheck-textarea-disabled.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <textarea spellcheck="false">blahblahblah</textarea>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-textarea-focused-notreadonly.html b/editor/reftests/spellcheck-textarea-focused-notreadonly.html
deleted file mode 100644
index 475ae6002..000000000
--- a/editor/reftests/spellcheck-textarea-focused-notreadonly.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
-
- <textarea id="testBox" style="padding:2px;" readonly></textarea>
- <script type="text/javascript">
- //Adding focus to the textbox should trigger a spellcheck
- var textbox = document.getElementById("testBox");
- addEventListener("load", function() {
- textbox.readOnly = false;
- textbox.focus();
- textbox.value = "blahblahblah";
- textbox.selectionStart = textbox.selectionEnd = 0;
- textbox.blur();
- }, false);
- </script>
-
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-textarea-focused-reframe.html b/editor/reftests/spellcheck-textarea-focused-reframe.html
deleted file mode 100644
index 6e6f871dd..000000000
--- a/editor/reftests/spellcheck-textarea-focused-reframe.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
-
- <textarea id="testBox" onfocus="reframe(this);">blahblahblah</textarea>
- <script type="text/javascript">
- function reframe(textbox) {
- textbox.style.display = "none";
- textbox.style.display = "";
- textbox.clientWidth;
- }
- //Adding focus to the textbox should trigger a spellcheck
- document.getElementById("testBox").focus();
- document.getElementById("testBox").blur();
- </script>
-
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-textarea-focused.html b/editor/reftests/spellcheck-textarea-focused.html
deleted file mode 100644
index 04d689cc1..000000000
--- a/editor/reftests/spellcheck-textarea-focused.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
-
- <textarea id="testBox">blahblahblah</textarea>
- <script type="text/javascript">
- //Adding focus to the textbox should trigger a spellcheck
- document.getElementById("testBox").focus();
- document.getElementById("testBox").blur();
- </script>
-
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-textarea-nofocus-ref.html b/editor/reftests/spellcheck-textarea-nofocus-ref.html
deleted file mode 100644
index 8d993983e..000000000
--- a/editor/reftests/spellcheck-textarea-nofocus-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <textarea spellcheck="true">blahblahblah</textarea>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-textarea-nofocus.html b/editor/reftests/spellcheck-textarea-nofocus.html
deleted file mode 100644
index a1ce1a0a9..000000000
--- a/editor/reftests/spellcheck-textarea-nofocus.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <textarea>blahblahblah</textarea>
-</body>
-</html> \ No newline at end of file
diff --git a/editor/reftests/spellcheck-textarea-property-dynamic-inherit.html b/editor/reftests/spellcheck-textarea-property-dynamic-inherit.html
deleted file mode 100644
index 125f578bf..000000000
--- a/editor/reftests/spellcheck-textarea-property-dynamic-inherit.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()">
- <textarea>blahblahblah</textarea>
- <script>
- function init() {
- document.body.spellcheck = false;
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-textarea-property-dynamic-override-inherit.html b/editor/reftests/spellcheck-textarea-property-dynamic-override-inherit.html
deleted file mode 100644
index 0e773646e..000000000
--- a/editor/reftests/spellcheck-textarea-property-dynamic-override-inherit.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()" spellcheck="true">
- <textarea>blahblahblah</textarea>
- <script>
- function init() {
- document.body.spellcheck = false;
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-textarea-property-dynamic-override.html b/editor/reftests/spellcheck-textarea-property-dynamic-override.html
deleted file mode 100644
index f929d3bec..000000000
--- a/editor/reftests/spellcheck-textarea-property-dynamic-override.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()">
- <textarea spellcheck="true">blahblahblah</textarea>
- <script>
- function init() {
- document.querySelector("textarea").spellcheck = false;
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-textarea-property-dynamic.html b/editor/reftests/spellcheck-textarea-property-dynamic.html
deleted file mode 100644
index d0c94f68e..000000000
--- a/editor/reftests/spellcheck-textarea-property-dynamic.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body onload="init()">
- <textarea>blahblahblah</textarea>
- <script>
- function init() {
- document.querySelector("textarea").spellcheck = false;
- }
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-textarea-ref.html b/editor/reftests/spellcheck-textarea-ref.html
deleted file mode 100644
index 91ecd1d8e..000000000
--- a/editor/reftests/spellcheck-textarea-ref.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <textarea spellcheck="true">blahblahblah</textarea>
- <script type="text/javascript">
- var box = document.getElementsByTagName("textarea")[0];
- box.focus(); //Bring the textbox into focus, triggering a spellcheck
- box.blur(); //Blur in order to make things similar to other tests otherwise
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-textarea-ref2.html b/editor/reftests/spellcheck-textarea-ref2.html
deleted file mode 100644
index 6bd588a23..000000000
--- a/editor/reftests/spellcheck-textarea-ref2.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
- <textarea spellcheck="true" style="padding:2px;">blahblahblah</textarea>
- <script type="text/javascript">
- var box = document.getElementsByTagName("textarea")[0];
- box.focus(); //Bring the textbox into focus, triggering a spellcheck
- box.blur(); //Blur in order to make things similar to other tests otherwise
- </script>
-</body>
-</html>
diff --git a/editor/reftests/spellcheck-url-valid-ref.html b/editor/reftests/spellcheck-url-valid-ref.html
deleted file mode 100644
index 7f9f7530d..000000000
--- a/editor/reftests/spellcheck-url-valid-ref.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea autofocus rows=10 cols=60 spellcheck=false>
-http://fooi.barj/bazk
-https://fooi.barj/bazk
-news://fooi.barj/bazk
-ftp://fooi.barj/bazk
-data:fooi/barj,bazk
-javascript:fooi.barj.bazk();
-fooi@barj.bazk
-</textarea>
- </body>
-</html>
diff --git a/editor/reftests/spellcheck-url-valid.html b/editor/reftests/spellcheck-url-valid.html
deleted file mode 100644
index f492560a2..000000000
--- a/editor/reftests/spellcheck-url-valid.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <textarea autofocus rows=10 cols=60>
-http://fooi.barj/bazk
-https://fooi.barj/bazk
-news://fooi.barj/bazk
-ftp://fooi.barj/bazk
-data:fooi/barj,bazk
-javascript:fooi.barj.bazk();
-fooi@barj.bazk
-</textarea>
- </body>
-</html>
diff --git a/editor/reftests/unneeded_scroll-ref.html b/editor/reftests/unneeded_scroll-ref.html
deleted file mode 100644
index 9d6ec25bb..000000000
--- a/editor/reftests/unneeded_scroll-ref.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <div>
- <textarea>I
- am
- a
- long
- long
- long
- long
- textarea
- </textarea>
- </div>
- </body>
-</html>
diff --git a/editor/reftests/unneeded_scroll.html b/editor/reftests/unneeded_scroll.html
deleted file mode 100644
index 6d9eba355..000000000
--- a/editor/reftests/unneeded_scroll.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<html>
- <body>
- <script>
- document.addEventListener("DOMContentLoaded", function() {
- var t = document.querySelector("textarea");
- t.focus();
- document.querySelector("#dst").appendChild(t);
- }, false);
- </script>
- <div>
- <textarea>I
- am
- a
- long
- long
- long
- long
- textarea
- </textarea>
- </div>
- <div id="dst"></div>
- </body>
-</html>
diff --git a/editor/reftests/xul/autocomplete-1.xul b/editor/reftests/xul/autocomplete-1.xul
deleted file mode 100644
index 4ba8edb8c..000000000
--- a/editor/reftests/xul/autocomplete-1.xul
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <!-- leading space in the value to ensure no pixels of t get clipped
- in one rendering but not the other -->
- <textbox type="autocomplete" value=" test"/>
-
-</window>
diff --git a/editor/reftests/xul/autocomplete-ref.xul b/editor/reftests/xul/autocomplete-ref.xul
deleted file mode 100644
index 829948964..000000000
--- a/editor/reftests/xul/autocomplete-ref.xul
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="input.css" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <html:input class="ac" value=" test"/>
-
-</window>
diff --git a/editor/reftests/xul/empty-1.xul b/editor/reftests/xul/empty-1.xul
deleted file mode 100644
index cb0bd576b..000000000
--- a/editor/reftests/xul/empty-1.xul
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="placeholder-reset.css" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox placeholder=" test"/>
-
-</window>
diff --git a/editor/reftests/xul/empty-2.xul b/editor/reftests/xul/empty-2.xul
deleted file mode 100644
index e7f59fa6e..000000000
--- a/editor/reftests/xul/empty-2.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox placeholder=" test" value="value"/>
-
-</window>
diff --git a/editor/reftests/xul/empty-ref.xul b/editor/reftests/xul/empty-ref.xul
deleted file mode 100644
index 6caf215ed..000000000
--- a/editor/reftests/xul/empty-ref.xul
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="input.css" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <html:input class="empty" value=" test"/>
-
-</window>
diff --git a/editor/reftests/xul/emptyautocomplete-1.xul b/editor/reftests/xul/emptyautocomplete-1.xul
deleted file mode 100644
index ddbd50512..000000000
--- a/editor/reftests/xul/emptyautocomplete-1.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox type="autocomplete"/>
-
-</window>
diff --git a/editor/reftests/xul/emptyautocomplete-ref.xul b/editor/reftests/xul/emptyautocomplete-ref.xul
deleted file mode 100644
index abe557fdb..000000000
--- a/editor/reftests/xul/emptyautocomplete-ref.xul
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="input.css" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <html:input class="ac"/>
-
-</window>
diff --git a/editor/reftests/xul/emptymultiline-1.xul b/editor/reftests/xul/emptymultiline-1.xul
deleted file mode 100644
index dbe72be3d..000000000
--- a/editor/reftests/xul/emptymultiline-1.xul
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="input.css" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox multiline="true"/>
-
-</window>
diff --git a/editor/reftests/xul/emptymultiline-2.xul b/editor/reftests/xul/emptymultiline-2.xul
deleted file mode 100644
index c43d432ad..000000000
--- a/editor/reftests/xul/emptymultiline-2.xul
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="input.css" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox multiline="true" rows="10"/>
-
-</window>
diff --git a/editor/reftests/xul/emptymultiline-ref.xul b/editor/reftests/xul/emptymultiline-ref.xul
deleted file mode 100644
index ef79718dd..000000000
--- a/editor/reftests/xul/emptymultiline-ref.xul
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="input.css" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <html:textarea rows="10" style="resize: none;"/>
-
-</window>
diff --git a/editor/reftests/xul/emptytextbox-1.xul b/editor/reftests/xul/emptytextbox-1.xul
deleted file mode 100644
index aba191a94..000000000
--- a/editor/reftests/xul/emptytextbox-1.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox/>
-
-</window>
diff --git a/editor/reftests/xul/emptytextbox-2.xul b/editor/reftests/xul/emptytextbox-2.xul
deleted file mode 100644
index 973e89882..000000000
--- a/editor/reftests/xul/emptytextbox-2.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox type="password"/>
-
-</window>
diff --git a/editor/reftests/xul/emptytextbox-3.xul b/editor/reftests/xul/emptytextbox-3.xul
deleted file mode 100644
index a37ce6429..000000000
--- a/editor/reftests/xul/emptytextbox-3.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox type="number"/>
-
-</window>
diff --git a/editor/reftests/xul/emptytextbox-4.xul b/editor/reftests/xul/emptytextbox-4.xul
deleted file mode 100644
index 979cd118e..000000000
--- a/editor/reftests/xul/emptytextbox-4.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox type="search"/>
-
-</window>
diff --git a/editor/reftests/xul/emptytextbox-5.xul b/editor/reftests/xul/emptytextbox-5.xul
deleted file mode 100644
index 6c8c27971..000000000
--- a/editor/reftests/xul/emptytextbox-5.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox type="timed"/>
-
-</window>
diff --git a/editor/reftests/xul/emptytextbox-ref.xul b/editor/reftests/xul/emptytextbox-ref.xul
deleted file mode 100644
index 58089ca6d..000000000
--- a/editor/reftests/xul/emptytextbox-ref.xul
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="input.css" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <html:input/>
-
-</window>
diff --git a/editor/reftests/xul/input.css b/editor/reftests/xul/input.css
deleted file mode 100644
index 2104b16d2..000000000
--- a/editor/reftests/xul/input.css
+++ /dev/null
@@ -1,70 +0,0 @@
-@namespace url('http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul');
-@namespace html url('http://www.w3.org/1999/xhtml');
-
-#mac html|input, #mac html|textarea {
- margin: 4px;
- padding: 0 1px;
-}
-
-#win html|input, #win html|textarea {
- margin: 2px 4px;
- padding: 2px 3px 3px;
- padding-inline-start: 5px;
-}
-
-#win html|input:-moz-system-metric(windows-default-theme) {
- padding: 1px 2px 2px;
- padding-inline-start: 4px;
-}
-
-#linux html|input, #linux html|textarea {
- margin: 2px 4px;
- padding: 2px 5px 3px;
-}
-
-textbox[multiline="true"], html|textarea {
- border: none !important;
- -moz-appearance: none !important;
- background-color: white !important;
- border-top-right-radius: 0;
- border-bottom-left-radius: 0;
-}
-
-html|input, html|textarea {
- font: inherit;
-}
-
-html|input.ac {
- padding: 0 4px !important;
-}
-
-html|input.empty {
- color: graytext;
-}
-
-:root:not(.winxp) html|input.empty:-moz-system-metric(windows-default-theme) {
- font-style: italic;
-}
-
-html|input.num {
- text-align: end;
-}
-
-#mac html|input.num {
- margin-inline-end: 8px;
-}
-
-#win html|input.num {
- padding: 0 !important;
-}
-
-#linux html|input.num {
- margin-inline-end: 3px;
- padding: 3px 4px;
-}
-
-html|div.plainfield {
- color: -moz-fieldtext;
- white-space: pre;
-}
-
diff --git a/editor/reftests/xul/number-1.xul b/editor/reftests/xul/number-1.xul
deleted file mode 100644
index a37ce6429..000000000
--- a/editor/reftests/xul/number-1.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox type="number"/>
-
-</window>
diff --git a/editor/reftests/xul/number-2.xul b/editor/reftests/xul/number-2.xul
deleted file mode 100644
index 73d2e84a0..000000000
--- a/editor/reftests/xul/number-2.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox type="number" hidespinbuttons="false"/>
-
-</window>
diff --git a/editor/reftests/xul/number-3.xul b/editor/reftests/xul/number-3.xul
deleted file mode 100644
index 8ddadcf63..000000000
--- a/editor/reftests/xul/number-3.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox type="number" hidespinbuttons="true"/>
-
-</window>
diff --git a/editor/reftests/xul/number-4.xul b/editor/reftests/xul/number-4.xul
deleted file mode 100644
index 40650e8e4..000000000
--- a/editor/reftests/xul/number-4.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox type="number" value="1" hidespinbuttons="true"/>
-
-</window>
diff --git a/editor/reftests/xul/number-5.xul b/editor/reftests/xul/number-5.xul
deleted file mode 100644
index bd6346fe5..000000000
--- a/editor/reftests/xul/number-5.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox type="number" value="test" hidespinbuttons="true"/>
-
-</window>
diff --git a/editor/reftests/xul/number-ref.xul b/editor/reftests/xul/number-ref.xul
deleted file mode 100644
index abff29d97..000000000
--- a/editor/reftests/xul/number-ref.xul
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="input.css" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <html:input value="0" class="num"/>
-
-</window>
diff --git a/editor/reftests/xul/numberwithvalue-1.xul b/editor/reftests/xul/numberwithvalue-1.xul
deleted file mode 100644
index 3aaebcfdf..000000000
--- a/editor/reftests/xul/numberwithvalue-1.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox type="number" value="123" hidespinbuttons="true"/>
-
-</window>
diff --git a/editor/reftests/xul/numberwithvalue-ref.xul b/editor/reftests/xul/numberwithvalue-ref.xul
deleted file mode 100644
index 8ddc7a144..000000000
--- a/editor/reftests/xul/numberwithvalue-ref.xul
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="input.css" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <html:input value="123" class="num"/>
-
-</window>
diff --git a/editor/reftests/xul/passwd-1.xul b/editor/reftests/xul/passwd-1.xul
deleted file mode 100644
index 1f9619a16..000000000
--- a/editor/reftests/xul/passwd-1.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox type="password" value="test"/>
-
-</window>
diff --git a/editor/reftests/xul/passwd-2.xul b/editor/reftests/xul/passwd-2.xul
deleted file mode 100644
index 54fa5937b..000000000
--- a/editor/reftests/xul/passwd-2.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox type="password" value="abcd"/>
-
-</window>
diff --git a/editor/reftests/xul/passwd-3.xul b/editor/reftests/xul/passwd-3.xul
deleted file mode 100644
index b1849931b..000000000
--- a/editor/reftests/xul/passwd-3.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox value="test"/>
-
-</window>
diff --git a/editor/reftests/xul/passwd-ref.xul b/editor/reftests/xul/passwd-ref.xul
deleted file mode 100644
index 1f93bc339..000000000
--- a/editor/reftests/xul/passwd-ref.xul
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="input.css" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <html:input type="password" value="test"/>
-
-</window>
diff --git a/editor/reftests/xul/placeholder-reset.css b/editor/reftests/xul/placeholder-reset.css
deleted file mode 100644
index a2c41e69b..000000000
--- a/editor/reftests/xul/placeholder-reset.css
+++ /dev/null
@@ -1,8 +0,0 @@
-@namespace url('http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul');
-@namespace html url('http://www.w3.org/1999/xhtml');
-
-/* We need to have a non-transparent placeholder so we can test it. */
-html|input::placeholder {
- opacity: 1.0;
- color: graytext;
-}
diff --git a/editor/reftests/xul/plain-1.xul b/editor/reftests/xul/plain-1.xul
deleted file mode 100644
index ab573d0fc..000000000
--- a/editor/reftests/xul/plain-1.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox value=" test" class="plain"/>
-
-</window>
diff --git a/editor/reftests/xul/plain-ref.xul b/editor/reftests/xul/plain-ref.xul
deleted file mode 100644
index f345e675e..000000000
--- a/editor/reftests/xul/plain-ref.xul
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="input.css" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <html:div class="plainfield"> test</html:div>
-
-</window>
diff --git a/editor/reftests/xul/platform.js b/editor/reftests/xul/platform.js
deleted file mode 100644
index d3f5d33bf..000000000
--- a/editor/reftests/xul/platform.js
+++ /dev/null
@@ -1,28 +0,0 @@
-// The appearance of XUL elements is platform-specific, so we set the
-// style of the root element according to the platform, so that the
-// CSS code inside input.css can select the correct styles for each
-// platform.
-
-var id;
-var ua = navigator.userAgent;
-
-if (/Windows/.test(ua)) {
- id = "win";
- if (/NT 5\.1/.test(ua) || /NT 5\.2; Win64/.test(ua))
- var classname = "winxp";
-}
-else if (/Linux/.test(ua))
- id = "linux";
-else if (/SunOS/.test(ua))
- id = "linux";
-else if (/Mac OS X/.test(ua))
- id = "mac";
-
-if (id)
- document.documentElement.setAttribute("id", id);
-else
- document.documentElement.appendChild(
- document.createTextNode("Unrecognized platform")
- );
-if (classname)
- document.documentElement.setAttribute("class", classname);
diff --git a/editor/reftests/xul/reftest-stylo.list b/editor/reftests/xul/reftest-stylo.list
deleted file mode 100644
index cfaa7a058..000000000
--- a/editor/reftests/xul/reftest-stylo.list
+++ /dev/null
@@ -1,67 +0,0 @@
-# DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
-fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet||((browserIsRemote&&winWidget))) == empty-1.xul empty-1.xul
-# bug 783658
-# Initial mulet triage: parity with B2G/B2G Desktop, Windows: bug 1239170
-skip-if((B2G&&browserIsRemote)||Mulet) == empty-2.xul empty-2.xul
-# Initial mulet triage: parity with B2G/B2G Desktop
-# There is no way to simulate an autocomplete textbox in windows XP/Vista/7/8/10 default theme using CSS.
-# Therefore, the equlity tests below should be marked as failing.
-fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == autocomplete-1.xul autocomplete-1.xul
-# bug 783658
-# Initial mulet triage: parity with B2G/B2G Desktop
-fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == emptyautocomplete-1.xul emptyautocomplete-1.xul
-# bug 783658
-# Initial mulet triage: parity with B2G/B2G Desktop
-skip-if((B2G&&browserIsRemote)||Mulet) == emptymultiline-1.xul emptymultiline-1.xul
-# Initial mulet triage: parity with B2G/B2G Desktop
-fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet) == emptymultiline-2.xul emptymultiline-2.xul
-# bug 783658
-# Initial mulet triage: parity with B2G/B2G Desktop
-fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet||((browserIsRemote&&winWidget))) == emptytextbox-1.xul emptytextbox-1.xul
-# bug 783658
-# Initial mulet triage: parity with B2G/B2G Desktop, Windows: bug 1239170
-fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet||((browserIsRemote&&winWidget))) == emptytextbox-2.xul emptytextbox-2.xul
-# bug 783658
-# Initial mulet triage: parity with B2G/B2G Desktop, Windows: bug 1239170
-fails skip-if((B2G&&browserIsRemote)||Mulet) == emptytextbox-3.xul emptytextbox-3.xul
-# Initial mulet triage: parity with B2G/B2G Desktop
-skip-if((B2G&&browserIsRemote)||Mulet) == emptytextbox-4.xul emptytextbox-4.xul
-# Initial mulet triage: parity with B2G/B2G Desktop
-fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet||((browserIsRemote&&winWidget))) == emptytextbox-5.xul emptytextbox-5.xul
-# bug 783658
-# Initial mulet triage: parity with B2G/B2G Desktop, Windows: bug 1239170
-# There is no way to simulate a number textbox in windows XP/Vista/7 default theme using CSS.
-# Therefore, the equlity tests below should be marked as failing.
-skip-if((B2G&&browserIsRemote)||Mulet) == number-1.xul number-1.xul
-# Initial mulet triage: parity with B2G/B2G Desktop
-skip-if((B2G&&browserIsRemote)||Mulet) == number-2.xul number-2.xul
-# Initial mulet triage: parity with B2G/B2G Desktop
-fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == number-3.xul number-3.xul
-# bug 783658
-# Initial mulet triage: parity with B2G/B2G Desktop
-skip-if((B2G&&browserIsRemote)||Mulet) == number-4.xul number-4.xul
-# Initial mulet triage: parity with B2G/B2G Desktop
-fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == number-5.xul number-5.xul
-# bug 783658
-# Initial mulet triage: parity with B2G/B2G Desktop
-fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet) == numberwithvalue-1.xul numberwithvalue-1.xul
-# bug 783658
-# Initial mulet triage: parity with B2G/B2G Desktop
-fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet||((browserIsRemote&&winWidget))) == passwd-1.xul passwd-1.xul
-# bug 783658
-# Initial mulet triage: parity with B2G/B2G Desktop, Windows: bug 1239170
-fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet||((browserIsRemote&&winWidget))) == passwd-2.xul passwd-2.xul
-# bug 783658
-# Initial mulet triage: parity with B2G/B2G Desktop, Windows: bug 1239170
-skip-if((B2G&&browserIsRemote)||Mulet) == passwd-3.xul passwd-3.xul
-# Initial mulet triage: parity with B2G/B2G Desktop
-fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet) == plain-1.xul plain-1.xul
-# bug 783658
-# Initial mulet triage: parity with B2G/B2G Desktop
-fails-if(Android||B2G) skip-if((B2G&&browserIsRemote)||Mulet||(browserIsRemote&&winWidget)) == textbox-1.xul textbox-1.xul
-# Initial mulet triage: parity with B2G/B2G Desktop, Windows: bug 1239170
-skip-if((B2G&&browserIsRemote)||Mulet) == textbox-disabled.xul textbox-disabled.xul
-# Initial mulet triage: parity with B2G/B2G Desktop
-# Read-only textboxes look like normal textboxes in windows Vista/7 default theme
-fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(6\.[012]|10\.0)/.test(http.oscpu)) skip-if((B2G&&browserIsRemote)||Mulet||(browserIsRemote&&winWidget)) == textbox-readonly.xul textbox-readonly.xul
-# Initial mulet triage: parity with B2G/B2G Desktop, Windows: bug 1239170
diff --git a/editor/reftests/xul/reftest.list b/editor/reftests/xul/reftest.list
deleted file mode 100644
index 76bd9174f..000000000
--- a/editor/reftests/xul/reftest.list
+++ /dev/null
@@ -1,29 +0,0 @@
-fails-if(Android) skip-if(browserIsRemote&&winWidget) == empty-1.xul empty-ref.xul # Windows: bug 1239170
-!= empty-2.xul empty-ref.xul
-# There is no way to simulate an autocomplete textbox in windows XP/Vista/7/8/10 default theme using CSS.
-# Therefore, the equlity tests below should be marked as failing.
-fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) == autocomplete-1.xul autocomplete-ref.xul # bug 783658
-fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) == emptyautocomplete-1.xul emptyautocomplete-ref.xul # bug 783658
-!= emptymultiline-1.xul emptymultiline-ref.xul
-fails-if(Android) == emptymultiline-2.xul emptymultiline-ref.xul # bug 783658
-fails-if(Android) skip-if(browserIsRemote&&winWidget) == emptytextbox-1.xul emptytextbox-ref.xul # Windows: bug 1239170
-fails-if(Android) skip-if(browserIsRemote&&winWidget) == emptytextbox-2.xul emptytextbox-ref.xul # Windows: bug 1239170
-!= emptytextbox-3.xul emptytextbox-ref.xul
-!= emptytextbox-4.xul emptytextbox-ref.xul
-fails-if(Android) skip-if(browserIsRemote&&winWidget) == emptytextbox-5.xul emptytextbox-ref.xul # Windows: bug 1239170
-# There is no way to simulate a number textbox in windows XP/Vista/7 default theme using CSS.
-# Therefore, the equlity tests below should be marked as failing.
-!= number-1.xul number-ref.xul
-!= number-2.xul number-ref.xul
-fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) == number-3.xul number-ref.xul # bug 783658
-!= number-4.xul number-ref.xul
-fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) == number-5.xul number-ref.xul # bug 783658
-fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) == numberwithvalue-1.xul numberwithvalue-ref.xul # bug 783658
-fails-if(Android) skip-if(browserIsRemote&&winWidget) == passwd-1.xul passwd-ref.xul # Windows: bug 1239170
-fails-if(Android) skip-if(browserIsRemote&&winWidget) == passwd-2.xul passwd-ref.xul # Windows: bug 1239170
-!= passwd-3.xul passwd-ref.xul
-fails-if(Android) == plain-1.xul plain-ref.xul # bug 783658
-fails-if(Android) skip-if(browserIsRemote&&winWidget) == textbox-1.xul textbox-ref.xul # Windows: bug 1239170
-!= textbox-disabled.xul textbox-ref.xul
-# Read-only textboxes look like normal textboxes in windows Vista/7 default theme
-fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(6\.[012]|10\.0)/.test(http.oscpu)) skip-if(browserIsRemote&&winWidget) != textbox-readonly.xul textbox-ref.xul # Windows: bug 1239170
diff --git a/editor/reftests/xul/textbox-1.xul b/editor/reftests/xul/textbox-1.xul
deleted file mode 100644
index aae7e89ea..000000000
--- a/editor/reftests/xul/textbox-1.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox value=" test"/>
-
-</window>
diff --git a/editor/reftests/xul/textbox-disabled.xul b/editor/reftests/xul/textbox-disabled.xul
deleted file mode 100644
index c1ae83a3c..000000000
--- a/editor/reftests/xul/textbox-disabled.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox value=" test" disabled="true"/>
-
-</window>
diff --git a/editor/reftests/xul/textbox-readonly.xul b/editor/reftests/xul/textbox-readonly.xul
deleted file mode 100644
index f9d8b5f57..000000000
--- a/editor/reftests/xul/textbox-readonly.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <textbox value=" test" readonly="true"/>
-
-</window>
diff --git a/editor/reftests/xul/textbox-ref.xul b/editor/reftests/xul/textbox-ref.xul
deleted file mode 100644
index 8be9fc8e4..000000000
--- a/editor/reftests/xul/textbox-ref.xul
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="input.css" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- title="Textbox tests">
-
- <script type="text/javascript" src="platform.js"/>
-
- <html:input value=" test"/>
-
-</window>
diff --git a/editor/txmgr/moz.build b/editor/txmgr/moz.build
deleted file mode 100644
index f3b9cac8e..000000000
--- a/editor/txmgr/moz.build
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-TEST_DIRS += ['tests']
-
-XPIDL_SOURCES += [
- 'nsITransaction.idl',
- 'nsITransactionList.idl',
- 'nsITransactionListener.idl',
- 'nsITransactionManager.idl',
-]
-
-XPIDL_MODULE = 'txmgr'
-
-EXPORTS += [
- 'nsTransactionManagerCID.h',
-]
-
-SOURCES += [
- 'nsTransactionItem.cpp',
- 'nsTransactionList.cpp',
- 'nsTransactionManager.cpp',
- 'nsTransactionManagerFactory.cpp',
- 'nsTransactionStack.cpp',
-]
-
-FINAL_LIBRARY = 'xul'
diff --git a/editor/txmgr/nsITransaction.idl b/editor/txmgr/nsITransaction.idl
deleted file mode 100644
index 7e2e2aee4..000000000
--- a/editor/txmgr/nsITransaction.idl
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-/*
- * The nsITransaction interface.
- * <P>
- * This interface is implemented by an object that needs to
- * execute some behavior that must be tracked by the transaction manager.
- */
-[scriptable, uuid(58e330c1-7b48-11d2-98b9-00805f297d89)]
-interface nsITransaction : nsISupports
-{
- /**
- * Executes the transaction.
- */
- void doTransaction();
-
- /**
- * Restores the state to what it was before the transaction was executed.
- */
- void undoTransaction();
-
- /**
- * Executes the transaction again. Can only be called on a transaction that
- * was previously undone.
- * <P>
- * In most cases, the redoTransaction() method will actually call the
- * doTransaction() method to execute the transaction again.
- */
- void redoTransaction();
-
- /**
- * The transaction's transient state. This attribute is checked by
- * the transaction manager after the transaction's Execute() method is called.
- * If the transient state is false, a reference to the transaction is
- * held by the transaction manager so that the transactions' undoTransaction()
- * and redoTransaction() methods can be called. If the transient state is
- * true, the transaction manager returns immediately after the transaction's
- * doTransaction() method is called, no references to the transaction are
- * maintained. Transient transactions cannot be undone or redone by the
- * transaction manager.
- */
- readonly attribute boolean isTransient;
-
- /**
- * Attempts to merge a transaction into "this" transaction. Both transactions
- * must be in their undo state, doTransaction() methods already called. The
- * transaction manager calls this method to coalesce a new transaction with
- * the transaction on the top of the undo stack.
- * This method returns a boolean value that indicates the merge result.
- * A true value indicates that the transactions were merged successfully,
- * a false value if the merge was not possible or failed. If true,
- * the transaction manager will Release() the new transacton instead of
- * pushing it on the undo stack.
- * @param aTransaction the previously executed transaction to merge.
- */
- boolean merge(in nsITransaction aTransaction);
-};
-
diff --git a/editor/txmgr/nsITransactionList.idl b/editor/txmgr/nsITransactionList.idl
deleted file mode 100644
index de6d191de..000000000
--- a/editor/txmgr/nsITransactionList.idl
+++ /dev/null
@@ -1,70 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsITransaction;
-
-/*
- * The nsITransactionList interface.
- * <P>
- * The implementation for this interface is provided by the Transaction Manager.
- * This interface provides a mechanism for accessing the transactions on the
- * Undo or Redo stacks as well as any auto-aggregated children that a
- * transaction may have.
- */
-[scriptable, uuid(d007ceff-c978-486a-b697-384ca01997be)]
-
-interface nsITransactionList : nsISupports
-{
- /**
- * The number of transactions contained in this list.
- */
- readonly attribute long numItems;
-
- /**
- * itemIsBatch() returns true if the item at aIndex is a batch. Note that
- * currently there is no requirement for a TransactionManager implementation
- * to associate a toplevel nsITransaction with a batch so it is possible for
- * itemIsBatch() to return true and getItem() to return null. However, you
- * can still access the transactions contained in the batch with a call to
- * getChildListForItem().
- * @param aIndex The index of the item in the list.
- */
- boolean itemIsBatch(in long aIndex);
-
- /**
- * getItem() returns the transaction at the given index in the list. Note that
- * a null can be returned here if the item is a batch. The transaction
- * returned is AddRef'd so it is up to the caller to Release the transaction
- * when it is done.
- * @param aIndex The index of the item in the list.
- */
- nsITransaction getItem(in long aIndex);
-
- /**
- * getData() returns the data (of type nsISupports array) associated with
- * the transaction list.
- */
- void getData(in long aIndex, [optional] out unsigned long aLength,
- [array, size_is(aLength), retval] out nsISupports aData);
-
- /**
- * getNumChildrenForItem() returns the number of child (auto-aggreated)
- * transactions the item at aIndex has.
- * @param aIndex The index of the item in the list.
- */
- long getNumChildrenForItem(in long aIndex);
-
- /**
- * getChildListForItem() returns the list of children associated with the
- * item at aIndex. Implementations may return null if there are no children,
- * or an empty list. The list returned is AddRef'd so it is up to the caller
- * to Release the transaction when it is done.
- * @param aIndex The index of the item in the list.
- */
- nsITransactionList getChildListForItem(in long aIndex);
-};
-
diff --git a/editor/txmgr/nsITransactionListener.idl b/editor/txmgr/nsITransactionListener.idl
deleted file mode 100644
index c63f9e3b8..000000000
--- a/editor/txmgr/nsITransactionListener.idl
+++ /dev/null
@@ -1,170 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsITransaction;
-interface nsITransactionManager;
-
-/**
- * The nsITransactionListener interface.
- * <P>
- * This interface is implemented by an object that tracks transactions.
- */
-[scriptable, uuid(58e330c4-7b48-11d2-98b9-00805f297d89)]
-interface nsITransactionListener : nsISupports
-{
- /**
- * Called before a transaction manager calls a transaction's
- * doTransaction() method.
- * @param aManager the transaction manager doing the transaction.
- * @param aTransaction the transaction being executed.
- * @result boolean value returned by listener which indicates
- * its desire to interrupt normal control flow. Listeners should
- * return true if they want to interrupt normal control flow, without
- * throwing an error.
- */
- boolean willDo(in nsITransactionManager aManager,
- in nsITransaction aTransaction);
-
- /**
- * Called after a transaction manager calls the doTransaction() method of
- * a transaction.
- * @param aManager the transaction manager that did the transaction.
- * @param aTransaction the transaction that was executed.
- * @param aDoResult the nsresult returned after executing
- * the transaction.
- */
- void didDo(in nsITransactionManager aManager,
- in nsITransaction aTransaction,
- in nsresult aDoResult);
-
- /**
- * Called before a transaction manager calls the Undo() method of
- * a transaction.
- * @param aManager the transaction manager undoing the transaction.
- * @param aTransaction the transaction being undone.
- * @result boolean value returned by listener which indicates
- * its desire to interrupt normal control flow. Listeners should
- * return true if they want to interrupt normal control flow, without
- * throwing an error. Note that listeners can also interrupt normal
- * control flow by throwing an nsresult that indicates an error.
- */
- boolean willUndo(in nsITransactionManager aManager,
- in nsITransaction aTransaction);
-
- /**
- * Called after a transaction manager calls the Undo() method of
- * a transaction.
- * @param aManager the transaction manager undoing the transaction.
- * @param aTransaction the transaction being undone.
- * @param aUndoResult the nsresult returned after undoing the transaction.
- */
- void didUndo(in nsITransactionManager aManager,
- in nsITransaction aTransaction,
- in nsresult aUndoResult);
-
- /**
- * Called before a transaction manager calls the Redo() method of
- * a transaction.
- * @param aManager the transaction manager redoing the transaction.
- * @param aTransaction the transaction being redone.
- * @result boolean value returned by listener which indicates
- * its desire to interrupt normal control flow. Listeners should
- * return true if they want to interrupt normal control flow, without
- * throwing an error. Note that listeners can also interrupt normal
- * control flow by throwing an nsresult that indicates an error.
- */
- boolean willRedo(in nsITransactionManager aManager,
- in nsITransaction aTransaction);
-
- /**
- * Called after a transaction manager calls the Redo() method of
- * a transaction.
- * @param aManager the transaction manager redoing the transaction.
- * @param aTransaction the transaction being redone.
- * @param aRedoResult the nsresult returned after redoing the transaction.
- */
- void didRedo(in nsITransactionManager aManager,
- in nsITransaction aTransaction,
- in nsresult aRedoResult);
-
- /**
- * Called before a transaction manager begins a batch.
- * @param aManager the transaction manager beginning a batch.
- * @result boolean value returned by listener which indicates
- * its desire to interrupt normal control flow. Listeners should
- * return true if they want to interrupt normal control flow, without
- * throwing an error. Note that listeners can also interrupt normal
- * control flow by throwing an nsresult that indicates an error.
- */
- boolean willBeginBatch(in nsITransactionManager aManager);
-
- /**
- * Called after a transaction manager begins a batch.
- * @param aManager the transaction manager that began a batch.
- * @param aResult the nsresult returned after beginning a batch.
- */
- void didBeginBatch(in nsITransactionManager aManager,
- in nsresult aResult);
-
- /**
- * Called before a transaction manager ends a batch.
- * @param aManager the transaction manager ending a batch.
- * @result boolean value returned by listener which indicates
- * its desire to interrupt normal control flow. Listeners should
- * return true if they want to interrupt normal control flow, without
- * throwing an error. Note that listeners can also interrupt normal
- * control flow by throwing an nsresult that indicates an error.
- */
- boolean willEndBatch(in nsITransactionManager aManager);
-
- /**
- * Called after a transaction manager ends a batch.
- * @param aManager the transaction manager ending a batch.
- * @param aResult the nsresult returned after ending a batch.
- */
- void didEndBatch(in nsITransactionManager aManager,
- in nsresult aResult);
-
- /**
- * Called before a transaction manager tries to merge
- * a transaction, that was just executed, with the
- * transaction at the top of the undo stack.
- * @param aManager the transaction manager ending a batch.
- * @param aTopTransaction the transaction at the top of the undo stack.
- * @param aTransactionToMerge the transaction to merge.
- * @result boolean value returned by listener which indicates
- * its desire to interrupt normal control flow. Listeners should
- * return true if they want to interrupt normal control flow, without
- * throwing an error. Note that listeners can also interrupt normal
- * control flow by throwing an nsresult that indicates an error.
- */
- boolean willMerge(in nsITransactionManager aManager,
- in nsITransaction aTopTransaction,
- in nsITransaction aTransactionToMerge);
-
- /**
- * Called after a transaction manager tries to merge
- * a transaction, that was just executed, with the
- * transaction at the top of the undo stack.
- * @param aManager the transaction manager ending a batch.
- * @param aTopTransaction the transaction at the top of the undo stack.
- * @param aTransactionToMerge the transaction to merge.
- * @param aDidMerge true if transaction was merged, else false.
- * @param aMergeResult the nsresult returned after the merge attempt.
- * @param aInterrupt listeners should set this to PR_TRUE if they
- * want to interrupt normal control flow, without throwing an error.
- */
- void didMerge(in nsITransactionManager aManager,
- in nsITransaction aTopTransaction,
- in nsITransaction aTransactionToMerge,
- in boolean aDidMerge,
- in nsresult aMergeResult);
-
-
- /* XXX: We should probably add pruning notification methods. */
-};
-
diff --git a/editor/txmgr/nsITransactionManager.idl b/editor/txmgr/nsITransactionManager.idl
deleted file mode 100644
index 0587d5ca1..000000000
--- a/editor/txmgr/nsITransactionManager.idl
+++ /dev/null
@@ -1,168 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "nsITransaction.idl"
-#include "nsITransactionList.idl"
-#include "nsITransactionListener.idl"
-
-%{ C++
-
-#define NS_TRANSACTIONMANAGER_CONTRACTID "@mozilla.org/transactionmanager;1"
-
-%} C++
-
-/**
- * The nsITransactionManager interface.
- * <P>
- * This interface is implemented by an object that wants to
- * manage/track transactions.
- */
-[scriptable, builtinclass, uuid(c77763df-0fb9-41a8-8074-8e882f605755)]
-interface nsITransactionManager : nsISupports
-{
- /**
- * Calls a transaction's doTransaction() method, then pushes it on the
- * undo stack.
- * <P>
- * This method calls the transaction's AddRef() method.
- * The transaction's Release() method will be called when the undo or redo
- * stack is pruned or when the transaction manager is destroyed.
- * @param aTransaction the transaction to do.
- */
- void doTransaction(in nsITransaction aTransaction);
-
- /**
- * Pops the topmost transaction on the undo stack, calls its
- * undoTransaction() method, then pushes it on the redo stack.
- */
- void undoTransaction();
-
- /**
- * Pops the topmost transaction on the redo stack, calls its
- * redoTransaction() method, then pushes it on the undo stack.
- */
- void redoTransaction();
-
- /**
- * Clears the undo and redo stacks.
- */
- void clear();
-
- /**
- * Clears the undo stack only.
- */
- void clearUndoStack();
-
- /**
- * Clears the redo stack only.
- */
- void clearRedoStack();
-
- /**
- * Turns on the transaction manager's batch mode, forcing all transactions
- * executed by the transaction manager's doTransaction() method to be
- * aggregated together until EndBatch() is called. This mode allows an
- * application to execute and group together several independent transactions
- * so they can be undone with a single call to undoTransaction().
- * @param aData An arbitrary nsISupports object that is associated with the
- * batch. Can be retrieved from nsITransactionList.
- */
- void beginBatch(in nsISupports aData);
-
- /**
- * Turns off the transaction manager's batch mode.
- * @param aAllowEmpty If true, a batch containing no children will be
- * pushed onto the undo stack. Otherwise, ending a batch with no
- * children will result in no transactions being pushed on the undo stack.
- */
- void endBatch(in boolean aAllowEmpty);
-
- /**
- * The number of items on the undo stack.
- */
- readonly attribute long numberOfUndoItems;
-
- /**
- * The number of items on the redo stack.
- */
- readonly attribute long numberOfRedoItems;
-
- /**
- * Sets the maximum number of transaction items the transaction manager will
- * maintain at any time. This is commonly referred to as the number of levels
- * of undo.
- * @param aMaxCount A value of -1 means no limit. A value of zero means the
- * transaction manager will execute each transaction, then immediately release
- * all references it has to the transaction without pushing it on the undo
- * stack. A value greater than zero indicates the max number of transactions
- * that can exist at any time on both the undo and redo stacks. This method
- * will prune the necessary number of transactions on the undo and redo
- * stacks if the value specified is less than the number of items that exist
- * on both the undo and redo stacks.
- */
- attribute long maxTransactionCount;
-
- /**
- * Combines the transaction at the top of the undo stack (if any) with the
- * preceding undo transaction (if any) into a batch transaction. Thus,
- * a call to undoTransaction() will undo both transactions.
- */
- void batchTopUndo();
-
- /**
- * Removes the transaction at the top of the undo stack (if any) without
- * transacting.
- */
- void removeTopUndo();
-
- /**
- * Returns an AddRef'd pointer to the transaction at the top of the
- * undo stack. Callers should be aware that this method could return
- * return a null in some implementations if there is a batch at the top
- * of the undo stack.
- */
- nsITransaction peekUndoStack();
-
- /**
- * Returns an AddRef'd pointer to the transaction at the top of the
- * redo stack. Callers should be aware that this method could return
- * return a null in some implementations if there is a batch at the top
- * of the redo stack.
- */
- nsITransaction peekRedoStack();
-
- /**
- * Returns the list of transactions on the undo stack. Note that the
- * transaction at the top of the undo stack will actually be at the
- * index 'n-1' in the list, where 'n' is the number of items in the list.
- */
- nsITransactionList getUndoList();
-
- /**
- * Returns the list of transactions on the redo stack. Note that the
- * transaction at the top of the redo stack will actually be at the
- * index 'n-1' in the list, where 'n' is the number of items in the list.
- */
- nsITransactionList getRedoList();
-
- /**
- * Adds a listener to the transaction manager's notification list. Listeners
- * are notified whenever a transaction is done, undone, or redone.
- * <P>
- * The listener's AddRef() method is called.
- * @param aListener the lister to add.
- */
- void AddListener(in nsITransactionListener aListener);
-
- /**
- * Removes a listener from the transaction manager's notification list.
- * <P>
- * The listener's Release() method is called.
- * @param aListener the lister to remove.
- */
- void RemoveListener(in nsITransactionListener aListener);
-};
-
diff --git a/editor/txmgr/nsTransactionItem.cpp b/editor/txmgr/nsTransactionItem.cpp
deleted file mode 100644
index afea20a0b..000000000
--- a/editor/txmgr/nsTransactionItem.cpp
+++ /dev/null
@@ -1,349 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/mozalloc.h"
-#include "nsCOMPtr.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsISupportsImpl.h"
-#include "nsITransaction.h"
-#include "nsTransactionItem.h"
-#include "nsTransactionManager.h"
-#include "nsTransactionStack.h"
-
-nsTransactionItem::nsTransactionItem(nsITransaction *aTransaction)
- : mTransaction(aTransaction), mUndoStack(0), mRedoStack(0)
-{
-}
-
-nsTransactionItem::~nsTransactionItem()
-{
- delete mRedoStack;
- delete mUndoStack;
-}
-
-void
-nsTransactionItem::CleanUp()
-{
- mData.Clear();
- mTransaction = nullptr;
- if (mRedoStack) {
- mRedoStack->DoUnlink();
- }
- if (mUndoStack) {
- mUndoStack->DoUnlink();
- }
-}
-
-NS_IMPL_CYCLE_COLLECTING_NATIVE_ADDREF(nsTransactionItem)
-NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE_WITH_LAST_RELEASE(nsTransactionItem,
- CleanUp())
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsTransactionItem)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsTransactionItem)
- tmp->CleanUp();
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsTransactionItem)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mData)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransaction)
- if (tmp->mRedoStack) {
- tmp->mRedoStack->DoTraverse(cb);
- }
- if (tmp->mUndoStack) {
- tmp->mUndoStack->DoTraverse(cb);
- }
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsTransactionItem, AddRef)
-NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsTransactionItem, Release)
-
-nsresult
-nsTransactionItem::AddChild(nsTransactionItem *aTransactionItem)
-{
- NS_ENSURE_TRUE(aTransactionItem, NS_ERROR_NULL_POINTER);
-
- if (!mUndoStack) {
- mUndoStack = new nsTransactionStack(nsTransactionStack::FOR_UNDO);
- }
-
- mUndoStack->Push(aTransactionItem);
- return NS_OK;
-}
-
-already_AddRefed<nsITransaction>
-nsTransactionItem::GetTransaction()
-{
- nsCOMPtr<nsITransaction> txn = mTransaction;
- return txn.forget();
-}
-
-nsresult
-nsTransactionItem::GetIsBatch(bool *aIsBatch)
-{
- NS_ENSURE_TRUE(aIsBatch, NS_ERROR_NULL_POINTER);
- *aIsBatch = !mTransaction;
- return NS_OK;
-}
-
-nsresult
-nsTransactionItem::GetNumberOfChildren(int32_t *aNumChildren)
-{
- NS_ENSURE_TRUE(aNumChildren, NS_ERROR_NULL_POINTER);
-
- *aNumChildren = 0;
-
- int32_t ui = 0;
- nsresult rv = GetNumberOfUndoItems(&ui);
- NS_ENSURE_SUCCESS(rv, rv);
-
- int32_t ri = 0;
- rv = GetNumberOfRedoItems(&ri);
- NS_ENSURE_SUCCESS(rv, rv);
-
- *aNumChildren = ui + ri;
- return NS_OK;
-}
-
-nsresult
-nsTransactionItem::GetChild(int32_t aIndex, nsTransactionItem **aChild)
-{
- NS_ENSURE_TRUE(aChild, NS_ERROR_NULL_POINTER);
-
- *aChild = 0;
-
- int32_t numItems = 0;
- nsresult rv = GetNumberOfChildren(&numItems);
- NS_ENSURE_SUCCESS(rv, rv);
- if (aIndex < 0 || aIndex >= numItems) {
- return NS_ERROR_FAILURE;
- }
-
- // Children are expected to be in the order they were added,
- // so the child first added would be at the bottom of the undo
- // stack, or if there are no items on the undo stack, it would
- // be at the top of the redo stack.
- rv = GetNumberOfUndoItems(&numItems);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (numItems > 0 && aIndex < numItems) {
- NS_ENSURE_TRUE(mUndoStack, NS_ERROR_FAILURE);
-
- RefPtr<nsTransactionItem> child = mUndoStack->GetItem(aIndex);
- child.forget(aChild);
- return *aChild ? NS_OK : NS_ERROR_FAILURE;
- }
-
- // Adjust the index for the redo stack:
- aIndex -= numItems;
-
- rv = GetNumberOfRedoItems(&numItems);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(mRedoStack && numItems != 0 && aIndex < numItems, NS_ERROR_FAILURE);
-
- RefPtr<nsTransactionItem> child = mRedoStack->GetItem(aIndex);
- child.forget(aChild);
- return *aChild ? NS_OK : NS_ERROR_FAILURE;
-}
-
-nsresult
-nsTransactionItem::DoTransaction()
-{
- if (mTransaction) {
- return mTransaction->DoTransaction();
- }
- return NS_OK;
-}
-
-nsresult
-nsTransactionItem::UndoTransaction(nsTransactionManager *aTxMgr)
-{
- nsresult rv = UndoChildren(aTxMgr);
- if (NS_FAILED(rv)) {
- RecoverFromUndoError(aTxMgr);
- return rv;
- }
-
- if (!mTransaction) {
- return NS_OK;
- }
-
- rv = mTransaction->UndoTransaction();
- if (NS_FAILED(rv)) {
- RecoverFromUndoError(aTxMgr);
- return rv;
- }
-
- return NS_OK;
-}
-
-nsresult
-nsTransactionItem::UndoChildren(nsTransactionManager *aTxMgr)
-{
- if (mUndoStack) {
- if (!mRedoStack && mUndoStack) {
- mRedoStack = new nsTransactionStack(nsTransactionStack::FOR_REDO);
- }
-
- /* Undo all of the transaction items children! */
- int32_t sz = mUndoStack->GetSize();
-
- nsresult rv = NS_OK;
- while (sz-- > 0) {
- RefPtr<nsTransactionItem> item = mUndoStack->Peek();
- if (!item) {
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsITransaction> t = item->GetTransaction();
- bool doInterrupt = false;
- rv = aTxMgr->WillUndoNotify(t, &doInterrupt);
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (doInterrupt) {
- return NS_OK;
- }
-
- rv = item->UndoTransaction(aTxMgr);
- if (NS_SUCCEEDED(rv)) {
- item = mUndoStack->Pop();
- mRedoStack->Push(item.forget());
- }
-
- nsresult rv2 = aTxMgr->DidUndoNotify(t, rv);
- if (NS_SUCCEEDED(rv)) {
- rv = rv2;
- }
- }
- // XXX NS_OK if there is no Undo items or all methods work fine, otherwise,
- // the result of the last item's UndoTransaction() or
- // DidUndoNotify() if UndoTransaction() succeeded.
- return rv;
- }
-
- return NS_OK;
-}
-
-nsresult
-nsTransactionItem::RedoTransaction(nsTransactionManager *aTxMgr)
-{
- nsCOMPtr<nsITransaction> transaction(mTransaction);
- if (transaction) {
- nsresult rv = transaction->RedoTransaction();
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- nsresult rv = RedoChildren(aTxMgr);
- if (NS_FAILED(rv)) {
- RecoverFromRedoError(aTxMgr);
- return rv;
- }
-
- return NS_OK;
-}
-
-nsresult
-nsTransactionItem::RedoChildren(nsTransactionManager *aTxMgr)
-{
- if (!mRedoStack) {
- return NS_OK;
- }
-
- /* Redo all of the transaction items children! */
- int32_t sz = mRedoStack->GetSize();
-
- nsresult rv = NS_OK;
- while (sz-- > 0) {
- RefPtr<nsTransactionItem> item = mRedoStack->Peek();
- if (!item) {
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsITransaction> t = item->GetTransaction();
- bool doInterrupt = false;
- rv = aTxMgr->WillRedoNotify(t, &doInterrupt);
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (doInterrupt) {
- return NS_OK;
- }
-
- rv = item->RedoTransaction(aTxMgr);
- if (NS_SUCCEEDED(rv)) {
- item = mRedoStack->Pop();
- mUndoStack->Push(item.forget());
- }
-
- // XXX Shouldn't this DidRedoNotify()? (bug 1311626)
- nsresult rv2 = aTxMgr->DidUndoNotify(t, rv);
- if (NS_SUCCEEDED(rv)) {
- rv = rv2;
- }
- }
- // XXX NS_OK if there is no Redo items or all methods work fine, otherwise,
- // the result of the last item's RedoTransaction() or
- // DidUndoNotify() if UndoTransaction() succeeded.
- return rv;
-}
-
-nsresult
-nsTransactionItem::GetNumberOfUndoItems(int32_t *aNumItems)
-{
- NS_ENSURE_TRUE(aNumItems, NS_ERROR_NULL_POINTER);
-
- if (!mUndoStack) {
- *aNumItems = 0;
- return NS_OK;
- }
-
- *aNumItems = mUndoStack->GetSize();
- return *aNumItems ? NS_OK : NS_ERROR_FAILURE;
-}
-
-nsresult
-nsTransactionItem::GetNumberOfRedoItems(int32_t *aNumItems)
-{
- NS_ENSURE_TRUE(aNumItems, NS_ERROR_NULL_POINTER);
-
- if (!mRedoStack) {
- *aNumItems = 0;
- return NS_OK;
- }
-
- *aNumItems = mRedoStack->GetSize();
- return *aNumItems ? NS_OK : NS_ERROR_FAILURE;
-}
-
-nsresult
-nsTransactionItem::RecoverFromUndoError(nsTransactionManager *aTxMgr)
-{
- // If this method gets called, we never got to the point where we
- // successfully called UndoTransaction() for the transaction item itself.
- // Just redo any children that successfully called undo!
- return RedoChildren(aTxMgr);
-}
-
-nsresult
-nsTransactionItem::RecoverFromRedoError(nsTransactionManager *aTxMgr)
-{
- // If this method gets called, we already successfully called
- // RedoTransaction() for the transaction item itself. Undo all
- // the children that successfully called RedoTransaction(),
- // then undo the transaction item itself.
- nsresult rv = UndoChildren(aTxMgr);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- if (!mTransaction) {
- return NS_OK;
- }
-
- return mTransaction->UndoTransaction();
-}
-
diff --git a/editor/txmgr/nsTransactionItem.h b/editor/txmgr/nsTransactionItem.h
deleted file mode 100644
index dc868203b..000000000
--- a/editor/txmgr/nsTransactionItem.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsTransactionItem_h__
-#define nsTransactionItem_h__
-
-#include "nsCOMPtr.h"
-#include "nsCOMArray.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsISupportsImpl.h"
-#include "nscore.h"
-
-class nsITransaction;
-class nsTransactionManager;
-class nsTransactionStack;
-
-class nsTransactionItem final
-{
- nsCOMArray<nsISupports> mData;
- nsCOMPtr<nsITransaction> mTransaction;
- nsTransactionStack *mUndoStack;
- nsTransactionStack *mRedoStack;
-
-public:
-
- explicit nsTransactionItem(nsITransaction *aTransaction);
- NS_METHOD_(MozExternalRefCountType) AddRef();
- NS_METHOD_(MozExternalRefCountType) Release();
-
- NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsTransactionItem)
-
- virtual nsresult AddChild(nsTransactionItem *aTransactionItem);
- already_AddRefed<nsITransaction> GetTransaction();
- virtual nsresult GetIsBatch(bool *aIsBatch);
- virtual nsresult GetNumberOfChildren(int32_t *aNumChildren);
- virtual nsresult GetChild(int32_t aIndex, nsTransactionItem **aChild);
-
- virtual nsresult DoTransaction(void);
- virtual nsresult UndoTransaction(nsTransactionManager *aTxMgr);
- virtual nsresult RedoTransaction(nsTransactionManager *aTxMgr);
-
- nsCOMArray<nsISupports>& GetData()
- {
- return mData;
- }
-
-private:
-
- virtual nsresult UndoChildren(nsTransactionManager *aTxMgr);
- virtual nsresult RedoChildren(nsTransactionManager *aTxMgr);
-
- virtual nsresult RecoverFromUndoError(nsTransactionManager *aTxMgr);
- virtual nsresult RecoverFromRedoError(nsTransactionManager *aTxMgr);
-
- virtual nsresult GetNumberOfUndoItems(int32_t *aNumItems);
- virtual nsresult GetNumberOfRedoItems(int32_t *aNumItems);
-
- void CleanUp();
-protected:
- virtual ~nsTransactionItem();
-
- nsCycleCollectingAutoRefCnt mRefCnt;
- NS_DECL_OWNINGTHREAD
-};
-
-#endif // nsTransactionItem_h__
diff --git a/editor/txmgr/nsTransactionList.cpp b/editor/txmgr/nsTransactionList.cpp
deleted file mode 100644
index 756edfd49..000000000
--- a/editor/txmgr/nsTransactionList.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/mozalloc.h"
-#include "nsCOMPtr.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsID.h"
-#include "nsISupportsUtils.h"
-#include "nsITransactionManager.h"
-#include "nsTransactionItem.h"
-#include "nsTransactionList.h"
-#include "nsTransactionStack.h"
-#include "nscore.h"
-
-NS_IMPL_ISUPPORTS(nsTransactionList, nsITransactionList)
-
-nsTransactionList::nsTransactionList(nsITransactionManager *aTxnMgr, nsTransactionStack *aTxnStack)
- : mTxnStack(aTxnStack)
- , mTxnItem(nullptr)
-{
- if (aTxnMgr)
- mTxnMgr = do_GetWeakReference(aTxnMgr);
-}
-
-nsTransactionList::nsTransactionList(nsITransactionManager *aTxnMgr, nsTransactionItem *aTxnItem)
- : mTxnStack(0)
- , mTxnItem(aTxnItem)
-{
- if (aTxnMgr)
- mTxnMgr = do_GetWeakReference(aTxnMgr);
-}
-
-nsTransactionList::~nsTransactionList()
-{
- mTxnStack = 0;
- mTxnItem = nullptr;
-}
-
-NS_IMETHODIMP nsTransactionList::GetNumItems(int32_t *aNumItems)
-{
- NS_ENSURE_TRUE(aNumItems, NS_ERROR_NULL_POINTER);
-
- *aNumItems = 0;
-
- nsCOMPtr<nsITransactionManager> txMgr = do_QueryReferent(mTxnMgr);
- NS_ENSURE_TRUE(txMgr, NS_ERROR_FAILURE);
-
- if (mTxnStack) {
- *aNumItems = mTxnStack->GetSize();
- } else if (mTxnItem) {
- return mTxnItem->GetNumberOfChildren(aNumItems);
- }
-
- return NS_OK;
-}
-
-NS_IMETHODIMP nsTransactionList::ItemIsBatch(int32_t aIndex, bool *aIsBatch)
-{
- NS_ENSURE_TRUE(aIsBatch, NS_ERROR_NULL_POINTER);
-
- *aIsBatch = false;
-
- nsCOMPtr<nsITransactionManager> txMgr = do_QueryReferent(mTxnMgr);
- NS_ENSURE_TRUE(txMgr, NS_ERROR_FAILURE);
-
- RefPtr<nsTransactionItem> item;
- if (mTxnStack) {
- item = mTxnStack->GetItem(aIndex);
- } else if (mTxnItem) {
- nsresult rv = mTxnItem->GetChild(aIndex, getter_AddRefs(item));
- NS_ENSURE_SUCCESS(rv, rv);
- }
- NS_ENSURE_TRUE(item, NS_ERROR_FAILURE);
-
- return item->GetIsBatch(aIsBatch);
-}
-
-NS_IMETHODIMP nsTransactionList::GetData(int32_t aIndex,
- uint32_t *aLength,
- nsISupports ***aData)
-{
- nsCOMPtr<nsITransactionManager> txMgr = do_QueryReferent(mTxnMgr);
- NS_ENSURE_TRUE(txMgr, NS_ERROR_FAILURE);
-
- RefPtr<nsTransactionItem> item;
- if (mTxnStack) {
- item = mTxnStack->GetItem(aIndex);
- } else if (mTxnItem) {
- nsresult rv = mTxnItem->GetChild(aIndex, getter_AddRefs(item));
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- nsCOMArray<nsISupports>& data = item->GetData();
- nsISupports** ret = static_cast<nsISupports**>(moz_xmalloc(data.Count() *
- sizeof(nsISupports*)));
-
- for (int32_t i = 0; i < data.Count(); i++) {
- NS_ADDREF(ret[i] = data[i]);
- }
- *aLength = data.Count();
- *aData = ret;
- return NS_OK;
-}
-
-NS_IMETHODIMP nsTransactionList::GetItem(int32_t aIndex, nsITransaction **aItem)
-{
- NS_ENSURE_TRUE(aItem, NS_ERROR_NULL_POINTER);
-
- *aItem = 0;
-
- nsCOMPtr<nsITransactionManager> txMgr = do_QueryReferent(mTxnMgr);
- NS_ENSURE_TRUE(txMgr, NS_ERROR_FAILURE);
-
- RefPtr<nsTransactionItem> item;
- if (mTxnStack) {
- item = mTxnStack->GetItem(aIndex);
- } else if (mTxnItem) {
- nsresult rv = mTxnItem->GetChild(aIndex, getter_AddRefs(item));
- NS_ENSURE_SUCCESS(rv, rv);
- }
- NS_ENSURE_TRUE(item, NS_ERROR_FAILURE);
-
- *aItem = item->GetTransaction().take();
- return NS_OK;
-}
-
-NS_IMETHODIMP nsTransactionList::GetNumChildrenForItem(int32_t aIndex, int32_t *aNumChildren)
-{
- NS_ENSURE_TRUE(aNumChildren, NS_ERROR_NULL_POINTER);
-
- *aNumChildren = 0;
-
- nsCOMPtr<nsITransactionManager> txMgr = do_QueryReferent(mTxnMgr);
- NS_ENSURE_TRUE(txMgr, NS_ERROR_FAILURE);
-
- RefPtr<nsTransactionItem> item;
- if (mTxnStack) {
- item = mTxnStack->GetItem(aIndex);
- } else if (mTxnItem) {
- nsresult rv = mTxnItem->GetChild(aIndex, getter_AddRefs(item));
- NS_ENSURE_SUCCESS(rv, rv);
- }
- NS_ENSURE_TRUE(item, NS_ERROR_FAILURE);
-
- return item->GetNumberOfChildren(aNumChildren);
-}
-
-NS_IMETHODIMP nsTransactionList::GetChildListForItem(int32_t aIndex, nsITransactionList **aTxnList)
-{
- NS_ENSURE_TRUE(aTxnList, NS_ERROR_NULL_POINTER);
-
- *aTxnList = 0;
-
- nsCOMPtr<nsITransactionManager> txMgr = do_QueryReferent(mTxnMgr);
- NS_ENSURE_TRUE(txMgr, NS_ERROR_FAILURE);
-
- RefPtr<nsTransactionItem> item;
- if (mTxnStack) {
- item = mTxnStack->GetItem(aIndex);
- } else if (mTxnItem) {
- nsresult rv = mTxnItem->GetChild(aIndex, getter_AddRefs(item));
- NS_ENSURE_SUCCESS(rv, rv);
- }
- NS_ENSURE_TRUE(item, NS_ERROR_FAILURE);
-
- *aTxnList = (nsITransactionList *)new nsTransactionList(txMgr, item);
- NS_ENSURE_TRUE(*aTxnList, NS_ERROR_OUT_OF_MEMORY);
-
- NS_ADDREF(*aTxnList);
- return NS_OK;
-}
diff --git a/editor/txmgr/nsTransactionList.h b/editor/txmgr/nsTransactionList.h
deleted file mode 100644
index e3dde1255..000000000
--- a/editor/txmgr/nsTransactionList.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsTransactionList_h__
-#define nsTransactionList_h__
-
-#include "nsISupportsImpl.h"
-#include "nsITransactionList.h"
-#include "nsIWeakReferenceUtils.h"
-
-class nsITransaction;
-class nsITransactionManager;
-class nsTransactionItem;
-class nsTransactionStack;
-
-/** implementation of a transaction list object.
- *
- */
-class nsTransactionList : public nsITransactionList
-{
-private:
-
- nsWeakPtr mTxnMgr;
- nsTransactionStack *mTxnStack;
- RefPtr<nsTransactionItem> mTxnItem;
-
-protected:
- virtual ~nsTransactionList();
-
-public:
-
- nsTransactionList(nsITransactionManager *aTxnMgr, nsTransactionStack *aTxnStack);
- nsTransactionList(nsITransactionManager *aTxnMgr, nsTransactionItem *aTxnItem);
-
- /* Macro for AddRef(), Release(), and QueryInterface() */
- NS_DECL_ISUPPORTS
-
- /* nsITransactionManager method implementations. */
- NS_DECL_NSITRANSACTIONLIST
-
- /* nsTransactionList specific methods. */
-};
-
-#endif // nsTransactionList_h__
diff --git a/editor/txmgr/nsTransactionManager.cpp b/editor/txmgr/nsTransactionManager.cpp
deleted file mode 100644
index 10f9c3d06..000000000
--- a/editor/txmgr/nsTransactionManager.cpp
+++ /dev/null
@@ -1,752 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/Assertions.h"
-#include "mozilla/mozalloc.h"
-#include "nsCOMPtr.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsISupportsBase.h"
-#include "nsISupportsUtils.h"
-#include "nsITransaction.h"
-#include "nsITransactionList.h"
-#include "nsITransactionListener.h"
-#include "nsIWeakReference.h"
-#include "nsTransactionItem.h"
-#include "nsTransactionList.h"
-#include "nsTransactionManager.h"
-#include "nsTransactionStack.h"
-
-nsTransactionManager::nsTransactionManager(int32_t aMaxTransactionCount)
- : mMaxTransactionCount(aMaxTransactionCount)
- , mDoStack(nsTransactionStack::FOR_UNDO)
- , mUndoStack(nsTransactionStack::FOR_UNDO)
- , mRedoStack(nsTransactionStack::FOR_REDO)
-{
-}
-
-nsTransactionManager::~nsTransactionManager()
-{
-}
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsTransactionManager)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsTransactionManager)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mListeners)
- tmp->mDoStack.DoUnlink();
- tmp->mUndoStack.DoUnlink();
- tmp->mRedoStack.DoUnlink();
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsTransactionManager)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListeners)
- tmp->mDoStack.DoTraverse(cb);
- tmp->mUndoStack.DoTraverse(cb);
- tmp->mRedoStack.DoTraverse(cb);
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsTransactionManager)
- NS_INTERFACE_MAP_ENTRY(nsITransactionManager)
- NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
- NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITransactionManager)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTransactionManager)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTransactionManager)
-
-NS_IMETHODIMP
-nsTransactionManager::DoTransaction(nsITransaction *aTransaction)
-{
- NS_ENSURE_TRUE(aTransaction, NS_ERROR_NULL_POINTER);
-
- bool doInterrupt = false;
-
- nsresult rv = WillDoNotify(aTransaction, &doInterrupt);
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (doInterrupt) {
- return NS_OK;
- }
-
- rv = BeginTransaction(aTransaction, nullptr);
- if (NS_FAILED(rv)) {
- DidDoNotify(aTransaction, rv);
- return rv;
- }
-
- rv = EndTransaction(false);
-
- nsresult rv2 = DidDoNotify(aTransaction, rv);
- if (NS_SUCCEEDED(rv)) {
- rv = rv2;
- }
-
- // XXX The result of EndTransaction() or DidDoNotify() if EndTransaction()
- // succeeded.
- return rv;
-}
-
-NS_IMETHODIMP
-nsTransactionManager::UndoTransaction()
-{
- // It is illegal to call UndoTransaction() while the transaction manager is
- // executing a transaction's DoTransaction() method! If this happens,
- // the UndoTransaction() request is ignored, and we return NS_ERROR_FAILURE.
- if (!mDoStack.IsEmpty()) {
- return NS_ERROR_FAILURE;
- }
-
- // Peek at the top of the undo stack. Don't remove the transaction
- // until it has successfully completed.
- RefPtr<nsTransactionItem> tx = mUndoStack.Peek();
- if (!tx) {
- // Bail if there's nothing on the stack.
- return NS_OK;
- }
-
- nsCOMPtr<nsITransaction> t = tx->GetTransaction();
- bool doInterrupt = false;
- nsresult rv = WillUndoNotify(t, &doInterrupt);
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (doInterrupt) {
- return NS_OK;
- }
-
- rv = tx->UndoTransaction(this);
- if (NS_SUCCEEDED(rv)) {
- tx = mUndoStack.Pop();
- mRedoStack.Push(tx.forget());
- }
-
- nsresult rv2 = DidUndoNotify(t, rv);
- if (NS_SUCCEEDED(rv)) {
- rv = rv2;
- }
-
- // XXX The result of UndoTransaction() or DidUndoNotify() if UndoTransaction()
- // succeeded.
- return rv;
-}
-
-NS_IMETHODIMP
-nsTransactionManager::RedoTransaction()
-{
- // It is illegal to call RedoTransaction() while the transaction manager is
- // executing a transaction's DoTransaction() method! If this happens,
- // the RedoTransaction() request is ignored, and we return NS_ERROR_FAILURE.
- if (!mDoStack.IsEmpty()) {
- return NS_ERROR_FAILURE;
- }
-
- // Peek at the top of the redo stack. Don't remove the transaction
- // until it has successfully completed.
- RefPtr<nsTransactionItem> tx = mRedoStack.Peek();
- if (!tx) {
- // Bail if there's nothing on the stack.
- return NS_OK;
- }
-
- nsCOMPtr<nsITransaction> t = tx->GetTransaction();
- bool doInterrupt = false;
- nsresult rv = WillRedoNotify(t, &doInterrupt);
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (doInterrupt) {
- return NS_OK;
- }
-
- rv = tx->RedoTransaction(this);
- if (NS_SUCCEEDED(rv)) {
- tx = mRedoStack.Pop();
- mUndoStack.Push(tx.forget());
- }
-
- nsresult rv2 = DidRedoNotify(t, rv);
- if (NS_SUCCEEDED(rv)) {
- rv = rv2;
- }
-
- // XXX The result of RedoTransaction() or DidRedoNotify() if RedoTransaction()
- // succeeded.
- return rv;
-}
-
-NS_IMETHODIMP
-nsTransactionManager::Clear()
-{
- nsresult rv = ClearRedoStack();
- if (NS_FAILED(rv)) {
- return rv;
- }
- return ClearUndoStack();
-}
-
-NS_IMETHODIMP
-nsTransactionManager::BeginBatch(nsISupports* aData)
-{
- // We can batch independent transactions together by simply pushing
- // a dummy transaction item on the do stack. This dummy transaction item
- // will be popped off the do stack, and then pushed on the undo stack
- // in EndBatch().
- bool doInterrupt = false;
- nsresult rv = WillBeginBatchNotify(&doInterrupt);
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (doInterrupt) {
- return NS_OK;
- }
-
- rv = BeginTransaction(0, aData);
-
- nsresult rv2 = DidBeginBatchNotify(rv);
- if (NS_SUCCEEDED(rv)) {
- rv = rv2;
- }
-
- // XXX The result of BeginTransaction() or DidBeginBatchNotify() if
- // BeginTransaction() succeeded.
- return rv;
-}
-
-NS_IMETHODIMP
-nsTransactionManager::EndBatch(bool aAllowEmpty)
-{
- // XXX: Need to add some mechanism to detect the case where the transaction
- // at the top of the do stack isn't the dummy transaction, so we can
- // throw an error!! This can happen if someone calls EndBatch() within
- // the DoTransaction() method of a transaction.
- //
- // For now, we can detect this case by checking the value of the
- // dummy transaction's mTransaction field. If it is our dummy
- // transaction, it should be nullptr. This may not be true in the
- // future when we allow users to execute a transaction when beginning
- // a batch!!!!
- RefPtr<nsTransactionItem> tx = mDoStack.Peek();
- nsCOMPtr<nsITransaction> ti;
- if (tx) {
- ti = tx->GetTransaction();
- }
- if (!tx || ti) {
- return NS_ERROR_FAILURE;
- }
-
- bool doInterrupt = false;
- nsresult rv = WillEndBatchNotify(&doInterrupt);
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (doInterrupt) {
- return NS_OK;
- }
-
- rv = EndTransaction(aAllowEmpty);
- nsresult rv2 = DidEndBatchNotify(rv);
- if (NS_SUCCEEDED(rv)) {
- rv = rv2;
- }
-
- // XXX The result of EndTransaction() or DidEndBatchNotify() if
- // EndTransaction() succeeded.
- return rv;
-}
-
-NS_IMETHODIMP
-nsTransactionManager::GetNumberOfUndoItems(int32_t *aNumItems)
-{
- *aNumItems = mUndoStack.GetSize();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTransactionManager::GetNumberOfRedoItems(int32_t *aNumItems)
-{
- *aNumItems = mRedoStack.GetSize();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTransactionManager::GetMaxTransactionCount(int32_t *aMaxCount)
-{
- NS_ENSURE_TRUE(aMaxCount, NS_ERROR_NULL_POINTER);
- *aMaxCount = mMaxTransactionCount;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTransactionManager::SetMaxTransactionCount(int32_t aMaxCount)
-{
- // It is illegal to call SetMaxTransactionCount() while the transaction
- // manager is executing a transaction's DoTransaction() method because
- // the undo and redo stacks might get pruned! If this happens, the
- // SetMaxTransactionCount() request is ignored, and we return
- // NS_ERROR_FAILURE.
- if (!mDoStack.IsEmpty()) {
- return NS_ERROR_FAILURE;
- }
-
- // If aMaxCount is less than zero, the user wants unlimited
- // levels of undo! No need to prune the undo or redo stacks!
- if (aMaxCount < 0) {
- mMaxTransactionCount = -1;
- return NS_OK;
- }
-
- // If aMaxCount is greater than the number of transactions that currently
- // exist on the undo and redo stack, there is no need to prune the
- // undo or redo stacks!
- int32_t numUndoItems = mUndoStack.GetSize();
- int32_t numRedoItems = mRedoStack.GetSize();
- int32_t total = numUndoItems + numRedoItems;
- if (aMaxCount > total) {
- mMaxTransactionCount = aMaxCount;
- return NS_OK;
- }
-
- // Try getting rid of some transactions on the undo stack! Start at
- // the bottom of the stack and pop towards the top.
- while (numUndoItems > 0 && (numRedoItems + numUndoItems) > aMaxCount) {
- RefPtr<nsTransactionItem> tx = mUndoStack.PopBottom();
- if (!tx) {
- return NS_ERROR_FAILURE;
- }
- --numUndoItems;
- }
-
- // If necessary, get rid of some transactions on the redo stack! Start at
- // the bottom of the stack and pop towards the top.
- while (numRedoItems > 0 && (numRedoItems + numUndoItems) > aMaxCount) {
- RefPtr<nsTransactionItem> tx = mRedoStack.PopBottom();
- if (!tx) {
- return NS_ERROR_FAILURE;
- }
- --numRedoItems;
- }
-
- mMaxTransactionCount = aMaxCount;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTransactionManager::PeekUndoStack(nsITransaction **aTransaction)
-{
- MOZ_ASSERT(aTransaction);
- *aTransaction = PeekUndoStack().take();
- return NS_OK;
-}
-
-already_AddRefed<nsITransaction>
-nsTransactionManager::PeekUndoStack()
-{
- RefPtr<nsTransactionItem> tx = mUndoStack.Peek();
- if (!tx) {
- return nullptr;
- }
- return tx->GetTransaction();
-}
-
-NS_IMETHODIMP
-nsTransactionManager::PeekRedoStack(nsITransaction** aTransaction)
-{
- MOZ_ASSERT(aTransaction);
- *aTransaction = PeekRedoStack().take();
- return NS_OK;
-}
-
-already_AddRefed<nsITransaction>
-nsTransactionManager::PeekRedoStack()
-{
- RefPtr<nsTransactionItem> tx = mRedoStack.Peek();
- if (!tx) {
- return nullptr;
- }
- return tx->GetTransaction();
-}
-
-NS_IMETHODIMP
-nsTransactionManager::GetUndoList(nsITransactionList **aTransactionList)
-{
- NS_ENSURE_TRUE(aTransactionList, NS_ERROR_NULL_POINTER);
-
- *aTransactionList = (nsITransactionList *)new nsTransactionList(this, &mUndoStack);
- NS_IF_ADDREF(*aTransactionList);
- return (! *aTransactionList) ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
-}
-
-NS_IMETHODIMP
-nsTransactionManager::GetRedoList(nsITransactionList **aTransactionList)
-{
- NS_ENSURE_TRUE(aTransactionList, NS_ERROR_NULL_POINTER);
-
- *aTransactionList = (nsITransactionList *)new nsTransactionList(this, &mRedoStack);
- NS_IF_ADDREF(*aTransactionList);
- return (! *aTransactionList) ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
-}
-
-nsresult
-nsTransactionManager::BatchTopUndo()
-{
- if (mUndoStack.GetSize() < 2) {
- // Not enough transactions to merge into one batch.
- return NS_OK;
- }
-
- RefPtr<nsTransactionItem> lastUndo;
- RefPtr<nsTransactionItem> previousUndo;
-
- lastUndo = mUndoStack.Pop();
- MOZ_ASSERT(lastUndo, "There should be at least two transactions.");
-
- previousUndo = mUndoStack.Peek();
- MOZ_ASSERT(previousUndo, "There should be at least two transactions.");
-
- nsresult rv = previousUndo->AddChild(lastUndo);
-
- // Transfer data from the transactions that is going to be
- // merged to the transaction that it is being merged with.
- nsCOMArray<nsISupports>& lastData = lastUndo->GetData();
- nsCOMArray<nsISupports>& previousData = previousUndo->GetData();
- NS_ENSURE_TRUE(previousData.AppendObjects(lastData), NS_ERROR_UNEXPECTED);
- lastData.Clear();
- return rv;
-}
-
-nsresult
-nsTransactionManager::RemoveTopUndo()
-{
- if (mUndoStack.IsEmpty()) {
- return NS_OK;
- }
-
- RefPtr<nsTransactionItem> lastUndo = mUndoStack.Pop();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTransactionManager::AddListener(nsITransactionListener *aListener)
-{
- NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER);
- return mListeners.AppendObject(aListener) ? NS_OK : NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-nsTransactionManager::RemoveListener(nsITransactionListener *aListener)
-{
- NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER);
- return mListeners.RemoveObject(aListener) ? NS_OK : NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-nsTransactionManager::ClearUndoStack()
-{
- mUndoStack.Clear();
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTransactionManager::ClearRedoStack()
-{
- mRedoStack.Clear();
- return NS_OK;
-}
-
-nsresult
-nsTransactionManager::WillDoNotify(nsITransaction *aTransaction, bool *aInterrupt)
-{
- for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) {
- nsITransactionListener* listener = mListeners[i];
- NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE);
-
- nsresult rv = listener->WillDo(this, aTransaction, aInterrupt);
- if (NS_FAILED(rv) || *aInterrupt) {
- return rv;
- }
- }
- return NS_OK;
-}
-
-nsresult
-nsTransactionManager::DidDoNotify(nsITransaction *aTransaction, nsresult aDoResult)
-{
- for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) {
- nsITransactionListener* listener = mListeners[i];
- NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE);
-
- nsresult rv = listener->DidDo(this, aTransaction, aDoResult);
- if (NS_FAILED(rv)) {
- return rv;
- }
- }
- return NS_OK;
-}
-
-nsresult
-nsTransactionManager::WillUndoNotify(nsITransaction *aTransaction, bool *aInterrupt)
-{
- for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) {
- nsITransactionListener* listener = mListeners[i];
- NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE);
-
- nsresult rv = listener->WillUndo(this, aTransaction, aInterrupt);
- if (NS_FAILED(rv) || *aInterrupt) {
- return rv;
- }
- }
- return NS_OK;
-}
-
-nsresult
-nsTransactionManager::DidUndoNotify(nsITransaction *aTransaction, nsresult aUndoResult)
-{
- for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) {
- nsITransactionListener* listener = mListeners[i];
- NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE);
-
- nsresult rv = listener->DidUndo(this, aTransaction, aUndoResult);
- if (NS_FAILED(rv)) {
- return rv;
- }
- }
- return NS_OK;
-}
-
-nsresult
-nsTransactionManager::WillRedoNotify(nsITransaction *aTransaction, bool *aInterrupt)
-{
- for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) {
- nsITransactionListener* listener = mListeners[i];
- NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE);
-
- nsresult rv = listener->WillRedo(this, aTransaction, aInterrupt);
- if (NS_FAILED(rv) || *aInterrupt) {
- return rv;
- }
- }
- return NS_OK;
-}
-
-nsresult
-nsTransactionManager::DidRedoNotify(nsITransaction *aTransaction, nsresult aRedoResult)
-{
- for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) {
- nsITransactionListener* listener = mListeners[i];
- NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE);
-
- nsresult rv = listener->DidRedo(this, aTransaction, aRedoResult);
- if (NS_FAILED(rv)) {
- return rv;
- }
- }
- return NS_OK;
-}
-
-nsresult
-nsTransactionManager::WillBeginBatchNotify(bool *aInterrupt)
-{
- for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) {
- nsITransactionListener* listener = mListeners[i];
- NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE);
-
- nsresult rv = listener->WillBeginBatch(this, aInterrupt);
- if (NS_FAILED(rv) || *aInterrupt) {
- return rv;
- }
- }
- return NS_OK;
-}
-
-nsresult
-nsTransactionManager::DidBeginBatchNotify(nsresult aResult)
-{
- for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) {
- nsITransactionListener* listener = mListeners[i];
- NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE);
-
- nsresult rv = listener->DidBeginBatch(this, aResult);
- if (NS_FAILED(rv)) {
- return rv;
- }
- }
- return NS_OK;
-}
-
-nsresult
-nsTransactionManager::WillEndBatchNotify(bool *aInterrupt)
-{
- for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) {
- nsITransactionListener* listener = mListeners[i];
- NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE);
-
- nsresult rv = listener->WillEndBatch(this, aInterrupt);
- if (NS_FAILED(rv) || *aInterrupt) {
- return rv;
- }
- }
- return NS_OK;
-}
-
-nsresult
-nsTransactionManager::DidEndBatchNotify(nsresult aResult)
-{
- for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) {
- nsITransactionListener* listener = mListeners[i];
- NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE);
-
- nsresult rv = listener->DidEndBatch(this, aResult);
- if (NS_FAILED(rv)) {
- return rv;
- }
- }
- return NS_OK;
-}
-
-nsresult
-nsTransactionManager::WillMergeNotify(nsITransaction *aTop, nsITransaction *aTransaction, bool *aInterrupt)
-{
- for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) {
- nsITransactionListener* listener = mListeners[i];
- NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE);
-
- nsresult rv = listener->WillMerge(this, aTop, aTransaction, aInterrupt);
- if (NS_FAILED(rv) || *aInterrupt) {
- return rv;
- }
- }
- return NS_OK;
-}
-
-nsresult
-nsTransactionManager::DidMergeNotify(nsITransaction *aTop,
- nsITransaction *aTransaction,
- bool aDidMerge,
- nsresult aMergeResult)
-{
- for (int32_t i = 0, lcount = mListeners.Count(); i < lcount; i++) {
- nsITransactionListener* listener = mListeners[i];
- NS_ENSURE_TRUE(listener, NS_ERROR_FAILURE);
-
- nsresult rv =
- listener->DidMerge(this, aTop, aTransaction, aDidMerge, aMergeResult);
- if (NS_FAILED(rv)) {
- return rv;
- }
- }
- return NS_OK;
-}
-
-nsresult
-nsTransactionManager::BeginTransaction(nsITransaction *aTransaction,
- nsISupports *aData)
-{
- // XXX: POSSIBLE OPTIMIZATION
- // We could use a factory that pre-allocates/recycles transaction items.
- RefPtr<nsTransactionItem> tx = new nsTransactionItem(aTransaction);
- if (!tx) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- if (aData) {
- nsCOMArray<nsISupports>& data = tx->GetData();
- data.AppendObject(aData);
- }
-
- mDoStack.Push(tx);
-
- nsresult rv = tx->DoTransaction();
- if (NS_FAILED(rv)) {
- tx = mDoStack.Pop();
- return rv;
- }
- return NS_OK;
-}
-
-nsresult
-nsTransactionManager::EndTransaction(bool aAllowEmpty)
-{
- RefPtr<nsTransactionItem> tx = mDoStack.Pop();
- if (!tx) {
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsITransaction> tint = tx->GetTransaction();
- if (!tint && !aAllowEmpty) {
- // If we get here, the transaction must be a dummy batch transaction
- // created by BeginBatch(). If it contains no children, get rid of it!
- int32_t nc = 0;
- tx->GetNumberOfChildren(&nc);
- if (!nc) {
- return NS_OK;
- }
- }
-
- // Check if the transaction is transient. If it is, there's nothing
- // more to do, just return.
- bool isTransient = false;
- nsresult rv = NS_OK;
- if (tint) {
- rv = tint->GetIsTransient(&isTransient);
- }
- if (NS_FAILED(rv) || isTransient || !mMaxTransactionCount) {
- // XXX: Should we be clearing the redo stack if the transaction
- // is transient and there is nothing on the do stack?
- return rv;
- }
-
- // Check if there is a transaction on the do stack. If there is,
- // the current transaction is a "sub" transaction, and should
- // be added to the transaction at the top of the do stack.
- RefPtr<nsTransactionItem> top = mDoStack.Peek();
- if (top) {
- return top->AddChild(tx); // XXX: What do we do if this fails?
- }
-
- // The transaction succeeded, so clear the redo stack.
- rv = ClearRedoStack();
- if (NS_FAILED(rv)) {
- // XXX: What do we do if this fails?
- }
-
- // Check if we can coalesce this transaction with the one at the top
- // of the undo stack.
- top = mUndoStack.Peek();
- if (tint && top) {
- bool didMerge = false;
- nsCOMPtr<nsITransaction> topTransaction = top->GetTransaction();
- if (topTransaction) {
- bool doInterrupt = false;
- rv = WillMergeNotify(topTransaction, tint, &doInterrupt);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!doInterrupt) {
- rv = topTransaction->Merge(tint, &didMerge);
- nsresult rv2 = DidMergeNotify(topTransaction, tint, didMerge, rv);
- if (NS_SUCCEEDED(rv)) {
- rv = rv2;
- }
- if (NS_FAILED(rv)) {
- // XXX: What do we do if this fails?
- }
- if (didMerge) {
- return rv;
- }
- }
- }
- }
-
- // Check to see if we've hit the max level of undo. If so,
- // pop the bottom transaction off the undo stack and release it!
- int32_t sz = mUndoStack.GetSize();
- if (mMaxTransactionCount > 0 && sz >= mMaxTransactionCount) {
- RefPtr<nsTransactionItem> overflow = mUndoStack.PopBottom();
- }
-
- // Push the transaction on the undo stack:
- mUndoStack.Push(tx.forget());
- return NS_OK;
-}
diff --git a/editor/txmgr/nsTransactionManager.h b/editor/txmgr/nsTransactionManager.h
deleted file mode 100644
index 17d21819f..000000000
--- a/editor/txmgr/nsTransactionManager.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsTransactionManager_h__
-#define nsTransactionManager_h__
-
-#include "nsCOMArray.h"
-#include "nsCOMPtr.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsTransactionStack.h"
-#include "nsISupportsImpl.h"
-#include "nsITransactionManager.h"
-#include "nsTransactionStack.h"
-#include "nsWeakReference.h"
-#include "nscore.h"
-
-class nsITransaction;
-class nsITransactionListener;
-
-/** implementation of a transaction manager object.
- *
- */
-class nsTransactionManager final : public nsITransactionManager
- , public nsSupportsWeakReference
-{
-private:
-
- int32_t mMaxTransactionCount;
- nsTransactionStack mDoStack;
- nsTransactionStack mUndoStack;
- nsTransactionStack mRedoStack;
- nsCOMArray<nsITransactionListener> mListeners;
-
- /** The default destructor.
- */
- virtual ~nsTransactionManager();
-
-public:
-
- /** The default constructor.
- */
- explicit nsTransactionManager(int32_t aMaxTransactionCount=-1);
-
- /* Macro for AddRef(), Release(), and QueryInterface() */
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsTransactionManager,
- nsITransactionManager)
-
- /* nsITransactionManager method implementations. */
- NS_DECL_NSITRANSACTIONMANAGER
-
- already_AddRefed<nsITransaction> PeekUndoStack();
- already_AddRefed<nsITransaction> PeekRedoStack();
-
- virtual nsresult WillDoNotify(nsITransaction *aTransaction, bool *aInterrupt);
- virtual nsresult DidDoNotify(nsITransaction *aTransaction, nsresult aExecuteResult);
- virtual nsresult WillUndoNotify(nsITransaction *aTransaction, bool *aInterrupt);
- virtual nsresult DidUndoNotify(nsITransaction *aTransaction, nsresult aUndoResult);
- virtual nsresult WillRedoNotify(nsITransaction *aTransaction, bool *aInterrupt);
- virtual nsresult DidRedoNotify(nsITransaction *aTransaction, nsresult aRedoResult);
- virtual nsresult WillBeginBatchNotify(bool *aInterrupt);
- virtual nsresult DidBeginBatchNotify(nsresult aResult);
- virtual nsresult WillEndBatchNotify(bool *aInterrupt);
- virtual nsresult DidEndBatchNotify(nsresult aResult);
- virtual nsresult WillMergeNotify(nsITransaction *aTop,
- nsITransaction *aTransaction,
- bool *aInterrupt);
- virtual nsresult DidMergeNotify(nsITransaction *aTop,
- nsITransaction *aTransaction,
- bool aDidMerge,
- nsresult aMergeResult);
-
-private:
-
- /* nsTransactionManager specific private methods. */
- virtual nsresult BeginTransaction(nsITransaction *aTransaction,
- nsISupports *aData);
- virtual nsresult EndTransaction(bool aAllowEmpty);
-};
-
-#endif // nsTransactionManager_h__
diff --git a/editor/txmgr/nsTransactionManagerCID.h b/editor/txmgr/nsTransactionManagerCID.h
deleted file mode 100644
index f65e98579..000000000
--- a/editor/txmgr/nsTransactionManagerCID.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsTransactionManagerCID_h__
-#define nsTransactionManagerCID_h__
-
-#define NS_TRANSACTIONMANAGER_CID \
-{ /* 9C8F9601-801A-11d2-98BA-00805F297D89 */ \
-0x9c8f9601, 0x801a, 0x11d2, \
-{ 0x98, 0xba, 0x0, 0x80, 0x5f, 0x29, 0x7d, 0x89 } }
-
-#endif /* nsTransactionManagerCID_h__ */
diff --git a/editor/txmgr/nsTransactionManagerFactory.cpp b/editor/txmgr/nsTransactionManagerFactory.cpp
deleted file mode 100644
index a4cbb5950..000000000
--- a/editor/txmgr/nsTransactionManagerFactory.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <stddef.h>
-
-#include "mozilla/Module.h"
-#include "mozilla/ModuleUtils.h"
-#include "nsID.h"
-#include "nsITransactionManager.h"
-#include "nsTransactionManager.h"
-#include "nsTransactionManagerCID.h"
-
-////////////////////////////////////////////////////////////////////////
-// Define the contructor function for the objects
-//
-// NOTE: This creates an instance of objects by using the default constructor
-//
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransactionManager)
-NS_DEFINE_NAMED_CID(NS_TRANSACTIONMANAGER_CID);
-
-static const mozilla::Module::CIDEntry kTxMgrCIDs[] = {
- { &kNS_TRANSACTIONMANAGER_CID, false, nullptr, nsTransactionManagerConstructor },
- { nullptr }
-};
-
-static const mozilla::Module::ContractIDEntry kTxMgrContracts[] = {
- { NS_TRANSACTIONMANAGER_CONTRACTID, &kNS_TRANSACTIONMANAGER_CID },
- { nullptr }
-};
-
-static const mozilla::Module kTxMgrModule = {
- mozilla::Module::kVersion,
- kTxMgrCIDs,
- kTxMgrContracts
-};
-NSMODULE_DEFN(nsTransactionManagerModule) = &kTxMgrModule;
diff --git a/editor/txmgr/nsTransactionStack.cpp b/editor/txmgr/nsTransactionStack.cpp
deleted file mode 100644
index febfa3110..000000000
--- a/editor/txmgr/nsTransactionStack.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsCOMPtr.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsISupportsUtils.h"
-#include "nsTransactionItem.h"
-#include "nsTransactionStack.h"
-#include "nscore.h"
-
-class nsTransactionStackDeallocator : public nsDequeFunctor {
- virtual void* operator() (void* aObject) {
- RefPtr<nsTransactionItem> releaseMe = dont_AddRef(static_cast<nsTransactionItem*>(aObject));
- return nullptr;
- }
-};
-
-nsTransactionStack::nsTransactionStack(Type aType)
- : nsDeque(new nsTransactionStackDeallocator())
- , mType(aType)
-{
-}
-
-nsTransactionStack::~nsTransactionStack()
-{
- Clear();
-}
-
-void
-nsTransactionStack::Push(nsTransactionItem* aTransactionItem)
-{
- if (!aTransactionItem) {
- return;
- }
-
- RefPtr<nsTransactionItem> item(aTransactionItem);
- Push(item.forget());
-}
-
-void
-nsTransactionStack::Push(already_AddRefed<nsTransactionItem> aTransactionItem)
-{
- RefPtr<nsTransactionItem> item(aTransactionItem);
- if (!item) {
- return;
- }
-
- nsDeque::Push(item.forget().take());
-}
-
-already_AddRefed<nsTransactionItem>
-nsTransactionStack::Pop()
-{
- RefPtr<nsTransactionItem> item =
- dont_AddRef(static_cast<nsTransactionItem*>(nsDeque::Pop()));
- return item.forget();
-}
-
-already_AddRefed<nsTransactionItem>
-nsTransactionStack::PopBottom()
-{
- RefPtr<nsTransactionItem> item =
- dont_AddRef(static_cast<nsTransactionItem*>(nsDeque::PopFront()));
- return item.forget();
-}
-
-already_AddRefed<nsTransactionItem>
-nsTransactionStack::Peek()
-{
- RefPtr<nsTransactionItem> item =
- static_cast<nsTransactionItem*>(nsDeque::Peek());
- return item.forget();
-}
-
-already_AddRefed<nsTransactionItem>
-nsTransactionStack::GetItem(int32_t aIndex)
-{
- if (aIndex < 0 || aIndex >= static_cast<int32_t>(nsDeque::GetSize())) {
- return nullptr;
- }
- RefPtr<nsTransactionItem> item =
- static_cast<nsTransactionItem*>(nsDeque::ObjectAt(aIndex));
- return item.forget();
-}
-
-void
-nsTransactionStack::Clear()
-{
- while (GetSize() != 0) {
- RefPtr<nsTransactionItem> item =
- mType == FOR_UNDO ? Pop() : PopBottom();
- }
-}
-
-void
-nsTransactionStack::DoTraverse(nsCycleCollectionTraversalCallback &cb)
-{
- int32_t size = GetSize();
- for (int32_t i = 0; i < size; ++i) {
- nsTransactionItem* item = static_cast<nsTransactionItem*>(nsDeque::ObjectAt(i));
- if (item) {
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "transaction stack mDeque[i]");
- cb.NoteNativeChild(item, NS_CYCLE_COLLECTION_PARTICIPANT(nsTransactionItem));
- }
- }
-}
diff --git a/editor/txmgr/nsTransactionStack.h b/editor/txmgr/nsTransactionStack.h
deleted file mode 100644
index f6f6c3a2e..000000000
--- a/editor/txmgr/nsTransactionStack.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsTransactionStack_h__
-#define nsTransactionStack_h__
-
-#include "nsDeque.h"
-
-class nsCycleCollectionTraversalCallback;
-class nsTransactionItem;
-
-class nsTransactionStack : private nsDeque
-{
-public:
- enum Type { FOR_UNDO, FOR_REDO };
-
- explicit nsTransactionStack(Type aType);
- ~nsTransactionStack();
-
- void Push(nsTransactionItem *aTransactionItem);
- void Push(already_AddRefed<nsTransactionItem> aTransactionItem);
- already_AddRefed<nsTransactionItem> Pop();
- already_AddRefed<nsTransactionItem> PopBottom();
- already_AddRefed<nsTransactionItem> Peek();
- already_AddRefed<nsTransactionItem> GetItem(int32_t aIndex);
- void Clear();
- int32_t GetSize() const { return static_cast<int32_t>(nsDeque::GetSize()); }
- bool IsEmpty() const { return GetSize() == 0; }
-
- void DoUnlink() { Clear(); }
- void DoTraverse(nsCycleCollectionTraversalCallback &cb);
-
-private:
- const Type mType;
-};
-
-#endif // nsTransactionStack_h__
diff --git a/editor/txmgr/tests/TestTXMgr.cpp b/editor/txmgr/tests/TestTXMgr.cpp
deleted file mode 100644
index 4e77aae7f..000000000
--- a/editor/txmgr/tests/TestTXMgr.cpp
+++ /dev/null
@@ -1,4478 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "TestHarness.h"
-
-#include "nsITransactionManager.h"
-#include "nsComponentManagerUtils.h"
-#include "mozilla/Likely.h"
-
-static int32_t sConstructorCount = 0;
-static int32_t sDestructorCount = 0;
-static int32_t *sDestructorOrderArr = 0;
-static int32_t sDoCount = 0;
-static int32_t *sDoOrderArr = 0;
-static int32_t sUndoCount = 0;
-static int32_t *sUndoOrderArr = 0;
-static int32_t sRedoCount = 0;
-static int32_t *sRedoOrderArr = 0;
-
-// #define ENABLE_DEBUG_PRINTFS 1
-
-int32_t sSimpleTestDestructorOrderArr[] = {
- 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 1, 22, 23, 24, 25, 26, 27, 28,
- 29, 30, 31, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- 53, 54, 55, 56, 57, 58, 59, 60, 61, 41, 40, 62, 39, 38,
- 37, 36, 35, 34, 33, 32, 68, 63, 64, 65, 66, 67, 69, 71,
- 70, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
- 99, 100, 101, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 131,
- 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117,
- 116, 115, 114, 113, 112 };
-
-int32_t sSimpleTestDoOrderArr[] = {
- 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, 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, 52, 53, 54, 55, 56,
- 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
- 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
- 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
- 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
- 127, 128, 129, 130, 131 };
-
-int32_t sSimpleTestUndoOrderArr[] = {
- 41, 40, 39, 38, 62, 39, 38, 37, 69, 71, 70, 111, 110, 109,
- 108, 107, 106, 105, 104, 103, 102, 131, 130, 129, 128, 127, 126, 125,
- 124, 123, 122 };
-
-static int32_t sSimpleTestRedoOrderArr[] = {
- 38, 39, 70 };
-
-int32_t sAggregateTestDestructorOrderArr[] = {
- 14, 13, 12, 11, 10, 9, 8, 21, 20, 19, 18, 17, 16, 15,
- 28, 27, 26, 25, 24, 23, 22, 35, 34, 33, 32, 31, 30, 29,
- 42, 41, 40, 39, 38, 37, 36, 49, 48, 47, 46, 45, 44, 43,
- 56, 55, 54, 53, 52, 51, 50, 63, 62, 61, 60, 59, 58, 57,
- 70, 69, 68, 67, 66, 65, 64, 77, 76, 75, 74, 73, 72, 71,
- 84, 83, 82, 81, 80, 79, 78, 91, 90, 89, 88, 87, 86, 85,
- 98, 97, 96, 95, 94, 93, 92, 105, 104, 103, 102, 101, 100, 99,
- 112, 111, 110, 109, 108, 107, 106, 119, 118, 117, 116, 115, 114, 113,
- 126, 125, 124, 123, 122, 121, 120, 133, 132, 131, 130, 129, 128, 127,
- 140, 139, 138, 137, 136, 135, 134, 147, 146, 145, 144, 143, 142, 141,
- 7, 6, 5, 4, 3, 2, 1, 154, 153, 152, 151, 150, 149, 148,
- 161, 160, 159, 158, 157, 156, 155, 168, 167, 166, 165, 164, 163, 162,
- 175, 174, 173, 172, 171, 170, 169, 182, 181, 180, 179, 178, 177, 176,
- 189, 188, 187, 186, 185, 184, 183, 196, 195, 194, 193, 192, 191, 190,
- 203, 202, 201, 200, 199, 198, 197, 210, 209, 208, 207, 206, 205, 204,
- 217, 216, 215, 214, 213, 212, 211, 294, 293, 292, 291, 290, 289, 288,
- 301, 300, 299, 298, 297, 296, 295, 308, 307, 306, 305, 304, 303, 302,
- 315, 314, 313, 312, 311, 310, 309, 322, 321, 320, 319, 318, 317, 316,
- 329, 328, 327, 326, 325, 324, 323, 336, 335, 334, 333, 332, 331, 330,
- 343, 342, 341, 340, 339, 338, 337, 350, 349, 348, 347, 346, 345, 344,
- 357, 356, 355, 354, 353, 352, 351, 364, 363, 362, 361, 360, 359, 358,
- 371, 370, 369, 368, 367, 366, 365, 378, 377, 376, 375, 374, 373, 372,
- 385, 384, 383, 382, 381, 380, 379, 392, 391, 390, 389, 388, 387, 386,
- 399, 398, 397, 396, 395, 394, 393, 406, 405, 404, 403, 402, 401, 400,
- 413, 412, 411, 410, 409, 408, 407, 420, 419, 418, 417, 416, 415, 414,
- 427, 426, 425, 424, 423, 422, 421, 287, 286, 285, 284, 283, 282, 281,
- 280, 279, 278, 277, 276, 275, 274, 434, 433, 432, 431, 430, 429, 428,
- 273, 272, 271, 270, 269, 268, 267, 266, 265, 264, 263, 262, 261, 260,
- 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 247, 246,
- 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232,
- 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218,
- 472, 471, 470, 441, 440, 439, 438, 437, 436, 435, 448, 447, 446, 445,
- 444, 443, 442, 455, 454, 453, 452, 451, 450, 449, 462, 461, 460, 459,
- 458, 457, 456, 469, 468, 467, 466, 465, 464, 463, 479, 478, 477, 476,
- 475, 474, 473, 493, 492, 491, 490, 489, 488, 487, 486, 485, 484, 483,
- 482, 481, 480, 496, 497, 495, 499, 500, 498, 494, 503, 504, 502, 506,
- 507, 505, 501, 510, 511, 509, 513, 514, 512, 508, 517, 518, 516, 520,
- 521, 519, 515, 524, 525, 523, 527, 528, 526, 522, 531, 532, 530, 534,
- 535, 533, 529, 538, 539, 537, 541, 542, 540, 536, 545, 546, 544, 548,
- 549, 547, 543, 552, 553, 551, 555, 556, 554, 550, 559, 560, 558, 562,
- 563, 561, 557, 566, 567, 565, 569, 570, 568, 564, 573, 574, 572, 576,
- 577, 575, 571, 580, 581, 579, 583, 584, 582, 578, 587, 588, 586, 590,
- 591, 589, 585, 594, 595, 593, 597, 598, 596, 592, 601, 602, 600, 604,
- 605, 603, 599, 608, 609, 607, 611, 612, 610, 606, 615, 616, 614, 618,
- 619, 617, 613, 622, 623, 621, 625, 626, 624, 620, 629, 630, 628, 632,
- 633, 631, 627, 640, 639, 638, 637, 636, 635, 634, 647, 646, 645, 644,
- 643, 642, 641, 654, 653, 652, 651, 650, 649, 648, 661, 660, 659, 658,
- 657, 656, 655, 668, 667, 666, 665, 664, 663, 662, 675, 674, 673, 672,
- 671, 670, 669, 682, 681, 680, 679, 678, 677, 676, 689, 688, 687, 686,
- 685, 684, 683, 696, 695, 694, 693, 692, 691, 690, 703, 702, 701, 700,
- 699, 698, 697, 773, 772, 771, 770, 769, 768, 767, 766, 765, 764, 763,
- 762, 761, 760, 759, 758, 757, 756, 755, 754, 753, 752, 751, 750, 749,
- 748, 747, 746, 745, 744, 743, 742, 741, 740, 739, 738, 737, 736, 735,
- 734, 733, 732, 731, 730, 729, 728, 727, 726, 725, 724, 723, 722, 721,
- 720, 719, 718, 717, 716, 715, 714, 713, 712, 711, 710, 709, 708, 707,
- 706, 705, 704, 913, 912, 911, 910, 909, 908, 907, 906, 905, 904, 903,
- 902, 901, 900, 899, 898, 897, 896, 895, 894, 893, 892, 891, 890, 889,
- 888, 887, 886, 885, 884, 883, 882, 881, 880, 879, 878, 877, 876, 875,
- 874, 873, 872, 871, 870, 869, 868, 867, 866, 865, 864, 863, 862, 861,
- 860, 859, 858, 857, 856, 855, 854, 853, 852, 851, 850, 849, 848, 847,
- 846, 845, 844, 843, 842, 841, 840, 839, 838, 837, 836, 835, 834, 833,
- 832, 831, 830, 829, 828, 827, 826, 825, 824, 823, 822, 821, 820, 819,
- 818, 817, 816, 815, 814, 813, 812, 811, 810, 809, 808, 807, 806, 805,
- 804, 803, 802, 801, 800, 799, 798, 797, 796, 795, 794, 793, 792, 791,
- 790, 789, 788, 787, 786, 785, 784, 783, 782, 781, 780, 779, 778, 777,
- 776, 775, 774 };
-
-int32_t sAggregateTestDoOrderArr[] = {
- 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, 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, 52, 53, 54, 55, 56,
- 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
- 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
- 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
- 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
- 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
- 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
- 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
- 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
- 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
- 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
- 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
- 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
- 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
- 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266,
- 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280,
- 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
- 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
- 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322,
- 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336,
- 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350,
- 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364,
- 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378,
- 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392,
- 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406,
- 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420,
- 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434,
- 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448,
- 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462,
- 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476,
- 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490,
- 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504,
- 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518,
- 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532,
- 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546,
- 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560,
- 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574,
- 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588,
- 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602,
- 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616,
- 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630,
- 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644,
- 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658,
- 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672,
- 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686,
- 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700,
- 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714,
- 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728,
- 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742,
- 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756,
- 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770,
- 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784,
- 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798,
- 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812,
- 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826,
- 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840,
- 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854,
- 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868,
- 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882,
- 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896,
- 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910,
- 911, 912, 913 };
-
-int32_t sAggregateTestUndoOrderArr[] = {
- 287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274,
- 273, 272, 271, 270, 269, 268, 267, 266, 265, 264, 263, 262, 261, 260,
- 434, 433, 432, 431, 430, 429, 428, 273, 272, 271, 270, 269, 268, 267,
- 266, 265, 264, 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253,
- 479, 478, 477, 476, 475, 493, 492, 491, 490, 489, 488, 487, 486, 485,
- 484, 483, 482, 481, 480, 485, 484, 483, 482, 481, 480, 773, 772, 771,
- 770, 769, 768, 767, 766, 765, 764, 763, 762, 761, 760, 759, 758, 757,
- 756, 755, 754, 753, 752, 751, 750, 749, 748, 747, 746, 745, 744, 743,
- 742, 741, 740, 739, 738, 737, 736, 735, 734, 733, 732, 731, 730, 729,
- 728, 727, 726, 725, 724, 723, 722, 721, 720, 719, 718, 717, 716, 715,
- 714, 713, 712, 711, 710, 709, 708, 707, 706, 705, 704, 913, 912, 911,
- 910, 909, 908, 907, 906, 905, 904, 903, 902, 901, 900, 899, 898, 897,
- 896, 895, 894, 893, 892, 891, 890, 889, 888, 887, 886, 885, 884, 883,
- 882, 881, 880, 879, 878, 877, 876, 875, 874, 873, 872, 871, 870, 869,
- 868, 867, 866, 865, 864, 863, 862, 861, 860, 859, 858, 857, 856, 855,
- 854, 853, 852, 851, 850, 849, 848, 847, 846, 845, 844 };
-
-int32_t sAggregateTestRedoOrderArr[] = {
- 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
- 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486 };
-
-int32_t sSimpleBatchTestDestructorOrderArr[] = {
- 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 38, 39, 40, 43, 42, 41, 64, 63, 62, 61, 60,
- 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46,
- 45, 44, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9,
- 8, 7, 6, 5, 4, 3, 2, 1, 65, 67, 66, 68, 69, 70,
- 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- 85, 86, 87, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97,
- 96, 95, 94, 93, 92, 91, 90, 89, 88 };
-
-int32_t sSimpleBatchTestDoOrderArr[] = {
- 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, 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, 52, 53, 54, 55, 56,
- 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
- 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
- 99, 100, 101, 102, 103, 104, 105, 106, 107 };
-
-int32_t sSimpleBatchTestUndoOrderArr[] = {
- 43, 42, 41, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,
- 9, 8, 7, 6, 5, 4, 3, 2, 1, 43, 42, 41, 63, 62,
- 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48,
- 47, 46, 45, 44, 65, 67, 66, 107, 106, 105, 104, 103, 102, 101,
- 100, 99, 98 };
-
-int32_t sSimpleBatchTestRedoOrderArr[] = {
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 41, 42, 43, 66 };
-
-int32_t sAggregateBatchTestDestructorOrderArr[] = {
- 147, 146, 145, 144, 143, 142, 141, 154, 153, 152, 151, 150, 149, 148,
- 161, 160, 159, 158, 157, 156, 155, 168, 167, 166, 165, 164, 163, 162,
- 175, 174, 173, 172, 171, 170, 169, 182, 181, 180, 179, 178, 177, 176,
- 189, 188, 187, 186, 185, 184, 183, 196, 195, 194, 193, 192, 191, 190,
- 203, 202, 201, 200, 199, 198, 197, 210, 209, 208, 207, 206, 205, 204,
- 217, 216, 215, 214, 213, 212, 211, 224, 223, 222, 221, 220, 219, 218,
- 231, 230, 229, 228, 227, 226, 225, 238, 237, 236, 235, 234, 233, 232,
- 245, 244, 243, 242, 241, 240, 239, 252, 251, 250, 249, 248, 247, 246,
- 259, 258, 257, 256, 255, 254, 253, 266, 265, 264, 263, 262, 261, 260,
- 273, 272, 271, 270, 269, 268, 267, 280, 279, 278, 277, 276, 275, 274,
- 301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 288,
- 287, 286, 285, 284, 283, 282, 281, 444, 443, 442, 441, 440, 439, 438,
- 437, 436, 435, 434, 433, 432, 431, 430, 429, 428, 427, 426, 425, 424,
- 423, 422, 421, 420, 419, 418, 417, 416, 415, 414, 413, 412, 411, 410,
- 409, 408, 407, 406, 405, 404, 403, 402, 401, 400, 399, 398, 397, 396,
- 395, 394, 393, 392, 391, 390, 389, 388, 387, 386, 385, 384, 383, 382,
- 381, 380, 379, 378, 377, 376, 375, 374, 373, 372, 371, 370, 369, 368,
- 367, 366, 365, 364, 363, 362, 361, 360, 359, 358, 357, 356, 355, 354,
- 353, 352, 351, 350, 349, 348, 347, 346, 345, 344, 343, 342, 341, 340,
- 339, 338, 337, 336, 335, 334, 333, 332, 331, 330, 329, 328, 327, 326,
- 325, 324, 323, 322, 321, 320, 319, 318, 317, 316, 315, 314, 313, 312,
- 311, 310, 309, 308, 307, 306, 305, 304, 303, 302, 140, 139, 138, 137,
- 136, 135, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123,
- 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109,
- 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95,
- 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81,
- 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67,
- 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53,
- 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39,
- 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25,
- 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11,
- 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 451, 450, 449, 448,
- 447, 446, 445, 465, 464, 463, 462, 461, 460, 459, 458, 457, 456, 455,
- 454, 453, 452, 468, 469, 467, 471, 472, 470, 466, 475, 476, 474, 478,
- 479, 477, 473, 482, 483, 481, 485, 486, 484, 480, 489, 490, 488, 492,
- 493, 491, 487, 496, 497, 495, 499, 500, 498, 494, 503, 504, 502, 506,
- 507, 505, 501, 510, 511, 509, 513, 514, 512, 508, 517, 518, 516, 520,
- 521, 519, 515, 524, 525, 523, 527, 528, 526, 522, 531, 532, 530, 534,
- 535, 533, 529, 538, 539, 537, 541, 542, 540, 536, 545, 546, 544, 548,
- 549, 547, 543, 552, 553, 551, 555, 556, 554, 550, 559, 560, 558, 562,
- 563, 561, 557, 566, 567, 565, 569, 570, 568, 564, 573, 574, 572, 576,
- 577, 575, 571, 580, 581, 579, 583, 584, 582, 578, 587, 588, 586, 590,
- 591, 589, 585, 594, 595, 593, 597, 598, 596, 592, 601, 602, 600, 604,
- 605, 603, 599, 745, 744, 743, 742, 741, 740, 739, 738, 737, 736, 735,
- 734, 733, 732, 731, 730, 729, 728, 727, 726, 725, 724, 723, 722, 721,
- 720, 719, 718, 717, 716, 715, 714, 713, 712, 711, 710, 709, 708, 707,
- 706, 705, 704, 703, 702, 701, 700, 699, 698, 697, 696, 695, 694, 693,
- 692, 691, 690, 689, 688, 687, 686, 685, 684, 683, 682, 681, 680, 679,
- 678, 677, 676, 675, 674, 673, 672, 671, 670, 669, 668, 667, 666, 665,
- 664, 663, 662, 661, 660, 659, 658, 657, 656, 655, 654, 653, 652, 651,
- 650, 649, 648, 647, 646, 645, 644, 643, 642, 641, 640, 639, 638, 637,
- 636, 635, 634, 633, 632, 631, 630, 629, 628, 627, 626, 625, 624, 623,
- 622, 621, 620, 619, 618, 617, 616, 615, 614, 613, 612, 611, 610, 609,
- 608, 607, 606 };
-
-int32_t sAggregateBatchTestDoOrderArr[] = {
- 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, 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, 52, 53, 54, 55, 56,
- 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
- 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
- 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
- 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
- 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
- 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
- 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
- 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
- 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
- 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
- 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
- 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
- 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
- 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266,
- 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280,
- 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
- 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
- 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322,
- 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336,
- 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350,
- 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364,
- 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378,
- 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392,
- 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406,
- 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420,
- 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434,
- 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448,
- 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462,
- 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476,
- 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490,
- 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504,
- 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518,
- 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532,
- 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546,
- 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560,
- 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574,
- 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588,
- 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602,
- 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616,
- 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630,
- 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644,
- 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658,
- 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672,
- 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686,
- 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700,
- 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714,
- 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728,
- 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742,
- 743, 744, 745 };
-
-int32_t sAggregateBatchTestUndoOrderArr[] = {
- 301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 288,
- 287, 286, 285, 284, 283, 282, 281, 140, 139, 138, 137, 136, 135, 134,
- 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120,
- 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106,
- 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92,
- 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78,
- 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64,
- 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50,
- 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36,
- 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22,
- 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8,
- 7, 6, 5, 4, 3, 2, 1, 301, 300, 299, 298, 297, 296, 295,
- 294, 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, 283, 282, 281,
- 441, 440, 439, 438, 437, 436, 435, 434, 433, 432, 431, 430, 429, 428,
- 427, 426, 425, 424, 423, 422, 421, 420, 419, 418, 417, 416, 415, 414,
- 413, 412, 411, 410, 409, 408, 407, 406, 405, 404, 403, 402, 401, 400,
- 399, 398, 397, 396, 395, 394, 393, 392, 391, 390, 389, 388, 387, 386,
- 385, 384, 383, 382, 381, 380, 379, 378, 377, 376, 375, 374, 373, 372,
- 371, 370, 369, 368, 367, 366, 365, 364, 363, 362, 361, 360, 359, 358,
- 357, 356, 355, 354, 353, 352, 351, 350, 349, 348, 347, 346, 345, 344,
- 343, 342, 341, 340, 339, 338, 337, 336, 335, 334, 333, 332, 331, 330,
- 329, 328, 327, 326, 325, 324, 323, 322, 321, 320, 319, 318, 317, 316,
- 315, 314, 313, 312, 311, 310, 309, 308, 307, 306, 305, 304, 303, 302,
- 451, 450, 449, 448, 447, 465, 464, 463, 462, 461, 460, 459, 458, 457,
- 456, 455, 454, 453, 452, 457, 456, 455, 454, 453, 452, 745, 744, 743,
- 742, 741, 740, 739, 738, 737, 736, 735, 734, 733, 732, 731, 730, 729,
- 728, 727, 726, 725, 724, 723, 722, 721, 720, 719, 718, 717, 716, 715,
- 714, 713, 712, 711, 710, 709, 708, 707, 706, 705, 704, 703, 702, 701,
- 700, 699, 698, 697, 696, 695, 694, 693, 692, 691, 690, 689, 688, 687,
- 686, 685, 684, 683, 682, 681, 680, 679, 678, 677, 676 };
-
-int32_t sAggregateBatchTestRedoOrderArr[] = {
- 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, 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, 52, 53, 54, 55, 56,
- 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
- 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
- 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
- 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
- 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
- 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
- 295, 296, 297, 298, 299, 300, 301, 448, 449, 450, 451, 452, 453, 454,
- 455, 456, 457, 458 };
-
-#define TEST_TXMGR_IF_RELEASE(tx) if (tx) tx->Release(); // Release but don't clear pointer!
-
-class TestTransaction : public nsITransaction
-{
-protected:
- virtual ~TestTransaction() {}
-
-public:
-
- TestTransaction() {}
-
- NS_DECL_ISUPPORTS
-};
-
-NS_IMPL_ISUPPORTS(TestTransaction, nsITransaction)
-
-class SimpleTransaction : public TestTransaction
-{
-protected:
-
-#define NONE_FLAG 0
-#define THROWS_DO_ERROR_FLAG 1
-#define THROWS_UNDO_ERROR_FLAG 2
-#define THROWS_REDO_ERROR_FLAG 4
-#define MERGE_FLAG 8
-#define TRANSIENT_FLAG 16
-#define BATCH_FLAG 32
-#define ALL_ERROR_FLAGS (THROWS_DO_ERROR_FLAG|THROWS_UNDO_ERROR_FLAG|THROWS_REDO_ERROR_FLAG)
-
- int32_t mVal;
- int32_t mFlags;
-
-public:
-
- explicit SimpleTransaction(int32_t aFlags=NONE_FLAG)
- : mVal(++sConstructorCount), mFlags(aFlags)
- {}
-
- virtual ~SimpleTransaction()
- {
- //
- // Make sure transactions are being destroyed in the order we expect!
- // Notice that we don't check to see if we go past the end of the array.
- // This is done on purpose since we want to crash if the order array is out
- // of date.
- //
- /* Disabled because the current cycle collector doesn't delete
- cycle collectable objects synchronously, nor doesn't guarantee any order.
- if (sDestructorOrderArr && mVal != sDestructorOrderArr[sDestructorCount]) {
- fail("~SimpleTransaction expected %d got %d.\n",
- mVal, sDestructorOrderArr[sDestructorCount]);
- exit(-1);
- }
- */
-
- ++sDestructorCount;
-
-#ifdef ENABLE_DEBUG_PRINTFS
- printf("\n~SimpleTransaction: %d - 0x%.8x\n", mVal, (int32_t)this);
-#endif // ENABLE_DEBUG_PRINTFS
-
- mVal = -1;
- }
-
- NS_IMETHOD DoTransaction()
- {
- //
- // Make sure DoTransaction() is called in the order we expect!
- // Notice that we don't check to see if we go past the end of the array.
- // This is done on purpose since we want to crash if the order array is out
- // of date.
- //
- if (sDoOrderArr && mVal != sDoOrderArr[sDoCount]) {
- fail("DoTransaction expected %d got %d.\n",
- mVal, sDoOrderArr[sDoCount]);
- exit(-1);
- }
-
- ++sDoCount;
-
-#ifdef ENABLE_DEBUG_PRINTFS
- printf("\nSimpleTransaction.DoTransaction: %d - 0x%.8x\n", mVal, (int32_t)this);
-#endif // ENABLE_DEBUG_PRINTFS
-
- return (mFlags & THROWS_DO_ERROR_FLAG) ? NS_ERROR_FAILURE : NS_OK;
- }
-
- NS_IMETHOD UndoTransaction()
- {
- //
- // Make sure UndoTransaction() is called in the order we expect!
- // Notice that we don't check to see if we go past the end of the array.
- // This is done on purpose since we want to crash if the order array is out
- // of date.
- //
- if (sUndoOrderArr && mVal != sUndoOrderArr[sUndoCount]) {
- fail("UndoTransaction expected %d got %d.\n",
- mVal, sUndoOrderArr[sUndoCount]);
- exit(-1);
- }
-
- ++sUndoCount;
-
-#ifdef ENABLE_DEBUG_PRINTFS
- printf("\nSimpleTransaction.Undo: %d - 0x%.8x\n", mVal, (int32_t)this);
-#endif // ENABLE_DEBUG_PRINTFS
-
- return (mFlags & THROWS_UNDO_ERROR_FLAG) ? NS_ERROR_FAILURE : NS_OK;
- }
-
- NS_IMETHOD RedoTransaction()
- {
- //
- // Make sure RedoTransaction() is called in the order we expect!
- // Notice that we don't check to see if we go past the end of the array.
- // This is done on purpose since we want to crash if the order array is out
- // of date.
- //
- if (sRedoOrderArr && mVal != sRedoOrderArr[sRedoCount]) {
- fail("RedoTransaction expected %d got %d.\n",
- mVal, sRedoOrderArr[sRedoCount]);
- exit(-1);
- }
-
- ++sRedoCount;
-
-#ifdef ENABLE_DEBUG_PRINTFS
- printf("\nSimpleTransaction.Redo: %d - 0x%.8x\n", mVal, (int32_t)this);
-#endif // ENABLE_DEBUG_PRINTFS
-
- return (mFlags & THROWS_REDO_ERROR_FLAG) ? NS_ERROR_FAILURE : NS_OK;
- }
-
- NS_IMETHOD GetIsTransient(bool *aIsTransient)
- {
- if (aIsTransient) {
- *aIsTransient = (mFlags & TRANSIENT_FLAG) ? true : false;
- }
- return NS_OK;
- }
-
- NS_IMETHOD Merge(nsITransaction *aTransaction, bool *aDidMerge)
- {
- if (aDidMerge) {
- *aDidMerge = (mFlags & MERGE_FLAG) ? true : false;
- }
- return NS_OK;
- }
-};
-
-class AggregateTransaction : public SimpleTransaction
-{
-private:
-
- AggregateTransaction(nsITransactionManager *aTXMgr, int32_t aLevel,
- int32_t aNumber, int32_t aMaxLevel,
- int32_t aNumChildrenPerNode,
- int32_t aFlags)
- {
- mLevel = aLevel;
- mNumber = aNumber;
- mTXMgr = aTXMgr;
- mFlags = aFlags & (~ALL_ERROR_FLAGS);
- mErrorFlags = aFlags & ALL_ERROR_FLAGS;
- mTXMgr = aTXMgr;
- mMaxLevel = aMaxLevel;
- mNumChildrenPerNode = aNumChildrenPerNode;
- }
-
- nsITransactionManager *mTXMgr;
-
- int32_t mLevel;
- int32_t mNumber;
- int32_t mErrorFlags;
-
- int32_t mMaxLevel;
- int32_t mNumChildrenPerNode;
-
-public:
-
- AggregateTransaction(nsITransactionManager *aTXMgr,
- int32_t aMaxLevel, int32_t aNumChildrenPerNode,
- int32_t aFlags=NONE_FLAG)
- {
- mLevel = 1;
- mNumber = 1;
- mFlags = aFlags & (~ALL_ERROR_FLAGS);
- mErrorFlags = aFlags & ALL_ERROR_FLAGS;
- mTXMgr = aTXMgr;
- mMaxLevel = aMaxLevel;
- mNumChildrenPerNode = aNumChildrenPerNode;
- }
-
- virtual ~AggregateTransaction()
- {
- // printf("~AggregateTransaction(0x%.8x) - %3d (%3d)\n", this, mLevel, mVal);
- }
-
- NS_IMETHOD DoTransaction()
- {
- if (mLevel >= mMaxLevel) {
- // Only leaf nodes can throw errors!
- mFlags |= mErrorFlags;
- }
-
- nsresult rv = SimpleTransaction::DoTransaction();
- if (NS_FAILED(rv)) {
- // fail("QueryInterface() failed for transaction level %d. (%d)\n",
- // mLevel, rv);
- return rv;
- }
-
- if (mLevel >= mMaxLevel) {
- return NS_OK;
- }
-
- if (mFlags & BATCH_FLAG) {
- rv = mTXMgr->BeginBatch(nullptr);
- if (NS_FAILED(rv)) {
- return rv;
- }
- }
-
- int32_t cLevel = mLevel + 1;
-
- for (int i = 1; i <= mNumChildrenPerNode; i++) {
- int32_t flags = mErrorFlags & THROWS_DO_ERROR_FLAG;
-
- if ((mErrorFlags & THROWS_REDO_ERROR_FLAG) && i == mNumChildrenPerNode) {
- // Make the rightmost leaf transaction throw the error!
- flags = THROWS_REDO_ERROR_FLAG;
- mErrorFlags = mErrorFlags & (~THROWS_REDO_ERROR_FLAG);
- } else if ((mErrorFlags & THROWS_UNDO_ERROR_FLAG) && i == 1) {
- // Make the leftmost leaf transaction throw the error!
- flags = THROWS_UNDO_ERROR_FLAG;
- mErrorFlags = mErrorFlags & (~THROWS_UNDO_ERROR_FLAG);
- }
-
- flags |= mFlags & BATCH_FLAG;
-
- AggregateTransaction *tximpl =
- new AggregateTransaction(mTXMgr, cLevel, i, mMaxLevel,
- mNumChildrenPerNode, flags);
-
- if (!tximpl) {
- fail("Failed to allocate AggregateTransaction %d, level %d. (%d)\n",
- i, mLevel, rv);
-
- if (mFlags & BATCH_FLAG) {
- mTXMgr->EndBatch(false);
- }
-
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- nsITransaction *tx = 0;
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction %d, level %d. (%d)\n",
- i, mLevel, rv);
-
- if (mFlags & BATCH_FLAG) {
- mTXMgr->EndBatch(false);
- }
- return rv;
- }
-
- rv = mTXMgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- // fail("Failed to execute transaction %d, level %d. (%d)\n",
- // i, mLevel, rv);
- tx->Release();
- if (mFlags & BATCH_FLAG) {
- mTXMgr->EndBatch(false);
- }
- return rv;
- }
- tx->Release();
- }
-
- if (mFlags & BATCH_FLAG) {
- mTXMgr->EndBatch(false);
- }
- return rv;
- }
-};
-
-class TestTransactionFactory
-{
-public:
- virtual TestTransaction *create(nsITransactionManager *txmgr, int32_t flags) = 0;
-};
-
-class SimpleTransactionFactory : public TestTransactionFactory
-{
-public:
-
- TestTransaction *create(nsITransactionManager *txmgr, int32_t flags)
- {
- return (TestTransaction *)new SimpleTransaction(flags);
- }
-};
-
-class AggregateTransactionFactory : public TestTransactionFactory
-{
-private:
-
- int32_t mMaxLevel;
- int32_t mNumChildrenPerNode;
- int32_t mFixedFlags;
-
-public:
-
- AggregateTransactionFactory(int32_t aMaxLevel, int32_t aNumChildrenPerNode,
- int32_t aFixedFlags=NONE_FLAG)
- : mMaxLevel(aMaxLevel), mNumChildrenPerNode(aNumChildrenPerNode),
- mFixedFlags(aFixedFlags)
- {
- }
-
- virtual TestTransaction *create(nsITransactionManager *txmgr, int32_t flags)
- {
- return (TestTransaction *)new AggregateTransaction(txmgr, mMaxLevel,
- mNumChildrenPerNode,
- flags | mFixedFlags);
- }
-};
-
-void
-reset_globals()
-{
- sConstructorCount = 0;
-
- sDestructorCount = 0;
- sDestructorOrderArr = 0;
-
- sDoCount = 0;
- sDoOrderArr = 0;
-
- sUndoCount = 0;
- sUndoOrderArr = 0;
-
- sRedoCount = 0;
- sRedoOrderArr = 0;
-}
-
-/**
- * Test behaviors in non-batch mode.
- **/
-nsresult
-quick_test(TestTransactionFactory *factory)
-{
- /*******************************************************************
- *
- * Create a transaction manager implementation:
- *
- *******************************************************************/
-
- nsresult rv;
- nsCOMPtr<nsITransactionManager> mgr =
- do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &rv);
- if (NS_FAILED(rv) || !mgr) {
- fail("Failed to create Transaction Manager instance.\n");
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- passed("Create transaction manager instance");
-
- /*******************************************************************
- *
- * Call DoTransaction() with a null transaction:
- *
- *******************************************************************/
-
- rv = mgr->DoTransaction(0);
- if (rv != NS_ERROR_NULL_POINTER) {
- fail("DoTransaction() returned unexpected error. (%d)\n", rv);
- return rv;
- }
-
- passed("Call DoTransaction() with null transaction");
-
- /*******************************************************************
- *
- * Call UndoTransaction() with an empty undo stack:
- *
- *******************************************************************/
-
- rv = mgr->UndoTransaction();
- if (NS_FAILED(rv)) {
- fail("Undo on empty undo stack failed. (%d)\n", rv);
- return rv;
- }
-
- passed("Call UndoTransaction() with empty undo stack");
-
- /*******************************************************************
- *
- * Call RedoTransaction() with an empty redo stack:
- *
- *******************************************************************/
-
- rv = mgr->RedoTransaction();
- if (NS_FAILED(rv)) {
- fail("Redo on empty redo stack failed. (%d)\n", rv);
- return rv;
- }
-
- passed("Call RedoTransaction() with empty redo stack");
-
- /*******************************************************************
- *
- * Call SetMaxTransactionCount(-1) with empty undo and redo stacks:
- *
- *******************************************************************/
-
- rv = mgr->SetMaxTransactionCount(-1);
- if (NS_FAILED(rv)) {
- fail("SetMaxTransactionCount(-1) failed. (%d)\n", rv);
- return rv;
- }
-
- passed("Call SetMaxTransactionCount(-1) with empty undo and redo stacks");
-
- /*******************************************************************
- *
- * Call SetMaxTransactionCount(0) with empty undo and redo stacks:
- *
- *******************************************************************/
-
- rv = mgr->SetMaxTransactionCount(0);
- if (NS_FAILED(rv)) {
- fail("SetMaxTransactionCount(0) failed. (%d)\n", rv);
- return rv;
- }
-
- passed("Call SetMaxTransactionCount(0) with empty undo and redo stacks");
-
- /*******************************************************************
- *
- * Call SetMaxTransactionCount(10) with empty undo and redo stacks:
- *
- *******************************************************************/
-
- rv = mgr->SetMaxTransactionCount(10);
- if (NS_FAILED(rv)) {
- fail("SetMaxTransactionCount(10) failed. (%d)\n", rv);
- return rv;
- }
-
- passed("Call SetMaxTransactionCount(10) with empty undo and redo stacks");
-
- /*******************************************************************
- *
- * Call Clear() with empty undo and redo stacks:
- *
- *******************************************************************/
-
- rv = mgr->Clear();
- if (NS_FAILED(rv)) {
- fail("Clear on empty undo and redo stack failed. (%d)\n", rv);
- return rv;
- }
-
- passed("Call Clear() with empty undo and redo stack");
-
- int32_t numitems;
-
- /*******************************************************************
- *
- * Call GetNumberOfUndoItems() with an empty undo stack:
- *
- *******************************************************************/
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Call GetNumberOfUndoItems() with empty undo stack");
-
- /*******************************************************************
- *
- * Call GetNumberOfRedoItems() with an empty redo stack:
- *
- *******************************************************************/
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Call GetNumberOfRedoItems() with empty redo stack");
-
- nsITransaction *tx;
-
- /*******************************************************************
- *
- * Call PeekUndoStack() with an empty undo stack:
- *
- *******************************************************************/
-
- tx = 0;
- rv = mgr->PeekUndoStack(&tx);
-
- TEST_TXMGR_IF_RELEASE(tx); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("PeekUndoStack() on empty undo stack failed. (%d)\n", rv);
- return rv;
- }
-
- if (tx) {
- fail("PeekUndoStack() on empty undo stack failed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Call PeekUndoStack() with empty undo stack");
-
- /*******************************************************************
- *
- * Call PeekRedoStack() with an empty undo stack:
- *
- *******************************************************************/
-
- tx = 0;
- rv = mgr->PeekRedoStack(&tx);
-
- TEST_TXMGR_IF_RELEASE(tx); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("PeekRedoStack() on empty redo stack failed. (%d)\n", rv);
- return rv;
- }
-
- if (tx) {
- fail("PeekRedoStack() on empty redo stack failed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Call PeekRedoStack() with empty undo stack");
-
- /*******************************************************************
- *
- * Call AddListener() with a null listener pointer:
- *
- *******************************************************************/
-
- rv = mgr->AddListener(0);
- if (rv != NS_ERROR_NULL_POINTER) {
- fail("AddListener() returned unexpected error. (%d)\n", rv);
- return rv;
- }
-
- passed("Call AddListener() with null listener");
-
- /*******************************************************************
- *
- * Call RemoveListener() with a null listener pointer:
- *
- *******************************************************************/
-
- rv = mgr->RemoveListener(0);
- if (rv != NS_ERROR_NULL_POINTER) {
- fail("RemoveListener() returned unexpected error. (%d)\n", rv);
- return rv;
- }
-
- passed("Call RemoveListener() with null listener");
-
- int32_t i;
- TestTransaction *tximpl;
- nsITransaction *u1, *u2;
- nsITransaction *r1, *r2;
-
- /*******************************************************************
- *
- * Test coalescing by executing a transaction that can merge any
- * command into itself. Then execute 20 transaction. Afterwards,
- * we should still have the first transaction sitting on the undo
- * stack. Then clear the undo and redo stacks.
- *
- *******************************************************************/
-
- rv = mgr->SetMaxTransactionCount(10);
- if (NS_FAILED(rv)) {
- fail("SetMaxTransactionCount(10) failed. (%d)\n", rv);
- return rv;
- }
-
-
- tximpl = factory->create(mgr, MERGE_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate initial transaction.\n");
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
-
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for initial transaction. (%d)\n",
- rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("Failed to execute initial transaction. (%d)\n", rv);
- return rv;
- }
-
- tx->Release();
-
- u1 = u2 = r1 = r2 = 0;
-
- rv = mgr->PeekUndoStack(&u1);
-
- TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (u1 != tx) {
- fail("Top of undo stack is different!. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->PeekRedoStack(&r1);
-
- TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- for (i = 1; i <= 20; i++) {
- tximpl = factory->create(mgr, NONE_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction %d.\n", i);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction %d. (%d)\n",
- i, rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("Failed to execute transaction %d. (%d)\n", i, rv);
- return rv;
- }
-
- tx->Release();
- }
-
- rv = mgr->PeekUndoStack(&u2);
-
- TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (u1 != u2) {
- fail("Top of undo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->PeekRedoStack(&r2);
-
- TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (r1 != r2) {
- fail("Top of redo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->Clear();
- if (NS_FAILED(rv)) {
- fail("Clear() failed. (%d)\n", rv);
- return rv;
- }
-
- passed("Test coalescing of transactions");
-
- /*******************************************************************
- *
- * Execute 20 transactions. Afterwards, we should have 10
- * transactions on the undo stack:
- *
- *******************************************************************/
-
- for (i = 1; i <= 20; i++) {
- tximpl = factory->create(mgr, NONE_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction %d.\n", i);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction %d. (%d)\n",
- i, rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("Failed to execute transaction %d. (%d)\n", i, rv);
- return rv;
- }
-
- tx->Release();
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 10 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 10) {
- fail("GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
-
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Execute 20 transactions");
-
- /*******************************************************************
- *
- * Execute 20 transient transactions. Afterwards, we should still
- * have the same 10 transactions on the undo stack:
- *
- *******************************************************************/
-
- u1 = u2 = r1 = r2 = 0;
-
- rv = mgr->PeekUndoStack(&u1);
-
- TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekRedoStack(&r1);
-
- TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- for (i = 1; i <= 20; i++) {
- tximpl = factory->create(mgr, TRANSIENT_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction %d.\n", i);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction %d. (%d)\n",
- i, rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("Failed to execute transaction %d. (%d)\n", i, rv);
- return rv;
- }
-
- tx->Release();
- }
-
- rv = mgr->PeekUndoStack(&u2);
-
- TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (u1 != u2) {
- fail("Top of undo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->PeekRedoStack(&r2);
-
- TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (r1 != r2) {
- fail("Top of redo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 10 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 10) {
- fail("GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Execute 20 transient transactions");
-
- /*******************************************************************
- *
- * Undo 4 transactions. Afterwards, we should have 6 transactions
- * on the undo stack, and 4 on the redo stack:
- *
- *******************************************************************/
-
- for (i = 1; i <= 4; i++) {
- rv = mgr->UndoTransaction();
- if (NS_FAILED(rv)) {
- fail("Failed to undo transaction %d. (%d)\n", i, rv);
- return rv;
- }
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 6 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 6) {
- fail("GetNumberOfUndoItems() expected 6 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on redo stack with 4 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 4) {
- fail("GetNumberOfRedoItems() expected 4 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Undo 4 transactions");
-
- /*******************************************************************
- *
- * Redo 2 transactions. Afterwards, we should have 8 transactions
- * on the undo stack, and 2 on the redo stack:
- *
- *******************************************************************/
-
- for (i = 1; i <= 2; ++i) {
- rv = mgr->RedoTransaction();
- if (NS_FAILED(rv)) {
- fail("Failed to redo transaction %d. (%d)\n", i, rv);
- return rv;
- }
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 8 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 8) {
- fail("GetNumberOfUndoItems() expected 8 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on redo stack with 2 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 2) {
- fail("GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Redo 2 transactions");
-
- /*******************************************************************
- *
- * Execute a new transaction. The redo stack should get pruned!
- *
- *******************************************************************/
-
- tximpl = factory->create(mgr, NONE_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction.\n");
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
-
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("Failed to execute transaction. (%d)\n", rv);
- return rv;
- }
-
- tx->Release();
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 9 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 9) {
- fail("GetNumberOfUndoItems() expected 9 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Check if new transactions prune the redo stack");
-
- /*******************************************************************
- *
- * Undo 4 transactions then clear the undo and redo stacks.
- *
- *******************************************************************/
-
- for (i = 1; i <= 4; ++i) {
- rv = mgr->UndoTransaction();
- if (NS_FAILED(rv)) {
- fail("Failed to undo transaction %d. (%d)\n", i, rv);
- return rv;
- }
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 5 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 5) {
- fail("GetNumberOfUndoItems() expected 5 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on redo stack with 4 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 4) {
- fail("GetNumberOfRedoItems() expected 4 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->Clear();
- if (NS_FAILED(rv)) {
- fail("Clear() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on cleared undo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on cleared redo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Undo 4 transactions then clear the undo and redo stacks");
-
- /*******************************************************************
- *
- * Execute 5 transactions.
- *
- *******************************************************************/
-
- for (i = 1; i <= 5; i++) {
- tximpl = factory->create(mgr, NONE_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction %d.\n", i);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction %d. (%d)\n",
- i, rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("Failed to execute transaction %d. (%d)\n", i, rv);
- return rv;
- }
-
- tx->Release();
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 5 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 5) {
- fail("GetNumberOfUndoItems() expected 5 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Execute 5 transactions");
-
- /*******************************************************************
- *
- * Test transaction DoTransaction() error:
- *
- *******************************************************************/
-
- tximpl = factory->create(mgr, THROWS_DO_ERROR_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction.\n");
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
-
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction. (%d)\n", rv);
- return rv;
- }
-
- u1 = u2 = r1 = r2 = 0;
-
- rv = mgr->PeekUndoStack(&u1);
-
- TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekRedoStack(&r1);
-
- TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (rv != NS_ERROR_FAILURE) {
- fail("DoTransaction() returned unexpected error. (%d)\n", rv);
- return rv;
- }
-
- tx->Release();
-
- rv = mgr->PeekUndoStack(&u2);
-
- TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (u1 != u2) {
- fail("Top of undo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->PeekRedoStack(&r2);
-
- TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (r1 != r2) {
- fail("Top of redo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
-
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 5 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 5) {
- fail("GetNumberOfUndoItems() expected 5 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on empty redo stack. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Test transaction DoTransaction() error");
-
- /*******************************************************************
- *
- * Test transaction UndoTransaction() error:
- *
- *******************************************************************/
-
- tximpl = factory->create(mgr, THROWS_UNDO_ERROR_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction.\n");
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
-
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("DoTransaction() returned unexpected error. (%d)\n", rv);
- return rv;
- }
-
- tx->Release();
-
- u1 = u2 = r1 = r2 = 0;
-
- rv = mgr->PeekUndoStack(&u1);
-
- TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekRedoStack(&r1);
-
- TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->UndoTransaction();
- if (rv != NS_ERROR_FAILURE) {
- fail("UndoTransaction() returned unexpected error. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekUndoStack(&u2);
-
- TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (u1 != u2) {
- fail("Top of undo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->PeekRedoStack(&r2);
-
- TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (r1 != r2) {
- fail("Top of redo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 6 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 6) {
- fail("GetNumberOfUndoItems() expected 6 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on empty redo stack. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Test transaction UndoTransaction() error");
-
- /*******************************************************************
- *
- * Test transaction RedoTransaction() error:
- *
- *******************************************************************/
-
- tximpl = factory->create(mgr, THROWS_REDO_ERROR_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction.\n");
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
-
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for RedoErrorTransaction. (%d)\n",
- rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
-
- if (NS_FAILED(rv)) {
- fail("DoTransaction() returned unexpected error. (%d)\n", rv);
- return rv;
- }
-
- tx->Release();
-
- //
- // Execute a normal transaction to be used in a later test:
- //
-
- tximpl = factory->create(mgr, NONE_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction.\n");
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
-
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("DoTransaction() returned unexpected error. (%d)\n", rv);
- return rv;
- }
-
- tx->Release();
-
- //
- // Undo the 2 transactions just executed.
- //
-
- for (i = 1; i <= 2; ++i) {
- rv = mgr->UndoTransaction();
- if (NS_FAILED(rv)) {
- fail("Failed to undo transaction %d. (%d)\n", i, rv);
- return rv;
- }
- }
-
- //
- // The RedoErrorTransaction should now be at the top of the redo stack!
- //
-
- u1 = u2 = r1 = r2 = 0;
-
- rv = mgr->PeekUndoStack(&u1);
-
- TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekRedoStack(&r1);
-
- TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->RedoTransaction();
- if (rv != NS_ERROR_FAILURE) {
- fail("RedoTransaction() returned unexpected error. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekUndoStack(&u2);
-
- TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (u1 != u2) {
- fail("Top of undo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->PeekRedoStack(&r2);
-
- TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (r1 != r2) {
- fail("Top of redo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 6 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 6) {
- fail("GetNumberOfUndoItems() expected 6 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on redo stack with 2 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 2) {
- fail("GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Test transaction RedoTransaction() error");
-
- /*******************************************************************
- *
- * Make sure that setting the transaction manager's max transaction
- * count to zero, clears both the undo and redo stacks, and executes
- * all new commands without pushing them on the undo stack!
- *
- *******************************************************************/
-
- rv = mgr->SetMaxTransactionCount(0);
- if (NS_FAILED(rv)) {
- fail("SetMaxTransactionCount(0) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- for (i = 1; i <= 20; i++) {
- tximpl = factory->create(mgr, NONE_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction %d.\n", i);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction %d. (%d)\n",
- i, rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("Failed to execute transaction %d. (%d)\n", i, rv);
- return rv;
- }
-
- tx->Release();
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
- }
-
- passed("Test max transaction count of zero");
-
- /*******************************************************************
- *
- * Make sure that setting the transaction manager's max transaction
- * count to something greater than the number of transactions on
- * both the undo and redo stacks causes no pruning of the stacks:
- *
- *******************************************************************/
-
- rv = mgr->SetMaxTransactionCount(-1);
- if (NS_FAILED(rv)) {
- fail("SetMaxTransactionCount(-1) failed. (%d)\n", rv);
- return rv;
- }
-
- // Push 20 transactions on the undo stack:
-
- for (i = 1; i <= 20; i++) {
- tximpl = factory->create(mgr, NONE_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction %d.\n", i);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction %d. (%d)\n",
- i, rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("Failed to execute transaction %d. (%d)\n", i, rv);
- return rv;
- }
-
- tx->Release();
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with %d items failed. (%d)\n",
- i, rv);
- return rv;
- }
-
- if (numitems != i) {
- fail("GetNumberOfUndoItems() expected %d got %d. (%d)\n",
- i, numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
- }
-
- for (i = 1; i <= 10; i++) {
- rv = mgr->UndoTransaction();
- if (NS_FAILED(rv)) {
- fail("Failed to undo transaction %d. (%d)\n", i, rv);
- return rv;
- }
- }
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on empty undo stack with 10 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 10) {
- fail("GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 10) {
- fail("GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- u1 = u2 = r1 = r2 = 0;
-
- rv = mgr->PeekUndoStack(&u1);
-
- TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekRedoStack(&r1);
-
- TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->SetMaxTransactionCount(25);
- if (NS_FAILED(rv)) {
- fail("SetMaxTransactionCount(25) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekUndoStack(&u2);
-
- TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (u1 != u2) {
- fail("Top of undo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->PeekRedoStack(&r2);
-
- TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (r1 != r2) {
- fail("Top of redo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 10 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 10) {
- fail("GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 10) {
- fail("GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Test SetMaxTransactionCount() greater than num stack items");
-
- /*******************************************************************
- *
- * Test undo stack pruning by setting the transaction
- * manager's max transaction count to a number lower than the
- * number of transactions on both the undo and redo stacks:
- *
- *******************************************************************/
-
- u1 = u2 = r1 = r2 = 0;
-
- rv = mgr->PeekUndoStack(&u1);
-
- TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekRedoStack(&r1);
-
- TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->SetMaxTransactionCount(15);
- if (NS_FAILED(rv)) {
- fail("SetMaxTransactionCount(15) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekUndoStack(&u2);
-
- TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (u1 != u2) {
- fail("Top of undo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->PeekRedoStack(&r2);
-
- TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (r1 != r2) {
- fail("Top of redo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 5 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 5) {
- fail("GetNumberOfUndoItems() expected 5 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 10) {
- fail("GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Test SetMaxTransactionCount() pruning undo stack");
-
- /*******************************************************************
- *
- * Test redo stack pruning by setting the transaction
- * manager's max transaction count to a number lower than the
- * number of transactions on both the undo and redo stacks:
- *
- *******************************************************************/
-
- u1 = u2 = r1 = r2 = 0;
-
- rv = mgr->PeekUndoStack(&u1);
-
- TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekRedoStack(&r1);
-
- TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->SetMaxTransactionCount(5);
- if (NS_FAILED(rv)) {
- fail("SetMaxTransactionCount(5) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekUndoStack(&u2);
-
- TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (u2) {
- fail("Unexpected item at top of undo stack. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->PeekRedoStack(&r2);
-
- TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (r1 != r2) {
- fail("Top of redo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 0) {
- fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on redo stack with 5 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 5) {
- fail("GetNumberOfRedoItems() expected 5 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Test SetMaxTransactionCount() pruning redo stack");
-
- /*******************************************************************
- *
- * Release the transaction manager. Any transactions on the undo
- * and redo stack should automatically be released:
- *
- *******************************************************************/
-
- rv = mgr->SetMaxTransactionCount(-1);
- if (NS_FAILED(rv)) {
- fail("SetMaxTransactionCount(-1) failed. (%d)\n", rv);
- return rv;
- }
-
- // Push 20 transactions on the undo stack:
-
- for (i = 1; i <= 20; i++) {
- tximpl = factory->create(mgr, NONE_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction %d.\n", i);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction %d. (%d)\n",
- i, rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("Failed to execute transaction %d. (%d)\n", i, rv);
- return rv;
- }
-
- tx->Release();
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with %d items failed. (%d)\n",
- i, rv);
- return rv;
- }
-
- if (numitems != i) {
- fail("GetNumberOfUndoItems() expected %d got %d. (%d)\n",
- i, numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
- }
-
- for (i = 1; i <= 10; i++) {
- rv = mgr->UndoTransaction();
- if (NS_FAILED(rv)) {
- fail("Failed to undo transaction %d. (%d)\n", i, rv);
- return rv;
- }
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 10 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 10) {
- fail("GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 10) {
- fail("GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->Clear();
- if (NS_FAILED(rv)) {
- fail("Clear() failed. (%d)\n", rv);
- return rv;
- }
-
- passed("Release the transaction manager");
-
- /*******************************************************************
- *
- * Make sure number of transactions created matches number of
- * transactions destroyed!
- *
- *******************************************************************/
-
- /* Disabled because the current cycle collector doesn't delete
- cycle collectable objects synchronously.
- if (sConstructorCount != sDestructorCount) {
- fail("Transaction constructor count (%d) != destructor count (%d).\n",
- sConstructorCount, sDestructorCount);
- return NS_ERROR_FAILURE;
- }*/
-
- passed("Number of transactions created and destroyed match");
- passed("%d transactions processed during quick test", sConstructorCount);
-
- return NS_OK;
-}
-
-nsresult
-simple_test()
-{
- /*******************************************************************
- *
- * Initialize globals for test.
- *
- *******************************************************************/
- reset_globals();
- sDestructorOrderArr = sSimpleTestDestructorOrderArr;
- sDoOrderArr = sSimpleTestDoOrderArr;
- sUndoOrderArr = sSimpleTestUndoOrderArr;
- sRedoOrderArr = sSimpleTestRedoOrderArr;
-
- /*******************************************************************
- *
- * Run the quick test.
- *
- *******************************************************************/
-
- printf("\n-----------------------------------------------------\n");
- printf("- Begin Simple Transaction Test:\n");
- printf("-----------------------------------------------------\n");
-
- SimpleTransactionFactory factory;
-
- return quick_test(&factory);
-}
-
-nsresult
-aggregation_test()
-{
- /*******************************************************************
- *
- * Initialize globals for test.
- *
- *******************************************************************/
-
- reset_globals();
- sDestructorOrderArr = sAggregateTestDestructorOrderArr;
- sDoOrderArr = sAggregateTestDoOrderArr;
- sUndoOrderArr = sAggregateTestUndoOrderArr;
- sRedoOrderArr = sAggregateTestRedoOrderArr;
-
- /*******************************************************************
- *
- * Run the quick test.
- *
- *******************************************************************/
-
- printf("\n-----------------------------------------------------\n");
- printf("- Begin Aggregate Transaction Test:\n");
- printf("-----------------------------------------------------\n");
-
- AggregateTransactionFactory factory(3, 2);
-
- return quick_test(&factory);
-}
-
-/**
- * Test behaviors in batch mode.
- **/
-nsresult
-quick_batch_test(TestTransactionFactory *factory)
-{
- /*******************************************************************
- *
- * Create a transaction manager implementation:
- *
- *******************************************************************/
-
- nsresult rv;
- nsCOMPtr<nsITransactionManager> mgr =
- do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &rv);
- if (NS_FAILED(rv) || !mgr) {
- fail("Failed to create Transaction Manager instance.\n");
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- passed("Create transaction manager instance");
-
- int32_t numitems;
-
- /*******************************************************************
- *
- * Make sure an unbalanced call to EndBatch(false) with empty undo stack
- * throws an error!
- *
- *******************************************************************/
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->EndBatch(false);
- if (rv != NS_ERROR_FAILURE) {
- fail("EndBatch(false) returned unexpected status. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Test unbalanced EndBatch(false) with empty undo stack");
-
- /*******************************************************************
- *
- * Make sure that an empty batch is not added to the undo stack
- * when it is closed.
- *
- *******************************************************************/
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->BeginBatch(nullptr);
- if (NS_FAILED(rv)) {
- fail("BeginBatch(nullptr) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->EndBatch(false);
- if (NS_FAILED(rv)) {
- fail("EndBatch(false) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Test empty batch");
-
- int32_t i;
- TestTransaction *tximpl;
- nsITransaction *tx;
-
- /*******************************************************************
- *
- * Execute 20 transactions. Afterwards, we should have 1
- * transaction on the undo stack:
- *
- *******************************************************************/
-
- rv = mgr->BeginBatch(nullptr);
- if (NS_FAILED(rv)) {
- fail("BeginBatch(nullptr) failed. (%d)\n", rv);
- return rv;
- }
-
- for (i = 1; i <= 20; i++) {
- tximpl = factory->create(mgr, NONE_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction %d.\n", i);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction %d. (%d)\n",
- i, rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("Failed to execute transaction %d. (%d)\n", i, rv);
- return rv;
- }
-
- tx->Release();
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 0) {
- fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->EndBatch(false);
- if (NS_FAILED(rv)) {
- fail("EndBatch(false) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Execute 20 batched transactions");
-
- nsITransaction *u1, *u2;
- nsITransaction *r1, *r2;
-
- /*******************************************************************
- *
- * Execute 20 transient transactions. Afterwards, we should still
- * have the same transaction on the undo stack:
- *
- *******************************************************************/
-
- u1 = u2 = r1 = r2 = 0;
-
- rv = mgr->PeekUndoStack(&u1);
-
- TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekRedoStack(&r1);
-
- TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->BeginBatch(nullptr);
- if (NS_FAILED(rv)) {
- fail("BeginBatch(nullptr) failed. (%d)\n", rv);
- return rv;
- }
-
- for (i = 1; i <= 20; i++) {
- tximpl = factory->create(mgr, TRANSIENT_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction %d.\n", i);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction %d. (%d)\n",
- i, rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("Failed to execute transaction %d. (%d)\n", i, rv);
- return rv;
- }
-
- tx->Release();
- }
-
- rv = mgr->EndBatch(false);
- if (NS_FAILED(rv)) {
- fail("EndBatch(false) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekUndoStack(&u2);
-
- TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (u1 != u2) {
- fail("Top of undo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->PeekRedoStack(&r2);
-
- TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (r1 != r2) {
- fail("Top of redo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
-
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Execute 20 batched transient transactions");
-
- /*******************************************************************
- *
- * Test nested batching. Afterwards, we should have 2 transactions
- * on the undo stack:
- *
- *******************************************************************/
-
- rv = mgr->BeginBatch(nullptr);
- if (NS_FAILED(rv)) {
- fail("BeginBatch(nullptr) failed. (%d)\n", rv);
- return rv;
- }
-
- tximpl = factory->create(mgr, NONE_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction.\n");
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("Failed to execute transaction. (%d)\n", rv);
- return rv;
- }
-
- tx->Release();
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->BeginBatch(nullptr);
- if (NS_FAILED(rv)) {
- fail("BeginBatch(nullptr) failed. (%d)\n", rv);
- return rv;
- }
-
- tximpl = factory->create(mgr, NONE_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction.\n");
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("Failed to execute transaction. (%d)\n", rv);
- return rv;
- }
-
- tx->Release();
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->BeginBatch(nullptr);
- if (NS_FAILED(rv)) {
- fail("BeginBatch(nullptr) failed. (%d)\n", rv);
- return rv;
- }
-
- tximpl = factory->create(mgr, NONE_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction.\n");
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("Failed to execute transaction. (%d)\n", rv);
- return rv;
- }
-
- tx->Release();
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->EndBatch(false);
- if (NS_FAILED(rv)) {
- fail("EndBatch(false) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->EndBatch(false);
- if (NS_FAILED(rv)) {
- fail("EndBatch(false) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->EndBatch(false);
- if (NS_FAILED(rv)) {
- fail("EndBatch(false) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 2) {
- fail("GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Test nested batched transactions");
-
- /*******************************************************************
- *
- * Undo 2 batch transactions. Afterwards, we should have 0
- * transactions on the undo stack and 2 on the redo stack.
- *
- *******************************************************************/
-
- for (i = 1; i <= 2; ++i) {
- rv = mgr->UndoTransaction();
- if (NS_FAILED(rv)) {
- fail("Failed to undo transaction %d. (%d)\n", i, rv);
- return rv;
- }
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on redo stack with 2 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 2) {
- fail("GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Undo 2 batch transactions");
-
- /*******************************************************************
- *
- * Redo 2 batch transactions. Afterwards, we should have 2
- * transactions on the undo stack and 0 on the redo stack.
- *
- *******************************************************************/
-
- for (i = 1; i <= 2; ++i) {
- rv = mgr->RedoTransaction();
- if (NS_FAILED(rv)) {
- fail("Failed to undo transaction %d. (%d)\n", i, rv);
- return rv;
- }
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 2) {
- fail("GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Redo 2 batch transactions");
-
- /*******************************************************************
- *
- * Call undo. Afterwards, we should have 1 transaction
- * on the undo stack, and 1 on the redo stack:
- *
- *******************************************************************/
-
- rv = mgr->UndoTransaction();
- if (NS_FAILED(rv)) {
- fail("Failed to undo transaction. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
-
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Undo a batched transaction that was redone");
-
- /*******************************************************************
- *
- * Make sure an unbalanced call to EndBatch(false) throws an error and
- * doesn't affect the undo and redo stacks!
- *
- *******************************************************************/
-
- rv = mgr->EndBatch(false);
- if (rv != NS_ERROR_FAILURE) {
- fail("EndBatch(false) returned unexpected status. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Test effect of unbalanced EndBatch(false) on undo and redo stacks");
-
- /*******************************************************************
- *
- * Make sure that an empty batch is not added to the undo stack
- * when it is closed, and that it does not affect the undo and redo
- * stacks.
- *
- *******************************************************************/
-
- rv = mgr->BeginBatch(nullptr);
- if (NS_FAILED(rv)) {
- fail("BeginBatch(nullptr) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->EndBatch(false);
- if (NS_FAILED(rv)) {
- fail("EndBatch(false) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Test effect of empty batch on undo and redo stacks");
-
- /*******************************************************************
- *
- * Execute a new transaction. The redo stack should get pruned!
- *
- *******************************************************************/
-
- rv = mgr->BeginBatch(nullptr);
- if (NS_FAILED(rv)) {
- fail("BeginBatch(nullptr) failed. (%d)\n", rv);
- return rv;
- }
-
- for (i = 1; i <= 20; i++) {
- tximpl = factory->create(mgr, NONE_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction %d.\n", i);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction %d. (%d)\n",
- i, rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("Failed to execute transaction %d. (%d)\n", i, rv);
- return rv;
- }
-
- tx->Release();
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on redo stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->EndBatch(false);
- if (NS_FAILED(rv)) {
- fail("EndBatch(false) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 2) {
- fail("GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Check if new batched transactions prune the redo stack");
-
- /*******************************************************************
- *
- * Call undo.
- *
- *******************************************************************/
-
- // Move a transaction over to the redo stack, so that we have one
- // transaction on the undo stack, and one on the redo stack!
-
- rv = mgr->UndoTransaction();
- if (NS_FAILED(rv)) {
- fail("Failed to undo transaction. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on redo stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Call undo");
-
- /*******************************************************************
- *
- * Test transaction DoTransaction() error:
- *
- *******************************************************************/
-
- tximpl = factory->create(mgr, THROWS_DO_ERROR_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction.\n");
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
-
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction. (%d)\n", rv);
- return rv;
- }
-
- u1 = u2 = r1 = r2 = 0;
-
- rv = mgr->PeekUndoStack(&u1);
-
- TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekRedoStack(&r1);
-
- TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->BeginBatch(nullptr);
- if (NS_FAILED(rv)) {
- fail("BeginBatch(nullptr) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (rv != NS_ERROR_FAILURE) {
- fail("DoTransaction() returned unexpected error. (%d)\n", rv);
- return rv;
- }
-
- tx->Release();
-
- rv = mgr->EndBatch(false);
- if (NS_FAILED(rv)) {
- fail("EndBatch(false) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekUndoStack(&u2);
-
- TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (u1 != u2) {
- fail("Top of undo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->PeekRedoStack(&r2);
-
- TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (r1 != r2) {
- fail("Top of redo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on redo stack with 1 item failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 1) {
- fail("GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Test transaction DoTransaction() error");
-
- /*******************************************************************
- *
- * Test transaction UndoTransaction() error:
- *
- *******************************************************************/
-
- tximpl = factory->create(mgr, THROWS_UNDO_ERROR_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction.\n");
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
-
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->BeginBatch(nullptr);
- if (NS_FAILED(rv)) {
- fail("BeginBatch(nullptr) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("DoTransaction() returned unexpected error. (%d)\n", rv);
- return rv;
- }
-
- tx->Release();
-
- rv = mgr->EndBatch(false);
- if (NS_FAILED(rv)) {
- fail("EndBatch(false) failed. (%d)\n", rv);
- return rv;
- }
-
- u1 = u2 = r1 = r2 = 0;
-
- rv = mgr->PeekUndoStack(&u1);
-
- TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekRedoStack(&r1);
-
- TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->UndoTransaction();
- if (rv != NS_ERROR_FAILURE) {
- fail("UndoTransaction() returned unexpected error. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekUndoStack(&u2);
-
- TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (u1 != u2) {
- fail("Top of undo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->PeekRedoStack(&r2);
-
- TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (r1 != r2) {
- fail("Top of redo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 2) {
- fail("GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on empty redo stack. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Test transaction UndoTransaction() error");
-
- /*******************************************************************
- *
- * Test transaction RedoTransaction() error:
- *
- *******************************************************************/
-
- tximpl = factory->create(mgr, THROWS_REDO_ERROR_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction.\n");
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
-
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for RedoErrorTransaction. (%d)\n",
- rv);
- return rv;
- }
-
- rv = mgr->BeginBatch(nullptr);
- if (NS_FAILED(rv)) {
- fail("BeginBatch(nullptr) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("DoTransaction() returned unexpected error. (%d)\n", rv);
- return rv;
- }
-
- tx->Release();
-
- rv = mgr->EndBatch(false);
- if (NS_FAILED(rv)) {
- fail("EndBatch(false) failed. (%d)\n", rv);
- return rv;
- }
-
- //
- // Execute a normal transaction to be used in a later test:
- //
-
- tximpl = factory->create(mgr, NONE_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction.\n");
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
-
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("DoTransaction() returned unexpected error. (%d)\n", rv);
- return rv;
- }
-
- tx->Release();
-
- //
- // Undo the 2 transactions just executed.
- //
-
- for (i = 1; i <= 2; ++i) {
- rv = mgr->UndoTransaction();
- if (NS_FAILED(rv)) {
- fail("Failed to undo transaction %d. (%d)\n", i, rv);
- return rv;
- }
- }
-
- //
- // The RedoErrorTransaction should now be at the top of the redo stack!
- //
-
- u1 = u2 = r1 = r2 = 0;
-
- rv = mgr->PeekUndoStack(&u1);
-
- TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekRedoStack(&r1);
-
- TEST_TXMGR_IF_RELEASE(r1); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Initial PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->RedoTransaction();
- if (rv != NS_ERROR_FAILURE) {
- fail("RedoTransaction() returned unexpected error. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->PeekUndoStack(&u2);
-
- TEST_TXMGR_IF_RELEASE(u2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekUndoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (u1 != u2) {
- fail("Top of undo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->PeekRedoStack(&r2);
-
- TEST_TXMGR_IF_RELEASE(r2); // Don't hold onto any references!
-
- if (NS_FAILED(rv)) {
- fail("Second PeekRedoStack() failed. (%d)\n", rv);
- return rv;
- }
-
- if (r1 != r2) {
- fail("Top of redo stack changed. (%d)\n", rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with 2 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 2) {
- fail("GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on redo stack with 2 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 2) {
- fail("GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- passed("Test transaction RedoTransaction() error");
-
- /*******************************************************************
- *
- * Make sure that setting the transaction manager's max transaction
- * count to zero, clears both the undo and redo stacks, and executes
- * all new commands without pushing them on the undo stack!
- *
- *******************************************************************/
-
- rv = mgr->SetMaxTransactionCount(0);
- if (NS_FAILED(rv)) {
- fail("SetMaxTransactionCount(0) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- for (i = 1; i <= 20; i++) {
- tximpl = factory->create(mgr, NONE_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction %d.\n", i);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction %d. (%d)\n",
- i, rv);
- return rv;
- }
-
- rv = mgr->BeginBatch(nullptr);
- if (NS_FAILED(rv)) {
- fail("BeginBatch(nullptr) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("Failed to execute transaction %d. (%d)\n", i, rv);
- return rv;
- }
-
- tx->Release();
-
- rv = mgr->EndBatch(false);
- if (NS_FAILED(rv)) {
- fail("EndBatch(false) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
- }
-
- passed("Test max transaction count of zero");
-
- /*******************************************************************
- *
- * Release the transaction manager. Any transactions on the undo
- * and redo stack should automatically be released:
- *
- *******************************************************************/
-
- rv = mgr->SetMaxTransactionCount(-1);
- if (NS_FAILED(rv)) {
- fail("SetMaxTransactionCount(0) failed. (%d)\n", rv);
- return rv;
- }
-
- // Push 20 transactions on the undo stack:
-
- for (i = 1; i <= 20; i++) {
- tximpl = factory->create(mgr, NONE_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction %d.\n", i);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction %d. (%d)\n",
- i, rv);
- return rv;
- }
-
- rv = mgr->BeginBatch(nullptr);
- if (NS_FAILED(rv)) {
- fail("BeginBatch(nullptr) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("Failed to execute transaction %d. (%d)\n", i, rv);
- return rv;
- }
-
- tx->Release();
-
- rv = mgr->EndBatch(false);
- if (NS_FAILED(rv)) {
- fail("EndBatch(false) failed. (%d)\n", rv);
- return rv;
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on undo stack with %d items failed. (%d)\n",
- i, rv);
- return rv;
- }
-
- if (numitems != i) {
- fail("GetNumberOfUndoItems() expected %d got %d. (%d)\n",
- i, numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems) {
- fail("GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
- }
-
- for (i = 1; i <= 10; i++) {
- rv = mgr->UndoTransaction();
- if (NS_FAILED(rv)) {
- fail("Failed to undo transaction %d. (%d)\n", i, rv);
- return rv;
- }
- }
-
- rv = mgr->GetNumberOfUndoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfUndoItems() on empty undo stack with 10 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 10) {
- fail("GetNumberOfUndoItems() expected 10 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->GetNumberOfRedoItems(&numitems);
- if (NS_FAILED(rv)) {
- fail("GetNumberOfRedoItems() on redo stack with 10 items failed. (%d)\n",
- rv);
- return rv;
- }
-
- if (numitems != 10) {
- fail("GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
- numitems, rv);
- return NS_ERROR_FAILURE;
- }
-
- rv = mgr->Clear();
- if (NS_FAILED(rv)) {
- fail("Clear() failed. (%d)\n", rv);
- return rv;
- }
-
- passed("Release the transaction manager");
-
- /*******************************************************************
- *
- * Make sure number of transactions created matches number of
- * transactions destroyed!
- *
- *******************************************************************/
-
- /* Disabled because the current cycle collector doesn't delete
- cycle collectable objects synchronously.
- if (sConstructorCount != sDestructorCount) {
- fail("Transaction constructor count (%d) != destructor count (%d).\n",
- sConstructorCount, sDestructorCount);
- return NS_ERROR_FAILURE;
- }*/
-
- passed("Number of transactions created and destroyed match");
- passed("%d transactions processed during quick batch test",
- sConstructorCount);
-
- return NS_OK;
-}
-
-nsresult
-simple_batch_test()
-{
- /*******************************************************************
- *
- * Initialize globals for test.
- *
- *******************************************************************/
- reset_globals();
- sDestructorOrderArr = sSimpleBatchTestDestructorOrderArr;
- sDoOrderArr = sSimpleBatchTestDoOrderArr;
- sUndoOrderArr = sSimpleBatchTestUndoOrderArr;
- sRedoOrderArr = sSimpleBatchTestRedoOrderArr;
-
- /*******************************************************************
- *
- * Run the quick batch test.
- *
- *******************************************************************/
-
- printf("\n-----------------------------------------------------\n");
- printf("- Begin Batch Transaction Test:\n");
- printf("-----------------------------------------------------\n");
-
- SimpleTransactionFactory factory;
-
- return quick_batch_test(&factory);
-}
-
-nsresult
-aggregation_batch_test()
-{
- /*******************************************************************
- *
- * Initialize globals for test.
- *
- *******************************************************************/
-
- reset_globals();
- sDestructorOrderArr = sAggregateBatchTestDestructorOrderArr;
- sDoOrderArr = sAggregateBatchTestDoOrderArr;
- sUndoOrderArr = sAggregateBatchTestUndoOrderArr;
- sRedoOrderArr = sAggregateBatchTestRedoOrderArr;
-
- /*******************************************************************
- *
- * Run the quick batch test.
- *
- *******************************************************************/
-
- printf("\n-----------------------------------------------------\n");
- printf("- Begin Batch Aggregate Transaction Test:\n");
- printf("-----------------------------------------------------\n");
-
- AggregateTransactionFactory factory(3, 2, BATCH_FLAG);
-
- return quick_batch_test(&factory);
-}
-
-/**
- * Create 'iterations * (iterations + 1) / 2' transactions;
- * do/undo/redo/undo them.
- **/
-nsresult
-stress_test(TestTransactionFactory *factory, int32_t iterations)
-{
- printf("Stress test of %i iterations (may take a while) ... ", iterations);
- fflush(stdout);
-
- /*******************************************************************
- *
- * Create a transaction manager:
- *
- *******************************************************************/
-
- nsresult rv;
- nsCOMPtr<nsITransactionManager> mgr =
- do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &rv);
- if (NS_FAILED(rv) || !mgr) {
- fail("Failed to create Transaction Manager instance.\n");
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- int32_t i, j;
- nsITransaction *tx;
-
- for (i = 1; i <= iterations; i++) {
- /*******************************************************************
- *
- * Create and execute a bunch of transactions:
- *
- *******************************************************************/
-
- for (j = 1; j <= i; j++) {
- TestTransaction *tximpl = factory->create(mgr, NONE_FLAG);
-
- if (!tximpl) {
- fail("Failed to allocate transaction %d-%d.\n", i, j);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- tx = 0;
- rv = tximpl->QueryInterface(NS_GET_IID(nsITransaction), (void **)&tx);
- if (NS_FAILED(rv)) {
- fail("QueryInterface() failed for transaction %d-%d. (%d)\n",
- i, j, rv);
- return rv;
- }
-
- rv = mgr->DoTransaction(tx);
- if (NS_FAILED(rv)) {
- fail("Failed to execute transaction %d-%d. (%d)\n",
- i, j, rv);
- return rv;
- }
-
- tx->Release();
- }
-
- /*******************************************************************
- *
- * Undo all the transactions:
- *
- *******************************************************************/
-
- for (j = 1; j <= i; j++) {
- rv = mgr->UndoTransaction();
- if (NS_FAILED(rv)) {
- fail("Failed to undo transaction %d-%d. (%d)\n", i, j, rv);
- return rv;
- }
- }
-
- /*******************************************************************
- *
- * Redo all the transactions:
- *
- *******************************************************************/
-
- for (j = 1; j <= i; j++) {
- rv = mgr->RedoTransaction();
- if (NS_FAILED(rv)) {
- fail("Failed to redo transaction %d-%d. (%d)\n", i, j, rv);
- return rv;
- }
- }
-
- /*******************************************************************
- *
- * Undo all the transactions again so that they all end up on
- * the redo stack for pruning the next time we execute a new
- * transaction
- *
- *******************************************************************/
-
- for (j = 1; j <= i; j++) {
- rv = mgr->UndoTransaction();
- if (NS_FAILED(rv)) {
- fail("Failed to undo transaction %d-%d. (%d)\n", i, j, rv);
- return rv;
- }
- }
-
- // Trivial feedback not to let the user think the test is stuck.
- if (MOZ_UNLIKELY(j % 100 == 0)) {
- printf("%i ", j);
- }
- } // for, iterations.
-
- printf("passed\n");
-
- rv = mgr->Clear();
- if (NS_FAILED(rv)) {
- fail("Clear() failed. (%d)\n", rv);
- return rv;
- }
-
- /* Disabled because the current cycle collector doesn't delete
- cycle collectable objects synchronously.
- if (sConstructorCount != sDestructorCount) {
- fail("Transaction constructor count (%d) != destructor count (%d).\n",
- sConstructorCount, sDestructorCount);
- return NS_ERROR_FAILURE;
- }*/
-
- passed("%d transactions processed during stress test", sConstructorCount);
-
- return NS_OK;
-}
-
-nsresult
-simple_stress_test()
-{
- /*******************************************************************
- *
- * Initialize globals for test.
- *
- *******************************************************************/
-
- reset_globals();
-
- /*******************************************************************
- *
- * Do the stress test:
- *
- *******************************************************************/
-
- printf("\n-----------------------------------------------------\n");
- printf("- Simple Transaction Stress Test:\n");
- printf("-----------------------------------------------------\n");
-
- SimpleTransactionFactory factory;
-
- int32_t iterations =
-#ifdef DEBUG
- 10
-#else
- //
- // 1500 iterations sends 1,125,750 transactions through the system!!
- //
- 1500
-#endif
- ;
- return stress_test(&factory, iterations);
-}
-
-nsresult
-aggregation_stress_test()
-{
- /*******************************************************************
- *
- * Initialize globals for test.
- *
- *******************************************************************/
-
- reset_globals();
-
- /*******************************************************************
- *
- * Do the stress test:
- *
- *******************************************************************/
-
- printf("\n-----------------------------------------------------\n");
- printf("- Aggregate Transaction Stress Test:\n");
- printf("-----------------------------------------------------\n");
-
- AggregateTransactionFactory factory(3, 4);
-
- int32_t iterations =
-#ifdef DEBUG
- 10
-#else
- //
- // 500 iterations sends 2,630,250 transactions through the system!!
- //
- 500
-#endif
- ;
- return stress_test(&factory, iterations);
-}
-
-nsresult
-aggregation_batch_stress_test()
-{
- /*******************************************************************
- *
- * Initialize globals for test.
- *
- *******************************************************************/
-
- reset_globals();
-
- /*******************************************************************
- *
- * Do the stress test:
- *
- *******************************************************************/
-
- printf("\n-----------------------------------------------------\n");
- printf("- Aggregate Batch Transaction Stress Test:\n");
- printf("-----------------------------------------------------\n");
-
- AggregateTransactionFactory factory(3, 4, BATCH_FLAG);
-
- int32_t iterations =
-#ifdef DEBUG
- 10
-#else
-#if defined(MOZ_ASAN) || defined(MOZ_WIDGET_ANDROID)
- // See Bug 929985: 500 is too many for ASAN and Android, 100 is safe.
- 100
-#else
- //
- // 500 iterations sends 2,630,250 transactions through the system!!
- //
- 500
-#endif
-#endif
- ;
- return stress_test(&factory, iterations);
-}
-
-int
-main (int argc, char *argv[])
-{
- ScopedXPCOM xpcom("nsITransactionManager");
- if (xpcom.failed()) {
- return 1;
- }
-
- //
- // quick_test() part:
- //
-
- nsresult rv = simple_test();
- NS_ENSURE_SUCCESS(rv, 1);
-
- rv = aggregation_test();
- NS_ENSURE_SUCCESS(rv, 1);
-
- //
- // quick_batch_test() part:
- //
-
- rv = simple_batch_test();
- NS_ENSURE_SUCCESS(rv, 1);
-
- rv = aggregation_batch_test();
- NS_ENSURE_SUCCESS(rv, 1);
-
- //
- // stress_test() part:
- //
-
- rv = simple_stress_test();
- NS_ENSURE_SUCCESS(rv, 1);
-
- rv = aggregation_stress_test();
- NS_ENSURE_SUCCESS(rv, 1);
-
- rv = aggregation_batch_stress_test();
- NS_ENSURE_SUCCESS(rv, 1);
-
- return 0;
-}
diff --git a/editor/txmgr/tests/crashtests/407072-1.html b/editor/txmgr/tests/crashtests/407072-1.html
deleted file mode 100644
index e3aa3c216..000000000
--- a/editor/txmgr/tests/crashtests/407072-1.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<html>
-<head>
-<script>
-
-function boom()
-{
- var br = document.getElementById("br");
- br.contentEditable = "true";
- br.focus();
-
- try { document.execCommand("justifyfull", false, null); } catch(e) { }
- try { document.execCommand("justifyfull", false, null); } catch(e) { }
- document.execCommand("underline", false, null);
- document.execCommand("insertimage", false, "foo");
- try { document.execCommand("outdent", false, null); } catch(e) { }
-}
-
-</script>
-</head>
-
-<body onload="boom();"><br id="br"></body>
-</html>
diff --git a/editor/txmgr/tests/crashtests/449006-1.html b/editor/txmgr/tests/crashtests/449006-1.html
deleted file mode 100644
index 65e6ed981..000000000
--- a/editor/txmgr/tests/crashtests/449006-1.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<html>
-<head>
-<script type="text/javascript">
-
-function boom()
-{
- document.getElementById("d").focus();
- document.execCommand("inserthtml", false, "AB");
- document.execCommand("delete", false, null);
- document.execCommand("undo", false, null);
-
- document.addEventListener("DOMCharacterDataModified", f, false);
- document.execCommand("redo", false, null);
- document.removeEventListener("DOMCharacterDataModified", f, false);
-
- function f()
- {
- document.removeEventListener("DOMCharacterDataModified", f, false);
- document.execCommand("formatBlock", false, "<h3>");
- }
-}
-
-</script>
-</head>
-
-<body onload="boom();"><div id="d" contenteditable="true"></div></body>
-
-</html>
diff --git a/editor/txmgr/tests/crashtests/crashtests.list b/editor/txmgr/tests/crashtests/crashtests.list
deleted file mode 100644
index d39187592..000000000
--- a/editor/txmgr/tests/crashtests/crashtests.list
+++ /dev/null
@@ -1,2 +0,0 @@
-needs-focus load 407072-1.html
-load 449006-1.html
diff --git a/editor/txmgr/tests/moz.build b/editor/txmgr/tests/moz.build
deleted file mode 100644
index 59679e388..000000000
--- a/editor/txmgr/tests/moz.build
+++ /dev/null
@@ -1,8 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-GeckoCppUnitTests([
- 'TestTXMgr',
-])
diff --git a/editor/txtsvc/moz.build b/editor/txtsvc/moz.build
deleted file mode 100644
index 0395c80fe..000000000
--- a/editor/txtsvc/moz.build
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-XPIDL_SOURCES += [
- 'nsIInlineSpellChecker.idl',
- 'nsITextServicesFilter.idl',
-]
-
-XPIDL_MODULE = 'txtsvc'
-
-EXPORTS += [
- 'nsISpellChecker.h',
- 'nsITextService.h',
- 'nsITextServicesDocument.h',
- 'nsTextServicesCID.h',
-]
-
-SOURCES += [
- 'nsFilteredContentIterator.cpp',
- 'nsTextServicesDocument.cpp',
-]
-
-FINAL_LIBRARY = 'xul'
diff --git a/editor/txtsvc/nsFilteredContentIterator.cpp b/editor/txtsvc/nsFilteredContentIterator.cpp
deleted file mode 100644
index cccfb90ad..000000000
--- a/editor/txtsvc/nsFilteredContentIterator.cpp
+++ /dev/null
@@ -1,424 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/mozalloc.h"
-#include "nsComponentManagerUtils.h"
-#include "nsContentUtils.h"
-#include "nsDebug.h"
-#include "nsError.h"
-#include "nsFilteredContentIterator.h"
-#include "nsIAtom.h"
-#include "nsIContent.h"
-#include "nsIContentIterator.h"
-#include "nsIDOMNode.h"
-#include "nsINode.h"
-#include "nsISupportsBase.h"
-#include "nsISupportsUtils.h"
-#include "nsITextServicesFilter.h"
-#include "nsRange.h"
-
-//------------------------------------------------------------
-nsFilteredContentIterator::nsFilteredContentIterator(nsITextServicesFilter* aFilter) :
- mFilter(aFilter),
- mDidSkip(false),
- mIsOutOfRange(false),
- mDirection(eDirNotSet)
-{
- mIterator = do_CreateInstance("@mozilla.org/content/post-content-iterator;1");
- mPreIterator = do_CreateInstance("@mozilla.org/content/pre-content-iterator;1");
-}
-
-//------------------------------------------------------------
-nsFilteredContentIterator::~nsFilteredContentIterator()
-{
-}
-
-//------------------------------------------------------------
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFilteredContentIterator)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFilteredContentIterator)
-
-NS_INTERFACE_MAP_BEGIN(nsFilteredContentIterator)
- NS_INTERFACE_MAP_ENTRY(nsIContentIterator)
- NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentIterator)
- NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsFilteredContentIterator)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTION(nsFilteredContentIterator,
- mCurrentIterator,
- mIterator,
- mPreIterator,
- mFilter,
- mRange)
-
-//------------------------------------------------------------
-nsresult
-nsFilteredContentIterator::Init(nsINode* aRoot)
-{
- NS_ENSURE_ARG_POINTER(aRoot);
- NS_ENSURE_TRUE(mPreIterator, NS_ERROR_FAILURE);
- NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
- mIsOutOfRange = false;
- mDirection = eForward;
- mCurrentIterator = mPreIterator;
-
- mRange = new nsRange(aRoot);
- nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(aRoot));
- if (domNode) {
- mRange->SelectNode(domNode);
- }
-
- nsresult rv = mPreIterator->Init(mRange);
- NS_ENSURE_SUCCESS(rv, rv);
- return mIterator->Init(mRange);
-}
-
-//------------------------------------------------------------
-nsresult
-nsFilteredContentIterator::Init(nsIDOMRange* aRange)
-{
- NS_ENSURE_TRUE(mPreIterator, NS_ERROR_FAILURE);
- NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
- NS_ENSURE_ARG_POINTER(aRange);
- mIsOutOfRange = false;
- mDirection = eForward;
- mCurrentIterator = mPreIterator;
-
- mRange = static_cast<nsRange*>(aRange)->CloneRange();
-
- nsresult rv = mPreIterator->Init(mRange);
- NS_ENSURE_SUCCESS(rv, rv);
- return mIterator->Init(mRange);
-}
-
-//------------------------------------------------------------
-nsresult
-nsFilteredContentIterator::SwitchDirections(bool aChangeToForward)
-{
- nsINode *node = mCurrentIterator->GetCurrentNode();
-
- if (aChangeToForward) {
- mCurrentIterator = mPreIterator;
- mDirection = eForward;
- } else {
- mCurrentIterator = mIterator;
- mDirection = eBackward;
- }
-
- if (node) {
- nsresult rv = mCurrentIterator->PositionAt(node);
- if (NS_FAILED(rv)) {
- mIsOutOfRange = true;
- return rv;
- }
- }
- return NS_OK;
-}
-
-//------------------------------------------------------------
-void
-nsFilteredContentIterator::First()
-{
- if (!mCurrentIterator) {
- NS_ERROR("Missing iterator!");
-
- return;
- }
-
- // If we are switching directions then
- // we need to switch how we process the nodes
- if (mDirection != eForward) {
- mCurrentIterator = mPreIterator;
- mDirection = eForward;
- mIsOutOfRange = false;
- }
-
- mCurrentIterator->First();
-
- if (mCurrentIterator->IsDone()) {
- return;
- }
-
- nsINode *currentNode = mCurrentIterator->GetCurrentNode();
- nsCOMPtr<nsIDOMNode> node(do_QueryInterface(currentNode));
-
- bool didCross;
- CheckAdvNode(node, didCross, eForward);
-}
-
-//------------------------------------------------------------
-void
-nsFilteredContentIterator::Last()
-{
- if (!mCurrentIterator) {
- NS_ERROR("Missing iterator!");
-
- return;
- }
-
- // If we are switching directions then
- // we need to switch how we process the nodes
- if (mDirection != eBackward) {
- mCurrentIterator = mIterator;
- mDirection = eBackward;
- mIsOutOfRange = false;
- }
-
- mCurrentIterator->Last();
-
- if (mCurrentIterator->IsDone()) {
- return;
- }
-
- nsINode *currentNode = mCurrentIterator->GetCurrentNode();
- nsCOMPtr<nsIDOMNode> node(do_QueryInterface(currentNode));
-
- bool didCross;
- CheckAdvNode(node, didCross, eBackward);
-}
-
-///////////////////////////////////////////////////////////////////////////
-// ContentToParentOffset: returns the content node's parent and offset.
-//
-static void
-ContentToParentOffset(nsIContent *aContent, nsIDOMNode **aParent,
- int32_t *aOffset)
-{
- if (!aParent || !aOffset)
- return;
-
- *aParent = nullptr;
- *aOffset = 0;
-
- if (!aContent)
- return;
-
- nsIContent* parent = aContent->GetParent();
-
- if (!parent)
- return;
-
- *aOffset = parent->IndexOf(aContent);
-
- CallQueryInterface(parent, aParent);
-}
-
-///////////////////////////////////////////////////////////////////////////
-// ContentIsInTraversalRange: returns true if content is visited during
-// the traversal of the range in the specified mode.
-//
-static bool
-ContentIsInTraversalRange(nsIContent *aContent, bool aIsPreMode,
- nsIDOMNode *aStartNode, int32_t aStartOffset,
- nsIDOMNode *aEndNode, int32_t aEndOffset)
-{
- NS_ENSURE_TRUE(aStartNode && aEndNode && aContent, false);
-
- nsCOMPtr<nsIDOMNode> parentNode;
- int32_t indx = 0;
-
- ContentToParentOffset(aContent, getter_AddRefs(parentNode), &indx);
-
- NS_ENSURE_TRUE(parentNode, false);
-
- if (!aIsPreMode)
- ++indx;
-
- int32_t startRes = nsContentUtils::ComparePoints(aStartNode, aStartOffset,
- parentNode, indx);
- int32_t endRes = nsContentUtils::ComparePoints(aEndNode, aEndOffset,
- parentNode, indx);
- return (startRes <= 0) && (endRes >= 0);
-}
-
-static bool
-ContentIsInTraversalRange(nsRange* aRange, nsIDOMNode* aNextNode, bool aIsPreMode)
-{
- nsCOMPtr<nsIContent> content(do_QueryInterface(aNextNode));
- NS_ENSURE_TRUE(content && aRange, false);
-
- nsCOMPtr<nsIDOMNode> sNode;
- nsCOMPtr<nsIDOMNode> eNode;
- uint32_t sOffset;
- uint32_t eOffset;
- aRange->GetStartContainer(getter_AddRefs(sNode));
- aRange->GetStartOffset(&sOffset);
- aRange->GetEndContainer(getter_AddRefs(eNode));
- aRange->GetEndOffset(&eOffset);
- return ContentIsInTraversalRange(content, aIsPreMode,
- sNode, static_cast<int32_t>(sOffset),
- eNode, static_cast<int32_t>(eOffset));
-}
-
-//------------------------------------------------------------
-// Helper function to advance to the next or previous node
-nsresult
-nsFilteredContentIterator::AdvanceNode(nsIDOMNode* aNode, nsIDOMNode*& aNewNode, eDirectionType aDir)
-{
- nsCOMPtr<nsIDOMNode> nextNode;
- if (aDir == eForward) {
- aNode->GetNextSibling(getter_AddRefs(nextNode));
- } else {
- aNode->GetPreviousSibling(getter_AddRefs(nextNode));
- }
-
- if (nextNode) {
- // If we got here, that means we found the nxt/prv node
- // make sure it is in our DOMRange
- bool intersects = ContentIsInTraversalRange(mRange, nextNode, aDir == eForward);
- if (intersects) {
- aNewNode = nextNode;
- NS_ADDREF(aNewNode);
- return NS_OK;
- }
- } else {
- // The next node was null so we need to walk up the parent(s)
- nsCOMPtr<nsIDOMNode> parent;
- aNode->GetParentNode(getter_AddRefs(parent));
- NS_ASSERTION(parent, "parent can't be nullptr");
-
- // Make sure the parent is in the DOMRange before going further
- bool intersects = ContentIsInTraversalRange(mRange, nextNode, aDir == eForward);
- if (intersects) {
- // Now find the nxt/prv node after/before this node
- nsresult rv = AdvanceNode(parent, aNewNode, aDir);
- if (NS_SUCCEEDED(rv) && aNewNode) {
- return NS_OK;
- }
- }
- }
-
- // if we get here it pretty much means
- // we went out of the DOM Range
- mIsOutOfRange = true;
-
- return NS_ERROR_FAILURE;
-}
-
-//------------------------------------------------------------
-// Helper function to see if the next/prev node should be skipped
-void
-nsFilteredContentIterator::CheckAdvNode(nsIDOMNode* aNode, bool& aDidSkip, eDirectionType aDir)
-{
- aDidSkip = false;
- mIsOutOfRange = false;
-
- if (aNode && mFilter) {
- nsCOMPtr<nsIDOMNode> currentNode = aNode;
- bool skipIt;
- while (1) {
- nsresult rv = mFilter->Skip(aNode, &skipIt);
- if (NS_SUCCEEDED(rv) && skipIt) {
- aDidSkip = true;
- // Get the next/prev node and then
- // see if we should skip that
- nsCOMPtr<nsIDOMNode> advNode;
- rv = AdvanceNode(aNode, *getter_AddRefs(advNode), aDir);
- if (NS_SUCCEEDED(rv) && advNode) {
- aNode = advNode;
- } else {
- return; // fell out of range
- }
- } else {
- if (aNode != currentNode) {
- nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
- mCurrentIterator->PositionAt(content);
- }
- return; // found something
- }
- }
- }
-}
-
-void
-nsFilteredContentIterator::Next()
-{
- if (mIsOutOfRange || !mCurrentIterator) {
- NS_ASSERTION(mCurrentIterator, "Missing iterator!");
-
- return;
- }
-
- // If we are switching directions then
- // we need to switch how we process the nodes
- if (mDirection != eForward) {
- nsresult rv = SwitchDirections(true);
- if (NS_FAILED(rv)) {
- return;
- }
- }
-
- mCurrentIterator->Next();
-
- if (mCurrentIterator->IsDone()) {
- return;
- }
-
- // If we can't get the current node then
- // don't check to see if we can skip it
- nsINode *currentNode = mCurrentIterator->GetCurrentNode();
-
- nsCOMPtr<nsIDOMNode> node(do_QueryInterface(currentNode));
- CheckAdvNode(node, mDidSkip, eForward);
-}
-
-void
-nsFilteredContentIterator::Prev()
-{
- if (mIsOutOfRange || !mCurrentIterator) {
- NS_ASSERTION(mCurrentIterator, "Missing iterator!");
-
- return;
- }
-
- // If we are switching directions then
- // we need to switch how we process the nodes
- if (mDirection != eBackward) {
- nsresult rv = SwitchDirections(false);
- if (NS_FAILED(rv)) {
- return;
- }
- }
-
- mCurrentIterator->Prev();
-
- if (mCurrentIterator->IsDone()) {
- return;
- }
-
- // If we can't get the current node then
- // don't check to see if we can skip it
- nsINode *currentNode = mCurrentIterator->GetCurrentNode();
-
- nsCOMPtr<nsIDOMNode> node(do_QueryInterface(currentNode));
- CheckAdvNode(node, mDidSkip, eBackward);
-}
-
-nsINode *
-nsFilteredContentIterator::GetCurrentNode()
-{
- if (mIsOutOfRange || !mCurrentIterator) {
- return nullptr;
- }
-
- return mCurrentIterator->GetCurrentNode();
-}
-
-bool
-nsFilteredContentIterator::IsDone()
-{
- if (mIsOutOfRange || !mCurrentIterator) {
- return true;
- }
-
- return mCurrentIterator->IsDone();
-}
-
-nsresult
-nsFilteredContentIterator::PositionAt(nsINode* aCurNode)
-{
- NS_ENSURE_TRUE(mCurrentIterator, NS_ERROR_FAILURE);
- mIsOutOfRange = false;
- return mCurrentIterator->PositionAt(aCurNode);
-}
diff --git a/editor/txtsvc/nsFilteredContentIterator.h b/editor/txtsvc/nsFilteredContentIterator.h
deleted file mode 100644
index 9dde8132f..000000000
--- a/editor/txtsvc/nsFilteredContentIterator.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsFilteredContentIterator_h__
-#define nsFilteredContentIterator_h__
-
-#include "nsCOMPtr.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsIContentIterator.h"
-#include "nsISupportsImpl.h"
-#include "nscore.h"
-
-class nsIAtom;
-class nsIDOMNode;
-class nsIDOMRange;
-class nsINode;
-class nsITextServicesFilter;
-class nsRange;
-
-class nsFilteredContentIterator final : public nsIContentIterator
-{
-public:
-
- // nsISupports interface...
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS(nsFilteredContentIterator)
-
- explicit nsFilteredContentIterator(nsITextServicesFilter* aFilter);
-
- /* nsIContentIterator */
- virtual nsresult Init(nsINode* aRoot) override;
- virtual nsresult Init(nsIDOMRange* aRange) override;
- virtual void First() override;
- virtual void Last() override;
- virtual void Next() override;
- virtual void Prev() override;
- virtual nsINode *GetCurrentNode() override;
- virtual bool IsDone() override;
- virtual nsresult PositionAt(nsINode* aCurNode) override;
-
- /* Helpers */
- bool DidSkip() { return mDidSkip; }
- void ClearDidSkip() { mDidSkip = false; }
-
-protected:
- nsFilteredContentIterator() : mDidSkip(false), mIsOutOfRange(false) { }
-
- virtual ~nsFilteredContentIterator();
-
- // enum to give us the direction
- typedef enum {eDirNotSet, eForward, eBackward} eDirectionType;
- nsresult AdvanceNode(nsIDOMNode* aNode, nsIDOMNode*& aNewNode, eDirectionType aDir);
- void CheckAdvNode(nsIDOMNode* aNode, bool& aDidSkip, eDirectionType aDir);
- nsresult SwitchDirections(bool aChangeToForward);
-
- nsCOMPtr<nsIContentIterator> mCurrentIterator;
- nsCOMPtr<nsIContentIterator> mIterator;
- nsCOMPtr<nsIContentIterator> mPreIterator;
-
- nsCOMPtr<nsIAtom> mBlockQuoteAtom;
- nsCOMPtr<nsIAtom> mScriptAtom;
- nsCOMPtr<nsIAtom> mTextAreaAtom;
- nsCOMPtr<nsIAtom> mSelectAreaAtom;
- nsCOMPtr<nsIAtom> mMapAtom;
-
- nsCOMPtr<nsITextServicesFilter> mFilter;
- RefPtr<nsRange> mRange;
- bool mDidSkip;
- bool mIsOutOfRange;
- eDirectionType mDirection;
-};
-
-#endif
diff --git a/editor/txtsvc/nsIInlineSpellChecker.idl b/editor/txtsvc/nsIInlineSpellChecker.idl
deleted file mode 100644
index 62ea06bfc..000000000
--- a/editor/txtsvc/nsIInlineSpellChecker.idl
+++ /dev/null
@@ -1,50 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "domstubs.idl"
-
-interface nsISelection;
-interface nsIEditor;
-interface nsIEditorSpellCheck;
-
-[scriptable, uuid(b7b7a77c-40c4-4196-b0b7-b0338243b3fe)]
-interface nsIInlineSpellChecker : nsISupports
-{
- readonly attribute nsIEditorSpellCheck spellChecker;
-
- void init(in nsIEditor aEditor);
- void cleanup(in boolean aDestroyingFrames);
-
- attribute boolean enableRealTimeSpell;
-
- void spellCheckAfterEditorChange(in long aAction,
- in nsISelection aSelection,
- in nsIDOMNode aPreviousSelectedNode,
- in long aPreviousSelectedOffset,
- in nsIDOMNode aStartNode,
- in long aStartOffset,
- in nsIDOMNode aEndNode,
- in long aEndOffset);
-
- void spellCheckRange(in nsIDOMRange aSelection);
-
- nsIDOMRange getMisspelledWord(in nsIDOMNode aNode, in long aOffset);
- void replaceWord(in nsIDOMNode aNode, in long aOffset, in AString aNewword);
- void addWordToDictionary(in AString aWord);
- void removeWordFromDictionary(in AString aWord);
-
- void ignoreWord(in AString aWord);
- void ignoreWords([array, size_is(aCount)] in wstring aWordsToIgnore, in unsigned long aCount);
- void updateCurrentDictionary();
-
- readonly attribute boolean spellCheckPending;
-};
-
-%{C++
-
-#define MOZ_INLINESPELLCHECKER_CONTRACTID "@mozilla.org/spellchecker-inline;1"
-
-%}
diff --git a/editor/txtsvc/nsISpellChecker.h b/editor/txtsvc/nsISpellChecker.h
deleted file mode 100644
index cafc725be..000000000
--- a/editor/txtsvc/nsISpellChecker.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsISpellChecker_h__
-#define nsISpellChecker_h__
-
-#include "nsISupports.h"
-#include "nsTArray.h"
-
-#define NS_SPELLCHECKER_CONTRACTID "@mozilla.org/spellchecker;1"
-
-#define NS_ISPELLCHECKER_IID \
-{ /* 27bff957-b486-40ae-9f5d-af0cdd211868 */ \
-0x27bff957, 0xb486, 0x40ae, \
- { 0x9f, 0x5d, 0xaf, 0x0c, 0xdd, 0x21, 0x18, 0x68 } }
-
-class nsITextServicesDocument;
-class nsString;
-
-/**
- * A generic interface for a spelling checker.
- */
-class nsISpellChecker : public nsISupports{
-public:
-
- NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISPELLCHECKER_IID)
-
- /**
- * Tells the spellchecker what document to check.
- * @param aDoc is the document to check.
- * @param aFromStartOfDoc If true, start check from beginning of document,
- * if false, start check from current cursor position.
- */
- NS_IMETHOD SetDocument(nsITextServicesDocument *aDoc, bool aFromStartofDoc) = 0;
-
- /**
- * Selects (hilites) the next misspelled word in the document.
- * @param aWord will contain the misspelled word.
- * @param aSuggestions is an array of nsStrings, that represent the
- * suggested replacements for the misspelled word.
- */
- NS_IMETHOD NextMisspelledWord(nsAString &aWord, nsTArray<nsString> *aSuggestions) = 0;
-
- /**
- * Checks if a word is misspelled. No document is required to use this method.
- * @param aWord is the word to check.
- * @param aIsMisspelled will be set to true if the word is misspelled.
- * @param aSuggestions is an array of nsStrings which represent the
- * suggested replacements for the misspelled word. The array will be empty
- * if there aren't any suggestions.
- */
- NS_IMETHOD CheckWord(const nsAString &aWord, bool *aIsMisspelled, nsTArray<nsString> *aSuggestions) = 0;
-
- /**
- * Replaces the old word with the specified new word.
- * @param aOldWord is the word to be replaced.
- * @param aNewWord is the word that is to replace old word.
- * @param aAllOccurrences will replace all occurrences of old
- * word, in the document, with new word when it is true. If
- * false, it will replace the 1st occurrence only!
- */
- NS_IMETHOD Replace(const nsAString &aOldWord, const nsAString &aNewWord, bool aAllOccurrences) = 0;
-
- /**
- * Ignores all occurrences of the specified word in the document.
- * @param aWord is the word to ignore.
- */
- NS_IMETHOD IgnoreAll(const nsAString &aWord) = 0;
-
- /**
- * Add a word to the user's personal dictionary.
- * @param aWord is the word to add.
- */
- NS_IMETHOD AddWordToPersonalDictionary(const nsAString &aWord) = 0;
-
- /**
- * Remove a word from the user's personal dictionary.
- * @param aWord is the word to remove.
- */
- NS_IMETHOD RemoveWordFromPersonalDictionary(const nsAString &aWord) = 0;
-
- /**
- * Returns the list of words in the user's personal dictionary.
- * @param aWordList is an array of nsStrings that represent the
- * list of words in the user's personal dictionary.
- */
- NS_IMETHOD GetPersonalDictionary(nsTArray<nsString> *aWordList) = 0;
-
- /**
- * Returns the list of strings representing the dictionaries
- * the spellchecker supports. It was suggested that the strings
- * returned be in the RFC 1766 format. This format looks something
- * like <ISO 639 language code>-<ISO 3166 country code>.
- * For example: en-US
- * @param aDictionaryList is an array of nsStrings that represent the
- * dictionaries supported by the spellchecker.
- */
- NS_IMETHOD GetDictionaryList(nsTArray<nsString> *aDictionaryList) = 0;
-
- /**
- * Returns a string representing the current dictionary.
- * @param aDictionary will contain the name of the dictionary.
- * This name is the same string that is in the list returned
- * by GetDictionaryList().
- */
- NS_IMETHOD GetCurrentDictionary(nsAString &aDictionary) = 0;
-
- /**
- * Tells the spellchecker to use a specific dictionary.
- * @param aDictionary a string that is in the list returned
- * by GetDictionaryList() or an empty string. If aDictionary is
- * empty string, spellchecker will be disabled.
- */
- NS_IMETHOD SetCurrentDictionary(const nsAString &aDictionary) = 0;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsISpellChecker, NS_ISPELLCHECKER_IID)
-
-#endif // nsISpellChecker_h__
-
diff --git a/editor/txtsvc/nsITextService.h b/editor/txtsvc/nsITextService.h
deleted file mode 100644
index 13ffe3657..000000000
--- a/editor/txtsvc/nsITextService.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsITextService_h__
-#define nsITextService_h__
-
-#include "nsISupports.h"
-
-class nsITextServicesDocument;
-
-/*
-TextService interface to outside world
-*/
-
-#define NS_ITEXTSERVICE_IID \
-{ /* 019718E0-CDB5-11d2-8D3C-000000000000 */ \
-0x019718e0, 0xcdb5, 0x11d2, \
-{ 0x8d, 0x3c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }
-
-
-/**
- *
- */
-class nsITextService : public nsISupports{
-public:
-
- NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITEXTSERVICE_IID)
-
- /**
- *
- */
- NS_IMETHOD Init(nsITextServicesDocument *aDoc) = 0;
- NS_IMETHOD Execute() = 0;
- NS_IMETHOD GetMenuString(nsString &aString) = 0;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsITextService, NS_ITEXTSERVICE_IID)
-
-#endif // nsITextService_h__
-
diff --git a/editor/txtsvc/nsITextServicesDocument.h b/editor/txtsvc/nsITextServicesDocument.h
deleted file mode 100644
index 8b9d9e506..000000000
--- a/editor/txtsvc/nsITextServicesDocument.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsITextServicesDocument_h__
-#define nsITextServicesDocument_h__
-
-#include "nsISupports.h"
-
-class nsIDOMDocument;
-class nsIDOMRange;
-class nsIEditor;
-class nsString;
-class nsITextServicesFilter;
-
-/*
-TextServicesDocument interface to outside world
-*/
-
-#define NS_ITEXTSERVICESDOCUMENT_IID \
-{ /* 019718E1-CDB5-11d2-8D3C-000000000000 */ \
-0x019718e1, 0xcdb5, 0x11d2, \
-{ 0x8d, 0x3c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }
-
-
-/**
- * The nsITextServicesDocument presents the document in as a
- * bunch of flattened text blocks. Each text block can be retrieved
- * as an nsString (array of characters).
- */
-class nsITextServicesDocument : public nsISupports{
-public:
-
- NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITEXTSERVICESDOCUMENT_IID)
-
- typedef enum { eDSNormal=0, eDSUndlerline } TSDDisplayStyle;
-
- typedef enum { eBlockNotFound=0, // There is no text block (TB) in or before the selection (S).
- eBlockOutside, // No TB in S, but found one before/after S.
- eBlockInside, // S extends beyond the start and end of TB.
- eBlockContains, // TB contains entire S.
- eBlockPartial // S begins or ends in TB but extends outside of TB.
- } TSDBlockSelectionStatus;
-
- /**
- * Get the DOM document for the document in use.
- * @return aDocument the dom document [OUT]
- */
- NS_IMETHOD GetDocument(nsIDOMDocument **aDocument) = 0;
-
- /**
- * Initializes the text services document to use a particular
- * editor. The text services document will use the DOM document
- * and presentation shell used by the editor.
- * @param aEditor is the editor to use. The editor is AddRef'd
- * by this method.
- */
- NS_IMETHOD InitWithEditor(nsIEditor *aEditor) = 0;
-
- /**
- * Sets the range/extent over which the text services document
- * will iterate. Note that InitWithEditor() should have been called prior to
- * calling this method. If this method is never called, the text services
- * defaults to iterating over the entire document.
- *
- * @param aDOMRange is the range to use. aDOMRange must point to a
- * valid range object.
- */
- NS_IMETHOD SetExtent(nsIDOMRange* aDOMRange) = 0;
-
- /**
- * Expands the end points of the range so that it spans complete words.
- * This call does not change any internal state of the text services document.
- *
- * @param aDOMRange the range to be expanded/adjusted.
- */
- NS_IMETHOD ExpandRangeToWordBoundaries(nsIDOMRange *aRange) = 0;
-
- /**
- * Sets the filter to be used while iterating over content.
- * @param aFilter filter to be used while iterating over content.
- */
- NS_IMETHOD SetFilter(nsITextServicesFilter *aFilter) = 0;
-
- /**
- * Returns the text in the current text block.
- * @param aStr will contain the text.
- */
-
- NS_IMETHOD GetCurrentTextBlock(nsString *aStr) = 0;
-
- /**
- * Tells the document to point to the first text block
- * in the document. This method does not adjust the current
- * cursor position or selection.
- */
-
- NS_IMETHOD FirstBlock() = 0;
-
- /**
- * Tells the document to point to the last text block that
- * contains the current selection or caret.
- * @param aSelectionStatus will contain the text block selection status
- * @param aSelectionOffset will contain the offset into the
- * string returned by GetCurrentTextBlock() where the selection
- * begins.
- * @param aLength will contain the number of characters that are
- * selected in the string.
- */
-
- NS_IMETHOD LastSelectedBlock(TSDBlockSelectionStatus *aSelectionStatus, int32_t *aSelectionOffset, int32_t *aSelectionLength) = 0;
-
- /**
- * Tells the document to point to the text block before
- * the current one. This method will return NS_OK, even
- * if there is no previous block. Callers should call IsDone()
- * to check if we have gone beyond the first text block in
- * the document.
- */
-
- NS_IMETHOD PrevBlock() = 0;
-
- /**
- * Tells the document to point to the text block after
- * the current one. This method will return NS_OK, even
- * if there is no next block. Callers should call IsDone()
- * to check if we have gone beyond the last text block
- * in the document.
- */
-
- NS_IMETHOD NextBlock() = 0;
-
- /**
- * IsDone() will always set aIsDone == false unless
- * the document contains no text, PrevBlock() was called
- * while the document was already pointing to the first
- * text block in the document, or NextBlock() was called
- * while the document was already pointing to the last
- * text block in the document.
- * @param aIsDone will contain the result.
- */
-
- NS_IMETHOD IsDone(bool *aIsDone) = 0;
-
- /**
- * SetSelection() allows the caller to set the selection
- * based on an offset into the string returned by
- * GetCurrentTextBlock(). A length of zero places the cursor
- * at that offset. A positive non-zero length "n" selects
- * n characters in the string.
- * @param aOffset offset into string returned by GetCurrentTextBlock().
- * @param aLength number characters selected.
- */
-
- NS_IMETHOD SetSelection(int32_t aOffset, int32_t aLength) = 0;
-
- /**
- * Scrolls the document so that the current selection is visible.
- */
-
- NS_IMETHOD ScrollSelectionIntoView() = 0;
-
- /**
- * Deletes the text selected by SetSelection(). Calling
- * DeleteSelection with nothing selected, or with a collapsed
- * selection (cursor) does nothing and returns NS_OK.
- */
-
- NS_IMETHOD DeleteSelection() = 0;
-
- /**
- * Inserts the given text at the current cursor position.
- * If there is a selection, it will be deleted before the
- * text is inserted.
- */
-
- NS_IMETHOD InsertText(const nsString *aText) = 0;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsITextServicesDocument,
- NS_ITEXTSERVICESDOCUMENT_IID)
-
-#endif // nsITextServicesDocument_h__
-
diff --git a/editor/txtsvc/nsITextServicesFilter.idl b/editor/txtsvc/nsITextServicesFilter.idl
deleted file mode 100644
index b2dba0e4a..000000000
--- a/editor/txtsvc/nsITextServicesFilter.idl
+++ /dev/null
@@ -1,21 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsIDOMNode;
-
-[scriptable, uuid(5BEC321F-59AC-413a-A4AD-8A8D7C50A0D0)]
-interface nsITextServicesFilter : nsISupports
-{
-
- /**
- * Indicates whether the content node should be skipped by the iterator
- * @param aNode - node to skip
- */
- boolean skip(in nsIDOMNode aNode);
-
-};
-
diff --git a/editor/txtsvc/nsTSAtomList.h b/editor/txtsvc/nsTSAtomList.h
deleted file mode 100644
index 13feb9f12..000000000
--- a/editor/txtsvc/nsTSAtomList.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/******
-
- This file contains the list of all text services nsIAtoms and their values
-
- It is designed to be used as inline input to nsTextServicesDocument.cpp *only*
- through the magic of C preprocessing.
-
- All entries must be enclosed in the macro TS_ATOM which will have cruel
- and unusual things done to it
-
- It is recommended (but not strictly necessary) to keep all entries
- in alphabetical order
-
- The first argument to TS_ATOM is the C++ identifier of the atom
- The second argument is the string value of the atom
-
- ******/
-
-// OUTPUT_CLASS=nsTextServicesDocument
-// MACRO_NAME=TS_ATOM
-
-TS_ATOM(sAAtom, "a")
-TS_ATOM(sAddressAtom, "address")
-TS_ATOM(sBigAtom, "big")
-TS_ATOM(sBAtom, "b")
-TS_ATOM(sCiteAtom, "cite")
-TS_ATOM(sCodeAtom, "code")
-TS_ATOM(sDfnAtom, "dfn")
-TS_ATOM(sEmAtom, "em")
-TS_ATOM(sFontAtom, "font")
-TS_ATOM(sIAtom, "i")
-TS_ATOM(sKbdAtom, "kbd")
-TS_ATOM(sKeygenAtom, "keygen")
-TS_ATOM(sNobrAtom, "nobr")
-TS_ATOM(sSAtom, "s")
-TS_ATOM(sSampAtom, "samp")
-TS_ATOM(sSmallAtom, "small")
-TS_ATOM(sSpacerAtom, "spacer")
-TS_ATOM(sSpanAtom, "span")
-TS_ATOM(sStrikeAtom, "strike")
-TS_ATOM(sStrongAtom, "strong")
-TS_ATOM(sSubAtom, "sub")
-TS_ATOM(sSupAtom, "sup")
-TS_ATOM(sTtAtom, "tt")
-TS_ATOM(sUAtom, "u")
-TS_ATOM(sVarAtom, "var")
-TS_ATOM(sWbrAtom, "wbr")
diff --git a/editor/txtsvc/nsTextServicesCID.h b/editor/txtsvc/nsTextServicesCID.h
deleted file mode 100644
index 62b282134..000000000
--- a/editor/txtsvc/nsTextServicesCID.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsTextServicesCID_h__
-#define nsTextServicesCID_h__
-
-#define NS_TEXTSERVICESDOCUMENTINTERNAL_CID \
-{ /* 019718E2-CDB5-11d2-8D3C-000000000000 */ \
-0x019718e2, 0xcdb5, 0x11d2, \
-{ 0x8d, 0x3c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }
-
-#define NS_TEXTSERVICESDOCUMENT_CID \
-{ /* 019718E3-CDB5-11d2-8D3C-000000000000 */ \
-0x019718e3, 0xcdb5, 0x11d2, \
-{ 0x8d, 0x3c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }
-
-#endif /* nsTextServicesCID_h__ */
diff --git a/editor/txtsvc/nsTextServicesDocument.cpp b/editor/txtsvc/nsTextServicesDocument.cpp
deleted file mode 100644
index 23a1bec3f..000000000
--- a/editor/txtsvc/nsTextServicesDocument.cpp
+++ /dev/null
@@ -1,3514 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <stddef.h> // for nullptr
-
-#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
-#include "mozilla/dom/Selection.h"
-#include "mozilla/mozalloc.h" // for operator new, etc
-#include "nsAString.h" // for nsAString_internal::Length, etc
-#include "nsContentUtils.h" // for nsContentUtils
-#include "nsDebug.h" // for NS_ENSURE_TRUE, etc
-#include "nsDependentSubstring.h" // for Substring
-#include "nsError.h" // for NS_OK, NS_ERROR_FAILURE, etc
-#include "nsFilteredContentIterator.h" // for nsFilteredContentIterator
-#include "nsIContent.h" // for nsIContent, etc
-#include "nsIContentIterator.h" // for nsIContentIterator
-#include "nsID.h" // for NS_GET_IID
-#include "nsIDOMDocument.h" // for nsIDOMDocument
-#include "nsIDOMElement.h" // for nsIDOMElement
-#include "nsIDOMHTMLDocument.h" // for nsIDOMHTMLDocument
-#include "nsIDOMHTMLElement.h" // for nsIDOMHTMLElement
-#include "nsIDOMNode.h" // for nsIDOMNode, etc
-#include "nsIDOMRange.h" // for nsIDOMRange, etc
-#include "nsIEditor.h" // for nsIEditor, etc
-#include "nsINode.h" // for nsINode
-#include "nsIPlaintextEditor.h" // for nsIPlaintextEditor
-#include "nsISelection.h" // for nsISelection
-#include "nsISelectionController.h" // for nsISelectionController, etc
-#include "nsISupportsBase.h" // for nsISupports
-#include "nsISupportsUtils.h" // for NS_IF_ADDREF, NS_ADDREF, etc
-#include "nsITextServicesFilter.h" // for nsITextServicesFilter
-#include "nsIWordBreaker.h" // for nsWordRange, nsIWordBreaker
-#include "nsRange.h" // for nsRange
-#include "nsStaticAtom.h" // for NS_STATIC_ATOM, etc
-#include "nsString.h" // for nsString, nsAutoString
-#include "nsTextServicesDocument.h"
-#include "nscore.h" // for nsresult, NS_IMETHODIMP, etc
-
-#define LOCK_DOC(doc)
-#define UNLOCK_DOC(doc)
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-class OffsetEntry
-{
-public:
- OffsetEntry(nsIDOMNode *aNode, int32_t aOffset, int32_t aLength)
- : mNode(aNode), mNodeOffset(0), mStrOffset(aOffset), mLength(aLength),
- mIsInsertedText(false), mIsValid(true)
- {
- if (mStrOffset < 1) {
- mStrOffset = 0;
- }
- if (mLength < 1) {
- mLength = 0;
- }
- }
-
- virtual ~OffsetEntry()
- {
- mNode = 0;
- mNodeOffset = 0;
- mStrOffset = 0;
- mLength = 0;
- mIsValid = false;
- }
-
- nsIDOMNode *mNode;
- int32_t mNodeOffset;
- int32_t mStrOffset;
- int32_t mLength;
- bool mIsInsertedText;
- bool mIsValid;
-};
-
-#define TS_ATOM(name_, value_) nsIAtom* nsTextServicesDocument::name_ = 0;
-#include "nsTSAtomList.h" // IWYU pragma: keep
-#undef TS_ATOM
-
-nsTextServicesDocument::nsTextServicesDocument()
-{
- mSelStartIndex = -1;
- mSelStartOffset = -1;
- mSelEndIndex = -1;
- mSelEndOffset = -1;
-
- mIteratorStatus = eIsDone;
-}
-
-nsTextServicesDocument::~nsTextServicesDocument()
-{
- ClearOffsetTable(&mOffsetTable);
-}
-
-#define TS_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
-#include "nsTSAtomList.h" // IWYU pragma: keep
-#undef TS_ATOM
-
-/* static */
-void
-nsTextServicesDocument::RegisterAtoms()
-{
- static const nsStaticAtom ts_atoms[] = {
-#define TS_ATOM(name_, value_) NS_STATIC_ATOM(name_##_buffer, &name_),
-#include "nsTSAtomList.h" // IWYU pragma: keep
-#undef TS_ATOM
- };
-
- NS_RegisterStaticAtoms(ts_atoms);
-}
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTextServicesDocument)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTextServicesDocument)
-
-NS_INTERFACE_MAP_BEGIN(nsTextServicesDocument)
- NS_INTERFACE_MAP_ENTRY(nsITextServicesDocument)
- NS_INTERFACE_MAP_ENTRY(nsIEditActionListener)
- NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITextServicesDocument)
- NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsTextServicesDocument)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTION(nsTextServicesDocument,
- mDOMDocument,
- mSelCon,
- mIterator,
- mPrevTextBlock,
- mNextTextBlock,
- mExtent,
- mTxtSvcFilter)
-
-NS_IMETHODIMP
-nsTextServicesDocument::InitWithEditor(nsIEditor *aEditor)
-{
- nsCOMPtr<nsISelectionController> selCon;
- nsCOMPtr<nsIDOMDocument> doc;
-
- NS_ENSURE_TRUE(aEditor, NS_ERROR_NULL_POINTER);
-
- LOCK_DOC(this);
-
- // Check to see if we already have an mSelCon. If we do, it
- // better be the same one the editor uses!
-
- nsresult rv = aEditor->GetSelectionController(getter_AddRefs(selCon));
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- if (!selCon || (mSelCon && selCon != mSelCon)) {
- UNLOCK_DOC(this);
- return NS_ERROR_FAILURE;
- }
-
- if (!mSelCon) {
- mSelCon = selCon;
- }
-
- // Check to see if we already have an mDOMDocument. If we do, it
- // better be the same one the editor uses!
-
- rv = aEditor->GetDocument(getter_AddRefs(doc));
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- if (!doc || (mDOMDocument && doc != mDOMDocument)) {
- UNLOCK_DOC(this);
- return NS_ERROR_FAILURE;
- }
-
- if (!mDOMDocument) {
- mDOMDocument = doc;
-
- rv = CreateDocumentContentIterator(getter_AddRefs(mIterator));
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- mIteratorStatus = nsTextServicesDocument::eIsDone;
-
- rv = FirstBlock();
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
- }
-
- mEditor = do_GetWeakReference(aEditor);
-
- rv = aEditor->AddEditActionListener(this);
-
- UNLOCK_DOC(this);
-
- return rv;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::GetDocument(nsIDOMDocument **aDoc)
-{
- NS_ENSURE_TRUE(aDoc, NS_ERROR_NULL_POINTER);
-
- *aDoc = nullptr; // init out param
- NS_ENSURE_TRUE(mDOMDocument, NS_ERROR_NOT_INITIALIZED);
-
- *aDoc = mDOMDocument;
- NS_ADDREF(*aDoc);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::SetExtent(nsIDOMRange* aDOMRange)
-{
- NS_ENSURE_ARG_POINTER(aDOMRange);
- NS_ENSURE_TRUE(mDOMDocument, NS_ERROR_FAILURE);
-
- LOCK_DOC(this);
-
- // We need to store a copy of aDOMRange since we don't
- // know where it came from.
-
- mExtent = static_cast<nsRange*>(aDOMRange)->CloneRange();
-
- // Create a new iterator based on our new extent range.
-
- nsresult rv = CreateContentIterator(mExtent, getter_AddRefs(mIterator));
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- // Now position the iterator at the start of the first block
- // in the range.
-
- mIteratorStatus = nsTextServicesDocument::eIsDone;
-
- rv = FirstBlock();
-
- UNLOCK_DOC(this);
-
- return rv;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::ExpandRangeToWordBoundaries(nsIDOMRange *aRange)
-{
- NS_ENSURE_ARG_POINTER(aRange);
- RefPtr<nsRange> range = static_cast<nsRange*>(aRange);
-
- // Get the end points of the range.
-
- nsCOMPtr<nsIDOMNode> rngStartNode, rngEndNode;
- int32_t rngStartOffset, rngEndOffset;
-
- nsresult rv = GetRangeEndPoints(range, getter_AddRefs(rngStartNode),
- &rngStartOffset,
- getter_AddRefs(rngEndNode),
- &rngEndOffset);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Create a content iterator based on the range.
-
- nsCOMPtr<nsIContentIterator> iter;
- rv = CreateContentIterator(range, getter_AddRefs(iter));
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Find the first text node in the range.
-
- TSDIteratorStatus iterStatus;
-
- rv = FirstTextNode(iter, &iterStatus);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (iterStatus == nsTextServicesDocument::eIsDone) {
- // No text was found so there's no adjustment necessary!
- return NS_OK;
- }
-
- nsINode *firstText = iter->GetCurrentNode();
- NS_ENSURE_TRUE(firstText, NS_ERROR_FAILURE);
-
- // Find the last text node in the range.
-
- rv = LastTextNode(iter, &iterStatus);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (iterStatus == nsTextServicesDocument::eIsDone) {
- // We should never get here because a first text block
- // was found above.
- NS_ASSERTION(false, "Found a first without a last!");
- return NS_ERROR_FAILURE;
- }
-
- nsINode *lastText = iter->GetCurrentNode();
- NS_ENSURE_TRUE(lastText, NS_ERROR_FAILURE);
-
- // Now make sure our end points are in terms of text nodes in the range!
-
- nsCOMPtr<nsIDOMNode> firstTextNode = do_QueryInterface(firstText);
- NS_ENSURE_TRUE(firstTextNode, NS_ERROR_FAILURE);
-
- if (rngStartNode != firstTextNode) {
- // The range includes the start of the first text node!
- rngStartNode = firstTextNode;
- rngStartOffset = 0;
- }
-
- nsCOMPtr<nsIDOMNode> lastTextNode = do_QueryInterface(lastText);
- NS_ENSURE_TRUE(lastTextNode, NS_ERROR_FAILURE);
-
- if (rngEndNode != lastTextNode) {
- // The range includes the end of the last text node!
- rngEndNode = lastTextNode;
- nsAutoString str;
- lastTextNode->GetNodeValue(str);
- rngEndOffset = str.Length();
- }
-
- // Create a doc iterator so that we can scan beyond
- // the bounds of the extent range.
-
- nsCOMPtr<nsIContentIterator> docIter;
- rv = CreateDocumentContentIterator(getter_AddRefs(docIter));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Grab all the text in the block containing our
- // first text node.
-
- rv = docIter->PositionAt(firstText);
- NS_ENSURE_SUCCESS(rv, rv);
-
- iterStatus = nsTextServicesDocument::eValid;
-
- nsTArray<OffsetEntry*> offsetTable;
- nsAutoString blockStr;
-
- rv = CreateOffsetTable(&offsetTable, docIter, &iterStatus,
- nullptr, &blockStr);
- if (NS_FAILED(rv)) {
- ClearOffsetTable(&offsetTable);
- return rv;
- }
-
- nsCOMPtr<nsIDOMNode> wordStartNode, wordEndNode;
- int32_t wordStartOffset, wordEndOffset;
-
- rv = FindWordBounds(&offsetTable, &blockStr,
- rngStartNode, rngStartOffset,
- getter_AddRefs(wordStartNode), &wordStartOffset,
- getter_AddRefs(wordEndNode), &wordEndOffset);
-
- ClearOffsetTable(&offsetTable);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- rngStartNode = wordStartNode;
- rngStartOffset = wordStartOffset;
-
- // Grab all the text in the block containing our
- // last text node.
-
- rv = docIter->PositionAt(lastText);
- NS_ENSURE_SUCCESS(rv, rv);
-
- iterStatus = nsTextServicesDocument::eValid;
-
- rv = CreateOffsetTable(&offsetTable, docIter, &iterStatus,
- nullptr, &blockStr);
- if (NS_FAILED(rv)) {
- ClearOffsetTable(&offsetTable);
- return rv;
- }
-
- rv = FindWordBounds(&offsetTable, &blockStr,
- rngEndNode, rngEndOffset,
- getter_AddRefs(wordStartNode), &wordStartOffset,
- getter_AddRefs(wordEndNode), &wordEndOffset);
-
- ClearOffsetTable(&offsetTable);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- // To prevent expanding the range too much, we only change
- // rngEndNode and rngEndOffset if it isn't already at the start of the
- // word and isn't equivalent to rngStartNode and rngStartOffset.
-
- if (rngEndNode != wordStartNode ||
- rngEndOffset != wordStartOffset ||
- (rngEndNode == rngStartNode && rngEndOffset == rngStartOffset)) {
- rngEndNode = wordEndNode;
- rngEndOffset = wordEndOffset;
- }
-
- // Now adjust the range so that it uses our new
- // end points.
- nsCOMPtr<nsINode> startNode = do_QueryInterface(rngStartNode);
- nsCOMPtr<nsINode> endNode = do_QueryInterface(rngEndNode);
- rv = range->SetStartAndEnd(startNode, rngStartOffset, endNode, rngEndOffset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::SetFilter(nsITextServicesFilter *aFilter)
-{
- // Hang on to the filter so we can set it into the filtered iterator.
- mTxtSvcFilter = aFilter;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::GetCurrentTextBlock(nsString *aStr)
-{
- NS_ENSURE_TRUE(aStr, NS_ERROR_NULL_POINTER);
-
- aStr->Truncate();
-
- NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
-
- LOCK_DOC(this);
-
- nsresult rv = CreateOffsetTable(&mOffsetTable, mIterator, &mIteratorStatus,
- mExtent, aStr);
-
- UNLOCK_DOC(this);
-
- return rv;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::FirstBlock()
-{
- NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
-
- LOCK_DOC(this);
-
- nsresult rv = FirstTextNode(mIterator, &mIteratorStatus);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- // Keep track of prev and next blocks, just in case
- // the text service blows away the current block.
-
- if (mIteratorStatus == nsTextServicesDocument::eValid) {
- mPrevTextBlock = nullptr;
- rv = GetFirstTextNodeInNextBlock(getter_AddRefs(mNextTextBlock));
- } else {
- // There's no text block in the document!
-
- mPrevTextBlock = nullptr;
- mNextTextBlock = nullptr;
- }
-
- UNLOCK_DOC(this);
-
- // XXX Result of FirstTextNode() or GetFirstTextNodeInNextBlock().
- return rv;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::LastSelectedBlock(TSDBlockSelectionStatus *aSelStatus,
- int32_t *aSelOffset,
- int32_t *aSelLength)
-{
- NS_ENSURE_TRUE(aSelStatus && aSelOffset && aSelLength, NS_ERROR_NULL_POINTER);
-
- LOCK_DOC(this);
-
- mIteratorStatus = nsTextServicesDocument::eIsDone;
-
- *aSelStatus = nsITextServicesDocument::eBlockNotFound;
- *aSelOffset = *aSelLength = -1;
-
- if (!mSelCon || !mIterator) {
- UNLOCK_DOC(this);
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsISelection> domSelection;
- nsresult rv = mSelCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
- getter_AddRefs(domSelection));
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- RefPtr<Selection> selection = domSelection->AsSelection();
-
- bool isCollapsed = selection->IsCollapsed();
-
- nsCOMPtr<nsIContentIterator> iter;
- RefPtr<nsRange> range;
- nsCOMPtr<nsIDOMNode> parent;
-
- if (isCollapsed) {
- // We have a caret. Check if the caret is in a text node.
- // If it is, make the text node's block the current block.
- // If the caret isn't in a text node, search forwards in
- // the document, till we find a text node.
-
- range = selection->GetRangeAt(0);
-
- if (!range) {
- UNLOCK_DOC(this);
- return NS_ERROR_FAILURE;
- }
-
- rv = range->GetStartContainer(getter_AddRefs(parent));
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- if (!parent) {
- UNLOCK_DOC(this);
- return NS_ERROR_FAILURE;
- }
-
- uint32_t offset;
- rv = range->GetStartOffset(&offset);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- if (IsTextNode(parent)) {
- // The caret is in a text node. Find the beginning
- // of the text block containing this text node and
- // return.
-
- nsCOMPtr<nsIContent> content(do_QueryInterface(parent));
-
- if (!content) {
- UNLOCK_DOC(this);
- return NS_ERROR_FAILURE;
- }
-
- rv = mIterator->PositionAt(content);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- rv = FirstTextNodeInCurrentBlock(mIterator);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- mIteratorStatus = nsTextServicesDocument::eValid;
-
- rv = CreateOffsetTable(&mOffsetTable, mIterator, &mIteratorStatus,
- mExtent, nullptr);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- rv = GetSelection(aSelStatus, aSelOffset, aSelLength);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- if (*aSelStatus == nsITextServicesDocument::eBlockContains) {
- rv = SetSelectionInternal(*aSelOffset, *aSelLength, false);
- }
- } else {
- // The caret isn't in a text node. Create an iterator
- // based on a range that extends from the current caret
- // position to the end of the document, then walk forwards
- // till you find a text node, then find the beginning of it's block.
-
- rv = CreateDocumentContentRootToNodeOffsetRange(
- parent, static_cast<int32_t>(offset), false,
- getter_AddRefs(range));
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- rv = range->GetCollapsed(&isCollapsed);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- if (isCollapsed) {
- // If we get here, the range is collapsed because there is nothing after
- // the caret! Just return NS_OK;
-
- UNLOCK_DOC(this);
- return NS_OK;
- }
-
- rv = CreateContentIterator(range, getter_AddRefs(iter));
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- iter->First();
-
- nsCOMPtr<nsIContent> content;
- while (!iter->IsDone()) {
- content = do_QueryInterface(iter->GetCurrentNode());
-
- if (IsTextNode(content)) {
- break;
- }
-
- content = nullptr;
-
- iter->Next();
- }
-
- if (!content) {
- UNLOCK_DOC(this);
- return NS_OK;
- }
-
- rv = mIterator->PositionAt(content);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- rv = FirstTextNodeInCurrentBlock(mIterator);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- mIteratorStatus = nsTextServicesDocument::eValid;
-
- rv = CreateOffsetTable(&mOffsetTable, mIterator, &mIteratorStatus,
- mExtent, nullptr);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- rv = GetSelection(aSelStatus, aSelOffset, aSelLength);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
- }
-
- UNLOCK_DOC(this);
-
- // Result of SetSelectionInternal() in the |if| block or NS_OK.
- return rv;
- }
-
- // If we get here, we have an uncollapsed selection!
- // Look backwards through each range in the selection till you
- // find the first text node. If you find one, find the
- // beginning of its text block, and make it the current
- // block.
-
- int32_t rangeCount;
- rv = selection->GetRangeCount(&rangeCount);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- NS_ASSERTION(rangeCount > 0, "Unexpected range count!");
-
- if (rangeCount <= 0) {
- UNLOCK_DOC(this);
- return NS_OK;
- }
-
- // XXX: We may need to add some code here to make sure
- // the ranges are sorted in document appearance order!
-
- for (int32_t i = rangeCount - 1; i >= 0; i--) {
- // Get the i'th range from the selection.
-
- range = selection->GetRangeAt(i);
-
- if (!range) {
- UNLOCK_DOC(this);
- return NS_OK; // XXX Really?
- }
-
- // Create an iterator for the range.
-
- rv = CreateContentIterator(range, getter_AddRefs(iter));
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- iter->Last();
-
- // Now walk through the range till we find a text node.
-
- while (!iter->IsDone()) {
- if (iter->GetCurrentNode()->NodeType() == nsIDOMNode::TEXT_NODE) {
- // We found a text node, so position the document's
- // iterator at the beginning of the block, then get
- // the selection in terms of the string offset.
- nsCOMPtr<nsIContent> content = iter->GetCurrentNode()->AsContent();
-
- rv = mIterator->PositionAt(content);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- rv = FirstTextNodeInCurrentBlock(mIterator);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- mIteratorStatus = nsTextServicesDocument::eValid;
-
- rv = CreateOffsetTable(&mOffsetTable, mIterator, &mIteratorStatus,
- mExtent, nullptr);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- rv = GetSelection(aSelStatus, aSelOffset, aSelLength);
-
- UNLOCK_DOC(this);
-
- return rv;
-
- }
-
- iter->Prev();
- }
- }
-
- // If we get here, we didn't find any text node in the selection!
- // Create a range that extends from the end of the selection,
- // to the end of the document, then iterate forwards through
- // it till you find a text node!
-
- range = selection->GetRangeAt(rangeCount - 1);
-
- if (!range) {
- UNLOCK_DOC(this);
- return NS_ERROR_FAILURE;
- }
-
- rv = range->GetEndContainer(getter_AddRefs(parent));
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- if (!parent) {
- UNLOCK_DOC(this);
- return NS_ERROR_FAILURE;
- }
-
- uint32_t offset;
- rv = range->GetEndOffset(&offset);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- rv = CreateDocumentContentRootToNodeOffsetRange(
- parent, static_cast<int32_t>(offset), false, getter_AddRefs(range));
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- rv = range->GetCollapsed(&isCollapsed);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- if (isCollapsed) {
- // If we get here, the range is collapsed because there is nothing after
- // the current selection! Just return NS_OK;
-
- UNLOCK_DOC(this);
- return NS_OK;
- }
-
- rv = CreateContentIterator(range, getter_AddRefs(iter));
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- iter->First();
-
- while (!iter->IsDone()) {
- if (iter->GetCurrentNode()->NodeType() == nsIDOMNode::TEXT_NODE) {
- // We found a text node! Adjust the document's iterator to point
- // to the beginning of its text block, then get the current selection.
- nsCOMPtr<nsIContent> content = iter->GetCurrentNode()->AsContent();
-
- rv = mIterator->PositionAt(content);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- rv = FirstTextNodeInCurrentBlock(mIterator);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
-
- mIteratorStatus = nsTextServicesDocument::eValid;
-
- rv = CreateOffsetTable(&mOffsetTable, mIterator, &mIteratorStatus,
- mExtent, nullptr);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- rv = GetSelection(aSelStatus, aSelOffset, aSelLength);
-
- UNLOCK_DOC(this);
-
- return rv;
- }
-
- iter->Next();
- }
-
- // If we get here, we didn't find any block before or inside
- // the selection! Just return OK.
-
- UNLOCK_DOC(this);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::PrevBlock()
-{
- NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
-
- LOCK_DOC(this);
-
- if (mIteratorStatus == nsTextServicesDocument::eIsDone) {
- return NS_OK;
- }
-
- switch (mIteratorStatus) {
- case nsTextServicesDocument::eValid:
- case nsTextServicesDocument::eNext: {
-
- nsresult rv = FirstTextNodeInPrevBlock(mIterator);
-
- if (NS_FAILED(rv)) {
- mIteratorStatus = nsTextServicesDocument::eIsDone;
- UNLOCK_DOC(this);
- return rv;
- }
-
- if (mIterator->IsDone()) {
- mIteratorStatus = nsTextServicesDocument::eIsDone;
- UNLOCK_DOC(this);
- return NS_OK;
- }
-
- mIteratorStatus = nsTextServicesDocument::eValid;
- break;
- }
- case nsTextServicesDocument::ePrev:
-
- // The iterator already points to the previous
- // block, so don't do anything.
-
- mIteratorStatus = nsTextServicesDocument::eValid;
- break;
-
- default:
-
- mIteratorStatus = nsTextServicesDocument::eIsDone;
- break;
- }
-
- // Keep track of prev and next blocks, just in case
- // the text service blows away the current block.
- nsresult rv = NS_OK;
- if (mIteratorStatus == nsTextServicesDocument::eValid) {
- GetFirstTextNodeInPrevBlock(getter_AddRefs(mPrevTextBlock));
- rv = GetFirstTextNodeInNextBlock(getter_AddRefs(mNextTextBlock));
- } else {
- // We must be done!
- mPrevTextBlock = nullptr;
- mNextTextBlock = nullptr;
- }
-
- UNLOCK_DOC(this);
-
- // XXX The result of GetFirstTextNodeInNextBlock() or NS_OK.
- return rv;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::NextBlock()
-{
- NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
-
- LOCK_DOC(this);
-
- if (mIteratorStatus == nsTextServicesDocument::eIsDone) {
- return NS_OK;
- }
-
- switch (mIteratorStatus) {
- case nsTextServicesDocument::eValid: {
-
- // Advance the iterator to the next text block.
-
- nsresult rv = FirstTextNodeInNextBlock(mIterator);
-
- if (NS_FAILED(rv)) {
- mIteratorStatus = nsTextServicesDocument::eIsDone;
- UNLOCK_DOC(this);
- return rv;
- }
-
- if (mIterator->IsDone()) {
- mIteratorStatus = nsTextServicesDocument::eIsDone;
- UNLOCK_DOC(this);
- return NS_OK;
- }
-
- mIteratorStatus = nsTextServicesDocument::eValid;
- break;
- }
- case nsTextServicesDocument::eNext:
-
- // The iterator already points to the next block,
- // so don't do anything to it!
-
- mIteratorStatus = nsTextServicesDocument::eValid;
- break;
-
- case nsTextServicesDocument::ePrev:
-
- // If the iterator is pointing to the previous block,
- // we know that there is no next text block! Just
- // fall through to the default case!
-
- default:
-
- mIteratorStatus = nsTextServicesDocument::eIsDone;
- break;
- }
-
- // Keep track of prev and next blocks, just in case
- // the text service blows away the current block.
- nsresult rv = NS_OK;
- if (mIteratorStatus == nsTextServicesDocument::eValid) {
- GetFirstTextNodeInPrevBlock(getter_AddRefs(mPrevTextBlock));
- rv = GetFirstTextNodeInNextBlock(getter_AddRefs(mNextTextBlock));
- } else {
- // We must be done.
- mPrevTextBlock = nullptr;
- mNextTextBlock = nullptr;
- }
-
- UNLOCK_DOC(this);
-
- // The result of GetFirstTextNodeInNextBlock() or NS_OK.
- return rv;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::IsDone(bool *aIsDone)
-{
- NS_ENSURE_TRUE(aIsDone, NS_ERROR_NULL_POINTER);
-
- *aIsDone = false;
-
- NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
-
- LOCK_DOC(this);
-
- *aIsDone = (mIteratorStatus == nsTextServicesDocument::eIsDone) ? true : false;
-
- UNLOCK_DOC(this);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::SetSelection(int32_t aOffset, int32_t aLength)
-{
- NS_ENSURE_TRUE(mSelCon && aOffset >= 0 && aLength >= 0, NS_ERROR_FAILURE);
-
- LOCK_DOC(this);
-
- nsresult rv = SetSelectionInternal(aOffset, aLength, true);
-
- UNLOCK_DOC(this);
-
- //**** KDEBUG ****
- // printf("\n * Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset);
- //**** KDEBUG ****
-
- return rv;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::ScrollSelectionIntoView()
-{
- NS_ENSURE_TRUE(mSelCon, NS_ERROR_FAILURE);
-
- LOCK_DOC(this);
-
- // After ScrollSelectionIntoView(), the pending notifications might be flushed
- // and PresShell/PresContext/Frames may be dead. See bug 418470.
- nsresult rv =
- mSelCon->ScrollSelectionIntoView(
- nsISelectionController::SELECTION_NORMAL,
- nsISelectionController::SELECTION_FOCUS_REGION,
- nsISelectionController::SCROLL_SYNCHRONOUS);
-
- UNLOCK_DOC(this);
-
- return rv;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::DeleteSelection()
-{
- // We don't allow deletion during a collapsed selection!
- nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
- NS_ASSERTION(editor, "DeleteSelection called without an editor present!");
- NS_ASSERTION(SelectionIsValid(), "DeleteSelection called without a valid selection!");
-
- if (!editor || !SelectionIsValid()) {
- return NS_ERROR_FAILURE;
- }
- if (SelectionIsCollapsed()) {
- return NS_OK;
- }
-
- LOCK_DOC(this);
-
- //**** KDEBUG ****
- // printf("\n---- Before Delete\n");
- // printf("Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset);
- // PrintOffsetTable();
- //**** KDEBUG ****
-
- // If we have an mExtent, save off its current set of
- // end points so we can compare them against mExtent's
- // set after the deletion of the content.
-
- nsCOMPtr<nsIDOMNode> origStartNode, origEndNode;
- int32_t origStartOffset = 0, origEndOffset = 0;
-
- if (mExtent) {
- nsresult rv =
- GetRangeEndPoints(mExtent,
- getter_AddRefs(origStartNode), &origStartOffset,
- getter_AddRefs(origEndNode), &origEndOffset);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
- }
-
- int32_t selLength;
- OffsetEntry *entry, *newEntry;
-
- for (int32_t i = mSelStartIndex; i <= mSelEndIndex; i++) {
- entry = mOffsetTable[i];
-
- if (i == mSelStartIndex) {
- // Calculate the length of the selection. Note that the
- // selection length can be zero if the start of the selection
- // is at the very end of a text node entry.
-
- if (entry->mIsInsertedText) {
- // Inserted text offset entries have no width when
- // talking in terms of string offsets! If the beginning
- // of the selection is in an inserted text offset entry,
- // the caret is always at the end of the entry!
-
- selLength = 0;
- } else {
- selLength = entry->mLength - (mSelStartOffset - entry->mStrOffset);
- }
-
- if (selLength > 0 && mSelStartOffset > entry->mStrOffset) {
- // Selection doesn't start at the beginning of the
- // text node entry. We need to split this entry into
- // two pieces, the piece before the selection, and
- // the piece inside the selection.
-
- nsresult rv = SplitOffsetEntry(i, selLength);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- // Adjust selection indexes to account for new entry:
-
- ++mSelStartIndex;
- ++mSelEndIndex;
- ++i;
-
- entry = mOffsetTable[i];
- }
-
-
- if (selLength > 0 && mSelStartIndex < mSelEndIndex) {
- // The entire entry is contained in the selection. Mark the
- // entry invalid.
- entry->mIsValid = false;
- }
- }
-
- //**** KDEBUG ****
- // printf("\n---- Middle Delete\n");
- // printf("Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset);
- // PrintOffsetTable();
- //**** KDEBUG ****
-
- if (i == mSelEndIndex) {
- if (entry->mIsInsertedText) {
- // Inserted text offset entries have no width when
- // talking in terms of string offsets! If the end
- // of the selection is in an inserted text offset entry,
- // the selection includes the entire entry!
-
- entry->mIsValid = false;
- } else {
- // Calculate the length of the selection. Note that the
- // selection length can be zero if the end of the selection
- // is at the very beginning of a text node entry.
-
- selLength = mSelEndOffset - entry->mStrOffset;
-
- if (selLength > 0 &&
- mSelEndOffset < entry->mStrOffset + entry->mLength) {
- // mStrOffset is guaranteed to be inside the selection, even
- // when mSelStartIndex == mSelEndIndex.
-
- nsresult rv = SplitOffsetEntry(i, entry->mLength - selLength);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- // Update the entry fields:
-
- newEntry = mOffsetTable[i+1];
- newEntry->mNodeOffset = entry->mNodeOffset;
- }
-
-
- if (selLength > 0 &&
- mSelEndOffset == entry->mStrOffset + entry->mLength) {
- // The entire entry is contained in the selection. Mark the
- // entry invalid.
- entry->mIsValid = false;
- }
- }
- }
-
- if (i != mSelStartIndex && i != mSelEndIndex) {
- // The entire entry is contained in the selection. Mark the
- // entry invalid.
- entry->mIsValid = false;
- }
- }
-
- // Make sure mIterator always points to something valid!
-
- AdjustContentIterator();
-
- // Now delete the actual content!
-
- nsresult rv =
- editor->DeleteSelection(nsIEditor::ePrevious, nsIEditor::eStrip);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- // Now that we've actually deleted the selected content,
- // check to see if our mExtent has changed, if so, then
- // we have to create a new content iterator!
-
- if (origStartNode && origEndNode) {
- nsCOMPtr<nsIDOMNode> curStartNode, curEndNode;
- int32_t curStartOffset = 0, curEndOffset = 0;
-
- rv = GetRangeEndPoints(mExtent,
- getter_AddRefs(curStartNode), &curStartOffset,
- getter_AddRefs(curEndNode), &curEndOffset);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- if (origStartNode != curStartNode || origEndNode != curEndNode) {
- // The range has changed, so we need to create a new content
- // iterator based on the new range.
-
- nsCOMPtr<nsIContent> curContent;
-
- if (mIteratorStatus != nsTextServicesDocument::eIsDone) {
- // The old iterator is still pointing to something valid,
- // so get its current node so we can restore it after we
- // create the new iterator!
-
- curContent = mIterator->GetCurrentNode()
- ? mIterator->GetCurrentNode()->AsContent()
- : nullptr;
- }
-
- // Create the new iterator.
-
- rv = CreateContentIterator(mExtent, getter_AddRefs(mIterator));
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- // Now make the new iterator point to the content node
- // the old one was pointing at.
-
- if (curContent) {
- rv = mIterator->PositionAt(curContent);
-
- if (NS_FAILED(rv)) {
- mIteratorStatus = eIsDone;
- } else {
- mIteratorStatus = eValid;
- }
- }
- }
- }
-
- entry = 0;
-
- // Move the caret to the end of the first valid entry.
- // Start with mSelStartIndex since it may still be valid.
-
- for (int32_t i = mSelStartIndex; !entry && i >= 0; i--) {
- entry = mOffsetTable[i];
-
- if (!entry->mIsValid) {
- entry = 0;
- } else {
- mSelStartIndex = mSelEndIndex = i;
- mSelStartOffset = mSelEndOffset = entry->mStrOffset + entry->mLength;
- }
- }
-
- // If we still don't have a valid entry, move the caret
- // to the next valid entry after the selection:
-
- for (int32_t i = mSelEndIndex;
- !entry && i < static_cast<int32_t>(mOffsetTable.Length()); i++) {
- entry = mOffsetTable[i];
-
- if (!entry->mIsValid) {
- entry = 0;
- } else {
- mSelStartIndex = mSelEndIndex = i;
- mSelStartOffset = mSelEndOffset = entry->mStrOffset;
- }
- }
-
- if (entry) {
- SetSelection(mSelStartOffset, 0);
- } else {
- // Uuughh we have no valid offset entry to place our
- // caret ... just mark the selection invalid.
- mSelStartIndex = mSelEndIndex = -1;
- mSelStartOffset = mSelEndOffset = -1;
- }
-
- // Now remove any invalid entries from the offset table.
-
- rv = RemoveInvalidOffsetEntries();
-
- //**** KDEBUG ****
- // printf("\n---- After Delete\n");
- // printf("Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset);
- // PrintOffsetTable();
- //**** KDEBUG ****
-
- UNLOCK_DOC(this);
-
- return rv;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::InsertText(const nsString *aText)
-{
- nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
- NS_ASSERTION(editor, "InsertText called without an editor present!");
-
- if (!editor || !SelectionIsValid()) {
- return NS_ERROR_FAILURE;
- }
-
- NS_ENSURE_TRUE(aText, NS_ERROR_NULL_POINTER);
-
- // If the selection is not collapsed, we need to save
- // off the selection offsets so we can restore the
- // selection and delete the selected content after we've
- // inserted the new text. This is necessary to try and
- // retain as much of the original style of the content
- // being deleted.
-
- bool collapsedSelection = SelectionIsCollapsed();
- int32_t savedSelOffset = mSelStartOffset;
- int32_t savedSelLength = mSelEndOffset - mSelStartOffset;
-
- if (!collapsedSelection) {
- // Collapse to the start of the current selection
- // for the insert!
-
- nsresult rv = SetSelection(mSelStartOffset, 0);
-
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
-
- LOCK_DOC(this);
-
- nsresult rv = editor->BeginTransaction();
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- nsCOMPtr<nsIPlaintextEditor> textEditor (do_QueryInterface(editor, &rv));
- if (textEditor) {
- rv = textEditor->InsertText(*aText);
- }
-
- if (NS_FAILED(rv)) {
- editor->EndTransaction();
- UNLOCK_DOC(this);
- return rv;
- }
-
- //**** KDEBUG ****
- // printf("\n---- Before Insert\n");
- // printf("Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset);
- // PrintOffsetTable();
- //**** KDEBUG ****
-
- int32_t strLength = aText->Length();
-
- nsCOMPtr<nsISelection> selection;
- OffsetEntry *itEntry;
- OffsetEntry *entry = mOffsetTable[mSelStartIndex];
- void *node = entry->mNode;
-
- NS_ASSERTION((entry->mIsValid), "Invalid insertion point!");
-
- if (entry->mStrOffset == mSelStartOffset) {
- if (entry->mIsInsertedText) {
- // If the caret is in an inserted text offset entry,
- // we simply insert the text at the end of the entry.
-
- entry->mLength += strLength;
- } else {
- // Insert an inserted text offset entry before the current
- // entry!
-
- itEntry = new OffsetEntry(entry->mNode, entry->mStrOffset, strLength);
-
- if (!itEntry) {
- editor->EndTransaction();
- UNLOCK_DOC(this);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- itEntry->mIsInsertedText = true;
- itEntry->mNodeOffset = entry->mNodeOffset;
-
- if (!mOffsetTable.InsertElementAt(mSelStartIndex, itEntry)) {
- editor->EndTransaction();
- UNLOCK_DOC(this);
- return NS_ERROR_FAILURE;
- }
- }
- } else if (entry->mStrOffset + entry->mLength == mSelStartOffset) {
- // We are inserting text at the end of the current offset entry.
- // Look at the next valid entry in the table. If it's an inserted
- // text entry, add to its length and adjust its node offset. If
- // it isn't, add a new inserted text entry.
-
- // XXX Rename this!
- uint32_t i = mSelStartIndex + 1;
- itEntry = 0;
-
- if (mOffsetTable.Length() > i) {
- itEntry = mOffsetTable[i];
-
- if (!itEntry) {
- editor->EndTransaction();
- UNLOCK_DOC(this);
- return NS_ERROR_FAILURE;
- }
-
- // Check if the entry is a match. If it isn't, set
- // iEntry to zero.
-
- if (!itEntry->mIsInsertedText || itEntry->mStrOffset != mSelStartOffset) {
- itEntry = 0;
- }
- }
-
- if (!itEntry) {
- // We didn't find an inserted text offset entry, so
- // create one.
-
- itEntry = new OffsetEntry(entry->mNode, mSelStartOffset, 0);
-
- if (!itEntry) {
- editor->EndTransaction();
- UNLOCK_DOC(this);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- itEntry->mNodeOffset = entry->mNodeOffset + entry->mLength;
- itEntry->mIsInsertedText = true;
-
- if (!mOffsetTable.InsertElementAt(i, itEntry)) {
- delete itEntry;
- return NS_ERROR_FAILURE;
- }
- }
-
- // We have a valid inserted text offset entry. Update its
- // length, adjust the selection indexes, and make sure the
- // caret is properly placed!
-
- itEntry->mLength += strLength;
-
- mSelStartIndex = mSelEndIndex = i;
-
- rv = mSelCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
- getter_AddRefs(selection));
-
- if (NS_FAILED(rv)) {
- editor->EndTransaction();
- UNLOCK_DOC(this);
- return rv;
- }
-
- rv = selection->Collapse(itEntry->mNode,
- itEntry->mNodeOffset + itEntry->mLength);
-
- if (NS_FAILED(rv)) {
- editor->EndTransaction();
- UNLOCK_DOC(this);
- return rv;
- }
- } else if (entry->mStrOffset + entry->mLength > mSelStartOffset) {
- // We are inserting text into the middle of the current offset entry.
- // split the current entry into two parts, then insert an inserted text
- // entry between them!
-
- // XXX Rename this!
- uint32_t i = entry->mLength - (mSelStartOffset - entry->mStrOffset);
-
- rv = SplitOffsetEntry(mSelStartIndex, i);
-
- if (NS_FAILED(rv)) {
- editor->EndTransaction();
- UNLOCK_DOC(this);
- return rv;
- }
-
- itEntry = new OffsetEntry(entry->mNode, mSelStartOffset, strLength);
-
- if (!itEntry) {
- editor->EndTransaction();
- UNLOCK_DOC(this);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- itEntry->mIsInsertedText = true;
- itEntry->mNodeOffset = entry->mNodeOffset + entry->mLength;
-
- if (!mOffsetTable.InsertElementAt(mSelStartIndex + 1, itEntry)) {
- editor->EndTransaction();
- UNLOCK_DOC(this);
- return NS_ERROR_FAILURE;
- }
-
- mSelEndIndex = ++mSelStartIndex;
- }
-
- // We've just finished inserting an inserted text offset entry.
- // update all entries with the same mNode pointer that follow
- // it in the table!
-
- for (size_t i = mSelStartIndex + 1; i < mOffsetTable.Length(); i++) {
- entry = mOffsetTable[i];
- if (entry->mNode != node) {
- break;
- }
- if (entry->mIsValid) {
- entry->mNodeOffset += strLength;
- }
- }
-
- //**** KDEBUG ****
- // printf("\n---- After Insert\n");
- // printf("Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset);
- // PrintOffsetTable();
- //**** KDEBUG ****
-
- if (!collapsedSelection) {
- rv = SetSelection(savedSelOffset, savedSelLength);
-
- if (NS_FAILED(rv)) {
- editor->EndTransaction();
- UNLOCK_DOC(this);
- return rv;
- }
-
- rv = DeleteSelection();
-
- if (NS_FAILED(rv)) {
- editor->EndTransaction();
- UNLOCK_DOC(this);
- return rv;
- }
- }
-
- rv = editor->EndTransaction();
-
- UNLOCK_DOC(this);
-
- return rv;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::DidInsertNode(nsIDOMNode *aNode,
- nsIDOMNode *aParent,
- int32_t aPosition,
- nsresult aResult)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::DidDeleteNode(nsIDOMNode *aChild, nsresult aResult)
-{
- NS_ENSURE_SUCCESS(aResult, NS_OK);
-
- NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
-
- //**** KDEBUG ****
- // printf("** DeleteNode: 0x%.8x\n", aChild);
- // fflush(stdout);
- //**** KDEBUG ****
-
- LOCK_DOC(this);
-
- int32_t nodeIndex = 0;
- bool hasEntry = false;
- OffsetEntry *entry;
-
- nsresult rv =
- NodeHasOffsetEntry(&mOffsetTable, aChild, &hasEntry, &nodeIndex);
-
- if (NS_FAILED(rv)) {
- UNLOCK_DOC(this);
- return rv;
- }
-
- if (!hasEntry) {
- // It's okay if the node isn't in the offset table, the
- // editor could be cleaning house.
- UNLOCK_DOC(this);
- return NS_OK;
- }
-
- nsCOMPtr<nsIDOMNode> node = do_QueryInterface(mIterator->GetCurrentNode());
-
- if (node && node == aChild &&
- mIteratorStatus != nsTextServicesDocument::eIsDone) {
- // XXX: This should never really happen because
- // AdjustContentIterator() should have been called prior
- // to the delete to try and position the iterator on the
- // next valid text node in the offset table, and if there
- // wasn't a next, it would've set mIteratorStatus to eIsDone.
-
- NS_ERROR("DeleteNode called for current iterator node.");
- }
-
- int32_t tcount = mOffsetTable.Length();
-
- while (nodeIndex < tcount) {
- entry = mOffsetTable[nodeIndex];
-
- if (!entry) {
- UNLOCK_DOC(this);
- return NS_ERROR_FAILURE;
- }
-
- if (entry->mNode == aChild) {
- entry->mIsValid = false;
- }
-
- nodeIndex++;
- }
-
- UNLOCK_DOC(this);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::DidSplitNode(nsIDOMNode *aExistingRightNode,
- int32_t aOffset,
- nsIDOMNode *aNewLeftNode,
- nsresult aResult)
-{
- //**** KDEBUG ****
- // printf("** SplitNode: 0x%.8x %d 0x%.8x\n", aExistingRightNode, aOffset, aNewLeftNode);
- // fflush(stdout);
- //**** KDEBUG ****
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::DidJoinNodes(nsIDOMNode *aLeftNode,
- nsIDOMNode *aRightNode,
- nsIDOMNode *aParent,
- nsresult aResult)
-{
- NS_ENSURE_SUCCESS(aResult, NS_OK);
-
- //**** KDEBUG ****
- // printf("** JoinNodes: 0x%.8x 0x%.8x 0x%.8x\n", aLeftNode, aRightNode, aParent);
- // fflush(stdout);
- //**** KDEBUG ****
-
- // Make sure that both nodes are text nodes -- otherwise we don't care.
-
- uint16_t type;
- nsresult rv = aLeftNode->GetNodeType(&type);
- NS_ENSURE_SUCCESS(rv, NS_OK);
- if (nsIDOMNode::TEXT_NODE != type) {
- return NS_OK;
- }
-
- rv = aRightNode->GetNodeType(&type);
- NS_ENSURE_SUCCESS(rv, NS_OK);
- if (nsIDOMNode::TEXT_NODE != type) {
- return NS_OK;
- }
-
- // Note: The editor merges the contents of the left node into the
- // contents of the right.
-
- int32_t leftIndex = 0;
- int32_t rightIndex = 0;
- bool leftHasEntry = false;
- bool rightHasEntry = false;
-
- rv = NodeHasOffsetEntry(&mOffsetTable, aLeftNode, &leftHasEntry, &leftIndex);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!leftHasEntry) {
- // It's okay if the node isn't in the offset table, the
- // editor could be cleaning house.
- return NS_OK;
- }
-
- rv = NodeHasOffsetEntry(&mOffsetTable, aRightNode,
- &rightHasEntry, &rightIndex);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (!rightHasEntry) {
- // It's okay if the node isn't in the offset table, the
- // editor could be cleaning house.
- return NS_OK;
- }
-
- NS_ASSERTION(leftIndex < rightIndex, "Indexes out of order.");
-
- if (leftIndex > rightIndex) {
- // Don't know how to handle this situation.
- return NS_ERROR_FAILURE;
- }
-
- LOCK_DOC(this);
-
- OffsetEntry *entry = mOffsetTable[rightIndex];
- NS_ASSERTION(entry->mNodeOffset == 0, "Unexpected offset value for rightIndex.");
-
- // Run through the table and change all entries referring to
- // the left node so that they now refer to the right node:
-
- nsAutoString str;
- aLeftNode->GetNodeValue(str);
- int32_t nodeLength = str.Length();
-
- for (int32_t i = leftIndex; i < rightIndex; i++) {
- entry = mOffsetTable[i];
- if (entry->mNode != aLeftNode) {
- break;
- }
- if (entry->mIsValid) {
- entry->mNode = aRightNode;
- }
- }
-
- // Run through the table and adjust the node offsets
- // for all entries referring to the right node.
-
- for (int32_t i = rightIndex;
- i < static_cast<int32_t>(mOffsetTable.Length()); i++) {
- entry = mOffsetTable[i];
- if (entry->mNode != aRightNode) {
- break;
- }
- if (entry->mIsValid) {
- entry->mNodeOffset += nodeLength;
- }
- }
-
- // Now check to see if the iterator is pointing to the
- // left node. If it is, make it point to the right node!
-
- nsCOMPtr<nsIContent> leftContent = do_QueryInterface(aLeftNode);
- nsCOMPtr<nsIContent> rightContent = do_QueryInterface(aRightNode);
-
- if (!leftContent || !rightContent) {
- UNLOCK_DOC(this);
- return NS_ERROR_FAILURE;
- }
-
- if (mIterator->GetCurrentNode() == leftContent) {
- mIterator->PositionAt(rightContent);
- }
-
- UNLOCK_DOC(this);
-
- return NS_OK;
-}
-
-nsresult
-nsTextServicesDocument::CreateContentIterator(nsRange* aRange,
- nsIContentIterator** aIterator)
-{
- NS_ENSURE_TRUE(aRange && aIterator, NS_ERROR_NULL_POINTER);
-
- *aIterator = nullptr;
-
- // Create a nsFilteredContentIterator
- // This class wraps the ContentIterator in order to give itself a chance
- // to filter out certain content nodes
- RefPtr<nsFilteredContentIterator> filter = new nsFilteredContentIterator(mTxtSvcFilter);
-
- nsresult rv = filter->Init(aRange);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- filter.forget(aIterator);
- return NS_OK;
-}
-
-nsresult
-nsTextServicesDocument::GetDocumentContentRootNode(nsIDOMNode **aNode)
-{
- NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
-
- *aNode = 0;
-
- NS_ENSURE_TRUE(mDOMDocument, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryInterface(mDOMDocument);
-
- if (htmlDoc) {
- // For HTML documents, the content root node is the body.
-
- nsCOMPtr<nsIDOMHTMLElement> bodyElement;
-
- nsresult rv = htmlDoc->GetBody(getter_AddRefs(bodyElement));
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- NS_ENSURE_TRUE(bodyElement, NS_ERROR_FAILURE);
-
- bodyElement.forget(aNode);
- } else {
- // For non-HTML documents, the content root node will be the document element.
-
- nsCOMPtr<nsIDOMElement> docElement;
-
- nsresult rv = mDOMDocument->GetDocumentElement(getter_AddRefs(docElement));
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- NS_ENSURE_TRUE(docElement, NS_ERROR_FAILURE);
-
- docElement.forget(aNode);
- }
-
- return NS_OK;
-}
-
-nsresult
-nsTextServicesDocument::CreateDocumentContentRange(nsRange** aRange)
-{
- *aRange = nullptr;
-
- nsCOMPtr<nsIDOMNode> node;
- nsresult rv = GetDocumentContentRootNode(getter_AddRefs(node));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsINode> nativeNode = do_QueryInterface(node);
- NS_ENSURE_STATE(nativeNode);
-
- RefPtr<nsRange> range = new nsRange(nativeNode);
-
- rv = range->SelectNodeContents(node);
- NS_ENSURE_SUCCESS(rv, rv);
-
- range.forget(aRange);
- return NS_OK;
-}
-
-nsresult
-nsTextServicesDocument::CreateDocumentContentRootToNodeOffsetRange(
- nsIDOMNode* aParent, int32_t aOffset, bool aToStart, nsRange** aRange)
-{
- NS_ENSURE_TRUE(aParent && aRange, NS_ERROR_NULL_POINTER);
-
- *aRange = 0;
-
- NS_ASSERTION(aOffset >= 0, "Invalid offset!");
-
- if (aOffset < 0) {
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsIDOMNode> bodyNode;
- nsresult rv = GetDocumentContentRootNode(getter_AddRefs(bodyNode));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(bodyNode, NS_ERROR_NULL_POINTER);
-
- nsCOMPtr<nsIDOMNode> startNode;
- nsCOMPtr<nsIDOMNode> endNode;
- int32_t startOffset, endOffset;
-
- if (aToStart) {
- // The range should begin at the start of the document
- // and extend up until (aParent, aOffset).
-
- startNode = bodyNode;
- startOffset = 0;
- endNode = aParent;
- endOffset = aOffset;
- } else {
- // The range should begin at (aParent, aOffset) and
- // extend to the end of the document.
-
- startNode = aParent;
- startOffset = aOffset;
- endNode = bodyNode;
-
- nsCOMPtr<nsINode> body = do_QueryInterface(bodyNode);
- endOffset = body ? int32_t(body->GetChildCount()) : 0;
- }
-
- return nsRange::CreateRange(startNode, startOffset, endNode, endOffset,
- aRange);
-}
-
-nsresult
-nsTextServicesDocument::CreateDocumentContentIterator(nsIContentIterator **aIterator)
-{
- NS_ENSURE_TRUE(aIterator, NS_ERROR_NULL_POINTER);
-
- RefPtr<nsRange> range;
-
- nsresult rv = CreateDocumentContentRange(getter_AddRefs(range));
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- return CreateContentIterator(range, aIterator);
-}
-
-nsresult
-nsTextServicesDocument::AdjustContentIterator()
-{
- NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mIterator->GetCurrentNode()));
-
- NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
-
- nsIDOMNode *nodePtr = node.get();
- int32_t tcount = mOffsetTable.Length();
-
- nsIDOMNode *prevValidNode = 0;
- nsIDOMNode *nextValidNode = 0;
- bool foundEntry = false;
- OffsetEntry *entry;
-
- for (int32_t i = 0; i < tcount && !nextValidNode; i++) {
- entry = mOffsetTable[i];
-
- NS_ENSURE_TRUE(entry, NS_ERROR_FAILURE);
-
- if (entry->mNode == nodePtr) {
- if (entry->mIsValid) {
- // The iterator is still pointing to something valid!
- // Do nothing!
- return NS_OK;
- }
- // We found an invalid entry that points to
- // the current iterator node. Stop looking for
- // a previous valid node!
- foundEntry = true;
- }
-
- if (entry->mIsValid) {
- if (!foundEntry) {
- prevValidNode = entry->mNode;
- } else {
- nextValidNode = entry->mNode;
- }
- }
- }
-
- nsCOMPtr<nsIContent> content;
-
- if (prevValidNode) {
- content = do_QueryInterface(prevValidNode);
- } else if (nextValidNode) {
- content = do_QueryInterface(nextValidNode);
- }
-
- if (content) {
- nsresult rv = mIterator->PositionAt(content);
-
- if (NS_FAILED(rv)) {
- mIteratorStatus = eIsDone;
- } else {
- mIteratorStatus = eValid;
- }
- return rv;
- }
-
- // If we get here, there aren't any valid entries
- // in the offset table! Try to position the iterator
- // on the next text block first, then previous if
- // one doesn't exist!
-
- if (mNextTextBlock) {
- nsresult rv = mIterator->PositionAt(mNextTextBlock);
-
- if (NS_FAILED(rv)) {
- mIteratorStatus = eIsDone;
- return rv;
- }
-
- mIteratorStatus = eNext;
- } else if (mPrevTextBlock) {
- nsresult rv = mIterator->PositionAt(mPrevTextBlock);
-
- if (NS_FAILED(rv)) {
- mIteratorStatus = eIsDone;
- return rv;
- }
-
- mIteratorStatus = ePrev;
- } else {
- mIteratorStatus = eIsDone;
- }
- return NS_OK;
-}
-
-bool
-nsTextServicesDocument::DidSkip(nsIContentIterator* aFilteredIter)
-{
- // We can assume here that the Iterator is a nsFilteredContentIterator because
- // all the iterator are created in CreateContentIterator which create a
- // nsFilteredContentIterator
- // So if the iterator bailed on one of the "filtered" content nodes then we
- // consider that to be a block and bail with true
- if (aFilteredIter) {
- nsFilteredContentIterator* filter = static_cast<nsFilteredContentIterator *>(aFilteredIter);
- if (filter && filter->DidSkip()) {
- return true;
- }
- }
- return false;
-}
-
-void
-nsTextServicesDocument::ClearDidSkip(nsIContentIterator* aFilteredIter)
-{
- // Clear filter's skip flag
- if (aFilteredIter) {
- nsFilteredContentIterator* filter = static_cast<nsFilteredContentIterator *>(aFilteredIter);
- filter->ClearDidSkip();
- }
-}
-
-bool
-nsTextServicesDocument::IsBlockNode(nsIContent *aContent)
-{
- if (!aContent) {
- NS_ERROR("How did a null pointer get passed to IsBlockNode?");
- return false;
- }
-
- nsIAtom *atom = aContent->NodeInfo()->NameAtom();
-
- return (sAAtom != atom &&
- sAddressAtom != atom &&
- sBigAtom != atom &&
- sBAtom != atom &&
- sCiteAtom != atom &&
- sCodeAtom != atom &&
- sDfnAtom != atom &&
- sEmAtom != atom &&
- sFontAtom != atom &&
- sIAtom != atom &&
- sKbdAtom != atom &&
- sKeygenAtom != atom &&
- sNobrAtom != atom &&
- sSAtom != atom &&
- sSampAtom != atom &&
- sSmallAtom != atom &&
- sSpacerAtom != atom &&
- sSpanAtom != atom &&
- sStrikeAtom != atom &&
- sStrongAtom != atom &&
- sSubAtom != atom &&
- sSupAtom != atom &&
- sTtAtom != atom &&
- sUAtom != atom &&
- sVarAtom != atom &&
- sWbrAtom != atom);
-}
-
-bool
-nsTextServicesDocument::HasSameBlockNodeParent(nsIContent *aContent1, nsIContent *aContent2)
-{
- nsIContent* p1 = aContent1->GetParent();
- nsIContent* p2 = aContent2->GetParent();
-
- // Quick test:
-
- if (p1 == p2) {
- return true;
- }
-
- // Walk up the parent hierarchy looking for closest block boundary node:
-
- while (p1 && !IsBlockNode(p1)) {
- p1 = p1->GetParent();
- }
-
- while (p2 && !IsBlockNode(p2)) {
- p2 = p2->GetParent();
- }
-
- return p1 == p2;
-}
-
-bool
-nsTextServicesDocument::IsTextNode(nsIContent *aContent)
-{
- NS_ENSURE_TRUE(aContent, false);
- return nsIDOMNode::TEXT_NODE == aContent->NodeType();
-}
-
-bool
-nsTextServicesDocument::IsTextNode(nsIDOMNode *aNode)
-{
- NS_ENSURE_TRUE(aNode, false);
-
- nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
- return IsTextNode(content);
-}
-
-nsresult
-nsTextServicesDocument::SetSelectionInternal(int32_t aOffset, int32_t aLength, bool aDoUpdate)
-{
- NS_ENSURE_TRUE(mSelCon && aOffset >= 0 && aLength >= 0, NS_ERROR_FAILURE);
-
- nsIDOMNode *sNode = 0, *eNode = 0;
- int32_t sOffset = 0, eOffset = 0;
- OffsetEntry *entry;
-
- // Find start of selection in node offset terms:
-
- for (size_t i = 0; !sNode && i < mOffsetTable.Length(); i++) {
- entry = mOffsetTable[i];
- if (entry->mIsValid) {
- if (entry->mIsInsertedText) {
- // Caret can only be placed at the end of an
- // inserted text offset entry, if the offsets
- // match exactly!
-
- if (entry->mStrOffset == aOffset) {
- sNode = entry->mNode;
- sOffset = entry->mNodeOffset + entry->mLength;
- }
- } else if (aOffset >= entry->mStrOffset) {
- bool foundEntry = false;
- int32_t strEndOffset = entry->mStrOffset + entry->mLength;
-
- if (aOffset < strEndOffset) {
- foundEntry = true;
- } else if (aOffset == strEndOffset) {
- // Peek after this entry to see if we have any
- // inserted text entries belonging to the same
- // entry->mNode. If so, we have to place the selection
- // after it!
-
- if (i + 1 < mOffsetTable.Length()) {
- OffsetEntry *nextEntry = mOffsetTable[i+1];
-
- if (!nextEntry->mIsValid || nextEntry->mStrOffset != aOffset) {
- // Next offset entry isn't an exact match, so we'll
- // just use the current entry.
- foundEntry = true;
- }
- }
- }
-
- if (foundEntry) {
- sNode = entry->mNode;
- sOffset = entry->mNodeOffset + aOffset - entry->mStrOffset;
- }
- }
-
- if (sNode) {
- mSelStartIndex = static_cast<int32_t>(i);
- mSelStartOffset = aOffset;
- }
- }
- }
-
- NS_ENSURE_TRUE(sNode, NS_ERROR_FAILURE);
-
- // XXX: If we ever get a SetSelection() method in nsIEditor, we should
- // use it.
-
- nsCOMPtr<nsISelection> selection;
-
- if (aDoUpdate) {
- nsresult rv =
- mSelCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
- getter_AddRefs(selection));
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = selection->Collapse(sNode, sOffset);
-
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- if (aLength <= 0) {
- // We have a collapsed selection. (Caret)
-
- mSelEndIndex = mSelStartIndex;
- mSelEndOffset = mSelStartOffset;
-
- //**** KDEBUG ****
- // printf("\n* Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset);
- //**** KDEBUG ****
-
- return NS_OK;
- }
-
- // Find the end of the selection in node offset terms:
- int32_t endOffset = aOffset + aLength;
- for (int32_t i = mOffsetTable.Length() - 1; !eNode && i >= 0; i--) {
- entry = mOffsetTable[i];
-
- if (entry->mIsValid) {
- if (entry->mIsInsertedText) {
- if (entry->mStrOffset == eOffset) {
- // If the selection ends on an inserted text offset entry,
- // the selection includes the entire entry!
-
- eNode = entry->mNode;
- eOffset = entry->mNodeOffset + entry->mLength;
- }
- } else if (endOffset >= entry->mStrOffset &&
- endOffset <= entry->mStrOffset + entry->mLength) {
- eNode = entry->mNode;
- eOffset = entry->mNodeOffset + endOffset - entry->mStrOffset;
- }
-
- if (eNode) {
- mSelEndIndex = i;
- mSelEndOffset = endOffset;
- }
- }
- }
-
- if (aDoUpdate && eNode) {
- nsresult rv = selection->Extend(eNode, eOffset);
-
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- //**** KDEBUG ****
- // printf("\n * Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset);
- //**** KDEBUG ****
-
- return NS_OK;
-}
-
-nsresult
-nsTextServicesDocument::GetSelection(nsITextServicesDocument::TSDBlockSelectionStatus *aSelStatus, int32_t *aSelOffset, int32_t *aSelLength)
-{
- NS_ENSURE_TRUE(aSelStatus && aSelOffset && aSelLength, NS_ERROR_NULL_POINTER);
-
- *aSelStatus = nsITextServicesDocument::eBlockNotFound;
- *aSelOffset = -1;
- *aSelLength = -1;
-
- NS_ENSURE_TRUE(mDOMDocument && mSelCon, NS_ERROR_FAILURE);
-
- if (mIteratorStatus == nsTextServicesDocument::eIsDone) {
- return NS_OK;
- }
-
- nsCOMPtr<nsISelection> selection;
- bool isCollapsed;
-
- nsresult rv = mSelCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
- getter_AddRefs(selection));
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
-
- rv = selection->GetIsCollapsed(&isCollapsed);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- // XXX: If we expose this method publicly, we need to
- // add LOCK_DOC/UNLOCK_DOC calls!
-
- // LOCK_DOC(this);
-
- if (isCollapsed) {
- rv = GetCollapsedSelection(aSelStatus, aSelOffset, aSelLength);
- } else {
- rv = GetUncollapsedSelection(aSelStatus, aSelOffset, aSelLength);
- }
-
- // UNLOCK_DOC(this);
-
- // XXX The result of GetCollapsedSelection() or GetUncollapsedSelection().
- return rv;
-}
-
-nsresult
-nsTextServicesDocument::GetCollapsedSelection(nsITextServicesDocument::TSDBlockSelectionStatus *aSelStatus, int32_t *aSelOffset, int32_t *aSelLength)
-{
- nsCOMPtr<nsISelection> domSelection;
- nsresult rv =
- mSelCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
- getter_AddRefs(domSelection));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(domSelection, NS_ERROR_FAILURE);
-
- RefPtr<Selection> selection = domSelection->AsSelection();
-
- // The calling function should have done the GetIsCollapsed()
- // check already. Just assume it's collapsed!
- *aSelStatus = nsITextServicesDocument::eBlockOutside;
- *aSelOffset = *aSelLength = -1;
-
- int32_t tableCount = mOffsetTable.Length();
-
- if (!tableCount) {
- return NS_OK;
- }
-
- // Get pointers to the first and last offset entries
- // in the table.
-
- OffsetEntry* eStart = mOffsetTable[0];
- OffsetEntry* eEnd;
- if (tableCount > 1) {
- eEnd = mOffsetTable[tableCount - 1];
- } else {
- eEnd = eStart;
- }
-
- int32_t eStartOffset = eStart->mNodeOffset;
- int32_t eEndOffset = eEnd->mNodeOffset + eEnd->mLength;
-
- RefPtr<nsRange> range = selection->GetRangeAt(0);
- NS_ENSURE_STATE(range);
-
- nsCOMPtr<nsIDOMNode> domParent;
- rv = range->GetStartContainer(getter_AddRefs(domParent));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsINode> parent = do_QueryInterface(domParent);
- MOZ_ASSERT(parent);
-
- uint32_t offset;
- rv = range->GetStartOffset(&offset);
- NS_ENSURE_SUCCESS(rv, rv);
-
- int32_t e1s1 = nsContentUtils::ComparePoints(eStart->mNode, eStartOffset,
- domParent,
- static_cast<int32_t>(offset));
- int32_t e2s1 = nsContentUtils::ComparePoints(eEnd->mNode, eEndOffset,
- domParent,
- static_cast<int32_t>(offset));
-
- if (e1s1 > 0 || e2s1 < 0) {
- // We're done if the caret is outside the current text block.
- return NS_OK;
- }
-
- if (parent->NodeType() == nsIDOMNode::TEXT_NODE) {
- // Good news, the caret is in a text node. Look
- // through the offset table for the entry that
- // matches its parent and offset.
-
- for (int32_t i = 0; i < tableCount; i++) {
- OffsetEntry* entry = mOffsetTable[i];
- NS_ENSURE_TRUE(entry, NS_ERROR_FAILURE);
-
- if (entry->mNode == domParent.get() &&
- entry->mNodeOffset <= static_cast<int32_t>(offset) &&
- static_cast<int32_t>(offset) <= entry->mNodeOffset + entry->mLength) {
- *aSelStatus = nsITextServicesDocument::eBlockContains;
- *aSelOffset = entry->mStrOffset + (offset - entry->mNodeOffset);
- *aSelLength = 0;
-
- return NS_OK;
- }
- }
-
- // If we get here, we didn't find a text node entry
- // in our offset table that matched.
-
- return NS_ERROR_FAILURE;
- }
-
- // The caret is in our text block, but it's positioned in some
- // non-text node (ex. <b>). Create a range based on the start
- // and end of the text block, then create an iterator based on
- // this range, with its initial position set to the closest
- // child of this non-text node. Then look for the closest text
- // node.
-
- rv = CreateRange(eStart->mNode, eStartOffset, eEnd->mNode, eEndOffset,
- getter_AddRefs(range));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIContentIterator> iter;
- rv = CreateContentIterator(range, getter_AddRefs(iter));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsIContent* saveNode;
- if (parent->HasChildren()) {
- // XXX: We need to make sure that all of parent's
- // children are in the text block.
-
- // If the parent has children, position the iterator
- // on the child that is to the left of the offset.
-
- uint32_t childIndex = offset;
-
- if (childIndex > 0) {
- uint32_t numChildren = parent->GetChildCount();
- NS_ASSERTION(childIndex <= numChildren, "Invalid selection offset!");
-
- if (childIndex > numChildren) {
- childIndex = numChildren;
- }
-
- childIndex -= 1;
- }
-
- nsIContent* content = parent->GetChildAt(childIndex);
- NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
-
- rv = iter->PositionAt(content);
- NS_ENSURE_SUCCESS(rv, rv);
-
- saveNode = content;
- } else {
- // The parent has no children, so position the iterator
- // on the parent.
- NS_ENSURE_TRUE(parent->IsContent(), NS_ERROR_FAILURE);
- nsCOMPtr<nsIContent> content = parent->AsContent();
-
- rv = iter->PositionAt(content);
- NS_ENSURE_SUCCESS(rv, rv);
-
- saveNode = content;
- }
-
- // Now iterate to the left, towards the beginning of
- // the text block, to find the first text node you
- // come across.
-
- nsIContent* node = nullptr;
- while (!iter->IsDone()) {
- nsINode* current = iter->GetCurrentNode();
- if (current->NodeType() == nsIDOMNode::TEXT_NODE) {
- node = static_cast<nsIContent*>(current);
- break;
- }
-
- iter->Prev();
- }
-
- if (node) {
- // We found a node, now set the offset to the end
- // of the text node.
- offset = node->TextLength();
- } else {
- // We should never really get here, but I'm paranoid.
-
- // We didn't find a text node above, so iterate to
- // the right, towards the end of the text block, looking
- // for a text node.
-
- rv = iter->PositionAt(saveNode);
- NS_ENSURE_SUCCESS(rv, rv);
-
- node = nullptr;
- while (!iter->IsDone()) {
- nsINode* current = iter->GetCurrentNode();
-
- if (current->NodeType() == nsIDOMNode::TEXT_NODE) {
- node = static_cast<nsIContent*>(current);
- break;
- }
-
- iter->Next();
- }
-
- NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
-
- // We found a text node, so set the offset to
- // the beginning of the node.
-
- offset = 0;
- }
-
- for (int32_t i = 0; i < tableCount; i++) {
- OffsetEntry* entry = mOffsetTable[i];
- NS_ENSURE_TRUE(entry, NS_ERROR_FAILURE);
-
- if (entry->mNode == node->AsDOMNode() &&
- entry->mNodeOffset <= static_cast<int32_t>(offset) &&
- static_cast<int32_t>(offset) <= entry->mNodeOffset + entry->mLength) {
- *aSelStatus = nsITextServicesDocument::eBlockContains;
- *aSelOffset = entry->mStrOffset + (offset - entry->mNodeOffset);
- *aSelLength = 0;
-
- // Now move the caret so that it is actually in the text node.
- // We do this to keep things in sync.
- //
- // In most cases, the user shouldn't see any movement in the caret
- // on screen.
-
- return SetSelectionInternal(*aSelOffset, *aSelLength, true);
- }
- }
-
- return NS_ERROR_FAILURE;
-}
-
-nsresult
-nsTextServicesDocument::GetUncollapsedSelection(nsITextServicesDocument::TSDBlockSelectionStatus *aSelStatus, int32_t *aSelOffset, int32_t *aSelLength)
-{
- RefPtr<nsRange> range;
- OffsetEntry *entry;
-
- nsCOMPtr<nsISelection> domSelection;
- nsresult rv = mSelCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
- getter_AddRefs(domSelection));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(domSelection, NS_ERROR_FAILURE);
-
- RefPtr<Selection> selection = domSelection->AsSelection();
-
- // It is assumed that the calling function has made sure that the
- // selection is not collapsed, and that the input params to this
- // method are initialized to some defaults.
-
- nsCOMPtr<nsIDOMNode> startParent, endParent;
- int32_t startOffset, endOffset;
- int32_t rangeCount, tableCount;
- int32_t e1s1 = 0, e1s2 = 0, e2s1 = 0, e2s2 = 0;
-
- OffsetEntry *eStart, *eEnd;
- int32_t eStartOffset, eEndOffset;
-
- tableCount = mOffsetTable.Length();
-
- // Get pointers to the first and last offset entries
- // in the table.
-
- eStart = mOffsetTable[0];
-
- if (tableCount > 1) {
- eEnd = mOffsetTable[tableCount - 1];
- } else {
- eEnd = eStart;
- }
-
- eStartOffset = eStart->mNodeOffset;
- eEndOffset = eEnd->mNodeOffset + eEnd->mLength;
-
- rv = selection->GetRangeCount(&rangeCount);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Find the first range in the selection that intersects
- // the current text block.
-
- for (int32_t i = 0; i < rangeCount; i++) {
- range = selection->GetRangeAt(i);
- NS_ENSURE_STATE(range);
-
- rv = GetRangeEndPoints(range,
- getter_AddRefs(startParent), &startOffset,
- getter_AddRefs(endParent), &endOffset);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- e1s2 = nsContentUtils::ComparePoints(eStart->mNode, eStartOffset,
- endParent, endOffset);
- e2s1 = nsContentUtils::ComparePoints(eEnd->mNode, eEndOffset,
- startParent, startOffset);
-
- // Break out of the loop if the text block intersects the current range.
-
- if (e1s2 <= 0 && e2s1 >= 0) {
- break;
- }
- }
-
- // We're done if we didn't find an intersecting range.
-
- if (rangeCount < 1 || e1s2 > 0 || e2s1 < 0) {
- *aSelStatus = nsITextServicesDocument::eBlockOutside;
- *aSelOffset = *aSelLength = -1;
- return NS_OK;
- }
-
- // Now that we have an intersecting range, find out more info:
-
- e1s1 = nsContentUtils::ComparePoints(eStart->mNode, eStartOffset,
- startParent, startOffset);
- e2s2 = nsContentUtils::ComparePoints(eEnd->mNode, eEndOffset,
- endParent, endOffset);
-
- if (rangeCount > 1) {
- // There are multiple selection ranges, we only deal
- // with the first one that intersects the current,
- // text block, so mark this a as a partial.
- *aSelStatus = nsITextServicesDocument::eBlockPartial;
- } else if (e1s1 > 0 && e2s2 < 0) {
- // The range extends beyond the start and
- // end of the current text block.
- *aSelStatus = nsITextServicesDocument::eBlockInside;
- } else if (e1s1 <= 0 && e2s2 >= 0) {
- // The current text block contains the entire
- // range.
- *aSelStatus = nsITextServicesDocument::eBlockContains;
- } else {
- // The range partially intersects the block.
- *aSelStatus = nsITextServicesDocument::eBlockPartial;
- }
-
- // Now create a range based on the intersection of the
- // text block and range:
-
- nsCOMPtr<nsIDOMNode> p1, p2;
- int32_t o1, o2;
-
- // The start of the range will be the rightmost
- // start node.
-
- if (e1s1 >= 0) {
- p1 = do_QueryInterface(eStart->mNode);
- o1 = eStartOffset;
- } else {
- p1 = startParent;
- o1 = startOffset;
- }
-
- // The end of the range will be the leftmost
- // end node.
-
- if (e2s2 <= 0) {
- p2 = do_QueryInterface(eEnd->mNode);
- o2 = eEndOffset;
- } else {
- p2 = endParent;
- o2 = endOffset;
- }
-
- rv = CreateRange(p1, o1, p2, o2, getter_AddRefs(range));
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Now iterate over this range to figure out the selection's
- // block offset and length.
-
- nsCOMPtr<nsIContentIterator> iter;
-
- rv = CreateContentIterator(range, getter_AddRefs(iter));
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Find the first text node in the range.
-
- bool found;
- nsCOMPtr<nsIContent> content;
-
- iter->First();
-
- if (!IsTextNode(p1)) {
- found = false;
-
- while (!iter->IsDone()) {
- content = do_QueryInterface(iter->GetCurrentNode());
-
- if (IsTextNode(content)) {
- p1 = do_QueryInterface(content);
-
- NS_ENSURE_TRUE(p1, NS_ERROR_FAILURE);
-
- o1 = 0;
- found = true;
-
- break;
- }
-
- iter->Next();
- }
-
- NS_ENSURE_TRUE(found, NS_ERROR_FAILURE);
- }
-
- // Find the last text node in the range.
-
- iter->Last();
-
- if (!IsTextNode(p2)) {
- found = false;
- while (!iter->IsDone()) {
- content = do_QueryInterface(iter->GetCurrentNode());
- if (IsTextNode(content)) {
- p2 = do_QueryInterface(content);
-
- NS_ENSURE_TRUE(p2, NS_ERROR_FAILURE);
-
- nsString str;
-
- rv = p2->GetNodeValue(str);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- o2 = str.Length();
- found = true;
-
- break;
- }
-
- iter->Prev();
- }
-
- NS_ENSURE_TRUE(found, NS_ERROR_FAILURE);
- }
-
- found = false;
- *aSelLength = 0;
-
- for (int32_t i = 0; i < tableCount; i++) {
- entry = mOffsetTable[i];
- NS_ENSURE_TRUE(entry, NS_ERROR_FAILURE);
- if (!found) {
- if (entry->mNode == p1.get() &&
- entry->mNodeOffset <= o1 &&
- o1 <= entry->mNodeOffset + entry->mLength) {
- *aSelOffset = entry->mStrOffset + (o1 - entry->mNodeOffset);
- if (p1 == p2 &&
- entry->mNodeOffset <= o2 &&
- o2 <= entry->mNodeOffset + entry->mLength) {
- // The start and end of the range are in the same offset
- // entry. Calculate the length of the range then we're done.
- *aSelLength = o2 - o1;
- break;
- }
- // Add the length of the sub string in this offset entry
- // that follows the start of the range.
- *aSelLength = entry->mLength - (o1 - entry->mNodeOffset);
- found = true;
- }
- } else { // Found.
- if (entry->mNode == p2.get() &&
- entry->mNodeOffset <= o2 &&
- o2 <= entry->mNodeOffset + entry->mLength) {
- // We found the end of the range. Calculate the length of the
- // sub string that is before the end of the range, then we're done.
- *aSelLength += o2 - entry->mNodeOffset;
- break;
- }
- // The entire entry must be in the range.
- *aSelLength += entry->mLength;
- }
- }
-
- return NS_OK;
-}
-
-bool
-nsTextServicesDocument::SelectionIsCollapsed()
-{
- return(mSelStartIndex == mSelEndIndex && mSelStartOffset == mSelEndOffset);
-}
-
-bool
-nsTextServicesDocument::SelectionIsValid()
-{
- return(mSelStartIndex >= 0);
-}
-
-nsresult
-nsTextServicesDocument::GetRangeEndPoints(nsRange* aRange,
- nsIDOMNode **aStartParent, int32_t *aStartOffset,
- nsIDOMNode **aEndParent, int32_t *aEndOffset)
-{
- NS_ENSURE_TRUE(aRange && aStartParent && aStartOffset && aEndParent && aEndOffset, NS_ERROR_NULL_POINTER);
-
- nsresult rv = aRange->GetStartContainer(aStartParent);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- NS_ENSURE_TRUE(aStartParent, NS_ERROR_FAILURE);
-
- uint32_t offset;
- rv = aRange->GetStartOffset(&offset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- *aStartOffset = static_cast<int32_t>(offset);
-
- rv = aRange->GetEndContainer(aEndParent);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- NS_ENSURE_TRUE(aEndParent, NS_ERROR_FAILURE);
-
- rv = aRange->GetEndOffset(&offset);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- *aEndOffset = static_cast<int32_t>(offset);
- return NS_OK;
-}
-
-nsresult
-nsTextServicesDocument::CreateRange(nsIDOMNode *aStartParent, int32_t aStartOffset,
- nsIDOMNode *aEndParent, int32_t aEndOffset,
- nsRange** aRange)
-{
- return nsRange::CreateRange(aStartParent, aStartOffset, aEndParent,
- aEndOffset, aRange);
-}
-
-nsresult
-nsTextServicesDocument::FirstTextNode(nsIContentIterator *aIterator,
- TSDIteratorStatus *aIteratorStatus)
-{
- if (aIteratorStatus) {
- *aIteratorStatus = nsTextServicesDocument::eIsDone;
- }
-
- aIterator->First();
-
- while (!aIterator->IsDone()) {
- if (aIterator->GetCurrentNode()->NodeType() == nsIDOMNode::TEXT_NODE) {
- if (aIteratorStatus) {
- *aIteratorStatus = nsTextServicesDocument::eValid;
- }
- break;
- }
- aIterator->Next();
- }
-
- return NS_OK;
-}
-
-nsresult
-nsTextServicesDocument::LastTextNode(nsIContentIterator *aIterator,
- TSDIteratorStatus *aIteratorStatus)
-{
- if (aIteratorStatus) {
- *aIteratorStatus = nsTextServicesDocument::eIsDone;
- }
-
- aIterator->Last();
-
- while (!aIterator->IsDone()) {
- if (aIterator->GetCurrentNode()->NodeType() == nsIDOMNode::TEXT_NODE) {
- if (aIteratorStatus) {
- *aIteratorStatus = nsTextServicesDocument::eValid;
- }
- break;
- }
- aIterator->Prev();
- }
-
- return NS_OK;
-}
-
-nsresult
-nsTextServicesDocument::FirstTextNodeInCurrentBlock(nsIContentIterator *iter)
-{
- NS_ENSURE_TRUE(iter, NS_ERROR_NULL_POINTER);
-
- ClearDidSkip(iter);
-
- nsCOMPtr<nsIContent> last;
-
- // Walk backwards over adjacent text nodes until
- // we hit a block boundary:
-
- while (!iter->IsDone()) {
- nsCOMPtr<nsIContent> content = iter->GetCurrentNode()->IsContent()
- ? iter->GetCurrentNode()->AsContent()
- : nullptr;
- if (last && IsBlockNode(content)) {
- break;
- }
- if (IsTextNode(content)) {
- if (last && !HasSameBlockNodeParent(content, last)) {
- // We're done, the current text node is in a
- // different block.
- break;
- }
- last = content;
- }
-
- iter->Prev();
-
- if (DidSkip(iter)) {
- break;
- }
- }
-
- if (last) {
- iter->PositionAt(last);
- }
-
- // XXX: What should we return if last is null?
-
- return NS_OK;
-}
-
-nsresult
-nsTextServicesDocument::FirstTextNodeInPrevBlock(nsIContentIterator *aIterator)
-{
- NS_ENSURE_TRUE(aIterator, NS_ERROR_NULL_POINTER);
-
- // XXX: What if mIterator is not currently on a text node?
-
- // Make sure mIterator is pointing to the first text node in the
- // current block:
-
- nsresult rv = FirstTextNodeInCurrentBlock(aIterator);
-
- NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
-
- // Point mIterator to the first node before the first text node:
-
- aIterator->Prev();
-
- if (aIterator->IsDone()) {
- return NS_ERROR_FAILURE;
- }
-
- // Now find the first text node of the next block:
-
- return FirstTextNodeInCurrentBlock(aIterator);
-}
-
-nsresult
-nsTextServicesDocument::FirstTextNodeInNextBlock(nsIContentIterator *aIterator)
-{
- nsCOMPtr<nsIContent> prev;
- bool crossedBlockBoundary = false;
-
- NS_ENSURE_TRUE(aIterator, NS_ERROR_NULL_POINTER);
-
- ClearDidSkip(aIterator);
-
- while (!aIterator->IsDone()) {
- nsCOMPtr<nsIContent> content = aIterator->GetCurrentNode()->IsContent()
- ? aIterator->GetCurrentNode()->AsContent()
- : nullptr;
-
- if (IsTextNode(content)) {
- if (crossedBlockBoundary ||
- (prev && !HasSameBlockNodeParent(prev, content))) {
- break;
- }
- prev = content;
- } else if (!crossedBlockBoundary && IsBlockNode(content)) {
- crossedBlockBoundary = true;
- }
-
- aIterator->Next();
-
- if (!crossedBlockBoundary && DidSkip(aIterator)) {
- crossedBlockBoundary = true;
- }
- }
-
- return NS_OK;
-}
-
-nsresult
-nsTextServicesDocument::GetFirstTextNodeInPrevBlock(nsIContent **aContent)
-{
- NS_ENSURE_TRUE(aContent, NS_ERROR_NULL_POINTER);
-
- *aContent = 0;
-
- // Save the iterator's current content node so we can restore
- // it when we are done:
-
- nsINode* node = mIterator->GetCurrentNode();
-
- nsresult rv = FirstTextNodeInPrevBlock(mIterator);
-
- if (NS_FAILED(rv)) {
- // Try to restore the iterator before returning.
- mIterator->PositionAt(node);
- return rv;
- }
-
- if (!mIterator->IsDone()) {
- nsCOMPtr<nsIContent> current = mIterator->GetCurrentNode()->IsContent()
- ? mIterator->GetCurrentNode()->AsContent()
- : nullptr;
- current.forget(aContent);
- }
-
- // Restore the iterator:
-
- return mIterator->PositionAt(node);
-}
-
-nsresult
-nsTextServicesDocument::GetFirstTextNodeInNextBlock(nsIContent **aContent)
-{
- NS_ENSURE_TRUE(aContent, NS_ERROR_NULL_POINTER);
-
- *aContent = 0;
-
- // Save the iterator's current content node so we can restore
- // it when we are done:
-
- nsINode* node = mIterator->GetCurrentNode();
-
- nsresult rv = FirstTextNodeInNextBlock(mIterator);
-
- if (NS_FAILED(rv)) {
- // Try to restore the iterator before returning.
- mIterator->PositionAt(node);
- return rv;
- }
-
- if (!mIterator->IsDone()) {
- nsCOMPtr<nsIContent> current = mIterator->GetCurrentNode()->IsContent()
- ? mIterator->GetCurrentNode()->AsContent()
- : nullptr;
- current.forget(aContent);
- }
-
- // Restore the iterator:
- return mIterator->PositionAt(node);
-}
-
-nsresult
-nsTextServicesDocument::CreateOffsetTable(nsTArray<OffsetEntry*> *aOffsetTable,
- nsIContentIterator *aIterator,
- TSDIteratorStatus *aIteratorStatus,
- nsRange* aIterRange, nsString* aStr)
-{
- nsCOMPtr<nsIContent> first;
- nsCOMPtr<nsIContent> prev;
-
- NS_ENSURE_TRUE(aIterator, NS_ERROR_NULL_POINTER);
-
- ClearOffsetTable(aOffsetTable);
-
- if (aStr) {
- aStr->Truncate();
- }
-
- if (*aIteratorStatus == nsTextServicesDocument::eIsDone) {
- return NS_OK;
- }
-
- // If we have an aIterRange, retrieve the endpoints so
- // they can be used in the while loop below to trim entries
- // for text nodes that are partially selected by aIterRange.
-
- nsCOMPtr<nsIDOMNode> rngStartNode, rngEndNode;
- int32_t rngStartOffset = 0, rngEndOffset = 0;
-
- if (aIterRange) {
- nsresult rv =
- GetRangeEndPoints(aIterRange,
- getter_AddRefs(rngStartNode), &rngStartOffset,
- getter_AddRefs(rngEndNode), &rngEndOffset);
-
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // The text service could have added text nodes to the beginning
- // of the current block and called this method again. Make sure
- // we really are at the beginning of the current block:
-
- nsresult rv = FirstTextNodeInCurrentBlock(aIterator);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- int32_t offset = 0;
-
- ClearDidSkip(aIterator);
-
- while (!aIterator->IsDone()) {
- nsCOMPtr<nsIContent> content = aIterator->GetCurrentNode()->IsContent()
- ? aIterator->GetCurrentNode()->AsContent()
- : nullptr;
- if (IsTextNode(content)) {
- if (prev && !HasSameBlockNodeParent(prev, content)) {
- break;
- }
-
- nsCOMPtr<nsIDOMNode> node = do_QueryInterface(content);
- if (node) {
- nsString str;
-
- rv = node->GetNodeValue(str);
-
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Add an entry for this text node into the offset table:
-
- OffsetEntry *entry = new OffsetEntry(node, offset, str.Length());
- aOffsetTable->AppendElement(entry);
-
- // If one or both of the endpoints of the iteration range
- // are in the text node for this entry, make sure the entry
- // only accounts for the portion of the text node that is
- // in the range.
-
- int32_t startOffset = 0;
- int32_t endOffset = str.Length();
- bool adjustStr = false;
-
- if (entry->mNode == rngStartNode) {
- entry->mNodeOffset = startOffset = rngStartOffset;
- adjustStr = true;
- }
-
- if (entry->mNode == rngEndNode) {
- endOffset = rngEndOffset;
- adjustStr = true;
- }
-
- if (adjustStr) {
- entry->mLength = endOffset - startOffset;
- str = Substring(str, startOffset, entry->mLength);
- }
-
- offset += str.Length();
-
- if (aStr) {
- // Append the text node's string to the output string:
- if (!first) {
- *aStr = str;
- } else {
- *aStr += str;
- }
- }
- }
-
- prev = content;
-
- if (!first) {
- first = content;
- }
- }
- // XXX This should be checked before IsTextNode(), but IsBlockNode() returns
- // true even if content is a text node. See bug 1311934.
- else if (IsBlockNode(content)) {
- break;
- }
-
- aIterator->Next();
-
- if (DidSkip(aIterator)) {
- break;
- }
- }
-
- if (first) {
- // Always leave the iterator pointing at the first
- // text node of the current block!
- aIterator->PositionAt(first);
- } else {
- // If we never ran across a text node, the iterator
- // might have been pointing to something invalid to
- // begin with.
- *aIteratorStatus = nsTextServicesDocument::eIsDone;
- }
-
- return NS_OK;
-}
-
-nsresult
-nsTextServicesDocument::RemoveInvalidOffsetEntries()
-{
- for (size_t i = 0; i < mOffsetTable.Length(); ) {
- OffsetEntry* entry = mOffsetTable[i];
- if (!entry->mIsValid) {
- mOffsetTable.RemoveElementAt(i);
- if (mSelStartIndex >= 0 && static_cast<size_t>(mSelStartIndex) >= i) {
- // We are deleting an entry that comes before
- // mSelStartIndex, decrement mSelStartIndex so
- // that it points to the correct entry!
-
- NS_ASSERTION(i != static_cast<size_t>(mSelStartIndex),
- "Invalid selection index.");
-
- --mSelStartIndex;
- --mSelEndIndex;
- }
- } else {
- i++;
- }
- }
-
- return NS_OK;
-}
-
-nsresult
-nsTextServicesDocument::ClearOffsetTable(nsTArray<OffsetEntry*> *aOffsetTable)
-{
- for (size_t i = 0; i < aOffsetTable->Length(); i++) {
- delete aOffsetTable->ElementAt(i);
- }
-
- aOffsetTable->Clear();
-
- return NS_OK;
-}
-
-nsresult
-nsTextServicesDocument::SplitOffsetEntry(int32_t aTableIndex, int32_t aNewEntryLength)
-{
- OffsetEntry *entry = mOffsetTable[aTableIndex];
-
- NS_ASSERTION((aNewEntryLength > 0), "aNewEntryLength <= 0");
- NS_ASSERTION((aNewEntryLength < entry->mLength), "aNewEntryLength >= mLength");
-
- if (aNewEntryLength < 1 || aNewEntryLength >= entry->mLength) {
- return NS_ERROR_FAILURE;
- }
-
- int32_t oldLength = entry->mLength - aNewEntryLength;
-
- OffsetEntry *newEntry = new OffsetEntry(entry->mNode,
- entry->mStrOffset + oldLength,
- aNewEntryLength);
-
- if (!mOffsetTable.InsertElementAt(aTableIndex + 1, newEntry)) {
- delete newEntry;
- return NS_ERROR_FAILURE;
- }
-
- // Adjust entry fields:
-
- entry->mLength = oldLength;
- newEntry->mNodeOffset = entry->mNodeOffset + oldLength;
-
- return NS_OK;
-}
-
-nsresult
-nsTextServicesDocument::NodeHasOffsetEntry(nsTArray<OffsetEntry*> *aOffsetTable, nsIDOMNode *aNode, bool *aHasEntry, int32_t *aEntryIndex)
-{
- NS_ENSURE_TRUE(aNode && aHasEntry && aEntryIndex, NS_ERROR_NULL_POINTER);
-
- for (size_t i = 0; i < aOffsetTable->Length(); i++) {
- OffsetEntry* entry = (*aOffsetTable)[i];
-
- NS_ENSURE_TRUE(entry, NS_ERROR_FAILURE);
-
- if (entry->mNode == aNode) {
- *aHasEntry = true;
- *aEntryIndex = i;
- return NS_OK;
- }
- }
-
- *aHasEntry = false;
- *aEntryIndex = -1;
- return NS_OK;
-}
-
-// Spellchecker code has this. See bug 211343
-#define IS_NBSP_CHAR(c) (((unsigned char)0xa0)==(c))
-
-nsresult
-nsTextServicesDocument::FindWordBounds(nsTArray<OffsetEntry*> *aOffsetTable,
- nsString *aBlockStr,
- nsIDOMNode *aNode,
- int32_t aNodeOffset,
- nsIDOMNode **aWordStartNode,
- int32_t *aWordStartOffset,
- nsIDOMNode **aWordEndNode,
- int32_t *aWordEndOffset)
-{
- // Initialize return values.
-
- if (aWordStartNode) {
- *aWordStartNode = nullptr;
- }
- if (aWordStartOffset) {
- *aWordStartOffset = 0;
- }
- if (aWordEndNode) {
- *aWordEndNode = nullptr;
- }
- if (aWordEndOffset) {
- *aWordEndOffset = 0;
- }
-
- int32_t entryIndex = 0;
- bool hasEntry = false;
-
- // It's assumed that aNode is a text node. The first thing
- // we do is get its index in the offset table so we can
- // calculate the dom point's string offset.
-
- nsresult rv = NodeHasOffsetEntry(aOffsetTable, aNode, &hasEntry, &entryIndex);
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(hasEntry, NS_ERROR_FAILURE);
-
- // Next we map aNodeOffset into a string offset.
-
- OffsetEntry *entry = (*aOffsetTable)[entryIndex];
- uint32_t strOffset = entry->mStrOffset + aNodeOffset - entry->mNodeOffset;
-
- // Now we use the word breaker to find the beginning and end
- // of the word from our calculated string offset.
-
- const char16_t *str = aBlockStr->get();
- uint32_t strLen = aBlockStr->Length();
-
- nsIWordBreaker* wordBreaker = nsContentUtils::WordBreaker();
- nsWordRange res = wordBreaker->FindWord(str, strLen, strOffset);
- if (res.mBegin > strLen) {
- return str ? NS_ERROR_ILLEGAL_VALUE : NS_ERROR_NULL_POINTER;
- }
-
- // Strip out the NBSPs at the ends
- while (res.mBegin <= res.mEnd && IS_NBSP_CHAR(str[res.mBegin])) {
- res.mBegin++;
- }
- if (str[res.mEnd] == (unsigned char)0x20) {
- uint32_t realEndWord = res.mEnd - 1;
- while (realEndWord > res.mBegin && IS_NBSP_CHAR(str[realEndWord])) {
- realEndWord--;
- }
- if (realEndWord < res.mEnd - 1) {
- res.mEnd = realEndWord + 1;
- }
- }
-
- // Now that we have the string offsets for the beginning
- // and end of the word, run through the offset table and
- // convert them back into dom points.
-
- size_t lastIndex = aOffsetTable->Length() - 1;
- for (size_t i = 0; i <= lastIndex; i++) {
- entry = (*aOffsetTable)[i];
-
- int32_t strEndOffset = entry->mStrOffset + entry->mLength;
-
- // Check to see if res.mBegin is within the range covered
- // by this entry. Note that if res.mBegin is after the last
- // character covered by this entry, we will use the next
- // entry if there is one.
-
- if (uint32_t(entry->mStrOffset) <= res.mBegin &&
- (res.mBegin < static_cast<uint32_t>(strEndOffset) ||
- (res.mBegin == static_cast<uint32_t>(strEndOffset) &&
- i == lastIndex))) {
- if (aWordStartNode) {
- *aWordStartNode = entry->mNode;
- NS_IF_ADDREF(*aWordStartNode);
- }
-
- if (aWordStartOffset) {
- *aWordStartOffset = entry->mNodeOffset + res.mBegin - entry->mStrOffset;
- }
-
- if (!aWordEndNode && !aWordEndOffset) {
- // We've found our start entry, but if we're not looking
- // for end entries, we're done.
- break;
- }
- }
-
- // Check to see if res.mEnd is within the range covered
- // by this entry.
-
- if (static_cast<uint32_t>(entry->mStrOffset) <= res.mEnd &&
- res.mEnd <= static_cast<uint32_t>(strEndOffset)) {
- if (res.mBegin == res.mEnd &&
- res.mEnd == static_cast<uint32_t>(strEndOffset) &&
- i != lastIndex) {
- // Wait for the next round so that we use the same entry
- // we did for aWordStartNode.
- continue;
- }
-
- if (aWordEndNode) {
- *aWordEndNode = entry->mNode;
- NS_IF_ADDREF(*aWordEndNode);
- }
-
- if (aWordEndOffset) {
- *aWordEndOffset = entry->mNodeOffset + res.mEnd - entry->mStrOffset;
- }
- break;
- }
- }
-
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::WillInsertNode(nsIDOMNode *aNode,
- nsIDOMNode *aParent,
- int32_t aPosition)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::WillDeleteNode(nsIDOMNode *aChild)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::WillSplitNode(nsIDOMNode *aExistingRightNode,
- int32_t aOffset)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::WillJoinNodes(nsIDOMNode *aLeftNode,
- nsIDOMNode *aRightNode,
- nsIDOMNode *aParent)
-{
- return NS_OK;
-}
-
-// -------------------------------
-// stubs for unused listen methods
-// -------------------------------
-
-NS_IMETHODIMP
-nsTextServicesDocument::WillCreateNode(const nsAString& aTag, nsIDOMNode *aParent, int32_t aPosition)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::DidCreateNode(const nsAString& aTag, nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t aPosition, nsresult aResult)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::WillInsertText(nsIDOMCharacterData *aTextNode, int32_t aOffset, const nsAString &aString)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::DidInsertText(nsIDOMCharacterData *aTextNode, int32_t aOffset, const nsAString &aString, nsresult aResult)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::WillDeleteText(nsIDOMCharacterData *aTextNode, int32_t aOffset, int32_t aLength)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::DidDeleteText(nsIDOMCharacterData *aTextNode, int32_t aOffset, int32_t aLength, nsresult aResult)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::WillDeleteSelection(nsISelection *aSelection)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTextServicesDocument::DidDeleteSelection(nsISelection *aSelection)
-{
- return NS_OK;
-}
diff --git a/editor/txtsvc/nsTextServicesDocument.h b/editor/txtsvc/nsTextServicesDocument.h
deleted file mode 100644
index d4e034546..000000000
--- a/editor/txtsvc/nsTextServicesDocument.h
+++ /dev/null
@@ -1,236 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsTextServicesDocument_h__
-#define nsTextServicesDocument_h__
-
-#include "nsCOMPtr.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsIEditActionListener.h"
-#include "nsISupportsImpl.h"
-#include "nsITextServicesDocument.h"
-#include "nsIWeakReferenceUtils.h"
-#include "nsTArray.h"
-#include "nscore.h"
-
-class OffsetEntry;
-class nsIAtom;
-class nsIContent;
-class nsIContentIterator;
-class nsIDOMCharacterData;
-class nsIDOMDocument;
-class nsIDOMNode;
-class nsIDOMRange;
-class nsIEditor;
-class nsISelection;
-class nsISelectionController;
-class nsITextServicesFilter;
-class nsString;
-
-/** implementation of a text services object.
- *
- */
-class nsTextServicesDocument final : public nsITextServicesDocument,
- public nsIEditActionListener
-{
-private:
- static nsIAtom *sAAtom;
- static nsIAtom *sAddressAtom;
- static nsIAtom *sBigAtom;
- static nsIAtom *sBAtom;
- static nsIAtom *sCiteAtom;
- static nsIAtom *sCodeAtom;
- static nsIAtom *sDfnAtom;
- static nsIAtom *sEmAtom;
- static nsIAtom *sFontAtom;
- static nsIAtom *sIAtom;
- static nsIAtom *sKbdAtom;
- static nsIAtom *sKeygenAtom;
- static nsIAtom *sNobrAtom;
- static nsIAtom *sSAtom;
- static nsIAtom *sSampAtom;
- static nsIAtom *sSmallAtom;
- static nsIAtom *sSpacerAtom;
- static nsIAtom *sSpanAtom;
- static nsIAtom *sStrikeAtom;
- static nsIAtom *sStrongAtom;
- static nsIAtom *sSubAtom;
- static nsIAtom *sSupAtom;
- static nsIAtom *sTtAtom;
- static nsIAtom *sUAtom;
- static nsIAtom *sVarAtom;
- static nsIAtom *sWbrAtom;
-
- typedef enum { eIsDone=0, // No iterator (I), or iterator doesn't point to anything valid.
- eValid, // I points to first text node (TN) in current block (CB).
- ePrev, // No TN in CB, I points to first TN in prev block.
- eNext // No TN in CB, I points to first TN in next block.
- } TSDIteratorStatus;
-
- nsCOMPtr<nsIDOMDocument> mDOMDocument;
- nsCOMPtr<nsISelectionController>mSelCon;
- nsWeakPtr mEditor; // avoid a cycle with the spell checker and editor
- nsCOMPtr<nsIContentIterator> mIterator;
- TSDIteratorStatus mIteratorStatus;
- nsCOMPtr<nsIContent> mPrevTextBlock;
- nsCOMPtr<nsIContent> mNextTextBlock;
- nsTArray<OffsetEntry*> mOffsetTable;
-
- int32_t mSelStartIndex;
- int32_t mSelStartOffset;
- int32_t mSelEndIndex;
- int32_t mSelEndOffset;
-
- RefPtr<nsRange> mExtent;
-
- nsCOMPtr<nsITextServicesFilter> mTxtSvcFilter;
-
-protected:
- /** The default destructor.
- */
- virtual ~nsTextServicesDocument();
-
-public:
-
- /** The default constructor.
- */
- nsTextServicesDocument();
-
- /** To be called at module init
- */
- static void RegisterAtoms();
-
- /* Macro for AddRef(), Release(), and QueryInterface() */
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsTextServicesDocument, nsITextServicesDocument)
-
- /* nsITextServicesDocument method implementations. */
- NS_IMETHOD InitWithEditor(nsIEditor *aEditor) override;
- NS_IMETHOD GetDocument(nsIDOMDocument **aDoc) override;
- NS_IMETHOD SetExtent(nsIDOMRange* aDOMRange) override;
- NS_IMETHOD ExpandRangeToWordBoundaries(nsIDOMRange *aRange) override;
- NS_IMETHOD SetFilter(nsITextServicesFilter *aFilter) override;
- NS_IMETHOD GetCurrentTextBlock(nsString *aStr) override;
- NS_IMETHOD FirstBlock() override;
- NS_IMETHOD LastSelectedBlock(TSDBlockSelectionStatus *aSelStatus, int32_t *aSelOffset, int32_t *aSelLength) override;
- NS_IMETHOD PrevBlock() override;
- NS_IMETHOD NextBlock() override;
- NS_IMETHOD IsDone(bool *aIsDone) override;
- NS_IMETHOD SetSelection(int32_t aOffset, int32_t aLength) override;
- NS_IMETHOD ScrollSelectionIntoView() override;
- NS_IMETHOD DeleteSelection() override;
- NS_IMETHOD InsertText(const nsString *aText) override;
-
- /* nsIEditActionListener method implementations. */
- NS_IMETHOD WillInsertNode(nsIDOMNode *aNode,
- nsIDOMNode *aParent,
- int32_t aPosition) override;
- NS_IMETHOD DidInsertNode(nsIDOMNode *aNode,
- nsIDOMNode *aParent,
- int32_t aPosition,
- nsresult aResult) override;
-
- NS_IMETHOD WillDeleteNode(nsIDOMNode *aChild) override;
- NS_IMETHOD DidDeleteNode(nsIDOMNode *aChild, nsresult aResult) override;
-
- NS_IMETHOD WillSplitNode(nsIDOMNode * aExistingRightNode,
- int32_t aOffset) override;
- NS_IMETHOD DidSplitNode(nsIDOMNode *aExistingRightNode,
- int32_t aOffset,
- nsIDOMNode *aNewLeftNode,
- nsresult aResult) override;
-
- NS_IMETHOD WillJoinNodes(nsIDOMNode *aLeftNode,
- nsIDOMNode *aRightNode,
- nsIDOMNode *aParent) override;
- NS_IMETHOD DidJoinNodes(nsIDOMNode *aLeftNode,
- nsIDOMNode *aRightNode,
- nsIDOMNode *aParent,
- nsresult aResult) override;
- // these listen methods are unused:
- NS_IMETHOD WillCreateNode(const nsAString& aTag, nsIDOMNode *aParent, int32_t aPosition) override;
- NS_IMETHOD DidCreateNode(const nsAString& aTag, nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t aPosition, nsresult aResult) override;
- NS_IMETHOD WillInsertText(nsIDOMCharacterData *aTextNode, int32_t aOffset, const nsAString &aString) override;
- NS_IMETHOD DidInsertText(nsIDOMCharacterData *aTextNode, int32_t aOffset, const nsAString &aString, nsresult aResult) override;
- NS_IMETHOD WillDeleteText(nsIDOMCharacterData *aTextNode, int32_t aOffset, int32_t aLength) override;
- NS_IMETHOD DidDeleteText(nsIDOMCharacterData *aTextNode, int32_t aOffset, int32_t aLength, nsresult aResult) override;
- NS_IMETHOD WillDeleteSelection(nsISelection *aSelection) override;
- NS_IMETHOD DidDeleteSelection(nsISelection *aSelection) override;
-
- /* Helper functions */
- static nsresult GetRangeEndPoints(nsRange* aRange, nsIDOMNode** aParent1,
- int32_t* aOffset1, nsIDOMNode** aParent2,
- int32_t* aOffset2);
- static nsresult CreateRange(nsIDOMNode* aStartParent, int32_t aStartOffset,
- nsIDOMNode* aEndParent, int32_t aEndOffset,
- nsRange** aRange);
-
-private:
- /* nsTextServicesDocument private methods. */
-
- nsresult CreateContentIterator(nsRange* aRange,
- nsIContentIterator** aIterator);
-
- nsresult GetDocumentContentRootNode(nsIDOMNode **aNode);
- nsresult CreateDocumentContentRange(nsRange** aRange);
- nsresult CreateDocumentContentRootToNodeOffsetRange(nsIDOMNode* aParent,
- int32_t aOffset,
- bool aToStart,
- nsRange** aRange);
- nsresult CreateDocumentContentIterator(nsIContentIterator **aIterator);
-
- nsresult AdjustContentIterator();
-
- static nsresult FirstTextNode(nsIContentIterator *aIterator, TSDIteratorStatus *IteratorStatus);
- static nsresult LastTextNode(nsIContentIterator *aIterator, TSDIteratorStatus *IteratorStatus);
-
- static nsresult FirstTextNodeInCurrentBlock(nsIContentIterator *aIterator);
- static nsresult FirstTextNodeInPrevBlock(nsIContentIterator *aIterator);
- static nsresult FirstTextNodeInNextBlock(nsIContentIterator *aIterator);
-
- nsresult GetFirstTextNodeInPrevBlock(nsIContent **aContent);
- nsresult GetFirstTextNodeInNextBlock(nsIContent **aContent);
-
- static bool IsBlockNode(nsIContent *aContent);
- static bool IsTextNode(nsIContent *aContent);
- static bool IsTextNode(nsIDOMNode *aNode);
-
- static bool DidSkip(nsIContentIterator* aFilteredIter);
- static void ClearDidSkip(nsIContentIterator* aFilteredIter);
-
- static bool HasSameBlockNodeParent(nsIContent *aContent1, nsIContent *aContent2);
-
- nsresult SetSelectionInternal(int32_t aOffset, int32_t aLength, bool aDoUpdate);
- nsresult GetSelection(TSDBlockSelectionStatus *aSelStatus, int32_t *aSelOffset, int32_t *aSelLength);
- nsresult GetCollapsedSelection(TSDBlockSelectionStatus *aSelStatus, int32_t *aSelOffset, int32_t *aSelLength);
- nsresult GetUncollapsedSelection(TSDBlockSelectionStatus *aSelStatus, int32_t *aSelOffset, int32_t *aSelLength);
-
- bool SelectionIsCollapsed();
- bool SelectionIsValid();
-
- static nsresult CreateOffsetTable(nsTArray<OffsetEntry*> *aOffsetTable,
- nsIContentIterator *aIterator,
- TSDIteratorStatus *aIteratorStatus,
- nsRange* aIterRange, nsString* aStr);
- static nsresult ClearOffsetTable(nsTArray<OffsetEntry*> *aOffsetTable);
-
- static nsresult NodeHasOffsetEntry(nsTArray<OffsetEntry*> *aOffsetTable,
- nsIDOMNode *aNode,
- bool *aHasEntry,
- int32_t *aEntryIndex);
-
- nsresult RemoveInvalidOffsetEntries();
- nsresult SplitOffsetEntry(int32_t aTableIndex, int32_t aOffsetIntoEntry);
-
- static nsresult FindWordBounds(nsTArray<OffsetEntry*> *offsetTable,
- nsString *blockStr,
- nsIDOMNode *aNode, int32_t aNodeOffset,
- nsIDOMNode **aWordStartNode,
- int32_t *aWordStartOffset,
- nsIDOMNode **aWordEndNode,
- int32_t *aWordEndOffset);
-};
-
-#endif // nsTextServicesDocument_h__
diff --git a/editor/txtsvc/nsTextServicesFactory.cpp b/editor/txtsvc/nsTextServicesFactory.cpp
deleted file mode 100644
index 845fb344d..000000000
--- a/editor/txtsvc/nsTextServicesFactory.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIGenericFactory.h"
-
-#include "nsTextServicesDocument.h"
-#include "nsTextServicesCID.h"
-
-////////////////////////////////////////////////////////////////////////
-// Define the contructor function for the objects
-//
-// NOTE: This creates an instance of objects by using the default constructor
-//
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsTextServicesDocument)
-
-////////////////////////////////////////////////////////////////////////
-// Define a table of CIDs implemented by this module along with other
-// information like the function to create an instance, contractid, and
-// class name.
-//
-static const nsModuleComponentInfo components[] = {
- { nullptr, NS_TEXTSERVICESDOCUMENT_CID, "@mozilla.org/textservices/textservicesdocument;1", nsTextServicesDocumentConstructor },
-};
-
-////////////////////////////////////////////////////////////////////////
-// Implement the NSGetModule() exported function for your module
-// and the entire implementation of the module object.
-//
-NS_IMPL_NSGETMODULE(nsTextServicesModule, components)
diff --git a/editor/ui/composer/content/ComposerCommands.js b/editor/ui/composer/content/ComposerCommands.js
deleted file mode 100644
index 1dfbe03b7..000000000
--- a/editor/ui/composer/content/ComposerCommands.js
+++ /dev/null
@@ -1,3900 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Implementations of nsIControllerCommand for composer commands */
-
-var gComposerJSCommandControllerID = 0;
-
-
-//-----------------------------------------------------------------------------------
-function SetupHTMLEditorCommands()
-{
- var commandTable = GetComposerCommandTable();
- if (!commandTable)
- return;
-
- // Include everthing a text editor does
- SetupTextEditorCommands();
-
- //dump("Registering HTML editor commands\n");
-
- commandTable.registerCommand("cmd_renderedHTMLEnabler", nsDummyHTMLCommand);
-
- commandTable.registerCommand("cmd_grid", nsGridCommand);
-
- commandTable.registerCommand("cmd_listProperties", nsListPropertiesCommand);
- commandTable.registerCommand("cmd_pageProperties", nsPagePropertiesCommand);
- commandTable.registerCommand("cmd_colorProperties", nsColorPropertiesCommand);
- commandTable.registerCommand("cmd_increaseFontStep", nsIncreaseFontCommand);
- commandTable.registerCommand("cmd_decreaseFontStep", nsDecreaseFontCommand);
- commandTable.registerCommand("cmd_advancedProperties", nsAdvancedPropertiesCommand);
- commandTable.registerCommand("cmd_objectProperties", nsObjectPropertiesCommand);
- commandTable.registerCommand("cmd_removeNamedAnchors", nsRemoveNamedAnchorsCommand);
- commandTable.registerCommand("cmd_editLink", nsEditLinkCommand);
-
- commandTable.registerCommand("cmd_form", nsFormCommand);
- commandTable.registerCommand("cmd_inputtag", nsInputTagCommand);
- commandTable.registerCommand("cmd_inputimage", nsInputImageCommand);
- commandTable.registerCommand("cmd_textarea", nsTextAreaCommand);
- commandTable.registerCommand("cmd_select", nsSelectCommand);
- commandTable.registerCommand("cmd_button", nsButtonCommand);
- commandTable.registerCommand("cmd_label", nsLabelCommand);
- commandTable.registerCommand("cmd_fieldset", nsFieldSetCommand);
- commandTable.registerCommand("cmd_isindex", nsIsIndexCommand);
- commandTable.registerCommand("cmd_image", nsImageCommand);
- commandTable.registerCommand("cmd_hline", nsHLineCommand);
- commandTable.registerCommand("cmd_link", nsLinkCommand);
- commandTable.registerCommand("cmd_anchor", nsAnchorCommand);
- commandTable.registerCommand("cmd_insertHTMLWithDialog", nsInsertHTMLWithDialogCommand);
- commandTable.registerCommand("cmd_insertMathWithDialog", nsInsertMathWithDialogCommand);
- commandTable.registerCommand("cmd_insertBreak", nsInsertBreakCommand);
- commandTable.registerCommand("cmd_insertBreakAll",nsInsertBreakAllCommand);
-
- commandTable.registerCommand("cmd_table", nsInsertOrEditTableCommand);
- commandTable.registerCommand("cmd_editTable", nsEditTableCommand);
- commandTable.registerCommand("cmd_SelectTable", nsSelectTableCommand);
- commandTable.registerCommand("cmd_SelectRow", nsSelectTableRowCommand);
- commandTable.registerCommand("cmd_SelectColumn", nsSelectTableColumnCommand);
- commandTable.registerCommand("cmd_SelectCell", nsSelectTableCellCommand);
- commandTable.registerCommand("cmd_SelectAllCells", nsSelectAllTableCellsCommand);
- commandTable.registerCommand("cmd_InsertTable", nsInsertTableCommand);
- commandTable.registerCommand("cmd_InsertRowAbove", nsInsertTableRowAboveCommand);
- commandTable.registerCommand("cmd_InsertRowBelow", nsInsertTableRowBelowCommand);
- commandTable.registerCommand("cmd_InsertColumnBefore", nsInsertTableColumnBeforeCommand);
- commandTable.registerCommand("cmd_InsertColumnAfter", nsInsertTableColumnAfterCommand);
- commandTable.registerCommand("cmd_InsertCellBefore", nsInsertTableCellBeforeCommand);
- commandTable.registerCommand("cmd_InsertCellAfter", nsInsertTableCellAfterCommand);
- commandTable.registerCommand("cmd_DeleteTable", nsDeleteTableCommand);
- commandTable.registerCommand("cmd_DeleteRow", nsDeleteTableRowCommand);
- commandTable.registerCommand("cmd_DeleteColumn", nsDeleteTableColumnCommand);
- commandTable.registerCommand("cmd_DeleteCell", nsDeleteTableCellCommand);
- commandTable.registerCommand("cmd_DeleteCellContents", nsDeleteTableCellContentsCommand);
- commandTable.registerCommand("cmd_JoinTableCells", nsJoinTableCellsCommand);
- commandTable.registerCommand("cmd_SplitTableCell", nsSplitTableCellCommand);
- commandTable.registerCommand("cmd_TableOrCellColor", nsTableOrCellColorCommand);
- commandTable.registerCommand("cmd_NormalizeTable", nsNormalizeTableCommand);
- commandTable.registerCommand("cmd_smiley", nsSetSmiley);
- commandTable.registerCommand("cmd_ConvertToTable", nsConvertToTable);
-}
-
-function SetupTextEditorCommands()
-{
- var commandTable = GetComposerCommandTable();
- if (!commandTable)
- return;
-
- //dump("Registering plain text editor commands\n");
-
- commandTable.registerCommand("cmd_findReplace",nsFindReplaceCommand);
- commandTable.registerCommand("cmd_find", nsFindCommand);
- commandTable.registerCommand("cmd_findNext", nsFindAgainCommand);
- commandTable.registerCommand("cmd_findPrev", nsFindAgainCommand);
- commandTable.registerCommand("cmd_rewrap", nsRewrapCommand);
- commandTable.registerCommand("cmd_spelling", nsSpellingCommand);
- commandTable.registerCommand("cmd_validate", nsValidateCommand);
- commandTable.registerCommand("cmd_checkLinks", nsCheckLinksCommand);
- commandTable.registerCommand("cmd_insertChars", nsInsertCharsCommand);
-}
-
-function SetupComposerWindowCommands()
-{
- // Don't need to do this if already done
- if (gComposerWindowControllerID)
- return;
-
- // Create a command controller and register commands
- // specific to Web Composer window (file-related commands, HTML Source...)
- // We can't use the composer controller created on the content window else
- // we can't process commands when in HTMLSource editor
- // IMPORTANT: For each of these commands, the doCommand method
- // must first call SetEditMode(gPreviousNonSourceDisplayMode);
- // to go from HTML Source mode to any other edit mode
-
- var windowControllers = window.controllers;
-
- if (!windowControllers) return;
-
- var commandTable;
- var composerController;
- var editorController;
- try {
- composerController = Components.classes["@mozilla.org/embedcomp/base-command-controller;1"].createInstance();
-
- editorController = composerController.QueryInterface(Components.interfaces.nsIControllerContext);
- editorController.init(null); // init it without passing in a command table
-
- // Get the nsIControllerCommandTable interface we need to register commands
- var interfaceRequestor = composerController.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
- commandTable = interfaceRequestor.getInterface(Components.interfaces.nsIControllerCommandTable);
- }
- catch (e)
- {
- dump("Failed to create composerController\n");
- return;
- }
-
-
- if (!commandTable)
- {
- dump("Failed to get interface for nsIControllerCommandManager\n");
- return;
- }
-
- // File-related commands
- commandTable.registerCommand("cmd_open", nsOpenCommand);
- commandTable.registerCommand("cmd_save", nsSaveCommand);
- commandTable.registerCommand("cmd_saveAs", nsSaveAsCommand);
- commandTable.registerCommand("cmd_exportToText", nsExportToTextCommand);
- commandTable.registerCommand("cmd_saveAndChangeEncoding", nsSaveAndChangeEncodingCommand);
- commandTable.registerCommand("cmd_publish", nsPublishCommand);
- commandTable.registerCommand("cmd_publishAs", nsPublishAsCommand);
- commandTable.registerCommand("cmd_publishSettings",nsPublishSettingsCommand);
- commandTable.registerCommand("cmd_revert", nsRevertCommand);
- commandTable.registerCommand("cmd_openRemote", nsOpenRemoteCommand);
- commandTable.registerCommand("cmd_preview", nsPreviewCommand);
- commandTable.registerCommand("cmd_editSendPage", nsSendPageCommand);
- commandTable.registerCommand("cmd_print", nsPrintCommand);
- commandTable.registerCommand("cmd_printpreview", nsPrintPreviewCommand);
- commandTable.registerCommand("cmd_printSetup", nsPrintSetupCommand);
- commandTable.registerCommand("cmd_close", nsCloseCommand);
- commandTable.registerCommand("cmd_preferences", nsPreferencesCommand);
-
- // Edit Mode commands
- if (GetCurrentEditorType() == "html")
- {
- commandTable.registerCommand("cmd_NormalMode", nsNormalModeCommand);
- commandTable.registerCommand("cmd_AllTagsMode", nsAllTagsModeCommand);
- commandTable.registerCommand("cmd_HTMLSourceMode", nsHTMLSourceModeCommand);
- commandTable.registerCommand("cmd_PreviewMode", nsPreviewModeCommand);
- commandTable.registerCommand("cmd_FinishHTMLSource", nsFinishHTMLSource);
- commandTable.registerCommand("cmd_CancelHTMLSource", nsCancelHTMLSource);
- commandTable.registerCommand("cmd_updateStructToolbar", nsUpdateStructToolbarCommand);
- }
-
- windowControllers.insertControllerAt(0, editorController);
-
- // Store the controller ID so we can be sure to get the right one later
- gComposerWindowControllerID = windowControllers.getControllerId(editorController);
-}
-
-//-----------------------------------------------------------------------------------
-function GetComposerCommandTable()
-{
- var controller;
- if (gComposerJSCommandControllerID)
- {
- try {
- controller = window.content.controllers.getControllerById(gComposerJSCommandControllerID);
- } catch (e) {}
- }
- if (!controller)
- {
- //create it
- controller = Components.classes["@mozilla.org/embedcomp/base-command-controller;1"].createInstance();
-
- var editorController = controller.QueryInterface(Components.interfaces.nsIControllerContext);
- editorController.init(null);
- editorController.setCommandContext(GetCurrentEditorElement());
- window.content.controllers.insertControllerAt(0, controller);
-
- // Store the controller ID so we can be sure to get the right one later
- gComposerJSCommandControllerID = window.content.controllers.getControllerId(controller);
- }
-
- if (controller)
- {
- var interfaceRequestor = controller.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
- return interfaceRequestor.getInterface(Components.interfaces.nsIControllerCommandTable);
- }
- return null;
-}
-
-//-----------------------------------------------------------------------------------
-function goUpdateCommandState(command)
-{
- try
- {
- var controller = top.document.commandDispatcher.getControllerForCommand(command);
- if (!(controller instanceof Components.interfaces.nsICommandController))
- return;
-
- var params = newCommandParams();
- if (!params) return;
-
- controller.getCommandStateWithParams(command, params);
-
- switch (command)
- {
- case "cmd_bold":
- case "cmd_italic":
- case "cmd_underline":
- case "cmd_var":
- case "cmd_samp":
- case "cmd_code":
- case "cmd_acronym":
- case "cmd_abbr":
- case "cmd_cite":
- case "cmd_strong":
- case "cmd_em":
- case "cmd_superscript":
- case "cmd_subscript":
- case "cmd_strikethrough":
- case "cmd_tt":
- case "cmd_nobreak":
- case "cmd_ul":
- case "cmd_ol":
- pokeStyleUI(command, params.getBooleanValue("state_all"));
- break;
-
- case "cmd_paragraphState":
- case "cmd_align":
- case "cmd_highlight":
- case "cmd_backgroundColor":
- case "cmd_fontColor":
- case "cmd_fontFace":
- case "cmd_fontSize":
- case "cmd_absPos":
- pokeMultiStateUI(command, params);
- break;
-
- case "cmd_decreaseZIndex":
- case "cmd_increaseZIndex":
- case "cmd_indent":
- case "cmd_outdent":
- case "cmd_increaseFont":
- case "cmd_decreaseFont":
- case "cmd_increaseFontStep":
- case "cmd_decreaseFontStep":
- case "cmd_removeStyles":
- case "cmd_smiley":
- break;
-
- default: dump("no update for command: " +command+"\n");
- }
- }
- catch (e) { dump("An error occurred updating the "+command+" command: \n"+e+"\n"); }
-}
-
-function goUpdateComposerMenuItems(commandset)
-{
- //dump("Updating commands for " + commandset.id + "\n");
-
- for (var i = 0; i < commandset.childNodes.length; i++)
- {
- var commandNode = commandset.childNodes[i];
- var commandID = commandNode.id;
- if (commandID)
- {
- goUpdateCommand(commandID); // enable or disable
- if (commandNode.hasAttribute("state"))
- goUpdateCommandState(commandID);
- }
- }
-}
-
-//-----------------------------------------------------------------------------------
-function goDoCommandParams(command, params)
-{
- try
- {
- var controller = top.document.commandDispatcher.getControllerForCommand(command);
- if (controller && controller.isCommandEnabled(command))
- {
- if (controller instanceof Components.interfaces.nsICommandController)
- {
- controller.doCommandWithParams(command, params);
-
- // the following two lines should be removed when we implement observers
- if (params)
- controller.getCommandStateWithParams(command, params);
- }
- else
- {
- controller.doCommand(command);
- }
- ResetStructToolbar();
- }
- }
- catch (e)
- {
- dump("An error occurred executing the "+command+" command\n");
- }
-}
-
-function pokeStyleUI(uiID, aDesiredState)
-{
- try {
- var commandNode = top.document.getElementById(uiID);
- if (!commandNode)
- return;
-
- var uiState = ("true" == commandNode.getAttribute("state"));
- if (aDesiredState != uiState)
- {
- commandNode.setAttribute("state", aDesiredState ? "true" : "false");
- }
- } catch(e) { dump("poking UI for "+uiID+" failed: "+e+"\n"); }
-}
-
-function doStyleUICommand(cmdStr)
-{
- try
- {
- var cmdParams = newCommandParams();
- goDoCommandParams(cmdStr, cmdParams);
- if (cmdParams)
- pokeStyleUI(cmdStr, cmdParams.getBooleanValue("state_all"));
-
- ResetStructToolbar();
- } catch(e) {}
-}
-
-// Copied from jsmime.js.
-function stringToTypedArray(buffer) {
- var typedarray = new Uint8Array(buffer.length);
- for (var i = 0; i < buffer.length; i++) {
- typedarray[i] = buffer.charCodeAt(i);
- }
- return typedarray;
-}
-
-function pokeMultiStateUI(uiID, cmdParams)
-{
- try
- {
- var commandNode = document.getElementById(uiID);
- if (!commandNode)
- return;
-
- var isMixed = cmdParams.getBooleanValue("state_mixed");
- var desiredAttrib;
- if (isMixed)
- desiredAttrib = "mixed";
- else {
- var valuetype = cmdParams.getValueType("state_attribute");
- if (valuetype == Components.interfaces.nsICommandParams.eStringType) {
- desiredAttrib = cmdParams.getCStringValue("state_attribute");
- // Decode UTF-8, for example for font names in Japanese.
- desiredAttrib = new TextDecoder("UTF-8").decode(stringToTypedArray(desiredAttrib));
- } else {
- desiredAttrib = cmdParams.getStringValue("state_attribute");
- }
-
- }
-
- var uiState = commandNode.getAttribute("state");
- if (desiredAttrib != uiState)
- {
- commandNode.setAttribute("state", desiredAttrib);
- }
- } catch(e) {}
-}
-
-function doStatefulCommand(commandID, newState)
-{
- var commandNode = document.getElementById(commandID);
- if (commandNode)
- commandNode.setAttribute("state", newState);
- gContentWindow.focus(); // needed for command dispatch to work
-
- try
- {
- var cmdParams = newCommandParams();
- if (!cmdParams) return;
-
- cmdParams.setStringValue("state_attribute", newState);
- goDoCommandParams(commandID, cmdParams);
-
- pokeMultiStateUI(commandID, cmdParams);
-
- ResetStructToolbar();
- } catch(e) { dump("error thrown in doStatefulCommand: "+e+"\n"); }
-}
-
-//-----------------------------------------------------------------------------------
-function PrintObject(obj)
-{
- dump("-----" + obj + "------\n");
- var names = "";
- for (var i in obj)
- {
- if (i == "value")
- names += i + ": " + obj.value + "\n";
- else if (i == "id")
- names += i + ": " + obj.id + "\n";
- else
- names += i + "\n";
- }
-
- dump(names + "-----------\n");
-}
-
-//-----------------------------------------------------------------------------------
-function PrintNodeID(id)
-{
- PrintObject(document.getElementById(id));
-}
-
-//-----------------------------------------------------------------------------------
-var nsDummyHTMLCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- // do nothing
- dump("Hey, who's calling the dummy command?\n");
- }
-
-};
-
-//-----------------------------------------------------------------------------------
-var nsOpenCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return true; // we can always do this
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- var fileType = IsHTMLEditor() ? "html" : "text";
- var title = GetString(IsHTMLEditor() ? "OpenHTMLFile" : "OpenTextFile");
-
- var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
- fp.init(window, title, nsIFilePicker.modeOpen);
-
- SetFilePickerDirectory(fp, fileType);
-
- // Direct user to prefer HTML files and/or text files depending on whether
- // loading into Composer or Text editor, so we call separately to control
- // the order of the filter list.
- if (fileType == "html")
- fp.appendFilters(nsIFilePicker.filterHTML);
- fp.appendFilters(nsIFilePicker.filterText);
- fp.appendFilters(nsIFilePicker.filterAll);
-
- /* doesn't handle *.shtml files */
- if (fp.show() == nsIFilePicker.returnCancel)
- return;
-
- // editPage checks for already open window and activates it.
- if (fp.fileURL.spec) {
- SaveFilePickerDirectory(fp, fileType);
- editPage(fp.fileURL.spec, fileType);
- }
- }
-};
-
-// STRUCTURE TOOLBAR
-//
-var nsUpdateStructToolbarCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- UpdateStructToolbar();
- return true;
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
- doCommand: function(aCommand) {}
-}
-
-// ******* File output commands and utilities ******** //
-//-----------------------------------------------------------------------------------
-var nsSaveCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- // Always allow saving when editing a remote document,
- // otherwise the document modified state would prevent that
- // when you first open a remote file.
- try {
- var docUrl = GetDocumentUrl();
- return IsDocumentEditable() &&
- (IsDocumentModified() || IsHTMLSourceChanged() ||
- IsUrlAboutBlank(docUrl) || GetScheme(docUrl) != "file");
- } catch (e) {return false;}
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- var result = false;
- var editor = GetCurrentEditor();
- if (editor)
- {
- if (IsHTMLEditor())
- SetEditMode(gPreviousNonSourceDisplayMode);
- result = SaveDocument(IsUrlAboutBlank(GetDocumentUrl()), false, editor.contentsMIMEType);
- }
- return result;
- }
-}
-
-var nsSaveAsCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- var result = false;
- var editor = GetCurrentEditor();
- if (editor)
- {
- if (IsHTMLEditor())
- SetEditMode(gPreviousNonSourceDisplayMode);
- result = SaveDocument(true, false, editor.contentsMIMEType);
- }
- return result;
- }
-}
-
-var nsExportToTextCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- if (GetCurrentEditor())
- {
- SetEditMode(gPreviousNonSourceDisplayMode);
- var result = SaveDocument(true, true, "text/plain");
- return result;
- }
- return false;
- }
-}
-
-var nsSaveAndChangeEncodingCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- SetEditMode(gPreviousNonSourceDisplayMode);
- window.ok = false;
- window.exportToText = false;
- var oldTitle = GetDocumentTitle();
- window.openDialog("chrome://editor/content/EditorSaveAsCharset.xul","_blank", "chrome,close,titlebar,modal,resizable=yes");
-
- if (GetDocumentTitle() != oldTitle)
- UpdateWindowTitle();
-
- if (window.ok)
- {
- if (window.exportToText)
- {
- window.ok = SaveDocument(true, true, "text/plain");
- }
- else
- {
- var editor = GetCurrentEditor();
- window.ok = SaveDocument(true, false, editor ? editor.contentsMIMEType : null);
- }
- }
-
- return window.ok;
- }
-};
-
-var nsPublishCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- if (IsDocumentEditable())
- {
- // Always allow publishing when editing a local document,
- // otherwise the document modified state would prevent that
- // when you first open any local file.
- try {
- var docUrl = GetDocumentUrl();
- return IsDocumentModified() || IsHTMLSourceChanged()
- || IsUrlAboutBlank(docUrl) || GetScheme(docUrl) == "file";
- } catch (e) {return false;}
- }
- return false;
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- if (GetCurrentEditor())
- {
- let docUrl = GetDocumentUrl();
- let filename = GetFilename(docUrl);
- let publishData;
-
- // First check pref to always show publish dialog
- let showPublishDialog = Services.prefs.getBoolPref("editor.always_show_publish_dialog");
-
- if (!showPublishDialog && filename)
- {
- // Try to get publish data from the document url
- publishData = CreatePublishDataFromUrl(docUrl);
-
- // If none, use default publishing site? Need a pref for this
- //if (!publishData)
- // publishData = GetPublishDataFromSiteName(GetDefaultPublishSiteName(), filename);
- }
-
- if (showPublishDialog || !publishData)
- {
- // Show the publish dialog
- publishData = {};
- window.ok = false;
- let oldTitle = GetDocumentTitle();
- window.openDialog("chrome://editor/content/EditorPublish.xul","_blank",
- "chrome,close,titlebar,modal", "", "", publishData);
- if (GetDocumentTitle() != oldTitle)
- UpdateWindowTitle();
-
- if (!window.ok)
- return false;
- }
- if (publishData)
- {
- SetEditMode(gPreviousNonSourceDisplayMode);
- return Publish(publishData);
- }
- }
- return false;
- }
-}
-
-var nsPublishAsCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- if (GetCurrentEditor())
- {
- SetEditMode(gPreviousNonSourceDisplayMode);
-
- window.ok = false;
- var publishData = {};
- var oldTitle = GetDocumentTitle();
- window.openDialog("chrome://editor/content/EditorPublish.xul","_blank",
- "chrome,close,titlebar,modal", "", "", publishData);
- if (GetDocumentTitle() != oldTitle)
- UpdateWindowTitle();
-
- if (window.ok)
- return Publish(publishData);
- }
- return false;
- }
-}
-
-// ------- output utilites ----- //
-
-// returns a fileExtension string
-function GetExtensionBasedOnMimeType(aMIMEType)
-{
- try {
- var mimeService = null;
- mimeService = Components.classes["@mozilla.org/mime;1"]
- .getService(Components.interfaces.nsIMIMEService);
-
- var fileExtension = mimeService.getPrimaryExtension(aMIMEType, null);
-
- // the MIME service likes to give back ".htm" for text/html files,
- // so do a special-case fix here.
- if (fileExtension == "htm")
- fileExtension = "html";
-
- return fileExtension;
- }
- catch (e) {}
- return "";
-}
-
-function GetSuggestedFileName(aDocumentURLString, aMIMEType)
-{
- var extension = GetExtensionBasedOnMimeType(aMIMEType);
- if (extension)
- extension = "." + extension;
-
- // check for existing file name we can use
- if (aDocumentURLString && !IsUrlAboutBlank(aDocumentURLString))
- {
- try {
- let docURI = Services.io.newURI(aDocumentURLString,
- GetCurrentEditor().documentCharacterSet, null);
- docURI = docURI.QueryInterface(Components.interfaces.nsIURL);
-
- // grab the file name
- let url = validateFileName(decodeURIComponent(docURI.fileBaseName));
- if (url)
- return url + extension;
- } catch(e) {}
- }
-
- // Check if there is a title we can use to generate a valid filename,
- // if we can't, use the default filename.
- var title = validateFileName(GetDocumentTitle()) ||
- GetString("untitledDefaultFilename");
- return title + extension;
-}
-
-// returns file picker result
-function PromptForSaveLocation(aDoSaveAsText, aEditorType, aMIMEType, aDocumentURLString)
-{
- var dialogResult = {};
- dialogResult.filepickerClick = nsIFilePicker.returnCancel;
- dialogResult.resultingURI = "";
- dialogResult.resultingLocalFile = null;
-
- var fp = null;
- try {
- fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
- } catch (e) {}
- if (!fp) return dialogResult;
-
- // determine prompt string based on type of saving we'll do
- var promptString;
- if (aDoSaveAsText || aEditorType == "text")
- promptString = GetString("SaveTextAs");
- else
- promptString = GetString("SaveDocumentAs");
-
- fp.init(window, promptString, nsIFilePicker.modeSave);
-
- // Set filters according to the type of output
- if (aDoSaveAsText)
- fp.appendFilters(nsIFilePicker.filterText);
- else
- fp.appendFilters(nsIFilePicker.filterHTML);
- fp.appendFilters(nsIFilePicker.filterAll);
-
- // now let's actually set the filepicker's suggested filename
- var suggestedFileName = GetSuggestedFileName(aDocumentURLString, aMIMEType);
- if (suggestedFileName)
- fp.defaultString = suggestedFileName;
-
- // set the file picker's current directory
- // assuming we have information needed (like prior saved location)
- try {
- var fileHandler = GetFileProtocolHandler();
-
- var isLocalFile = true;
- try {
- let docURI = Services.io.newURI(aDocumentURLString, GetCurrentEditor().documentCharacterSet, null);
- isLocalFile = docURI.schemeIs("file");
- }
- catch (e) {}
-
- var parentLocation = null;
- if (isLocalFile)
- {
- var fileLocation = fileHandler.getFileFromURLSpec(aDocumentURLString); // this asserts if url is not local
- parentLocation = fileLocation.parent;
- }
- if (parentLocation)
- {
- // Save current filepicker's default location
- if ("gFilePickerDirectory" in window)
- gFilePickerDirectory = fp.displayDirectory;
-
- fp.displayDirectory = parentLocation;
- }
- else
- {
- // Initialize to the last-used directory for the particular type (saved in prefs)
- SetFilePickerDirectory(fp, aEditorType);
- }
- }
- catch(e) {}
-
- dialogResult.filepickerClick = fp.show();
- if (dialogResult.filepickerClick != nsIFilePicker.returnCancel)
- {
- // reset urlstring to new save location
- dialogResult.resultingURIString = fileHandler.getURLSpecFromFile(fp.file);
- dialogResult.resultingLocalFile = fp.file;
- SaveFilePickerDirectory(fp, aEditorType);
- }
- else if ("gFilePickerDirectory" in window && gFilePickerDirectory)
- fp.displayDirectory = gFilePickerDirectory;
-
- return dialogResult;
-}
-
-/**
- * If needed, prompt for document title and set the document title to the
- * preferred value.
- * @return true if the title was set up successfully;
- * false if the user cancelled the title prompt
- */
-function PromptAndSetTitleIfNone()
-{
- if (GetDocumentTitle()) // we have a title; no need to prompt!
- return true;
-
- let result = {value:null};
- let captionStr = GetString("DocumentTitle");
- let msgStr = GetString("NeedDocTitle") + '\n' + GetString("DocTitleHelp");
- let confirmed = Services.prompt.prompt(window, captionStr, msgStr, result, null, {value:0});
- if (confirmed)
- SetDocumentTitle(TrimString(result.value));
-
- return confirmed;
-}
-
-var gPersistObj;
-
-// Don't forget to do these things after calling OutputFileWithPersistAPI:
-// we need to update the uri before notifying listeners
-// if (doUpdateURI)
-// SetDocumentURI(docURI);
-// UpdateWindowTitle();
-// if (!aSaveCopy)
-// editor.resetModificationCount();
- // this should cause notification to listeners that document has changed
-
-const webPersist = Components.interfaces.nsIWebBrowserPersist;
-function OutputFileWithPersistAPI(editorDoc, aDestinationLocation, aRelatedFilesParentDir, aMimeType)
-{
- gPersistObj = null;
- var editor = GetCurrentEditor();
- try {
- var imeEditor = editor.QueryInterface(Components.interfaces.nsIEditorIMESupport);
- imeEditor.forceCompositionEnd();
- } catch (e) {}
-
- var isLocalFile = false;
- try {
- var tmp1 = aDestinationLocation.QueryInterface(Components.interfaces.nsIFile);
- isLocalFile = true;
- }
- catch (e) {
- try {
- var tmp = aDestinationLocation.QueryInterface(Components.interfaces.nsIURI);
- isLocalFile = tmp.schemeIs("file");
- }
- catch (e) {}
- }
-
- try {
- // we should supply a parent directory if/when we turn on functionality to save related documents
- var persistObj = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"].createInstance(webPersist);
- persistObj.progressListener = gEditorOutputProgressListener;
-
- var wrapColumn = GetWrapColumn();
- var outputFlags = GetOutputFlags(aMimeType, wrapColumn);
-
- // for 4.x parity as well as improving readability of file locally on server
- // this will always send crlf for upload (http/ftp)
- if (!isLocalFile) // if we aren't saving locally then send both cr and lf
- {
- outputFlags |= webPersist.ENCODE_FLAGS_CR_LINEBREAKS | webPersist.ENCODE_FLAGS_LF_LINEBREAKS;
-
- // we want to serialize the output for all remote publishing
- // some servers can handle only one connection at a time
- // some day perhaps we can make this user-configurable per site?
- persistObj.persistFlags = persistObj.persistFlags | webPersist.PERSIST_FLAGS_SERIALIZE_OUTPUT;
- }
-
- // note: we always want to set the replace existing files flag since we have
- // already given user the chance to not replace an existing file (file picker)
- // or the user picked an option where the file is implicitly being replaced (save)
- persistObj.persistFlags = persistObj.persistFlags
- | webPersist.PERSIST_FLAGS_NO_BASE_TAG_MODIFICATIONS
- | webPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES
- | webPersist.PERSIST_FLAGS_DONT_FIXUP_LINKS
- | webPersist.PERSIST_FLAGS_DONT_CHANGE_FILENAMES
- | webPersist.PERSIST_FLAGS_FIXUP_ORIGINAL_DOM;
- persistObj.saveDocument(editorDoc, aDestinationLocation, aRelatedFilesParentDir,
- aMimeType, outputFlags, wrapColumn);
- gPersistObj = persistObj;
- }
- catch(e) { dump("caught an error, bail\n"); return false; }
-
- return true;
-}
-
-// returns output flags based on mimetype, wrapCol and prefs
-function GetOutputFlags(aMimeType, aWrapColumn)
-{
- var outputFlags = 0;
- var editor = GetCurrentEditor();
- var outputEntity = (editor && editor.documentCharacterSet == "ISO-8859-1")
- ? webPersist.ENCODE_FLAGS_ENCODE_LATIN1_ENTITIES
- : webPersist.ENCODE_FLAGS_ENCODE_BASIC_ENTITIES;
- if (aMimeType == "text/plain")
- {
- // When saving in "text/plain" format, always do formatting
- outputFlags |= webPersist.ENCODE_FLAGS_FORMATTED;
- }
- else
- {
- // Should we prettyprint? Check the pref
- if (Services.prefs.getBoolPref("editor.prettyprint"))
- outputFlags |= webPersist.ENCODE_FLAGS_FORMATTED;
-
- try {
- // How much entity names should we output? Check the pref
- switch (Services.prefs.getCharPref("editor.encode_entity")) {
- case "basic" : outputEntity = webPersist.ENCODE_FLAGS_ENCODE_BASIC_ENTITIES; break;
- case "latin1" : outputEntity = webPersist.ENCODE_FLAGS_ENCODE_LATIN1_ENTITIES; break;
- case "html" : outputEntity = webPersist.ENCODE_FLAGS_ENCODE_HTML_ENTITIES; break;
- case "none" : outputEntity = 0; break;
- }
- }
- catch (e) {}
- }
- outputFlags |= outputEntity;
-
- if (aWrapColumn > 0)
- outputFlags |= webPersist.ENCODE_FLAGS_WRAP;
-
- return outputFlags;
-}
-
-// returns number of column where to wrap
-const nsIWebBrowserPersist = Components.interfaces.nsIWebBrowserPersist;
-function GetWrapColumn()
-{
- try {
- return GetCurrentEditor().wrapWidth;
- } catch (e) {}
- return 0;
-}
-
-const gShowDebugOutputStateChange = false;
-const gShowDebugOutputProgress = false;
-const gShowDebugOutputStatusChange = false;
-
-const gShowDebugOutputLocationChange = false;
-const gShowDebugOutputSecurityChange = false;
-
-const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
-const nsIChannel = Components.interfaces.nsIChannel;
-
-const kErrorBindingAborted = 2152398850;
-const kErrorBindingRedirected = 2152398851;
-const kFileNotFound = 2152857618;
-
-var gEditorOutputProgressListener =
-{
- onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus)
- {
- var editor = GetCurrentEditor();
-
- // Use this to access onStateChange flags
- var requestSpec;
- try {
- var channel = aRequest.QueryInterface(nsIChannel);
- requestSpec = StripUsernamePasswordFromURI(channel.URI);
- } catch (e) {
- if (gShowDebugOutputStateChange)
- dump("***** onStateChange; NO REQUEST CHANNEL\n");
- }
-
- var pubSpec;
- if (gPublishData)
- pubSpec = gPublishData.publishUrl + gPublishData.docDir + gPublishData.filename;
-
- if (gShowDebugOutputStateChange)
- {
- dump("\n***** onStateChange request: " + requestSpec + "\n");
- dump(" state flags: ");
-
- if (aStateFlags & nsIWebProgressListener.STATE_START)
- dump(" STATE_START, ");
- if (aStateFlags & nsIWebProgressListener.STATE_STOP)
- dump(" STATE_STOP, ");
- if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK)
- dump(" STATE_IS_NETWORK ");
-
- dump("\n * requestSpec="+requestSpec+", pubSpec="+pubSpec+", aStatus="+aStatus+"\n");
-
- DumpDebugStatus(aStatus);
- }
- // The rest only concerns publishing, so bail out if no dialog
- if (!gProgressDialog)
- return;
-
- // Detect start of file upload of any file:
- // (We ignore any START messages after gPersistObj says publishing is finished
- if ((aStateFlags & nsIWebProgressListener.STATE_START)
- && gPersistObj && requestSpec
- && (gPersistObj.currentState != gPersistObj.PERSIST_STATE_FINISHED))
- {
- try {
- // Add url to progress dialog's list showing each file uploading
- gProgressDialog.SetProgressStatus(GetFilename(requestSpec), "busy");
- } catch(e) {}
- }
-
- // Detect end of file upload of any file:
- if (aStateFlags & nsIWebProgressListener.STATE_STOP)
- {
- // ignore aStatus == kErrorBindingAborted; check http response for possible errors
- try {
- // check http channel for response: 200 range is ok; other ranges are not
- var httpChannel = aRequest.QueryInterface(Components.interfaces.nsIHttpChannel);
- var httpResponse = httpChannel.responseStatus;
- if (httpResponse < 200 || httpResponse >= 300)
- aStatus = httpResponse; // not a real error but enough to pass check below
- else if (aStatus == kErrorBindingAborted)
- aStatus = 0;
-
- if (gShowDebugOutputStateChange)
- dump("http response is: "+httpResponse+"\n");
- }
- catch(e)
- {
- if (aStatus == kErrorBindingAborted)
- aStatus = 0;
- }
-
- // We abort publishing for all errors except if image src file is not found
- var abortPublishing = (aStatus != 0 && aStatus != kFileNotFound);
-
- // Notify progress dialog when we receive the STOP
- // notification for a file if there was an error
- // or a successful finish
- // (Check requestSpec to be sure message is for destination url)
- if (aStatus != 0
- || (requestSpec && requestSpec.startsWith(GetScheme(gPublishData.publishUrl))))
- {
- try {
- gProgressDialog.SetProgressFinished(GetFilename(requestSpec), aStatus);
- } catch(e) {}
- }
-
-
- if (abortPublishing)
- {
- // Cancel publishing
- gPersistObj.cancelSave();
-
- // Don't do any commands after failure
- gCommandAfterPublishing = null;
-
- // Restore original document to undo image src url adjustments
- if (gRestoreDocumentSource)
- {
- try {
- editor.rebuildDocumentFromSource(gRestoreDocumentSource);
-
- // Clear transaction cache since we just did a potentially
- // very large insert and this will eat up memory
- editor.transactionManager.clear();
- }
- catch (e) {}
- }
-
- // Notify progress dialog that we're finished
- // and keep open to show error
- gProgressDialog.SetProgressFinished(null, 0);
-
- // We don't want to change location or reset mod count, etc.
- return;
- }
-
- //XXX HACK: "file://" protocol is not supported in network code
- // (bug 151867 filed to add this support, bug 151869 filed
- // to remove this and other code in nsIWebBrowserPersist)
- // nsIWebBrowserPersist *does* copy the file(s), but we don't
- // get normal onStateChange messages.
-
- // Case 1: If images are included, we get fairly normal
- // STATE_START/STATE_STOP & STATE_IS_NETWORK messages associated with the image files,
- // thus we must finish HTML file progress below
-
- // Case 2: If just HTML file is uploaded, we get STATE_START and STATE_STOP
- // notification with a null "requestSpec", and
- // the gPersistObj is destroyed before we get here!
- // So create an new object so we can flow through normal processing below
- if (!requestSpec && GetScheme(gPublishData.publishUrl) == "file"
- && (!gPersistObj || gPersistObj.currentState == nsIWebBrowserPersist.PERSIST_STATE_FINISHED))
- {
- aStateFlags |= nsIWebProgressListener.STATE_IS_NETWORK;
- if (!gPersistObj)
- {
- gPersistObj =
- {
- result : aStatus,
- currentState : nsIWebBrowserPersist.PERSIST_STATE_FINISHED
- }
- }
- }
-
- // STATE_IS_NETWORK signals end of publishing, as does the gPersistObj.currentState
- if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK
- && gPersistObj.currentState == nsIWebBrowserPersist.PERSIST_STATE_FINISHED)
- {
- if (GetScheme(gPublishData.publishUrl) == "file")
- {
- //XXX "file://" hack: We don't get notified about the HTML file, so end progress for it
- // (This covers both "Case 1 and 2" described above)
- gProgressDialog.SetProgressFinished(gPublishData.filename, gPersistObj.result);
- }
-
- if (gPersistObj.result == 0)
- {
- // All files are finished and publishing succeeded (some images may have failed)
- try {
- // Make a new docURI from the "browse location" in case "publish location" was FTP
- // We need to set document uri before notifying listeners
- var docUrl = GetDocUrlFromPublishData(gPublishData);
- SetDocumentURI(Services.io.newURI(docUrl, editor.documentCharacterSet, null));
-
- UpdateWindowTitle();
-
- // this should cause notification to listeners that doc has changed
- editor.resetModificationCount();
-
- // Set UI based on whether we're editing a remote or local url
- SetSaveAndPublishUI(urlstring);
-
- } catch (e) {}
-
- // Save publishData to prefs
- if (gPublishData)
- {
- if (gPublishData.savePublishData)
- {
- // We published successfully, so we can safely
- // save docDir and otherDir to prefs
- gPublishData.saveDirs = true;
- SavePublishDataToPrefs(gPublishData);
- }
- else
- SavePassword(gPublishData);
- }
-
- // Ask progress dialog to close, but it may not
- // if user checked checkbox to keep it open
- gProgressDialog.RequestCloseDialog();
- }
- else
- {
- // We previously aborted publishing because of error:
- // Calling gPersistObj.cancelSave() resulted in a non-zero gPersistObj.result,
- // so notify progress dialog we're finished
- gProgressDialog.SetProgressFinished(null, 0);
- }
- }
- }
- },
-
- onProgressChange : function(aWebProgress, aRequest, aCurSelfProgress,
- aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress)
- {
- if (!gPersistObj)
- return;
-
- if (gShowDebugOutputProgress)
- {
- dump("\n onProgressChange: gPersistObj.result="+gPersistObj.result+"\n");
- try {
- var channel = aRequest.QueryInterface(nsIChannel);
- dump("***** onProgressChange request: " + channel.URI.spec + "\n");
- }
- catch (e) {}
- dump("***** self: "+aCurSelfProgress+" / "+aMaxSelfProgress+"\n");
- dump("***** total: "+aCurTotalProgress+" / "+aMaxTotalProgress+"\n\n");
-
- if (gPersistObj.currentState == gPersistObj.PERSIST_STATE_READY)
- dump(" Persister is ready to save data\n\n");
- else if (gPersistObj.currentState == gPersistObj.PERSIST_STATE_SAVING)
- dump(" Persister is saving data.\n\n");
- else if (gPersistObj.currentState == gPersistObj.PERSIST_STATE_FINISHED)
- dump(" PERSISTER HAS FINISHED SAVING DATA\n\n\n");
- }
- },
-
- onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags)
- {
- if (gShowDebugOutputLocationChange)
- {
- dump("***** onLocationChange: "+aLocation.spec+"\n");
- try {
- var channel = aRequest.QueryInterface(nsIChannel);
- dump("***** request: " + channel.URI.spec + "\n");
- }
- catch(e) {}
- }
- },
-
- onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
- {
- if (gShowDebugOutputStatusChange)
- {
- dump("***** onStatusChange: "+aMessage+"\n");
- try {
- var channel = aRequest.QueryInterface(nsIChannel);
- dump("***** request: " + channel.URI.spec + "\n");
- }
- catch (e) { dump(" couldn't get request\n"); }
-
- DumpDebugStatus(aStatus);
-
- if (gPersistObj)
- {
- if (gPersistObj.currentState == gPersistObj.PERSIST_STATE_READY)
- dump(" Persister is ready to save data\n\n");
- else if (gPersistObj.currentState == gPersistObj.PERSIST_STATE_SAVING)
- dump(" Persister is saving data.\n\n");
- else if (gPersistObj.currentState == gPersistObj.PERSIST_STATE_FINISHED)
- dump(" PERSISTER HAS FINISHED SAVING DATA\n\n\n");
- }
- }
- },
-
- onSecurityChange : function(aWebProgress, aRequest, state)
- {
- if (gShowDebugOutputSecurityChange)
- {
- try {
- var channel = aRequest.QueryInterface(nsIChannel);
- dump("***** onSecurityChange request: " + channel.URI.spec + "\n");
- } catch (e) {}
- }
- },
-
- QueryInterface : function(aIID)
- {
- if (aIID.equals(Components.interfaces.nsIWebProgressListener)
- || aIID.equals(Components.interfaces.nsISupports)
- || aIID.equals(Components.interfaces.nsISupportsWeakReference)
- || aIID.equals(Components.interfaces.nsIPrompt)
- || aIID.equals(Components.interfaces.nsIAuthPrompt))
- return this;
- throw Components.results.NS_NOINTERFACE;
- },
-
-// nsIPrompt
- alert : function(dlgTitle, text)
- {
- Services.prompt.alert(gProgressDialog ? gProgressDialog : window, dlgTitle, text);
- },
- alertCheck : function(dialogTitle, text, checkBoxLabel, checkObj)
- {
- Services.prompt.alert(window, dialogTitle, text);
- },
- confirm : function(dlgTitle, text)
- {
- return ConfirmWithTitle(dlgTitle, text, null, null);
- },
- confirmCheck : function(dlgTitle, text, checkBoxLabel, checkObj)
- {
- Services.prompt.confirmEx(window, dlgTitle, text, nsIPromptService.STD_OK_CANCEL_BUTTONS,
- "", "", "", checkBoxLabel, checkObj);
- },
- confirmEx : function(dlgTitle, text, btnFlags, btn0Title, btn1Title, btn2Title, checkBoxLabel, checkVal)
- {
- return Services.prompt.confirmEx(window, dlgTitle, text, btnFlags,
- btn0Title, btn1Title, btn2Title,
- checkBoxLabel, checkVal);
- },
-
- /*************************************************************************
- * gEditorOutputProgressListener needs to implement both nsIPrompt *
- * (providing alert) and nsIAuthPrompt (providing password saving). *
- * Unfortunately, both interfaces specify prompt/promptPassword/ *
- * promptUsernameAndPassword, albeit with conflicting method signatures. *
- * Luckily, though, we only make use of their nsIAuthPrompt variants, *
- * hence we can comment out the nsIPrompt ones here to avoid JavaScript *
- * strict mode clutter. See bug 371174 for more information. *
- *************************************************************************
- prompt : function(dlgTitle, text, inoutText, checkBoxLabel, checkObj)
- {
- return Services.prompt.prompt(window, dlgTitle, text, inoutText, checkBoxLabel, checkObj);
- },
- promptPassword : function(dlgTitle, text, pwObj, checkBoxLabel, savePWObj)
- {
- var ret = false;
- try {
- // Note difference with nsIAuthPrompt::promptPassword, which has
- // just "in" savePassword param, while nsIPrompt is "inout"
- // Initialize with user's previous preference for this site
- if (gPublishData)
- savePWObj.value = gPublishData.savePassword;
-
- ret = Services.prompt.promptPassword(gProgressDialog ? gProgressDialog : window,
- dlgTitle, text, pwObj, checkBoxLabel, savePWObj);
-
- if (!ret)
- setTimeout(CancelPublishing, 0);
-
- if (ret && gPublishData)
- UpdateUsernamePasswordFromPrompt(gPublishData, gPublishData.username, pwObj.value, savePWObj.value);
- } catch(e) {}
-
- return ret;
- },
- promptUsernameAndPassword : function(dlgTitle, text, userObj, pwObj, checkBoxLabel, savePWObj)
- {
- var ret = PromptUsernameAndPassword(dlgTitle, text, savePWObj.value, userObj, pwObj);
- if (!ret)
- setTimeout(CancelPublishing, 0);
-
- return ret;
- },
- *************************************************************************/
-
- select : function(dlgTitle, text, count, selectList, outSelection)
- {
- return Services.prompt.select(window, dlgTitle, text, count, selectList, outSelection);
- },
-
-// nsIAuthPrompt
- prompt : function(dlgTitle, text, pwrealm, savePW, defaultText, result)
- {
- var ret = Services.prompt.prompt(gProgressDialog ? gProgressDialog : window,
- dlgTitle, text, defaultText, pwrealm, savePWObj);
- if (!ret)
- setTimeout(CancelPublishing, 0);
- return ret;
- },
-
- promptUsernameAndPassword : function(dlgTitle, text, pwrealm, savePW, userObj, pwObj)
- {
- var ret = PromptUsernameAndPassword(dlgTitle, text, savePW, userObj, pwObj);
- if (!ret)
- setTimeout(CancelPublishing, 0);
- return ret;
- },
-
- promptPassword : function(dlgTitle, text, pwrealm, savePW, pwObj)
- {
- var ret = false;
- try {
- // Note difference with nsIPrompt::promptPassword, which has
- // "inout" savePassword param, while nsIAuthPrompt is just "in"
- // Also nsIAuth doesn't supply "checkBoxLabel"
- // Initialize with user's previous preference for this site
- var savePWObj = {value:savePW};
- // Initialize with user's previous preference for this site
- if (gPublishData)
- savePWObj.value = gPublishData.savePassword;
-
- ret = Services.prompt.promptPassword(gProgressDialog ? gProgressDialog : window,
- dlgTitle, text, pwObj, GetString("SavePassword"), savePWObj);
-
- if (!ret)
- setTimeout(CancelPublishing, 0);
-
- if (ret && gPublishData)
- UpdateUsernamePasswordFromPrompt(gPublishData, gPublishData.username, pwObj.value, savePWObj.value);
- } catch(e) {}
-
- return ret;
- }
-}
-
-function PromptUsernameAndPassword(dlgTitle, text, savePW, userObj, pwObj)
-{
- // HTTP prompts us twice even if user Cancels from 1st attempt!
- // So never put up dialog if there's no publish data
- if (!gPublishData)
- return false
-
- var ret = false;
- try {
-
- var savePWObj = {value:savePW};
-
- // Initialize with user's previous preference for this site
- if (gPublishData)
- {
- // HTTP put uses this dialog if either username or password is bad,
- // so prefill username input field with the previous value for modification
- savePWObj.value = gPublishData.savePassword;
- if (!userObj.value)
- userObj.value = gPublishData.username;
- }
-
- ret = Services.prompt.promptUsernameAndPassword(gProgressDialog ? gProgressDialog : window,
- dlgTitle, text, userObj, pwObj,
- GetString("SavePassword"), savePWObj);
- if (ret && gPublishData)
- UpdateUsernamePasswordFromPrompt(gPublishData, userObj.value, pwObj.value, savePWObj.value);
-
- } catch (e) {}
-
- return ret;
-}
-
-function DumpDebugStatus(aStatus)
-{
- // see nsError.h and netCore.h and ftpCore.h
-
- if (aStatus == kErrorBindingAborted)
- dump("***** status is NS_BINDING_ABORTED\n");
- else if (aStatus == kErrorBindingRedirected)
- dump("***** status is NS_BINDING_REDIRECTED\n");
- else if (aStatus == 2152398859) // in netCore.h 11
- dump("***** status is ALREADY_CONNECTED\n");
- else if (aStatus == 2152398860) // in netCore.h 12
- dump("***** status is NOT_CONNECTED\n");
- else if (aStatus == 2152398861) // in nsISocketTransportService.idl 13
- dump("***** status is CONNECTION_REFUSED\n");
- else if (aStatus == 2152398862) // in nsISocketTransportService.idl 14
- dump("***** status is NET_TIMEOUT\n");
- else if (aStatus == 2152398863) // in netCore.h 15
- dump("***** status is IN_PROGRESS\n");
- else if (aStatus == 2152398864) // 0x804b0010 in netCore.h 16
- dump("***** status is OFFLINE\n");
- else if (aStatus == 2152398865) // in netCore.h 17
- dump("***** status is NO_CONTENT\n");
- else if (aStatus == 2152398866) // in netCore.h 18
- dump("***** status is UNKNOWN_PROTOCOL\n");
- else if (aStatus == 2152398867) // in netCore.h 19
- dump("***** status is PORT_ACCESS_NOT_ALLOWED\n");
- else if (aStatus == 2152398868) // in nsISocketTransportService.idl 20
- dump("***** status is NET_RESET\n");
- else if (aStatus == 2152398869) // in ftpCore.h 21
- dump("***** status is FTP_LOGIN\n");
- else if (aStatus == 2152398870) // in ftpCore.h 22
- dump("***** status is FTP_CWD\n");
- else if (aStatus == 2152398871) // in ftpCore.h 23
- dump("***** status is FTP_PASV\n");
- else if (aStatus == 2152398872) // in ftpCore.h 24
- dump("***** status is FTP_PWD\n");
- else if (aStatus == 2152857601)
- dump("***** status is UNRECOGNIZED_PATH\n");
- else if (aStatus == 2152857602)
- dump("***** status is UNRESOLABLE SYMLINK\n");
- else if (aStatus == 2152857604)
- dump("***** status is UNKNOWN_TYPE\n");
- else if (aStatus == 2152857605)
- dump("***** status is DESTINATION_NOT_DIR\n");
- else if (aStatus == 2152857606)
- dump("***** status is TARGET_DOES_NOT_EXIST\n");
- else if (aStatus == 2152857608)
- dump("***** status is ALREADY_EXISTS\n");
- else if (aStatus == 2152857609)
- dump("***** status is INVALID_PATH\n");
- else if (aStatus == 2152857610)
- dump("***** status is DISK_FULL\n");
- else if (aStatus == 2152857612)
- dump("***** status is NOT_DIRECTORY\n");
- else if (aStatus == 2152857613)
- dump("***** status is IS_DIRECTORY\n");
- else if (aStatus == 2152857614)
- dump("***** status is IS_LOCKED\n");
- else if (aStatus == 2152857615)
- dump("***** status is TOO_BIG\n");
- else if (aStatus == 2152857616)
- dump("***** status is NO_DEVICE_SPACE\n");
- else if (aStatus == 2152857617)
- dump("***** status is NAME_TOO_LONG\n");
- else if (aStatus == 2152857618) // 80520012
- dump("***** status is FILE_NOT_FOUND\n");
- else if (aStatus == 2152857619)
- dump("***** status is READ_ONLY\n");
- else if (aStatus == 2152857620)
- dump("***** status is DIR_NOT_EMPTY\n");
- else if (aStatus == 2152857621)
- dump("***** status is ACCESS_DENIED\n");
- else if (aStatus == 2152398878)
- dump("***** status is ? (No connection or time out?)\n");
- else
- dump("***** status is " + aStatus + "\n");
-}
-
-// Update any data that the user supplied in a prompt dialog
-function UpdateUsernamePasswordFromPrompt(publishData, username, password, savePassword)
-{
- if (!publishData)
- return;
-
- // Set flag to save publish data after publishing if it changed in dialog
- // and the "SavePassword" checkbox was checked
- // or we already had site data for this site
- // (Thus we don't automatically create a site until user brings up Publish As dialog)
- publishData.savePublishData = (gPublishData.username != username || gPublishData.password != password)
- && (savePassword || !publishData.notInSiteData);
-
- publishData.username = username;
- publishData.password = password;
- publishData.savePassword = savePassword;
-}
-
-const kSupportedTextMimeTypes =
-[
- "text/plain",
- "text/css",
- "text/rdf",
- "text/xsl",
- "text/javascript",
- "text/ecmascript",
- "application/javascript",
- "application/ecmascript",
- "application/x-javascript",
- "text/xul",
- "application/vnd.mozilla.xul+xml"
-];
-
-function IsSupportedTextMimeType(aMimeType)
-{
- for (var i = 0; i < kSupportedTextMimeTypes.length; i++)
- {
- if (kSupportedTextMimeTypes[i] == aMimeType)
- return true;
- }
- return false;
-}
-
-// throws an error or returns true if user attempted save; false if user canceled save
-function SaveDocument(aSaveAs, aSaveCopy, aMimeType)
-{
- var editor = GetCurrentEditor();
- if (!aMimeType || aMimeType == "" || !editor)
- throw Components.results.NS_ERROR_NOT_INITIALIZED;
-
- var editorDoc = editor.document;
- if (!editorDoc)
- throw Components.results.NS_ERROR_NOT_INITIALIZED;
-
- // if we don't have the right editor type bail (we handle text and html)
- var editorType = GetCurrentEditorType();
- if (["text", "html", "htmlmail", "textmail"].indexOf(editorType) == -1)
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
-
- var saveAsTextFile = IsSupportedTextMimeType(aMimeType);
-
- // check if the file is to be saved is a format we don't understand; if so, bail
- if (aMimeType != kHTMLMimeType && aMimeType != kXHTMLMimeType && !saveAsTextFile)
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
-
- if (saveAsTextFile)
- aMimeType = "text/plain";
-
- var urlstring = GetDocumentUrl();
- var mustShowFileDialog = (aSaveAs || IsUrlAboutBlank(urlstring) || (urlstring == ""));
-
- // If editing a remote URL, force SaveAs dialog
- if (!mustShowFileDialog && GetScheme(urlstring) != "file")
- mustShowFileDialog = true;
-
- var replacing = !aSaveAs;
- var titleChanged = false;
- var doUpdateURI = false;
- var tempLocalFile = null;
-
- if (mustShowFileDialog)
- {
- try {
- // Prompt for title if we are saving to HTML
- if (!saveAsTextFile && (editorType == "html"))
- {
- var userContinuing = PromptAndSetTitleIfNone(); // not cancel
- if (!userContinuing)
- return false;
- }
-
- var dialogResult = PromptForSaveLocation(saveAsTextFile, editorType, aMimeType, urlstring);
- if (dialogResult.filepickerClick == nsIFilePicker.returnCancel)
- return false;
-
- replacing = (dialogResult.filepickerClick == nsIFilePicker.returnReplace);
- urlstring = dialogResult.resultingURIString;
- tempLocalFile = dialogResult.resultingLocalFile;
-
- // update the new URL for the webshell unless we are saving a copy
- if (!aSaveCopy)
- doUpdateURI = true;
- } catch (e) {
- Components.utils.reportError(e);
- return false;
- }
- } // mustShowFileDialog
-
- var success = true;
- try {
- // if somehow we didn't get a local file but we did get a uri,
- // attempt to create the localfile if it's a "file" url
- var docURI;
- if (!tempLocalFile)
- {
- docURI = Services.io.newURI(urlstring, editor.documentCharacterSet, null);
-
- if (docURI.schemeIs("file"))
- {
- var fileHandler = GetFileProtocolHandler();
- tempLocalFile = fileHandler.getFileFromURLSpec(urlstring).QueryInterface(Components.interfaces.nsILocalFile);
- }
- }
-
- // this is the location where the related files will go
- var relatedFilesDir = null;
-
- // Only change links or move files if pref is set
- // and we are saving to a new location
- if (Services.prefs.getBoolPref("editor.save_associated_files") && aSaveAs)
- {
- try {
- if (tempLocalFile)
- {
- // if we are saving to the same parent directory, don't set relatedFilesDir
- // grab old location, chop off file
- // grab new location, chop off file, compare
- var oldLocation = GetDocumentUrl();
- var oldLocationLastSlash = oldLocation.lastIndexOf("\/");
- if (oldLocationLastSlash != -1)
- oldLocation = oldLocation.slice(0, oldLocationLastSlash);
-
- var relatedFilesDirStr = urlstring;
- var newLocationLastSlash = relatedFilesDirStr.lastIndexOf("\/");
- if (newLocationLastSlash != -1)
- relatedFilesDirStr = relatedFilesDirStr.slice(0, newLocationLastSlash);
- if (oldLocation == relatedFilesDirStr || IsUrlAboutBlank(oldLocation))
- relatedFilesDir = null;
- else
- relatedFilesDir = tempLocalFile.parent;
- }
- else
- {
- var lastSlash = urlstring.lastIndexOf("\/");
- if (lastSlash != -1)
- {
- var relatedFilesDirString = urlstring.slice(0, lastSlash + 1); // include last slash
- relatedFilesDir = Services.io.newURI(relatedFilesDirString, editor.documentCharacterSet, null);
- }
- }
- } catch(e) { relatedFilesDir = null; }
- }
-
- let destinationLocation = tempLocalFile ? tempLocalFile : docURI;
-
- success = OutputFileWithPersistAPI(editorDoc, destinationLocation, relatedFilesDir, aMimeType);
- }
- catch (e)
- {
- success = false;
- }
-
- if (success)
- {
- try {
- if (doUpdateURI)
- {
- // If a local file, we must create a new uri from nsILocalFile
- if (tempLocalFile)
- docURI = GetFileProtocolHandler().newFileURI(tempLocalFile);
-
- // We need to set new document uri before notifying listeners
- SetDocumentURI(docURI);
- }
-
- // Update window title to show possibly different filename
- // This also covers problem that after undoing a title change,
- // window title loses the extra [filename] part that this adds
- UpdateWindowTitle();
-
- if (!aSaveCopy)
- editor.resetModificationCount();
- // this should cause notification to listeners that document has changed
-
- // Set UI based on whether we're editing a remote or local url
- SetSaveAndPublishUI(urlstring);
- } catch (e) {}
- }
- else
- {
- Services.prompt.alert(window, GetString("SaveDocument"), GetString("SaveFileFailed"));
- }
- return success;
-}
-
-function SetDocumentURI(uri)
-{
- try {
- // XXX WE'LL NEED TO GET "CURRENT" CONTENT FRAME ONCE MULTIPLE EDITORS ARE ALLOWED
- GetCurrentEditorElement().docShell.setCurrentURI(uri);
- } catch (e) { dump("SetDocumentURI:\n"+e +"\n"); }
-}
-
-
-//------------------------------- Publishing
-var gPublishData;
-var gProgressDialog;
-var gCommandAfterPublishing = null;
-var gRestoreDocumentSource;
-
-function Publish(publishData)
-{
- if (!publishData)
- return false;
-
- // Set data in global for username password requests
- // and to do "post saving" actions after monitoring nsIWebProgressListener messages
- // and we are sure file transfer was successful
- gPublishData = publishData;
-
- gPublishData.docURI = CreateURIFromPublishData(publishData, true);
- if (!gPublishData.docURI)
- {
- Services.prompt.alert(window, GetString("Publish"), GetString("PublishFailed"));
- return false;
- }
-
- if (gPublishData.publishOtherFiles)
- gPublishData.otherFilesURI = CreateURIFromPublishData(publishData, false);
- else
- gPublishData.otherFilesURI = null;
-
- if (gShowDebugOutputStateChange)
- {
- dump("\n *** publishData: PublishUrl="+publishData.publishUrl+", BrowseUrl="+publishData.browseUrl+
- ", Username="+publishData.username+", Dir="+publishData.docDir+
- ", Filename="+publishData.filename+"\n");
- dump(" * gPublishData.docURI.spec w/o pass="+StripPassword(gPublishData.docURI.spec)+", PublishOtherFiles="+gPublishData.publishOtherFiles+"\n");
- }
-
- // XXX Missing username will make FTP fail
- // and it won't call us for prompt dialog (bug 132320)
- // (It does prompt if just password is missing)
- // So we should do the prompt ourselves before trying to publish
- if (GetScheme(publishData.publishUrl) == "ftp" && !publishData.username)
- {
- var message = GetString("PromptFTPUsernamePassword").replace(/%host%/, GetHost(publishData.publishUrl));
- var savePWobj = {value:publishData.savePassword};
- var userObj = {value:publishData.username};
- var pwObj = {value:publishData.password};
- if (!PromptUsernameAndPassword(GetString("Prompt"), message, savePWobj, userObj, pwObj))
- return false; // User canceled out of dialog
-
- // Reset data in URI objects
- gPublishData.docURI.username = publishData.username;
- gPublishData.docURI.password = publishData.password;
-
- if (gPublishData.otherFilesURI)
- {
- gPublishData.otherFilesURI.username = publishData.username;
- gPublishData.otherFilesURI.password = publishData.password;
- }
- }
-
- try {
- // We launch dialog as a dependent
- // Don't allow editing document!
- SetDocumentEditable(false);
-
- // Start progress monitoring
- gProgressDialog =
- window.openDialog("chrome://editor/content/EditorPublishProgress.xul", "_blank",
- "chrome,dependent,titlebar", gPublishData, gPersistObj);
-
- } catch (e) {}
-
- // Network transfer is often too quick for the progress dialog to be initialized
- // and we can completely miss messages for quickly-terminated bad URLs,
- // so we can't call OutputFileWithPersistAPI right away.
- // StartPublishing() is called at the end of the dialog's onload method
- return true;
-}
-
-function StartPublishing()
-{
- var editor = GetCurrentEditor();
- if (editor && gPublishData && gPublishData.docURI && gProgressDialog)
- {
- gRestoreDocumentSource = null;
-
- // Save backup document since nsIWebBrowserPersist changes image src urls
- // but we only need to do this if publishing images and other related files
- if (gPublishData.otherFilesURI)
- {
- try {
- gRestoreDocumentSource =
- editor.outputToString(editor.contentsMIMEType, kOutputEncodeW3CEntities);
- } catch (e) {}
- }
-
- OutputFileWithPersistAPI(editor.document,
- gPublishData.docURI, gPublishData.otherFilesURI,
- editor.contentsMIMEType);
- return gPersistObj;
- }
- return null;
-}
-
-function CancelPublishing()
-{
- try {
- gPersistObj.cancelSave();
- gProgressDialog.SetProgressStatusCancel();
- } catch (e) {}
-
- // If canceling publishing do not do any commands after this
- gCommandAfterPublishing = null;
-
- if (gProgressDialog)
- {
- // Close Progress dialog
- // (this will call FinishPublishing())
- gProgressDialog.CloseDialog();
- }
- else
- FinishPublishing();
-}
-
-function FinishPublishing()
-{
- SetDocumentEditable(true);
- gProgressDialog = null;
- gPublishData = null;
- gRestoreDocumentSource = null;
-
- if (gCommandAfterPublishing)
- {
- // Be sure to null out the global now incase of trouble when executing command
- var command = gCommandAfterPublishing;
- gCommandAfterPublishing = null;
- goDoCommand(command);
- }
-}
-
-// Create a nsIURI object filled in with all required publishing info
-function CreateURIFromPublishData(publishData, doDocUri)
-{
- if (!publishData || !publishData.publishUrl)
- return null;
-
- var URI;
- try {
- var spec = publishData.publishUrl;
- if (doDocUri)
- spec += FormatDirForPublishing(publishData.docDir) + publishData.filename;
- else
- spec += FormatDirForPublishing(publishData.otherDir);
-
- URI = Services.io.newURI(spec, GetCurrentEditor().documentCharacterSet, null);
-
- if (publishData.username)
- URI.username = publishData.username;
- if (publishData.password)
- URI.password = publishData.password;
- }
- catch (e) {}
-
- return URI;
-}
-
-// Resolve the correct "http:" document URL when publishing via ftp
-function GetDocUrlFromPublishData(publishData)
-{
- if (!publishData || !publishData.filename || !publishData.publishUrl)
- return "";
-
- // If user was previously editing an "ftp" url, then keep that as the new scheme
- var url;
- var docScheme = GetScheme(GetDocumentUrl());
-
- // Always use the "HTTP" address if available
- // XXX Should we do some more validation here for bad urls???
- // Let's at least check for a scheme!
- if (!GetScheme(publishData.browseUrl))
- url = publishData.publishUrl;
- else
- url = publishData.browseUrl;
-
- url += FormatDirForPublishing(publishData.docDir) + publishData.filename;
-
- if (GetScheme(url) == "ftp")
- url = InsertUsernameIntoUrl(url, publishData.username);
-
- return url;
-}
-
-function SetSaveAndPublishUI(urlstring)
-{
- // Be sure enabled state of toolbar buttons are correct
- goUpdateCommand("cmd_save");
- goUpdateCommand("cmd_publish");
-}
-
-function SetDocumentEditable(isDocEditable)
-{
- var editor = GetCurrentEditor();
- if (editor && editor.document)
- {
- try {
- var flags = editor.flags;
- editor.flags = isDocEditable ?
- flags &= ~nsIPlaintextEditor.eEditorReadonlyMask :
- flags | nsIPlaintextEditor.eEditorReadonlyMask;
- } catch(e) {}
-
- // update all commands
- window.updateCommands("create");
- }
-}
-
-// ****** end of save / publish **********//
-
-//-----------------------------------------------------------------------------------
-var nsPublishSettingsCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- if (GetCurrentEditor())
- {
- // Launch Publish Settings dialog
-
- window.ok = window.openDialog("chrome://editor/content/EditorPublishSettings.xul","_blank", "chrome,close,titlebar,modal", "");
- return window.ok;
- }
- return false;
- }
-}
-
-//-----------------------------------------------------------------------------------
-var nsRevertCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() &&
- IsDocumentModified() &&
- !IsUrlAboutBlank(GetDocumentUrl()));
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- // Confirm with the user to abandon current changes
- // Put the page title in the message string
- let title = GetDocumentTitle();
- let msg = GetString("AbandonChanges").replace(/%title%/,title);
-
- let result = Services.prompt.confirmEx(window, GetString("RevertCaption"), msg,
- (Services.prompt.BUTTON_TITLE_REVERT * Services.prompt.BUTTON_POS_0) +
- (Services.prompt.BUTTON_TITLE_CANCEL * Services.prompt.BUTTON_POS_1),
- null, null, null, null, {value:0});
-
- // Reload page if first button (Revert) was pressed
- if (result == 0)
- {
- CancelHTMLSource();
- EditorLoadUrl(GetDocumentUrl());
- }
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsCloseCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return GetCurrentEditor() != null;
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- CloseWindow();
- }
-};
-
-function CloseWindow()
-{
- // Check to make sure document is saved. "true" means allow "Don't Save" button,
- // so user can choose to close without saving
- if (CheckAndSaveDocument("cmd_close", true))
- {
- if (window.InsertCharWindow)
- SwitchInsertCharToAnotherEditorOrClose();
-
- try {
- var basewin = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
- .getInterface(Components.interfaces.nsIWebNavigation)
- .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
- .treeOwner
- .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
- .getInterface(Components.interfaces.nsIBaseWindow);
- basewin.destroy();
- } catch (e) {}
- }
-}
-
-//-----------------------------------------------------------------------------------
-var nsOpenRemoteCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return true; // we can always do this
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- var params = { action: "2", url: "" };
- openDialog("chrome://communicator/content/openLocation.xul", "_blank", "chrome,modal,titlebar", params);
- var win = getTopWin();
- switch (params.action) {
- case "0": // current window
- win.focus();
- win.loadURI(params.url, null, null, true);
- break;
- case "1": // new window
- openDialog(getBrowserURL(), "_blank", "all,dialog=no", params.url, null,
- null, null, true);
- break;
- case "2": // edit
- editPage(params.url);
- break;
- case "3": // new tab
- win.focus();
- var browser = win.getBrowser();
- browser.selectedTab = browser.addTab(params.url, {allowThirdPartyFixup: true});
- break;
- case "4": // private
- openNewPrivateWith(params.url);
- break;
- default:
- break;
- }
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsPreviewCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() &&
- IsHTMLEditor() &&
- (DocumentHasBeenSaved() || IsDocumentModified()));
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- // Don't continue if user canceled during prompt for saving
- // DocumentHasBeenSaved will test if we have a URL and suppress "Don't Save" button if not
- if (!CheckAndSaveDocument("cmd_preview", DocumentHasBeenSaved()))
- return;
-
- // Check if we saved again just in case?
- if (DocumentHasBeenSaved())
- {
- let browser;
- try {
- // Find a browser with this URL
- let enumerator = Services.wm.getEnumerator("navigator:browser");
-
- var documentURI = GetDocumentUrl();
- while (enumerator.hasMoreElements())
- {
- browser = enumerator.getNext();
- if (browser && (documentURI == browser.getBrowser().currentURI.spec))
- break;
-
- browser = null;
- }
- }
- catch (ex) {}
-
- // If none found, open a new browser
- if (!browser)
- {
- browser = window.openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no", documentURI);
- }
- else
- {
- try {
- browser.BrowserReloadSkipCache();
- browser.focus();
- } catch (ex) {}
- }
- }
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsSendPageCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() &&
- (DocumentHasBeenSaved() || IsDocumentModified()));
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- // Don't continue if user canceled during prompt for saving
- // DocumentHasBeenSaved will test if we have a URL and suppress "Don't Save" button if not
- if (!CheckAndSaveDocument("cmd_editSendPage", DocumentHasBeenSaved()))
- return;
-
- // Check if we saved again just in case?
- if (DocumentHasBeenSaved())
- {
- // Launch Messenger Composer window with current page as contents
- try
- {
- openComposeWindow(GetDocumentUrl(), GetDocumentTitle());
- } catch (ex) { dump("Cannot Send Page: " + ex + "\n"); }
- }
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsPrintCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return true; // we can always do this
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- // In editor.js
- SetEditMode(gPreviousNonSourceDisplayMode);
- try {
- let browser = GetCurrentEditorElement();
- PrintUtils.printWindow(browser.outerWindowID, browser);
- } catch (e) {}
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsPrintPreviewCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return true; // we can always do this
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- // In editor.js
- SetEditMode(gPreviousNonSourceDisplayMode);
- try {
- PrintUtils.printPreview(PrintPreviewListener);
- } catch (e) {}
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsPrintSetupCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return true; // we can always do this
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- // In editor.js
- SetEditMode(gPreviousNonSourceDisplayMode);
- PrintUtils.showPageSetup();
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsFindReplaceCommand =
-{
- isCommandEnabled: function(aCommand, editorElement)
- {
- return editorElement.getEditor(editorElement.contentWindow) != null;
- },
-
- getCommandStateParams: function(aCommand, aParams, editorElement) {},
- doCommandParams: function(aCommand, aParams, editorElement) {},
-
- doCommand: function(aCommand, editorElement)
- {
- window.openDialog("chrome://editor/content/EdReplace.xul", "_blank",
- "chrome,modal,titlebar", editorElement);
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsFindCommand =
-{
- isCommandEnabled: function(aCommand, editorElement)
- {
- return editorElement.getEditor(editorElement.contentWindow) != null;
- },
-
- getCommandStateParams: function(aCommand, aParams, editorElement) {},
- doCommandParams: function(aCommand, aParams, editorElement) {},
-
- doCommand: function(aCommand, editorElement)
- {
- document.getElementById("FindToolbar").onFindCommand();
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsFindAgainCommand =
-{
- isCommandEnabled: function(aCommand, editorElement)
- {
- // we can only do this if the search pattern is non-empty. Not sure how
- // to get that from here
- return editorElement.getEditor(editorElement.contentWindow) != null;
- },
-
- getCommandStateParams: function(aCommand, aParams, editorElement) {},
- doCommandParams: function(aCommand, aParams, editorElement) {},
-
- doCommand: function(aCommand, editorElement)
- {
- let findPrev = (aCommand == "cmd_findPrev");
- document.getElementById("FindToolbar").onFindAgainCommand(findPrev);
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsRewrapCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && !IsInHTMLSourceMode() &&
- GetCurrentEditor() instanceof Components.interfaces.nsIEditorMailSupport);
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- GetCurrentEditor().QueryInterface(Components.interfaces.nsIEditorMailSupport).rewrap(false);
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsSpellingCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() &&
- !IsInHTMLSourceMode() && IsSpellCheckerInstalled());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- window.cancelSendMessage = false;
- try {
- var skipBlockQuotes = (window.document.documentElement.getAttribute("windowtype") == "msgcompose");
- window.openDialog("chrome://editor/content/EdSpellCheck.xul", "_blank",
- "dialog,close,titlebar,modal,resizable", false, skipBlockQuotes, true);
- }
- catch(ex) {}
- }
-};
-
-// Validate using http://validator.w3.org/file-upload.html
-var URL2Validate;
-var nsValidateCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return GetCurrentEditor() != null;
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- // If the document hasn't been modified,
- // then just validate the current url.
- if (IsDocumentModified() || IsHTMLSourceChanged())
- {
- if (!CheckAndSaveDocument("cmd_validate", false))
- return;
-
- // Check if we saved again just in case?
- if (!DocumentHasBeenSaved()) // user hit cancel?
- return;
- }
-
- URL2Validate = GetDocumentUrl();
- // See if it's a file:
- var ifile;
- try {
- var fileHandler = GetFileProtocolHandler();
- ifile = fileHandler.getFileFromURLSpec(URL2Validate);
- // nsIFile throws an exception if it's not a file url
- } catch (e) { ifile = null; }
- if (ifile)
- {
- URL2Validate = ifile.path;
- var vwin = window.open("http://validator.w3.org/file-upload.html",
- "EditorValidate");
- // Window loads asynchronously, so pass control to the load listener:
- vwin.addEventListener("load", this.validateFilePageLoaded, false);
- }
- else
- {
- var vwin2 = window.open("http://validator.w3.org/check?uri="
- + URL2Validate
- + "&doctype=Inline",
- "EditorValidate");
- // This does the validation, no need to wait for page loaded.
- }
- },
- validateFilePageLoaded: function(event)
- {
- event.target.forms[0].uploaded_file.value = URL2Validate;
- }
-};
-
-var nsCheckLinksCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- window.openDialog("chrome://editor/content/EdLinkChecker.xul","_blank", "chrome,close,titlebar,modal");
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsFormCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- window.openDialog("chrome://editor/content/EdFormProps.xul", "_blank", "chrome,close,titlebar,modal");
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsInputTagCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- window.openDialog("chrome://editor/content/EdInputProps.xul", "_blank", "chrome,close,titlebar,modal");
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsInputImageCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- window.openDialog("chrome://editor/content/EdInputImage.xul", "_blank", "chrome,close,titlebar,modal");
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsTextAreaCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- window.openDialog("chrome://editor/content/EdTextAreaProps.xul", "_blank", "chrome,close,titlebar,modal");
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsSelectCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- window.openDialog("chrome://editor/content/EdSelectProps.xul", "_blank", "chrome,close,titlebar,modal");
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsButtonCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- window.openDialog("chrome://editor/content/EdButtonProps.xul", "_blank", "chrome,close,titlebar,modal");
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsLabelCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- var tagName = "label";
- try {
- var editor = GetCurrentEditor();
- // Find selected label or if start/end of selection is in label
- var labelElement = editor.getSelectedElement(tagName);
- if (!labelElement)
- labelElement = editor.getElementOrParentByTagName(tagName, editor.selection.anchorNode);
- if (!labelElement)
- labelElement = editor.getElementOrParentByTagName(tagName, editor.selection.focusNode);
- if (labelElement) {
- // We only open the dialog for an existing label
- window.openDialog("chrome://editor/content/EdLabelProps.xul", "_blank", "chrome,close,titlebar,modal", labelElement);
- } else {
- EditorSetTextProperty(tagName, "", "");
- }
- } catch (e) {}
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsFieldSetCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- window.openDialog("chrome://editor/content/EdFieldSetProps.xul", "_blank", "chrome,close,titlebar,modal");
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsIsIndexCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- try {
- var editor = GetCurrentEditor();
- var isindexElement = editor.createElementWithDefaults("isindex");
- isindexElement.setAttribute("prompt", editor.outputToString("text/plain", kOutputSelectionOnly));
- editor.insertElementAtSelection(isindexElement, true);
- } catch (e) {}
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsImageCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- window.openDialog("chrome://editor/content/EdImageProps.xul","_blank", "chrome,close,titlebar,modal");
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsHLineCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- // Inserting an HLine is different in that we don't use properties dialog
- // unless we are editing an existing line's attributes
- // We get the last-used attributes from the prefs and insert immediately
-
- var tagName = "hr";
- var editor = GetCurrentEditor();
-
- var hLine;
- try {
- hLine = editor.getSelectedElement(tagName);
- } catch (e) {return;}
-
- if (hLine)
- {
- // We only open the dialog for an existing HRule
- window.openDialog("chrome://editor/content/EdHLineProps.xul", "_blank", "chrome,close,titlebar,modal");
- }
- else
- {
- try {
- hLine = editor.createElementWithDefaults(tagName);
-
- // We change the default attributes to those saved in the user prefs
- let align = Services.prefs.getIntPref("editor.hrule.align");
- if (align == 0)
- editor.setAttributeOrEquivalent(hLine, "align", "left", true);
- else if (align == 2)
- editor.setAttributeOrEquivalent(hLine, "align", "right", true);
-
- //Note: Default is center (don't write attribute)
-
- let width = Services.prefs.getIntPref("editor.hrule.width");
- if (Services.prefs.getBoolPref("editor.hrule.width_percent"))
- width = width +"%";
-
- editor.setAttributeOrEquivalent(hLine, "width", width, true);
-
- let height = Services.prefs.getIntPref("editor.hrule.height");
- editor.setAttributeOrEquivalent(hLine, "size", String(height), true);
-
- if (Services.prefs.getBoolPref("editor.hrule.shading"))
- hLine.removeAttribute("noshade");
- else
- hLine.setAttribute("noshade", "noshade");
-
- editor.insertElementAtSelection(hLine, true);
-
- } catch (e) {}
- }
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsLinkCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- // If selected element is an image, launch that dialog instead
- // since last tab panel handles link around an image
- var element = GetObjectForProperties();
- if (element && element.nodeName.toLowerCase() == "img")
- window.openDialog("chrome://editor/content/EdImageProps.xul","_blank", "chrome,close,titlebar,modal", null, true);
- else
- window.openDialog("chrome://editor/content/EdLinkProps.xul","_blank", "chrome,close,titlebar,modal");
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsAnchorCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- window.openDialog("chrome://editor/content/EdNamedAnchorProps.xul", "_blank", "chrome,close,titlebar,modal", "");
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsInsertHTMLWithDialogCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- window.openDialog("chrome://editor/content/EdInsSrc.xul","_blank", "chrome,close,titlebar,modal,resizable", "");
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsInsertMathWithDialogCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- window.openDialog("chrome://editor/content/EdInsertMath.xul", "_blank", "chrome,close,titlebar,modal,resizable", "");
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsInsertCharsCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- EditorFindOrCreateInsertCharWindow();
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsInsertBreakCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- try {
- GetCurrentEditor().insertHTML("<br>");
- } catch (e) {}
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsInsertBreakAllCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- try {
- GetCurrentEditor().insertHTML("<br clear='all'>");
- } catch (e) {}
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsGridCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- window.openDialog("chrome://editor/content/EdSnapToGrid.xul","_blank", "chrome,close,titlebar,modal");
- }
-};
-
-
-//-----------------------------------------------------------------------------------
-var nsListPropertiesCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- window.openDialog("chrome://editor/content/EdListProps.xul","_blank", "chrome,close,titlebar,modal");
- }
-};
-
-
-//-----------------------------------------------------------------------------------
-var nsPagePropertiesCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- var oldTitle = GetDocumentTitle();
- window.openDialog("chrome://editor/content/EdPageProps.xul","_blank", "chrome,close,titlebar,modal", "");
-
- // Update main window title and
- // recent menu data in prefs if doc title changed
- if (GetDocumentTitle() != oldTitle)
- UpdateWindowTitle();
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsObjectPropertiesCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- var isEnabled = false;
- if (IsDocumentEditable() && IsEditingRenderedHTML())
- {
- isEnabled = (GetObjectForProperties() != null ||
- GetCurrentEditor().getSelectedElement("href") != null);
- }
- return isEnabled;
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- // Launch Object properties for appropriate selected element
- var element = GetObjectForProperties();
- if (element)
- {
- var name = element.nodeName.toLowerCase();
- switch (name)
- {
- case 'img':
- goDoCommand("cmd_image");
- break;
- case 'hr':
- goDoCommand("cmd_hline");
- break;
- case 'form':
- goDoCommand("cmd_form");
- break;
- case 'input':
- var type = element.getAttribute("type");
- if (type && type.toLowerCase() == "image")
- goDoCommand("cmd_inputimage");
- else
- goDoCommand("cmd_inputtag");
- break;
- case 'textarea':
- goDoCommand("cmd_textarea");
- break;
- case 'select':
- goDoCommand("cmd_select");
- break;
- case 'button':
- goDoCommand("cmd_button");
- break;
- case 'label':
- goDoCommand("cmd_label");
- break;
- case 'fieldset':
- goDoCommand("cmd_fieldset");
- break;
- case 'table':
- EditorInsertOrEditTable(false);
- break;
- case 'td':
- case 'th':
- EditorTableCellProperties();
- break;
- case 'ol':
- case 'ul':
- case 'dl':
- case 'li':
- goDoCommand("cmd_listProperties");
- break;
- case 'a':
- if (element.name)
- {
- goDoCommand("cmd_anchor");
- }
- else if (element.href)
- {
- goDoCommand("cmd_link");
- }
- break;
- case 'math':
- goDoCommand("cmd_insertMathWithDialog");
- break;
- default:
- doAdvancedProperties(element);
- break;
- }
- } else {
- // We get a partially-selected link if asked for specifically
- try {
- element = GetCurrentEditor().getSelectedElement("href");
- } catch (e) {}
- if (element)
- goDoCommand("cmd_link");
- }
- }
-};
-
-
-//-----------------------------------------------------------------------------------
-var nsSetSmiley =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon)
- {
- var smileyCode = aParams.getStringValue("state_attribute");
-
- var strSml;
- switch(smileyCode)
- {
- case ":-)": strSml="s1";
- break;
- case ":-(": strSml="s2";
- break;
- case ";-)": strSml="s3";
- break;
- case ":-P":
- case ":-p":
- case ":-b": strSml="s4";
- break;
- case ":-D": strSml="s5";
- break;
- case ":-[": strSml="s6";
- break;
- case ":-/":
- case ":/":
- case ":-\\":
- case ":\\": strSml="s7";
- break;
- case "=-O":
- case "=-o": strSml="s8";
- break;
- case ":-*": strSml="s9";
- break;
- case ">:o":
- case ">:-o": strSml="s10";
- break;
- case "8-)": strSml="s11";
- break;
- case ":-$": strSml="s12";
- break;
- case ":-!": strSml="s13";
- break;
- case "O:-)":
- case "o:-)": strSml="s14";
- break;
- case ":'(": strSml="s15";
- break;
- case ":-X":
- case ":-x": strSml="s16";
- break;
- default: strSml="";
- break;
- }
-
- try
- {
- var editor = GetCurrentEditor();
- var selection = editor.selection;
- var extElement = editor.createElementWithDefaults("span");
- extElement.setAttribute("class", "moz-smiley-" + strSml);
-
- var intElement = editor.createElementWithDefaults("span");
- if (!intElement)
- return;
-
- var txtElement = editor.document.createTextNode(smileyCode);
- if (!txtElement)
- return;
-
- intElement.appendChild (txtElement);
- extElement.appendChild (intElement);
-
-
- editor.insertElementAtSelection(extElement,true);
- window.content.focus();
-
- }
- catch (e)
- {
- dump("Exception occured in smiley InsertElementAtSelection\n");
- }
- },
- // This is now deprecated in favor of "doCommandParams"
- doCommand: function(aCommand) {}
-};
-
-
-function doAdvancedProperties(element)
-{
- if (element)
- {
- window.openDialog("chrome://editor/content/EdAdvancedEdit.xul", "_blank", "chrome,close,titlebar,modal,resizable=yes", "", element);
- }
-}
-
-var nsAdvancedPropertiesCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- // Launch AdvancedEdit dialog for the selected element
- try {
- var element = GetCurrentEditor().getSelectedElement("");
- doAdvancedProperties(element);
- } catch (e) {}
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsColorPropertiesCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- window.openDialog("chrome://editor/content/EdColorProps.xul","_blank", "chrome,close,titlebar,modal", "");
- UpdateDefaultColors();
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsIncreaseFontCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- if (!(IsDocumentEditable() && IsEditingRenderedHTML()))
- return false;
- var setIndex = getFontSizeIndex();
- return (setIndex >= 0 && setIndex < 5);
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- var setIndex = getFontSizeIndex();
- if (setIndex < 0 || setIndex >= 5)
- return;
- var sizes = ['x-small', 'small', 'medium', 'large', 'x-large', 'xx-large' ];
- EditorSetFontSize(sizes[setIndex+1]);
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsDecreaseFontCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- if (!(IsDocumentEditable() && IsEditingRenderedHTML()))
- return false;
- var setIndex = getFontSizeIndex();
- return (setIndex > 0);
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- var setIndex = getFontSizeIndex();
- if (setIndex <= 0)
- return;
- var sizes = ['x-small', 'small', 'medium', 'large', 'x-large', 'xx-large' ];
- EditorSetFontSize(sizes[setIndex-1]);
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsRemoveNamedAnchorsCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- // We could see if there's any link in selection, but it doesn't seem worth the work!
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- EditorRemoveTextProperty("name", "");
- window.content.focus();
- }
-};
-
-
-//-----------------------------------------------------------------------------------
-var nsEditLinkCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- // Not really used -- this command is only in context menu, and we do enabling there
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- try {
- var element = GetCurrentEditor().getSelectedElement("href");
- if (element)
- editPage(element.href);
- } catch (e) {}
- window.content.focus();
- }
-};
-
-
-//-----------------------------------------------------------------------------------
-var nsNormalModeCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsHTMLEditor() && IsDocumentEditable();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- SetEditMode(kDisplayModeNormal);
- }
-};
-
-var nsAllTagsModeCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsHTMLEditor());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- SetEditMode(kDisplayModeAllTags);
- }
-};
-
-var nsHTMLSourceModeCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsHTMLEditor());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- SetEditMode(kDisplayModeSource);
- }
-};
-
-var nsPreviewModeCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsHTMLEditor());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- SetEditMode(kDisplayModePreview);
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsInsertOrEditTableCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return (IsDocumentEditable() && IsEditingRenderedHTML());
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- if (IsInTableCell())
- EditorTableCellProperties();
- else
- EditorInsertOrEditTable(true);
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsEditTableCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsInTable();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- EditorInsertOrEditTable(false);
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsSelectTableCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsInTable();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- try {
- GetCurrentTableEditor().selectTable();
- } catch(e) {}
- window.content.focus();
- }
-};
-
-var nsSelectTableRowCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsInTableCell();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- try {
- GetCurrentTableEditor().selectTableRow();
- } catch(e) {}
- window.content.focus();
- }
-};
-
-var nsSelectTableColumnCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsInTableCell();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- try {
- GetCurrentTableEditor().selectTableColumn();
- } catch(e) {}
- window.content.focus();
- }
-};
-
-var nsSelectTableCellCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsInTableCell();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- try {
- GetCurrentTableEditor().selectTableCell();
- } catch(e) {}
- window.content.focus();
- }
-};
-
-var nsSelectAllTableCellsCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsInTable();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- try {
- GetCurrentTableEditor().selectAllTableCells();
- } catch(e) {}
- window.content.focus();
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsInsertTableCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsDocumentEditable() && IsEditingRenderedHTML();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- EditorInsertTable();
- }
-};
-
-var nsInsertTableRowAboveCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsInTableCell();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- try {
- GetCurrentTableEditor().insertTableRow(1, false);
- } catch(e) {}
- window.content.focus();
- }
-};
-
-var nsInsertTableRowBelowCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsInTableCell();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- try {
- GetCurrentTableEditor().insertTableRow(1, true);
- } catch(e) {}
- window.content.focus();
- }
-};
-
-var nsInsertTableColumnBeforeCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsInTableCell();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- try {
- GetCurrentTableEditor().insertTableColumn(1, false);
- } catch(e) {}
- window.content.focus();
- }
-};
-
-var nsInsertTableColumnAfterCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsInTableCell();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- try {
- GetCurrentTableEditor().insertTableColumn(1, true);
- } catch(e) {}
- window.content.focus();
- }
-};
-
-var nsInsertTableCellBeforeCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsInTableCell();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- try {
- GetCurrentTableEditor().insertTableCell(1, false);
- } catch(e) {}
- window.content.focus();
- }
-};
-
-var nsInsertTableCellAfterCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsInTableCell();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- try {
- GetCurrentTableEditor().insertTableCell(1, true);
- } catch(e) {}
- window.content.focus();
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsDeleteTableCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsInTable();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- try {
- GetCurrentTableEditor().deleteTable();
- } catch(e) {}
- window.content.focus();
- }
-};
-
-var nsDeleteTableRowCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsInTableCell();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- var rows = GetNumberOfContiguousSelectedRows();
- // Delete at least one row
- if (rows == 0)
- rows = 1;
-
- try {
- var editor = GetCurrentTableEditor();
- editor.beginTransaction();
-
- // Loop to delete all blocks of contiguous, selected rows
- while (rows)
- {
- editor.deleteTableRow(rows);
- rows = GetNumberOfContiguousSelectedRows();
- }
- } finally { editor.endTransaction(); }
- window.content.focus();
- }
-};
-
-var nsDeleteTableColumnCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsInTableCell();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- var columns = GetNumberOfContiguousSelectedColumns();
- // Delete at least one column
- if (columns == 0)
- columns = 1;
-
- try {
- var editor = GetCurrentTableEditor();
- editor.beginTransaction();
-
- // Loop to delete all blocks of contiguous, selected columns
- while (columns)
- {
- editor.deleteTableColumn(columns);
- columns = GetNumberOfContiguousSelectedColumns();
- }
- } finally { editor.endTransaction(); }
- window.content.focus();
- }
-};
-
-var nsDeleteTableCellCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsInTableCell();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- try {
- GetCurrentTableEditor().deleteTableCell(1);
- } catch (e) {}
- window.content.focus();
- }
-};
-
-var nsDeleteTableCellContentsCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsInTableCell();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- try {
- GetCurrentTableEditor().deleteTableCellContents();
- } catch (e) {}
- window.content.focus();
- }
-};
-
-
-//-----------------------------------------------------------------------------------
-var nsNormalizeTableCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsInTable();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- // Use nullptr to let editor find table enclosing current selection
- try {
- GetCurrentTableEditor().normalizeTable(null);
- } catch (e) {}
- window.content.focus();
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsJoinTableCellsCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- if (IsDocumentEditable() && IsEditingRenderedHTML())
- {
- try {
- var editor = GetCurrentTableEditor();
- var tagNameObj = { value: "" };
- var countObj = { value: 0 };
- var cell = editor.getSelectedOrParentTableElement(tagNameObj, countObj);
-
- // We need a cell and either > 1 selected cell or a cell to the right
- // (this cell may originate in a row spanned from above current row)
- // Note that editor returns "td" for "th" also.
- // (this is a pain! Editor and gecko use lowercase tagNames, JS uses uppercase!)
- if (cell && (tagNameObj.value == "td"))
- {
- // Selected cells
- if (countObj.value > 1) return true;
-
- var colSpan = cell.getAttribute("colspan");
-
- // getAttribute returns string, we need number
- // no attribute means colspan = 1
- if (!colSpan)
- colSpan = Number(1);
- else
- colSpan = Number(colSpan);
-
- var rowObj = { value: 0 };
- var colObj = { value: 0 };
- editor.getCellIndexes(cell, rowObj, colObj);
-
- // Test if cell exists to the right of current cell
- // (cells with 0 span should never have cells to the right
- // if there is, user can select the 2 cells to join them)
- return (colSpan && editor.getCellAt(null, rowObj.value,
- colObj.value + colSpan));
- }
- } catch (e) {}
- }
- return false;
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- // Param: Don't merge non-contiguous cells
- try {
- GetCurrentTableEditor().joinTableCells(false);
- } catch (e) {}
- window.content.focus();
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsSplitTableCellCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- if (IsDocumentEditable() && IsEditingRenderedHTML())
- {
- var tagNameObj = { value: "" };
- var countObj = { value: 0 };
- var cell;
- try {
- cell = GetCurrentTableEditor().getSelectedOrParentTableElement(tagNameObj, countObj);
- } catch (e) {}
-
- // We need a cell parent and there's just 1 selected cell
- // or selection is entirely inside 1 cell
- if ( cell && (tagNameObj.value == "td") &&
- countObj.value <= 1 &&
- IsSelectionInOneCell() )
- {
- var colSpan = cell.getAttribute("colspan");
- var rowSpan = cell.getAttribute("rowspan");
- if (!colSpan) colSpan = 1;
- if (!rowSpan) rowSpan = 1;
- return (colSpan > 1 || rowSpan > 1 ||
- colSpan == 0 || rowSpan == 0);
- }
- }
- return false;
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- try {
- GetCurrentTableEditor().splitTableCell();
- } catch (e) {}
- window.content.focus();
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsTableOrCellColorCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return IsInTable();
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- EditorSelectColor("TableOrCell");
- }
-};
-
-//-----------------------------------------------------------------------------------
-var nsPreferencesCommand =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return true;
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- goPreferences('composer_pane');
- }
-};
-
-
-var nsFinishHTMLSource =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return true;
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- // In editor.js
- SetEditMode(gPreviousNonSourceDisplayMode);
- }
-};
-
-var nsCancelHTMLSource =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- return true;
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- // In editor.js
- CancelHTMLSource();
- }
-};
-
-var nsConvertToTable =
-{
- isCommandEnabled: function(aCommand, dummy)
- {
- if (IsDocumentEditable() && IsEditingRenderedHTML())
- {
- var selection;
- try {
- selection = GetCurrentEditor().selection;
- } catch (e) {}
-
- if (selection && !selection.isCollapsed)
- {
- // Don't allow if table or cell is the selection
- var element;
- try {
- element = GetCurrentEditor().getSelectedElement("");
- } catch (e) {}
- if (element)
- {
- var name = element.nodeName.toLowerCase();
- if (name == "td" ||
- name == "th" ||
- name == "caption" ||
- name == "table")
- return false;
- }
-
- // Selection start and end must be in the same cell
- // in same cell or both are NOT in a cell
- if ( GetParentTableCell(selection.focusNode) !=
- GetParentTableCell(selection.anchorNode) )
- return false
-
- return true;
- }
- }
- return false;
- },
-
- getCommandStateParams: function(aCommand, aParams, aRefCon) {},
- doCommandParams: function(aCommand, aParams, aRefCon) {},
-
- doCommand: function(aCommand)
- {
- if (this.isCommandEnabled())
- {
- window.openDialog("chrome://editor/content/EdConvertToTable.xul","_blank", "chrome,close,titlebar,modal")
- }
- }
-};
-
diff --git a/editor/ui/composer/content/EditorContent.css b/editor/ui/composer/content/EditorContent.css
deleted file mode 100644
index 941b6ad03..000000000
--- a/editor/ui/composer/content/EditorContent.css
+++ /dev/null
@@ -1,62 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Styles to alter look of things in the Editor content window
- * for the "Normal Edit Mode" These settings will be removed
- * when we display in completely WYSIWYG "Edit Preview" mode
- * Anything that should never change, like cursors, should be
- * place in EditorOverride.css, instead of here.
-*/
-
-@import url(chrome://communicator/skin/smileys.css);
-
-a[name] {
- min-height: 17px; margin-left: 2px; margin-top: 2px;
- padding-left: 20px;
- background-image: url(chrome://editor/content/images/tag-anchor.gif);
- background-repeat: no-repeat;
- background-position: top left;
-}
-
-/* Force border display for empty cells
- and tables with 0 border
-*/
-table {
- empty-cells: show;
-}
-
-/* give a red dotted border to tables and cells with no border
- otherwise they are invisible
-*/
-table[empty-cells],
- table[border="0"],
- /* next two selectors on line below for the case where tbody is omitted */
- table[border="0"] > tr > td, table[border="0"] > tr > th,
- table[border="0"] > thead > tr > td, table[border="0"] > tbody > tr > td, table[border="0"] > tfoot > tr > td,
- table[border="0"] > thead > tr > th, table[border="0"] > tbody > tr > th, table[border="0"] > tfoot > tr > th,
- table:not([border]),
- /* next two selectors on line below for the case where tbody is omitted */
- table:not([border]) > tr > td, table:not([border]) > tr > th,
- table:not([border]) > thead > tr > td, table:not([border]) > tbody > tr > td, table:not([border]) > tfoot > tr > td,
- table:not([border]) > thead > tr > th, table:not([border]) > tbody > tr > th, table:not([border]) > tfoot > tr > th
-{
- border: 1px dotted red;
-}
-
-/* give a green dashed border to forms otherwise they are invisible
-*/
-form
-{
- border: 2px dashed green;
-}
-/* give a green dotted border to labels otherwise they are invisible
-*/
-label
-{
- border: 1px dotted green;
-}
-
-img {
- -moz-force-broken-image-icon: 1;
-}
diff --git a/editor/ui/composer/content/editor.js b/editor/ui/composer/content/editor.js
deleted file mode 100644
index 8209abdd6..000000000
--- a/editor/ui/composer/content/editor.js
+++ /dev/null
@@ -1,3226 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-Components.utils.import("resource:///modules/editorUtilities.jsm");
-Components.utils.import("resource://gre/modules/AppConstants.jsm");
-
-/* Main Composer window UI control */
-
-var gComposerWindowControllerID = 0;
-var prefAuthorString = "";
-
-var kDisplayModeNormal = 0;
-var kDisplayModeAllTags = 1;
-var kDisplayModeSource = 2;
-var kDisplayModePreview = 3;
-
-const kDisplayModeMenuIDs = ["viewNormalMode", "viewAllTagsMode", "viewSourceMode", "viewPreviewMode"];
-const kDisplayModeTabIDS = ["NormalModeButton", "TagModeButton", "SourceModeButton", "PreviewModeButton"];
-const kNormalStyleSheet = "chrome://editor/content/EditorContent.css";
-const kAllTagsStyleSheet = "chrome://editor/content/EditorAllTags.css";
-const kContentEditableStyleSheet = "resource://gre/res/contenteditable.css";
-
-var kTextMimeType = "text/plain";
-var kHTMLMimeType = "text/html";
-var kXHTMLMimeType = "application/xhtml+xml";
-
-var gPreviousNonSourceDisplayMode = 1;
-var gEditorDisplayMode = -1;
-var gDocWasModified = false; // Check if clean document, if clean then unload when user "Opens"
-var gContentWindow = 0;
-var gSourceContentWindow = 0;
-var gSourceTextEditor = null;
-var gContentWindowDeck;
-var gFormatToolbar;
-var gFormatToolbarHidden = false;
-var gViewFormatToolbar;
-var gChromeState;
-var gColorObj = { LastTextColor:"", LastBackgroundColor:"", LastHighlightColor:"",
- Type:"", SelectedType:"", NoDefault:false, Cancel:false,
- HighlightColor:"", BackgroundColor:"", PageColor:"",
- TextColor:"", TableColor:"", CellColor:""
- };
-var gDefaultTextColor = "";
-var gDefaultBackgroundColor = "";
-var gCSSPrefListener;
-var gEditorToolbarPrefListener;
-var gReturnInParagraphPrefListener;
-var gLocalFonts = null;
-
-var gLastFocusNode = null;
-var gLastFocusNodeWasSelected = false;
-
-// These must be kept in synch with the XUL <options> lists
-var gFontSizeNames = ["xx-small","x-small","small","medium","large","x-large","xx-large"];
-
-var nsIFilePicker = Components.interfaces.nsIFilePicker;
-
-var kEditorToolbarPrefs = "editor.toolbars.showbutton.";
-var kUseCssPref = "editor.use_css";
-var kCRInParagraphsPref = "editor.CR_creates_new_p";
-
-function ShowHideToolbarSeparators(toolbar) {
- // Make sure the toolbar actually exists.
- if (!toolbar)
- return;
- var childNodes = toolbar.childNodes;
- var separator = null;
- var hideSeparator = true;
- for (var i = 0; childNodes[i].localName != "spacer"; i++) {
- if (childNodes[i].localName == "toolbarseparator") {
- if (separator)
- separator.hidden = true;
- separator = childNodes[i];
- } else if (!childNodes[i].hidden) {
- if (separator)
- separator.hidden = hideSeparator;
- separator = null;
- hideSeparator = false;
- }
- }
-}
-
-function ShowHideToolbarButtons()
-{
- let array = Services.prefs.getChildList(kEditorToolbarPrefs);
- for (let i in array) {
- let prefName = array[i];
- let id = prefName.substr(kEditorToolbarPrefs.length);
- let button = document.getElementById(id + "Button") ||
- document.getElementById(id + "-button");
- if (button)
- button.hidden = !Services.prefs.getBoolPref(prefName);
- }
- ShowHideToolbarSeparators(document.getElementById("EditToolbar"));
- ShowHideToolbarSeparators(document.getElementById("FormatToolbar"));
-}
-
-function nsPrefListener(prefName)
-{
- this.startup(prefName);
-}
-
-// implements nsIObserver
-nsPrefListener.prototype =
-{
- domain: "",
- startup: function(prefName)
- {
- this.domain = prefName;
- try {
- Services.prefs.addObserver(this.domain, this, false);
- } catch(ex) {
- dump("Failed to observe prefs: " + ex + "\n");
- }
- },
- shutdown: function()
- {
- try {
- Services.prefs.removeObserver(this.domain, this);
- } catch(ex) {
- dump("Failed to remove pref observers: " + ex + "\n");
- }
- },
- observe: function(subject, topic, prefName)
- {
- if (!IsHTMLEditor())
- return;
- // verify that we're changing a button pref
- if (topic != "nsPref:changed")
- return;
-
- let editor = GetCurrentEditor();
- if (prefName == kUseCssPref)
- {
- let cmd = document.getElementById("cmd_highlight");
- if (cmd) {
- let useCSS = Services.prefs.getBoolPref(prefName);
-
- if (useCSS && editor) {
- let mixedObj = {};
- let state = editor.getHighlightColorState(mixedObj);
- cmd.setAttribute("state", state);
- cmd.collapsed = false;
- }
- else {
- cmd.setAttribute("state", "transparent");
- cmd.collapsed = true;
- }
-
- if (editor)
- editor.isCSSEnabled = useCSS;
- }
- }
- else if (prefName.startsWith(kEditorToolbarPrefs))
- {
- let id = prefName.substr(kEditorToolbarPrefs.length) + "Button";
- let button = document.getElementById(id);
- if (button) {
- button.hidden = !Services.prefs.getBoolPref(prefName);
- ShowHideToolbarSeparators(button.parentNode);
- }
- }
- else if (editor && (prefName == kCRInParagraphsPref))
- editor.returnInParagraphCreatesNewParagraph = Services.prefs.getBoolPref(prefName);
- }
-}
-
-const gSourceTextListener =
-{
- NotifyDocumentCreated: function NotifyDocumentCreated() {},
- NotifyDocumentWillBeDestroyed: function NotifyDocumentWillBeDestroyed() {},
- NotifyDocumentStateChanged: function NotifyDocumentStateChanged(isChanged)
- {
- window.updateCommands("save");
- }
-};
-
-const gSourceTextObserver =
-{
- observe: function observe(aSubject, aTopic, aData)
- {
- // we currently only use this to update undo
- window.updateCommands("undo");
- }
-};
-
-// This should be called by all editor users when they close their window.
-function EditorCleanup()
-{
- SwitchInsertCharToAnotherEditorOrClose();
-}
-
-var DocumentReloadListener =
-{
- NotifyDocumentCreated: function() {},
- NotifyDocumentWillBeDestroyed: function() {},
-
- NotifyDocumentStateChanged:function( isNowDirty )
- {
- var editor = GetCurrentEditor();
- try {
- // unregister the listener to prevent multiple callbacks
- editor.removeDocumentStateListener( DocumentReloadListener );
-
- var charset = editor.documentCharacterSet;
-
- // update the META charset with the current presentation charset
- editor.documentCharacterSet = charset;
-
- } catch (e) {}
- }
-};
-
-// implements nsIObserver
-var gEditorDocumentObserver =
-{
- observe: function(aSubject, aTopic, aData)
- {
- // Should we allow this even if NOT the focused editor?
- var commandManager = GetCurrentCommandManager();
- if (commandManager != aSubject)
- return;
-
- var editor = GetCurrentEditor();
- switch(aTopic)
- {
- case "obs_documentCreated":
- // Just for convenience
- gContentWindow = window.content;
-
- // Get state to see if document creation succeeded
- var params = newCommandParams();
- if (!params)
- return;
-
- try {
- commandManager.getCommandState(aTopic, gContentWindow, params);
- var errorStringId = 0;
- var editorStatus = params.getLongValue("state_data");
- if (!editor && editorStatus == nsIEditingSession.eEditorOK)
- {
- dump("\n ****** NO EDITOR BUT NO EDITOR ERROR REPORTED ******* \n\n");
- editorStatus = nsIEditingSession.eEditorErrorUnknown;
- }
-
- switch (editorStatus)
- {
- case nsIEditingSession.eEditorErrorCantEditFramesets:
- errorStringId = "CantEditFramesetMsg";
- break;
- case nsIEditingSession.eEditorErrorCantEditMimeType:
- errorStringId = "CantEditMimeTypeMsg";
- break;
- case nsIEditingSession.eEditorErrorUnknown:
- errorStringId = "CantEditDocumentMsg";
- break;
- // Note that for "eEditorErrorFileNotFound,
- // network code popped up an alert dialog, so we don't need to
- }
- if (errorStringId)
- Services.prompt.alert(window, "", GetString(errorStringId));
- } catch(e) { dump("EXCEPTION GETTING obs_documentCreated state "+e+"\n"); }
-
- // We have a bad editor -- nsIEditingSession will rebuild an editor
- // with a blank page, so simply abort here
- if (editorStatus)
- return;
-
- if (!("InsertCharWindow" in window))
- window.InsertCharWindow = null;
-
- try {
- editor.QueryInterface(nsIEditorStyleSheets);
-
- // and extra styles for showing anchors, table borders, smileys, etc
- editor.addOverrideStyleSheet(kNormalStyleSheet);
-
- // remove contenteditable stylesheets if they were applied by the
- // editingSession
- editor.removeOverrideStyleSheet(kContentEditableStyleSheet);
- } catch (e) {}
-
- // Things for just the Web Composer application
- if (IsWebComposer())
- {
- InlineSpellCheckerUI.init(editor);
- document.getElementById('menu_inlineSpellCheck').setAttribute('disabled', !InlineSpellCheckerUI.canSpellCheck);
-
- editor.returnInParagraphCreatesNewParagraph = Services.prefs.getBoolPref(kCRInParagraphsPref);
-
- // Set focus to content window if not a mail composer
- // Race conditions prevent us from setting focus here
- // when loading a url into blank window
- setTimeout(SetFocusOnStartup, 0);
-
- // Call EditorSetDefaultPrefsAndDoctype first so it gets the default author before initing toolbars
- editor.enableUndo(false);
- EditorSetDefaultPrefsAndDoctype();
- editor.resetModificationCount();
- editor.enableUndo(true);
-
- // We may load a text document into an html editor,
- // so be sure editortype is set correctly
- // XXX We really should use the "real" plaintext editor for this!
- if (editor.contentsMIMEType == "text/plain")
- {
- try {
- GetCurrentEditorElement().editortype = "text";
- } catch (e) { dump (e)+"\n"; }
-
- // Hide or disable UI not used for plaintext editing
- HideItem("FormatToolbar");
- HideItem("EditModeToolbar");
- HideItem("formatMenu");
- HideItem("tableMenu");
- HideItem("menu_validate");
- HideItem("sep_validate");
- HideItem("previewButton");
- HideItem("imageButton");
- HideItem("linkButton");
- HideItem("namedAnchorButton");
- HideItem("hlineButton");
- HideItem("tableButton");
-
- HideItem("fileExportToText");
- HideItem("previewInBrowser");
-
-/* XXX When paste actually converts formatted rich text to pretty formatted plain text
- and pasteNoFormatting is fixed to paste the text without formatting (what paste
- currently does), then this item shouldn't be hidden: */
- HideItem("menu_pasteNoFormatting");
-
- HideItem("cmd_viewFormatToolbar");
- HideItem("cmd_viewEditModeToolbar");
-
- HideItem("viewSep1");
- HideItem("viewNormalMode");
- HideItem("viewAllTagsMode");
- HideItem("viewSourceMode");
- HideItem("viewPreviewMode");
-
- HideItem("structSpacer");
-
- // Hide everything in "Insert" except for "Symbols"
- let menuPopupChildren = document.querySelectorAll('[id="insertMenuPopup"] > :not(#insertChars)');
- for (let i = 0; i < menuPopupChildren.length; i++)
- menuPopupChildren.item(i).hidden = true;
- }
-
- // Set window title
- UpdateWindowTitle();
-
- // We must wait until document is created to get proper Url
- // (Windows may load with local file paths)
- SetSaveAndPublishUI(GetDocumentUrl());
-
- // Start in "Normal" edit mode
- SetDisplayMode(kDisplayModeNormal);
- }
-
- // Add mouse click watcher if right type of editor
- if (IsHTMLEditor())
- {
- // Force color widgets to update
- onFontColorChange();
- onBackgroundColorChange();
- }
- break;
-
- case "cmd_setDocumentModified":
- window.updateCommands("save");
- break;
-
- case "obs_documentWillBeDestroyed":
- dump("obs_documentWillBeDestroyed notification\n");
- break;
-
- case "obs_documentLocationChanged":
- // Ignore this when editor doesn't exist,
- // which happens once when page load starts
- if (editor)
- try {
- editor.updateBaseURL();
- } catch(e) { dump (e); }
- break;
-
- case "cmd_bold":
- // Update all style items
- // cmd_bold is a proxy; see EditorSharedStartup (above) for details
- window.updateCommands("style");
- window.updateCommands("undo");
- break;
- }
- }
-}
-
-function SetFocusOnStartup()
-{
- gContentWindow.focus();
-}
-
-function EditorLoadUrl(url)
-{
- try {
- if (url)
- GetCurrentEditorElement().webNavigation.loadURI(url, // uri string
- Components.interfaces.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE, // load flags
- null, // referrer
- null, // post-data stream
- null);
- } catch (e) { dump(" EditorLoadUrl failed: "+e+"\n"); }
-}
-
-// This should be called by all Composer types
-function EditorSharedStartup()
-{
- // Just for convenience
- gContentWindow = window.content;
-
- // Disable DNS Prefetching on the docshell - we don't need it for composer
- // type windows.
- GetCurrentEditorElement().docShell.allowDNSPrefetch = false;
-
- // Set up the mime type and register the commands.
- if (IsHTMLEditor())
- SetupHTMLEditorCommands();
- else
- SetupTextEditorCommands();
-
- // add observer to be called when document is really done loading
- // and is modified
- // Note: We're really screwed if we fail to install this observer!
- try {
- var commandManager = GetCurrentCommandManager();
- commandManager.addCommandObserver(gEditorDocumentObserver, "obs_documentCreated");
- commandManager.addCommandObserver(gEditorDocumentObserver, "cmd_setDocumentModified");
- commandManager.addCommandObserver(gEditorDocumentObserver, "obs_documentWillBeDestroyed");
- commandManager.addCommandObserver(gEditorDocumentObserver, "obs_documentLocationChanged");
-
- // Until nsIControllerCommandGroup-based code is implemented,
- // we will observe just the bold command to trigger update of
- // all toolbar style items
- commandManager.addCommandObserver(gEditorDocumentObserver, "cmd_bold");
- } catch (e) { dump(e); }
-
- var isMac = AppConstants.platform == "macosx";
-
- // Set platform-specific hints for how to select cells
- // Mac uses "Cmd", all others use "Ctrl"
- var tableKey = GetString(isMac ? "XulKeyMac" : "TableSelectKey");
- var dragStr = tableKey+GetString("Drag");
- var clickStr = tableKey+GetString("Click");
-
- var delStr = GetString(isMac ? "Clear" : "Del");
-
- SafeSetAttribute("menu_SelectCell", "acceltext", clickStr);
- SafeSetAttribute("menu_SelectRow", "acceltext", dragStr);
- SafeSetAttribute("menu_SelectColumn", "acceltext", dragStr);
- SafeSetAttribute("menu_SelectAllCells", "acceltext", dragStr);
- // And add "Del" or "Clear"
- SafeSetAttribute("menu_DeleteCellContents", "acceltext", delStr);
-
- // Set text for indent, outdent keybinding
-
- // hide UI that we don't have components for
- RemoveInapplicableUIElements();
-
- // Use browser colors as initial values for editor's default colors
- var BrowserColors = GetDefaultBrowserColors();
- if (BrowserColors)
- {
- gDefaultTextColor = BrowserColors.TextColor;
- gDefaultBackgroundColor = BrowserColors.BackgroundColor;
- }
-
- // For new window, no default last-picked colors
- gColorObj.LastTextColor = "";
- gColorObj.LastBackgroundColor = "";
- gColorObj.LastHighlightColor = "";
-}
-
-function SafeSetAttribute(nodeID, attributeName, attributeValue)
-{
- var theNode = document.getElementById(nodeID);
- if (theNode)
- theNode.setAttribute(attributeName, attributeValue);
-}
-
-function DocumentHasBeenSaved()
-{
- var fileurl = "";
- try {
- fileurl = GetDocumentUrl();
- } catch (e) {
- return false;
- }
-
- if (!fileurl || IsUrlAboutBlank(fileurl))
- return false;
-
- // We have a file URL already
- return true;
-}
-
-function CheckAndSaveDocument(command, allowDontSave)
-{
- var document;
- try {
- // if we don't have an editor or an document, bail
- var editor = GetCurrentEditor();
- document = editor.document;
- if (!document)
- return true;
- } catch (e) { return true; }
-
- if (!IsDocumentModified() && !IsHTMLSourceChanged())
- return true;
-
- // call window.focus, since we need to pop up a dialog
- // and therefore need to be visible (to prevent user confusion)
- top.document.commandDispatcher.focusedWindow.focus();
-
- var scheme = GetScheme(GetDocumentUrl());
- var doPublish = (scheme && scheme != "file");
-
- var strID;
- switch (command)
- {
- case "cmd_close":
- strID = "BeforeClosing";
- break;
- case "cmd_preview":
- strID = "BeforePreview";
- break;
- case "cmd_editSendPage":
- strID = "SendPageReason";
- break;
- case "cmd_validate":
- strID = "BeforeValidate";
- break;
- }
-
- var reasonToSave = strID ? GetString(strID) : "";
-
- var title = document.title || GetString("untitledDefaultFilename");
-
- var dialogTitle = GetString(doPublish ? "PublishPage" : "SaveDocument");
- var dialogMsg = GetString(doPublish ? "PublishPrompt" : "SaveFilePrompt");
- dialogMsg = (dialogMsg.replace(/%title%/,title)).replace(/%reason%/,reasonToSave);
-
- let result = {value:0};
- let promptFlags = Services.prompt.BUTTON_TITLE_CANCEL * Services.prompt.BUTTON_POS_1;
- let button1Title = null;
- let button3Title = null;
-
- if (doPublish)
- {
- promptFlags += Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_0;
- button1Title = GetString("Publish");
- button3Title = GetString("DontPublish");
- }
- else
- {
- promptFlags += Services.prompt.BUTTON_TITLE_SAVE * Services.prompt.BUTTON_POS_0;
- }
-
- // If allowing "Don't..." button, add that
- if (allowDontSave)
- promptFlags += doPublish ?
- (Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_2)
- : (Services.prompt.BUTTON_TITLE_DONT_SAVE * Services.prompt.BUTTON_POS_2);
-
- result = Services.prompt.confirmEx(window, dialogTitle, dialogMsg, promptFlags,
- button1Title, null, button3Title, null, {value:0});
-
- if (result == 0)
- {
- // Save, but first finish HTML source mode
- SetEditMode(gPreviousNonSourceDisplayMode);
- if (doPublish)
- {
- // We save the command the user wanted to do in a global
- // and return as if user canceled because publishing is asynchronous
- // This command will be fired when publishing finishes
- gCommandAfterPublishing = command;
- goDoCommand("cmd_publish");
- return false;
- }
-
- // Save to local disk
- return SaveDocument(false, false, editor.contentsMIMEType);
- }
-
- if (result == 2) // "Don't Save"
- return true;
-
- // Default or result == 1 (Cancel)
- return false;
-}
-
-// --------------------------- View menu ---------------------------
-
-function EditorSetCharacterSet(aEvent)
-{
- try {
- var editor = GetCurrentEditor();
- if (aEvent.target.hasAttribute("charset"))
- editor.documentCharacterSet = aEvent.target.getAttribute("charset");
- var docUrl = GetDocumentUrl();
- if( !IsUrlAboutBlank(docUrl))
- {
- // reloading the document will reverse any changes to the META charset,
- // we need to put them back in, which is achieved by a dedicated listener
- editor.addDocumentStateListener( DocumentReloadListener );
- EditorLoadUrl(docUrl);
- }
- } catch (e) {}
-}
-
-// --------------------------- Text style ---------------------------
-
-function onParagraphFormatChange(paraMenuList, commandID)
-{
- if (!paraMenuList)
- return;
-
- var commandNode = document.getElementById(commandID);
- var state = commandNode.getAttribute("state");
-
- // force match with "normal"
- if (state == "body")
- state = "";
-
- if (state == "mixed")
- {
- //Selection is the "mixed" ( > 1 style) state
- paraMenuList.selectedItem = null;
- paraMenuList.setAttribute("label",GetString('Mixed'));
- }
- else
- {
- var menuPopup = document.getElementById("ParagraphPopup");
- var menuItems = menuPopup.childNodes;
- for (var i=0; i < menuItems.length; i++)
- {
- var menuItem = menuItems.item(i);
- if ("value" in menuItem && menuItem.value == state)
- {
- paraMenuList.selectedItem = menuItem;
- break;
- }
- }
- }
-}
-
-/**
- * Selects the current font face in the menulist.
- *
- * @param fontFaceMenuList The menulist element containing the list of fonts.
- * @param commandID The commandID which holds the current font name
- * in its "state" attribute.
- */
-function onFontFaceChange(fontFaceMenuList, commandID)
-{
- var commandNode = document.getElementById(commandID);
- var editorFont = commandNode.getAttribute("state");
-
- // Strip quotes in font names. Experiments have shown that we only
- // ever get double quotes around the font name, never single quotes,
- // even if they were in the HTML source. Also single or double
- // quotes within the font name are never returned.
- editorFont = editorFont.replace(/"/g, "");
-
- switch (editorFont) {
- case "mixed":
- // Selection is the "mixed" ( > 1 style) state.
- fontFaceMenuList.selectedItem = null;
- fontFaceMenuList.setAttribute("label",GetString('Mixed'));
- return;
- case "":
- case "serif":
- case "sans-serif":
- // Generic variable width.
- fontFaceMenuList.selectedIndex = 0;
- return;
- case "tt":
- case "monospace":
- // Generic fixed width.
- fontFaceMenuList.selectedIndex = 1;
- return;
- default:
- }
-
- let menuPopup = fontFaceMenuList.menupopup;
- let menuItems = menuPopup.childNodes;
-
- const genericFamilies = [ "serif", "sans-serif", "monospace", "fantasy", "cursive" ];
- // Bug 1139524: Normalise before we compare: Make it lower case
- // and replace ", " with "," so that entries like
- // "Helvetica, Arial, sans-serif" are always recognised correctly
- let editorFontToLower = editorFont.toLowerCase().replace(/, /g, ",");
- let foundFont = null;
- let exactMatch = false;
- let usedFontsSep = menuPopup.querySelector("menuseparator.fontFaceMenuAfterUsedFonts");
- let editorFontOptions = editorFontToLower.split(",");
- let editorOptionsCount = editorFontOptions.length;
- let matchedFontIndex = editorOptionsCount; // initialise to high invalid value
-
- // The font menu has this structure:
- // 0: Variable Width
- // 1: Fixed Width
- // 2: Separator
- // 3: Helvetica, Arial (stored as Helvetica, Arial, sans-serif)
- // 4: Times (stored as Times New Roman, Times, serif)
- // 5: Courier (stored as Courier New, Courier, monospace)
- // 6: Separator, "menuseparator.fontFaceMenuAfterDefaultFonts"
- // from 7: Used Font Section (for quick selection)
- // followed by separator, "menuseparator.fontFaceMenuAfterUsedFonts"
- // followed by all other available fonts.
- // The following variable keeps track of where we are when we loop over the menu.
- let afterUsedFontSection = false;
-
- // The menu items not only have "label" and "value", but also some other attributes:
- // "value_parsed": Is the toLowerCase() and space-stripped value.
- // "value_cache": Is a concatenation of all editor fonts that were ever mapped
- // onto this menu item. This is done for optimization.
- // "used": This item is in the used font section.
-
- for (let i = 0; i < menuItems.length; i++)
- {
- let menuItem = menuItems.item(i);
- if (menuItem.hasAttribute("label") && menuItem.hasAttribute("value_parsed"))
- {
- // The element seems to represent a font <menuitem>.
- let fontMenuValue = menuItem.getAttribute("value_parsed");
- if (fontMenuValue == editorFontToLower ||
- (menuItem.hasAttribute("value_cache") &&
- menuItem.getAttribute("value_cache").split("|").includes(editorFontToLower)))
- {
- // This menuitem contains the font we are looking for.
- foundFont = menuItem;
- exactMatch = true;
- break;
- }
- else if (editorOptionsCount > 1 && afterUsedFontSection)
- {
- // Once we are in the list of all other available fonts,
- // we will find the one that best matches one of the options.
- let matchPos = editorFontOptions.indexOf(fontMenuValue);
- if (matchPos >= 0 && matchPos < matchedFontIndex)
- {
- // This menu font comes earlier in the list of options,
- // so prefer it.
- matchedFontIndex = matchPos;
- foundFont = menuItem;
- // If we matched the first option, we don't need to look for
- // a better match.
- if (matchPos == 0)
- break;
- }
- }
- }
- else
- {
- // Some other element type.
- if (menuItem == usedFontsSep)
- {
- // We have now passed the section of used fonts and are now in the list of all.
- afterUsedFontSection = true;
- }
- }
- }
-
- if (foundFont)
- {
- let defaultFontsSep = menuPopup.querySelector("menuseparator.fontFaceMenuAfterDefaultFonts");
- if (exactMatch)
- {
- if (afterUsedFontSection)
- {
- // Copy the matched font into the section of used fonts.
- // We insert after the separator following the default fonts,
- // so right at the beginning of the used fonts section.
- let copyItem = foundFont.cloneNode(true);
- menuPopup.insertBefore(copyItem, defaultFontsSep.nextSibling);
- usedFontsSep.hidden = false;
- foundFont = copyItem;
- foundFont.setAttribute("used", "true");
- }
- }
- else
- {
- // Keep only the found font and generic families in the font string.
- editorFont = editorFont.replace(/, /g, ",").split(",").filter(
- font => ((font.toLowerCase() == foundFont.getAttribute("value_parsed")) ||
- genericFamilies.includes(font))).join(",");
-
- // Check if such an item is already in the used font section.
- if (afterUsedFontSection)
- foundFont = menuPopup.querySelector('menuitem[used="true"][value_parsed="'+
- editorFont.toLowerCase()+'"]');
- // If not, create a new entry which will be inserted into that section.
- if (!foundFont)
- foundFont = createFontFaceMenuitem(editorFont, editorFont, menuPopup);
-
- // Add the editor font string into the 'cache' attribute in the element
- // so we can later find it quickly without building the reduced string again.
- let fontCache = "";
- if (foundFont.hasAttribute("value_cache"))
- fontCache = foundFont.getAttribute("value_cache");
- foundFont.setAttribute("value_cache", fontCache + "|" + editorFontToLower);
-
- // If we created a new item, set it up and insert.
- if (!foundFont.hasAttribute("used")) {
- foundFont.setAttribute("used", "true");
- usedFontsSep.hidden = false;
- menuPopup.insertBefore(foundFont, defaultFontsSep.nextSibling);
- }
- }
- }
- else
- {
- // The editor encountered a font that is not installed on this system.
- // Add it to the font menu now, in the used-fonts section right at the
- // bottom before the separator of the section.
- let fontLabel = GetFormattedString("NotInstalled", editorFont);
- foundFont = createFontFaceMenuitem(fontLabel, editorFont, menuPopup);
- foundFont.setAttribute("used", "true");
- usedFontsSep.hidden = false;
- menuPopup.insertBefore(foundFont, usedFontsSep);
- }
- fontFaceMenuList.selectedItem = foundFont;
-}
-
-/**
- * Clears the used fonts list from all the font face menulists.
- */
-function ClearUsedFonts()
-{
- let userFontSeps = document.querySelectorAll("menuseparator.fontFaceMenuAfterDefaultFonts");
- for (let userFontSep of userFontSeps) {
- let parentList = userFontSep.parentNode;
- while (true) {
- let nextNode = userFontSep.nextSibling;
- if (nextNode.tagName != "menuseparator") {
- nextNode.remove();
- } else {
- if (nextNode.classList.contains("fontFaceMenuAfterUsedFonts")) {
- nextNode.hidden = true;
- break;
- }
- }
- }
- }
-}
-
-function EditorSelectFontSize()
-{
- var select = document.getElementById("FontSizeSelect");
- if (select)
- {
- if (select.selectedIndex == -1)
- return;
-
- EditorSetFontSize(gFontSizeNames[select.selectedIndex]);
- }
-}
-
-function onFontSizeChange(fontSizeMenulist, commandID)
-{
- // If we don't match anything, set to "0 (normal)"
- var newIndex = 2;
- var size = fontSizeMenulist.getAttribute("size");
- if ( size == "mixed")
- {
- // No single type selected
- newIndex = -1;
- }
- else
- {
- for (var i = 0; i < gFontSizeNames.length; i++)
- {
- if( gFontSizeNames[i] == size )
- {
- newIndex = i;
- break;
- }
- }
- }
- if (fontSizeMenulist.selectedIndex != newIndex)
- fontSizeMenulist.selectedIndex = newIndex;
-}
-
-function EditorSetFontSize(size)
-{
- if( size == "0" || size == "normal" ||
- size == "medium" )
- {
- EditorRemoveTextProperty("font", "size");
- // Also remove big and small,
- // else it will seem like size isn't changing correctly
- EditorRemoveTextProperty("small", "");
- EditorRemoveTextProperty("big", "");
- } else {
- // Temp: convert from new CSS size strings to old HTML size strings
- switch (size)
- {
- case "xx-small":
- case "x-small":
- size = "-2";
- break;
- case "small":
- size = "-1";
- break;
- case "large":
- size = "+1";
- break;
- case "x-large":
- size = "+2";
- break;
- case "xx-large":
- size = "+3";
- break;
- }
- EditorSetTextProperty("font", "size", size);
- }
- gContentWindow.focus();
-}
-
-function initFontFaceMenu(menuPopup)
-{
- initLocalFontFaceMenu(menuPopup);
-
- if (menuPopup)
- {
- var children = menuPopup.childNodes;
- if (!children) return;
-
- var mixed = { value: false };
- var editorFont = GetCurrentEditor().getFontFaceState(mixed);
-
- // Strip quotes in font names. Experiments have shown that we only
- // ever get double quotes around the font name, never single quotes,
- // even if they were in the HTML source. Also single or double
- // quotes within the font name are never returned.
- editorFont = editorFont.replace(/"/g, "");
-
- if (!mixed.value)
- {
- switch (editorFont)
- {
- case "":
- case "serif":
- case "sans-serif":
- // Generic variable width.
- editorFont = "";
- break;
- case "tt":
- case "monospace":
- // Generic fixed width.
- editorFont = "tt";
- break;
- default:
- editorFont = editorFont.toLowerCase().replace(/, /g, ","); // bug 1139524
- }
- }
-
- var editorFontOptions = editorFont.split(',');
- var matchedOption = editorFontOptions.length; // initialise to high invalid value
- for (var i = 0; i < children.length; i++)
- {
- var menuItem = children[i];
- if (menuItem.localName == "menuitem")
- {
- var matchFound = false;
- if (!mixed.value)
- {
- var menuFont = menuItem.getAttribute("value").toLowerCase().replace(/, /g, ",");
-
- // First compare the entire font string to match items that contain commas.
- if (menuFont == editorFont)
- {
- menuItem.setAttribute("checked", "true");
- break;
- }
-
- // Next compare the individual options.
- else if (editorFontOptions.length > 1)
- {
- var matchPos = editorFontOptions.indexOf(menuFont);
- if (matchPos >= 0 && matchPos < matchedOption) {
- // This menu font comes earlier in the list of options,
- // so prefer it.
- menuItem.setAttribute("checked", "true");
-
- // If we matched the first option, we don't need to look for
- // a better match.
- if (matchPos == 0)
- break;
-
- matchedOption = matchPos;
- matchFound = true;
- }
- }
- }
-
- // In case this item doesn't match, make sure we've cleared the checkmark.
- if (!matchFound)
- menuItem.removeAttribute("checked");
- }
- }
- }
-}
-
-// Number of fixed font face menuitems, these are:
-// Variable Width
-// Fixed Width
-// ==separator
-// Helvetica, Arial
-// Times
-// Courier
-// ==separator
-// ==separator
-const kFixedFontFaceMenuItems = 8;
-
-function initLocalFontFaceMenu(menuPopup)
-{
- if (!gLocalFonts)
- {
- // Build list of all local fonts once per editor
- try
- {
- var enumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"]
- .getService(Components.interfaces.nsIFontEnumerator);
- var localFontCount = { value: 0 }
- gLocalFonts = enumerator.EnumerateAllFonts(localFontCount);
- }
- catch(e) { }
- }
-
- // Don't use radios for menulists.
- let useRadioMenuitems = (menuPopup.parentNode.localName == "menu");
- menuPopup.setAttribute("useRadios", useRadioMenuitems);
- if (menuPopup.childNodes.length == kFixedFontFaceMenuItems)
- {
- if (gLocalFonts.length == 0) {
- menuPopup.querySelector(".fontFaceMenuAfterDefaultFonts").hidden = true;
- }
- for (let i = 0; i < gLocalFonts.length; ++i)
- {
- // Remove Linux system generic fonts that collide with CSS generic fonts.
- if (gLocalFonts[i] != "" &&
- gLocalFonts[i] != "serif" &&
- gLocalFonts[i] != "sans-serif" &&
- gLocalFonts[i] != "monospace")
- {
- let itemNode = createFontFaceMenuitem(gLocalFonts[i], gLocalFonts[i], menuPopup);
- menuPopup.appendChild(itemNode);
- }
- }
- }
-}
-
-/**
- * Creates a menuitem element for the font faces menulist. Returns the menuitem
- * but does not add it automatically to the menupopup.
- *
- * @param aFontLabel Label to be displayed for the item.
- * @param aFontName The font face value to be used for the item.
- * Will be used in <font face="value"> in the edited document.
- * @param aMenuPopup The menupopup for which this menuitem is created.
- */
-function createFontFaceMenuitem(aFontLabel, aFontName, aMenuPopup)
-{
- let itemNode = document.createElementNS(XUL_NS, "menuitem");
- itemNode.setAttribute("label", aFontLabel);
- itemNode.setAttribute("value", aFontName);
- itemNode.setAttribute("value_parsed", aFontName.toLowerCase().replace(/, /g, ","));
- itemNode.setAttribute("tooltiptext", aFontLabel);
- if (aMenuPopup.getAttribute("useRadios") == "true") {
- itemNode.setAttribute("type", "radio");
- itemNode.setAttribute("observes", "cmd_renderedHTMLEnabler");
- }
- return itemNode;
-}
-
-/**
- * Helper function
- */
-function getFontSizeIndex()
-{
- var firstHas = { value: false };
- var anyHas = { value: false };
- var allHas = { value: false };
-
- var fontSize = EditorGetTextProperty("font", "size", null, firstHas, anyHas, allHas);
-
- // If the element has no size attribute and no size was found at all,
- // we assume "medium" size. This is highly problematic since
- // CSS sizes are not recognised and will show as "medium" as well.
- // Currently we can't distinguish between "no attribute" which
- // can imply "medium" and "CSS attribute present" which should not
- // imply "medium".
- if (!anyHas.value)
- return 2;
-
- // Mixed selection.
- if (!allHas.value)
- return -1;
-
- switch (fontSize)
- {
- case "-3":
- case "-2":
- case "0":
- case "1":
- // x-small.
- return 0;
- case "-1":
- case "2":
- // small.
- return 1;
- case "3":
- // medium.
- return 2;
- case "+1":
- case "4":
- // large.
- return 3;
- case "+2":
- case "5":
- // x-large.
- return 4;
- case "+3":
- case "+4":
- case "6":
- case "7":
- // xx-large.
- return 5;
- }
-
- // We shouldn't get here. All the selection has a value we don't understand.
- return -1;
-}
-
-function initFontSizeMenu(menuPopup, fullMenu)
-{
- if (menuPopup)
- {
- var children = menuPopup.childNodes;
- if (!children)
- return;
-
- // Fixed size items start after menu separator depending on whether it is
- // a full menu.
- var menuIndex = fullMenu ? 3 : 0;
-
- var setIndex = getFontSizeIndex();
- if (setIndex >= 0)
- {
- children[menuIndex + setIndex].setAttribute("checked", true);
- }
- else
- {
- // In case of mixed, clear all items.
- for (var i = menuIndex; i < children.length; i++) {
- children[i].setAttribute("checked", false);
- }
- }
-
- // Some configurations might not have the "small/big" indicator as
- // last item. If there is no indicator, we are done.
- if (!menuPopup.lastChild.id.includes("smallBigInfo"))
- return;
-
- // While it would be better to show the number of levels,
- // at least this tells user if either of them are set.
- var firstHas = { value: false };
- var anyHas = { value: false };
- var allHas = { value: false };
-
- // Show "small"/"big" indicator.
- var htmlInfo = "";
- EditorGetTextProperty("small", "", "", firstHas, anyHas, allHas);
- if (anyHas.value)
- htmlInfo = "<small>";
- EditorGetTextProperty("big", "", "", firstHas, anyHas, allHas);
- if (anyHas.value)
- htmlInfo += "<big>";
-
- if (htmlInfo)
- {
- menuPopup.lastChild.hidden = false;
- menuPopup.lastChild.setAttribute("label", "HTML: " + htmlInfo);
- menuPopup.lastChild.setAttribute("checked", true);
- }
- else
- {
- menuPopup.lastChild.hidden = true;
- }
- }
-}
-
-function onHighlightColorChange()
-{
- ChangeButtonColor("cmd_highlight", "HighlightColorButton",
- "transparent");
-}
-
-function onFontColorChange()
-{
- ChangeButtonColor("cmd_fontColor", "TextColorButton",
- gDefaultTextColor);
-}
-
-function onBackgroundColorChange()
-{
- ChangeButtonColor("cmd_backgroundColor", "BackgroundColorButton",
- gDefaultBackgroundColor);
-}
-
-/* Helper function that changes the button color.
- * commandID - The ID of the command element.
- * id - The ID of the button needing to be changed.
- * defaultColor - The default color the button gets set to.
- */
-function ChangeButtonColor(commandID, id, defaultColor) {
- var commandNode = document.getElementById(commandID);
- if (commandNode)
- {
- var color = commandNode.getAttribute("state");
- var button = document.getElementById(id);
- if (button)
- {
- button.setAttribute("color", color);
-
- // No color or a mixed color - get color set on page or other defaults.
- if (!color || color == "mixed")
- color = defaultColor;
-
- button.setAttribute("style", "background-color:" + color + " !important");
- }
- }
-}
-
-// Call this when user changes text and/or background colors of the page
-function UpdateDefaultColors()
-{
- var BrowserColors = GetDefaultBrowserColors();
- var bodyelement = GetBodyElement();
- var defTextColor = gDefaultTextColor;
- var defBackColor = gDefaultBackgroundColor;
-
- if (bodyelement)
- {
- var color = bodyelement.getAttribute("text");
- if (color)
- gDefaultTextColor = color;
- else if (BrowserColors)
- gDefaultTextColor = BrowserColors.TextColor;
-
- color = bodyelement.getAttribute("bgcolor");
- if (color)
- gDefaultBackgroundColor = color;
- else if (BrowserColors)
- gDefaultBackgroundColor = BrowserColors.BackgroundColor;
- }
-
- // Trigger update on toolbar
- if (defTextColor != gDefaultTextColor)
- {
- goUpdateCommandState("cmd_fontColor");
- onFontColorChange();
- }
- if (defBackColor != gDefaultBackgroundColor)
- {
- goUpdateCommandState("cmd_backgroundColor");
- onBackgroundColorChange();
- }
-}
-
-function GetBackgroundElementWithColor()
-{
- var editor = GetCurrentTableEditor();
- if (!editor)
- return null;
-
- gColorObj.Type = "";
- gColorObj.PageColor = "";
- gColorObj.TableColor = "";
- gColorObj.CellColor = "";
- gColorObj.BackgroundColor = "";
- gColorObj.SelectedType = "";
-
- var tagNameObj = { value: "" };
- var element;
- try {
- element = editor.getSelectedOrParentTableElement(tagNameObj, {value:0});
- }
- catch(e) {}
-
- if (element && tagNameObj && tagNameObj.value)
- {
- gColorObj.BackgroundColor = GetHTMLOrCSSStyleValue(element, "bgcolor", "background-color");
- gColorObj.BackgroundColor = ConvertRGBColorIntoHEXColor(gColorObj.BackgroundColor);
- if (tagNameObj.value.toLowerCase() == "td")
- {
- gColorObj.Type = "Cell";
- gColorObj.CellColor = gColorObj.BackgroundColor;
-
- // Get any color that might be on parent table
- var table = GetParentTable(element);
- gColorObj.TableColor = GetHTMLOrCSSStyleValue(table, "bgcolor", "background-color");
- gColorObj.TableColor = ConvertRGBColorIntoHEXColor(gColorObj.TableColor);
- }
- else
- {
- gColorObj.Type = "Table";
- gColorObj.TableColor = gColorObj.BackgroundColor;
- }
- gColorObj.SelectedType = gColorObj.Type;
- }
- else
- {
- let IsCSSPrefChecked = Services.prefs.getBoolPref(kUseCssPref);
- if (IsCSSPrefChecked && IsHTMLEditor())
- {
- let selection = editor.selection;
- if (selection)
- {
- element = selection.focusNode;
- while (!editor.nodeIsBlock(element))
- element = element.parentNode;
- }
- else
- {
- element = GetBodyElement();
- }
- }
- else
- {
- element = GetBodyElement();
- }
- if (element)
- {
- gColorObj.Type = "Page";
- gColorObj.BackgroundColor = GetHTMLOrCSSStyleValue(element, "bgcolor", "background-color");
- if (gColorObj.BackgroundColor == "")
- {
- gColorObj.BackgroundColor = "transparent";
- }
- else
- {
- gColorObj.BackgroundColor = ConvertRGBColorIntoHEXColor(gColorObj.BackgroundColor);
- }
- gColorObj.PageColor = gColorObj.BackgroundColor;
- }
- }
- return element;
-}
-
-function SetSmiley(smileyText)
-{
- try {
- GetCurrentEditor().insertText(smileyText);
- gContentWindow.focus();
- }
- catch(e) {}
-}
-
-function EditorSelectColor(colorType, mouseEvent)
-{
- var editor = GetCurrentEditor();
- if (!editor || !gColorObj)
- return;
-
- // Shift + mouse click automatically applies last color, if available
- var useLastColor = mouseEvent ? ( mouseEvent.button == 0 && mouseEvent.shiftKey ) : false;
- var element;
- var table;
- var currentColor = "";
- var commandNode;
-
- if (!colorType)
- colorType = "";
-
- if (colorType == "Text")
- {
- gColorObj.Type = colorType;
-
- // Get color from command node state
- commandNode = document.getElementById("cmd_fontColor");
- currentColor = commandNode.getAttribute("state");
- currentColor = ConvertRGBColorIntoHEXColor(currentColor);
- gColorObj.TextColor = currentColor;
-
- if (useLastColor && gColorObj.LastTextColor )
- gColorObj.TextColor = gColorObj.LastTextColor;
- else
- useLastColor = false;
- }
- else if (colorType == "Highlight")
- {
- gColorObj.Type = colorType;
-
- // Get color from command node state
- commandNode = document.getElementById("cmd_highlight");
- currentColor = commandNode.getAttribute("state");
- currentColor = ConvertRGBColorIntoHEXColor(currentColor);
- gColorObj.HighlightColor = currentColor;
-
- if (useLastColor && gColorObj.LastHighlightColor )
- gColorObj.HighlightColor = gColorObj.LastHighlightColor;
- else
- useLastColor = false;
- }
- else
- {
- element = GetBackgroundElementWithColor();
- if (!element)
- return;
-
- // Get the table if we found a cell
- if (gColorObj.Type == "Table")
- table = element;
- else if (gColorObj.Type == "Cell")
- table = GetParentTable(element);
-
- // Save to avoid resetting if not necessary
- currentColor = gColorObj.BackgroundColor;
-
- if (colorType == "TableOrCell" || colorType == "Cell")
- {
- if (gColorObj.Type == "Cell")
- gColorObj.Type = colorType;
- else if (gColorObj.Type != "Table")
- return;
- }
- else if (colorType == "Table" && gColorObj.Type == "Page")
- return;
-
- if (colorType == "" && gColorObj.Type == "Cell")
- {
- // Using empty string for requested type means
- // we can let user select cell or table
- gColorObj.Type = "TableOrCell";
- }
-
- if (useLastColor && gColorObj.LastBackgroundColor )
- gColorObj.BackgroundColor = gColorObj.LastBackgroundColor;
- else
- useLastColor = false;
- }
- // Save the type we are really requesting
- colorType = gColorObj.Type;
-
- if (!useLastColor)
- {
- // Avoid the JS warning
- gColorObj.NoDefault = false;
-
- // Launch the ColorPicker dialog
- // TODO: Figure out how to position this under the color buttons on the toolbar
- window.openDialog("chrome://editor/content/EdColorPicker.xul", "_blank", "chrome,close,titlebar,modal", "", gColorObj);
-
- // User canceled the dialog
- if (gColorObj.Cancel)
- return;
- }
-
- if (gColorObj.Type == "Text")
- {
- if (currentColor != gColorObj.TextColor)
- {
- if (gColorObj.TextColor)
- EditorSetTextProperty("font", "color", gColorObj.TextColor);
- else
- EditorRemoveTextProperty("font", "color");
- }
- // Update the command state (this will trigger color button update)
- goUpdateCommandState("cmd_fontColor");
- }
- else if (gColorObj.Type == "Highlight")
- {
- if (currentColor != gColorObj.HighlightColor)
- {
- if (gColorObj.HighlightColor)
- EditorSetTextProperty("font", "bgcolor", gColorObj.HighlightColor);
- else
- EditorRemoveTextProperty("font", "bgcolor");
- }
- // Update the command state (this will trigger color button update)
- goUpdateCommandState("cmd_highlight");
- }
- else if (element)
- {
- if (gColorObj.Type == "Table")
- {
- // Set background on a table
- // Note that we shouldn't trust "currentColor" because of "TableOrCell" behavior
- if (table)
- {
- var bgcolor = table.getAttribute("bgcolor");
- if (bgcolor != gColorObj.BackgroundColor)
- try {
- if (gColorObj.BackgroundColor)
- editor.setAttributeOrEquivalent(table, "bgcolor", gColorObj.BackgroundColor, false);
- else
- editor.removeAttributeOrEquivalent(table, "bgcolor", false);
- } catch (e) {}
- }
- }
- else if (currentColor != gColorObj.BackgroundColor && IsHTMLEditor())
- {
- editor.beginTransaction();
- try
- {
- editor.setBackgroundColor(gColorObj.BackgroundColor);
-
- if (gColorObj.Type == "Page" && gColorObj.BackgroundColor)
- {
- // Set all page colors not explicitly set,
- // else you can end up with unreadable pages
- // because viewer's default colors may not be same as page author's
- var bodyelement = GetBodyElement();
- if (bodyelement)
- {
- var defColors = GetDefaultBrowserColors();
- if (defColors)
- {
- if (!bodyelement.getAttribute("text"))
- editor.setAttributeOrEquivalent(bodyelement, "text", defColors.TextColor, false);
-
- // The following attributes have no individual CSS declaration counterparts
- // Getting rid of them in favor of CSS implies CSS rules management
- if (!bodyelement.getAttribute("link"))
- editor.setAttribute(bodyelement, "link", defColors.LinkColor);
-
- if (!bodyelement.getAttribute("alink"))
- editor.setAttribute(bodyelement, "alink", defColors.ActiveLinkColor);
-
- if (!bodyelement.getAttribute("vlink"))
- editor.setAttribute(bodyelement, "vlink", defColors.VisitedLinkColor);
- }
- }
- }
- }
- catch(e) {}
-
- editor.endTransaction();
- }
-
- goUpdateCommandState("cmd_backgroundColor");
- }
- gContentWindow.focus();
-}
-
-function GetParentTable(element)
-{
- var node = element;
- while (node)
- {
- if (node.nodeName.toLowerCase() == "table")
- return node;
-
- node = node.parentNode;
- }
- return node;
-}
-
-function GetParentTableCell(element)
-{
- var node = element;
- while (node)
- {
- if (node.nodeName.toLowerCase() == "td" || node.nodeName.toLowerCase() == "th")
- return node;
-
- node = node.parentNode;
- }
- return node;
-}
-
-function EditorDblClick(event)
-{
- // We check event.explicitOriginalTarget here because .target will never
- // be a textnode (bug 193689)
- if (event.explicitOriginalTarget)
- {
- // Only bring up properties if clicked on an element or selected link
- var element;
- try {
- element = event.explicitOriginalTarget.QueryInterface(
- Components.interfaces.nsIDOMElement);
- } catch (e) {}
-
- // We use "href" instead of "a" to not be fooled by named anchor
- if (!element)
- try {
- element = GetCurrentEditor().getSelectedElement("href");
- } catch (e) {}
-
- // Don't fire for body/p and other block elements.
- // It's common that people try to double-click
- // to select a word, but the click hits an empty area.
- if (element &&
- !["body","p","h1","h2","h3","h4","h5","h6","blockquote","div","pre"]
- .includes(element.nodeName.toLowerCase()))
- {
- goDoCommand("cmd_objectProperties");
- event.preventDefault();
- }
- }
-}
-
-function EditorClick(event)
-{
- // For Web Composer: In Show All Tags Mode,
- // single click selects entire element,
- // except for body and table elements
- if (gEditorDisplayMode == kDisplayModeAllTags)
- {
- try
- {
- // We check event.explicitOriginalTarget here because .target will never
- // be a textnode (bug 193689)
- var element = event.explicitOriginalTarget.QueryInterface(
- Components.interfaces.nsIDOMElement);
- var name = element.localName;
- if (!["body", "caption", "table", "td", "th", "tr"].includes(name))
- {
- GetCurrentEditor().selectElement(event.explicitOriginalTarget);
- event.preventDefault();
- }
- } catch (e) {}
- }
-}
-
-/*TODO: We need an oncreate hook to do enabling/disabling for the
- Format menu. There should be code like this for the
- object-specific "Properties" item
-*/
-// For property dialogs, we want the selected element,
-// but will accept a parent link, list, or table cell if inside one
-function GetObjectForProperties()
-{
- var editor = GetCurrentEditor();
- if (!editor || !IsHTMLEditor())
- return null;
-
- var element;
- try {
- element = editor.getSelectedElement("");
- } catch (e) {}
- if (element) {
- if (element.namespaceURI == "http://www.w3.org/1998/Math/MathML") {
- // If the object is a MathML element, we collapse the selection on it and
- // we return its <math> ancestor. Hence the math dialog will be used.
- GetCurrentEditor().selection.collapse(element, 0);
- } else
- return element;
- }
-
- // Find nearest parent of selection anchor node
- // that is a link, list, table cell, or table
-
- var anchorNode
- var node;
- try {
- anchorNode = editor.selection.anchorNode;
- if (anchorNode.firstChild)
- {
- // Start at actual selected node
- var offset = editor.selection.anchorOffset;
- // Note: If collapsed, offset points to element AFTER caret,
- // thus node may be null
- node = anchorNode.childNodes.item(offset);
- }
- if (!node)
- node = anchorNode;
- } catch (e) {}
-
- while (node)
- {
- if (node.nodeName)
- {
- var nodeName = node.nodeName.toLowerCase();
-
- // Done when we hit the body
- if (nodeName == "body") break;
-
- if ((nodeName == "a" && node.href) ||
- nodeName == "ol" || nodeName == "ul" || nodeName == "dl" ||
- nodeName == "td" || nodeName == "th" ||
- nodeName == "table" || nodeName == "math")
- {
- return node;
- }
- }
- node = node.parentNode;
- }
- return null;
-}
-
-function SetEditMode(mode)
-{
- if (!IsHTMLEditor())
- return;
-
- var bodyElement = GetBodyElement();
- if (!bodyElement)
- {
- dump("SetEditMode: We don't have a body node!\n");
- return;
- }
-
- // must have editor if here!
- var editor = GetCurrentEditor();
- var inlineSpellCheckItem = document.getElementById('menu_inlineSpellCheck');
-
- // Switch the UI mode before inserting contents
- // so user can't type in source window while new window is being filled
- var previousMode = gEditorDisplayMode;
- if (!SetDisplayMode(mode))
- return;
-
- if (mode == kDisplayModeSource)
- {
- // Display the DOCTYPE as a non-editable string above edit area
- var domdoc;
- try { domdoc = editor.document; } catch (e) { dump( e + "\n");}
- if (domdoc)
- {
- var doctypeNode = document.getElementById("doctype-text");
- var dt = domdoc.doctype;
- if (doctypeNode)
- {
- if (dt)
- {
- doctypeNode.collapsed = false;
- var doctypeText = "<!DOCTYPE " + domdoc.doctype.name;
- if (dt.publicId)
- doctypeText += " PUBLIC \"" + domdoc.doctype.publicId;
- if (dt.systemId)
- doctypeText += " \"" + dt.systemId;
- doctypeText += "\">"
- doctypeNode.setAttribute("value", doctypeText);
- }
- else
- doctypeNode.collapsed = true;
- }
- }
- // Get the entire document's source string
-
- var flags = (editor.documentCharacterSet == "ISO-8859-1")
- ? kOutputEncodeLatin1Entities
- : kOutputEncodeBasicEntities;
- try {
- let encodeEntity = Services.prefs.getCharPref("editor.encode_entity");
- switch (encodeEntity) {
- case "basic" : flags = kOutputEncodeBasicEntities; break;
- case "latin1" : flags = kOutputEncodeLatin1Entities; break;
- case "html" : flags = kOutputEncodeHTMLEntities; break;
- case "none" : flags = 0; break;
- }
- } catch (e) { }
-
- if (Services.prefs.getBoolPref("editor.prettyprint"))
- flags |= kOutputFormatted;
-
- flags |= kOutputLFLineBreak;
- var source = editor.outputToString(editor.contentsMIMEType, flags);
- var start = source.search(/<html/i);
- if (start == -1) start = 0;
- gSourceTextEditor.insertText(source.slice(start));
- gSourceTextEditor.resetModificationCount();
- gSourceTextEditor.addDocumentStateListener(gSourceTextListener);
- gSourceTextEditor.enableUndo(true);
- gSourceContentWindow.commandManager.addCommandObserver(gSourceTextObserver, "cmd_undo");
- gSourceContentWindow.contentWindow.focus();
- goDoCommand("cmd_moveTop");
- }
- else if (previousMode == kDisplayModeSource)
- {
- // Only rebuild document if a change was made in source window
- if (IsHTMLSourceChanged())
- {
- // Disable spell checking when rebuilding source
- InlineSpellCheckerUI.enabled = false;
- inlineSpellCheckItem.removeAttribute('checked');
-
- // Reduce the undo count so we don't use too much memory
- // during multiple uses of source window
- // (reinserting entire doc caches all nodes)
- try {
- editor.transactionManager.maxTransactionCount = 1;
- } catch (e) {}
-
- editor.beginTransaction();
- try {
- // We are coming from edit source mode,
- // so transfer that back into the document
- source = gSourceTextEditor.outputToString(kTextMimeType, kOutputLFLineBreak).trim();
- if (editor.contentsMIMEType != kXHTMLMimeType)
- editor.rebuildDocumentFromSource(source);
- else {
- var fragment = editor.document.createRange().createContextualFragment(source);
- editor.enableUndo(false);
- GetBodyElement().remove();
- editor.document.replaceChild(fragment.firstChild, editor.document.documentElement);
- editor.enableUndo(true);
- }
-
- // Get the text for the <title> from the newly-parsed document
- // (must do this for proper conversion of "escaped" characters)
- let titleNode = editor.document.querySelector("title");
- SetDocumentTitle(titleNode ? titleNode.textContent : "");
-
- } catch (ex) {
- dump(ex);
- }
- editor.endTransaction();
-
- // Restore unlimited undo count
- try {
- editor.transactionManager.maxTransactionCount = -1;
- } catch (e) {}
- }
-
- // Clear out the string buffers
- gSourceContentWindow.commandManager.removeCommandObserver(gSourceTextObserver, "cmd_undo");
- gSourceTextEditor.removeDocumentStateListener(gSourceTextListener);
- gSourceTextEditor.enableUndo(false);
- gSourceTextEditor.selectAll();
- gSourceTextEditor.deleteSelection(gSourceTextEditor.eNone,
- gSourceTextEditor.eStrip);
- gSourceTextEditor.resetModificationCount();
-
- gContentWindow.focus();
- //goDoCommand("cmd_moveTop");
- }
-
- switch (mode) {
- case kDisplayModePreview:
- // Disable spell checking when previewing
- InlineSpellCheckerUI.enabled = false;
- inlineSpellCheckItem.removeAttribute('checked');
- // fall through
- case kDisplayModeSource:
- inlineSpellCheckItem.setAttribute('disabled', 'true');
- break;
- default:
- inlineSpellCheckItem.setAttribute('disabled', !InlineSpellCheckerUI.canSpellCheck);
- break;
- }
-}
-
-function CancelHTMLSource()
-{
- // Don't convert source text back into the DOM document
- gSourceTextEditor.resetModificationCount();
- SetDisplayMode(gPreviousNonSourceDisplayMode);
-}
-
-function SetDisplayMode(mode)
-{
- if (!IsHTMLEditor())
- return false;
-
- // Already in requested mode:
- // return false to indicate we didn't switch
- if (mode == gEditorDisplayMode)
- return false;
-
- var previousMode = gEditorDisplayMode;
- gEditorDisplayMode = mode;
-
- ResetStructToolbar();
- if (mode == kDisplayModeSource)
- {
- // Switch to the sourceWindow (second in the deck)
- gContentWindowDeck.selectedIndex = 1;
-
- //Hide the formatting toolbar if not already hidden
- gFormatToolbarHidden = gFormatToolbar.hidden;
- gFormatToolbar.hidden = true;
- gViewFormatToolbar.hidden = true;
-
- gSourceContentWindow.contentWindow.focus();
- }
- else
- {
- // Save the last non-source mode so we can cancel source editing easily
- gPreviousNonSourceDisplayMode = mode;
-
- // Load/unload appropriate override style sheet
- try {
- var editor = GetCurrentEditor();
- editor.QueryInterface(nsIEditorStyleSheets);
- editor instanceof Components.interfaces.nsIHTMLObjectResizer;
-
- switch (mode)
- {
- case kDisplayModePreview:
- // Disable all extra "edit mode" style sheets
- editor.enableStyleSheet(kNormalStyleSheet, false);
- editor.enableStyleSheet(kAllTagsStyleSheet, false);
- editor.objectResizingEnabled = true;
- break;
-
- case kDisplayModeNormal:
- editor.addOverrideStyleSheet(kNormalStyleSheet);
- // Disable ShowAllTags mode
- editor.enableStyleSheet(kAllTagsStyleSheet, false);
- editor.objectResizingEnabled = true;
- break;
-
- case kDisplayModeAllTags:
- editor.addOverrideStyleSheet(kNormalStyleSheet);
- editor.addOverrideStyleSheet(kAllTagsStyleSheet);
- // don't allow resizing in AllTags mode because the visible tags
- // change the computed size of images and tables...
- if (editor.resizedObject) {
- editor.hideResizers();
- }
- editor.objectResizingEnabled = false;
- break;
- }
- } catch(e) {}
-
- // Switch to the normal editor (first in the deck)
- gContentWindowDeck.selectedIndex = 0;
-
- // Restore menus and toolbars
- gFormatToolbar.hidden = gFormatToolbarHidden;
- gViewFormatToolbar.hidden = false;
-
- gContentWindow.focus();
- }
-
- // update commands to disable or re-enable stuff
- window.updateCommands("mode_switch");
-
- // Set the selected tab at bottom of window:
- // (Note: Setting "selectedIndex = mode" won't redraw tabs when menu is used.)
- document.getElementById("EditModeTabs").selectedItem = document.getElementById(kDisplayModeTabIDS[mode]);
-
- // Uncheck previous menuitem and set new check since toolbar may have been used
- if (previousMode >= 0)
- document.getElementById(kDisplayModeMenuIDs[previousMode]).setAttribute("checked","false");
- document.getElementById(kDisplayModeMenuIDs[mode]).setAttribute("checked","true");
-
-
- return true;
-}
-
-function UpdateWindowTitle()
-{
- try {
- var filename = "";
- var windowTitle = "";
- var title = GetDocumentTitle();
-
- // Append just the 'leaf' filename to the Doc. Title for the window caption
- var docUrl = GetDocumentUrl();
- if (docUrl && !IsUrlAboutBlank(docUrl))
- {
- var scheme = GetScheme(docUrl);
- filename = GetFilename(docUrl);
- if (filename)
- windowTitle = " [" + scheme + ":/.../" + filename + "]";
-
- var fileType = IsHTMLEditor() ? "html" : "text";
- // Save changed title in the recent pages data in prefs
- SaveRecentFilesPrefs(title, fileType);
- }
-
- // Set window title with " - Composer" or " - Text Editor" appended.
- var xulWin = document.documentElement;
-
- document.title = (title || filename || gUntitledString) +
- windowTitle +
- xulWin.getAttribute("titlemenuseparator") +
- xulWin.getAttribute("titlemodifier");
- } catch (e) { dump(e); }
-}
-
-function SaveRecentFilesPrefs(aTitle, aFileType)
-{
- var curUrl = StripPassword(GetDocumentUrl());
- var historyCount = Services.prefs.getIntPref("editor.history.url_maximum");
-
- var titleArray = [];
- var urlArray = [];
- var typeArray = [];
-
- if (historyCount && !IsUrlAboutBlank(curUrl) && GetScheme(curUrl) != "data")
- {
- titleArray.push(aTitle);
- urlArray.push(curUrl);
- typeArray.push(aFileType);
- }
-
- for (let i = 0; i < historyCount && urlArray.length < historyCount; i++)
- {
- let url = GetStringPref("editor.history_url_" + i);
-
- // Continue if URL pref is missing because
- // a URL not found during loading may have been removed
-
- // Skip over current an "data" URLs
- if (url && url != curUrl && GetScheme(url) != "data")
- {
- let title = GetStringPref("editor.history_title_" + i);
- let fileType = GetStringPref("editor.history_type_" + i);
- titleArray.push(title);
- urlArray.push(url);
- typeArray.push(fileType);
- }
- }
-
- // Resave the list back to prefs in the new order
- for (let i = 0; i < urlArray.length; i++)
- {
- SetStringPref("editor.history_title_" + i, titleArray[i]);
- SetStringPref("editor.history_url_" + i, urlArray[i]);
- SetStringPref("editor.history_type_" + i, typeArray[i]);
- }
-}
-
-function EditorInitFormatMenu()
-{
- try {
- InitObjectPropertiesMenuitem();
- InitRemoveStylesMenuitems("removeStylesMenuitem", "removeLinksMenuitem", "removeNamedAnchorsMenuitem");
- } catch(ex) {}
-}
-
-function InitObjectPropertiesMenuitem()
-{
- // Set strings and enable for the [Object] Properties item
- // Note that we directly do the enabling instead of
- // using goSetCommandEnabled since we already have the command.
- var cmd = document.getElementById("cmd_objectProperties");
- if (!cmd)
- return null;
-
- var element;
- var menuStr = GetString("AdvancedProperties");
- var name;
-
- if (IsEditingRenderedHTML())
- element = GetObjectForProperties();
-
- if (element && element.nodeName)
- {
- var objStr = "";
- cmd.removeAttribute("disabled");
- name = element.nodeName.toLowerCase();
- switch (name)
- {
- case "img":
- // Check if img is enclosed in link
- // (use "href" to not be fooled by named anchor)
- try
- {
- if (GetCurrentEditor().getElementOrParentByTagName("href", element))
- {
- objStr = GetString("ImageAndLink");
- // Return "href" so it is detected as a link.
- name = "href";
- }
- } catch(e) {}
-
- if (objStr == "")
- objStr = GetString("Image");
- break;
- case "hr":
- objStr = GetString("HLine");
- break;
- case "table":
- objStr = GetString("Table");
- break;
- case "th":
- name = "td";
- case "td":
- objStr = GetString("TableCell");
- break;
- case "ol":
- case "ul":
- case "dl":
- objStr = GetString("List");
- break;
- case "li":
- objStr = GetString("ListItem");
- break;
- case "form":
- objStr = GetString("Form");
- break;
- case "input":
- var type = element.getAttribute("type");
- if (type && type.toLowerCase() == "image")
- objStr = GetString("InputImage");
- else
- objStr = GetString("InputTag");
- break;
- case "textarea":
- objStr = GetString("TextArea");
- break;
- case "select":
- objStr = GetString("Select");
- break;
- case "button":
- objStr = GetString("Button");
- break;
- case "label":
- objStr = GetString("Label");
- break;
- case "fieldset":
- objStr = GetString("FieldSet");
- break;
- case "a":
- if (element.name)
- {
- objStr = GetString("NamedAnchor");
- name = "anchor";
- }
- else if(element.href)
- {
- objStr = GetString("Link");
- name = "href";
- }
- break;
- }
- if (objStr)
- menuStr = GetString("ObjectProperties").replace(/%obj%/,objStr);
- }
- else
- {
- // We show generic "Properties" string, but disable the command.
- cmd.setAttribute("disabled", "true");
- }
- cmd.setAttribute("label", menuStr);
- cmd.setAttribute("accesskey", GetString("ObjectPropertiesAccessKey"));
- return name;
-}
-
-function InitParagraphMenu()
-{
- var mixedObj = { value: null };
- var state;
- try {
- state = GetCurrentEditor().getParagraphState(mixedObj);
- }
- catch(e) {}
- var IDSuffix;
-
- // PROBLEM: When we get blockquote, it masks other styles contained by it
- // We need a separate method to get blockquote state
-
- // We use "x" as uninitialized paragraph state
- if (!state || state == "x")
- IDSuffix = "bodyText" // No paragraph container
- else
- IDSuffix = state;
-
- // Set "radio" check on one item, but...
- var menuItem = document.getElementById("menu_"+IDSuffix);
- menuItem.setAttribute("checked", "true");
-
- // ..."bodyText" is returned if mixed selection, so remove checkmark
- if (mixedObj.value)
- menuItem.setAttribute("checked", "false");
-}
-
-function GetListStateString()
-{
- try {
- var editor = GetCurrentEditor();
-
- var mixedObj = { value: null };
- var hasOL = { value: false };
- var hasUL = { value: false };
- var hasDL = { value: false };
- editor.getListState(mixedObj, hasOL, hasUL, hasDL);
-
- if (mixedObj.value)
- return "mixed";
- if (hasOL.value)
- return "ol";
- if (hasUL.value)
- return "ul";
-
- if (hasDL.value)
- {
- var hasLI = { value: false };
- var hasDT = { value: false };
- var hasDD = { value: false };
- editor.getListItemState(mixedObj, hasLI, hasDT, hasDD);
- if (mixedObj.value)
- return "mixed";
- if (hasLI.value)
- return "li";
- if (hasDT.value)
- return "dt";
- if (hasDD.value)
- return "dd";
- }
- } catch (e) {}
-
- // return "noList" if we aren't in a list at all
- return "noList";
-}
-
-function InitListMenu()
-{
- if (!IsHTMLEditor())
- return;
-
- var IDSuffix = GetListStateString();
-
- // Set enable state for the "None" menuitem
- goSetCommandEnabled("cmd_removeList", IDSuffix != "noList");
-
- // Set "radio" check on one item, but...
- // we won't find a match if it's "mixed"
- var menuItem = document.getElementById("menu_"+IDSuffix);
- if (menuItem)
- menuItem.setAttribute("checked", "true");
-}
-
-function GetAlignmentString()
-{
- var mixedObj = { value: null };
- var alignObj = { value: null };
- try {
- GetCurrentEditor().getAlignment(mixedObj, alignObj);
- } catch (e) {}
-
- if (mixedObj.value)
- return "mixed";
- if (alignObj.value == nsIHTMLEditor.eLeft)
- return "left";
- if (alignObj.value == nsIHTMLEditor.eCenter)
- return "center";
- if (alignObj.value == nsIHTMLEditor.eRight)
- return "right";
- if (alignObj.value == nsIHTMLEditor.eJustify)
- return "justify";
-
- // return "left" if we got here
- return "left";
-}
-
-function InitAlignMenu()
-{
- if (!IsHTMLEditor())
- return;
-
- var IDSuffix = GetAlignmentString();
-
- // we won't find a match if it's "mixed"
- var menuItem = document.getElementById("menu_"+IDSuffix);
- if (menuItem)
- menuItem.setAttribute("checked", "true");
-}
-
-function EditorSetDefaultPrefsAndDoctype()
-{
- var editor = GetCurrentEditor();
-
- var domdoc;
- try {
- domdoc = editor.document;
- } catch (e) { dump( e + "\n"); }
- if ( !domdoc )
- {
- dump("EditorSetDefaultPrefsAndDoctype: EDITOR DOCUMENT NOT FOUND\n");
- return;
- }
-
- // Insert a doctype element
- // if it is missing from existing doc
- if (!domdoc.doctype)
- {
- var newdoctype = domdoc.implementation.createDocumentType("HTML", "-//W3C//DTD HTML 4.01 Transitional//EN","");
- if (newdoctype)
- domdoc.insertBefore(newdoctype, domdoc.firstChild);
- }
-
- // search for head; we'll need this for meta tag additions
- let headelement = domdoc.querySelector("head");
- if (!headelement)
- {
- headelement = domdoc.createElement("head");
- if (headelement)
- domdoc.insertAfter(headelement, domdoc.firstChild);
- }
-
- /* only set default prefs for new documents */
- if (!IsUrlAboutBlank(GetDocumentUrl()))
- return;
-
- // search for author meta tag.
- // if one is found, don't do anything.
- // if not, create one and make it a child of the head tag
- // and set its content attribute to the value of the editor.author preference.
-
- if (domdoc.querySelector("meta"))
- {
- // we should do charset first since we need to have charset before
- // hitting other 8-bit char in other meta tags
- // grab charset pref and make it the default charset
- var element;
- var prefCharsetString = Services.prefs.getCharPref("intl.charset.fallback.override");
- if (prefCharsetString)
- editor.documentCharacterSet = prefCharsetString;
-
- // let's start by assuming we have an author in case we don't have the pref
-
- var prefAuthorString = null;
- let authorFound = domdoc.querySelector('meta[name="author"]');
- try
- {
- prefAuthorString = Services.prefs.getComplexValue("editor.author",
- Components.interfaces.nsISupportsString).data;
- }
- catch (ex) {}
- if (prefAuthorString && prefAuthorString != 0 && !authorFound && headelement)
- {
- // create meta tag with 2 attributes
- element = domdoc.createElement("meta");
- if (element)
- {
- element.setAttribute("name", "author");
- element.setAttribute("content", prefAuthorString);
- headelement.appendChild(element);
- }
- }
- }
-
- // add title tag if not present
- if (headelement && !editor.document.querySelector("title"))
- {
- var titleElement = domdoc.createElement("title");
- if (titleElement)
- headelement.appendChild(titleElement);
- }
-
- // find body node
- var bodyelement = GetBodyElement();
- if (bodyelement)
- {
- if (Services.prefs.getBoolPref("editor.use_custom_colors"))
- {
- let text_color = Services.prefs.getCharPref("editor.text_color");
- let background_color = Services.prefs.getCharPref("editor.background_color");
-
- // add the color attributes to the body tag.
- // and use them for the default text and background colors if not empty
- editor.setAttributeOrEquivalent(bodyelement, "text", text_color, true);
- gDefaultTextColor = text_color;
- editor.setAttributeOrEquivalent(bodyelement, "bgcolor", background_color, true);
- gDefaultBackgroundColor = background_color
- bodyelement.setAttribute("link", Services.prefs.getCharPref("editor.link_color"));
- bodyelement.setAttribute("alink", Services.prefs.getCharPref("editor.active_link_color"));
- bodyelement.setAttribute("vlink", Services.prefs.getCharPref("editor.followed_link_color"));
- }
- // Default image is independent of Custom colors???
- try {
- let background_image = Services.prefs.getCharPref("editor.default_background_image");
- if (background_image)
- editor.setAttributeOrEquivalent(bodyelement, "background", background_image, true);
- } catch (e) {dump("BACKGROUND EXCEPTION: "+e+"\n"); }
-
- }
- // auto-save???
-}
-
-function GetBodyElement()
-{
- try {
- return GetCurrentEditor().rootElement;
- }
- catch (ex) {
- dump("no body tag found?!\n");
- // better have one, how can we blow things up here?
- }
- return null;
-}
-
-// --------------------------- Logging stuff ---------------------------
-
-function EditorGetNodeFromOffsets(offsets)
-{
- var node = null;
- try {
- node = GetCurrentEditor().document;
-
- for (var i = 0; i < offsets.length; i++)
- node = node.childNodes[offsets[i]];
- } catch (e) {}
- return node;
-}
-
-function EditorSetSelectionFromOffsets(selRanges)
-{
- try {
- var editor = GetCurrentEditor();
- var selection = editor.selection;
- selection.removeAllRanges();
-
- var rangeArr, start, end, node, offset;
- for (var i = 0; i < selRanges.length; i++)
- {
- rangeArr = selRanges[i];
- start = rangeArr[0];
- end = rangeArr[1];
-
- var range = editor.document.createRange();
-
- node = EditorGetNodeFromOffsets(start[0]);
- offset = start[1];
-
- range.setStart(node, offset);
-
- node = EditorGetNodeFromOffsets(end[0]);
- offset = end[1];
-
- range.setEnd(node, offset);
-
- selection.addRange(range);
- }
- } catch (e) {}
-}
-
-//--------------------------------------------------------------------
-function initFontStyleMenu(menuPopup)
-{
- for (var i = 0; i < menuPopup.childNodes.length; i++)
- {
- var menuItem = menuPopup.childNodes[i];
- var theStyle = menuItem.getAttribute("state");
- if (theStyle)
- {
- menuItem.setAttribute("checked", theStyle);
- }
- }
-}
-
-//--------------------------------------------------------------------
-function onButtonUpdate(button, commmandID)
-{
- var commandNode = document.getElementById(commmandID);
- var state = commandNode.getAttribute("state");
- button.checked = state == "true";
-}
-
-//--------------------------------------------------------------------
-function onStateButtonUpdate(button, commmandID, onState)
-{
- var commandNode = document.getElementById(commmandID);
- var state = commandNode.getAttribute("state");
-
- button.checked = state == onState;
-}
-
-// --------------------------- Status calls ---------------------------
-function getColorAndSetColorWell(ColorPickerID, ColorWellID)
-{
- var colorWell;
- if (ColorWellID)
- colorWell = document.getElementById(ColorWellID);
-
- var colorPicker = document.getElementById(ColorPickerID);
- if (colorPicker)
- {
- // Extract color from colorPicker and assign to colorWell.
- var color = colorPicker.getAttribute("color");
-
- if (colorWell && color)
- {
- // Use setAttribute so colorwell can be a XUL element, such as button
- colorWell.setAttribute("style", "background-color: " + color);
- }
- }
- return color;
-}
-
-//-----------------------------------------------------------------------------------
-function IsSpellCheckerInstalled()
-{
- return "@mozilla.org/spellchecker;1" in Components.classes;
-}
-
-//-----------------------------------------------------------------------------------
-function IsFindInstalled()
-{
- return "@mozilla.org/embedcomp/rangefind;1" in Components.classes
- && "@mozilla.org/find/find_service;1" in Components.classes;
-}
-
-//-----------------------------------------------------------------------------------
-function RemoveInapplicableUIElements()
-{
- // For items that are in their own menu block, remove associated separator
- // (we can't use "hidden" since class="hide-in-IM" CSS rule interferes)
-
- // if no find, remove find ui
- if (!IsFindInstalled())
- {
- HideItem("menu_find");
- HideItem("menu_findnext");
- HideItem("menu_replace");
- HideItem("menu_find");
- RemoveItem("sep_find");
- }
-
- // if no spell checker, remove spell checker ui
- if (!IsSpellCheckerInstalled())
- {
- HideItem("spellingButton");
- HideItem("menu_checkspelling");
- RemoveItem("sep_checkspelling");
- }
-
- // Remove menu items (from overlay shared with HTML editor) in non-HTML.
- if (!IsHTMLEditor())
- {
- HideItem("insertAnchor");
- HideItem("insertImage");
- HideItem("insertHline");
- HideItem("insertTable");
- HideItem("insertHTML");
- HideItem("insertFormMenu");
- HideItem("fileExportToText");
- HideItem("viewFormatToolbar");
- HideItem("viewEditModeToolbar");
- }
-}
-
-function HideItem(id)
-{
- var item = document.getElementById(id);
- if (item)
- item.hidden = true;
-}
-
-function RemoveItem(id)
-{
- var item = document.getElementById(id);
- if (item)
- item.remove();
-}
-
-// Command Updating Strategy:
-// Don't update on on selection change, only when menu is displayed,
-// with this "oncreate" hander:
-function EditorInitTableMenu()
-{
- try {
- InitJoinCellMenuitem("menu_JoinTableCells");
- } catch (ex) {}
-
- // Set enable states for all table commands
- goUpdateTableMenuItems(document.getElementById("composerTableMenuItems"));
-}
-
-function InitJoinCellMenuitem(id)
-{
- // Change text on the "Join..." item depending if we
- // are joining selected cells or just cell to right
- // TODO: What to do about normal selection that crosses
- // table border? Try to figure out all cells
- // included in the selection?
- var menuText;
- var menuItem = document.getElementById(id);
- if (!menuItem) return;
-
- // Use "Join selected cells if there's more than 1 cell selected
- var numSelected;
- var foundElement;
-
- try {
- var tagNameObj = {};
- var countObj = {value:0}
- foundElement = GetCurrentTableEditor().getSelectedOrParentTableElement(tagNameObj, countObj);
- numSelected = countObj.value
- }
- catch(e) {}
- if (foundElement && numSelected > 1)
- menuText = GetString("JoinSelectedCells");
- else
- menuText = GetString("JoinCellToRight");
-
- menuItem.setAttribute("label",menuText);
- menuItem.setAttribute("accesskey",GetString("JoinCellAccesskey"));
-}
-
-function InitRemoveStylesMenuitems(removeStylesId, removeLinksId, removeNamedAnchorsId)
-{
- var editor = GetCurrentEditor();
- if (!editor)
- return;
-
- // Change wording of menuitems depending on selection
- var stylesItem = document.getElementById(removeStylesId);
- var linkItem = document.getElementById(removeLinksId);
-
- var isCollapsed = editor.selection.isCollapsed;
- if (stylesItem)
- {
- stylesItem.setAttribute("label", isCollapsed ? GetString("StopTextStyles") : GetString("RemoveTextStyles"));
- stylesItem.setAttribute("accesskey", GetString("RemoveTextStylesAccesskey"));
- }
- if (linkItem)
- {
- linkItem.setAttribute("label", isCollapsed ? GetString("StopLinks") : GetString("RemoveLinks"));
- linkItem.setAttribute("accesskey", GetString("RemoveLinksAccesskey"));
- // Note: disabling text style is a pain since there are so many - forget it!
-
- // Disable if not in a link, but always allow "Remove"
- // if selection isn't collapsed since we only look at anchor node
- try {
- SetElementEnabled(linkItem, !isCollapsed ||
- editor.getElementOrParentByTagName("href", null));
- } catch(e) {}
- }
- // Disable if selection is collapsed
- SetElementEnabledById(removeNamedAnchorsId, !isCollapsed);
-}
-
-function goUpdateTableMenuItems(commandset)
-{
- var editor = GetCurrentTableEditor();
- if (!editor)
- {
- dump("goUpdateTableMenuItems: too early, not initialized\n");
- return;
- }
-
- var enabled = false;
- var enabledIfTable = false;
-
- var flags = editor.flags;
- if (!(flags & nsIPlaintextEditor.eEditorReadonlyMask) &&
- IsEditingRenderedHTML())
- {
- var tagNameObj = { value: "" };
- var element;
- try {
- element = editor.getSelectedOrParentTableElement(tagNameObj, {value:0});
- }
- catch(e) {}
-
- if (element)
- {
- // Value when we need to have a selected table or inside a table
- enabledIfTable = true;
-
- // All others require being inside a cell or selected cell
- enabled = (tagNameObj.value == "td");
- }
- }
-
- // Loop through command nodes
- for (var i = 0; i < commandset.childNodes.length; i++)
- {
- var commandID = commandset.childNodes[i].getAttribute("id");
- if (commandID)
- {
- if (commandID == "cmd_InsertTable" ||
- commandID == "cmd_JoinTableCells" ||
- commandID == "cmd_SplitTableCell" ||
- commandID == "cmd_ConvertToTable")
- {
- // Call the update method in the command class
- goUpdateCommand(commandID);
- }
- // Directly set with the values calculated here
- else if (commandID == "cmd_DeleteTable" ||
- commandID == "cmd_NormalizeTable" ||
- commandID == "cmd_editTable" ||
- commandID == "cmd_TableOrCellColor" ||
- commandID == "cmd_SelectTable")
- {
- goSetCommandEnabled(commandID, enabledIfTable);
- } else {
- goSetCommandEnabled(commandID, enabled);
- }
- }
- }
-}
-
-//-----------------------------------------------------------------------------------
-// Helpers for inserting and editing tables:
-
-function IsInTable()
-{
- var editor = GetCurrentEditor();
- try {
- var flags = editor.flags;
- return (IsHTMLEditor() &&
- !(flags & nsIPlaintextEditor.eEditorReadonlyMask) &&
- IsEditingRenderedHTML() &&
- null != editor.getElementOrParentByTagName("table", null));
- } catch (e) {}
- return false;
-}
-
-function IsInTableCell()
-{
- try {
- var editor = GetCurrentEditor();
- var flags = editor.flags;
- return (IsHTMLEditor() &&
- !(flags & nsIPlaintextEditor.eEditorReadonlyMask) &&
- IsEditingRenderedHTML() &&
- null != editor.getElementOrParentByTagName("td", null));
- } catch (e) {}
- return false;
-
-}
-
-function IsSelectionInOneCell()
-{
- try {
- var editor = GetCurrentEditor();
- var selection = editor.selection;
-
- if (selection.rangeCount == 1)
- {
- // We have a "normal" single-range selection
- if (!selection.isCollapsed &&
- selection.anchorNode != selection.focusNode)
- {
- // Check if both nodes are within the same cell
- var anchorCell = editor.getElementOrParentByTagName("td", selection.anchorNode);
- var focusCell = editor.getElementOrParentByTagName("td", selection.focusNode);
- return (focusCell != null && anchorCell != null && (focusCell == anchorCell));
- }
- // Collapsed selection or anchor == focus (thus must be in 1 cell)
- return true;
- }
- } catch (e) {}
- return false;
-}
-
-// Call this with insertAllowed = true to allow inserting if not in existing table,
-// else use false to do nothing if not in a table
-function EditorInsertOrEditTable(insertAllowed)
-{
- if (IsInTable())
- {
- // Edit properties of existing table
- window.openDialog("chrome://editor/content/EdTableProps.xul", "_blank", "chrome,close,titlebar,modal", "","TablePanel");
- gContentWindow.focus();
- }
- else if (insertAllowed)
- {
- try {
- if (GetCurrentEditor().selection.isCollapsed)
- // If we have a caret, insert a blank table...
- EditorInsertTable();
- else
- // else convert the selection into a table
- goDoCommand("cmd_ConvertToTable");
- } catch (e) {}
- }
-}
-
-function EditorInsertTable()
-{
- // Insert a new table
- window.openDialog("chrome://editor/content/EdInsertTable.xul", "_blank", "chrome,close,titlebar,modal", "");
- gContentWindow.focus();
-}
-
-function EditorTableCellProperties()
-{
- if (!IsHTMLEditor())
- return;
-
- try {
- var cell = GetCurrentEditor().getElementOrParentByTagName("td", null);
- if (cell) {
- // Start Table Properties dialog on the "Cell" panel
- window.openDialog("chrome://editor/content/EdTableProps.xul", "_blank", "chrome,close,titlebar,modal", "", "CellPanel");
- gContentWindow.focus();
- }
- } catch (e) {}
-}
-
-function GetNumberOfContiguousSelectedRows()
-{
- if (!IsHTMLEditor())
- return 0;
-
- var rows = 0;
- try {
- var editor = GetCurrentTableEditor();
- var rowObj = { value: 0 };
- var colObj = { value: 0 };
- var cell = editor.getFirstSelectedCellInTable(rowObj, colObj);
- if (!cell)
- return 0;
-
- // We have at least one row
- rows++;
-
- var lastIndex = rowObj.value;
- do {
- cell = editor.getNextSelectedCell({value:0});
- if (cell)
- {
- editor.getCellIndexes(cell, rowObj, colObj);
- var index = rowObj.value;
- if (index == lastIndex + 1)
- {
- lastIndex = index;
- rows++;
- }
- }
- }
- while (cell);
- } catch (e) {}
-
- return rows;
-}
-
-function GetNumberOfContiguousSelectedColumns()
-{
- if (!IsHTMLEditor())
- return 0;
-
- var columns = 0;
- try {
- var editor = GetCurrentTableEditor();
- var colObj = { value: 0 };
- var rowObj = { value: 0 };
- var cell = editor.getFirstSelectedCellInTable(rowObj, colObj);
- if (!cell)
- return 0;
-
- // We have at least one column
- columns++;
-
- var lastIndex = colObj.value;
- do {
- cell = editor.getNextSelectedCell({value:0});
- if (cell)
- {
- editor.getCellIndexes(cell, rowObj, colObj);
- var index = colObj.value;
- if (index == lastIndex +1)
- {
- lastIndex = index;
- columns++;
- }
- }
- }
- while (cell);
- } catch (e) {}
-
- return columns;
-}
-
-function EditorOnFocus()
-{
- // Current window already has the InsertCharWindow
- if ("InsertCharWindow" in window && window.InsertCharWindow) return;
-
- // Find window with an InsertCharsWindow and switch association to this one
- var windowWithDialog = FindEditorWithInsertCharDialog();
- if (windowWithDialog)
- {
- // Switch the dialog to current window
- // this sets focus to dialog, so bring focus back to editor window
- if (SwitchInsertCharToThisWindow(windowWithDialog))
- top.document.commandDispatcher.focusedWindow.focus();
- }
-}
-
-function SwitchInsertCharToThisWindow(windowWithDialog)
-{
- if (windowWithDialog && "InsertCharWindow" in windowWithDialog &&
- windowWithDialog.InsertCharWindow)
- {
- // Move dialog association to the current window
- window.InsertCharWindow = windowWithDialog.InsertCharWindow;
- windowWithDialog.InsertCharWindow = null;
-
- // Switch the dialog's opener to current window's
- window.InsertCharWindow.opener = window;
-
- // Bring dialog to the forground
- window.InsertCharWindow.focus();
- return true;
- }
- return false;
-}
-
-function FindEditorWithInsertCharDialog()
-{
- try {
- // Find window with an InsertCharsWindow and switch association to this one
- let enumerator = Services.wm.getEnumerator(null);
-
- while (enumerator.hasMoreElements())
- {
- var tempWindow = enumerator.getNext();
-
- if (tempWindow != window && "InsertCharWindow" in tempWindow &&
- tempWindow.InsertCharWindow)
- {
- return tempWindow;
- }
- }
- }
- catch(e) {}
- return null;
-}
-
-function EditorFindOrCreateInsertCharWindow()
-{
- if ("InsertCharWindow" in window && window.InsertCharWindow)
- window.InsertCharWindow.focus();
- else
- {
- // Since we switch the dialog during EditorOnFocus(),
- // this should really never be found, but it's good to be sure
- var windowWithDialog = FindEditorWithInsertCharDialog();
- if (windowWithDialog)
- {
- SwitchInsertCharToThisWindow(windowWithDialog);
- }
- else
- {
- // The dialog will set window.InsertCharWindow to itself
- window.openDialog("chrome://editor/content/EdInsertChars.xul", "_blank", "chrome,close,titlebar", "");
- }
- }
-}
-
-// Find another HTML editor window to associate with the InsertChar dialog
-// or close it if none found (May be a mail composer)
-function SwitchInsertCharToAnotherEditorOrClose()
-{
- if ("InsertCharWindow" in window && window.InsertCharWindow)
- {
- var enumerator;
- try {
- enumerator = Services.wm.getEnumerator(null);
- }
- catch(e) {}
- if (!enumerator) return;
-
- // TODO: Fix this to search for command controllers and look for "cmd_InsertChars"
- // For now, detect just Web Composer and HTML Mail Composer
- while ( enumerator.hasMoreElements() )
- {
- var tempWindow = enumerator.getNext();
- if (tempWindow != window && tempWindow != window.InsertCharWindow &&
- "GetCurrentEditor" in tempWindow && tempWindow.GetCurrentEditor())
- {
- tempWindow.InsertCharWindow = window.InsertCharWindow;
- window.InsertCharWindow = null;
- tempWindow.InsertCharWindow.opener = tempWindow;
- return;
- }
- }
- // Didn't find another editor - close the dialog
- window.InsertCharWindow.close();
- }
-}
-
-function ResetStructToolbar()
-{
- gLastFocusNode = null;
- UpdateStructToolbar();
-}
-
-function newCommandListener(element)
-{
- return function() { return SelectFocusNodeAncestor(element); };
-}
-
-function newContextmenuListener(button, element)
-{
- return function() { return InitStructBarContextMenu(button, element); };
-}
-
-function UpdateStructToolbar()
-{
- var editor = GetCurrentEditor();
- if (!editor) return;
-
- var mixed = GetSelectionContainer();
- if (!mixed) return;
- var element = mixed.node;
- var oneElementSelected = mixed.oneElementSelected;
-
- if (!element) return;
-
- if (element == gLastFocusNode &&
- oneElementSelected == gLastFocusNodeWasSelected)
- return;
-
- gLastFocusNode = element;
- gLastFocusNodeWasSelected = mixed.oneElementSelected;
-
- var toolbar = document.getElementById("structToolbar");
- if (!toolbar) return;
- // We need to leave the <label> to flex the buttons to the left.
- for (let node of toolbar.querySelectorAll("toolbarbutton")) {
- node.remove();
- }
-
- toolbar.removeAttribute("label");
-
- if ( IsInHTMLSourceMode() ) {
- // we have destroyed the contents of the status bar and are
- // about to recreate it ; but we don't want to do that in
- // Source mode
- return;
- }
-
- var tag, button;
- var bodyElement = GetBodyElement();
- var isFocusNode = true;
- var tmp;
- do {
- tag = element.nodeName.toLowerCase();
-
- button = document.createElementNS(XUL_NS, "toolbarbutton");
- button.setAttribute("label", "<" + tag + ">");
- button.setAttribute("value", tag);
- button.setAttribute("context", "structToolbarContext");
- button.className = "struct-button";
-
- toolbar.insertBefore(button, toolbar.firstChild);
-
- button.addEventListener("command", newCommandListener(element), false);
-
- button.addEventListener("contextmenu", newContextmenuListener(button, element), false);
-
- if (isFocusNode && oneElementSelected) {
- button.setAttribute("checked", "true");
- isFocusNode = false;
- }
-
- tmp = element;
- element = element.parentNode;
-
- } while (tmp != bodyElement);
-}
-
-function SelectFocusNodeAncestor(element)
-{
- var editor = GetCurrentEditor();
- if (editor) {
- if (element == GetBodyElement())
- editor.selectAll();
- else
- editor.selectElement(element);
- }
- ResetStructToolbar();
-}
-
-function GetSelectionContainer()
-{
- var editor = GetCurrentEditor();
- if (!editor) return null;
-
- try {
- var selection = editor.selection;
- if (!selection) return null;
- }
- catch (e) { return null; }
-
- var result = { oneElementSelected:false };
-
- if (selection.isCollapsed) {
- result.node = selection.focusNode;
- }
- else {
- var rangeCount = selection.rangeCount;
- if (rangeCount == 1) {
- result.node = editor.getSelectedElement("");
- var range = selection.getRangeAt(0);
-
- // check for a weird case : when we select a piece of text inside
- // a text node and apply an inline style to it, the selection starts
- // at the end of the text node preceding the style and ends after the
- // last char of the style. Assume the style element is selected for
- // user's pleasure
- if (!result.node &&
- range.startContainer.nodeType == Node.TEXT_NODE &&
- range.startOffset == range.startContainer.length &&
- range.endContainer.nodeType == Node.TEXT_NODE &&
- range.endOffset == range.endContainer.length &&
- range.endContainer.nextSibling == null &&
- range.startContainer.nextSibling == range.endContainer.parentNode)
- result.node = range.endContainer.parentNode;
-
- if (!result.node) {
- // let's rely on the common ancestor of the selection
- result.node = range.commonAncestorContainer;
- }
- else {
- result.oneElementSelected = true;
- }
- }
- else {
- // assume table cells !
- var i, container = null;
- for (i = 0; i < rangeCount; i++) {
- range = selection.getRangeAt(i);
- if (!container) {
- container = range.startContainer;
- }
- else if (container != range.startContainer) {
- // all table cells don't belong to same row so let's
- // select the parent of all rows
- result.node = container.parentNode;
- break;
- }
- result.node = container;
- }
- }
- }
-
- // make sure we have an element here
- while (result.node.nodeType != Node.ELEMENT_NODE)
- result.node = result.node.parentNode;
-
- // and make sure the element is not a special editor node like
- // the <br> we insert in blank lines
- // and don't select anonymous content !!! (fix for bug 190279)
- while (result.node.hasAttribute("_moz_editor_bogus_node") ||
- editor.isAnonymousElement(result.node))
- result.node = result.node.parentNode;
-
- return result;
-}
-
-function FillInHTMLTooltipEditor(tooltip)
-{
- const XLinkNS = "http://www.w3.org/1999/xlink";
- var tooltipText = null;
- var node;
- if (IsInPreviewMode()) {
- for (node = document.tooltipNode; node; node = node.parentNode) {
- if (node.nodeType == Node.ELEMENT_NODE) {
- tooltipText = node.getAttributeNS(XLinkNS, "title");
- if (tooltipText && /\S/.test(tooltipText)) {
- tooltip.setAttribute("label", tooltipText);
- return true;
- }
- tooltipText = node.getAttribute("title");
- if (tooltipText && /\S/.test(tooltipText)) {
- tooltip.setAttribute("label", tooltipText);
- return true;
- }
- }
- }
- } else {
- for (node = document.tooltipNode; node; node = node.parentNode) {
- if (node instanceof Components.interfaces.nsIDOMHTMLImageElement ||
- node instanceof Components.interfaces.nsIDOMHTMLInputElement)
- tooltipText = node.getAttribute("src");
- else if (node instanceof Components.interfaces.nsIDOMHTMLAnchorElement)
- tooltipText = node.getAttribute("href") || node.name;
- if (tooltipText) {
- tooltip.setAttribute("label", tooltipText);
- return true;
- }
- }
- }
- return false;
-}
-
-function UpdateTOC()
-{
- window.openDialog("chrome://editor/content/EdInsertTOC.xul",
- "_blank", "chrome,close,modal,titlebar");
- window.content.focus();
-}
-
-function InitTOCMenu()
-{
- var elt = GetCurrentEditor().document.getElementById("mozToc");
- var createMenuitem = document.getElementById("insertTOCMenuitem");
- var updateMenuitem = document.getElementById("updateTOCMenuitem");
- var removeMenuitem = document.getElementById("removeTOCMenuitem");
- if (removeMenuitem && createMenuitem && updateMenuitem) {
- if (elt) {
- createMenuitem.setAttribute("disabled", "true");
- updateMenuitem.removeAttribute("disabled");
- removeMenuitem.removeAttribute("disabled");
- }
- else {
- createMenuitem.removeAttribute("disabled");
- removeMenuitem.setAttribute("disabled", "true");
- updateMenuitem.setAttribute("disabled", "true");
- }
- }
-}
-
-function RemoveTOC()
-{
- var theDocument = GetCurrentEditor().document;
- var elt = theDocument.getElementById("mozToc");
- if (elt) {
- elt.remove();
- }
-
- let anchorNodes = theDocument.querySelectorAll('a[name^="mozTocId"]');
- for (let node of anchorNodes) {
- if (node.parentNode) {
- node.remove();
- }
- }
-}
diff --git a/editor/ui/composer/content/editorApplicationOverlay.js b/editor/ui/composer/content/editorApplicationOverlay.js
deleted file mode 100644
index 131b81d0e..000000000
--- a/editor/ui/composer/content/editorApplicationOverlay.js
+++ /dev/null
@@ -1,161 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Implementations of nsIControllerCommand for composer commands */
-
-function initEditorContextMenuItems(aEvent)
-{
- var shouldShowEditPage = !gContextMenu.onImage && !gContextMenu.onLink && !gContextMenu.onTextInput && !gContextMenu.inDirList;
- gContextMenu.showItem( "context-editpage", shouldShowEditPage );
-
- var shouldShowEditLink = gContextMenu.onSaveableLink;
- gContextMenu.showItem( "context-editlink", shouldShowEditLink );
-
- // Hide the applications separator if there's no add-on apps present.
- gContextMenu.showItem("context-sep-apps", gContextMenu.shouldShowSeparator("context-sep-apps"));
-}
-
-function initEditorContextMenuListener(aEvent)
-{
- var popup = document.getElementById("contentAreaContextMenu");
- if (popup)
- popup.addEventListener("popupshowing", initEditorContextMenuItems, false);
-}
-
-addEventListener("load", initEditorContextMenuListener, false);
-
-function editDocument(aDocument)
-{
- if (!aDocument)
- aDocument = window.content.document;
-
- editPage(aDocument.URL);
-}
-
-function editPageOrFrame()
-{
- var focusedWindow = document.commandDispatcher.focusedWindow;
-
- // if the uri is a specific frame, grab it, else use the frameset uri
- // and let Composer handle error if necessary
- editPage(getContentFrameURI(focusedWindow));
-}
-
-function getContentFrameURI(aFocusedWindow)
-{
- var contentFrame = isContentFrame(aFocusedWindow) ?
- aFocusedWindow : window.content;
- return contentFrame.location.href;
-}
-
-// Any non-editor window wanting to create an editor with a URL
-// should use this instead of "window.openDialog..."
-// We must always find an existing window with requested URL
-function editPage(url, aFileType)
-{
- // aFileType is optional and needs to default to html.
- aFileType = aFileType || "html";
-
- // Always strip off "view-source:" and #anchors
- url = url.replace(/^view-source:/, "").replace(/#.*/, "");
-
- // if the current window is a browser window, then extract the current charset menu setting from the current
- // document and use it to initialize the new composer window...
-
- var wintype = document.documentElement.getAttribute('windowtype');
- var charsetArg;
-
- if (wintype == "navigator:browser" && content.document)
- charsetArg = "charset=" + content.document.characterSet;
-
- try {
- let uri = createURI(url, null, null);
-
- let enumerator = Services.wm.getEnumerator("composer:" + aFileType);
- let emptyWindow;
- while ( enumerator.hasMoreElements() )
- {
- var win = enumerator.getNext();
- if ( win && win.IsWebComposer())
- {
- if (CheckOpenWindowForURIMatch(uri, win))
- {
- // We found an editor with our url
- win.focus();
- return;
- }
- else if (!emptyWindow && win.PageIsEmptyAndUntouched())
- {
- emptyWindow = win;
- }
- }
- }
-
- if (emptyWindow)
- {
- // we have an empty window we can use
- if (aFileType == "html" && emptyWindow.IsInHTMLSourceMode())
- emptyWindow.SetEditMode(emptyWindow.PreviousNonSourceDisplayMode);
- emptyWindow.EditorLoadUrl(url);
- emptyWindow.focus();
- emptyWindow.SetSaveAndPublishUI(url);
- return;
- }
-
- // Create new Composer / Text Editor window.
- if (aFileType == "text" && ("EditorNewPlaintext" in window))
- EditorNewPlaintext(url, charsetArg);
- else
- NewEditorWindow(url, charsetArg);
-
- } catch(e) {}
-}
-
-function createURI(urlstring)
-{
- try {
- return Services.io.newURI(urlstring, null, null);
- } catch (e) {}
-
- return null;
-}
-
-function CheckOpenWindowForURIMatch(uri, win)
-{
- try {
- var contentWindow = win.content;
- var contentDoc = contentWindow.document;
- var htmlDoc = contentDoc.QueryInterface(Components.interfaces.nsIDOMHTMLDocument);
- var winuri = createURI(htmlDoc.URL);
- return winuri.equals(uri);
- } catch (e) {}
-
- return false;
-}
-
-function toEditor()
-{
- if (!CycleWindow("composer:html"))
- NewEditorWindow();
-}
-
-function NewEditorWindow(aUrl, aCharsetArg)
-{
- window.openDialog("chrome://editor/content",
- "_blank",
- "chrome,all,dialog=no",
- aUrl || "about:blank",
- aCharsetArg);
-}
-
-function NewEditorFromTemplate()
-{
- // XXX not implemented
-}
-
-function NewEditorFromDraft()
-{
- // XXX not implemented
-}
diff --git a/editor/ui/composer/content/editorMailOverlay.xul b/editor/ui/composer/content/editorMailOverlay.xul
deleted file mode 100644
index a52937149..000000000
--- a/editor/ui/composer/content/editorMailOverlay.xul
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-
-<!-- retrieve generic commands -->
-<?xul-overlay href="chrome://messenger/content/mailOverlay.xul"?>
-
-<overlay id="editorMailOverlay"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <!-- navigator specific commands -->
- <commandset id="tasksCommands">
- <!-- XXX insert commands here -->
- </commandset>
-
- <!-- navigator specific UI items -->
- <menupopup id="menu_NewPopup">
- <!-- XXX insert File->New Menu add-ins here -->
- </menupopup>
-
- <menupopup id="menu_FilePopup">
- <!-- XXX insert File Menu add-ins here -->
- </menupopup>
-</overlay>
-
diff --git a/editor/ui/composer/content/editorNavigatorOverlay.xul b/editor/ui/composer/content/editorNavigatorOverlay.xul
deleted file mode 100644
index f9907c7bd..000000000
--- a/editor/ui/composer/content/editorNavigatorOverlay.xul
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-
-<!-- retrieve generic commands -->
-<!-- <?xul-overlay href="chrome://messenger/content/mailOverlay.xul"?> -->
-
-<overlay id="editorNavigatorOverlay"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <!-- navigator specific commands -->
- <commandset id="tasksCommands">
- <!-- XXX insert commands here -->
- </commandset>
-
- <!-- navigator specific UI items -->
- <menupopup id="menu_NewPopup">
- <!-- XXX insert File->New Menu add-ins here -->
- </menupopup>
-
- <menupopup id="menu_FilePopup">
- <!-- XXX insert File Menu add-ins here -->
- </menupopup>
-</overlay>
-
diff --git a/editor/ui/composer/content/editorSmileyOverlay.xul b/editor/ui/composer/content/editorSmileyOverlay.xul
deleted file mode 100644
index 86441bc4b..000000000
--- a/editor/ui/composer/content/editorSmileyOverlay.xul
+++ /dev/null
@@ -1,108 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE overlay SYSTEM "chrome://editor/locale/editorSmileyOverlay.dtd">
-
-<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
- <!-- smiley menu -->
- <toolbarbutton id="smileButtonMenu"
- class="formatting-button"
- tooltiptext="&SmileButton.tooltip;"
- type="menu"
- observes="cmd_smiley">
- <menupopup id="smilyPopup">
- <menuitem class="smiley insert-smile menuitem-iconic" label="&smiley1Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-)' )"
- tooltiptext="&smiley1Cmd.tooltip;" />
- <menuitem class="smiley insert-frown menuitem-iconic" label="&smiley2Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-(' )"
- tooltiptext="&smiley2Cmd.tooltip;" />
- <menuitem class="smiley insert-wink menuitem-iconic" label="&smiley3Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ';-)' )"
- tooltiptext="&smiley3Cmd.tooltip;" />
- <menuitem class="smiley insert-tongue menuitem-iconic" label="&smiley4Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-P' )"
- tooltiptext="&smiley4Cmd.tooltip;" />
- <menuitem class="smiley insert-laughing menuitem-iconic" label="&smiley5Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-D' )"
- tooltiptext="&smiley5Cmd.tooltip;" />
- <menuitem class="smiley insert-embarrassed menuitem-iconic" label="&smiley6Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-[' )"
- tooltiptext="&smiley6Cmd.tooltip;" />
- <menuitem class="smiley insert-undecided menuitem-iconic" label="&smiley7Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-\\' )"
- tooltiptext="&smiley7Cmd.tooltip;" />
- <menuitem class="smiley insert-surprise menuitem-iconic" label="&smiley8Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', '=-O' )"
- tooltiptext="&smiley8Cmd.tooltip;" />
- <menuitem class="smiley insert-kiss menuitem-iconic" label="&smiley9Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-*' )"
- tooltiptext="&smiley9Cmd.tooltip;" />
- <menuitem class="smiley insert-yell menuitem-iconic" label="&smiley10Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', '>:o' )"
- tooltiptext="&smiley10Cmd.tooltip;" />
- <menuitem class="smiley insert-cool menuitem-iconic" label="&smiley11Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', '8-)' )"
- tooltiptext="&smiley11Cmd.tooltip;" />
- <menuitem class="smiley insert-money menuitem-iconic" label="&smiley12Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-$' )"
- tooltiptext="&smiley12Cmd.tooltip;" />
- <menuitem class="smiley insert-foot menuitem-iconic" label="&smiley13Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-!' )"
- tooltiptext="&smiley13Cmd.tooltip;" />
- <menuitem class="smiley insert-innocent menuitem-iconic" label="&smiley14Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', 'O:-)' )"
- tooltiptext="&smiley14Cmd.tooltip;" />
- <menuitem class="smiley insert-cry menuitem-iconic" label="&smiley15Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':\'(' )"
- tooltiptext="&smiley15Cmd.tooltip;" />
- <menuitem class="smiley insert-sealed menuitem-iconic" label="&smiley16Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-X' )"
- tooltiptext="&smiley16Cmd.tooltip;" />
-
- </menupopup>
- </toolbarbutton>
-
- <menu id="insertMenu">
- <menupopup id="insertMenuPopup">
- <menu id="insertSmiley" label="&insertSmiley.label;" accesskey="&insertSmiley.accesskey;" insertbefore="insertMenuSeparator">
- <menupopup id="smilyMenuPopup">
- <menuitem class="smiley insert-smile menuitem-iconic" label="&smiley1Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-)' )" accesskey="&smiley1Cmd.accesskey;"/>
- <menuitem class="smiley insert-frown menuitem-iconic" label="&smiley2Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-(' )" accesskey="&smiley2Cmd.accesskey;"/>
- <menuitem class="smiley insert-wink menuitem-iconic" label="&smiley3Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ';-)' )" accesskey="&smiley3Cmd.accesskey;"/>
- <menuitem class="smiley insert-tongue menuitem-iconic" label="&smiley4Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-P' )" accesskey="&smiley4Cmd.accesskey;"/>
- <menuitem class="smiley insert-laughing menuitem-iconic" label="&smiley5Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-D' )" accesskey="&smiley5Cmd.accesskey;"/>
- <menuitem class="smiley insert-embarrassed menuitem-iconic" label="&smiley6Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-[' )" accesskey="&smiley6Cmd.accesskey;"/>
- <menuitem class="smiley insert-undecided menuitem-iconic" label="&smiley7Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-\\' )" accesskey="&smiley7Cmd.accesskey;"/>
- <menuitem class="smiley insert-surprise menuitem-iconic" label="&smiley8Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', '=-O' )" accesskey="&smiley8Cmd.accesskey;"/>
- <menuitem class="smiley insert-kiss menuitem-iconic" label="&smiley9Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-*' )" accesskey="&smiley9Cmd.accesskey;"/>
- <menuitem class="smiley insert-yell menuitem-iconic" label="&smiley10Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', '>:o' )" accesskey="&smiley10Cmd.accesskey;"/>
- <menuitem class="smiley insert-cool menuitem-iconic" label="&smiley11Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', '8-)' )" accesskey="&smiley11Cmd.accesskey;"/>
- <menuitem class="smiley insert-money menuitem-iconic" label="&smiley12Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-$' )" accesskey="&smiley12Cmd.accesskey;"/>
- <menuitem class="smiley insert-foot menuitem-iconic" label="&smiley13Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-!' )" accesskey="&smiley13Cmd.accesskey;"/>
- <menuitem class="smiley insert-innocent menuitem-iconic" label="&smiley14Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', 'O:-)' )" accesskey="&smiley14Cmd.accesskey;"/>
- <menuitem class="smiley insert-cry menuitem-iconic" label="&smiley15Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':\'(' )" accesskey="&smiley15Cmd.accesskey;"/>
- <menuitem class="smiley insert-sealed menuitem-iconic" label="&smiley16Cmd.label;"
- oncommand="doStatefulCommand('cmd_smiley', ':-X' )" accesskey="&smiley16Cmd.accesskey;"/>
- </menupopup>
- </menu>
- </menupopup>
- </menu>
-</overlay>
diff --git a/editor/ui/composer/content/editorTasksOverlay.xul b/editor/ui/composer/content/editorTasksOverlay.xul
deleted file mode 100644
index 1a70d8c58..000000000
--- a/editor/ui/composer/content/editorTasksOverlay.xul
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE overlay SYSTEM "chrome://communicator/locale/tasksOverlay.dtd">
-
-<overlay id="editorTasksOverlay"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <script type="application/javascript"
- src="chrome://editor/content/editorApplicationOverlay.js"/>
-
- <keyset id="tasksKeys">
- <key id="key_editor" key="&editorCmd.commandkey;" command="Tasks:Editor" modifiers="accel"/>
- </keyset>
-
- <commandset id="tasksCommands">
- <command id="Tasks:Editor" oncommand="toEditor();"/>
- </commandset>
-
- <statusbarpanel id="component-bar">
- <toolbarbutton class="taskbutton" id="mini-comp" command="Tasks:Editor"
- tooltiptext="&taskComposer.tooltip;" insertafter="mini-nav"/>
- </statusbarpanel>
-
- <menupopup id="windowPopup">
- <menuitem label="&editorCmd.label;" accesskey="&editorCmd.accesskey;" key="key_editor" command="Tasks:Editor" id="tasksMenuEditor" insertafter="IMMenuItem,tasksMenuNavigator" class="menuitem-iconic icon-composer16 menu-iconic"/>
- </menupopup>
-
-</overlay>
-
diff --git a/editor/ui/composer/content/editorUtilities.js b/editor/ui/composer/content/editorUtilities.js
deleted file mode 100644
index cd57e8d72..000000000
--- a/editor/ui/composer/content/editorUtilities.js
+++ /dev/null
@@ -1,987 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-Components.utils.import("resource://gre/modules/Services.jsm");
-Components.utils.import("resource://gre/modules/AppConstants.jsm");
-
-/**** NAMESPACES ****/
-const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-
-// Each editor window must include this file
-// Variables shared by all dialogs:
-
-// Object to attach commonly-used widgets (all dialogs should use this)
-var gDialog = {};
-
-var kOutputEncodeBasicEntities = Components.interfaces.nsIDocumentEncoder.OutputEncodeBasicEntities;
-var kOutputEncodeHTMLEntities = Components.interfaces.nsIDocumentEncoder.OutputEncodeHTMLEntities;
-var kOutputEncodeLatin1Entities = Components.interfaces.nsIDocumentEncoder.OutputEncodeLatin1Entities;
-var kOutputEncodeW3CEntities = Components.interfaces.nsIDocumentEncoder.OutputEncodeW3CEntities;
-var kOutputFormatted = Components.interfaces.nsIDocumentEncoder.OutputFormatted;
-var kOutputLFLineBreak = Components.interfaces.nsIDocumentEncoder.OutputLFLineBreak;
-var kOutputSelectionOnly = Components.interfaces.nsIDocumentEncoder.OutputSelectionOnly;
-var kOutputWrap = Components.interfaces.nsIDocumentEncoder.OutputWrap;
-
-var gStringBundle;
-var gFilePickerDirectory;
-
-/************* Message dialogs ***************/
-
-// Optional: Caller may supply text to substitue for "Ok" and/or "Cancel"
-function ConfirmWithTitle(title, message, okButtonText, cancelButtonText)
-{
- let okFlag = okButtonText ? Services.prompt.BUTTON_TITLE_IS_STRING : Services.prompt.BUTTON_TITLE_OK;
- let cancelFlag = cancelButtonText ? Services.prompt.BUTTON_TITLE_IS_STRING : Services.prompt.BUTTON_TITLE_CANCEL;
-
- return Services.prompt.confirmEx(window, title, message,
- (okFlag * Services.prompt.BUTTON_POS_0) +
- (cancelFlag * Services.prompt.BUTTON_POS_1),
- okButtonText, cancelButtonText, null, null, {value:0}) == 0;
-}
-
-/************* String Utilities ***************/
-
-function GetString(name)
-{
- if (!gStringBundle)
- {
- try {
- gStringBundle = Services.strings.createBundle("chrome://editor/locale/editor.properties");
- } catch (ex) {}
- }
- if (gStringBundle)
- {
- try {
- return gStringBundle.GetStringFromName(name);
- } catch (e) {}
- }
- return null;
-}
-
-function GetFormattedString(aName, aVal)
-{
- if (!gStringBundle)
- {
- try {
- gStringBundle = Services.strings.createBundle("chrome://editor/locale/editor.properties");
- } catch (ex) {}
- }
- if (gStringBundle)
- {
- try {
- return gStringBundle.formatStringFromName(aName, [aVal], 1);
- } catch (e) {}
- }
- return null;
-}
-
-function TrimStringLeft(string)
-{
- if (!string)
- return "";
- return string.trimLeft();
-}
-
-function TrimStringRight(string)
-{
- if (!string)
- return "";
- return string.trimRight();
-}
-
-// Remove whitespace from both ends of a string
-function TrimString(string)
-{
- if (!string)
- return "";
- return string.trim();
-}
-
-function TruncateStringAtWordEnd(string, maxLength, addEllipses)
-{
- // Return empty if string is null, undefined, or the empty string
- if (!string)
- return "";
-
- // We assume they probably don't want whitespace at the beginning
- string = string.trimLeft();
- if (string.length <= maxLength)
- return string;
-
- // We need to truncate the string to maxLength or fewer chars
- if (addEllipses)
- maxLength -= 3;
- string = string.replace(RegExp("(.{0," + maxLength + "})\\s.*"), "$1")
-
- if (string.length > maxLength)
- string = string.slice(0, maxLength);
-
- if (addEllipses)
- string += "...";
- return string;
-}
-
-// Replace all whitespace characters with supplied character
-// E.g.: Use charReplace = " ", to "unwrap" the string by removing line-end chars
-// Use charReplace = "_" when you don't want spaces (like in a URL)
-function ReplaceWhitespace(string, charReplace)
-{
- return string.trim().replace(/\s+/g, charReplace);
-}
-
-// Replace whitespace with "_" and allow only HTML CDATA
-// characters: "a"-"z","A"-"Z","0"-"9", "_", ":", "-", ".",
-// and characters above ASCII 127
-function ConvertToCDATAString(string)
-{
- return string.replace(/\s+/g,"_").replace(/[^a-zA-Z0-9_\.\-\:\u0080-\uFFFF]+/g,'');
-}
-
-function GetSelectionAsText()
-{
- try {
- return GetCurrentEditor().outputToString("text/plain", kOutputSelectionOnly);
- } catch (e) {}
-
- return "";
-}
-
-
-/************* Get Current Editor and associated interfaces or info ***************/
-const nsIPlaintextEditor = Components.interfaces.nsIPlaintextEditor;
-const nsIHTMLEditor = Components.interfaces.nsIHTMLEditor;
-const nsITableEditor = Components.interfaces.nsITableEditor;
-const nsIEditorStyleSheets = Components.interfaces.nsIEditorStyleSheets;
-const nsIEditingSession = Components.interfaces.nsIEditingSession;
-
-function GetCurrentEditor()
-{
- // Get the active editor from the <editor> tag
- // XXX This will probably change if we support > 1 editor in main Composer window
- // (e.g. a plaintext editor for HTMLSource)
-
- // For dialogs: Search up parent chain to find top window with editor
- var editor;
- try {
- var editorElement = GetCurrentEditorElement();
- editor = editorElement.getEditor(editorElement.contentWindow);
-
- // Do QIs now so editor users won't have to figure out which interface to use
- // Using "instanceof" does the QI for us.
- editor instanceof Components.interfaces.nsIPlaintextEditor;
- editor instanceof Components.interfaces.nsIHTMLEditor;
- } catch (e) { dump (e)+"\n"; }
-
- return editor;
-}
-
-function GetCurrentTableEditor()
-{
- var editor = GetCurrentEditor();
- return (editor && (editor instanceof nsITableEditor)) ? editor : null;
-}
-
-function GetCurrentEditorElement()
-{
- var tmpWindow = window;
-
- do {
- // Get the <editor> element(s)
- let editorItem = tmpWindow.document.querySelector("editor");
-
- // This will change if we support > 1 editor element
- if (editorItem)
- return editorItem;
-
- tmpWindow = tmpWindow.opener;
- }
- while (tmpWindow);
-
- return null;
-}
-
-function GetCurrentCommandManager()
-{
- try {
- return GetCurrentEditorElement().commandManager;
- } catch (e) { dump (e)+"\n"; }
-
- return null;
-}
-
-function GetCurrentEditorType()
-{
- try {
- return GetCurrentEditorElement().editortype;
- } catch (e) { dump (e)+"\n"; }
-
- return "";
-}
-
-function IsHTMLEditor()
-{
- // We don't have an editorElement, just return false
- if (!GetCurrentEditorElement())
- return false;
-
- var editortype = GetCurrentEditorType();
- switch (editortype)
- {
- case "html":
- case "htmlmail":
- return true;
-
- case "text":
- case "textmail":
- return false
-
- default:
- dump("INVALID EDITOR TYPE: " + editortype + "\n");
- break;
- }
- return false;
-}
-
-function PageIsEmptyAndUntouched()
-{
- return IsDocumentEmpty() && !IsDocumentModified() && !IsHTMLSourceChanged();
-}
-
-function IsInHTMLSourceMode()
-{
- return (gEditorDisplayMode == kDisplayModeSource);
-}
-
-function IsInPreviewMode()
-{
- return (gEditorDisplayMode == kDisplayModePreview);
-}
-
-// are we editing HTML (i.e. neither in HTML source mode, nor editing a text file)
-function IsEditingRenderedHTML()
-{
- return IsHTMLEditor() && !IsInHTMLSourceMode();
-}
-
-function IsWebComposer()
-{
- return document.documentElement.id == "editorWindow";
-}
-
-function IsDocumentEditable()
-{
- try {
- return GetCurrentEditor().isDocumentEditable;
- } catch (e) {}
- return false;
-}
-
-function IsDocumentEmpty()
-{
- try {
- return GetCurrentEditor().documentIsEmpty;
- } catch (e) {}
- return false;
-}
-
-function IsDocumentModified()
-{
- try {
- return GetCurrentEditor().documentModified;
- } catch (e) {}
- return false;
-}
-
-function IsHTMLSourceChanged()
-{
- // gSourceTextEditor will not be defined if we're just a text editor.
- return gSourceTextEditor ? gSourceTextEditor.documentModified : false;
-}
-
-function newCommandParams()
-{
- try {
- return Components.classes["@mozilla.org/embedcomp/command-params;1"].createInstance(Components.interfaces.nsICommandParams);
- }
- catch(e) { dump("error thrown in newCommandParams: "+e+"\n"); }
- return null;
-}
-
-/************* General editing command utilities ***************/
-
-function GetDocumentTitle()
-{
- try {
- return new XPCNativeWrapper(GetCurrentEditor().document, "title").title;
- } catch (e) {}
-
- return "";
-}
-
-function SetDocumentTitle(title)
-{
-
- try {
- GetCurrentEditor().setDocumentTitle(title);
-
- // Update window title (doesn't work if called from a dialog)
- if ("UpdateWindowTitle" in window)
- window.UpdateWindowTitle();
- } catch (e) {}
-}
-
-var gAtomService;
-function GetAtomService()
-{
- gAtomService = Components.classes["@mozilla.org/atom-service;1"].getService(Components.interfaces.nsIAtomService);
-}
-
-function EditorGetTextProperty(property, attribute, value, firstHas, anyHas, allHas)
-{
- try {
- if (!gAtomService) GetAtomService();
- var propAtom = gAtomService.getAtom(property);
-
- return GetCurrentEditor().getInlinePropertyWithAttrValue(propAtom,
- attribute, value, firstHas, anyHas, allHas);
- }
- catch(e) {}
-}
-
-function EditorSetTextProperty(property, attribute, value)
-{
- try {
- if (!gAtomService) GetAtomService();
- var propAtom = gAtomService.getAtom(property);
-
- GetCurrentEditor().setInlineProperty(propAtom, attribute, value);
- if ("gContentWindow" in window)
- window.gContentWindow.focus();
- }
- catch(e) {}
-}
-
-function EditorRemoveTextProperty(property, attribute)
-{
- try {
- if (!gAtomService) GetAtomService();
- var propAtom = gAtomService.getAtom(property);
-
- GetCurrentEditor().removeInlineProperty(propAtom, attribute);
- if ("gContentWindow" in window)
- window.gContentWindow.focus();
- }
- catch(e) {}
-}
-
-/************* Element enbabling/disabling ***************/
-
-// this function takes an elementID and a flag
-// if the element can be found by ID, then it is either enabled (by removing "disabled" attr)
-// or disabled (setAttribute) as specified in the "doEnable" parameter
-function SetElementEnabledById(elementID, doEnable)
-{
- SetElementEnabled(document.getElementById(elementID), doEnable);
-}
-
-function SetElementEnabled(element, doEnable)
-{
- if ( element )
- {
- if ( doEnable )
- element.removeAttribute("disabled");
- else
- element.setAttribute("disabled", "true");
- }
- else
- {
- dump("Element not found in SetElementEnabled\n");
- }
-}
-
-/************* Services / Prefs ***************/
-
-function GetFileProtocolHandler()
-{
- let handler = Services.io.getProtocolHandler("file");
- return handler.QueryInterface(Components.interfaces.nsIFileProtocolHandler);
-}
-
-function GetStringPref(name)
-{
- try {
- return Services.prefs.getComplexValue(name, Components.interfaces.nsISupportsString).data;
- } catch (e) {}
- return "";
-}
-
-function SetStringPref(aPrefName, aPrefValue)
-{
- try {
- let str = Components.classes["@mozilla.org/supports-string;1"]
- .createInstance(Components.interfaces.nsISupportsString);
- str.data = aPrefValue;
- Services.prefs.setComplexValue(aPrefName, Components.interfaces.nsISupportsString, str);
- }
- catch(e) {}
-}
-
-// Set initial directory for a filepicker from URLs saved in prefs
-function SetFilePickerDirectory(filePicker, fileType)
-{
- if (filePicker)
- {
- try {
- // Save current directory so we can reset it in SaveFilePickerDirectory
- gFilePickerDirectory = filePicker.displayDirectory;
-
- let location = Services.prefs.getComplexValue("editor.lastFileLocation."+fileType,
- Components.interfaces.nsILocalFile);
- if (location)
- filePicker.displayDirectory = location;
- }
- catch(e) {}
- }
-}
-
-// Save the directory of the selected file to prefs
-function SaveFilePickerDirectory(filePicker, fileType)
-{
- if (filePicker && filePicker.file)
- {
- try {
- var fileDir;
- if (filePicker.file.parent)
- fileDir = filePicker.file.parent.QueryInterface(Components.interfaces.nsILocalFile);
-
- Services.prefs.setComplexValue("editor.lastFileLocation." + fileType,
- Components.interfaces.nsILocalFile, fileDir);
-
- Services.prefs.savePrefFile(null);
- } catch (e) {}
- }
-
- // Restore the directory used before SetFilePickerDirectory was called;
- // This reduces interference with Browser and other module directory defaults
- if (gFilePickerDirectory)
- filePicker.displayDirectory = gFilePickerDirectory;
-
- gFilePickerDirectory = null;
-}
-
-function GetDefaultBrowserColors()
-{
- var colors = { TextColor:0, BackgroundColor:0, LinkColor:0, ActiveLinkColor:0 , VisitedLinkColor:0 };
- var useSysColors = false;
- try { useSysColors = Services.prefs.getBoolPref("browser.display.use_system_colors"); } catch (e) {}
-
- if (!useSysColors)
- {
- try { colors.TextColor = Services.prefs.getCharPref("browser.display.foreground_color"); } catch (e) {}
-
- try { colors.BackgroundColor = Services.prefs.getCharPref("browser.display.background_color"); } catch (e) {}
- }
- // Use OS colors for text and background if explicitly asked or pref is not set
- if (!colors.TextColor)
- colors.TextColor = "windowtext";
-
- if (!colors.BackgroundColor)
- colors.BackgroundColor = "window";
-
- colors.LinkColor = Services.prefs.getCharPref("browser.anchor_color");
- colors.ActiveLinkColor = Services.prefs.getCharPref("browser.active_color");
- colors.VisitedLinkColor = Services.prefs.getCharPref("browser.visited_color");
-
- return colors;
-}
-
-/************* URL handling ***************/
-
-function TextIsURI(selectedText)
-{
- return selectedText && /^http:\/\/|^https:\/\/|^file:\/\/|^ftp:\/\/|^about:|^mailto:|^news:|^snews:|^telnet:|^ldap:|^ldaps:|^gopher:|^finger:|^javascript:/i.test(selectedText);
-}
-
-function IsUrlAboutBlank(urlString)
-{
- return (urlString == "about:blank");
-}
-
-function MakeRelativeUrl(url)
-{
- let inputUrl = url.trim();
- if (!inputUrl)
- return inputUrl;
-
- // Get the filespec relative to current document's location
- // NOTE: Can't do this if file isn't saved yet!
- var docUrl = GetDocumentBaseUrl();
- var docScheme = GetScheme(docUrl);
-
- // Can't relativize if no doc scheme (page hasn't been saved)
- if (!docScheme)
- return inputUrl;
-
- var urlScheme = GetScheme(inputUrl);
-
- // Do nothing if not the same scheme or url is already relativized
- if (docScheme != urlScheme)
- return inputUrl;
-
- // Host must be the same
- var docHost = GetHost(docUrl);
- var urlHost = GetHost(inputUrl);
- if (docHost != urlHost)
- return inputUrl;
-
-
- // Get just the file path part of the urls
- // XXX Should we use GetCurrentEditor().documentCharacterSet for 2nd param ?
- let docPath = Services.io.newURI(docUrl, GetCurrentEditor().documentCharacterSet, null).path;
- let urlPath = Services.io.newURI(inputUrl, GetCurrentEditor().documentCharacterSet, null).path;
-
- // We only return "urlPath", so we can convert the entire docPath for
- // case-insensitive comparisons.
- var doCaseInsensitive = (docScheme == "file" &&
- AppConstants.platform == "win");
-
- if (doCaseInsensitive)
- docPath = docPath.toLowerCase();
-
- // Get document filename before we start chopping up the docPath
- var docFilename = GetFilename(docPath);
-
- // Both url and doc paths now begin with "/"
- // Look for shared dirs starting after that
- urlPath = urlPath.slice(1);
- docPath = docPath.slice(1);
-
- var firstDirTest = true;
- var nextDocSlash = 0;
- var done = false;
-
- // Remove all matching subdirs common to both doc and input urls
- do {
- nextDocSlash = docPath.indexOf("\/");
- var nextUrlSlash = urlPath.indexOf("\/");
-
- if (nextUrlSlash == -1)
- {
- // We're done matching and all dirs in url
- // what's left is the filename
- done = true;
-
- // Remove filename for named anchors in the same file
- if (nextDocSlash == -1 && docFilename)
- {
- var anchorIndex = urlPath.indexOf("#");
- if (anchorIndex > 0)
- {
- var urlFilename = doCaseInsensitive ? urlPath.toLowerCase() : urlPath;
-
- if (urlFilename.startsWith(docFilename))
- urlPath = urlPath.slice(anchorIndex);
- }
- }
- }
- else if (nextDocSlash >= 0)
- {
- // Test for matching subdir
- var docDir = docPath.slice(0, nextDocSlash);
- var urlDir = urlPath.slice(0, nextUrlSlash);
- if (doCaseInsensitive)
- urlDir = urlDir.toLowerCase();
-
- if (urlDir == docDir)
- {
- // Remove matching dir+"/" from each path
- // and continue to next dir.
- docPath = docPath.slice(nextDocSlash+1);
- urlPath = urlPath.slice(nextUrlSlash+1);
- }
- else
- {
- // No match, we're done.
- done = true;
-
- // Be sure we are on the same local drive or volume
- // (the first "dir" in the path) because we can't
- // relativize to different drives/volumes.
- // UNIX doesn't have volumes, so we must not do this else
- // the first directory will be misinterpreted as a volume name.
- if (firstDirTest && docScheme == "file" &&
- AppConstants.platform != "unix")
- return inputUrl;
- }
- }
- else // No more doc dirs left, we're done
- done = true;
-
- firstDirTest = false;
- }
- while (!done);
-
- // Add "../" for each dir left in docPath
- while (nextDocSlash > 0)
- {
- urlPath = "../" + urlPath;
- nextDocSlash = docPath.indexOf("\/", nextDocSlash+1);
- }
- return urlPath;
-}
-
-function MakeAbsoluteUrl(url)
-{
- let resultUrl = TrimString(url);
- if (!resultUrl)
- return resultUrl;
-
- // Check if URL is already absolute, i.e., it has a scheme
- let urlScheme = GetScheme(resultUrl);
-
- if (urlScheme)
- return resultUrl;
-
- let docUrl = GetDocumentBaseUrl();
- let docScheme = GetScheme(docUrl);
-
- // Can't relativize if no doc scheme (page hasn't been saved)
- if (!docScheme)
- return resultUrl;
-
- // Make a URI object to use its "resolve" method
- let absoluteUrl = resultUrl;
- let docUri = Services.io.newURI(docUrl, GetCurrentEditor().documentCharacterSet, null);
-
- try {
- absoluteUrl = docUri.resolve(resultUrl);
- // This is deprecated and buggy!
- // If used, we must make it a path for the parent directory (remove filename)
- //absoluteUrl = IOService.resolveRelativePath(resultUrl, docUrl);
- } catch (e) {}
-
- return absoluteUrl;
-}
-
-// Get the HREF of the page's <base> tag or the document location
-// returns empty string if no base href and document hasn't been saved yet
-function GetDocumentBaseUrl()
-{
- try {
- var docUrl;
-
- // if document supplies a <base> tag, use that URL instead
- let base = GetCurrentEditor().document.querySelector("base");
- if (base)
- docUrl = base.getAttribute("href");
- if (!docUrl)
- docUrl = GetDocumentUrl();
-
- if (!IsUrlAboutBlank(docUrl))
- return docUrl;
- } catch (e) {}
- return "";
-}
-
-function GetDocumentUrl()
-{
- try {
- var aDOMHTMLDoc = GetCurrentEditor().document.QueryInterface(Components.interfaces.nsIDOMHTMLDocument);
- return aDOMHTMLDoc.URL;
- }
- catch (e) {}
- return "";
-}
-
-// Extract the scheme (e.g., 'file', 'http') from a URL string
-function GetScheme(urlspec)
-{
- var resultUrl = TrimString(urlspec);
- // Unsaved document URL has no acceptable scheme yet
- if (!resultUrl || IsUrlAboutBlank(resultUrl))
- return "";
-
- var scheme = "";
- try {
- // This fails if there's no scheme
- scheme = Services.io.extractScheme(resultUrl);
- } catch (e) {}
-
- return scheme ? scheme.toLowerCase() : "";
-}
-
-function GetHost(urlspec)
-{
- if (!urlspec)
- return "";
-
- var host = "";
- try {
- host = Services.io.newURI(urlspec, null, null).host;
- } catch (e) {}
-
- return host;
-}
-
-function GetUsername(urlspec)
-{
- if (!urlspec)
- return "";
-
- var username = "";
- try {
- username = Services.io.newURI(urlspec, null, null).username;
- } catch (e) {}
-
- return username;
-}
-
-function GetFilename(urlspec)
-{
- if (!urlspec || IsUrlAboutBlank(urlspec))
- return "";
-
- var filename;
-
- try {
- let uri = Services.io.newURI(urlspec, null, null);
- if (uri)
- {
- let url = uri.QueryInterface(Components.interfaces.nsIURL);
- if (url)
- filename = url.fileName;
- }
- } catch (e) {}
-
- return filename ? filename : "";
-}
-
-// Return the url without username and password
-// Optional output objects return extracted username and password strings
-// This uses just string routines via nsIIOServices
-function StripUsernamePassword(urlspec, usernameObj, passwordObj)
-{
- urlspec = TrimString(urlspec);
- if (!urlspec || IsUrlAboutBlank(urlspec))
- return urlspec;
-
- if (usernameObj)
- usernameObj.value = "";
- if (passwordObj)
- passwordObj.value = "";
-
- // "@" must exist else we will never detect username or password
- var atIndex = urlspec.indexOf("@");
- if (atIndex > 0)
- {
- try {
- let uri = Services.io.newURI(urlspec, null, null);
- let username = uri.username;
- let password = uri.password;
-
- if (usernameObj && username)
- usernameObj.value = username;
- if (passwordObj && password)
- passwordObj.value = password;
- if (username)
- {
- let usernameStart = urlspec.indexOf(username);
- if (usernameStart != -1)
- return urlspec.slice(0, usernameStart) + urlspec.slice(atIndex+1);
- }
- } catch (e) {}
- }
- return urlspec;
-}
-
-function StripPassword(urlspec, passwordObj)
-{
- urlspec = TrimString(urlspec);
- if (!urlspec || IsUrlAboutBlank(urlspec))
- return urlspec;
-
- if (passwordObj)
- passwordObj.value = "";
-
- // "@" must exist else we will never detect password
- var atIndex = urlspec.indexOf("@");
- if (atIndex > 0)
- {
- try {
- let password = Services.io.newURI(urlspec, null, null).password;
-
- if (passwordObj && password)
- passwordObj.value = password;
- if (password)
- {
- // Find last ":" before "@"
- let colon = urlspec.lastIndexOf(":", atIndex);
- if (colon != -1)
- {
- // Include the "@"
- return urlspec.slice(0, colon) + urlspec.slice(atIndex);
- }
- }
- } catch (e) {}
- }
- return urlspec;
-}
-
-// Version to use when you have an nsIURI object
-function StripUsernamePasswordFromURI(uri)
-{
- var urlspec = "";
- if (uri)
- {
- try {
- urlspec = uri.spec;
- var userPass = uri.userPass;
- if (userPass)
- {
- start = urlspec.indexOf(userPass);
- urlspec = urlspec.slice(0, start) + urlspec.slice(start+userPass.length+1);
- }
- } catch (e) {}
- }
- return urlspec;
-}
-
-function InsertUsernameIntoUrl(urlspec, username)
-{
- if (!urlspec || !username)
- return urlspec;
-
- try {
- let URI = Services.io.newURI(urlspec, GetCurrentEditor().documentCharacterSet, null);
- URI.username = username;
- return URI.spec;
- } catch (e) {}
-
- return urlspec;
-}
-
-function ConvertRGBColorIntoHEXColor(color)
-{
- if ( /rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/.test(color) ) {
- var r = Number(RegExp.$1).toString(16);
- if (r.length == 1) r = "0"+r;
- var g = Number(RegExp.$2).toString(16);
- if (g.length == 1) g = "0"+g;
- var b = Number(RegExp.$3).toString(16);
- if (b.length == 1) b = "0"+b;
- return "#"+r+g+b;
- }
- else
- {
- return color;
- }
-}
-
-/************* CSS ***************/
-
-function GetHTMLOrCSSStyleValue(element, attrName, cssPropertyName)
-{
- var value;
- if (Services.prefs.getBoolPref("editor.use_css") && IsHTMLEditor())
- value = element.style.getPropertyValue(cssPropertyName);
-
- if (!value)
- value = element.getAttribute(attrName);
-
- if (!value)
- return "";
-
- return value;
-}
-
-/************* Miscellaneous ***************/
-// Clone simple JS objects
-function Clone(obj)
-{
- var clone = {};
- for (var i in obj)
- {
- if (typeof obj[i] == 'object')
- clone[i] = Clone(obj[i]);
- else
- clone[i] = obj[i];
- }
- return clone;
-}
-
-/**
- * Utility funtions to handle shortended data: URLs in EdColorProps.js and EdImageOverlay.js.
- */
-
-/**
- * Is the passed in image URI a shortened data URI?
- * @return {bool}
- */
-function isImageDataShortened(aImageData) {
- return (/^data:/i.test(aImageData) && aImageData.includes("…"));
-}
-
-/**
- * Event handler for Copy or Cut
- * @param aEvent the event
- */
-function onCopyOrCutShortened(aEvent) {
- // Put the original data URI onto the clipboard in case the value
- // is a shortened data URI.
- let field = aEvent.target;
- let startPos = field.selectionStart;
- if (startPos == undefined)
- return;
- let endPos = field.selectionEnd;
- let selection = field.value.substring(startPos, endPos).trim();
-
- // Test that a) the user selected the whole value,
- // b) the value is a data URI,
- // c) it contains the ellipsis we added. Otherwise it could be
- // a new value that the user pasted in.
- if (selection == field.value.trim() && isImageDataShortened(selection)) {
- aEvent.clipboardData.setData("text/plain", field.fullDataURI);
- if (aEvent.type == "cut") {
- // We have to cut the selection manually. Since we tested that
- // everything was selected, we can just reset the field.
- field.value = "";
- }
- aEvent.preventDefault();
- }
-}
-
-/**
- * Set up element showing an image URI with a shortened version.
- * and add event handler for Copy or Cut.
- *
- * @param aImageData the data: URL of the image to be shortened.
- * Note: Original stored in 'aDialogField.fullDataURI'.
- * @param aDialogField The field of the dialog to contain the data.
- * @return {bool} URL was shortened?
- */
-function shortenImageData(aImageData, aDialogField) {
- let shortened = false;
- aDialogField.value = aImageData.replace(/^(data:.+;base64,)(.*)/i,
- function(match, nonDataPart, dataPart) {
- if (dataPart.length <= 35)
- return match;
-
- shortened = true;
- aDialogField.addEventListener("copy", onCopyOrCutShortened);
- aDialogField.addEventListener("cut", onCopyOrCutShortened);
- aDialogField.fullDataURI = aImageData;
- return nonDataPart + dataPart.substring(0, 5) + "…" +
- dataPart.substring(dataPart.length - 30);
- });
- return shortened;
-}
-
-/**
- * Return full data URIs for a shortened element.
- *
- * @param aDialogField The field of the dialog containing the data.
- */
-function restoredImageData(aDialogField) {
- return aDialogField.fullDataURI;
-}
diff --git a/editor/ui/composer/content/images/tag-anchor.gif b/editor/ui/composer/content/images/tag-anchor.gif
deleted file mode 100644
index ccb809b50..000000000
--- a/editor/ui/composer/content/images/tag-anchor.gif
+++ /dev/null
Binary files differ
diff --git a/editor/ui/dialogs/content/EdAEAttributes.js b/editor/ui/dialogs/content/EdAEAttributes.js
deleted file mode 100644
index a92a7b093..000000000
--- a/editor/ui/dialogs/content/EdAEAttributes.js
+++ /dev/null
@@ -1,1811 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// HTML Attributes object for "Name" menulist
-var gHTMLAttr = {};
-
-// JS Events Attributes object for "Name" menulist
-var gJSAttr = {};
-
-
-// Core HTML attribute values //
-// This is appended to Name menulist when "_core" is attribute name
-var gCoreHTMLAttr =
-[
- "^id",
- "class",
- "title"
-];
-
-// Core event attribute values //
-// This is appended to all JS menulists
-// except those elements having "noJSEvents"
-// as a value in their gJSAttr array.
-var gCoreJSEvents =
-[
- "onclick",
- "ondblclick",
- "onmousedown",
- "onmouseup",
- "onmouseover",
- "onmousemove",
- "onmouseout",
- "-",
- "onkeypress",
- "onkeydown",
- "onkeyup"
-];
-
-// Following are commonly-used strings
-
-// Alse accept: sRGB: #RRGGBB //
-var gHTMLColors =
-[
- "Aqua",
- "Black",
- "Blue",
- "Fuchsia",
- "Gray",
- "Green",
- "Lime",
- "Maroon",
- "Navy",
- "Olive",
- "Purple",
- "Red",
- "Silver",
- "Teal",
- "White",
- "Yellow"
-];
-
-var gHAlign =
-[
- "left",
- "center",
- "right"
-];
-
-var gHAlignJustify =
-[
- "left",
- "center",
- "right",
- "justify"
-];
-
-var gHAlignTableContent =
-[
- "left",
- "center",
- "right",
- "justify",
- "char"
-];
-
-var gVAlignTable =
-[
- "top",
- "middle",
- "bottom",
- "baseline"
-];
-
-var gTarget =
-[
- "_blank",
- "_self",
- "_parent",
- "_top"
-];
-
-// ================ HTML Attributes ================ //
-/* For each element, there is an array of attributes,
- whose name is the element name,
- used to fill the "Attribute Name" menulist.
- For each of those attributes, if they have a specific
- set of values, those are listed in an array named:
- "elementName_attName".
-
- In each values string, the following characters
- are signal to do input filtering:
- "#" Allow only integer values
- "%" Allow integer values or a number ending in "%"
- "+" Allow integer values and allow "+" or "-" as first character
- "!" Allow only one character
- "^" The first character can be only be A-Z, a-z, hyphen, underscore, colon or period
- "$" is an attribute required by HTML DTD
-*/
-
-/*
- Most elements have the "dir" attribute,
- so we use this value array
- for all elements instead of specifying
- separately for each element
-*/
-gHTMLAttr.all_dir =
-[
- "ltr",
- "rtl"
-];
-
-
-gHTMLAttr.a =
-[
- "charset",
- "type",
- "name",
- "href",
- "^hreflang",
- "target",
- "rel",
- "rev",
- "!accesskey",
- "shape", // with imagemap //
- "coords", // with imagemap //
- "#tabindex",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.a_target = gTarget;
-
-gHTMLAttr.a_rel =
-[
- "alternate",
- "stylesheet",
- "start",
- "next",
- "prev",
- "contents",
- "index",
- "glossary",
- "copyright",
- "chapter",
- "section",
- "subsection",
- "appendix",
- "help",
- "bookmark"
-];
-
-gHTMLAttr.a_rev =
-[
- "alternate",
- "stylesheet",
- "start",
- "next",
- "prev",
- "contents",
- "index",
- "glossary",
- "copyright",
- "chapter",
- "section",
- "subsection",
- "appendix",
- "help",
- "bookmark"
-];
-
-gHTMLAttr.a_shape =
-[
- "rect",
- "circle",
- "poly",
- "default"
-];
-
-gHTMLAttr.abbr =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.acronym =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.address =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-// this is deprecated //
-gHTMLAttr.applet =
-[
- "codebase",
- "archive",
- "code",
- "object",
- "alt",
- "name",
- "%$width",
- "%$height",
- "align",
- "#hspace",
- "#vspace",
- "-",
- "_core"
-];
-
-gHTMLAttr.applet_align =
-[
- "top",
- "middle",
- "bottom",
- "left",
- "right"
-];
-
-gHTMLAttr.area =
-[
- "shape",
- "coords",
- "href",
- "nohref",
- "target",
- "$alt",
- "#tabindex",
- "!accesskey",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.area_target = gTarget;
-
-gHTMLAttr.area_shape =
-[
- "rect",
- "circle",
- "poly",
- "default"
-];
-
-gHTMLAttr.area_nohref =
-[
- "nohref"
-];
-
-gHTMLAttr.b =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.base =
-[
- "href",
- "target"
-];
-
-gHTMLAttr.base_target = gTarget;
-
-// this is deprecated //
-gHTMLAttr.basefont =
-[
- "^id",
- "$size",
- "color",
- "face"
-];
-
-gHTMLAttr.basefont_color = gHTMLColors;
-
-gHTMLAttr.bdo =
-[
- "_core",
- "-",
- "^lang",
- "$dir"
-];
-
-gHTMLAttr.bdo_dir =
-[
- "ltr",
- "rtl"
-];
-
-gHTMLAttr.big =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.blockquote =
-[
- "cite",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.body =
-[
- "background",
- "bgcolor",
- "text",
- "link",
- "vlink",
- "alink",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.body_bgcolor = gHTMLColors;
-
-gHTMLAttr.body_text = gHTMLColors;
-
-gHTMLAttr.body_link = gHTMLColors;
-
-gHTMLAttr.body_vlink = gHTMLColors;
-
-gHTMLAttr.body_alink = gHTMLColors;
-
-gHTMLAttr.br =
-[
- "clear",
- "-",
- "_core"
-];
-
-gHTMLAttr.br_clear =
-[
- "none",
- "left",
- "all",
- "right"
-];
-
-gHTMLAttr.button =
-[
- "name",
- "value",
- "$type",
- "disabled",
- "#tabindex",
- "!accesskey",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.button_type =
-[
- "submit",
- "button",
- "reset"
-];
-
-gHTMLAttr.button_disabled =
-[
- "disabled"
-];
-
-gHTMLAttr.caption =
-[
- "align",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.caption_align =
-[
- "top",
- "bottom",
- "left",
- "right"
-];
-
-
-// this is deprecated //
-gHTMLAttr.center =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.cite =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.code =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.col =
-[
- "#$span",
- "%width",
- "align",
- "!char",
- "#charoff",
- "valign",
- "char",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.col_span =
-[
- "1" // default
-];
-
-gHTMLAttr.col_align = gHAlignTableContent;
-
-gHTMLAttr.col_valign =
-[
- "top",
- "middle",
- "bottom",
- "baseline"
-];
-
-
-gHTMLAttr.colgroup =
-[
- "#$span",
- "%width",
- "align",
- "!char",
- "#charoff",
- "valign",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.colgroup_span =
-[
- "1" // default
-];
-
-gHTMLAttr.colgroup_align = gHAlignTableContent;
-
-gHTMLAttr.colgroup_valign =
-[
- "top",
- "middle",
- "bottom",
- "baseline"
-];
-
-gHTMLAttr.dd =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.del =
-[
- "cite",
- "datetime",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.dfn =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-// this is deprecated //
-gHTMLAttr.dir =
-[
- "compact",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.dir_compact =
-[
- "compact"
-];
-
-gHTMLAttr.div =
-[
- "align",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.div_align = gHAlignJustify;
-
-gHTMLAttr.dl =
-[
- "compact",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.dl_compact =
-[
- "compact"
-];
-
-
-gHTMLAttr.dt =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.em =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.fieldset =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-// this is deprecated //
-gHTMLAttr.font =
-[
- "+size",
- "color",
- "face",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.font_color = gHTMLColors;
-
-gHTMLAttr.form =
-[
- "$action",
- "$method",
- "enctype",
- "accept",
- "name",
- "accept-charset",
- "target",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.form_method =
-[
- "get",
- "post"
-];
-
-gHTMLAttr.form_enctype =
-[
- "application/x-www-form-urlencoded"
-];
-
-gHTMLAttr.form_target = gTarget;
-
-gHTMLAttr.frame =
-[
- "longdesc",
- "name",
- "src",
- "#frameborder",
- "#marginwidth",
- "#marginheight",
- "noresize",
- "$scrolling"
-];
-
-gHTMLAttr.frame_frameborder =
-[
- "1",
- "0"
-];
-
-gHTMLAttr.frame_noresize =
-[
- "noresize"
-];
-
-gHTMLAttr.frame_scrolling =
-[
- "auto",
- "yes",
- "no"
-];
-
-
-gHTMLAttr.frameset =
-[
- "rows",
- "cols",
- "-",
- "_core"
-];
-
-gHTMLAttr.h1 =
-[
- "align",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.h1_align = gHAlignJustify;
-
-gHTMLAttr.h2 =
-[
- "align",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.h2_align = gHAlignJustify;
-
-gHTMLAttr.h3 =
-[
- "align",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.h3_align = gHAlignJustify;
-
-gHTMLAttr.h4 =
-[
- "align",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.h4_align = gHAlignJustify;
-
-
-gHTMLAttr.h5 =
-[
- "align",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.h5_align = gHAlignJustify;
-
-gHTMLAttr.h6 =
-[
- "align",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.h6_align = gHAlignJustify;
-
-gHTMLAttr.head =
-[
- "profile",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.hr =
-[
- "align",
- "noshade",
- "#size",
- "%width",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.hr_align = gHAlign;
-
-gHTMLAttr.hr_noshade =
-[
- "noshade"
-];
-
-
-gHTMLAttr.html =
-[
- "version",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.i =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.iframe =
-[
- "longdesc",
- "name",
- "src",
- "$frameborder",
- "marginwidth",
- "marginheight",
- "$scrolling",
- "align",
- "%height",
- "%width",
- "-",
- "_core"
-];
-
-gHTMLAttr.iframe_frameborder =
-[
- "1",
- "0"
-];
-
-gHTMLAttr.iframe_scrolling =
-[
- "auto",
- "yes",
- "no"
-];
-
-gHTMLAttr.iframe_align =
-[
- "top",
- "middle",
- "bottom",
- "left",
- "right"
-];
-
-gHTMLAttr.img =
-[
- "$src",
- "$alt",
- "longdesc",
- "name",
- "%height",
- "%width",
- "usemap",
- "ismap",
- "align",
- "#border",
- "#hspace",
- "#vspace",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.img_ismap =
-[
- "ismap"
-];
-
-gHTMLAttr.img_align =
-[
- "top",
- "middle",
- "bottom",
- "left",
- "right"
-];
-
-gHTMLAttr.input =
-[
- "$type",
- "name",
- "value",
- "checked",
- "disabled",
- "readonly",
- "#size",
- "#maxlength",
- "src",
- "alt",
- "usemap",
- "ismap",
- "#tabindex",
- "!accesskey",
- "accept",
- "align",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.input_type =
-[
- "text",
- "password",
- "checkbox",
- "radio",
- "submit",
- "reset",
- "file",
- "hidden",
- "image",
- "button"
-];
-
-gHTMLAttr.input_checked =
-[
- "checked"
-];
-
-gHTMLAttr.input_disabled =
-[
- "disabled"
-];
-
-gHTMLAttr.input_readonly =
-[
- "readonly"
-];
-
-
-gHTMLAttr.input_ismap =
-[
- "ismap"
-];
-
-
-gHTMLAttr.input_align =
-[
- "top",
- "middle",
- "bottom",
- "left",
- "right"
-];
-
-gHTMLAttr.ins =
-[
- "cite",
- "datetime",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.isindex =
-[
- "prompt",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.kbd =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.label =
-[
- "for",
- "!accesskey",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.legend =
-[
- "!accesskey",
- "align",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.legend_align =
-[
- "top",
- "bottom",
- "left",
- "right"
-];
-
-gHTMLAttr.li =
-[
- "type",
- "#value",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.li_type =
-[
- "disc",
- "square",
- "circle",
- "-",
- "1",
- "a",
- "A",
- "i",
- "I"
-];
-
-gHTMLAttr.link =
-[
- "charset",
- "href",
- "^hreflang",
- "type",
- "rel",
- "rev",
- "media",
- "target",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.link_target = gTarget;
-
-gHTMLAttr.link_rel =
-[
- "alternate",
- "stylesheet",
- "start",
- "next",
- "prev",
- "contents",
- "index",
- "glossary",
- "copyright",
- "chapter",
- "section",
- "subsection",
- "appendix",
- "help",
- "bookmark"
-];
-
-gHTMLAttr.link_rev =
-[
- "alternate",
- "stylesheet",
- "start",
- "next",
- "prev",
- "contents",
- "index",
- "glossary",
- "copyright",
- "chapter",
- "section",
- "subsection",
- "appendix",
- "help",
- "bookmark"
-];
-
-gHTMLAttr.map =
-[
- "$name",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.menu =
-[
- "compact",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.menu_compact =
-[
- "compact"
-];
-
-gHTMLAttr.meta =
-[
- "http-equiv",
- "name",
- "$content",
- "scheme",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.noframes =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.noscript =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.object =
-[
- "declare",
- "classid",
- "codebase",
- "data",
- "type",
- "codetype",
- "archive",
- "standby",
- "%height",
- "%width",
- "usemap",
- "name",
- "#tabindex",
- "align",
- "#border",
- "#hspace",
- "#vspace",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.object_declare =
-[
- "declare"
-];
-
-gHTMLAttr.object_align =
-[
- "top",
- "middle",
- "bottom",
- "left",
- "right"
-];
-
-gHTMLAttr.ol =
-[
- "type",
- "compact",
- "#start",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.ol_type =
-[
- "1",
- "a",
- "A",
- "i",
- "I"
-];
-
-gHTMLAttr.ol_compact =
-[
- "compact"
-];
-
-
-gHTMLAttr.optgroup =
-[
- "disabled",
- "$label",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.optgroup_disabled =
-[
- "disabled"
-];
-
-
-gHTMLAttr.option =
-[
- "selected",
- "disabled",
- "label",
- "value",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.option_selected =
-[
- "selected"
-];
-
-gHTMLAttr.option_disabled =
-[
- "disabled"
-];
-
-
-gHTMLAttr.p =
-[
- "align",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.p_align = gHAlignJustify;
-
-gHTMLAttr.param =
-[
- "^id",
- "$name",
- "value",
- "$valuetype",
- "type"
-];
-
-gHTMLAttr.param_valuetype =
-[
- "data",
- "ref",
- "object"
-];
-
-
-gHTMLAttr.pre =
-[
- "%width",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.q =
-[
- "cite",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.s =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.samp =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.script =
-[
- "charset",
- "$type",
- "language",
- "src",
- "defer"
-];
-
-gHTMLAttr.script_defer =
-[
- "defer"
-];
-
-
-gHTMLAttr.select =
-[
- "name",
- "#size",
- "multiple",
- "disabled",
- "#tabindex",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.select_multiple =
-[
- "multiple"
-];
-
-gHTMLAttr.select_disabled =
-[
- "disabled"
-];
-
-gHTMLAttr.small =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.span =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.strike =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.strong =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.style =
-[
- "$type",
- "media",
- "title",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.sub =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.sup =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.table =
-[
- "summary",
- "%width",
- "#border",
- "frame",
- "rules",
- "#cellspacing",
- "#cellpadding",
- "align",
- "bgcolor",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.table_frame =
-[
- "void",
- "above",
- "below",
- "hsides",
- "lhs",
- "rhs",
- "vsides",
- "box",
- "border"
-];
-
-gHTMLAttr.table_rules =
-[
- "none",
- "groups",
- "rows",
- "cols",
- "all"
-];
-
-// Note; This is alignment of the table,
-// not table contents, like all other table child elements
-gHTMLAttr.table_align = gHAlign;
-
-gHTMLAttr.table_bgcolor = gHTMLColors;
-
-gHTMLAttr.tbody =
-[
- "align",
- "!char",
- "#charoff",
- "valign",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.tbody_align = gHAlignTableContent;
-
-gHTMLAttr.tbody_valign = gVAlignTable;
-
-gHTMLAttr.td =
-[
- "abbr",
- "axis",
- "headers",
- "scope",
- "$#rowspan",
- "$#colspan",
- "align",
- "!char",
- "#charoff",
- "valign",
- "nowrap",
- "bgcolor",
- "%width",
- "%height",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.td_scope =
-[
- "row",
- "col",
- "rowgroup",
- "colgroup"
-];
-
-gHTMLAttr.td_rowspan =
-[
- "1" // default
-];
-
-gHTMLAttr.td_colspan =
-[
- "1" // default
-];
-
-gHTMLAttr.td_align = gHAlignTableContent;
-
-gHTMLAttr.td_valign = gVAlignTable;
-
-gHTMLAttr.td_nowrap =
-[
- "nowrap"
-];
-
-gHTMLAttr.td_bgcolor = gHTMLColors;
-
-gHTMLAttr.textarea =
-[
- "name",
- "$#rows",
- "$#cols",
- "disabled",
- "readonly",
- "#tabindex",
- "!accesskey",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.textarea_disabled =
-[
- "disabled"
-];
-
-gHTMLAttr.textarea_readonly =
-[
- "readonly"
-];
-
-
-gHTMLAttr.tfoot =
-[
- "align",
- "!char",
- "#charoff",
- "valign",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.tfoot_align = gHAlignTableContent;
-
-gHTMLAttr.tfoot_valign = gVAlignTable;
-
-gHTMLAttr.th =
-[
- "abbr",
- "axis",
- "headers",
- "scope",
- "$#rowspan",
- "$#colspan",
- "align",
- "!char",
- "#charoff",
- "valign",
- "nowrap",
- "bgcolor",
- "%width",
- "%height",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.th_scope =
-[
- "row",
- "col",
- "rowgroup",
- "colgroup"
-];
-
-gHTMLAttr.th_rowspan =
-[
- "1" // default
-];
-
-gHTMLAttr.th_colspan =
-[
- "1" // default
-];
-
-gHTMLAttr.th_align = gHAlignTableContent;
-
-gHTMLAttr.th_valign = gVAlignTable;
-
-gHTMLAttr.th_nowrap =
-[
- "nowrap"
-];
-
-gHTMLAttr.th_bgcolor = gHTMLColors;
-
-gHTMLAttr.thead =
-[
- "align",
- "!char",
- "#charoff",
- "valign",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.thead_align = gHAlignTableContent;
-
-gHTMLAttr.thead_valign = gVAlignTable;
-
-gHTMLAttr.title =
-[
- "^lang",
- "dir"
-];
-
-gHTMLAttr.tr =
-[
- "align",
- "!char",
- "#charoff",
- "valign",
- "bgcolor",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.tr_align = gHAlignTableContent;
-
-gHTMLAttr.tr_valign = gVAlignTable;
-
-gHTMLAttr.tr_bgcolor = gHTMLColors;
-
-gHTMLAttr.tt =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.u =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-gHTMLAttr.ul =
-[
- "type",
- "compact",
- "-",
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-gHTMLAttr.ul_type =
-[
- "disc",
- "square",
- "circle"
-];
-
-gHTMLAttr.ul_compact =
-[
- "compact"
-];
-
-
-// Prefix with "_" since this is reserved (it's stripped out)
-gHTMLAttr._var =
-[
- "_core",
- "-",
- "^lang",
- "dir"
-];
-
-// ================ JS Attributes ================ //
-// These are element specif even handlers.
-/* Most all elements use gCoreJSEvents, so those
- are assumed except for those listed here with "noEvents"
-*/
-
-gJSAttr.a =
-[
- "onfocus",
- "onblur"
-];
-
-gJSAttr.area =
-[
- "onfocus",
- "onblur"
-];
-
-gJSAttr.body =
-[
- "onload",
- "onupload"
-];
-
-gJSAttr.button =
-[
- "onfocus",
- "onblur"
-];
-
-gJSAttr.form =
-[
- "onsubmit",
- "onreset"
-];
-
-gJSAttr.frameset =
-[
- "onload",
- "onunload"
-];
-
-gJSAttr.input =
-[
- "onfocus",
- "onblur",
- "onselect",
- "onchange"
-];
-
-gJSAttr.label =
-[
- "onfocus",
- "onblur"
-];
-
-gJSAttr.select =
-[
- "onfocus",
- "onblur",
- "onchange"
-];
-
-gJSAttr.textarea =
-[
- "onfocus",
- "onblur",
- "onselect",
- "onchange"
-];
-
-// Elements that don't have JSEvents:
-gJSAttr.font =
-[
- "noJSEvents"
-];
-
-gJSAttr.applet =
-[
- "noJSEvents"
-];
-
-gJSAttr.isindex =
-[
- "noJSEvents"
-];
-
-gJSAttr.iframe =
-[
- "noJSEvents"
-];
-
diff --git a/editor/ui/dialogs/content/EdAECSSAttributes.js b/editor/ui/dialogs/content/EdAECSSAttributes.js
deleted file mode 100644
index 9cb05c9a1..000000000
--- a/editor/ui/dialogs/content/EdAECSSAttributes.js
+++ /dev/null
@@ -1,144 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// build attribute list in tree form from element attributes
-function BuildCSSAttributeTable()
-{
- var style = gElement.style;
- if (style == undefined)
- {
- dump("Inline styles undefined\n");
- return;
- }
-
- var declLength = style.length;
-
- if (declLength == undefined || declLength == 0)
- {
- if (declLength == undefined) {
- dump("Failed to query the number of inline style declarations\n");
- }
-
- return;
- }
-
- if (declLength > 0)
- {
- for (var i = 0; i < declLength; ++i)
- {
- var name = style.item(i);
- var value = style.getPropertyValue(name);
- AddTreeItem( name, value, "CSSAList", CSSAttrs );
- }
- }
-
- ClearCSSInputWidgets();
-}
-
-function onChangeCSSAttribute()
-{
- var name = TrimString(gDialog.AddCSSAttributeNameInput.value);
- if ( !name )
- return;
-
- var value = TrimString(gDialog.AddCSSAttributeValueInput.value);
-
- // First try to update existing attribute
- // If not found, add new attribute
- if ( !UpdateExistingAttribute( name, value, "CSSAList" ) && value)
- AddTreeItem( name, value, "CSSAList", CSSAttrs );
-}
-
-function ClearCSSInputWidgets()
-{
- gDialog.AddCSSAttributeTree.view.selection.clearSelection();
- gDialog.AddCSSAttributeNameInput.value ="";
- gDialog.AddCSSAttributeValueInput.value = "";
- SetTextboxFocus(gDialog.AddCSSAttributeNameInput);
-}
-
-function onSelectCSSTreeItem()
-{
- if (!gDoOnSelectTree)
- return;
-
- var tree = gDialog.AddCSSAttributeTree;
- if (tree && tree.view.selection.count)
- {
- gDialog.AddCSSAttributeNameInput.value = GetTreeItemAttributeStr(getSelectedItem(tree));
- gDialog.AddCSSAttributeValueInput.value = GetTreeItemValueStr(getSelectedItem(tree));
- }
-}
-
-function onInputCSSAttributeName()
-{
- var attName = TrimString(gDialog.AddCSSAttributeNameInput.value).toLowerCase();
- var newValue = "";
-
- var existingValue = GetAndSelectExistingAttributeValue(attName, "CSSAList");
- if (existingValue)
- newValue = existingValue;
-
- gDialog.AddCSSAttributeValueInput.value = newValue;
-}
-
-function editCSSAttributeValue(targetCell)
-{
- if (IsNotTreeHeader(targetCell))
- gDialog.AddCSSAttributeValueInput.inputField.select();
-}
-
-function UpdateCSSAttributes()
-{
- var CSSAList = document.getElementById("CSSAList");
- var styleString = "";
- for(var i = 0; i < CSSAList.childNodes.length; i++)
- {
- var item = CSSAList.childNodes[i];
- var name = GetTreeItemAttributeStr(item);
- var value = GetTreeItemValueStr(item);
- // this code allows users to be sloppy in typing in values, and enter
- // things like "foo: " and "bar;". This will trim off everything after the
- // respective character.
- if (name.includes(":"))
- name = name.substring(0, name.lastIndexOf(":"));
- if (value.includes(";"))
- value = value.substring(0, value.lastIndexOf(";"));
- if (i == (CSSAList.childNodes.length - 1))
- styleString += name + ": " + value + ";"; // last property
- else
- styleString += name + ": " + value + "; ";
- }
- if (styleString)
- {
- // Use editor transactions if modifying the element directly in the document
- doRemoveAttribute("style");
- doSetAttribute("style", styleString); // NOTE BUG 18894!!!
- }
- else if (gElement.getAttribute("style"))
- doRemoveAttribute("style");
-}
-
-function RemoveCSSAttribute()
-{
- // We only allow 1 selected item
- if (gDialog.AddCSSAttributeTree.view.selection.count)
- {
- // Remove the item from the tree
- // We always rebuild complete "style" string,
- // so no list of "removed" items
- getSelectedItem(gDialog.AddCSSAttributeTree).remove();
-
- ClearCSSInputWidgets();
- }
-}
-
-function SelectCSSTree( index )
-{
- gDoOnSelectTree = false;
- try {
- gDialog.AddCSSAttributeTree.selectedIndex = index;
- } catch (e) {}
- gDoOnSelectTree = true;
-}
diff --git a/editor/ui/dialogs/content/EdAEHTMLAttributes.js b/editor/ui/dialogs/content/EdAEHTMLAttributes.js
deleted file mode 100644
index a0a0d450d..000000000
--- a/editor/ui/dialogs/content/EdAEHTMLAttributes.js
+++ /dev/null
@@ -1,366 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-function BuildHTMLAttributeNameList()
-{
- gDialog.AddHTMLAttributeNameInput.removeAllItems();
-
- var elementName = gElement.localName;
- var attNames = gHTMLAttr[elementName];
-
- if (attNames && attNames.length)
- {
- var menuitem;
-
- for (var i = 0; i < attNames.length; i++)
- {
- var name = attNames[i];
-
- if (name == "_core")
- {
- // Signal to append the common 'core' attributes.
- for (var j = 0; j < gCoreHTMLAttr.length; j++)
- {
- name = gCoreHTMLAttr[j];
-
- // only filtering rule used for core attributes as of 8-20-01
- // Add more rules if necessary.
- if (name.includes("^"))
- {
- menuitem = gDialog.AddHTMLAttributeNameInput.appendItem(name.replace(/\^/g, ""));
- menuitem.setAttribute("limitFirstChar", "true");
- }
- else
- gDialog.AddHTMLAttributeNameInput.appendItem(name);
- }
- }
- else if (name == "-")
- {
- // Signal for separator
- var popup = gDialog.AddHTMLAttributeNameInput.firstChild;
- if (popup)
- {
- var sep = document.createElementNS(XUL_NS, "menuseparator");
- if (sep)
- popup.appendChild(sep);
- }
- }
- else
- {
- // Get information about value filtering
- let forceOneChar = name.includes("!");
- let forceInteger = name.includes("#");
- let forceSignedInteger = name.includes("+");
- let forceIntOrPercent = name.includes("%");
- let limitFirstChar = name.includes("\^");
- //let required = name.includes("$");
-
- // Strip flag characters
- name = name.replace(/[!^#%$+]/g, "");
-
- menuitem = gDialog.AddHTMLAttributeNameInput.appendItem(name);
- if (menuitem)
- {
- // Signify "required" attributes by special style
- //TODO: Don't do this until next version, when we add
- // explanatory text and an 'Autofill Required Attributes' button
- //if (required)
- // menuitem.setAttribute("class", "menuitem-highlight-1");
-
- // Set flags to filter value input
- if (forceOneChar)
- menuitem.setAttribute("forceOneChar","true");
- if (limitFirstChar)
- menuitem.setAttribute("limitFirstChar", "true");
- if (forceInteger)
- menuitem.setAttribute("forceInteger", "true");
- if (forceSignedInteger)
- menuitem.setAttribute("forceSignedInteger", "true");
- if (forceIntOrPercent)
- menuitem.setAttribute("forceIntOrPercent", "true");
- }
- }
- }
- }
-}
-
-// build attribute list in tree form from element attributes
-function BuildHTMLAttributeTable()
-{
- var nodeMap = gElement.attributes;
- var i;
- if (nodeMap.length > 0)
- {
- var added = false;
- for(i = 0; i < nodeMap.length; i++)
- {
- let name = nodeMap[i].name.trim().toLowerCase();
- if ( CheckAttributeNameSimilarity( nodeMap[i].nodeName, HTMLAttrs ) ||
- name.startsWith("on") || name == "style" ) {
- continue; // repeated or non-HTML attribute, ignore this one and go to next
- }
- if (!name.startsWith("_moz") &&
- AddTreeItem(name, nodeMap[i].value, "HTMLAList", HTMLAttrs))
- {
- added = true;
- }
- }
-
- if (added)
- SelectHTMLTree(0);
- }
-}
-
-function ClearHTMLInputWidgets()
-{
- gDialog.AddHTMLAttributeTree.view.selection.clearSelection();
- gDialog.AddHTMLAttributeNameInput.value ="";
- gDialog.AddHTMLAttributeValueInput.value = "";
- SetTextboxFocus(gDialog.AddHTMLAttributeNameInput);
-}
-
-function onSelectHTMLTreeItem()
-{
- if (!gDoOnSelectTree)
- return;
-
- var tree = gDialog.AddHTMLAttributeTree;
- if (tree && tree.view.selection.count)
- {
- var inputName = TrimString(gDialog.AddHTMLAttributeNameInput.value).toLowerCase();
- var selectedItem = getSelectedItem(tree);
- var selectedName = selectedItem.firstChild.firstChild.getAttribute("label");
-
- if (inputName == selectedName)
- {
- // Already editing selected name - just update the value input
- gDialog.AddHTMLAttributeValueInput.value = GetTreeItemValueStr(selectedItem);
- }
- else
- {
- gDialog.AddHTMLAttributeNameInput.value = selectedName;
-
- // Change value input based on new selected name
- onInputHTMLAttributeName();
- }
- }
-}
-
-function onInputHTMLAttributeName()
-{
- let attName = gDialog.AddHTMLAttributeNameInput.value.toLowerCase().trim();
-
- // Clear value widget, but prevent triggering update in tree
- gUpdateTreeValue = false;
- gDialog.AddHTMLAttributeValueInput.value = "";
- gUpdateTreeValue = true;
-
- if (attName)
- {
- // Get value list for current attribute name
- var valueListName;
-
- // Most elements have the "dir" attribute,
- // so we have just one array for the allowed values instead
- // requiring duplicate entries for each element in EdAEAttributes.js
- if (attName == "dir")
- valueListName = "all_dir";
- else
- valueListName = gElement.localName + "_" + attName;
-
- // Strip off leading "_" we sometimes use (when element name is reserved word)
- if (valueListName.startsWith("_"))
- valueListName = valueListName.slice(1);
-
- var newValue = "";
- var listLen = 0;
-
- // Index to which widget we were using to edit the value
- var deckIndex = gDialog.AddHTMLAttributeValueDeck.getAttribute("selectedIndex");
-
- if (valueListName in gHTMLAttr)
- {
- var valueList = gHTMLAttr[valueListName];
-
- listLen = valueList.length;
- if (listLen == 1)
- newValue = valueList[0];
-
- // Note: For case where "value list" is actually just
- // one (default) item, don't use menulist for that
- if (listLen > 1)
- {
- gDialog.AddHTMLAttributeValueMenulist.removeAllItems();
-
- if (deckIndex != "1")
- {
- // Switch to using editable menulist
- gDialog.AddHTMLAttributeValueInput = gDialog.AddHTMLAttributeValueMenulist;
- gDialog.AddHTMLAttributeValueDeck.setAttribute("selectedIndex", "1");
- }
- // Rebuild the list
- for (var i = 0; i < listLen; i++)
- {
- if (valueList[i] == "-")
- {
- // Signal for separator
- var popup = gDialog.AddHTMLAttributeValueInput.firstChild;
- if (popup)
- {
- var sep = document.createElementNS(XUL_NS, "menuseparator");
- if (sep)
- popup.appendChild(sep);
- }
- } else {
- gDialog.AddHTMLAttributeValueMenulist.appendItem(valueList[i]);
- }
- }
- }
- }
-
- if (listLen <= 1 && deckIndex != "0")
- {
- // No list: Use textbox for input instead
- gDialog.AddHTMLAttributeValueInput = gDialog.AddHTMLAttributeValueTextbox;
- gDialog.AddHTMLAttributeValueDeck.setAttribute("selectedIndex", "0");
- }
-
- // If attribute already exists in tree, use associated value,
- // else use default found above
- var existingValue = GetAndSelectExistingAttributeValue(attName, "HTMLAList");
- if (existingValue)
- newValue = existingValue;
-
- gDialog.AddHTMLAttributeValueInput.value = newValue;
-
- if (!existingValue)
- onInputHTMLAttributeValue();
- }
-}
-
-function onInputHTMLAttributeValue()
-{
- if (!gUpdateTreeValue)
- return;
-
- var name = TrimString(gDialog.AddHTMLAttributeNameInput.value);
- if (!name)
- return;
-
- // Trim spaces only from left since we must allow spaces within the string
- // (we always reset the input field's value below)
- var value = TrimStringLeft(gDialog.AddHTMLAttributeValueInput.value);
- if (value)
- {
- // Do value filtering based on type of attribute
- // (Do not use "forceInteger()" to avoid multiple
- // resetting of input's value and flickering)
- var selectedItem = gDialog.AddHTMLAttributeNameInput.selectedItem;
-
- if (selectedItem)
- {
- if ( selectedItem.getAttribute("forceOneChar") == "true" &&
- value.length > 1 )
- value = value.slice(0, 1);
-
- if ( selectedItem.getAttribute("forceIntOrPercent") == "true" )
- {
- // Allow integer with optional "%" as last character
- var percent = TrimStringRight(value).slice(-1);
- value = value.replace(/\D+/g,"");
- if (percent == "%")
- value += percent;
- }
- else if ( selectedItem.getAttribute("forceInteger") == "true" )
- {
- value = value.replace(/\D+/g,"");
- }
- else if ( selectedItem.getAttribute("forceSignedInteger") == "true" )
- {
- // Allow integer with optional "+" or "-" as first character
- var sign = value[0];
- value = value.replace(/\D+/g,"");
- if (sign == "+" || sign == "-")
- value = sign + value;
- }
-
- // Special case attributes
- if (selectedItem.getAttribute("limitFirstChar") == "true")
- {
- // Limit first character to letter, and all others to
- // letters, numbers, and a few others
- value = value.replace(/^[^a-zA-Z\u0080-\uFFFF]/, "").replace(/[^a-zA-Z0-9_\.\-\:\u0080-\uFFFF]+/g,'');
- }
-
- // Update once only if it changed
- if (value != gDialog.AddHTMLAttributeValueInput.value)
- gDialog.AddHTMLAttributeValueInput.value = value;
- }
- }
-
- // Update value in the tree list
- // If not found, add new attribute
- if (!UpdateExistingAttribute(name, value, "HTMLAList") && value)
- AddTreeItem(name, value, "HTMLAList", HTMLAttrs);
-}
-
-function editHTMLAttributeValue(targetCell)
-{
- if (IsNotTreeHeader(targetCell))
- gDialog.AddHTMLAttributeValueInput.inputField.select();
-}
-
-
-// update the object with added and removed attributes
-function UpdateHTMLAttributes()
-{
- var HTMLAList = document.getElementById("HTMLAList");
- var i;
-
- // remove removed attributes
- for (i = 0; i < HTMLRAttrs.length; i++)
- {
- var name = HTMLRAttrs[i];
-
- if (gElement.hasAttribute(name))
- doRemoveAttribute(name);
- }
-
- // Set added or changed attributes
- for( i = 0; i < HTMLAList.childNodes.length; i++)
- {
- var item = HTMLAList.childNodes[i];
- doSetAttribute( GetTreeItemAttributeStr(item), GetTreeItemValueStr(item));
- }
-}
-
-function RemoveHTMLAttribute()
-{
- // We only allow 1 selected item
- if (gDialog.AddHTMLAttributeTree.view.selection.count)
- {
- var item = getSelectedItem(gDialog.AddHTMLAttributeTree);
- var attr = GetTreeItemAttributeStr(item);
-
- // remove the item from the attribute array
- HTMLRAttrs[HTMLRAttrs.length] = attr;
- RemoveNameFromAttArray(attr, HTMLAttrs);
-
- // Remove the item from the tree
- item.remove();
-
- // Clear inputs and selected item in tree
- ClearHTMLInputWidgets();
- }
-}
-
-function SelectHTMLTree( index )
-{
-
- gDoOnSelectTree = false;
- try {
- gDialog.AddHTMLAttributeTree.selectedIndex = index;
- } catch (e) {}
- gDoOnSelectTree = true;
-}
diff --git a/editor/ui/dialogs/content/EdAEJSEAttributes.js b/editor/ui/dialogs/content/EdAEJSEAttributes.js
deleted file mode 100644
index e1894a8a6..000000000
--- a/editor/ui/dialogs/content/EdAEJSEAttributes.js
+++ /dev/null
@@ -1,192 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-function BuildJSEAttributeNameList()
-{
- gDialog.AddJSEAttributeNameList.removeAllItems();
-
- // Get events specific to current element
- var elementName = gElement.localName;
- if (elementName in gJSAttr)
- {
- var attNames = gJSAttr[elementName];
- var i;
- var popup;
- var sep;
-
- if (attNames && attNames.length)
- {
- // Since we don't allow user-editable JS events yet (but we will soon)
- // simply remove the JS tab to not allow adding JS events
- if (attNames[0] == "noJSEvents")
- {
- var tab = document.getElementById("tabJSE");
- if (tab)
- tab.remove();
-
- return;
- }
-
- for (i = 0; i < attNames.length; i++)
- gDialog.AddJSEAttributeNameList.appendItem(attNames[i], attNames[i]);
-
- popup = gDialog.AddJSEAttributeNameList.firstChild;
- if (popup)
- {
- sep = document.createElementNS(XUL_NS, "menuseparator");
- if (sep)
- popup.appendChild(sep);
- }
- }
- }
-
- // Always add core JS events unless we aborted above
- for (i = 0; i < gCoreJSEvents.length; i++)
- {
- if (gCoreJSEvents[i] == "-")
- {
- if (!popup)
- popup = gDialog.AddJSEAttributeNameList.firstChild;
-
- sep = document.createElementNS(XUL_NS, "menuseparator");
-
- if (popup && sep)
- popup.appendChild(sep);
- }
- else
- gDialog.AddJSEAttributeNameList.appendItem(gCoreJSEvents[i], gCoreJSEvents[i]);
- }
-
- gDialog.AddJSEAttributeNameList.selectedIndex = 0;
-
- // Use current name and value of first tree item if it exists
- onSelectJSETreeItem();
-}
-
-// build attribute list in tree form from element attributes
-function BuildJSEAttributeTable()
-{
- var nodeMap = gElement.attributes;
- if (nodeMap.length > 0)
- {
- var added = false;
- for (var i = 0; i < nodeMap.length; i++)
- {
- let name = nodeMap[i].nodeName.toLowerCase();
- if( CheckAttributeNameSimilarity( nodeMap[i].nodeName, JSEAttrs ) )
- continue; // repeated or non-JS handler, ignore this one and go to next
- if (!name.startsWith("on"))
- continue; // attribute isn't an event handler.
- var value = gElement.getAttribute(nodeMap[i].nodeName);
- if (AddTreeItem( name, value, "JSEAList", JSEAttrs )) // add item to tree
- added = true;
- }
-
- // Select first item
- if (added)
- gDialog.AddJSEAttributeTree.selectedIndex = 0;
- }
-}
-
-function onSelectJSEAttribute()
-{
- if(!gDoOnSelectTree)
- return;
-
- gDialog.AddJSEAttributeValueInput.value =
- GetAndSelectExistingAttributeValue(gDialog.AddJSEAttributeNameList.label, "JSEAList");
-}
-
-function onSelectJSETreeItem()
-{
- var tree = gDialog.AddJSEAttributeTree;
- if (tree && tree.view.selection.count)
- {
- // Select attribute name in list
- gDialog.AddJSEAttributeNameList.value = GetTreeItemAttributeStr(getSelectedItem(tree));
-
- // Set value input to that in tree (no need to update this in the tree)
- gUpdateTreeValue = false;
- gDialog.AddJSEAttributeValueInput.value = GetTreeItemValueStr(getSelectedItem(tree));
- gUpdateTreeValue = true;
- }
-}
-
-function onInputJSEAttributeValue()
-{
- if (gUpdateTreeValue)
- {
-
- var name = TrimString(gDialog.AddJSEAttributeNameList.label);
- var value = TrimString(gDialog.AddJSEAttributeValueInput.value);
-
- // Update value in the tree list
- // Since we have a non-editable menulist,
- // we MUST automatically add the event attribute if it doesn't exist
- if (!UpdateExistingAttribute( name, value, "JSEAList" ) && value)
- AddTreeItem( name, value, "JSEAList", JSEAttrs );
- }
-}
-
-function editJSEAttributeValue(targetCell)
-{
- if (IsNotTreeHeader(targetCell))
- gDialog.AddJSEAttributeValueInput.inputField.select();
-}
-
-function UpdateJSEAttributes()
-{
- var JSEAList = document.getElementById("JSEAList");
- var i;
-
- // remove removed attributes
- for (i = 0; i < JSERAttrs.length; i++)
- {
- var name = JSERAttrs[i];
-
- if (gElement.hasAttribute(name))
- doRemoveAttribute(name);
- }
-
- // Add events
- for (i = 0; i < JSEAList.childNodes.length; i++)
- {
- var item = JSEAList.childNodes[i];
-
- // set the event handler
- doSetAttribute( GetTreeItemAttributeStr(item), GetTreeItemValueStr(item) );
- }
-}
-
-function RemoveJSEAttribute()
-{
- // This differs from HTML and CSS panels:
- // We reselect after removing, because there is not
- // editable attribute name input, so we can't clear that
- // like we do in other panels
- var newIndex = gDialog.AddJSEAttributeTree.selectedIndex;
-
- // We only allow 1 selected item
- if (gDialog.AddJSEAttributeTree.view.selection.count)
- {
- var item = getSelectedItem(gDialog.AddJSEAttributeTree);
-
- // Name is the text of the treecell
- var attr = GetTreeItemAttributeStr(item);
-
- // remove the item from the attribute array
- if (newIndex >= (JSEAttrs.length-1))
- newIndex--;
-
- // remove the item from the attribute array
- JSERAttrs[JSERAttrs.length] = attr;
- RemoveNameFromAttArray(attr, JSEAttrs);
-
- // Remove the item from the tree
- item.remove();
-
- // Reselect an item
- gDialog.AddJSEAttributeTree.selectedIndex = newIndex;
- }
-}
diff --git a/editor/ui/dialogs/content/EdAdvancedEdit.js b/editor/ui/dialogs/content/EdAdvancedEdit.js
deleted file mode 100644
index 47135e589..000000000
--- a/editor/ui/dialogs/content/EdAdvancedEdit.js
+++ /dev/null
@@ -1,333 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/************** GLOBALS **************/
-var gElement = null; // handle to actual element edited
-
-var HTMLAttrs = []; // html attributes
-var CSSAttrs = []; // css attributes
-var JSEAttrs = []; // js events
-
-var HTMLRAttrs = []; // removed html attributes
-var JSERAttrs = []; // removed js events
-
-/* Set false to allow changing selection in tree
- without doing "onselect" handler actions
-*/
-var gDoOnSelectTree = true;
-var gUpdateTreeValue = true;
-
-/************** INITIALISATION && SETUP **************/
-
-/**
- * function : void Startup();
- * parameters : none
- * returns : none
- * desc. : startup and initialisation, prepares dialog.
- **/
-function Startup()
-{
- var editor = GetCurrentEditor();
-
- // Element to edit is passed in
- if (!editor || !window.arguments[1])
- {
- dump("Advanced Edit: No editor or element to edit not supplied\n");
- window.close();
- return;
- }
- // This is the return value for the parent,
- // who only needs to know if OK was clicked
- window.opener.AdvancedEditOK = false;
-
- // The actual element edited (not a copy!)
- gElement = window.arguments[1];
-
- // place the tag name in the header
- var tagLabel = document.getElementById("tagLabel");
- tagLabel.setAttribute("value", ("<" + gElement.localName + ">"));
-
- // Create dialog object to store controls for easy access
- gDialog.AddHTMLAttributeNameInput = document.getElementById("AddHTMLAttributeNameInput");
-
- // We use a <deck> to switch between editable menulist and textbox
- gDialog.AddHTMLAttributeValueDeck = document.getElementById("AddHTMLAttributeValueDeck");
- gDialog.AddHTMLAttributeValueMenulist = document.getElementById("AddHTMLAttributeValueMenulist");
- gDialog.AddHTMLAttributeValueTextbox = document.getElementById("AddHTMLAttributeValueTextbox");
- gDialog.AddHTMLAttributeValueInput = gDialog.AddHTMLAttributeValueTextbox;
-
- gDialog.AddHTMLAttributeTree = document.getElementById("HTMLATree");
- gDialog.AddCSSAttributeNameInput = document.getElementById("AddCSSAttributeNameInput");
- gDialog.AddCSSAttributeValueInput = document.getElementById("AddCSSAttributeValueInput");
- gDialog.AddCSSAttributeTree = document.getElementById("CSSATree");
- gDialog.AddJSEAttributeNameList = document.getElementById("AddJSEAttributeNameList");
- gDialog.AddJSEAttributeValueInput = document.getElementById("AddJSEAttributeValueInput");
- gDialog.AddJSEAttributeTree = document.getElementById("JSEATree");
- gDialog.okButton = document.documentElement.getButton("accept");
-
- // build the attribute trees
- BuildHTMLAttributeTable();
- BuildCSSAttributeTable();
- BuildJSEAttributeTable();
-
- // Build attribute name arrays for menulists
- BuildJSEAttributeNameList();
- BuildHTMLAttributeNameList();
- // No menulists for CSS panel (yet)
-
- // Set focus to Name editable menulist in HTML panel
- SetTextboxFocus(gDialog.AddHTMLAttributeNameInput);
-
- // size the dialog properly
- window.sizeToContent();
-
- SetWindowLocation();
-}
-
-/**
- * function : bool onAccept ( void );
- * parameters : none
- * returns : boolean true to close the window
- * desc. : event handler for ok button
- **/
-function onAccept()
-{
- var editor = GetCurrentEditor();
- editor.beginTransaction();
- try {
- // Update our gElement attributes
- UpdateHTMLAttributes();
- UpdateCSSAttributes();
- UpdateJSEAttributes();
- } catch(ex) {
- dump(ex);
- }
- editor.endTransaction();
-
- window.opener.AdvancedEditOK = true;
- SaveWindowLocation();
-
- return true; // do close the window
-}
-
-// Helpers for removing and setting attributes
-// Use editor transactions if modifying the element already in the document
-// (Temporary element from a property dialog won't have a parent node)
-function doRemoveAttribute(attrib)
-{
- try {
- var editor = GetCurrentEditor();
- if (gElement.parentNode)
- editor.removeAttribute(gElement, attrib);
- else
- gElement.removeAttribute(attrib);
- } catch(ex) {}
-}
-
-function doSetAttribute(attrib, value)
-{
- try {
- var editor = GetCurrentEditor();
- if (gElement.parentNode)
- editor.setAttribute(gElement, attrib, value);
- else
- gElement.setAttribute(attrib, value);
- } catch(ex) {}
-}
-
-/**
- * function : bool CheckAttributeNameSimilarity ( string attName, array attArray );
- * parameters : attribute to look for, array of current attributes
- * returns : true if attribute already exists, false if it does not
- * desc. : checks to see if any other attributes by the same name as the arg supplied
- * already exist.
- **/
-function CheckAttributeNameSimilarity(attName, attArray)
-{
- for (var i = 0; i < attArray.length; i++)
- {
- if (attName.toLowerCase() == attArray[i].toLowerCase())
- return true;
- }
- return false;
-}
-
-/**
- * function : bool UpdateExistingAttribute ( string attName, string attValue, string treeChildrenId );
- * parameters : attribute to look for, new value, ID of <treeChildren> node in XUL tree
- * returns : true if attribute already exists in tree, false if it does not
- * desc. : checks to see if any other attributes by the same name as the arg supplied
- * already exist while setting the associated value if different from current value
- **/
-function UpdateExistingAttribute( attName, attValue, treeChildrenId )
-{
- var treeChildren = document.getElementById(treeChildrenId);
- if (!treeChildren)
- return false;
-
- var name;
- var i;
- attName = TrimString(attName).toLowerCase();
- attValue = TrimString(attValue);
-
- for (i = 0; i < treeChildren.childNodes.length; i++)
- {
- var item = treeChildren.childNodes[i];
- name = GetTreeItemAttributeStr(item);
- if (name.toLowerCase() == attName)
- {
- // Set the text in the "value' column treecell
- SetTreeItemValueStr(item, attValue);
-
- // Select item just changed,
- // but don't trigger the tree's onSelect handler
- gDoOnSelectTree = false;
- try {
- selectTreeItem(treeChildren, item);
- } catch (e) {}
- gDoOnSelectTree = true;
-
- return true;
- }
- }
- return false;
-}
-
-/**
- * function : string GetAndSelectExistingAttributeValue ( string attName, string treeChildrenId );
- * parameters : attribute to look for, ID of <treeChildren> node in XUL tree
- * returns : value in from the tree or empty string if name not found
- **/
-function GetAndSelectExistingAttributeValue( attName, treeChildrenId )
-{
- if (!attName)
- return "";
-
- var treeChildren = document.getElementById(treeChildrenId);
- var name;
- var i;
-
- for (i = 0; i < treeChildren.childNodes.length; i++)
- {
- var item = treeChildren.childNodes[i];
- name = GetTreeItemAttributeStr(item);
- if (name.toLowerCase() == attName.toLowerCase())
- {
- // Select item in the tree
- // but don't trigger the tree's onSelect handler
- gDoOnSelectTree = false;
- try {
- selectTreeItem(treeChildren, item);
- } catch (e) {}
- gDoOnSelectTree = true;
-
- // Get the text in the "value' column treecell
- return GetTreeItemValueStr(item);
- }
- }
-
- // Attribute doesn't exist in tree, so remove selection
- gDoOnSelectTree = false;
- try {
- treeChildren.parentNode.view.selection.clearSelection();
- } catch (e) {}
- gDoOnSelectTree = true;
-
- return "";
-}
-
-/* Tree structure:
- <treeItem>
- <treeRow>
- <treeCell> // Name Cell
- <treeCell // Value Cell
-*/
-function GetTreeItemAttributeStr(treeItem)
-{
- if (treeItem)
- return TrimString(treeItem.firstChild.firstChild.getAttribute("label"));
-
- return "";
-}
-
-function GetTreeItemValueStr(treeItem)
-{
- if (treeItem)
- return TrimString(treeItem.firstChild.lastChild.getAttribute("label"));
-
- return "";
-}
-
-function SetTreeItemValueStr(treeItem, value)
-{
- if (treeItem && GetTreeItemValueStr(treeItem) != value)
- treeItem.firstChild.lastChild.setAttribute("label", value);
-}
-
-function IsNotTreeHeader(treeCell)
-{
- if (treeCell)
- return (treeCell.parentNode.parentNode.nodeName != "treehead");
-
- return false;
-}
-
-function RemoveNameFromAttArray(attName, attArray)
-{
- for (var i=0; i < attArray.length; i++)
- {
- if (attName.toLowerCase() == attArray[i].toLowerCase())
- {
- // Remove 1 array item
- attArray.splice(i,1);
- break;
- }
- }
-}
-
-// adds a generalised treeitem.
-function AddTreeItem ( name, value, treeChildrenId, attArray )
-{
- attArray[attArray.length] = name;
- var treeChildren = document.getElementById ( treeChildrenId );
- var treeitem = document.createElementNS ( XUL_NS, "treeitem" );
- var treerow = document.createElementNS ( XUL_NS, "treerow" );
-
- var attrCell = document.createElementNS ( XUL_NS, "treecell" );
- attrCell.setAttribute( "class", "propertylist" );
- attrCell.setAttribute( "label", name );
-
- var valueCell = document.createElementNS ( XUL_NS, "treecell" );
- valueCell.setAttribute( "class", "propertylist" );
- valueCell.setAttribute( "label", value );
-
- treerow.appendChild ( attrCell );
- treerow.appendChild ( valueCell );
- treeitem.appendChild ( treerow );
- treeChildren.appendChild ( treeitem );
-
- // Select item just added,
- // but suppress calling the onSelect handler
- gDoOnSelectTree = false;
- try {
- selectTreeItem(treeChildren, treeitem);
- } catch (e) {}
- gDoOnSelectTree = true;
-
- return treeitem;
-}
-
-function selectTreeItem(treeChildren, item)
-{
- var index = treeChildren.parentNode.contentView.getIndexOfItem(item);
- treeChildren.parentNode.view.selection.select(index);
-}
-
-function getSelectedItem(tree)
-{
- if (tree.view.selection.count == 1)
- return tree.contentView.getItemAtIndex(tree.currentIndex);
- else
- return null;
-}
diff --git a/editor/ui/dialogs/content/EdAdvancedEdit.xul b/editor/ui/dialogs/content/EdAdvancedEdit.xul
deleted file mode 100644
index f6eded080..000000000
--- a/editor/ui/dialogs/content/EdAdvancedEdit.xul
+++ /dev/null
@@ -1,183 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!-- first checkin of the year 2000! -->
-<!-- Ben Goodger, 12:50AM, 01/00/00 NZST -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<!-- May not need this here -->
-<!-- <?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?> -->
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EdAdvancedEdit.dtd">
-<dialog title="&WindowTitle.label;"
- id="advancedEditDlg"
- style="width: 40em;"
- xmlns ="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="Startup()"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <!-- element page functions -->
- <script type="application/javascript" src="chrome://editor/content/EdAEHTMLAttributes.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdAECSSAttributes.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdAEJSEAttributes.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdAEAttributes.js"/>
-
- <!-- global dialog functions -->
- <script type="application/javascript" src="chrome://editor/content/EdAdvancedEdit.js"/>
-
- <broadcaster id="args" value=""/>
-
- <hbox>
- <label value="&currentattributesfor.label;"/>
- <label class="header" id="tagLabel"/>
- </hbox>
-
- <separator class="thin"/>
-
- <tabbox flex="1">
- <tabs>
- <tab label="&tabHTML.label;"/>
- <tab label="&tabCSS.label;"/>
- <tab label="&tabJSE.label;" id="tabJSE"/>
- </tabs>
- <tabpanels flex="1">
- <!-- ============================================================== -->
- <!-- HTML Attributes -->
- <!-- ============================================================== -->
- <vbox>
- <tree id="HTMLATree" class="AttributesTree" flex="1"
- hidecolumnpicker="true" seltype="single"
- onselect="onSelectHTMLTreeItem();"
- onclick="onSelectHTMLTreeItem();"
- ondblclick="editHTMLAttributeValue(event.target);">
- <treecols>
- <treecol id="HTMLAttrCol" flex="35" label="&tree.attributeHeader.label;"/>
- <splitter class="tree-splitter"/>
- <treecol id="HTMLValCol" flex="65" label="&tree.valueHeader.label;"/>
- </treecols>
- <treechildren id="HTMLAList" class="gridlines" flex="1"/>
- </tree>
- <hbox align="center">
- <label value="&editAttribute.label;"/>
- <spacer flex="1"/>
- <button label="&removeAttribute.label;" oncommand="RemoveHTMLAttribute();"/>
- </hbox>
- <grid>
- <columns>
- <column flex="1"/><column flex="1"/>
- </columns>
- <rows>
- <row equalsize="always">
- <label control="AddHTMLAttributeNameInput" value="&AttName.label;"/>
- <label control="AddHTMLAttributeValueInput" value="&AttValue.label;"/>
- </row>
- <row align="top" equalsize="always">
- <!-- Lists are built at runtime -->
- <menulist id="AddHTMLAttributeNameInput" editable="true" flex="1"
- oninput="onInputHTMLAttributeName();"
- oncommand="onInputHTMLAttributeName();"/>
- <deck id="AddHTMLAttributeValueDeck" selectedIndex="0">
- <hbox align="top">
- <textbox id="AddHTMLAttributeValueTextbox" flex="1"
- oninput="onInputHTMLAttributeValue();"/>
- </hbox>
- <hbox align="top">
- <menulist id="AddHTMLAttributeValueMenulist" editable="true" flex="1"
- oninput="onInputHTMLAttributeValue();"
- oncommand="onInputHTMLAttributeValue();"/>
- </hbox>
- </deck>
- </row>
- </rows>
- </grid>
- </vbox>
- <!-- ============================================================== -->
- <!-- CSS Attributes -->
- <!-- ============================================================== -->
- <vbox>
- <tree id="CSSATree" class="AttributesTree" flex="1"
- hidecolumnpicker="true" seltype="single"
- onselect="onSelectCSSTreeItem();"
- onclick="onSelectCSSTreeItem();"
- ondblclick="editCSSAttributeValue(event.target);">
- <treecols>
- <treecol id="CSSPropCol" flex="35" label="&tree.propertyHeader.label;"/>
- <splitter class="tree-splitter"/>
- <treecol id="CSSValCol" flex="65" label="&tree.valueHeader.label;"/>
- </treecols>
- <treechildren id="CSSAList" class="gridlines" flex="1"/>
- </tree>
- <hbox align="center">
- <label value="&editAttribute.label;"/>
- <spacer flex="1"/>
- <button label="&removeAttribute.label;" oncommand="RemoveCSSAttribute();"/>
- </hbox>
- <grid>
- <columns>
- <column flex="1"/><column flex="1"/>
- </columns>
- <rows>
- <row equalsize="always">
- <label value="&PropertyName.label;"/>
- <label value="&AttValue.label;"/>
- </row>
- <row align="top" equalsize="always">
- <textbox id="AddCSSAttributeNameInput" flex="1"
- oninput="onInputCSSAttributeName();"/>
- <textbox id="AddCSSAttributeValueInput" flex="1"
- oninput="onChangeCSSAttribute();"/>
- </row>
- </rows>
- </grid>
- </vbox>
- <!-- ============================================================== -->
- <!-- JavaScript Event Handlers -->
- <!-- ============================================================== -->
- <vbox>
- <tree id="JSEATree" class="AttributesTree" flex="1"
- hidecolumnpicker="true" seltype="single"
- onselect="onSelectJSETreeItem();"
- onclick="onSelectJSETreeItem();"
- ondblclick="editJSEAttributeValue(event.target);">
- <treecols>
- <treecol id="AttrCol" flex="35" label="&tree.attributeHeader.label;"/>
- <splitter class="tree-splitter"/>
- <treecol id="HeaderCol" flex="65" label="&tree.valueHeader.label;"/>
- </treecols>
- <treechildren id="JSEAList" class="gridlines" flex="1"/>
- </tree>
- <hbox align="center">
- <label value="&editAttribute.label;"/>
- <spacer flex="1"/>
- <button label="&removeAttribute.label;" oncommand="RemoveJSEAttribute()"/>
- </hbox>
- <grid>
- <columns>
- <column flex="1"/><column flex="1"/>
- </columns>
- <rows>
- <row equalsize="always">
- <label value="&AttName.label;"/>
- <label value="&AttValue.label;"/>
- </row>
- <row align="top" equalsize="always">
- <!-- List is built at runtime -->
- <menulist id="AddJSEAttributeNameList" flex="1"
- oncommand="onSelectJSEAttribute();"/>
- <textbox id="AddJSEAttributeValueInput" flex="1"
- oninput="onInputJSEAttributeValue();"/>
- </row>
- </rows>
- </grid>
- </vbox>
- </tabpanels>
- </tabbox>
-</dialog>
diff --git a/editor/ui/dialogs/content/EdButtonProps.js b/editor/ui/dialogs/content/EdButtonProps.js
deleted file mode 100644
index 493ebd7df..000000000
--- a/editor/ui/dialogs/content/EdButtonProps.js
+++ /dev/null
@@ -1,146 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var insertNew;
-var buttonElement;
-
-// dialog initialization code
-
-function Startup()
-{
- var editor = GetCurrentEditor();
- if (!editor)
- {
- window.close();
- return;
- }
-
- gDialog = {
- buttonType: document.getElementById("ButtonType"),
- buttonName: document.getElementById("ButtonName"),
- buttonValue: document.getElementById("ButtonValue"),
- buttonDisabled: document.getElementById("ButtonDisabled"),
- buttonTabIndex: document.getElementById("ButtonTabIndex"),
- buttonAccessKey: document.getElementById("ButtonAccessKey"),
- MoreSection: document.getElementById("MoreSection"),
- MoreFewerButton: document.getElementById("MoreFewerButton"),
- RemoveButton: document.getElementById("RemoveButton")
- };
-
- // Get a single selected button element
- const kTagName = "button";
- try {
- buttonElement = editor.getSelectedElement(kTagName);
- } catch (e) {}
-
- if (buttonElement)
- // We found an element and don't need to insert one
- insertNew = false;
- else
- {
- insertNew = true;
-
- // We don't have an element selected,
- // so create one with default attributes
- try {
- buttonElement = editor.createElementWithDefaults(kTagName);
- } catch (e) {}
-
- if (!buttonElement)
- {
- dump("Failed to get selected element or create a new one!\n");
- window.close();
- return;
- }
- // Hide button removing existing button
- gDialog.RemoveButton.hidden = true;
- }
-
- // Make a copy to use for AdvancedEdit
- globalElement = buttonElement.cloneNode(false);
-
- InitDialog();
-
- InitMoreFewer();
-
- gDialog.buttonType.focus();
-
- SetWindowLocation();
-}
-
-function InitDialog()
-{
- var type = globalElement.getAttribute("type");
- var index = 0;
- switch (type)
- {
- case "button":
- index = 2;
- break;
- case "reset":
- index = 1;
- break;
- }
- gDialog.buttonType.selectedIndex = index;
- gDialog.buttonName.value = globalElement.getAttribute("name");
- gDialog.buttonValue.value = globalElement.getAttribute("value");
- gDialog.buttonDisabled.setAttribute("checked", globalElement.hasAttribute("disabled"));
- gDialog.buttonTabIndex.value = globalElement.getAttribute("tabindex");
- gDialog.buttonAccessKey.value = globalElement.getAttribute("accesskey");
-}
-
-function RemoveButton()
-{
- RemoveContainer(buttonElement);
- SaveWindowLocation();
- window.close();
-}
-
-function ValidateData()
-{
- var attributes = {
- type: ["", "reset", "button"][gDialog.buttonType.selectedIndex],
- name: gDialog.buttonName.value,
- value: gDialog.buttonValue.value,
- tabindex: gDialog.buttonTabIndex.value,
- accesskey: gDialog.buttonAccessKey.value
- };
- for (var a in attributes)
- {
- if (attributes[a])
- globalElement.setAttribute(a, attributes[a]);
- else
- globalElement.removeAttribute(a);
- }
- if (gDialog.buttonDisabled.checked)
- globalElement.setAttribute("disabled", "");
- else
- globalElement.removeAttribute("disabled");
- return true;
-}
-
-function onAccept()
-{
- // All values are valid - copy to actual element in doc or
- // element created to insert
- ValidateData();
-
- var editor = GetCurrentEditor();
-
- editor.cloneAttributes(buttonElement, globalElement);
-
- if (insertNew)
- {
- if (!InsertElementAroundSelection(buttonElement))
- {
- buttonElement.innerHTML = editor.outputToString("text/html", kOutputSelectionOnly);
- editor.insertElementAtSelection(buttonElement, true);
- }
- }
-
- SaveWindowLocation();
-
- return true;
-}
-
diff --git a/editor/ui/dialogs/content/EdButtonProps.xul b/editor/ui/dialogs/content/EdButtonProps.xul
deleted file mode 100644
index 822ca46b2..000000000
--- a/editor/ui/dialogs/content/EdButtonProps.xul
+++ /dev/null
@@ -1,84 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorButtonProperties.dtd">
-<dialog title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="Startup();"
- buttons="accept,cancel"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdButtonProps.js"/>
-
- <broadcaster id="args" value=""/>
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
-
- <groupbox><caption label="&Settings.label;"/>
- <grid><columns><column/><column/></columns>
- <rows>
- <row align="center">
- <label control="ButtonType" value="&ButtonType.label;" accesskey="&ButtonType.accesskey;"/>
- <menulist id="ButtonType">
- <menupopup>
- <menuitem label="&submit.value;"/>
- <menuitem label="&reset.value;"/>
- <menuitem label="&button.value;"/>
- </menupopup>
- </menulist>
- </row>
- <row align="center">
- <label control="ButtonName" value="&ButtonName.label;" accesskey="&ButtonName.accesskey;"/>
- <textbox id="ButtonName"/>
- </row>
- <row align="center">
- <label control="ButtonValue" value="&ButtonValue.label;" accesskey="&ButtonValue.accesskey;"/>
- <textbox id="ButtonValue"/>
- </row>
- </rows>
- </grid>
- <hbox>
- <button id="MoreFewerButton" oncommand="onMoreFewer();" persist="more"/>
- </hbox>
- <grid id="MoreSection"><columns><column/><column/></columns>
- <rows>
- <row>
- <spacer/>
- <checkbox id="ButtonDisabled" label="&ButtonDisabled.label;" accesskey="&ButtonDisabled.accesskey;"/>
- </row>
- <row align="center">
- <label control="ButtonTabIndex" value="&tabIndex.label;" accesskey="&tabIndex.accesskey;"/>
- <hbox>
- <textbox id="ButtonTabIndex" class="narrow" oninput="forceInteger(this.id);"/>
- </hbox>
- </row>
- <row align="center">
- <label control="ButtonAccessKey" value="&AccessKey.label;" accesskey="&AccessKey.accesskey;"/>
- <hbox>
- <textbox id="ButtonAccessKey" class="narrow"/>
- </hbox>
- </row>
- </rows>
- </grid>
- </groupbox>
-
- <!-- from EdDialogOverlay -->
- <hbox flex="1" style="margin-top: 0.2em">
- <button id="RemoveButton" label="&RemoveButton.label;" accesskey="&RemoveButton.accesskey;" oncommand="RemoveButton();"/>
- <!-- This will right-align the button -->
- <spacer flex="1"/>
- <button id="AdvancedEditButton"/>
- </hbox>
- <separator class="groove"/>
-
-</dialog>
diff --git a/editor/ui/dialogs/content/EdColorPicker.js b/editor/ui/dialogs/content/EdColorPicker.js
deleted file mode 100644
index e82d44440..000000000
--- a/editor/ui/dialogs/content/EdColorPicker.js
+++ /dev/null
@@ -1,306 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-//Cancel() is in EdDialogCommon.js
-
-var insertNew = true;
-var tagname = "TAG NAME"
-var gColor = "";
-var LastPickedColor = "";
-var ColorType = "Text";
-var TextType = false;
-var HighlightType = false;
-var TableOrCell = false;
-var LastPickedIsDefault = true;
-var NoDefault = false;
-var gColorObj;
-
-// dialog initialization code
-function Startup()
-{
- if (!window.arguments[1])
- {
- dump("EdColorPicker: Missing color object param\n");
- return;
- }
-
- // window.arguments[1] is object to get initial values and return color data
- gColorObj = window.arguments[1];
- gColorObj.Cancel = false;
-
- gDialog.ColorPicker = document.getElementById("ColorPicker");
- gDialog.ColorInput = document.getElementById("ColorInput");
- gDialog.LastPickedButton = document.getElementById("LastPickedButton");
- gDialog.LastPickedColor = document.getElementById("LastPickedColor");
- gDialog.CellOrTableGroup = document.getElementById("CellOrTableGroup");
- gDialog.TableRadio = document.getElementById("TableRadio");
- gDialog.CellRadio = document.getElementById("CellRadio");
- gDialog.ColorSwatch = document.getElementById("ColorPickerSwatch");
- gDialog.Ok = document.documentElement.getButton("accept");
-
- // The type of color we are setting:
- // text: Text, Link, ActiveLink, VisitedLink,
- // or background: Page, Table, or Cell
- if (gColorObj.Type)
- {
- ColorType = gColorObj.Type;
- // Get string for dialog title from passed-in type
- // (note constraint on editor.properties string name)
- let IsCSSPrefChecked = Services.prefs.getBoolPref("editor.use_css");
-
- if (GetCurrentEditor())
- {
- if (ColorType == "Page" && IsCSSPrefChecked && IsHTMLEditor())
- document.title = GetString("BlockColor");
- else
- document.title = GetString(ColorType + "Color");
- }
- }
-
- gDialog.ColorInput.value = "";
- var tmpColor;
- var haveTableRadio = false;
-
- switch (ColorType)
- {
- case "Page":
- tmpColor = gColorObj.PageColor;
- if (tmpColor && tmpColor.toLowerCase() != "window")
- gColor = tmpColor;
- break;
- case "Table":
- if (gColorObj.TableColor)
- gColor = gColorObj.TableColor;
- break;
- case "Cell":
- if (gColorObj.CellColor)
- gColor = gColorObj.CellColor;
- break;
- case "TableOrCell":
- TableOrCell = true;
- document.getElementById("TableOrCellGroup").collapsed = false;
- haveTableRadio = true;
- if (gColorObj.SelectedType == "Cell")
- {
- gColor = gColorObj.CellColor;
- gDialog.CellOrTableGroup.selectedItem = gDialog.CellRadio;
- gDialog.CellRadio.focus();
- }
- else
- {
- gColor = gColorObj.TableColor;
- gDialog.CellOrTableGroup.selectedItem = gDialog.TableRadio;
- gDialog.TableRadio.focus();
- }
- break;
- case "Highlight":
- HighlightType = true;
- if (gColorObj.HighlightColor)
- gColor = gColorObj.HighlightColor;
- break;
- default:
- // Any other type will change some kind of text,
- TextType = true;
- tmpColor = gColorObj.TextColor;
- if (tmpColor && tmpColor.toLowerCase() != "windowtext")
- gColor = gColorObj.TextColor;
- break;
- }
-
- // Set initial color in input field and in the colorpicker
- SetCurrentColor(gColor);
- gDialog.ColorPicker.initColor(gColor);
-
- // Use last-picked colors passed in, or those persistent on dialog
- if (TextType)
- {
- if ( !("LastTextColor" in gColorObj) || !gColorObj.LastTextColor)
- gColorObj.LastTextColor = gDialog.LastPickedColor.getAttribute("LastTextColor");
- LastPickedColor = gColorObj.LastTextColor;
- }
- else if (HighlightType)
- {
- if ( !("LastHighlightColor" in gColorObj) || !gColorObj.LastHighlightColor)
- gColorObj.LastHighlightColor = gDialog.LastPickedColor.getAttribute("LastHighlightColor");
- LastPickedColor = gColorObj.LastHighlightColor;
- }
- else
- {
- if ( !("LastBackgroundColor" in gColorObj) || !gColorObj.LastBackgroundColor)
- gColorObj.LastBackgroundColor = gDialog.LastPickedColor.getAttribute("LastBackgroundColor");
- LastPickedColor = gColorObj.LastBackgroundColor;
- }
-
- // Set method to detect clicking on OK button
- // so we don't get fooled by changing "default" behavior
- gDialog.Ok.setAttribute("onclick", "SetDefaultToOk()");
-
- if (!LastPickedColor) {
- // Hide the button, as there is no last color available.
- gDialog.LastPickedButton.hidden = true;
- } else {
- gDialog.LastPickedColor.setAttribute("style", "background-color: " + LastPickedColor);
-
- // Make "Last-picked" the default button, until the user selects a color.
- gDialog.Ok.removeAttribute("default");
- gDialog.LastPickedButton.setAttribute("default", "true");
- }
-
- // Caller can prevent user from submitting an empty, i.e., default color
- NoDefault = gColorObj.NoDefault;
- if (NoDefault)
- {
- // Hide the "Default button -- user must pick a color
- document.getElementById("DefaultColorButton").collapsed = true;
- }
-
- // Set focus to colorpicker if not set to table radio buttons above
- if (!haveTableRadio)
- gDialog.ColorPicker.focus();
-
- SetWindowLocation();
-}
-
-function ChangePalette(palette)
-{
- gDialog.ColorPicker.setAttribute("palettename", palette);
- window.sizeToContent();
-}
-
-function SelectColor()
-{
- var color = gDialog.ColorPicker.color;
- if (color)
- SetCurrentColor(color);
-}
-
-function RemoveColor()
-{
- SetCurrentColor("");
- gDialog.ColorInput.focus();
- SetDefaultToOk();
-}
-
-function SelectColorByKeypress(aEvent)
-{
- if (aEvent.charCode == aEvent.DOM_VK_SPACE)
- {
- SelectColor();
- SetDefaultToOk();
- }
-}
-
-function SelectLastPickedColor()
-{
- SetCurrentColor(LastPickedColor);
- if ( onAccept() )
- //window.close();
- return true;
-
- return false;
-}
-
-function SetCurrentColor(color)
-{
- // TODO: Validate color?
- if(!color) color = "";
- gColor = TrimString(color).toLowerCase();
- if (gColor == "mixed")
- gColor = "";
- gDialog.ColorInput.value = gColor;
- SetColorSwatch();
-}
-
-function SetColorSwatch()
-{
- // TODO: DON'T ALLOW SPACES?
- var color = TrimString(gDialog.ColorInput.value);
- if (color)
- {
- gDialog.ColorSwatch.setAttribute("style",("background-color:"+color));
- gDialog.ColorSwatch.removeAttribute("default");
- }
- else
- {
- gDialog.ColorSwatch.setAttribute("style",("background-color:inherit"));
- gDialog.ColorSwatch.setAttribute("default","true");
- }
-}
-
-function SetDefaultToOk()
-{
- gDialog.LastPickedButton.removeAttribute("default");
- gDialog.Ok.setAttribute("default","true");
- LastPickedIsDefault = false;
-}
-
-function ValidateData()
-{
- if (LastPickedIsDefault)
- gColor = LastPickedColor;
- else
- gColor = gDialog.ColorInput.value;
-
- gColor = TrimString(gColor).toLowerCase();
-
- // TODO: Validate the color string!
-
- if (NoDefault && !gColor)
- {
- ShowInputErrorMessage(GetString("NoColorError"));
- SetTextboxFocus(gDialog.ColorInput);
- return false;
- }
- return true;
-}
-
-function onAccept()
-{
- if (!ValidateData())
- return false;
-
- // Set return values and save in persistent color attributes
- if (TextType)
- {
- gColorObj.TextColor = gColor;
- if (gColor.length > 0)
- {
- gDialog.LastPickedColor.setAttribute("LastTextColor", gColor);
- gColorObj.LastTextColor = gColor;
- }
- }
- else if (HighlightType)
- {
- gColorObj.HighlightColor = gColor;
- if (gColor.length > 0)
- {
- gDialog.LastPickedColor.setAttribute("LastHighlightColor", gColor);
- gColorObj.LastHighlightColor = gColor;
- }
- }
- else
- {
- gColorObj.BackgroundColor = gColor;
- if (gColor.length > 0)
- {
- gDialog.LastPickedColor.setAttribute("LastBackgroundColor", gColor);
- gColorObj.LastBackgroundColor = gColor;
- }
- // If table or cell requested, tell caller which element to set on
- if (TableOrCell && gDialog.TableRadio.selected)
- gColorObj.Type = "Table";
- }
- SaveWindowLocation();
-
- return true; // do close the window
-}
-
-function onCancelColor()
-{
- // Tells caller that user canceled
- gColorObj.Cancel = true;
- SaveWindowLocation();
- return true;
-}
diff --git a/editor/ui/dialogs/content/EdColorPicker.xul b/editor/ui/dialogs/content/EdColorPicker.xul
deleted file mode 100644
index daf57de1e..000000000
--- a/editor/ui/dialogs/content/EdColorPicker.xul
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EdColorPicker.dtd">
-
-<dialog title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="Startup()"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancelColor();">
-
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdColorPicker.js"/>
-
- <broadcaster id="args" value=""/>
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
-
- <hbox id="TableOrCellGroup" align="center" collapsed="true">
- <label control="CellOrTableGroup" value="&background.label;" accesskey="&background.accessKey;"/>
- <radiogroup id="CellOrTableGroup" orient="horizontal">
- <radio id="TableRadio" label="&table.label;" accesskey="&table.accessKey;"/>
- <radio id="CellRadio" label="&cell.label;" accesskey="&cell.accessKey;"/>
- </radiogroup>
- </hbox>
- <colorpicker id="ColorPicker" palettename="standard"
- persist="palettename"
- onclick="SetDefaultToOk();"
- ondblclick="if (onAccept()) window.close();"
- onkeypress="SelectColorByKeypress(event);"
- onselect="SelectColor();"/>
-<!-- Web palette is not implemented???
- <hbox align="center">
- <label value="&palette.label;"/>
- <radio id="StandardPalette" label="&standardPalette.label;" oncommand="ChangePalette('standard')"/>
- <radio id="WebPalette" label="&webPalette.label;" oncommand="ChangePalette('web')"/>
- </hbox>
--->
- <spacer class="spacer"/>
- <vbox flex="1">
- <button id="LastPickedButton" crop="right" oncommand="SelectLastPickedColor();">
- <spacer id="LastPickedColor"
- LastTextColor="" LastBackgroundColor=""
- persist="LastTextColor LastBackgroundColor"/>
- <label value="&lastPickedColor.label;" accesskey="&lastPickedColor.accessKey;" flex="1" style="text-align: center;"/>
- </button>
- <label value="&setColor1.label;"/>
- <label value="&setColor2.label;" accesskey="&setColor2.accessKey;" control="ColorInput"/>
- <label value="&setColorExample.label;"/>
- <hbox align="center" flex="1=">
- <textbox id="ColorInput" style="width: 8em" oninput="SetColorSwatch(); SetDefaultToOk();"/>
- <spacer flex="1"/>
- <spacer id="ColorPickerSwatch"/>
- <spacer flex="1"/>
- <button id="DefaultColorButton" label="&default.label;" accesskey="&default.accessKey;"
- style="margin-right:0px;" oncommand="RemoveColor()"/>
- </hbox>
- </vbox>
- <separator class="groove"/>
-</dialog>
diff --git a/editor/ui/dialogs/content/EdColorProps.js b/editor/ui/dialogs/content/EdColorProps.js
deleted file mode 100644
index aa3062833..000000000
--- a/editor/ui/dialogs/content/EdColorProps.js
+++ /dev/null
@@ -1,428 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
- Behavior notes:
- Radio buttons select "UseDefaultColors" vs. "UseCustomColors" modes.
- If any color attribute is set in the body, mode is "Custom Colors",
- even if 1 or more (but not all) are actually null (= "use default")
- When in "Custom Colors" mode, all colors will be set on body tag,
- even if they are just default colors, to assure compatable colors in page.
- User cannot select "use default" for individual colors
-*/
-
-//Cancel() is in EdDialogCommon.js
-
-var gBodyElement;
-var prefs;
-var gBackgroundImage;
-
-// Initialize in case we can't get them from prefs???
-var defaultTextColor="#000000";
-var defaultLinkColor="#000099";
-var defaultActiveColor="#000099";
-var defaultVisitedColor="#990099";
-var defaultBackgroundColor="#FFFFFF";
-const styleStr = "style";
-const textStr = "text";
-const linkStr = "link";
-const vlinkStr = "vlink";
-const alinkStr = "alink";
-const bgcolorStr = "bgcolor";
-const backgroundStr = "background";
-const cssColorStr = "color";
-const cssBackgroundColorStr = "background-color";
-const cssBackgroundImageStr = "background-image";
-const colorStyle = cssColorStr + ": ";
-const backColorStyle = cssBackgroundColorStr + ": ";
-const backImageStyle = "; " + cssBackgroundImageStr + ": url(";
-
-var customTextColor;
-var customLinkColor;
-var customActiveColor;
-var customVisitedColor;
-var customBackgroundColor;
-var previewBGColor;
-var gHaveDocumentUrl = false;
-
-// dialog initialization code
-function Startup()
-{
- var editor = GetCurrentEditor();
- if (!editor)
- {
- window.close();
- return;
- }
-
- gDialog.ColorPreview = document.getElementById("ColorPreview");
- gDialog.NormalText = document.getElementById("NormalText");
- gDialog.LinkText = document.getElementById("LinkText");
- gDialog.ActiveLinkText = document.getElementById("ActiveLinkText");
- gDialog.VisitedLinkText = document.getElementById("VisitedLinkText");
- gDialog.PageColorGroup = document.getElementById("PageColorGroup");
- gDialog.DefaultColorsRadio = document.getElementById("DefaultColorsRadio");
- gDialog.CustomColorsRadio = document.getElementById("CustomColorsRadio");
- gDialog.BackgroundImageInput = document.getElementById("BackgroundImageInput");
-
- try {
- gBodyElement = editor.rootElement;
- } catch (e) {}
-
- if (!gBodyElement)
- {
- dump("Failed to get BODY element!\n");
- window.close();
- }
-
- // Set element we will edit
- globalElement = gBodyElement.cloneNode(false);
-
- // Initialize default colors from browser prefs
- var browserColors = GetDefaultBrowserColors();
- if (browserColors)
- {
- // Use author's browser pref colors passed into dialog
- defaultTextColor = browserColors.TextColor;
- defaultLinkColor = browserColors.LinkColor;
- defaultActiveColor = browserColors.ActiveLinkColor;
- defaultVisitedColor = browserColors.VisitedLinkColor;
- defaultBackgroundColor= browserColors.BackgroundColor;
- }
-
- // We only need to test for this once per dialog load
- gHaveDocumentUrl = GetDocumentBaseUrl();
-
- InitDialog();
-
- gDialog.PageColorGroup.focus();
-
- SetWindowLocation();
-}
-
-function InitDialog()
-{
- // Get image from document
- gBackgroundImage = GetHTMLOrCSSStyleValue(globalElement, backgroundStr, cssBackgroundImageStr);
- if (/url\((.*)\)/.test( gBackgroundImage ))
- gBackgroundImage = RegExp.$1;
-
- if (gBackgroundImage) {
- // Shorten data URIs for display.
- shortenImageData(gBackgroundImage, gDialog.BackgroundImageInput);
- gDialog.ColorPreview.setAttribute(styleStr, backImageStyle+gBackgroundImage+");");
- }
-
- SetRelativeCheckbox();
-
- customTextColor = GetHTMLOrCSSStyleValue(globalElement, textStr, cssColorStr);
- customTextColor = ConvertRGBColorIntoHEXColor(customTextColor);
- customLinkColor = globalElement.getAttribute(linkStr);
- customActiveColor = globalElement.getAttribute(alinkStr);
- customVisitedColor = globalElement.getAttribute(vlinkStr);
- customBackgroundColor = GetHTMLOrCSSStyleValue(globalElement, bgcolorStr, cssBackgroundColorStr);
- customBackgroundColor = ConvertRGBColorIntoHEXColor(customBackgroundColor);
-
- var haveCustomColor =
- customTextColor ||
- customLinkColor ||
- customVisitedColor ||
- customActiveColor ||
- customBackgroundColor;
-
- // Set default color explicitly for any that are missing
- // PROBLEM: We are using "windowtext" and "window" for the Windows OS
- // default color values. This works with CSS in preview window,
- // but we should NOT use these as values for HTML attributes!
-
- if (!customTextColor) customTextColor = defaultTextColor;
- if (!customLinkColor) customLinkColor = defaultLinkColor;
- if (!customActiveColor) customActiveColor = defaultActiveColor;
- if (!customVisitedColor) customVisitedColor = defaultVisitedColor;
- if (!customBackgroundColor) customBackgroundColor = defaultBackgroundColor;
-
- if (haveCustomColor)
- {
- // If any colors are set, then check the "Custom" radio button
- gDialog.PageColorGroup.selectedItem = gDialog.CustomColorsRadio;
- UseCustomColors();
- }
- else
- {
- gDialog.PageColorGroup.selectedItem = gDialog.DefaultColorsRadio;
- UseDefaultColors();
- }
-}
-
-function GetColorAndUpdate(ColorWellID)
-{
- // Only allow selecting when in custom mode
- if (!gDialog.CustomColorsRadio.selected) return;
-
- var colorWell = document.getElementById(ColorWellID);
- if (!colorWell) return;
-
- // Don't allow a blank color, i.e., using the "default"
- var colorObj = { NoDefault:true, Type:"", TextColor:0, PageColor:0, Cancel:false };
-
- switch( ColorWellID )
- {
- case "textCW":
- colorObj.Type = "Text";
- colorObj.TextColor = customTextColor;
- break;
- case "linkCW":
- colorObj.Type = "Link";
- colorObj.TextColor = customLinkColor;
- break;
- case "activeCW":
- colorObj.Type = "ActiveLink";
- colorObj.TextColor = customActiveColor;
- break;
- case "visitedCW":
- colorObj.Type = "VisitedLink";
- colorObj.TextColor = customVisitedColor;
- break;
- case "backgroundCW":
- colorObj.Type = "Page";
- colorObj.PageColor = customBackgroundColor;
- break;
- }
-
- window.openDialog("chrome://editor/content/EdColorPicker.xul", "_blank", "chrome,close,titlebar,modal", "", colorObj);
-
- // User canceled the dialog
- if (colorObj.Cancel)
- return;
-
- var color = "";
- switch( ColorWellID )
- {
- case "textCW":
- color = customTextColor = colorObj.TextColor;
- break;
- case "linkCW":
- color = customLinkColor = colorObj.TextColor;
- break;
- case "activeCW":
- color = customActiveColor = colorObj.TextColor;
- break;
- case "visitedCW":
- color = customVisitedColor = colorObj.TextColor;
- break;
- case "backgroundCW":
- color = customBackgroundColor = colorObj.BackgroundColor;
- break;
- }
-
- setColorWell(ColorWellID, color);
- SetColorPreview(ColorWellID, color);
-}
-
-function SetColorPreview(ColorWellID, color)
-{
- switch( ColorWellID )
- {
- case "textCW":
- gDialog.NormalText.setAttribute(styleStr,colorStyle+color);
- break;
- case "linkCW":
- gDialog.LinkText.setAttribute(styleStr,colorStyle+color);
- break;
- case "activeCW":
- gDialog.ActiveLinkText.setAttribute(styleStr,colorStyle+color);
- break;
- case "visitedCW":
- gDialog.VisitedLinkText.setAttribute(styleStr,colorStyle+color);
- break;
- case "backgroundCW":
- // Must combine background color and image style values
- var styleValue = backColorStyle+color;
- if (gBackgroundImage)
- styleValue += ";"+backImageStyle+gBackgroundImage+");";
-
- gDialog.ColorPreview.setAttribute(styleStr,styleValue);
- previewBGColor = color;
- break;
- }
-}
-
-function UseCustomColors()
-{
- SetElementEnabledById("TextButton", true);
- SetElementEnabledById("LinkButton", true);
- SetElementEnabledById("ActiveLinkButton", true);
- SetElementEnabledById("VisitedLinkButton", true);
- SetElementEnabledById("BackgroundButton", true);
- SetElementEnabledById("Text", true);
- SetElementEnabledById("Link", true);
- SetElementEnabledById("Active", true);
- SetElementEnabledById("Visited", true);
- SetElementEnabledById("Background", true);
-
- SetColorPreview("textCW", customTextColor);
- SetColorPreview("linkCW", customLinkColor);
- SetColorPreview("activeCW", customActiveColor);
- SetColorPreview("visitedCW", customVisitedColor);
- SetColorPreview("backgroundCW", customBackgroundColor);
-
- setColorWell("textCW", customTextColor);
- setColorWell("linkCW", customLinkColor);
- setColorWell("activeCW", customActiveColor);
- setColorWell("visitedCW", customVisitedColor);
- setColorWell("backgroundCW", customBackgroundColor);
-}
-
-function UseDefaultColors()
-{
- SetColorPreview("textCW", defaultTextColor);
- SetColorPreview("linkCW", defaultLinkColor);
- SetColorPreview("activeCW", defaultActiveColor);
- SetColorPreview("visitedCW", defaultVisitedColor);
- SetColorPreview("backgroundCW", defaultBackgroundColor);
-
- // Setting to blank color will remove color from buttons,
- setColorWell("textCW", "");
- setColorWell("linkCW", "");
- setColorWell("activeCW", "");
- setColorWell("visitedCW", "");
- setColorWell("backgroundCW", "");
-
- // Disable color buttons and labels
- SetElementEnabledById("TextButton", false);
- SetElementEnabledById("LinkButton", false);
- SetElementEnabledById("ActiveLinkButton", false);
- SetElementEnabledById("VisitedLinkButton", false);
- SetElementEnabledById("BackgroundButton", false);
- SetElementEnabledById("Text", false);
- SetElementEnabledById("Link", false);
- SetElementEnabledById("Active", false);
- SetElementEnabledById("Visited", false);
- SetElementEnabledById("Background", false);
-}
-
-function chooseFile()
-{
- // Get a local image file, converted into URL format
- var fileName = GetLocalFileURL("img");
- if (fileName)
- {
- // Always try to relativize local file URLs
- if (gHaveDocumentUrl)
- fileName = MakeRelativeUrl(fileName);
-
- gDialog.BackgroundImageInput.value = fileName;
-
- SetRelativeCheckbox();
-
- ValidateAndPreviewImage(true);
- }
- SetTextboxFocus(gDialog.BackgroundImageInput);
-}
-
-function ChangeBackgroundImage()
-{
- // Don't show error message for image while user is typing
- ValidateAndPreviewImage(false);
- SetRelativeCheckbox();
-}
-
-function ValidateAndPreviewImage(ShowErrorMessage)
-{
- // First make a string with just background color
- var styleValue = backColorStyle+previewBGColor+";";
-
- var retVal = true;
- var image = TrimString(gDialog.BackgroundImageInput.value);
- if (image)
- {
- if (isImageDataShortened(image))
- {
- gBackgroundImage = restoredImageData(gDialog.BackgroundImageInput);
- }
- else
- {
- gBackgroundImage = image;
-
- // Display must use absolute URL if possible
- var displayImage = gHaveDocumentUrl ? MakeAbsoluteUrl(image) : image;
- styleValue += backImageStyle+displayImage+");";
- }
- }
- else
- {
- gBackgroundImage = null;
- }
-
- // Set style on preview (removes image if not valid)
- gDialog.ColorPreview.setAttribute(styleStr, styleValue);
-
- // Note that an "empty" string is valid
- return retVal;
-}
-
-function ValidateData()
-{
- var editor = GetCurrentEditor();
- try {
- // Colors values are updated as they are picked, no validation necessary
- if (gDialog.DefaultColorsRadio.selected)
- {
- editor.removeAttributeOrEquivalent(globalElement, textStr, true);
- globalElement.removeAttribute(linkStr);
- globalElement.removeAttribute(vlinkStr);
- globalElement.removeAttribute(alinkStr);
- editor.removeAttributeOrEquivalent(globalElement, bgcolorStr, true);
- }
- else
- {
- //Do NOT accept the CSS "WindowsOS" color strings!
- // Problem: We really should try to get the actual color values
- // from windows, but I don't know how to do that!
- var tmpColor = customTextColor.toLowerCase();
- if (tmpColor != "windowtext")
- editor.setAttributeOrEquivalent(globalElement, textStr,
- customTextColor, true);
- else
- editor.removeAttributeOrEquivalent(globalElement, textStr, true);
-
- tmpColor = customBackgroundColor.toLowerCase();
- if (tmpColor != "window")
- editor.setAttributeOrEquivalent(globalElement, bgcolorStr, customBackgroundColor, true);
- else
- editor.removeAttributeOrEquivalent(globalElement, bgcolorStr, true);
-
- globalElement.setAttribute(linkStr, customLinkColor);
- globalElement.setAttribute(vlinkStr, customVisitedColor);
- globalElement.setAttribute(alinkStr, customActiveColor);
- }
-
- if (ValidateAndPreviewImage(true))
- {
- // A valid image may be null for no image
- if (gBackgroundImage)
- globalElement.setAttribute(backgroundStr, gBackgroundImage);
- else
- editor.removeAttributeOrEquivalent(globalElement, backgroundStr, true);
-
- return true;
- }
- } catch (e) {}
- return false;
-}
-
-function onAccept()
-{
- if (ValidateData())
- {
- // Copy attributes to element we are changing
- try {
- GetCurrentEditor().cloneAttributes(gBodyElement, globalElement);
- } catch (e) {}
-
- SaveWindowLocation();
- return true; // do close the window
- }
- return false;
-}
diff --git a/editor/ui/dialogs/content/EdColorProps.xul b/editor/ui/dialogs/content/EdColorProps.xul
deleted file mode 100644
index 9a3a55e2b..000000000
--- a/editor/ui/dialogs/content/EdColorProps.xul
+++ /dev/null
@@ -1,118 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorColorProperties.dtd">
-
-<dialog title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="Startup()"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdColorProps.js"/>
-
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
- <broadcaster id="args" value=""/>
-
- <groupbox align="start">
- <caption label="&pageColors.label;"/>
- <radiogroup id="PageColorGroup">
- <radio id="DefaultColorsRadio" label="&defaultColorsRadio.label;" oncommand="UseDefaultColors()"
- accesskey="&defaultColorsRadio.accessKey;"
- tooltiptext="&defaultColorsRadio.tooltip;" />
- <radio id="CustomColorsRadio" label="&customColorsRadio.label;" oncommand="UseCustomColors()"
- accesskey="&customColorsRadio.accessKey;"
- tooltiptext="&customColorsRadio.tooltip;" />
- </radiogroup>
- <hbox class="indent">
- <grid>
- <columns><column/><column/></columns>
- <rows>
- <row align="center">
- <label id="Text" control="TextButton"
- value="&normalText.label;&colon.character;"
- accesskey="&normalText.accessKey;"/>
- <button id="TextButton" class="color-button" oncommand="GetColorAndUpdate('textCW');">
- <spacer id="textCW" class="color-well"/>
- </button>
- </row>
- <row align="center">
- <label id="Link" control="LinkButton"
- value="&linkText.label;&colon.character;"
- accesskey="&linkText.accessKey;"/>
- <button id="LinkButton" class="color-button" oncommand="GetColorAndUpdate('linkCW');">
- <spacer id="linkCW" class="color-well"/>
- </button>
- </row>
- <row align="center">
- <label id="Active" control="ActiveLinkButton"
- value="&activeLinkText.label;&colon.character;"
- accesskey="&activeLinkText.accessKey;"/>
- <button id="ActiveLinkButton" class="color-button" oncommand="GetColorAndUpdate('activeCW');">
- <spacer id="activeCW" class="color-well"/>
- </button>
- </row>
- <row align="center">
- <label id="Visited" control="VisitedLinkButton"
- value="&visitedLinkText.label;&colon.character;"
- accesskey="&visitedLinkText.accessKey;"/>
- <button id="VisitedLinkButton" class="color-button" oncommand="GetColorAndUpdate('visitedCW');">
- <spacer id="visitedCW" class="color-well"/>
- </button>
- </row>
- <row align="center">
- <label id="Background" control="BackgroundButton"
- value="&background.label;"
- accesskey="&background.accessKey;"/>
- <button id="BackgroundButton" class="color-button" oncommand="GetColorAndUpdate('backgroundCW');">
- <spacer id="backgroundCW" class="color-well"/>
- </button>
- </row>
- </rows>
- </grid>
- <vbox id="ColorPreview" flex="1">
- <spacer flex="1"/>
- <label class="larger" id="NormalText" value="&normalText.label;"/>
- <spacer flex="1"/>
- <label class="larger" id="LinkText" value="&linkText.label;"/>
- <spacer flex="1"/>
- <label class="larger" id="ActiveLinkText" value="&activeLinkText.label;"/>
- <spacer flex="1"/>
- <label class="larger" id="VisitedLinkText" value="&visitedLinkText.label;"/>
- <spacer flex="1"/>
- </vbox>
- <spacer flex="1"/>
- </hbox>
- <spacer class="spacer"/>
- </groupbox>
- <spacer class="spacer"/>
- <label control="BackgroundImageInput"
- value="&backgroundImage.label;"
- accesskey="&backgroundImage.accessKey;"/>
- <textbox id="BackgroundImageInput" class="uri-element" oninput="ChangeBackgroundImage()"
- tooltiptext="&backgroundImage.tooltip;" flex="1"/>
- <hbox align="center">
- <!-- from EdDialogOverlay.xul 'for' identifies the textfield to get URL from -->
- <checkbox id="MakeRelativeCheckbox" for="BackgroundImageInput"/>
- <spacer flex="1"/>
- <!-- from EdDialogOverlay.xul -->
- <button id="ChooseFile"/>
- </hbox>
- <spacer class="smallspacer"/>
- <hbox>
- <spacer flex="1"/>
- <!-- from EdDialogOverlay.xul -->
- <button id="AdvancedEditButton"/>
- </hbox>
- <separator class="groove"/>
-</dialog>
diff --git a/editor/ui/dialogs/content/EdConvertToTable.js b/editor/ui/dialogs/content/EdConvertToTable.js
deleted file mode 100644
index 6e24b6f2d..000000000
--- a/editor/ui/dialogs/content/EdConvertToTable.js
+++ /dev/null
@@ -1,330 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var gIndex;
-var gCommaIndex = "0";
-var gSpaceIndex = "1";
-var gOtherIndex = "2";
-
-// dialog initialization code
-function Startup()
-{
- if (!GetCurrentEditor())
- {
- window.close();
- return;
- }
-
- gDialog.sepRadioGroup = document.getElementById("SepRadioGroup");
- gDialog.sepCharacterInput = document.getElementById("SepCharacterInput");
- gDialog.deleteSepCharacter = document.getElementById("DeleteSepCharacter");
- gDialog.collapseSpaces = document.getElementById("CollapseSpaces");
-
- // We persist the user's separator character
- gDialog.sepCharacterInput.value = gDialog.sepRadioGroup.getAttribute("character");
-
- gIndex = gDialog.sepRadioGroup.getAttribute("index");
-
- switch (gIndex)
- {
- case gCommaIndex:
- default:
- gDialog.sepRadioGroup.selectedItem = document.getElementById("comma");
- break;
- case gSpaceIndex:
- gDialog.sepRadioGroup.selectedItem = document.getElementById("space");
- break;
- case gOtherIndex:
- gDialog.sepRadioGroup.selectedItem = document.getElementById("other");
- break;
- }
-
- // Set initial enable state on character input and "collapse" checkbox
- SelectCharacter(gIndex);
-
- SetWindowLocation();
-}
-
-function InputSepCharacter()
-{
- var str = gDialog.sepCharacterInput.value;
-
- // Limit input to 1 character
- if (str.length > 1)
- str = str.slice(0,1);
-
- // We can never allow tag or entity delimiters for separator character
- if (str == "<" || str == ">" || str == "&" || str == ";" || str == " ")
- str = "";
-
- gDialog.sepCharacterInput.value = str;
-}
-
-function SelectCharacter(radioGroupIndex)
-{
- gIndex = radioGroupIndex;
- SetElementEnabledById("SepCharacterInput", gIndex == gOtherIndex);
- SetElementEnabledById("CollapseSpaces", gIndex == gSpaceIndex);
-}
-
-function onAccept()
-{
- var sepCharacter = "";
- switch (gIndex)
- {
- case gCommaIndex:
- sepCharacter = ",";
- break;
- case gSpaceIndex:
- sepCharacter = " ";
- break;
- case gOtherIndex:
- sepCharacter = gDialog.sepCharacterInput.value.slice(0,1);
- break;
- }
-
- var editor = GetCurrentEditor();
- var str;
- try {
- str = editor.outputToString("text/html", kOutputLFLineBreak | kOutputSelectionOnly);
- } catch (e) {}
- if (!str)
- {
- SaveWindowLocation();
- return true;
- }
-
- // Replace nbsp with spaces:
- str = str.replace(/\u00a0/g, " ");
-
- // Strip out </p> completely
- str = str.replace(/\s*<\/p>\s*/g, "");
-
- // Trim whitespace adjacent to <p> and <br> tags
- // and replace <p> with <br>
- // (which will be replaced with </tr> below)
- str = str.replace(/\s*<p>\s*|\s*<br>\s*/g, "<br>");
-
- // Trim leading <br>s
- str = str.replace(/^(<br>)+/, "");
-
- // Trim trailing <br>s
- str = str.replace(/(<br>)+$/, "");
-
- // Reduce multiple internal <br> to just 1
- // TODO: Maybe add a checkbox to let user decide
- //str = str.replace(/(<br>)+/g, "<br>");
-
- // Trim leading and trailing spaces
- str = str.trim();
-
- // Remove all tag contents so we don't replace
- // separator character within tags
- // Also converts lists to something usefull
- var stack = [];
- var start;
- var end;
- var searchStart = 0;
- var listSeparator = "";
- var listItemSeparator = "";
- var endList = false;
-
- do {
- start = str.indexOf("<", searchStart);
-
- if (start >= 0)
- {
- end = str.indexOf(">", start+1);
- if (end > start)
- {
- let tagContent = str.slice(start + 1, end).trim();
-
- if (/^ol|^ul|^dl/.test(tagContent))
- {
- // Replace list tag with <BR> to start new row
- // at begining of second or greater list tag
- str = str.slice(0, start) + listSeparator + str.slice(end+1);
- if (listSeparator == "")
- listSeparator = "<br>";
-
- // Reset for list item separation into cells
- listItemSeparator = "";
- }
- else if (/^li|^dt|^dd/.test(tagContent))
- {
- // Start a new row if this is first item after the ending the last list
- if (endList)
- listItemSeparator = "<br>";
-
- // Start new cell at begining of second or greater list items
- str = str.slice(0, start) + listItemSeparator + str.slice(end+1);
-
- if (endList || listItemSeparator == "")
- listItemSeparator = sepCharacter;
-
- endList = false;
- }
- else
- {
- // Find end tags
- endList = /^\/ol|^\/ul|^\/dl/.test(tagContent);
- if (endList || /^\/li|^\/dt|^\/dd/.test(tagContent))
- {
- // Strip out tag
- str = str.slice(0, start) + str.slice(end+1);
- }
- else
- {
- // Not a list-related tag: Store tag contents in an array
- stack.push(tagContent);
-
- // Keep the "<" and ">" while removing from source string
- start++;
- str = str.slice(0, start) + str.slice(end);
- }
- }
- }
- searchStart = start + 1;
- }
- } while (start >= 0);
-
- // Replace separator characters with table cells
- var replaceString;
- if (gDialog.deleteSepCharacter.checked)
- {
- replaceString = "";
- }
- else
- {
- // Don't delete separator character,
- // so include it at start of string to replace
- replaceString = sepCharacter;
- }
-
- replaceString += "<td>";
-
- if (sepCharacter.length > 0)
- {
- var tempStr = sepCharacter;
- var regExpChars = ".!@#$%^&*-+[]{}()\|\\\/";
- if (regExpChars.includes(sepCharacter))
- tempStr = "\\" + sepCharacter;
-
- if (gIndex == gSpaceIndex)
- {
- // If checkbox is checked,
- // one or more adjacent spaces are one separator
- if (gDialog.collapseSpaces.checked)
- tempStr = "\\s+"
- else
- tempStr = "\\s";
- }
- var pattern = new RegExp(tempStr, "g");
- str = str.replace(pattern, replaceString);
- }
-
- // Put back tag contents that we removed above
- searchStart = 0;
- var stackIndex = 0;
- do {
- start = str.indexOf("<", searchStart);
- end = start + 1;
- if (start >= 0 && str.charAt(end) == ">")
- {
- // We really need a FIFO stack!
- str = str.slice(0, end) + stack[stackIndex++] + str.slice(end);
- }
- searchStart = end;
-
- } while (start >= 0);
-
- // End table row and start another for each br or p
- str = str.replace(/\s*<br>\s*/g, "</tr>\n<tr><td>");
-
- // Add the table tags and the opening and closing tr/td tags
- // Default table attributes should be same as those used in nsHTMLEditor::CreateElementWithDefaults()
- // (Default width="100%" is used in EdInsertTable.js)
- str = "<table border=\"1\" width=\"100%\" cellpadding=\"2\" cellspacing=\"2\">\n<tr><td>" + str + "</tr>\n</table>\n";
-
- editor.beginTransaction();
-
- // Delete the selection -- makes it easier to find where table will insert
- var nodeBeforeTable = null;
- var nodeAfterTable = null;
- try {
- editor.deleteSelection(editor.eNone, editor.eStrip);
-
- var anchorNodeBeforeInsert = editor.selection.anchorNode;
- var offset = editor.selection.anchorOffset;
- if (anchorNodeBeforeInsert.nodeType == Node.TEXT_NODE)
- {
- // Text was split. Table should be right after the first or before
- nodeBeforeTable = anchorNodeBeforeInsert.previousSibling;
- nodeAfterTable = anchorNodeBeforeInsert;
- }
- else
- {
- // Table should be inserted right after node pointed to by selection
- if (offset > 0)
- nodeBeforeTable = anchorNodeBeforeInsert.childNodes.item(offset - 1);
-
- nodeAfterTable = anchorNodeBeforeInsert.childNodes.item(offset);
- }
-
- editor.insertHTML(str);
- } catch (e) {}
-
- var table = null;
- if (nodeAfterTable)
- {
- var previous = nodeAfterTable.previousSibling;
- if (previous && previous.nodeName.toLowerCase() == "table")
- table = previous;
- }
- if (!table && nodeBeforeTable)
- {
- var next = nodeBeforeTable.nextSibling;
- if (next && next.nodeName.toLowerCase() == "table")
- table = next;
- }
-
- if (table)
- {
- // Fixup table only if pref is set
- var firstRow;
- try {
- if (Services.prefs.getBoolPref("editor.table.maintain_structure"))
- editor.normalizeTable(table);
-
- firstRow = editor.getFirstRow(table);
- } catch(e) {}
-
- // Put caret in first cell
- if (firstRow)
- {
- var node2 = firstRow.firstChild;
- do {
- if (node2.nodeName.toLowerCase() == "td" ||
- node2.nodeName.toLowerCase() == "th")
- {
- try {
- editor.selection.collapse(node2, 0);
- } catch(e) {}
- break;
- }
- node2 = node.nextSibling;
- } while (node2);
- }
- }
-
- editor.endTransaction();
-
- // Save persisted attributes
- gDialog.sepRadioGroup.setAttribute("index", gIndex);
- if (gIndex == gOtherIndex)
- gDialog.sepRadioGroup.setAttribute("character", sepCharacter);
-
- SaveWindowLocation();
- return true;
-}
diff --git a/editor/ui/dialogs/content/EdConvertToTable.xul b/editor/ui/dialogs/content/EdConvertToTable.xul
deleted file mode 100644
index 2a8eb3817..000000000
--- a/editor/ui/dialogs/content/EdConvertToTable.xul
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EdConvertToTable.dtd">
-
-<dialog title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload = "Startup()"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();"
- style="min-width:20em">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <!--- Element-specific methods -->
- <script type="application/javascript" src="chrome://editor/content/EdConvertToTable.js"/>
-
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
- <description class="wrap" flex="1">&instructions1.label;</description>
- <description class="wrap" flex="1">&instructions2.label;</description>
- <radiogroup id="SepRadioGroup" persist="index character" index="0" character="">
- <radio id="comma" label="&commaRadio.label;" oncommand="SelectCharacter('0');"/>
- <radio id="space" label="&spaceRadio.label;" oncommand="SelectCharacter('1');"/>
- <hbox>
- <spacer class="radio-spacer"/>
- <checkbox id="CollapseSpaces" label="&collapseSpaces.label;"
- checked="true" persist="checked"
- tooltiptext="&collapseSpaces.tooltip;"/>
- </hbox>
- <hbox align="center">
- <radio id="other" label="&otherRadio.label;" oncommand="SelectCharacter('2');"/>
- <textbox class="narrow" id="SepCharacterInput" oninput="InputSepCharacter()"/>
- </hbox>
- </radiogroup>
- <spacer class="spacer"/>
- <checkbox id="DeleteSepCharacter" label="&deleteCharCheck.label;" persist="checked"/>
- <separator class="groove"/>
-</dialog>
diff --git a/editor/ui/dialogs/content/EdDialogCommon.js b/editor/ui/dialogs/content/EdDialogCommon.js
deleted file mode 100644
index 570189ae4..000000000
--- a/editor/ui/dialogs/content/EdDialogCommon.js
+++ /dev/null
@@ -1,1001 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// Each editor window must include this file
-
-// Object to attach commonly-used widgets (all dialogs should use this)
-var gDialog = {};
-
-var gValidationError = false;
-
-// Use for 'defaultIndex' param in InitPixelOrPercentMenulist
-const gPixel = 0;
-const gPercent = 1;
-
-const gMaxPixels = 100000; // Used for image size, borders, spacing, and padding
-// Gecko code uses 1000 for maximum rowspan, colspan
-// Also, editing performance is really bad above this
-const gMaxRows = 1000;
-const gMaxColumns = 1000;
-const gMaxTableSize = 1000000; // Width or height of table or cells
-
-// For dialogs that expand in size. Default is smaller size see "onMoreFewer()" below
-var SeeMore = false;
-
-// A XUL element with id="location" for managing
-// dialog location relative to parent window
-var gLocation;
-
-// The element being edited - so AdvancedEdit can have access to it
-var globalElement;
-
-/* Validate contents of an input field
- *
- * inputWidget The 'textbox' XUL element for text input of the attribute's value
- * listWidget The 'menulist' XUL element for choosing "pixel" or "percent"
- * May be null when no pixel/percent is used.
- * minVal minimum allowed for input widget's value
- * maxVal maximum allowed for input widget's value
- * (when "listWidget" is used, maxVal is used for "pixel" maximum,
- * 100% is assumed if "percent" is the user's choice)
- * element The DOM element that we set the attribute on. May be null.
- * attName Name of the attribute to set. May be null or ignored if "element" is null
- * mustHaveValue If true, error dialog is displayed if "value" is empty string
- *
- * This calls "ValidateNumberRange()", which puts up an error dialog to inform the user.
- * If error, we also:
- * Shift focus and select contents of the inputWidget,
- * Switch to appropriate panel of tabbed dialog if user implements "SwitchToValidate()",
- * and/or will expand the dialog to full size if "More / Fewer" feature is implemented
- *
- * Returns the "value" as a string, or "" if error or input contents are empty
- * The global "gValidationError" variable is set true if error was found
- */
-function ValidateNumber(inputWidget, listWidget, minVal, maxVal, element, attName, mustHaveValue, mustShowMoreSection)
-{
- if (!inputWidget)
- {
- gValidationError = true;
- return "";
- }
-
- // Global error return value
- gValidationError = false;
- var maxLimit = maxVal;
- var isPercent = false;
-
- var numString = TrimString(inputWidget.value);
- if (numString || mustHaveValue)
- {
- if (listWidget)
- isPercent = (listWidget.selectedIndex == 1);
- if (isPercent)
- maxLimit = 100;
-
- // This method puts up the error message
- numString = ValidateNumberRange(numString, minVal, maxLimit, mustHaveValue);
- if(!numString)
- {
- // Switch to appropriate panel for error reporting
- SwitchToValidatePanel();
-
- // or expand dialog for users of "More / Fewer" button
- if ("dialog" in window && dialog &&
- "MoreSection" in gDialog && gDialog.MoreSection)
- {
- if ( !SeeMore )
- onMoreFewer();
- }
-
- // Error - shift to offending input widget
- SetTextboxFocus(inputWidget);
- gValidationError = true;
- }
- else
- {
- if (isPercent)
- numString += "%";
- if (element)
- GetCurrentEditor().setAttributeOrEquivalent(element, attName, numString, true);
- }
- } else if (element) {
- GetCurrentEditor().removeAttributeOrEquivalent(element, attName, true)
- }
- return numString;
-}
-
-/* Validate contents of an input field
- *
- * value number to validate
- * minVal minimum allowed for input widget's value
- * maxVal maximum allowed for input widget's value
- * (when "listWidget" is used, maxVal is used for "pixel" maximum,
- * 100% is assumed if "percent" is the user's choice)
- * mustHaveValue If true, error dialog is displayed if "value" is empty string
- *
- * If inputWidget's value is outside of range, or is empty when "mustHaveValue" = true,
- * an error dialog is popuped up to inform the user. The focus is shifted
- * to the inputWidget.
- *
- * Returns the "value" as a string, or "" if error or input contents are empty
- * The global "gValidationError" variable is set true if error was found
- */
-function ValidateNumberRange(value, minValue, maxValue, mustHaveValue)
-{
- // Initialize global error flag
- gValidationError = false;
- value = TrimString(String(value));
-
- // We don't show error for empty string unless caller wants to
- if (!value && !mustHaveValue)
- return "";
-
- var numberStr = "";
-
- if (value.length > 0)
- {
- // Extract just numeric characters
- var number = Number(value.replace(/\D+/g, ""));
- if (number >= minValue && number <= maxValue )
- {
- // Return string version of the number
- return String(number);
- }
- numberStr = String(number);
- }
-
- var message = "";
-
- if (numberStr.length > 0)
- {
- // We have a number from user outside of allowed range
- message = GetString( "ValidateRangeMsg");
- message = message.replace(/%n%/, numberStr);
- message += "\n ";
- }
- message += GetString( "ValidateNumberMsg");
-
- // Replace variable placeholders in message with number values
- message = message.replace(/%min%/, minValue).replace(/%max%/, maxValue);
- ShowInputErrorMessage(message);
-
- // Return an empty string to indicate error
- gValidationError = true;
- return "";
-}
-
-function SetTextboxFocusById(id)
-{
- SetTextboxFocus(document.getElementById(id));
-}
-
-function SetTextboxFocus(textbox)
-{
- if (textbox)
- {
- //XXX Using the setTimeout is hacky workaround for bug 103197
- // Must create a new function to keep "textbox" in scope
- setTimeout( function(textbox) { textbox.focus(); textbox.select(); }, 0, textbox );
- }
-}
-
-function ShowInputErrorMessage(message)
-{
- Services.prompt.alert(window, GetString("InputError"), message);
- window.focus();
-}
-
-// Get the text appropriate to parent container
-// to determine what a "%" value is referring to.
-// elementForAtt is element we are actually setting attributes on
-// (a temporary copy of element in the doc to allow canceling),
-// but elementInDoc is needed to find parent context in document
-function GetAppropriatePercentString(elementForAtt, elementInDoc)
-{
- var editor = GetCurrentEditor();
- try {
- var name = elementForAtt.nodeName.toLowerCase();
- if ( name == "td" || name == "th")
- return GetString("PercentOfTable");
-
- // Check if element is within a table cell
- if (editor.getElementOrParentByTagName("td", elementInDoc))
- return GetString("PercentOfCell");
- else
- return GetString("PercentOfWindow");
- } catch (e) { return "";}
-}
-
-function ClearListbox(listbox)
-{
- if (listbox)
- {
- listbox.clearSelection();
- while (listbox.hasChildNodes())
- listbox.lastChild.remove();
- }
-}
-
-function forceInteger(elementID)
-{
- var editField = document.getElementById( elementID );
- if ( !editField )
- return;
-
- var stringIn = editField.value;
- if (stringIn && stringIn.length > 0)
- {
- // Strip out all nonnumeric characters
- stringIn = stringIn.replace(/\D+/g,"");
- if (!stringIn) stringIn = "";
-
- // Write back only if changed
- if (stringIn != editField.value)
- editField.value = stringIn;
- }
-}
-
-function InitPixelOrPercentMenulist(elementForAtt, elementInDoc, attribute, menulistID, defaultIndex)
-{
- if (!defaultIndex) defaultIndex = gPixel;
-
- // var size = elementForAtt.getAttribute(attribute);
- var size = GetHTMLOrCSSStyleValue(elementForAtt, attribute, attribute)
- var menulist = document.getElementById(menulistID);
- var pixelItem;
- var percentItem;
-
- if (!menulist)
- {
- dump("NO MENULIST found for ID="+menulistID+"\n");
- return size;
- }
-
- menulist.removeAllItems();
- pixelItem = menulist.appendItem(GetString("Pixels"));
-
- if (!pixelItem) return 0;
-
- percentItem = menulist.appendItem(GetAppropriatePercentString(elementForAtt, elementInDoc));
- if (size && size.length > 0)
- {
- // Search for a "%" or "px"
- if (size.includes("%"))
- {
- // Strip out the %
- size = size.substr(0, size.indexOf("%"));
- if (percentItem)
- menulist.selectedItem = percentItem;
- }
- else
- {
- if (size.includes("px"))
- // Strip out the px
- size = size.substr(0, size.indexOf("px"));
- menulist.selectedItem = pixelItem;
- }
- }
- else
- menulist.selectedIndex = defaultIndex;
-
- return size;
-}
-
-function onAdvancedEdit()
-{
- // First validate data from widgets in the "simpler" property dialog
- if (ValidateData())
- {
- // Set true if OK is clicked in the Advanced Edit dialog
- window.AdvancedEditOK = false;
- // Open the AdvancedEdit dialog, passing in the element to be edited
- // (the copy named "globalElement")
- window.openDialog("chrome://editor/content/EdAdvancedEdit.xul", "_blank", "chrome,close,titlebar,modal,resizable=yes", "", globalElement);
- window.focus();
- if (window.AdvancedEditOK)
- {
- // Copy edited attributes to the dialog widgets:
- InitDialog();
- }
- }
-}
-
-function getColor(ColorPickerID)
-{
- var colorPicker = document.getElementById(ColorPickerID);
- var color;
- if (colorPicker)
- {
- // Extract color from colorPicker and assign to colorWell.
- color = colorPicker.getAttribute("color");
- if (color && color == "")
- return null;
- // Clear color so next if it's called again before
- // color picker is actually used, we dedect the "don't set color" state
- colorPicker.setAttribute("color","");
- }
-
- return color;
-}
-
-function setColorWell(ColorWellID, color)
-{
- var colorWell = document.getElementById(ColorWellID);
- if (colorWell)
- {
- if (!color || color == "")
- {
- // Don't set color (use default)
- // Trigger change to not show color swatch
- colorWell.setAttribute("default","true");
- // Style in CSS sets "background-color",
- // but color won't clear unless we do this:
- colorWell.removeAttribute("style");
- }
- else
- {
- colorWell.removeAttribute("default");
- // Use setAttribute so colorwell can be a XUL element, such as button
- colorWell.setAttribute("style", "background-color:"+color);
- }
- }
-}
-
-function getColorAndSetColorWell(ColorPickerID, ColorWellID)
-{
- var color = getColor(ColorPickerID);
- setColorWell(ColorWellID, color);
- return color;
-}
-
-function InitMoreFewer()
-{
- // Set SeeMore bool to the OPPOSITE of the current state,
- // which is automatically saved by using the 'persist="more"'
- // attribute on the gDialog.MoreFewerButton button
- // onMoreFewer will toggle it and redraw the dialog
- SeeMore = (gDialog.MoreFewerButton.getAttribute("more") != "1");
- onMoreFewer();
- gDialog.MoreFewerButton.setAttribute("accesskey",GetString("PropertiesAccessKey"));
-}
-
-function onMoreFewer()
-{
- if (SeeMore)
- {
- gDialog.MoreSection.collapsed = true;
- gDialog.MoreFewerButton.setAttribute("more","0");
- gDialog.MoreFewerButton.setAttribute("label",GetString("MoreProperties"));
- SeeMore = false;
- }
- else
- {
- gDialog.MoreSection.collapsed = false;
- gDialog.MoreFewerButton.setAttribute("more","1");
- gDialog.MoreFewerButton.setAttribute("label",GetString("FewerProperties"));
- SeeMore = true;
- }
- window.sizeToContent();
-}
-
-function SwitchToValidatePanel()
-{
- // no default implementation
- // Only EdTableProps.js currently implements this
-}
-
-const nsIFilePicker = Components.interfaces.nsIFilePicker;
-
-function GetLocalFileURL(filterType)
-{
- var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
- var fileType = "html";
-
- if (filterType == "img")
- {
- fp.init(window, GetString("SelectImageFile"), nsIFilePicker.modeOpen);
- fp.appendFilters(nsIFilePicker.filterImages);
- fileType = "image";
- }
- // Current usage of this is in Link dialog,
- // where we always want HTML first
- else if (filterType.startsWith("html"))
- {
- fp.init(window, GetString("OpenHTMLFile"), nsIFilePicker.modeOpen);
-
- // When loading into Composer, direct user to prefer HTML files and text files,
- // so we call separately to control the order of the filter list
- fp.appendFilters(nsIFilePicker.filterHTML);
- fp.appendFilters(nsIFilePicker.filterText);
-
- // Link dialog also allows linking to images
- if (filterType.includes("img", 1))
- fp.appendFilters(nsIFilePicker.filterImages);
-
- }
- // Default or last filter is "All Files"
- fp.appendFilters(nsIFilePicker.filterAll);
-
- // set the file picker's current directory to last-opened location saved in prefs
- SetFilePickerDirectory(fp, fileType);
-
-
- /* doesn't handle *.shtml files */
- try {
- var ret = fp.show();
- if (ret == nsIFilePicker.returnCancel)
- return null;
- }
- catch (ex) {
- dump("filePicker.chooseInputFile threw an exception\n");
- return null;
- }
- SaveFilePickerDirectory(fp, fileType);
-
- var fileHandler = GetFileProtocolHandler();
- return fp.file ? fileHandler.getURLSpecFromFile(fp.file) : null;
-}
-
-function GetMetaElementByAttribute(name, value)
-{
- if (name)
- {
- name = name.toLowerCase();
- let editor = GetCurrentEditor();
- try {
- return editor.document.querySelector('meta[' + name + '="' + value + '"]');
- } catch (e) {}
- }
- return null;
-}
-
-function CreateMetaElementWithAttribute(name, value)
-{
- let editor = GetCurrentEditor();
- try {
- let metaElement = editor.createElementWithDefaults("meta");
- if (name) {
- metaElement.setAttribute(name, value);
- }
- return metaElement;
- } catch (e) {}
- return null;
-}
-
-// Change "content" attribute on a META element,
-// or delete entire element it if content is empty
-// This uses undoable editor transactions
-function SetMetaElementContent(metaElement, content, insertNew, prepend)
-{
- if (metaElement)
- {
- var editor = GetCurrentEditor();
- try {
- if(!content || content == "")
- {
- if (!insertNew)
- editor.deleteNode(metaElement);
- }
- else
- {
- if (insertNew)
- {
- metaElement.setAttribute("content", content);
- if (prepend)
- PrependHeadElement(metaElement);
- else
- AppendHeadElement(metaElement);
- }
- else
- editor.setAttribute(metaElement, "content", content);
- }
- } catch (e) {}
- }
-}
-
-function GetHeadElement()
-{
- var editor = GetCurrentEditor();
- try {
- return editor.document.querySelector("head");
- } catch (e) {}
-
- return null;
-}
-
-function PrependHeadElement(element)
-{
- var head = GetHeadElement();
- if (head)
- {
- var editor = GetCurrentEditor();
- try {
- // Use editor's undoable transaction
- // Last param "true" says "don't change the selection"
- editor.insertNode(element, head, 0, true);
- } catch (e) {}
- }
-}
-
-function AppendHeadElement(element)
-{
- var head = GetHeadElement();
- if (head)
- {
- var position = 0;
- if (head.hasChildNodes())
- position = head.childNodes.length;
-
- var editor = GetCurrentEditor();
- try {
- // Use editor's undoable transaction
- // Last param "true" says "don't change the selection"
- editor.insertNode(element, head, position, true);
- } catch (e) {}
- }
-}
-
-function SetWindowLocation()
-{
- gLocation = document.getElementById("location");
- if (gLocation)
- {
- window.screenX = Math.max(0, Math.min(window.opener.screenX + Number(gLocation.getAttribute("offsetX")),
- screen.availWidth - window.outerWidth));
- window.screenY = Math.max(0, Math.min(window.opener.screenY + Number(gLocation.getAttribute("offsetY")),
- screen.availHeight - window.outerHeight));
- }
-}
-
-function SaveWindowLocation()
-{
- if (gLocation)
- {
- var newOffsetX = window.screenX - window.opener.screenX;
- var newOffsetY = window.screenY - window.opener.screenY;
- gLocation.setAttribute("offsetX", window.screenX - window.opener.screenX);
- gLocation.setAttribute("offsetY", window.screenY - window.opener.screenY);
- }
-}
-
-function onCancel()
-{
- SaveWindowLocation();
- // Close dialog by returning true
- return true;
-}
-
-function SetRelativeCheckbox(checkbox)
-{
- if (!checkbox) {
- checkbox = document.getElementById("MakeRelativeCheckbox");
- if (!checkbox)
- return;
- }
-
- var editor = GetCurrentEditor();
- // Mail never allows relative URLs, so hide the checkbox
- if (editor && (editor.flags & Components.interfaces.nsIPlaintextEditor.eEditorMailMask))
- {
- checkbox.collapsed = true;
- return;
- }
-
- var input = document.getElementById(checkbox.getAttribute("for"));
- if (!input)
- return;
-
- var url = TrimString(input.value);
- var urlScheme = GetScheme(url);
-
- // Check it if url is relative (no scheme).
- checkbox.checked = url.length > 0 && !urlScheme;
-
- // Now do checkbox enabling:
- var enable = false;
-
- var docUrl = GetDocumentBaseUrl();
- var docScheme = GetScheme(docUrl);
-
- if (url && docUrl && docScheme)
- {
- if (urlScheme)
- {
- // Url is absolute
- // If we can make a relative URL, then enable must be true!
- // (this lets the smarts of MakeRelativeUrl do all the hard work)
- enable = (GetScheme(MakeRelativeUrl(url)).length == 0);
- }
- else
- {
- // Url is relative
- // Check if url is a named anchor
- // but document doesn't have a filename
- // (it's probably "index.html" or "index.htm",
- // but we don't want to allow a malformed URL)
- if (url[0] == "#")
- {
- var docFilename = GetFilename(docUrl);
- enable = docFilename.length > 0;
- }
- else
- {
- // Any other url is assumed
- // to be ok to try to make absolute
- enable = true;
- }
- }
- }
-
- SetElementEnabled(checkbox, enable);
-}
-
-// oncommand handler for the Relativize checkbox in EditorOverlay.xul
-function MakeInputValueRelativeOrAbsolute(checkbox)
-{
- var input = document.getElementById(checkbox.getAttribute("for"));
- if (!input)
- return;
-
- var docUrl = GetDocumentBaseUrl();
- if (!docUrl)
- {
- // Checkbox should be disabled if not saved,
- // but keep this error message in case we change that
- Services.prompt.alert(window, "", GetString("SaveToUseRelativeUrl"));
- window.focus();
- }
- else
- {
- // Note that "checked" is opposite of its last state,
- // which determines what we want to do here
- if (checkbox.checked)
- input.value = MakeRelativeUrl(input.value);
- else
- input.value = MakeAbsoluteUrl(input.value);
-
- // Reset checkbox to reflect url state
- SetRelativeCheckbox(checkbox);
- }
-}
-
-var IsBlockParent = [
- "applet",
- "blockquote",
- "body",
- "center",
- "dd",
- "div",
- "form",
- "li",
- "noscript",
- "object",
- "td",
- "th",
-];
-
-var NotAnInlineParent = [
- "col",
- "colgroup",
- "dl",
- "dir",
- "menu",
- "ol",
- "table",
- "tbody",
- "tfoot",
- "thead",
- "tr",
- "ul",
-];
-
-function nodeIsBreak(editor, node)
-{
- // XXX This doesn't work because .localName is lowercase (see bug 1306060).
- return !node || node.localName == 'BR' || editor.nodeIsBlock(node);
-}
-
-function InsertElementAroundSelection(element)
-{
- var editor = GetCurrentEditor();
- editor.beginTransaction();
-
- try {
- // First get the selection as a single range
- var range, start, end, offset;
- var count = editor.selection.rangeCount;
- if (count == 1)
- range = editor.selection.getRangeAt(0).cloneRange();
- else
- {
- range = editor.document.createRange();
- start = editor.selection.getRangeAt(0)
- range.setStart(start.startContainer, start.startOffset);
- end = editor.selection.getRangeAt(--count);
- range.setEnd(end.endContainer, end.endOffset);
- }
-
- // Flatten the selection to child nodes of the common ancestor
- while (range.startContainer != range.commonAncestorContainer)
- range.setStartBefore(range.startContainer);
- while (range.endContainer != range.commonAncestorContainer)
- range.setEndAfter(range.endContainer);
-
- if (editor.nodeIsBlock(element))
- // Block element parent must be a valid block
- while (!IsBlockParent.includes(range.commonAncestorContainer.localName))
- range.selectNode(range.commonAncestorContainer);
- else
- {
- // Fail if we're not inserting a block (use setInlineProperty instead)
- if (!nodeIsBreak(editor, range.commonAncestorContainer))
- return false;
- else if (NotAnInlineParent.includes(range.commonAncestorContainer.localName))
- // Inline element parent must not be an invalid block
- do range.selectNode(range.commonAncestorContainer);
- while (NotAnInlineParent.includes(range.commonAncestorContainer.localName));
- else
- // Further insert block check
- for (var i = range.startOffset; ; i++)
- if (i == range.endOffset)
- return false;
- else if (nodeIsBreak(editor, range.commonAncestorContainer.childNodes[i]))
- break;
- }
-
- // The range may be contained by body text, which should all be selected.
- offset = range.startOffset;
- start = range.startContainer.childNodes[offset];
- if (!nodeIsBreak(editor, start))
- {
- while (!nodeIsBreak(editor, start.previousSibling))
- {
- start = start.previousSibling;
- offset--;
- }
- }
- end = range.endContainer.childNodes[range.endOffset];
- if (end && !nodeIsBreak(editor, end.previousSibling))
- {
- while (!nodeIsBreak(editor, end))
- end = end.nextSibling;
- }
-
- // Now insert the node
- editor.insertNode(element, range.commonAncestorContainer, offset, true);
- offset = element.childNodes.length;
- if (!editor.nodeIsBlock(element))
- editor.setShouldTxnSetSelection(false);
-
- // Move all the old child nodes to the element
- var empty = true;
- while (start != end)
- {
- var next = start.nextSibling;
- editor.deleteNode(start);
- editor.insertNode(start, element, element.childNodes.length);
- empty = false;
- start = next;
- }
- if (!editor.nodeIsBlock(element))
- editor.setShouldTxnSetSelection(true);
- else
- {
- // Also move a trailing <br>
- // XXX This doesn't work because .localName is lowercase (see bug 1306060).
- if (start && start.localName == 'BR')
- {
- editor.deleteNode(start);
- editor.insertNode(start, element, element.childNodes.length);
- empty = false;
- }
- // Still nothing? Insert a <br> so the node is not empty
- if (empty)
- editor.insertNode(editor.createElementWithDefaults("br"), element, element.childNodes.length);
-
- // Hack to set the selection just inside the element
- editor.insertNode(editor.document.createTextNode(""), element, offset);
- }
- }
- finally {
- editor.endTransaction();
- }
-
- return true;
-}
-
-function nodeIsBlank(node)
-{
- return node && node.nodeType == Node.TEXT_NODE && !/\S/.test(node.data);
-}
-
-function nodeBeginsBlock(editor, node)
-{
- while (nodeIsBlank(node))
- node = node.nextSibling;
- return nodeIsBreak(editor, node);
-}
-
-function nodeEndsBlock(editor, node)
-{
- while (nodeIsBlank(node))
- node = node.previousSibling;
- return nodeIsBreak(editor, node);
-}
-
-// C++ function isn't exposed to JS :-(
-function RemoveBlockContainer(element)
-{
- var editor = GetCurrentEditor();
- editor.beginTransaction();
-
- try {
- var range = editor.document.createRange();
- range.selectNode(element);
- var offset = range.startOffset;
- var parent = element.parentNode;
-
- // May need to insert a break after the removed element
- if (!nodeBeginsBlock(editor, element.nextSibling) &&
- !nodeEndsBlock(editor, element.lastChild))
- editor.insertNode(editor.createElementWithDefaults("br"), parent, range.endOffset);
-
- // May need to insert a break before the removed element, or if it was empty
- if (!nodeEndsBlock(editor, element.previousSibling) &&
- !nodeBeginsBlock(editor, element.firstChild || element.nextSibling))
- editor.insertNode(editor.createElementWithDefaults("br"), parent, offset++);
-
- // Now remove the element
- editor.deleteNode(element);
-
- // Need to copy the contained nodes?
- for (var i = 0; i < element.childNodes.length; i++)
- editor.insertNode(element.childNodes[i].cloneNode(true), parent, offset++);
- }
- finally {
- editor.endTransaction();
- }
-}
-
-// C++ function isn't exposed to JS :-(
-function RemoveContainer(element)
-{
- var editor = GetCurrentEditor();
- editor.beginTransaction();
-
- try {
- var range = editor.document.createRange();
- var parent = element.parentNode;
- // Allow for automatic joining of text nodes
- // so we can't delete the container yet
- // so we need to copy the contained nodes
- for (var i = 0; i < element.childNodes.length; i++) {
- range.selectNode(element);
- editor.insertNode(element.childNodes[i].cloneNode(true), parent, range.startOffset);
- }
- // Now remove the element
- editor.deleteNode(element);
- }
- finally {
- editor.endTransaction();
- }
-}
-
-function FillLinkMenulist(linkMenulist, headingsArray)
-{
- var menupopup = linkMenulist.firstChild;
- var editor = GetCurrentEditor();
- try {
- var treeWalker = editor.document.createTreeWalker(editor.document, 1, null, true);
- var headingList = [];
- var anchorList = []; // for sorting
- var anchorMap = {}; // for weeding out duplicates and making heading anchors unique
- var anchor;
- var i;
- for (var element = treeWalker.nextNode(); element; element = treeWalker.nextNode())
- {
- // grab headings
- // Skip headings that already have a named anchor as their first child
- // (this may miss nearby anchors, but at least we don't insert another
- // under the same heading)
- if (element instanceof HTMLHeadingElement && element.textContent &&
- !(element.firstChild instanceof HTMLAnchorElement && element.firstChild.name))
- headingList.push(element);
-
- // grab named anchors
- if (element instanceof HTMLAnchorElement && element.name)
- {
- anchor = '#' + element.name;
- if (!(anchor in anchorMap))
- {
- anchorList.push({anchor: anchor, sortkey: anchor.toLowerCase()});
- anchorMap[anchor] = true;
- }
- }
-
- // grab IDs
- if (element.id)
- {
- anchor = '#' + element.id;
- if (!(anchor in anchorMap))
- {
- anchorList.push({anchor: anchor, sortkey: anchor.toLowerCase()});
- anchorMap[anchor] = true;
- }
- }
- }
- // add anchor for headings
- for (i = 0; i < headingList.length; i++)
- {
- var heading = headingList[i];
-
- // Use just first 40 characters, don't add "...",
- // and replace whitespace with "_" and strip non-word characters
- anchor = '#' + ConvertToCDATAString(TruncateStringAtWordEnd(heading.textContent, 40, false));
-
- // Append "_" to any name already in the list
- while (anchor in anchorMap)
- anchor += "_";
- anchorList.push({anchor: anchor, sortkey: anchor.toLowerCase()});
- anchorMap[anchor] = true;
-
- // Save nodes in an array so we can create anchor node under it later
- headingsArray[anchor] = heading;
- }
- if (anchorList.length)
- {
- // case insensitive sort
- anchorList.sort(function compare(a, b) {
- if (a.sortkey < b.sortkey) return -1;
- if (a.sortkey > b.sortkey) return 1;
- return 0;
- });
-
- for (i = 0; i < anchorList.length; i++)
- createMenuItem(menupopup,anchorList[i].anchor);
- }
- else
- {
- // Don't bother with named anchors in Mail.
- if (editor && (editor.flags & Components.interfaces.nsIPlaintextEditor.eEditorMailMask))
- {
- menupopup.remove();
- linkMenulist.removeAttribute("enablehistory");
- return;
- }
- var item = createMenuItem(menupopup, GetString("NoNamedAnchorsOrHeadings"));
- item.setAttribute("disabled", "true");
- }
- } catch (e) {}
-}
-
-function createMenuItem(aMenuPopup, aLabel)
-{
- var menuitem = document.createElement("menuitem");
- menuitem.setAttribute("label", aLabel);
- aMenuPopup.appendChild(menuitem);
- return menuitem;
-}
-
-// Shared by Image and Link dialogs for the "Choose" button for links
-function chooseLinkFile()
-{
- // Get a local file, converted into URL format
- var fileName = GetLocalFileURL("html, img");
- if (fileName)
- {
- // Always try to relativize local file URLs
- if (gHaveDocumentUrl)
- fileName = MakeRelativeUrl(fileName);
-
- gDialog.hrefInput.value = fileName;
-
- // Do stuff specific to a particular dialog
- // (This is defined separately in Image and Link dialogs)
- ChangeLinkLocation();
- }
- // Put focus into the input field
- SetTextboxFocus(gDialog.hrefInput);
-}
-
diff --git a/editor/ui/dialogs/content/EdDialogOverlay.xul b/editor/ui/dialogs/content/EdDialogOverlay.xul
deleted file mode 100644
index 8c3308071..000000000
--- a/editor/ui/dialogs/content/EdDialogOverlay.xul
+++ /dev/null
@@ -1,76 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE overlay SYSTEM "chrome://editor/locale/EdDialogOverlay.dtd">
-
-<overlay id="EdDialogOverlay"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
-<vbox id="AdvancedEdit">
- <hbox flex="1" style="margin-top: 0.2em" align="center">
- <!-- This will right-align the button -->
- <spacer flex="1"/>
- <button id="AdvancedEditButton1" oncommand="onAdvancedEdit()" label="&AdvancedEditButton.label;"
- accesskey="&AdvancedEditButton.accessKey;" tooltiptext="&AdvancedEditButton.tooltip;"/>
- </hbox>
- <separator id="advancedSeparator" class="groove"/>
-</vbox>
-
-<!-- Extra buttons to use when just button is needed
- E.g. Image Properties Dialog switches position between 2 locations
- Placed here to use same attributes as AdvancedEditButton button
--->
-<button
- id = "AdvancedEditButton"
- oncommand = "onAdvancedEdit();"
- label = "&AdvancedEditButton.label;"
- accesskey = "&AdvancedEditButton.accessKey;"
- tooltiptext="&AdvancedEditButton.tooltip;"/>
-
-<button
- id = "AdvancedEditButton2"
- oncommand = "onAdvancedEdit()"
- label = "&AdvancedEditButton.label;"
- accesskey = "&AdvancedEditButton.accessKey;"
- tooltiptext="&AdvancedEditButton.tooltip;"/>
-
-<button
- id = "ChooseFile"
- oncommand = "chooseFile()"
- label = "&chooseFileButton.label;"
- accesskey = "&chooseFileButton.accessKey;"/>
-
-<checkbox
- id = "MakeRelativeCheckbox"
- label = "&makeUrlRelative.label;"
- accesskey = "&makeUrlRelative.accessKey;"
- oncommand = "MakeInputValueRelativeOrAbsolute(this);"
- tooltiptext = "&makeUrlRelative.tooltip;"/>
-
-<vbox id="LinkLocationBox">
- <label control="hrefInput" accesskey="&LinkURLEditField.accessKey;" width="1">&LinkURLEditField.label;</label>
- <textbox id="hrefInput" type="autocomplete"
- autocompletesearch="unifiedcomplete" timeout="50" maxrows="6"
- enablehistory="true" class="uri-element padded"
- oninput="ChangeLinkLocation();">
- <menupopup class="autocomplete-history-popup"
- popupalign="topleft" popupanchor="bottomleft"
- oncommand="this.parentNode.value = event.target.getAttribute('label'); ChangeLinkLocation();"/>
- </textbox>
- <hbox align="center">
- <!-- from EdDialogOverlay.xul 'for' identifies the textfield to get URL from -->
- <checkbox id="MakeRelativeLink"
- for="hrefInput"
- label="&makeUrlRelative.label;"
- accesskey="&makeUrlRelative.accessKey;"
- oncommand="MakeInputValueRelativeOrAbsolute(this);"
- tooltiptext="&makeUrlRelative.tooltip;"/>
- <spacer flex="1"/>
- <button label="&chooseFileLinkButton.label;" accesskey="&chooseFileLinkButton.accessKey;" oncommand="chooseLinkFile();"/>
- </hbox>
-</vbox>
-
-</overlay>
diff --git a/editor/ui/dialogs/content/EdDialogTemplate.js b/editor/ui/dialogs/content/EdDialogTemplate.js
deleted file mode 100644
index 1a29c25f8..000000000
--- a/editor/ui/dialogs/content/EdDialogTemplate.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-//Cancel() is in EdDialogCommon.js
-var insertNew = true;
-var tagname = "TAG NAME"
-
-// dialog initialization code
-function Startup()
-{
- if (!GetCurrentEditor())
- {
- window.close();
- return;
- }
- // gDialog is declared in EdDialogCommon.js
- // Set commonly-used widgets like this:
- gDialog.fooButton = document.getElementById("fooButton");
-
- initDialog();
-
- // Set window location relative to parent window (based on persisted attributes)
- SetWindowLocation();
-
- // Set focus to first widget in dialog, e.g.:
- SetTextboxFocus(gDialog.fooButton);
-}
-
-function InitDialog()
-{
- // Initialize all dialog widgets here,
- // e.g., get attributes from an element for property dialog
-}
-
-function onAccept()
-{
- // Validate all user data and set attributes and possibly insert new element here
- // If there's an error the user must correct, return false to keep dialog open.
-
- SaveWindowLocation();
- return true; // do close the window
-}
diff --git a/editor/ui/dialogs/content/EdDialogTemplate.xul b/editor/ui/dialogs/content/EdDialogTemplate.xul
deleted file mode 100644
index 0422b5b30..000000000
--- a/editor/ui/dialogs/content/EdDialogTemplate.xul
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/Ed?????????.dtd">
-<!-- dialog containing a control requiring initial setup -->
-<dialog title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="Startup()"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/Ed?????.js"/>
-
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
- <broadcaster id="args" value=""/>
-</dialog>
diff --git a/editor/ui/dialogs/content/EdDictionary.js b/editor/ui/dialogs/content/EdDictionary.js
deleted file mode 100644
index 77c575c2b..000000000
--- a/editor/ui/dialogs/content/EdDictionary.js
+++ /dev/null
@@ -1,183 +0,0 @@
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var gSpellChecker;
-var gWordToAdd;
-
-function Startup()
-{
- if (!GetCurrentEditor())
- {
- window.close();
- return;
- }
- // Get the SpellChecker shell
- if ("gSpellChecker" in window.opener && window.opener.gSpellChecker)
- gSpellChecker = window.opener.gSpellChecker;
-
- if (!gSpellChecker)
- {
- dump("SpellChecker not found!!!\n");
- window.close();
- return;
- }
- // The word to add word is passed as the 2nd extra parameter in window.openDialog()
- gWordToAdd = window.arguments[1];
-
- gDialog.WordInput = document.getElementById("WordInput");
- gDialog.DictionaryList = document.getElementById("DictionaryList");
-
- gDialog.WordInput.value = gWordToAdd;
- FillDictionaryList();
-
- // Select the supplied word if it is already in the list
- SelectWordToAddInList();
- SetTextboxFocus(gDialog.WordInput);
-}
-
-function ValidateWordToAdd()
-{
- gWordToAdd = TrimString(gDialog.WordInput.value);
- if (gWordToAdd.length > 0)
- {
- return true;
- } else {
- return false;
- }
-}
-
-function SelectWordToAddInList()
-{
- for (var i = 0; i < gDialog.DictionaryList.getRowCount(); i++)
- {
-
- var wordInList = gDialog.DictionaryList.getItemAtIndex(i);
- if (wordInList && gWordToAdd == wordInList.label)
- {
- gDialog.DictionaryList.selectedIndex = i;
- break;
- }
- }
-}
-
-function AddWord()
-{
- if (ValidateWordToAdd())
- {
- try {
- gSpellChecker.AddWordToDictionary(gWordToAdd);
- }
- catch (e) {
- dump("Exception occured in gSpellChecker.AddWordToDictionary\nWord to add probably already existed\n");
- }
-
- // Rebuild the dialog list
- FillDictionaryList();
-
- SelectWordToAddInList();
- gDialog.WordInput.value = "";
- }
-}
-
-function ReplaceWord()
-{
- if (ValidateWordToAdd())
- {
- var selItem = gDialog.DictionaryList.selectedItem;
- if (selItem)
- {
- try {
- gSpellChecker.RemoveWordFromDictionary(selItem.label);
- } catch (e) {}
-
- try {
- // Add to the dictionary list
- gSpellChecker.AddWordToDictionary(gWordToAdd);
-
- // Just change the text on the selected item
- // instead of rebuilding the list
- selItem.label = gWordToAdd;
- } catch (e) {
- // Rebuild list and select the word - it was probably already in the list
- dump("Exception occured adding word in ReplaceWord\n");
- FillDictionaryList();
- SelectWordToAddInList();
- }
- }
- }
-}
-
-function RemoveWord()
-{
- var selIndex = gDialog.DictionaryList.selectedIndex;
- if (selIndex >= 0)
- {
- var word = gDialog.DictionaryList.selectedItem.label;
-
- // Remove word from list
- gDialog.DictionaryList.removeItemAt(selIndex);
-
- // Remove from dictionary
- try {
- //Not working: BUG 43348
- gSpellChecker.RemoveWordFromDictionary(word);
- }
- catch (e)
- {
- dump("Failed to remove word from dictionary\n");
- }
-
- ResetSelectedItem(selIndex);
- }
-}
-
-function FillDictionaryList()
-{
- var selIndex = gDialog.DictionaryList.selectedIndex;
-
- // Clear the current contents of the list
- ClearListbox(gDialog.DictionaryList);
-
- // Get the list from the spell checker
- gSpellChecker.GetPersonalDictionary()
-
- var haveList = false;
-
- // Get words until an empty string is returned
- do {
- var word = gSpellChecker.GetPersonalDictionaryWord();
- if (word != "")
- {
- gDialog.DictionaryList.appendItem(word, "");
- haveList = true;
- }
- } while (word != "");
-
- //XXX: BUG 74467: If list is empty, it doesn't layout to full height correctly
- // (ignores "rows" attribute) (bug is latered, so we are fixing here for now)
- if (!haveList)
- gDialog.DictionaryList.appendItem("", "");
-
- ResetSelectedItem(selIndex);
-}
-
-function ResetSelectedItem(index)
-{
- var lastIndex = gDialog.DictionaryList.getRowCount() - 1;
- if (index > lastIndex)
- index = lastIndex;
-
- // If we didn't have a selected item,
- // set it to the first item
- if (index == -1 && lastIndex >= 0)
- index = 0;
-
- gDialog.DictionaryList.selectedIndex = index;
-}
-
-function onClose()
-{
- return true;
-}
diff --git a/editor/ui/dialogs/content/EdDictionary.xul b/editor/ui/dialogs/content/EdDictionary.xul
deleted file mode 100644
index 837607c65..000000000
--- a/editor/ui/dialogs/content/EdDictionary.xul
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorPersonalDictionary.dtd">
-<dialog buttons="cancel" title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- persist="screenX screenY"
- onload = "Startup()"
- ondialogcancel="return onClose();">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDictionary.js"/>
-
- <broadcaster id="args" value=""/>
- <grid>
- <columns><column style="width: 15em" flex="1"/><column flex="1"/></columns>
- <rows>
- <row>
- <label value="&wordEditField.label;"
- control="WordInput"
- accesskey="&wordEditField.accessKey;"/>
- <spacer/>
- </row>
- <row>
- <textbox id="WordInput" flex="1"/>
- <button id="AddWord" oncommand="AddWord()" label="&AddButton.label;"
- accesskey="&AddButton.accessKey;"/>
- </row>
- <row>
- <label value="&DictionaryList.label;"
- control="DictionaryList"
- accesskey="&DictionaryList.accessKey;"/>
- <spacer/>
- </row>
- <row>
- <listbox rows="8" id="DictionaryList" flex="1"/>
- <vbox flex="1">
- <button id="ReplaceWord" oncommand="ReplaceWord()" label="&ReplaceButton.label;"
- accesskey="&ReplaceButton.accessKey;"/>
- <spacer class="spacer"/>
- <button id="RemoveWord" oncommand="RemoveWord()" label="&RemoveButton.label;"
- accesskey="&RemoveButton.accessKey;"/>
- <spacer class="spacer"/>
- <spacer flex="1"/>
- <button dlgtype="cancel" class="exit-dialog" id="close" label="&CloseButton.label;"
- default="true" oncommand="onClose();"
- accesskey="&CloseButton.accessKey;"/>
- </vbox>
- </row>
- </rows>
- </grid>
-</dialog>
diff --git a/editor/ui/dialogs/content/EdFieldSetProps.js b/editor/ui/dialogs/content/EdFieldSetProps.js
deleted file mode 100644
index c84b2d48c..000000000
--- a/editor/ui/dialogs/content/EdFieldSetProps.js
+++ /dev/null
@@ -1,182 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var insertNew;
-var fieldsetElement;
-var newLegend;
-var legendElement;
-
-// dialog initialization code
-
-function Startup()
-{
- var editor = GetCurrentEditor();
- if (!editor)
- {
- dump("Failed to get active editor!\n");
- window.close();
- return;
- }
-
- gDialog.editText = document.getElementById("EditText");
- gDialog.legendText = document.getElementById("LegendText");
- gDialog.legendAlign = document.getElementById("LegendAlign");
- gDialog.RemoveFieldSet = document.getElementById("RemoveFieldSet");
-
- // Get a single selected field set element
- const kTagName = "fieldset";
- try {
- // Find a selected fieldset, or if one is at start or end of selection.
- fieldsetElement = editor.getSelectedElement(kTagName);
- if (!fieldsetElement)
- fieldsetElement = editor.getElementOrParentByTagName(kTagName, editor.selection.anchorNode);
- if (!fieldsetElement)
- fieldsetElement = editor.getElementOrParentByTagName(kTagName, editor.selection.focusNode);
- } catch (e) {}
-
- if (fieldsetElement)
- // We found an element and don't need to insert one
- insertNew = false;
- else
- {
- insertNew = true;
-
- // We don't have an element selected,
- // so create one with default attributes
- try {
- fieldsetElement = editor.createElementWithDefaults(kTagName);
- } catch (e) {}
-
- if (!fieldsetElement)
- {
- dump("Failed to get selected element or create a new one!\n");
- window.close();
- return;
- }
- // Hide button removing existing fieldset
- gDialog.RemoveFieldSet.hidden = true;
- }
-
- legendElement = fieldsetElement.querySelector("legend");
- if (legendElement)
- {
- newLegend = false;
- var range = editor.document.createRange();
- range.selectNode(legendElement);
- gDialog.legendText.value = range.toString();
- if (legendElement.innerHTML.includes("<"))
- {
- gDialog.editText.checked = false;
- gDialog.editText.disabled = false;
- gDialog.legendText.disabled = true;
- gDialog.editText.addEventListener("command",
- () => Services.prompt.alert(window, GetString("Alert"), GetString("EditTextWarning")),
- {capture: false, once: true});
- gDialog.RemoveFieldSet.focus();
- }
- else
- SetTextboxFocus(gDialog.legendText);
- }
- else
- {
- newLegend = true;
-
- // We don't have an element selected,
- // so create one with default attributes
-
- legendElement = editor.createElementWithDefaults("legend");
- if (!legendElement)
- {
- dump("Failed to get selected element or create a new one!\n");
- window.close();
- return;
- }
- SetTextboxFocus(gDialog.legendText);
- }
-
- // Make a copy to use for AdvancedEdit
- globalElement = legendElement.cloneNode(false);
-
- InitDialog();
-
- SetWindowLocation();
-}
-
-function InitDialog()
-{
- gDialog.legendAlign.value = GetHTMLOrCSSStyleValue(globalElement, "align", "caption-side");
-}
-
-function RemoveFieldSet()
-{
- var editor = GetCurrentEditor();
- editor.beginTransaction();
- try {
- if (!newLegend)
- editor.deleteNode(legendElement);
- RemoveBlockContainer(fieldsetElement);
- } finally {
- editor.endTransaction();
- }
- SaveWindowLocation();
- window.close();
-}
-
-function ValidateData()
-{
- if (gDialog.legendAlign.value)
- globalElement.setAttribute("align", gDialog.legendAlign.value);
- else
- globalElement.removeAttribute("align");
- return true;
-}
-
-function onAccept()
-{
- // All values are valid - copy to actual element in doc
- ValidateData();
-
- var editor = GetCurrentEditor();
-
- editor.beginTransaction();
-
- try {
- editor.cloneAttributes(legendElement, globalElement);
-
- if (insertNew)
- {
- if (gDialog.legendText.value)
- {
- fieldsetElement.appendChild(legendElement);
- legendElement.appendChild(editor.document.createTextNode(gDialog.legendText.value));
- }
- InsertElementAroundSelection(fieldsetElement);
- }
- else if (gDialog.editText.checked)
- {
- editor.setShouldTxnSetSelection(false);
-
- if (gDialog.legendText.value)
- {
- if (newLegend)
- editor.insertNode(legendElement, fieldsetElement, 0, true);
- else while (legendElement.firstChild)
- editor.deleteNode(legendElement.lastChild);
- editor.insertNode(editor.document.createTextNode(gDialog.legendText.value), legendElement, 0);
- }
- else if (!newLegend)
- editor.deleteNode(legendElement);
-
- editor.setShouldTxnSetSelection(true);
- }
- }
- finally {
- editor.endTransaction();
- }
-
- SaveWindowLocation();
-
- return true;
-}
-
diff --git a/editor/ui/dialogs/content/EdFieldSetProps.xul b/editor/ui/dialogs/content/EdFieldSetProps.xul
deleted file mode 100644
index 41860a6eb..000000000
--- a/editor/ui/dialogs/content/EdFieldSetProps.xul
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorFieldSetProperties.dtd">
-<dialog title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="Startup();"
- buttons="accept,cancel"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdFieldSetProps.js"/>
-
- <broadcaster id="args" value=""/>
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
-
- <groupbox><caption label="&Legend.label;" accesskey="&Legend.accesskey;"/>
- <grid><columns><column/><column/></columns>
- <rows>
- <row align="center">
- <checkbox id="EditText" label="&EditLegendText.label;" accesskey="&EditLegendText.accesskey;" checked="true" disabled="true"
- oncommand="gDialog.legendText.disabled = !gDialog.editText.checked;"/>
- <textbox id="LegendText" accesskey="&Legend.accesskey;"/>
- </row>
- <row align="center">
- <label control="LegendAlign" value="&LegendAlign.label;" accesskey="&LegendAlign.accesskey;"/>
- <menulist id="LegendAlign">
- <menupopup>
- <menuitem label="&AlignDefault.label;"/>
- <menuitem label="&AlignLeft.label;" value="left"/>
- <menuitem label="&AlignCenter.label;" value="center"/>
- <menuitem label="&AlignRight.label;" value="right"/>
- </menupopup>
- </menulist>
- </row>
- </rows>
- </grid>
- </groupbox>
-
- <!-- from EdDialogOverlay -->
- <hbox flex="1" style="margin-top: 0.2em">
- <button id="RemoveFieldSet" label="&RemoveFieldSet.label;" accesskey="&RemoveFieldSet.accesskey;" oncommand="RemoveFieldSet();"/>
- <!-- This will right-align the button -->
- <spacer flex="1"/>
- <button id="AdvancedEditButton"/>
- </hbox>
- <separator class="groove"/>
-
-</dialog>
diff --git a/editor/ui/dialogs/content/EdFormProps.js b/editor/ui/dialogs/content/EdFormProps.js
deleted file mode 100644
index 83ac19df8..000000000
--- a/editor/ui/dialogs/content/EdFormProps.js
+++ /dev/null
@@ -1,128 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var gForm;
-var insertNew;
-var formElement;
-var formActionWarning;
-
-function Startup()
-{
- var editor = GetCurrentEditor();
- if (!editor)
- {
- dump("Failed to get active editor!\n");
- window.close();
- return;
- }
-
- gForm = {
- Name: document.getElementById("FormName"),
- Action: document.getElementById("FormAction"),
- Method: document.getElementById("FormMethod"),
- EncType: document.getElementById("FormEncType"),
- Target: document.getElementById("FormTarget")
- }
- gDialog.MoreSection = document.getElementById("MoreSection");
- gDialog.MoreFewerButton = document.getElementById("MoreFewerButton");
- gDialog.RemoveForm = document.getElementById("RemoveForm")
-
- // Get a single selected form element
- const kTagName = "form";
- try {
- formElement = editor.getSelectedElement(kTagName);
- if (!formElement)
- formElement = editor.getElementOrParentByTagName(kTagName, editor.selection.anchorNode);
- if (!formElement)
- formElement = editor.getElementOrParentByTagName(kTagName, editor.selection.focusNode);
- } catch (e) {}
-
- if (formElement)
- {
- // We found an element and don't need to insert one
- insertNew = false;
- formActionWarning = formElement.hasAttribute("action");
- }
- else
- {
- insertNew = true;
- formActionWarning = true;
-
- // We don't have an element selected,
- // so create one with default attributes
- try {
- formElement = editor.createElementWithDefaults(kTagName);
- } catch (e) {}
-
- if (!formElement)
- {
- dump("Failed to get selected element or create a new one!\n");
- window.close();
- return;
- }
- // Hide button removing existing form
- gDialog.RemoveForm.hidden = true;
- }
-
- // Make a copy to use for AdvancedEdit
- globalElement = formElement.cloneNode(false);
-
- InitDialog();
-
- InitMoreFewer();
-
- SetTextboxFocus(gForm.Name);
-
- SetWindowLocation();
-}
-
-function InitDialog()
-{
- for (var attribute in gForm)
- gForm[attribute].value = globalElement.getAttribute(attribute);
-}
-
-function RemoveForm()
-{
- RemoveBlockContainer(formElement);
- SaveWindowLocation();
- window.close();
-}
-
-function ValidateData()
-{
- for (var attribute in gForm)
- {
- if (gForm[attribute].value)
- globalElement.setAttribute(attribute, gForm[attribute].value);
- else
- globalElement.removeAttribute(attribute);
- }
- return true;
-}
-
-function onAccept()
-{
- if (formActionWarning && !gForm.Action.value)
- {
- Services.prompt.alert(window, GetString("Alert"), GetString("NoFormAction"));
- gForm.Action.focus();
- formActionWarning = false;
- return false;
- }
- // All values are valid - copy to actual element in doc or
- // element created to insert
- ValidateData();
-
- var editor = GetCurrentEditor();
-
- editor.cloneAttributes(formElement, globalElement);
-
- if (insertNew)
- InsertElementAroundSelection(formElement);
-
- SaveWindowLocation();
-
- return true;
-}
diff --git a/editor/ui/dialogs/content/EdFormProps.xul b/editor/ui/dialogs/content/EdFormProps.xul
deleted file mode 100644
index 7cf6c23d0..000000000
--- a/editor/ui/dialogs/content/EdFormProps.xul
+++ /dev/null
@@ -1,88 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorFormProperties.dtd">
-<dialog title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="Startup();"
- buttons="accept,cancel"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdFormProps.js"/>
-
- <broadcaster id="args" value=""/>
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
-
- <groupbox><caption label="&Settings.label;"/>
- <grid><columns><column/><column/></columns>
- <rows>
- <row align="center">
- <label control="FormName" value="&FormName.label;" accesskey="&FormName.accesskey;"/>
- <textbox id="FormName"/>
- </row>
- <row align="center">
- <label control="FormAction" value="&FormAction.label;" accesskey="&FormAction.accesskey;"/>
- <textbox id="FormAction"/>
- </row>
- <row align="center">
- <label control="FormMethod" value="&FormMethod.label;" accesskey="&FormMethod.accesskey;"/>
- <hbox>
- <menulist id="FormMethod" editable="true" autoSelectMenuitem="true">
- <menupopup>
- <menuitem label="GET"/>
- <menuitem label="POST"/>
- </menupopup>
- </menulist>
- </hbox>
- </row>
- <hbox>
- <button id="MoreFewerButton" oncommand="onMoreFewer();" persist="more"/>
- </hbox>
- <rows id="MoreSection">
- <row align="center">
- <label control="FormEncType" value="&FormEncType.label;" accesskey="&FormEncType.accesskey;"/>
- <menulist id="FormEncType" editable="true" autoSelectMenuitem="true">
- <menupopup>
- <menuitem label="application/x-www-form-urlencoded"/>
- <menuitem label="multipart/form-data"/>
- <menuitem label="text/plain"/>
- </menupopup>
- </menulist>
- </row>
- <row align="center">
- <label control="FormTarget" value="&FormTarget.label;" accesskey="&FormTarget.accesskey;"/>
- <menulist id="FormTarget" editable="true" autoSelectMenuitem="true">
- <menupopup>
- <menuitem label="_blank"/>
- <menuitem label="_self"/>
- <menuitem label="_parent"/>
- <menuitem label="_top"/>
- </menupopup>
- </menulist>
- </row>
- </rows>
- </rows>
- </grid>
- </groupbox>
-
- <!-- from EdDialogOverlay -->
- <hbox flex="1" style="margin-top: 0.2em">
- <button id="RemoveForm" label="&RemoveForm.label;" accesskey="&RemoveForm.accesskey;" oncommand="RemoveForm();"/>
- <!-- This will right-align the button -->
- <spacer flex="1"/>
- <button id="AdvancedEditButton"/>
- </hbox>
- <separator class="groove"/>
-
-</dialog>
diff --git a/editor/ui/dialogs/content/EdHLineProps.js b/editor/ui/dialogs/content/EdHLineProps.js
deleted file mode 100644
index 1a38a351d..000000000
--- a/editor/ui/dialogs/content/EdHLineProps.js
+++ /dev/null
@@ -1,195 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var tagName = "hr";
-var gHLineElement;
-var width;
-var height;
-var align;
-var shading;
-const gMaxHRSize = 1000; // This is hard-coded in nsHTMLHRElement::StringToAttribute()
-
-// dialog initialization code
-function Startup()
-{
- var editor = GetCurrentEditor();
- if (!editor)
- {
- window.close();
- return;
- }
- try {
- // Get the selected horizontal line
- gHLineElement = editor.getSelectedElement(tagName);
- } catch (e) {}
-
- if (!gHLineElement) {
- // We should never be here if not editing an existing HLine
- window.close();
- return;
- }
- gDialog.heightInput = document.getElementById("height");
- gDialog.widthInput = document.getElementById("width");
- gDialog.leftAlign = document.getElementById("leftAlign");
- gDialog.centerAlign = document.getElementById("centerAlign");
- gDialog.rightAlign = document.getElementById("rightAlign");
- gDialog.alignGroup = gDialog.rightAlign.radioGroup;
- gDialog.shading = document.getElementById("3dShading");
- gDialog.pixelOrPercentMenulist = document.getElementById("pixelOrPercentMenulist");
-
- // Make a copy to use for AdvancedEdit and onSaveDefault
- globalElement = gHLineElement.cloneNode(false);
-
- // Initialize control values based on existing attributes
- InitDialog()
-
- // SET FOCUS TO FIRST CONTROL
- SetTextboxFocus(gDialog.widthInput);
-
- // Resize window
- window.sizeToContent();
-
- SetWindowLocation();
-}
-
-// Set dialog widgets with attribute data
-// We get them from globalElement copy so this can be used
-// by AdvancedEdit(), which is shared by all property dialogs
-function InitDialog()
-{
- // Just to be confusing, "size" is used instead of height because it does
- // not accept % values, only pixels
- var height = GetHTMLOrCSSStyleValue(globalElement, "size", "height")
- if (height.includes("px")) {
- height = height.substr(0, height.indexOf("px"));
- }
- if(!height) {
- height = 2; //Default value
- }
-
- // We will use "height" here and in UI
- gDialog.heightInput.value = height;
-
- // Get the width attribute of the element, stripping out "%"
- // This sets contents of menulist (adds pixel and percent menuitems elements)
- gDialog.widthInput.value = InitPixelOrPercentMenulist(globalElement, gHLineElement, "width","pixelOrPercentMenulist");
-
- var marginLeft = GetHTMLOrCSSStyleValue(globalElement, "align", "margin-left").toLowerCase();
- var marginRight = GetHTMLOrCSSStyleValue(globalElement, "align", "margin-right").toLowerCase();
- align = marginLeft + " " + marginRight;
- gDialog.leftAlign.checked = (align == "left left" || align == "0px auto");
- gDialog.centerAlign.checked = (align == "center center" || align == "auto auto" || align == " ");
- gDialog.rightAlign.checked = (align == "right right" || align == "auto 0px");
-
- if (gDialog.centerAlign.checked) {
- gDialog.alignGroup.selectedItem = gDialog.centerAlign;
- }
- else if (gDialog.rightAlign.checked) {
- gDialog.alignGroup.selectedItem = gDialog.rightAlign;
- }
- else {
- gDialog.alignGroup.selectedItem = gDialog.leftAlign;
- }
-
- gDialog.shading.checked = !globalElement.hasAttribute("noshade");
-}
-
-function onSaveDefault()
-{
- // "false" means set attributes on the globalElement,
- // not the real element being edited
- if (ValidateData()) {
- var alignInt;
- if (align == "left") {
- alignInt = 0;
- } else if (align == "right") {
- alignInt = 2;
- } else {
- alignInt = 1;
- }
- Services.prefs.setIntPref("editor.hrule.align", alignInt);
-
- var percent;
- var widthInt;
- var heightInt;
-
- if (width)
- {
- if (width.includes("%")) {
- percent = true;
- widthInt = Number(width.substr(0, width.indexOf("%")));
- } else {
- percent = false;
- widthInt = Number(width);
- }
- }
- else
- {
- percent = true;
- widthInt = Number(100);
- }
-
- heightInt = height ? Number(height) : 2;
-
- Services.prefs.setIntPref("editor.hrule.width", widthInt);
- Services.prefs.setBoolPref("editor.hrule.width_percent", percent);
- Services.prefs.setIntPref("editor.hrule.height", heightInt);
- Services.prefs.setBoolPref("editor.hrule.shading", shading);
-
- // Write the prefs out NOW!
- Services.prefs.savePrefFile(null);
- }
-}
-
-// Get and validate data from widgets.
-// Set attributes on globalElement so they can be accessed by AdvancedEdit()
-function ValidateData()
-{
- // Height is always pixels
- height = ValidateNumber(gDialog.heightInput, null, 1, gMaxHRSize,
- globalElement, "size", false);
- if (gValidationError)
- return false;
-
- width = ValidateNumber(gDialog.widthInput, gDialog.pixelOrPercentMenulist, 1, gMaxPixels,
- globalElement, "width", false);
- if (gValidationError)
- return false;
-
- align = "left";
- if (gDialog.centerAlign.selected) {
- // Don't write out default attribute
- align = "";
- } else if (gDialog.rightAlign.selected) {
- align = "right";
- }
- if (align)
- globalElement.setAttribute("align", align);
- else
- try {
- GetCurrentEditor().removeAttributeOrEquivalent(globalElement, "align", true);
- } catch (e) {}
-
- if (gDialog.shading.checked) {
- shading = true;
- globalElement.removeAttribute("noshade");
- } else {
- shading = false;
- globalElement.setAttribute("noshade", "noshade");
- }
- return true;
-}
-
-function onAccept()
-{
- if (ValidateData())
- {
- // Copy attributes from the globalElement to the document element
- try {
- GetCurrentEditor().cloneAttributes(gHLineElement, globalElement);
- } catch (e) {}
- return true;
- }
- return false;
-}
diff --git a/editor/ui/dialogs/content/EdHLineProps.xul b/editor/ui/dialogs/content/EdHLineProps.xul
deleted file mode 100644
index 1a4d8fa14..000000000
--- a/editor/ui/dialogs/content/EdHLineProps.xul
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorHLineProperties.dtd">
-
-<dialog title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="Startup()"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <!--- Element-specific methods -->
- <script type="application/javascript" src="chrome://editor/content/EdHLineProps.js"/>
-
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
-
- <groupbox><caption label="&dimensionsBox.label;"/>
- <grid>
- <columns><column/><column/><column /></columns>
- <rows>
- <row align="center">
- <label control="width"
- value="&widthEditField.label;"
- accesskey="&widthEditField.accessKey;"/>
- <textbox class="narrow" id="width" flex="1" oninput="forceInteger('width')"/>
- <menulist id="pixelOrPercentMenulist" />
- <!-- menupopup and menuitems added by JS -->
- </row>
- <row align="center">
- <label control="height"
- value="&heightEditField.label;"
- accesskey="&heightEditField.accessKey;"/>
- <textbox class="narrow" id="height" oninput="forceInteger('height')"/>
- <label value="&pixelsPopup.value;" />
- </row>
- </rows>
- </grid>
- <checkbox id="3dShading" label="&threeDShading.label;" accesskey="&threeDShading.accessKey;"/>
- </groupbox>
- <groupbox><caption label="&alignmentBox.label;"/>
- <radiogroup id="alignmentGroup" orient="horizontal">
- <spacer class="spacer"/>
- <radio id="leftAlign" label="&leftRadio.label;" accesskey="&leftRadio.accessKey;"/>
- <radio id="centerAlign" label="&centerRadio.label;" accesskey="&centerRadio.accessKey;"/>
- <radio id="rightAlign" label="&rightRadio.label;" accesskey="&rightRadio.accessKey;"/>
- </radiogroup>
- </groupbox>
- <spacer class="spacer"/>
- <hbox>
- <button id="SaveDefault" label="&saveSettings.label;"
- accesskey="&saveSettings.accessKey;"
- oncommand="onSaveDefault()"
- tooltiptext="&saveSettings.tooltip;" />
- <spacer flex="1"/>
- <button id="AdvancedEditButton"/>
- </hbox>
- <separator class="groove"/>
-</dialog>
diff --git a/editor/ui/dialogs/content/EdImageOverlay.js b/editor/ui/dialogs/content/EdImageOverlay.js
deleted file mode 100644
index 175cab791..000000000
--- a/editor/ui/dialogs/content/EdImageOverlay.js
+++ /dev/null
@@ -1,598 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/*
- Note: We encourage non-empty alt text for images inserted into a page.
- When there's no alt text, we always write 'alt=""' as the attribute, since "alt" is a required attribute.
- We allow users to not have alt text by checking a "Don't use alterate text" radio button,
- and we don't accept spaces as valid alt text. A space used to be required to avoid the error message
- if user didn't enter alt text, but is unnecessary now that we no longer annoy the user
- with the error dialog if alt="" is present on an img element.
- We trim all spaces at the beginning and end of user's alt text
-*/
-
-var gInsertNewImage = true;
-var gDoAltTextError = false;
-var gConstrainOn = false;
-// Note used in current version, but these are set correctly
-// and could be used to reset width and height used for constrain ratio
-var gConstrainWidth = 0;
-var gConstrainHeight = 0;
-var imageElement;
-var gImageMap = 0;
-var gCanRemoveImageMap = false;
-var gRemoveImageMap = false;
-var gImageMapDisabled = false;
-var gActualWidth = "";
-var gActualHeight = "";
-var gOriginalSrc = "";
-var gHaveDocumentUrl = false;
-var gTimerID;
-var gValidateTab;
-
-// These must correspond to values in EditorDialog.css for each theme
-// (unfortunately, setting "style" attribute here doesn't work!)
-var gPreviewImageWidth = 80;
-var gPreviewImageHeight = 50;
-
-// dialog initialization code
-
-function ImageStartup()
-{
- gDialog.tabBox = document.getElementById( "TabBox" );
- gDialog.tabLocation = document.getElementById( "imageLocationTab" );
- gDialog.tabDimensions = document.getElementById( "imageDimensionsTab" );
- gDialog.tabBorder = document.getElementById( "imageBorderTab" );
- gDialog.srcInput = document.getElementById( "srcInput" );
- gDialog.titleInput = document.getElementById( "titleInput" );
- gDialog.altTextInput = document.getElementById( "altTextInput" );
- gDialog.altTextRadioGroup = document.getElementById( "altTextRadioGroup" );
- gDialog.altTextRadio = document.getElementById( "altTextRadio" );
- gDialog.noAltTextRadio = document.getElementById( "noAltTextRadio" );
- gDialog.actualSizeRadio = document.getElementById( "actualSizeRadio" );
- gDialog.constrainCheckbox = document.getElementById( "constrainCheckbox" );
- gDialog.widthInput = document.getElementById( "widthInput" );
- gDialog.heightInput = document.getElementById( "heightInput" );
- gDialog.widthUnitsMenulist = document.getElementById( "widthUnitsMenulist" );
- gDialog.heightUnitsMenulist = document.getElementById( "heightUnitsMenulist" );
- gDialog.imagelrInput = document.getElementById( "imageleftrightInput" );
- gDialog.imagetbInput = document.getElementById( "imagetopbottomInput" );
- gDialog.border = document.getElementById( "border" );
- gDialog.alignTypeSelect = document.getElementById( "alignTypeSelect" );
- gDialog.ImageHolder = document.getElementById( "preview-image-holder" );
- gDialog.PreviewWidth = document.getElementById( "PreviewWidth" );
- gDialog.PreviewHeight = document.getElementById( "PreviewHeight" );
- gDialog.PreviewSize = document.getElementById( "PreviewSize" );
- gDialog.PreviewImage = null;
- gDialog.OkButton = document.documentElement.getButton("accept");
-}
-
-// Set dialog widgets with attribute data
-// We get them from globalElement copy so this can be used
-// by AdvancedEdit(), which is shared by all property dialogs
-function InitImage()
-{
- // Set the controls to the image's attributes
- var src = globalElement.getAttribute("src");
-
- // For image insertion the 'src' attribute is null.
- if (src) {
- // Shorten data URIs for display.
- if (shortenImageData(src, gDialog.srcInput)) {
- gDialog.srcInput.removeAttribute("tooltiptext");
- gDialog.srcInput.setAttribute("tooltip", "shortenedDataURI");
- }
- }
-
- // Set "Relativize" checkbox according to current URL state
- SetRelativeCheckbox();
-
- // Force loading of image from its source and show preview image
- LoadPreviewImage();
-
- gDialog.titleInput.value = globalElement.getAttribute("title");
-
- var hasAltText = globalElement.hasAttribute("alt");
- var altText = globalElement.getAttribute("alt");
- gDialog.altTextInput.value = altText;
- if (altText || (!hasAltText && globalElement.hasAttribute("src")))
- {
- gDialog.altTextRadioGroup.selectedItem = gDialog.altTextRadio;
- }
- else if (hasAltText)
- {
- gDialog.altTextRadioGroup.selectedItem = gDialog.noAltTextRadio;
- }
- SetAltTextDisabled(gDialog.altTextRadioGroup.selectedItem == gDialog.noAltTextRadio);
-
- // setup the height and width widgets
- var width = InitPixelOrPercentMenulist(globalElement,
- gInsertNewImage ? null : imageElement,
- "width", "widthUnitsMenulist", gPixel);
- var height = InitPixelOrPercentMenulist(globalElement,
- gInsertNewImage ? null : imageElement,
- "height", "heightUnitsMenulist", gPixel);
-
- // Set actual radio button if both set values are the same as actual
- SetSizeWidgets(width, height);
-
- gDialog.widthInput.value = gConstrainWidth = width ? width : (gActualWidth ? gActualWidth : "");
- gDialog.heightInput.value = gConstrainHeight = height ? height : (gActualHeight ? gActualHeight : "");
-
- // set spacing editfields
- gDialog.imagelrInput.value = globalElement.getAttribute("hspace");
- gDialog.imagetbInput.value = globalElement.getAttribute("vspace");
-
- // dialog.border.value = globalElement.getAttribute("border");
- var bv = GetHTMLOrCSSStyleValue(globalElement, "border", "border-top-width");
- if (bv.includes("px"))
- {
- // Strip out the px
- bv = bv.substr(0, bv.indexOf("px"));
- }
- else if (bv == "thin")
- {
- bv = "1";
- }
- else if (bv == "medium")
- {
- bv = "3";
- }
- else if (bv == "thick")
- {
- bv = "5";
- }
- gDialog.border.value = bv;
-
- // Get alignment setting
- var align = globalElement.getAttribute("align");
- if (align)
- align = align.toLowerCase();
-
- var imgClass;
- var textID;
-
- switch ( align )
- {
- case "top":
- case "middle":
- case "right":
- case "left":
- gDialog.alignTypeSelect.value = align;
- break;
- default: // Default or "bottom"
- gDialog.alignTypeSelect.value = "bottom";
- }
-
- // Get image map for image
- gImageMap = GetImageMap();
-
- doOverallEnabling();
- doDimensionEnabling();
-}
-
-function SetSizeWidgets(width, height)
-{
- if (!(width || height) || (gActualWidth && gActualHeight && width == gActualWidth && height == gActualHeight))
- gDialog.actualSizeRadio.radioGroup.selectedItem = gDialog.actualSizeRadio;
-
- if (!gDialog.actualSizeRadio.selected)
- {
- // Decide if user's sizes are in the same ratio as actual sizes
- if (gActualWidth && gActualHeight)
- {
- if (gActualWidth > gActualHeight)
- gDialog.constrainCheckbox.checked = (Math.round(gActualHeight * width / gActualWidth) == height);
- else
- gDialog.constrainCheckbox.checked = (Math.round(gActualWidth * height / gActualHeight) == width);
- }
- }
-}
-
-// Disable alt text input when "Don't use alt" radio is checked
-function SetAltTextDisabled(disable)
-{
- gDialog.altTextInput.disabled = disable;
-}
-
-function GetImageMap()
-{
- var usemap = globalElement.getAttribute("usemap");
- if (usemap)
- {
- gCanRemoveImageMap = true;
- let mapname = usemap.substr(1);
- try {
- return GetCurrentEditor().document.querySelector('[name="' + mapname + '"]');
- } catch (e) {}
- }
- else
- {
- gCanRemoveImageMap = false;
- }
-
- return null;
-}
-
-function chooseFile()
-{
- if (gTimerID)
- clearTimeout(gTimerID);
- // Get a local file, converted into URL format
- var fileName = GetLocalFileURL("img");
- if (fileName)
- {
- // Always try to relativize local file URLs
- if (gHaveDocumentUrl)
- fileName = MakeRelativeUrl(fileName);
-
- gDialog.srcInput.value = fileName;
-
- SetRelativeCheckbox();
- doOverallEnabling();
- }
- LoadPreviewImage();
-
- // Put focus into the input field
- SetTextboxFocus(gDialog.srcInput);
-}
-
-function PreviewImageLoaded()
-{
- if (gDialog.PreviewImage)
- {
- // Image loading has completed -- we can get actual width
- gActualWidth = gDialog.PreviewImage.naturalWidth;
- gActualHeight = gDialog.PreviewImage.naturalHeight;
-
- if (gActualWidth && gActualHeight)
- {
- // Use actual size or scale to fit preview if either dimension is too large
- var width = gActualWidth;
- var height = gActualHeight;
- if (gActualWidth > gPreviewImageWidth)
- {
- width = gPreviewImageWidth;
- height = gActualHeight * (gPreviewImageWidth / gActualWidth);
- }
- if (height > gPreviewImageHeight)
- {
- height = gPreviewImageHeight;
- width = gActualWidth * (gPreviewImageHeight / gActualHeight);
- }
- gDialog.PreviewImage.width = width;
- gDialog.PreviewImage.height = height;
-
- gDialog.PreviewWidth.setAttribute("value", gActualWidth);
- gDialog.PreviewHeight.setAttribute("value", gActualHeight);
-
- gDialog.PreviewSize.collapsed = false;
- gDialog.ImageHolder.collapsed = false;
-
- SetSizeWidgets(gDialog.widthInput.value, gDialog.heightInput.value);
- }
-
- if (gDialog.actualSizeRadio.selected)
- SetActualSize();
- }
-}
-
-function LoadPreviewImage()
-{
- gDialog.PreviewSize.collapsed = true;
- // XXXbz workaround for bug 265416 / bug 266284
- gDialog.ImageHolder.collapsed = true;
-
- var imageSrc = TrimString(gDialog.srcInput.value);
- if (!imageSrc)
- return;
- if (isImageDataShortened(imageSrc))
- {
- imageSrc = restoredImageData(gDialog.srcInput);
- }
-
- try {
- // Remove the image URL from image cache so it loads fresh
- // (if we don't do this, loads after the first will always use image cache
- // and we won't see image edit changes or be able to get actual width and height)
-
- // We must have an absolute URL to preview it or remove it from the cache
- imageSrc = MakeAbsoluteUrl(imageSrc);
-
- if (GetScheme(imageSrc))
- {
- let uri = Services.io.newURI(imageSrc, null, null);
- if (uri)
- {
- let imgCache = Components.classes["@mozilla.org/image/cache;1"]
- .getService(Components.interfaces.imgICache);
-
- // This returns error if image wasn't in the cache; ignore that
- imgCache.removeEntry(uri);
- }
- }
- } catch(e) {}
-
- if (gDialog.PreviewImage)
- removeEventListener("load", PreviewImageLoaded, true);
-
- if (gDialog.ImageHolder.hasChildNodes())
- gDialog.ImageHolder.firstChild.remove();
-
- gDialog.PreviewImage = document.createElementNS("http://www.w3.org/1999/xhtml", "html:img");
- if (gDialog.PreviewImage)
- {
- // set the src before appending to the document -- see bug 198435 for why
- // this is needed.
- // XXXbz that bug is long-since fixed. Is this still needed?
- gDialog.PreviewImage.addEventListener("load", PreviewImageLoaded, true);
- gDialog.PreviewImage.src = imageSrc;
- gDialog.ImageHolder.appendChild(gDialog.PreviewImage);
- }
-}
-
-function SetActualSize()
-{
- gDialog.widthInput.value = gActualWidth ? gActualWidth : "";
- gDialog.widthUnitsMenulist.selectedIndex = 0;
- gDialog.heightInput.value = gActualHeight ? gActualHeight : "";
- gDialog.heightUnitsMenulist.selectedIndex = 0;
- doDimensionEnabling();
-}
-
-function ChangeImageSrc()
-{
- if (gTimerID)
- clearTimeout(gTimerID);
-
- gTimerID = setTimeout(LoadPreviewImage, 800);
-
- SetRelativeCheckbox();
- doOverallEnabling();
-}
-
-function doDimensionEnabling()
-{
- // Enabled unless "Actual Size" is selected
- var enable = !gDialog.actualSizeRadio.selected;
-
- // BUG 74145: After input field is disabled,
- // setting it enabled causes blinking caret to appear
- // even though focus isn't set to it.
- SetElementEnabledById( "heightInput", enable );
- SetElementEnabledById( "heightLabel", enable );
- SetElementEnabledById( "heightUnitsMenulist", enable );
-
- SetElementEnabledById( "widthInput", enable );
- SetElementEnabledById( "widthLabel", enable);
- SetElementEnabledById( "widthUnitsMenulist", enable );
-
- var constrainEnable = enable
- && ( gDialog.widthUnitsMenulist.selectedIndex == 0 )
- && ( gDialog.heightUnitsMenulist.selectedIndex == 0 );
-
- SetElementEnabledById( "constrainCheckbox", constrainEnable );
-}
-
-function doOverallEnabling()
-{
- var enabled = TrimString(gDialog.srcInput.value) != "";
-
- SetElementEnabled(gDialog.OkButton, enabled);
- SetElementEnabledById("AdvancedEditButton1", enabled);
- SetElementEnabledById("imagemapLabel", enabled);
- SetElementEnabledById("removeImageMap", gCanRemoveImageMap);
-}
-
-function ToggleConstrain()
-{
- // If just turned on, save the current width and height as basis for constrain ratio
- // Thus clicking on/off lets user say "Use these values as aspect ration"
- if (gDialog.constrainCheckbox.checked && !gDialog.constrainCheckbox.disabled
- && (gDialog.widthUnitsMenulist.selectedIndex == 0)
- && (gDialog.heightUnitsMenulist.selectedIndex == 0))
- {
- gConstrainWidth = Number(TrimString(gDialog.widthInput.value));
- gConstrainHeight = Number(TrimString(gDialog.heightInput.value));
- }
-}
-
-function constrainProportions( srcID, destID )
-{
- var srcElement = document.getElementById(srcID);
- if (!srcElement)
- return;
-
- var destElement = document.getElementById(destID);
- if (!destElement)
- return;
-
- // always force an integer (whether we are constraining or not)
- forceInteger(srcID);
-
- if (!gActualWidth || !gActualHeight ||
- !(gDialog.constrainCheckbox.checked && !gDialog.constrainCheckbox.disabled))
- return;
-
- // double-check that neither width nor height is in percent mode; bail if so!
- if ( (gDialog.widthUnitsMenulist.selectedIndex != 0)
- || (gDialog.heightUnitsMenulist.selectedIndex != 0) )
- return;
-
- // This always uses the actual width and height ratios
- // which is kind of funky if you change one number without the constrain
- // and then turn constrain on and change a number
- // I prefer the old strategy (below) but I can see some merit to this solution
- if (srcID == "widthInput")
- destElement.value = Math.round( srcElement.value * gActualHeight / gActualWidth );
- else
- destElement.value = Math.round( srcElement.value * gActualWidth / gActualHeight );
-
-/*
- // With this strategy, the width and height ratio
- // can be reset to whatever the user entered.
- if (srcID == "widthInput")
- destElement.value = Math.round( srcElement.value * gConstrainHeight / gConstrainWidth );
- else
- destElement.value = Math.round( srcElement.value * gConstrainWidth / gConstrainHeight );
-*/
-}
-
-function removeImageMap()
-{
- gRemoveImageMap = true;
- gCanRemoveImageMap = false;
- SetElementEnabledById("removeImageMap", false);
-}
-
-function SwitchToValidatePanel()
-{
- if (gDialog.tabBox && gValidateTab && gDialog.tabBox.selectedTab != gValidateTab)
- gDialog.tabBox.selectedTab = gValidateTab;
-}
-
-// Get data from widgets, validate, and set for the global element
-// accessible to AdvancedEdit() [in EdDialogCommon.js]
-function ValidateImage()
-{
- var editor = GetCurrentEditor();
- if (!editor)
- return false;
-
- gValidateTab = gDialog.tabLocation;
- if (!gDialog.srcInput.value)
- {
- Services.prompt.alert(window, GetString("Alert"), GetString("MissingImageError"));
- SwitchToValidatePanel();
- gDialog.srcInput.focus();
- return false;
- }
-
- // We must convert to "file:///" or "http://" format else image doesn't load!
- let src = gDialog.srcInput.value.trim();
-
- if (isImageDataShortened(src))
- {
- src = restoredImageData(gDialog.srcInput);
- }
- else
- {
- var checkbox = document.getElementById("MakeRelativeCheckbox");
- try
- {
- if (checkbox && !checkbox.checked)
- {
- src = Services.uriFixup.createFixupURI(src, Components.interfaces.nsIURIFixup.FIXUP_FLAG_NONE).spec;
- }
- } catch (e) { }
-
- globalElement.setAttribute("src", src);
- }
-
- let title = gDialog.titleInput.value.trim();
- if (title)
- globalElement.setAttribute("title", title);
- else
- globalElement.removeAttribute("title");
-
- // Force user to enter Alt text only if "Alternate text" radio is checked
- // Don't allow just spaces in alt text
- var alt = "";
- var useAlt = gDialog.altTextRadioGroup.selectedItem == gDialog.altTextRadio;
- if (useAlt)
- alt = TrimString(gDialog.altTextInput.value);
-
- if (alt || !useAlt)
- {
- globalElement.setAttribute("alt", alt);
- }
- else if (!gDoAltTextError)
- {
- globalElement.removeAttribute("alt");
- }
- else
- {
- Services.prompt.alert(window, GetString("Alert"), GetString("NoAltText"));
- SwitchToValidatePanel();
- gDialog.altTextInput.focus();
- return false;
- }
-
- var width = "";
- var height = "";
-
- gValidateTab = gDialog.tabDimensions;
- if (!gDialog.actualSizeRadio.selected)
- {
- // Get user values for width and height
- width = ValidateNumber(gDialog.widthInput, gDialog.widthUnitsMenulist, 1, gMaxPixels,
- globalElement, "width", false, true);
- if (gValidationError)
- return false;
-
- height = ValidateNumber(gDialog.heightInput, gDialog.heightUnitsMenulist, 1, gMaxPixels,
- globalElement, "height", false, true);
- if (gValidationError)
- return false;
- }
-
- // We always set the width and height attributes, even if same as actual.
- // This speeds up layout of pages since sizes are known before image is loaded
- if (!width)
- width = gActualWidth;
- if (!height)
- height = gActualHeight;
-
- // Remove existing width and height only if source changed
- // and we couldn't obtain actual dimensions
- var srcChanged = (src != gOriginalSrc);
- if (width)
- editor.setAttributeOrEquivalent(globalElement, "width", width, true);
- else if (srcChanged)
- editor.removeAttributeOrEquivalent(globalElement, "width", true);
-
- if (height)
- editor.setAttributeOrEquivalent(globalElement, "height", height, true);
- else if (srcChanged)
- editor.removeAttributeOrEquivalent(globalElement, "height", true);
-
- // spacing attributes
- gValidateTab = gDialog.tabBorder;
- ValidateNumber(gDialog.imagelrInput, null, 0, gMaxPixels,
- globalElement, "hspace", false, true, true);
- if (gValidationError)
- return false;
-
- ValidateNumber(gDialog.imagetbInput, null, 0, gMaxPixels,
- globalElement, "vspace", false, true);
- if (gValidationError)
- return false;
-
- // note this is deprecated and should be converted to stylesheets
- ValidateNumber(gDialog.border, null, 0, gMaxPixels,
- globalElement, "border", false, true);
- if (gValidationError)
- return false;
-
- // Default or setting "bottom" means don't set the attribute
- // Note that the attributes "left" and "right" are opposite
- // of what we use in the UI, which describes where the TEXT wraps,
- // not the image location (which is what the HTML describes)
- switch ( gDialog.alignTypeSelect.value )
- {
- case "top":
- case "middle":
- case "right":
- case "left":
- editor.setAttributeOrEquivalent( globalElement, "align",
- gDialog.alignTypeSelect.value , true);
- break;
- default:
- try {
- editor.removeAttributeOrEquivalent(globalElement, "align", true);
- } catch (e) {}
- }
-
- return true;
-}
diff --git a/editor/ui/dialogs/content/EdImageOverlay.xul b/editor/ui/dialogs/content/EdImageOverlay.xul
deleted file mode 100644
index 90d360e2e..000000000
--- a/editor/ui/dialogs/content/EdImageOverlay.xul
+++ /dev/null
@@ -1,267 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE overlay SYSTEM "chrome://editor/locale/EditorImageProperties.dtd">
-
-<overlay id="EdImageOverlay"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <script type="application/javascript" src="chrome://editor/content/EdImageOverlay.js"/>
-
- <tab id="imageInputTab" label="&imageInputTab.label;"/>
- <tab id="imageLocationTab" label="&imageLocationTab.label;"/>
- <tab id="imageDimensionsTab" label="&imageDimensionsTab.label;"/>
- <tab id="imageAppearanceTab" label="&imageAppearanceTab.label;"/>
- <tab id="imageLinkTab" label="&imageLinkTab.label;"/>
-
- <vbox id="imageLocation">
- <spacer class="spacer"/>
- <label control = "srcInput"
- value = "&locationEditField.label;"
- accesskey="&locationEditField.accessKey;"
- tooltiptext="&locationEditField.tooltip;"
- />
- <tooltip id="shortenedDataURI">
- <label value="&locationEditField.shortenedDataURI;"/>
- </tooltip>
- <textbox id="srcInput" oninput="ChangeImageSrc();" tabindex="1" class="uri-element"
- tooltiptext="&locationEditField.tooltip;"/>
- <hbox id="MakeRelativeHbox">
- <checkbox
- id = "MakeRelativeCheckbox"
- for = "srcInput"
- tabindex="2"/>
- <!-- mail compose will insert custom item here defined in mailComposeEditorOverlay.xul -->
- <spacer flex="1"/>
- <!-- from EdDialogOverlay.xul -->
- <button id="ChooseFile" tabindex="3"/>
- </hbox>
- <spacer class="spacer"/>
- <radiogroup id="altTextRadioGroup" flex="1">
- <grid>
- <columns><column/><column flex="1"/></columns>
- <rows>
- <row align="center">
- <label
- style = "margin-left: 26px"
- control = "titleInput"
- accesskey = "&title.accessKey;"
- value ="&title.label;"
- tooltiptext="&title.tooltip;"
- for = "titleInput"/>
- <textbox flex="1"
- id = "titleInput"
- class = "MinWidth20em"
- tooltiptext="&title.tooltip;"
- tabindex="4"/>
- </row>
- <row align="center">
- <radio id = "altTextRadio"
- label = "&altText.label;"
- accesskey = "&altText.accessKey;"
- tooltiptext="&altTextEditField.tooltip;"
- oncommand = "SetAltTextDisabled(false);"
- tabindex="5"/>
- <textbox flex="1"
- id = "altTextInput"
- class = "MinWidth20em"
- tooltiptext="&altTextEditField.tooltip;"
- oninput = "SetAltTextDisabled(false);"
- tabindex="6"/>
- </row>
- </rows>
- </grid>
-
- <radio id = "noAltTextRadio"
- label = "&noAltText.label;"
- accesskey = "&noAltText.accessKey;"
- oncommand = "SetAltTextDisabled(true);"/>
- </radiogroup>
- </vbox>
-
- <groupbox id="imagePreview" orient="horizontal" flex="1">
- <caption label="&previewBox.label;"/>
- <hbox id="preview-image-box" align="center">
- <spacer flex="1"/>
- <description id="preview-image-holder"/>
- <spacer flex="1"/>
- </hbox>
- <vbox id="PreviewSize" collapsed="true">
- <spacer flex="1"/>
- <label value="&actualSize.label;"/>
- <hbox>
- <label value="&widthEditField.label;"/>
- <spacer flex="1"/>
- <label id="PreviewWidth"/>
- </hbox>
- <hbox>
- <label value="&heightEditField.label;"/>
- <spacer flex="1"/>
- <label id="PreviewHeight"/>
- </hbox>
- <spacer flex="1"/>
- </vbox>
- </groupbox>
-
- <vbox id="imageDimensions" align="start">
- <spacer class="spacer"/>
- <hbox>
- <radiogroup id="imgSizeGroup">
- <radio
- id = "actualSizeRadio"
- label = "&actualSizeRadio.label;"
- accesskey = "&actualSizeRadio.accessKey;"
- tooltiptext="&actualSizeRadio.tooltip;"
- oncommand = "SetActualSize()"/>
- <radio
- id = "customSizeRadio"
- label = "&customSizeRadio.label;"
- selected = "true"
- accesskey = "&customSizeRadio.accessKey;"
- tooltiptext="&customSizeRadio.tooltip;"
- oncommand = "doDimensionEnabling();" />
- </radiogroup>
- <spacer flex="1"/>
- <vbox>
- <spacer flex="1"/>
- <checkbox id="constrainCheckbox" label="&constrainCheckbox.label;"
- accesskey="&constrainCheckbox.accessKey;"
- oncommand="ToggleConstrain()"
- tooltiptext="&constrainCheckbox.tooltip;"/>
- </vbox>
- <spacer flex="1"/>
- </hbox>
- <spacer class="spacer"/>
- <grid class="indent">
- <columns><column/><column/><column flex="1"/></columns>
- <rows>
- <row align="center">
- <label id = "widthLabel"
- control = "widthInput"
- accesskey = "&widthEditField.accessKey;"
- value = "&widthEditField.label;" />
- <textbox
- id = "widthInput"
- class = "narrow"
- oninput = "constrainProportions(this.id, 'heightInput')"/>
- <menulist id = "widthUnitsMenulist"
- oncommand = "doDimensionEnabling();" />
- <!-- contents are appended by JS -->
- </row>
- <row align="center">
- <label id = "heightLabel"
- control = "heightInput"
- accesskey = "&heightEditField.accessKey;"
- value = "&heightEditField.label;" />
- <textbox
- id = "heightInput"
- class = "narrow"
- oninput = "constrainProportions(this.id, 'widthInput')"/>
- <menulist id = "heightUnitsMenulist"
- oncommand = "doDimensionEnabling();" />
- <!-- contents are appended by JS -->
- </row>
- </rows>
- </grid>
- <spacer flex="1"/>
- </vbox>
-
- <hbox id="imageAppearance">
- <groupbox>
- <caption id="spacingLabel" label="&spacingBox.label;"/>
- <grid>
- <columns><column/><column/><column/></columns>
- <rows>
- <row align="center">
- <label
- class = "align-right"
- id = "leftrightLabel"
- control = "imageleftrightInput"
- accesskey = "&leftRightEditField.accessKey;"
- value = "&leftRightEditField.label;"/>
- <textbox
- class = "narrow"
- id = "imageleftrightInput"
- oninput = "forceInteger(this.id)"/>
- <label
- id = "leftrighttypeLabel"
- value = "&pixelsPopup.value;" />
- </row>
- <spacer class="spacer"/>
- <row align="center">
- <label
- class = "align-right"
- id = "topbottomLabel"
- control = "imagetopbottomInput"
- accesskey = "&topBottomEditField.accessKey;"
- value = "&topBottomEditField.label;"/>
- <textbox
- class = "narrow"
- id = "imagetopbottomInput"
- oninput = "forceInteger(this.id)"/>
- <label
- id = "topbottomtypeLabel"
- value = "&pixelsPopup.value;" />
- </row>
- <spacer class="spacer"/>
- <row align="center">
- <label class = "align-right"
- id = "borderLabel"
- control = "border"
- accesskey = "&borderEditField.accessKey;"
- value = "&borderEditField.label;"/>
- <textbox
- class = "narrow"
- id = "border"
- oninput = "forceInteger(this.id)"/>
- <label
- id = "bordertypeLabel"
- value = "&pixelsPopup.value;" />
- </row>
- </rows>
- </grid>
- </groupbox>
-
- <vbox>
- <groupbox align="start">
- <caption id="alignLabel" label="&alignment.label;"/>
- <menulist id="alignTypeSelect" class="align-menu">
- <menupopup>
- <menuitem class="align-menu menuitem-iconic"
- value="top"
- label="&topPopup.value;"/>
- <menuitem class="align-menu menuitem-iconic"
- value="middle"
- label="&centerPopup.value;"/>
- <menuitem class="align-menu menuitem-iconic"
- value="bottom"
- label="&bottomPopup.value;"/>
- <!-- HTML attribute value is opposite of the button label on purpose -->
- <menuitem class="align-menu menuitem-iconic"
- value="right"
- label="&wrapLeftPopup.value;"/>
- <menuitem class="align-menu menuitem-iconic"
- value="left"
- label="&wrapRightPopup.value;"/>
- </menupopup>
- </menulist>
- </groupbox>
-
- <groupbox>
- <caption id="imagemapLabel" label="&imagemapBox.label;"/>
- <hbox equalsize="always">
- <button
- id = "removeImageMap"
- oncommand = "removeImageMap()"
- accesskey = "&removeImageMapButton.accessKey;"
- label = "&removeImageMapButton.label;"
- flex = "1"/>
- <spacer flex="1"/><!-- remove when we restore Image Map Editor -->
- </hbox>
- </groupbox>
- </vbox>
- </hbox>
-
-</overlay>
diff --git a/editor/ui/dialogs/content/EdImageProps.js b/editor/ui/dialogs/content/EdImageProps.js
deleted file mode 100644
index 1c0e7002c..000000000
--- a/editor/ui/dialogs/content/EdImageProps.js
+++ /dev/null
@@ -1,316 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var gAnchorElement = null;
-var gLinkElement = null;
-var gOriginalHref = "";
-var gHNodeArray = {};
-
-// dialog initialization code
-
-function Startup()
-{
- var editor = GetCurrentEditor();
- if (!editor)
- {
- window.close();
- return;
- }
-
- ImageStartup();
- gDialog.hrefInput = document.getElementById("hrefInput");
- gDialog.makeRelativeLink = document.getElementById("MakeRelativeLink");
- gDialog.showLinkBorder = document.getElementById("showLinkBorder");
- gDialog.linkTab = document.getElementById("imageLinkTab");
- gDialog.linkAdvanced = document.getElementById("LinkAdvancedEditButton");
-
- // Get a single selected image element
- var tagName = "img";
- if ("arguments" in window && window.arguments[0])
- {
- imageElement = window.arguments[0];
- // We've been called from form field properties, so we can't insert a link
- gDialog.linkTab.remove();
- gDialog.linkTab = null;
- }
- else
- {
- // First check for <input type="image">
- try {
- imageElement = editor.getSelectedElement("input");
-
- if (!imageElement || imageElement.getAttribute("type") != "image") {
- // Get a single selected image element
- imageElement = editor.getSelectedElement(tagName);
- if (imageElement)
- gAnchorElement = editor.getElementOrParentByTagName("href", imageElement);
- }
- } catch (e) {}
-
- }
-
- if (imageElement)
- {
- // We found an element and don't need to insert one
- if (imageElement.hasAttribute("src"))
- {
- gInsertNewImage = false;
- gActualWidth = imageElement.naturalWidth;
- gActualHeight = imageElement.naturalHeight;
- }
- }
- else
- {
- gInsertNewImage = true;
-
- // We don't have an element selected,
- // so create one with default attributes
- try {
- imageElement = editor.createElementWithDefaults(tagName);
- } catch(e) {}
-
- if (!imageElement)
- {
- dump("Failed to get selected element or create a new one!\n");
- window.close();
- return;
- }
- try {
- gAnchorElement = editor.getSelectedElement("href");
- } catch (e) {}
- }
-
- // Make a copy to use for AdvancedEdit
- globalElement = imageElement.cloneNode(false);
-
- // We only need to test for this once per dialog load
- gHaveDocumentUrl = GetDocumentBaseUrl();
-
- InitDialog();
- if (gAnchorElement)
- {
- gOriginalHref = gAnchorElement.getAttribute("href");
- // Make a copy to use for AdvancedEdit
- gLinkElement = gAnchorElement.cloneNode(false);
- }
- else
- {
- gLinkElement = editor.createElementWithDefaults("a");
- }
- gDialog.hrefInput.value = gOriginalHref;
-
- FillLinkMenulist(gDialog.hrefInput, gHNodeArray);
- ChangeLinkLocation();
-
- // Save initial source URL
- gOriginalSrc = gDialog.srcInput.value;
-
- // By default turn constrain on, but both width and height must be in pixels
- gDialog.constrainCheckbox.checked =
- gDialog.widthUnitsMenulist.selectedIndex == 0 &&
- gDialog.heightUnitsMenulist.selectedIndex == 0;
-
- // Start in "Link" tab if 2nd arguement is true
- if (gDialog.linkTab && "arguments" in window && window.arguments[1])
- {
- document.getElementById("TabBox").selectedTab = gDialog.linkTab;
- SetTextboxFocus(gDialog.hrefInput);
- }
- else
- SetTextboxFocus(gDialog.srcInput);
-
- // Hide the separator from EdDialogOverlay.xul as we show our own
- document.getElementById("advancedSeparator").hidden = true;
-
- SetWindowLocation();
-}
-
-// Set dialog widgets with attribute data
-// We get them from globalElement copy so this can be used
-// by AdvancedEdit(), which is shared by all property dialogs
-function InitDialog()
-{
- InitImage();
- var border = TrimString(gDialog.border.value);
- gDialog.showLinkBorder.checked = border != "" && border > 0;
-}
-
-function ChangeLinkLocation()
-{
- var href = TrimString(gDialog.hrefInput.value);
- SetRelativeCheckbox(gDialog.makeRelativeLink);
- gDialog.showLinkBorder.disabled = !href;
- gDialog.linkAdvanced.disabled = !href;
- gLinkElement.setAttribute("href", href);
-}
-
-function ToggleShowLinkBorder()
-{
- if (gDialog.showLinkBorder.checked)
- {
- var border = TrimString(gDialog.border.value);
- if (!border || border == "0")
- gDialog.border.value = "2";
- }
- else
- {
- gDialog.border.value = "0";
- }
-}
-
-// Get data from widgets, validate, and set for the global element
-// accessible to AdvancedEdit() [in EdDialogCommon.js]
-function ValidateData()
-{
- return ValidateImage();
-}
-
-function onAccept()
-{
- // Use this now (default = false) so Advanced Edit button dialog doesn't trigger error message
- gDoAltTextError = true;
-
- if (ValidateData())
- {
- if ("arguments" in window && window.arguments[0])
- {
- SaveWindowLocation();
- return true;
- }
-
- var editor = GetCurrentEditor();
-
- editor.beginTransaction();
-
- try
- {
- if (gRemoveImageMap)
- {
- globalElement.removeAttribute("usemap");
- if (gImageMap)
- {
- editor.deleteNode(gImageMap);
- gInsertNewIMap = true;
- gImageMap = null;
- }
- }
- else if (gImageMap)
- {
- // un-comment to see that inserting image maps does not work!
- /*
- gImageMap = editor.createElementWithDefaults("map");
- gImageMap.setAttribute("name", "testing");
- var testArea = editor.createElementWithDefaults("area");
- testArea.setAttribute("shape", "circle");
- testArea.setAttribute("coords", "86,102,52");
- testArea.setAttribute("href", "test");
- gImageMap.appendChild(testArea);
- */
-
- // Assign to map if there is one
- var mapName = gImageMap.getAttribute("name");
- if (mapName != "")
- {
- globalElement.setAttribute("usemap", ("#"+mapName));
- if (globalElement.getAttribute("border") == "")
- globalElement.setAttribute("border", 0);
- }
- }
-
- // Create or remove the link as appropriate
- var href = gDialog.hrefInput.value;
- if (href != gOriginalHref)
- {
- if (href && !gInsertNewImage)
- {
- EditorSetTextProperty("a", "href", href);
- // gAnchorElement is needed for cloning attributes later.
- if (!gAnchorElement)
- gAnchorElement = editor.getElementOrParentByTagName("href", imageElement);
- }
- else
- {
- EditorRemoveTextProperty("href", "");
- }
- }
-
- // If inside a link, always write the 'border' attribute
- if (href)
- {
- if (gDialog.showLinkBorder.checked)
- {
- // Use default = 2 if border attribute is empty
- if (!globalElement.hasAttribute("border"))
- globalElement.setAttribute("border", "2");
- }
- else
- globalElement.setAttribute("border", "0");
- }
-
- if (gInsertNewImage)
- {
- if (href) {
- gLinkElement.appendChild(imageElement);
- editor.insertElementAtSelection(gLinkElement, true);
- }
- else
- // 'true' means delete the selection before inserting
- editor.insertElementAtSelection(imageElement, true);
- }
-
- // Check to see if the link was to a heading
- // Do this last because it moves the caret (BAD!)
- if (href in gHNodeArray)
- {
- var anchorNode = editor.createElementWithDefaults("a");
- if (anchorNode)
- {
- anchorNode.name = href.substr(1);
- // Remember to use editor method so it is undoable!
- editor.insertNode(anchorNode, gHNodeArray[href], 0, false);
- }
- }
- // All values are valid - copy to actual element in doc or
- // element we just inserted
- editor.cloneAttributes(imageElement, globalElement);
- if (gAnchorElement)
- editor.cloneAttributes(gAnchorElement, gLinkElement);
-
- // If document is empty, the map element won't insert,
- // so always insert the image first
- if (gImageMap && gInsertNewIMap)
- {
- // Insert the ImageMap element at beginning of document
- var body = editor.rootElement;
- editor.setShouldTxnSetSelection(false);
- editor.insertNode(gImageMap, body, 0);
- editor.setShouldTxnSetSelection(true);
- }
- }
- catch (e)
- {
- dump(e);
- }
-
- editor.endTransaction();
-
- SaveWindowLocation();
- return true;
- }
-
- gDoAltTextError = false;
-
- return false;
-}
-
-function onLinkAdvancedEdit()
-{
- window.AdvancedEditOK = false;
- window.openDialog("chrome://editor/content/EdAdvancedEdit.xul", "_blank",
- "chrome,close,titlebar,modal,resizable=yes", "",
- gLinkElement);
- window.focus();
- if (window.AdvancedEditOK)
- gDialog.hrefInput.value = gLinkElement.getAttribute("href");
-}
diff --git a/editor/ui/dialogs/content/EdImageProps.xul b/editor/ui/dialogs/content/EdImageProps.xul
deleted file mode 100644
index c2ddfeba0..000000000
--- a/editor/ui/dialogs/content/EdImageProps.xul
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdImageOverlay.xul"?>
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorImageProperties.dtd">
-
-
-<!-- dialog containing a control requiring initial setup -->
-<dialog id="imageDlg" title="&windowTitle.label;"
- xmlns ="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload = "Startup()"
- buttons="accept,cancel"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdImageProps.js"/>
-
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
- <broadcaster id="args" value=""/>
-
- <tabbox id="TabBox">
- <tabs flex="1">
- <tab id="imageLocationTab"/>
- <tab id="imageDimensionsTab"/>
- <tab id="imageAppearanceTab"/>
- <tab id="imageLinkTab"/>
- </tabs>
- <tabpanels>
- <!-- panels overlayed from EdImageOverlay.xul -->
- <vbox id="imageLocation"/>
- <vbox id="imageDimensions"/>
- <hbox id="imageAppearance"/>
- <vbox>
- <spacer class="spacer"/>
- <vbox id="LinkLocationBox"/>
- <spacer class="spacer"/>
- <hbox>
- <checkbox id="showLinkBorder"
- label="&showImageLinkBorder.label;"
- accesskey="&showImageLinkBorder.accessKey;"
- oncommand="ToggleShowLinkBorder();"/>
- <spacer flex="1"/>
- <button id="LinkAdvancedEditButton"
- label="&LinkAdvancedEditButton.label;"
- accesskey="&LinkAdvancedEditButton.accessKey;"
- tooltiptext="&LinkAdvancedEditButton.tooltip;"
- oncommand="onLinkAdvancedEdit();"/>
- </hbox>
- </vbox>
- </tabpanels>
- </tabbox>
-
- <hbox align="end">
- <groupbox id="imagePreview"/>
-
- <!-- from EdDialogOverlay -->
- <vbox id="AdvancedEdit"/>
- </hbox>
- <separator class="groove"/>
-
-</dialog>
diff --git a/editor/ui/dialogs/content/EdInputImage.js b/editor/ui/dialogs/content/EdInputImage.js
deleted file mode 100644
index bf9abcae3..000000000
--- a/editor/ui/dialogs/content/EdInputImage.js
+++ /dev/null
@@ -1,179 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// dialog initialization code
-
-function Startup()
-{
- var editor = GetCurrentEditor();
- if (!editor)
- {
- window.close();
- return;
- }
-
- gDialog = {
- inputName: document.getElementById( "InputName" ),
- inputDisabled: document.getElementById( "InputDisabled" ),
- inputTabIndex: document.getElementById( "InputTabIndex" )
- };
-
- ImageStartup();
-
- // Get a single selected input element
- var tagName = "input";
- try {
- imageElement = editor.getSelectedElement(tagName);
- } catch (e) {}
-
- if (imageElement)
- {
- // We found an element and don't need to insert one
- gInsertNewImage = false;
- }
- else
- {
- gInsertNewImage = true;
-
- // We don't have an element selected,
- // so create one with default attributes
- try {
- imageElement = editor.createElementWithDefaults(tagName);
- } catch(e) {}
-
- if (!imageElement )
- {
- dump("Failed to get selected element or create a new one!\n");
- window.close();
- return;
- }
- var imgElement;
- try {
- imgElement = editor.getSelectedElement("img");
- } catch(e) {}
-
- if (imgElement)
- {
- // We found an image element, convert it to an input type="image"
- var attributes = ["src", "alt", "width", "height", "hspace", "vspace", "border", "align", "usemap", "ismap"];
- for (i in attributes)
- imageElement.setAttribute(attributes[i], imgElement.getAttribute(attributes[i]));
- }
- }
-
- // Make a copy to use for AdvancedEdit
- globalElement = imageElement.cloneNode(false);
-
- // We only need to test for this once per dialog load
- gHaveDocumentUrl = GetDocumentBaseUrl();
-
- InitDialog();
-
- // Save initial source URL
- gOriginalSrc = gDialog.srcInput.value;
-
- // By default turn constrain on, but both width and height must be in pixels
- gDialog.constrainCheckbox.checked =
- gDialog.widthUnitsMenulist.selectedIndex == 0 &&
- gDialog.heightUnitsMenulist.selectedIndex == 0;
-
- SetTextboxFocus(gDialog.inputName);
-
- SetWindowLocation();
-}
-
-function InitDialog()
-{
- InitImage();
- gDialog.inputName.value = globalElement.getAttribute("name");
- gDialog.inputDisabled.setAttribute("checked", globalElement.hasAttribute("disabled"));
- gDialog.inputTabIndex.value = globalElement.getAttribute("tabindex");
-}
-
-function ValidateData()
-{
- if (!ValidateImage())
- return false;
- if (gDialog.inputName.value)
- globalElement.setAttribute("name", gDialog.inputName.value);
- else
- globalElement.removeAttribute("name");
- if (gDialog.inputTabIndex.value)
- globalElement.setAttribute("tabindex", gDialog.inputTabIndex.value);
- else
- globalElement.removeAttribute("tabindex");
- if (gDialog.inputDisabled.checked)
- globalElement.setAttribute("disabled", "");
- else
- globalElement.removeAttribute("disabled");
- globalElement.setAttribute("type", "image");
- return true;
-}
-
-function onAccept()
-{
- // Show alt text error only once
- // (we don't initialize doAltTextError=true
- // so Advanced edit button dialog doesn't trigger that error message)
- // Use this now (default = false) so Advanced Edit button dialog doesn't trigger error message
- gDoAltTextError = true;
-
- if (ValidateData())
- {
-
- var editor = GetCurrentEditor();
- editor.beginTransaction();
-
- try {
- if (gRemoveImageMap)
- {
- globalElement.removeAttribute("usemap");
- if (gImageMap)
- {
- editor.deleteNode(gImageMap);
- gInsertNewIMap = true;
- gImageMap = null;
- }
- }
- else if (gImageMap)
- {
- // Assign to map if there is one
- var mapName = gImageMap.getAttribute("name");
- if (mapName != "")
- {
- globalElement.setAttribute("usemap", ("#"+mapName));
- if (globalElement.getAttribute("border") == "")
- globalElement.setAttribute("border", 0);
- }
- }
-
- if (gInsertNewImage)
- {
- // 'true' means delete the selection before inserting
- // in case were are converting an image to an input type="image"
- editor.insertElementAtSelection(imageElement, true);
- }
- editor.cloneAttributes(imageElement, globalElement);
-
- // If document is empty, the map element won't insert,
- // so always insert the image element first
- if (gImageMap && gInsertNewIMap)
- {
- // Insert the ImageMap element at beginning of document
- var body = editor.rootElement;
- editor.setShouldTxnSetSelection(false);
- editor.insertNode(gImageMap, body, 0);
- editor.setShouldTxnSetSelection(true);
- }
- } catch (e) {}
-
- editor.endTransaction();
-
- SaveWindowLocation();
-
- return true;
- }
- return false;
-}
-
diff --git a/editor/ui/dialogs/content/EdInputImage.xul b/editor/ui/dialogs/content/EdInputImage.xul
deleted file mode 100644
index 026982f85..000000000
--- a/editor/ui/dialogs/content/EdInputImage.xul
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdImageOverlay.xul"?>
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorInputProperties.dtd">
-<dialog title="&windowTitleImage.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="Startup();"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdInputImage.js"/>
-
- <broadcaster id="args" value=""/>
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
-
- <tabbox id="TabBox">
- <tabs flex="1">
- <tab id="imageInputTab"/>
- <tab id="imageLocationTab"/>
- <tab id="imageDimensionsTab"/>
- <tab id="imageAppearanceTab"/>
- </tabs>
- <tabpanels>
- <groupbox><caption label="&InputSettings.label;"/>
- <grid><columns><column/><column/></columns>
- <rows>
- <row align="center">
- <label value="&InputName.label;"/>
- <textbox id="InputName"/>
- </row>
- <row>
- <spacer/>
- <checkbox id="InputDisabled" label="&InputDisabled.label;"/>
- </row>
- <row align="center">
- <label value="&tabIndex.label;"/>
- <hbox>
- <textbox id="InputTabIndex" class="narrow" oninput="forceInteger(this.id);"/>
- </hbox>
- </row>
- </rows>
- </grid>
- </groupbox>
-
- <!-- panels overlayed from EdImageOverlay.xul -->
- <vbox id="imageLocation"/>
- <vbox id="imageDimensions"/>
- <hbox id="imageAppearance"/>
-
- </tabpanels>
- </tabbox>
-
- <hbox align="end">
- <groupbox id="imagePreview"/>
-
- <!-- from EdDialogOverlay -->
- <vbox id="AdvancedEdit"/>
- </hbox>
-
-</dialog>
diff --git a/editor/ui/dialogs/content/EdInputProps.js b/editor/ui/dialogs/content/EdInputProps.js
deleted file mode 100644
index 430e6f3a0..000000000
--- a/editor/ui/dialogs/content/EdInputProps.js
+++ /dev/null
@@ -1,327 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var insertNew;
-var inputElement;
-
-// dialog initialization code
-
-function Startup()
-{
- var editor = GetCurrentEditor();
- if (!editor)
- {
- dump("Failed to get active editor!\n");
- window.close();
- return;
- }
-
- gDialog = {
- accept: document.documentElement.getButton("accept"),
- inputType: document.getElementById("InputType"),
- inputNameDeck: document.getElementById("InputNameDeck"),
- inputName: document.getElementById("InputName"),
- inputValueDeck: document.getElementById("InputValueDeck"),
- inputValue: document.getElementById("InputValue"),
- inputDeck: document.getElementById("InputDeck"),
- inputChecked: document.getElementById("InputChecked"),
- inputSelected: document.getElementById("InputSelected"),
- inputReadOnly: document.getElementById("InputReadOnly"),
- inputDisabled: document.getElementById("InputDisabled"),
- inputTabIndex: document.getElementById("InputTabIndex"),
- inputAccessKey: document.getElementById("InputAccessKey"),
- inputSize: document.getElementById("InputSize"),
- inputMaxLength: document.getElementById("InputMaxLength"),
- inputAccept: document.getElementById("InputAccept"),
- MoreSection: document.getElementById("MoreSection"),
- MoreFewerButton: document.getElementById("MoreFewerButton"),
- AdvancedEditButton: document.getElementById("AdvancedEditButton"),
- AdvancedEditDeck: document.getElementById("AdvancedEditDeck")
- };
-
- // Get a single selected input element
- const kTagName = "input";
- try {
- inputElement = editor.getSelectedElement(kTagName);
- } catch (e) {}
-
- if (inputElement)
- // We found an element and don't need to insert one
- insertNew = false;
- else
- {
- insertNew = true;
-
- // We don't have an element selected,
- // so create one with default attributes
- try {
- inputElement = editor.createElementWithDefaults(kTagName);
- } catch (e) {}
-
- if (!inputElement)
- {
- dump("Failed to get selected element or create a new one!\n");
- window.close();
- return;
- }
-
- var imgElement = editor.getSelectedElement("img");
- if (imgElement)
- {
- // We found an image element, convert it to an input type="image"
- inputElement.setAttribute("type", "image");
-
- var attributes = ["src", "alt", "width", "height", "hspace", "vspace", "border", "align"];
- for (i in attributes)
- inputElement.setAttribute(attributes[i], imgElement.getAttribute(attributes[i]));
- }
- else
- inputElement.setAttribute("value", GetSelectionAsText());
- }
-
- // Make a copy to use for AdvancedEdit
- globalElement = inputElement.cloneNode(false);
-
- InitDialog();
-
- InitMoreFewer();
-
- gDialog.inputType.focus();
-
- SetWindowLocation();
-}
-
-function InitDialog()
-{
- var type = globalElement.getAttribute("type");
- var index = 0;
- switch (type)
- {
- case "button":
- index = 9;
- break;
- case "checkbox":
- index = 2;
- break;
- case "file":
- index = 6;
- break;
- case "hidden":
- index = 7;
- break;
- case "image":
- index = 8;
- break;
- case "password":
- index = 1;
- break;
- case "radio":
- index = 3;
- break;
- case "reset":
- index = 5;
- break;
- case "submit":
- index = 4;
- break;
- }
- gDialog.inputType.selectedIndex = index;
- gDialog.inputName.value = globalElement.getAttribute("name");
- gDialog.inputValue.value = globalElement.getAttribute("value");
- gDialog.inputChecked.setAttribute("checked", globalElement.hasAttribute("checked"));
- gDialog.inputSelected.setAttribute("checked", globalElement.hasAttribute("checked"));
- gDialog.inputReadOnly.setAttribute("checked", globalElement.hasAttribute("readonly"));
- gDialog.inputDisabled.setAttribute("checked", globalElement.hasAttribute("disabled"));
- gDialog.inputTabIndex.value = globalElement.getAttribute("tabindex");
- gDialog.inputAccessKey.value = globalElement.getAttribute("accesskey");
- gDialog.inputSize.value = globalElement.getAttribute("size");
- gDialog.inputMaxLength.value = globalElement.getAttribute("maxlength");
- gDialog.inputAccept.value = globalElement.getAttribute("accept");
- SelectInputType();
-}
-
-function SelectInputType()
-{
- var index = gDialog.inputType.selectedIndex;
- gDialog.AdvancedEditDeck.setAttribute("selectedIndex", 0);
- gDialog.inputNameDeck.setAttribute("selectedIndex", 0);
- gDialog.inputValueDeck.setAttribute("selectedIndex", 0);
- gDialog.inputValue.disabled = false;
- gDialog.inputChecked.disabled = index != 2;
- gDialog.inputSelected.disabled = index != 3;
- gDialog.inputReadOnly.disabled = index > 1;
- gDialog.inputTabIndex.disabled = index == 7;
- gDialog.inputAccessKey.disabled = index == 7;
- gDialog.inputSize.disabled = index > 1;
- gDialog.inputMaxLength.disabled = index > 1;
- gDialog.inputAccept.disabled = index != 6;
- switch (index)
- {
- case 0:
- case 1:
- gDialog.inputValueDeck.setAttribute("selectedIndex", 1);
- gDialog.inputDeck.setAttribute("selectedIndex", 2);
- break;
- case 2:
- gDialog.inputDeck.setAttribute("selectedIndex", 0);
- break;
- case 3:
- gDialog.inputDeck.setAttribute("selectedIndex", 1);
- gDialog.inputNameDeck.setAttribute("selectedIndex", 1);
- break;
- case 6:
- gDialog.inputValue.disabled = true;
- gDialog.inputAccept.disabled = false;
- break;
- case 8:
- gDialog.inputValue.disabled = true;
- gDialog.AdvancedEditDeck.setAttribute("selectedIndex", 1);
- gDialog.inputName.removeEventListener("input", onInput, false);
- break;
- case 7:
- gDialog.inputValueDeck.setAttribute("selectedIndex", 1);
- break;
- }
- onInput();
-}
-
-function onInput()
-{
- var disabled = false;;
- switch (gDialog.inputType.selectedIndex)
- {
- case 3:
- disabled = disabled || !gDialog.inputValue.value;
- case 4:
- case 5:
- break;
- case 8:
- disabled = !globalElement.hasAttribute("src");
- break;
- default:
- disabled = !gDialog.inputName.value
- break;
- }
- if (gDialog.accept.disabled != disabled)
- {
- gDialog.accept.disabled = disabled;
- gDialog.AdvancedEditButton.disabled = disabled;
- }
-}
-
-function doImageProperties()
-{
- window.openDialog("chrome://editor/content/EdImageProps.xul",
- "_blank", "chrome,close,titlebar,modal", globalElement);
- window.focus();
- onInput();
-}
-
-function ValidateData()
-{
- var attributes = {
- type: "",
- name: gDialog.inputName.value,
- value: gDialog.inputValue.value,
- tabindex: gDialog.inputTabIndex.value,
- accesskey: "",
- size: "",
- maxlength: "",
- accept: ""
- };
- var index = gDialog.inputType.selectedIndex;
- var flags = {
- checked: false,
- readonly: false,
- disabled: gDialog.inputDisabled.checked
- };
- switch (index)
- {
- case 1:
- attributes.type = "password";
- case 0:
- flags.readonly = gDialog.inputReadOnly.checked;
- attributes.size = gDialog.inputSize.value;
- attributes.maxlength = gDialog.inputMaxLength.value;
- break;
- case 2:
- attributes.type = "checkbox";
- flags.checked = gDialog.inputChecked.checked;
- break;
- case 3:
- attributes.type = "radio";
- flags.checked = gDialog.inputSelected.checked;
- break;
- case 4:
- attributes.type = "submit";
- attributes.accesskey = gDialog.inputAccessKey.value;
- break;
- case 5:
- attributes.type = "reset";
- attributes.accesskey = gDialog.inputAccessKey.value;
- break;
- case 6:
- attributes.type = "file";
- attributes.accept = gDialog.inputAccept.value;
- attributes.value = "";
- break;
- case 7:
- attributes.type = "hidden";
- attributes.tabindex = "";
- break;
- case 8:
- attributes.type = "image";
- attributes.value = "";
- break;
- case 9:
- attributes.type = "button";
- attributes.accesskey = gDialog.inputAccessKey.value;
- break;
- }
- for (var a in attributes)
- {
- if (attributes[a])
- globalElement.setAttribute(a, attributes[a]);
- else
- globalElement.removeAttribute(a);
- }
- for (var f in flags)
- {
- if (flags[f])
- globalElement.setAttribute(f, "");
- else
- globalElement.removeAttribute(f);
- }
- return true;
-}
-
-function onAccept()
-{
- if (ValidateData())
- {
- // All values are valid - copy to actual element in doc or
- // element created to insert
-
- var editor = GetCurrentEditor();
-
- editor.cloneAttributes(inputElement, globalElement);
-
- if (insertNew)
- {
- try {
- // 'true' means delete the selection before inserting
- // in case were are converting an image to an input type="image"
- editor.insertElementAtSelection(inputElement, true);
- } catch (e) {
- dump(e);
- }
- }
-
- SaveWindowLocation();
-
- return true;
- }
- return false;
-}
-
diff --git a/editor/ui/dialogs/content/EdInputProps.xul b/editor/ui/dialogs/content/EdInputProps.xul
deleted file mode 100644
index 5b03eae74..000000000
--- a/editor/ui/dialogs/content/EdInputProps.xul
+++ /dev/null
@@ -1,124 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorInputProperties.dtd">
-<dialog title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="Startup();"
- buttons="accept,cancel"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdInputProps.js"/>
-
- <broadcaster id="args" value=""/>
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
-
- <groupbox><caption><label control="InputType" value="&InputType.label;" accesskey="&InputType.accesskey;"/></caption>
- <menulist id="InputType" oncommand="SelectInputType();">
- <menupopup>
- <menuitem label="&text.value;"/>
- <menuitem label="&password.value;"/>
- <menuitem label="&checkbox.value;"/>
- <menuitem label="&radio.value;"/>
- <menuitem label="&submit.value;"/>
- <menuitem label="&reset.value;"/>
- <menuitem label="&file.value;"/>
- <menuitem label="&hidden.value;"/>
- <menuitem label="&image.value;"/>
- <menuitem label="&button.value;"/>
- </menupopup>
- </menulist>
- </groupbox>
-
- <groupbox><caption label="&InputSettings.label;"/>
- <grid><columns><column/><column/></columns>
- <rows>
- <row align="center">
- <deck id="InputNameDeck">
- <label control="InputName" value="&InputName.label;" accesskey="&InputName.accesskey;"/>
- <label control="InputName" value="&GroupName.label;" accesskey="&GroupName.accesskey;"/>
- </deck>
- <textbox id="InputName" oninput="onInput();"/>
- </row>
- <row align="center">
- <deck id="InputValueDeck">
- <label control="InputValue" value="&InputValue.label;" accesskey="&InputValue.accesskey;"/>
- <label control="InputValue" value="&InitialValue.label;" accesskey="&InitialValue.accesskey;"/>
- </deck>
- <textbox id="InputValue" oninput="onInput();"/>
- </row>
- <row>
- <spacer/>
- <deck id="InputDeck" persist="index">
- <checkbox id="InputChecked" label="&InputChecked.label;" accesskey="&InputChecked.accesskey;"/>
- <checkbox id="InputSelected" label="&InputSelected.label;" accesskey="&InputSelected.accesskey;"/>
- <checkbox id="InputReadOnly" label="&InputReadOnly.label;" accesskey="&InputReadOnly.accesskey;"/>
- </deck>
- </row>
- </rows>
- </grid>
- <hbox>
- <button id="MoreFewerButton" oncommand="onMoreFewer();" persist="more"/>
- </hbox>
- <grid id="MoreSection" align="start">
- <columns><column/><column/></columns>
- <rows>
- <row>
- <spacer/>
- <checkbox id="InputDisabled" label="&InputDisabled.label;" accesskey="&InputDisabled.accesskey;"/>
- </row>
- <row align="center">
- <label control="InputTabIndex" value="&tabIndex.label;" accesskey="&tabIndex.accesskey;"/>
- <hbox>
- <textbox id="InputTabIndex" class="narrow" oninput="forceInteger(this.id);"/>
- </hbox>
- </row>
- <row align="center">
- <label control="InputAccessKey" value="&AccessKey.label;" accesskey="&AccessKey.accesskey;"/>
- <hbox>
- <textbox id="InputAccessKey" class="narrow"/>
- </hbox>
- </row>
- <row align="center">
- <label control="InputSize" value="&TextSize.label;" accesskey="&TextSize.accesskey;"/>
- <hbox>
- <textbox id="InputSize" class="narrow" oninput="forceInteger(this.id);"/>
- </hbox>
- </row>
- <row align="center">
- <label control="InputMaxLength" value="&TextLength.label;" accesskey="&TextLength.accesskey;"/>
- <hbox>
- <textbox id="InputMaxLength" class="narrow" oninput="forceInteger(this.id);"/>
- </hbox>
- </row>
- <row align="center">
- <label control="InputAccept" value="&Accept.label;" accesskey="&Accept.accesskey;"/>
- <textbox id="InputAccept"/>
- </row>
- </rows>
- </grid>
- </groupbox>
-
- <!-- from EdDialogOverlay -->
- <hbox flex="1" style="margin-top: 0.2em">
- <!-- This will right-align the button -->
- <spacer flex="1"/>
- <deck id="AdvancedEditDeck">
- <button id="AdvancedEditButton"/>
- <button label="&ImageProperties.label;" accesskey="&ImageProperties.accesskey;" oncommand="doImageProperties();"/>
- </deck>
- </hbox>
- <separator class="groove"/>
-
-</dialog>
diff --git a/editor/ui/dialogs/content/EdInsSrc.js b/editor/ui/dialogs/content/EdInsSrc.js
deleted file mode 100644
index afa2e31e2..000000000
--- a/editor/ui/dialogs/content/EdInsSrc.js
+++ /dev/null
@@ -1,142 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Insert Source HTML dialog */
-
-var gFullDataStrings = new Map();
-var gShortDataStrings = new Map();
-var gListenerAttached = false;
-
-function Startup()
-{
- let editor = GetCurrentEditor();
- if (!editor)
- {
- window.close();
- return;
- }
-
- document.documentElement.getButton("accept").removeAttribute("default");
-
- // Create dialog object to store controls for easy access
- gDialog.srcInput = document.getElementById("srcInput");
-
- // Attach a paste listener so we can detect pasted data URIs we need to shorten.
- gDialog.srcInput.addEventListener("paste", onPaste);
-
- let selection;
- try {
- selection = editor.outputToString("text/html", kOutputFormatted | kOutputSelectionOnly | kOutputWrap);
- } catch (e) {}
- if (selection)
- {
- selection = (selection.replace(/<body[^>]*>/,"")).replace(/<\/body>/,"");
-
- // Shorten data URIs for display.
- selection = replaceDataURIs(selection);
-
- if (selection)
- gDialog.srcInput.value = selection;
- }
- // Set initial focus
- gDialog.srcInput.focus();
- // Note: We can't set the caret location in a multiline textbox
- SetWindowLocation();
-}
-
-function replaceDataURIs(input)
-{
- return input.replace(/(data:.+;base64,)([^"' >]+)/gi,
- function(match, nonDataPart, dataPart) {
-
- if (gShortDataStrings.has(dataPart)) {
- // We found the exact same data URI, just return the shortened URI.
- return nonDataPart + gShortDataStrings.get(dataPart);
- }
-
- let l = 5;
- // Normally we insert the ellipsis after five characters but if it's not unique
- // we include more data.
- do {
- key = dataPart.substr(0, l) + "…" + dataPart.substr(dataPart.length - 10);
- l++;
- } while (gFullDataStrings.has(key) && l < dataPart.length - 10);
- gFullDataStrings.set(key, dataPart);
- gShortDataStrings.set(dataPart, key);
-
- // Attach listeners. In case anyone copies/cuts from the HTML window,
- // we want to restore the data URI on the clipboard.
- if (!gListenerAttached) {
- gDialog.srcInput.addEventListener("copy", onCopyOrCut);
- gDialog.srcInput.addEventListener("cut", onCopyOrCut);
- gListenerAttached = true;
- }
-
- return nonDataPart + key;
- });
-}
-
-function onCopyOrCut(event)
-{
- let startPos = gDialog.srcInput.selectionStart;
- if (startPos == undefined)
- return;
- let endPos = gDialog.srcInput.selectionEnd;
- let clipboard = gDialog.srcInput.value.substring(startPos, endPos);
-
- // Add back the original data URIs we stashed away earlier.
- clipboard = clipboard.replace(/(data:.+;base64,)([^"' >]+)/gi,
- function(match, nonDataPart, key) {
- if (!gFullDataStrings.has(key))
- return match; // user changed data URI
- return nonDataPart + gFullDataStrings.get(key);
- });
- event.clipboardData.setData("text/plain", clipboard);
- if (event.type == "cut") {
- // We have to cut the selection manually.
- gDialog.srcInput.value = gDialog.srcInput.value.substr(0, startPos) +
- gDialog.srcInput.value.substr(endPos);
- }
- event.preventDefault();
-}
-
-function onPaste(event)
-{
- let startPos = gDialog.srcInput.selectionStart;
- if (startPos == undefined)
- return;
- let endPos = gDialog.srcInput.selectionEnd;
- let clipboard = event.clipboardData.getData("text/plain");
-
- // We do out own paste by replacing the selection with the pre-processed
- // clipboard data.
- gDialog.srcInput.value = gDialog.srcInput.value.substr(0, startPos) +
- replaceDataURIs(clipboard) +
- gDialog.srcInput.value.substr(endPos);
- event.preventDefault();
-}
-
-function onAccept()
-{
- let html = gDialog.srcInput.value;
- if (!html)
- return false;
-
- // Add back the original data URIs we stashed away earlier.
- html = html.replace(/(data:.+;base64,)([^"' >]+)/gi,
- function(match, nonDataPart, key) {
- if (!gFullDataStrings.has(key))
- return match; // user changed data URI
- return nonDataPart + gFullDataStrings.get(key);
- });
-
- try {
- GetCurrentEditor().insertHTML(html);
- } catch (e) {}
- SaveWindowLocation();
-
- return true;
-}
-
diff --git a/editor/ui/dialogs/content/EdInsSrc.xul b/editor/ui/dialogs/content/EdInsSrc.xul
deleted file mode 100644
index a0b02b3df..000000000
--- a/editor/ui/dialogs/content/EdInsSrc.xul
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorInsertSource.dtd">
-
-<dialog title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload = "Startup()"
- buttonlabelaccept="&insertButton.label;"
- buttonaccesskeyaccept="&insertButton.accesskey;"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdInsSrc.js"/>
-
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
- <broadcaster id="args" value=""/>
-
- <label id="srcMessage" value="&sourceEditField.label;"/>
- <vbox flex="1" style="width: 30em; height: 20em;">
- <textbox id="srcInput" multiline="true" rows="1" style="width: 1em" flex="1" class="uri-element"/>
- </vbox>
- <!-- Will this accept the embedded HTML tags? -->
- <hbox>
- <spacer class="bigspacer"/>
- <label value="&example.label;"/>
- <label class="bold" value="&exampleOpenTag.label;"/>
- <label class="bold italic" value="&exampleText.label;"/>
- <label class="bold" value="&exampleCloseTag.label;"/>
- </hbox>
- <spacer class="spacer"/>
- <separator class="groove"/>
-</dialog>
diff --git a/editor/ui/dialogs/content/EdInsertChars.js b/editor/ui/dialogs/content/EdInsertChars.js
deleted file mode 100644
index 24a1172d6..000000000
--- a/editor/ui/dialogs/content/EdInsertChars.js
+++ /dev/null
@@ -1,409 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-//------------------------------------------------------------------
-// From Unicode 3.0 Page 54. 3.11 Conjoining Jamo Behavior
-var SBase = 0xac00;
-var LBase = 0x1100;
-var VBase = 0x1161;
-var TBase = 0x11A7;
-var LCount = 19;
-var VCount = 21;
-var TCount = 28;
-var NCount = VCount * TCount;
-// End of Unicode 3.0
-
-// dialog initialization code
-function Startup()
-{
- if (!GetCurrentEditor())
- {
- window.close();
- return;
- }
-
- StartupLatin();
-
- // Set a variable on the opener window so we
- // can track ownership of close this window with it
- window.opener.InsertCharWindow = window;
- window.sizeToContent();
-
- SetWindowLocation();
-}
-
-function onAccept()
-{
- // Insert the character
- try {
- GetCurrentEditor().insertText(LatinM.label);
- } catch(e) {}
-
- // Set persistent attributes to save
- // which category, letter, and character modifier was used
- CategoryGroup.setAttribute("category", category);
- CategoryGroup.setAttribute("letter_index", indexL);
- CategoryGroup.setAttribute("char_index", indexM);
-
- // Don't close the dialog
- return false;
-}
-
-// Don't allow inserting in HTML Source Mode
-function onFocus()
-{
- var enable = true;
- if ("gEditorDisplayMode" in window.opener)
- enable = !window.opener.IsInHTMLSourceMode();
-
- SetElementEnabled(document.documentElement.getButton("accept"), enable);
-}
-
-function onClose()
-{
- window.opener.InsertCharWindow = null;
- SaveWindowLocation();
- return true;
-}
-
-//------------------------------------------------------------------
-var LatinL;
-var LatinM;
-var LatinL_Label;
-var LatinM_Label;
-var indexL=0;
-var indexM=0;
-var indexM_AU=0;
-var indexM_AL=0;
-var indexM_U=0;
-var indexM_L=0;
-var indexM_S=0;
-var LItems=0;
-var category;
-var CategoryGroup;
-var initialize = true;
-
-function StartupLatin()
-{
-
- LatinL = document.getElementById("LatinL");
- LatinM = document.getElementById("LatinM");
- LatinL_Label = document.getElementById("LatinL_Label");
- LatinM_Label = document.getElementById("LatinM_Label");
-
- var Symbol = document.getElementById("Symbol");
- var AccentUpper = document.getElementById("AccentUpper");
- var AccentLower = document.getElementById("AccentLower");
- var Upper = document.getElementById("Upper");
- var Lower = document.getElementById("Lower");
- CategoryGroup = document.getElementById("CatGrp");
-
- // Initialize which radio button is set from persistent attribute...
- var category = CategoryGroup.getAttribute("category");
-
- // ...as well as indexes into the letter and character lists
- var index = Number(CategoryGroup.getAttribute("letter_index"));
- if (index && index >= 0)
- indexL = index;
- index = Number(CategoryGroup.getAttribute("char_index"));
- if (index && index >= 0)
- indexM = index;
-
-
- switch (category)
- {
- case "AccentUpper": // Uppercase Diacritical
- CategoryGroup.selectedItem = AccentUpper;
- indexM_AU = indexM;
- break;
- case "AccentLower": // Lowercase Diacritical
- CategoryGroup.selectedItem = AccentLower;
- indexM_AL = indexM;
- break;
- case "Upper": // Uppercase w/o Diacritical
- CategoryGroup.selectedItem = Upper;
- indexM_U = indexM;
- break;
- case "Lower": // Lowercase w/o Diacritical
- CategoryGroup.selectedItem = Lower;
- indexM_L = indexM;
- break;
- default:
- category = "Symbol";
- CategoryGroup.selectedItem = Symbol;
- indexM_S = indexM;
- break;
- }
-
- ChangeCategory(category);
- initialize = false;
-}
-
-function ChangeCategory(newCategory)
-{
- if (category != newCategory || initialize)
- {
- category = newCategory;
- // Note: Must do L before M to set LatinL.selectedIndex
- UpdateLatinL();
- UpdateLatinM();
- UpdateCharacter();
- }
-}
-
-function SelectLatinLetter()
-{
- if(LatinL.selectedIndex != indexL )
- {
- indexL = LatinL.selectedIndex;
- UpdateLatinM();
- UpdateCharacter();
- }
-}
-
-function SelectLatinModifier()
-{
- if(LatinM.selectedIndex != indexM )
- {
- indexM = LatinM.selectedIndex;
- UpdateCharacter();
- }
-}
-function DisableLatinL(disable)
-{
- if (disable) {
- LatinL_Label.setAttribute("disabled", "true");
- LatinL.setAttribute("disabled", "true");
- } else {
- LatinL_Label.removeAttribute("disabled");
- LatinL.removeAttribute("disabled");
- }
-}
-
-function UpdateLatinL()
-{
- LatinL.removeAllItems();
- if (category == "AccentUpper" || category == "AccentLower")
- {
- DisableLatinL(false);
- // No Q or q
- var alphabet = category == "AccentUpper" ? "ABCDEFGHIJKLMNOPRSTUVWXYZ" : "abcdefghijklmnoprstuvwxyz";
- for (var letter = 0; letter < alphabet.length; letter++)
- LatinL.appendItem(alphabet.charAt(letter));
-
- LatinL.selectedIndex = indexL;
- }
- else
- {
- // Other categories don't hinge on a "letter"
- DisableLatinL(true);
- // Note: don't change the indexL so it can be used next time
- }
-}
-
-function UpdateLatinM()
-{
- LatinM.removeAllItems();
- var i, accent;
- switch(category)
- {
- case "AccentUpper": // Uppercase Diacritical
- accent = upper[indexL];
- for(i=0; i < accent.length; i++)
- LatinM.appendItem(accent.charAt(i));
-
- if(indexM_AU < accent.length)
- indexM = indexM_AU;
- else
- indexM = accent.length - 1;
- indexM_AU = indexM;
- break;
-
- case "AccentLower": // Lowercase Diacritical
- accent = lower[indexL];
- for(i=0; i < accent.length; i++)
- LatinM.appendItem(accent.charAt(i));
-
- if(indexM_AL < accent.length)
- indexM = indexM_AL;
- else
- indexM = lower[indexL].length - 1;
- indexM_AL = indexM;
- break;
-
- case "Upper": // Uppercase w/o Diacritical
- for(i=0; i < otherupper.length; i++)
- LatinM.appendItem(otherupper.charAt(i));
-
- if(indexM_U < otherupper.length)
- indexM = indexM_U;
- else
- indexM = otherupper.length - 1;
- indexM_U = indexM;
- break;
-
- case "Lower": // Lowercase w/o Diacritical
- for(i=0; i < otherlower.length; i++)
- LatinM.appendItem(otherlower.charAt(i));
-
- if(indexM_L < otherlower.length)
- indexM = indexM_L;
- else
- indexM = otherlower.length - 1;
- indexM_L = indexM;
- break;
-
- case "Symbol": // Symbol
- for(i=0; i < symbol.length; i++)
- LatinM.appendItem(symbol.charAt(i));
-
- if(indexM_S < symbol.length)
- indexM = indexM_S;
- else
- indexM = symbol.length - 1;
- indexM_S = indexM;
- break;
- }
- LatinM.selectedIndex = indexM;
-}
-
-function UpdateCharacter()
-{
- indexM = LatinM.selectedIndex;
-
- switch(category)
- {
- case "AccentUpper": // Uppercase Diacritical
- indexM_AU = indexM;
- break;
- case "AccentLower": // Lowercase Diacritical
- indexM_AL = indexM;
- break;
- case "Upper": // Uppercase w/o Diacritical
- indexM_U = indexM;
- break;
- case "Lower": // Lowercase w/o Diacritical
- indexM_L = indexM;
- break;
- case "Symbol":
- indexM_S = indexM;
- break;
- }
-//dump("Letter Index="+indexL+", Character Index="+indexM+", Character = "+LatinM.label+"\n");
-}
-
-const upper=[
- // A
- "\u00c0\u00c1\u00c2\u00c3\u00c4\u00c5\u0100\u0102\u0104\u01cd\u01de\u01de\u01e0\u01fa\u0200\u0202\u0226\u1e00\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6",
- // B
- "\u0181\u0182\u0184\u1e02\u1e04\u1e06",
- // C
- "\u00c7\u0106\u0108\u010a\u010c\u0187\u1e08",
- // D
- "\u010e\u0110\u0189\u018a\u1e0a\u1e0c\u1e0e\u1e10\u1e12",
- // E
- "\u00C8\u00C9\u00CA\u00CB\u0112\u0114\u0116\u0118\u011A\u0204\u0206\u0228\u1e14\u1e16\u1e18\u1e1a\u1e1c\u1eb8\u1eba\u1ebc\u1ebe\u1ec0\u1ec2\u1ec4\u1ec6",
- // F
- "\u1e1e",
- // G
- "\u011c\u011E\u0120\u0122\u01e4\u01e6\u01f4\u1e20",
- // H
- "\u0124\u0126\u021e\u1e22\u1e24\u1e26\u1e28\u1e2a",
- // I
- "\u00CC\u00CD\u00CE\u00CF\u0128\u012a\u012C\u012e\u0130\u0208\u020a\u1e2c\u1e2e\u1ec8\u1eca",
- // J
- "\u0134\u01f0",
- // K
- "\u0136\u0198\u01e8\u1e30\u1e32\u1e34",
- // L
- "\u0139\u013B\u013D\u013F\u0141\u1e36\u1e38\u1e3a\u1e3c",
- // M
- "\u1e3e\u1e40\u1e42",
- // N
- "\u00D1\u0143\u0145\u0147\u014A\u01F8\u1e44\u1e46\u1e48\u1e4a",
- // O
- "\u00D2\u00D3\u00D4\u00D5\u00D6\u014C\u014E\u0150\u01ea\u01ec\u020c\u020e\u022A\u022C\u022E\u0230\u1e4c\u1e4e\u1e50\u1e52\u1ecc\u1ece\u1ed0\u1ed2\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2",
- // P
- "\u1e54\u1e56",
- // No Q
- // R
- "\u0154\u0156\u0158\u0210\u0212\u1e58\u1e5a\u1e5c\u1e5e",
- // S
- "\u015A\u015C\u015E\u0160\u0218\u1e60\u1e62\u1e64\u1e66\u1e68",
- // T
- "\u0162\u0164\u0166\u021A\u1e6a\u1e6c\u1e6e\u1e70",
- // U
- "\u00D9\u00DA\u00DB\u00DC\u0168\u016A\u016C\u016E\u0170\u0172\u0214\u0216\u1e72\u1e74\u1e76\u1e78\u1e7a\u1ee4\u1ee6\u1ee8\u1eea\u1eec\u1eee\u1ef0",
- // V
- "\u1e7c\u1e7e",
- // W
- "\u0174\u1e80\u1e82\u1e84\u1e86\u1e88",
- // X
- "\u1e8a\u1e8c",
- // Y
- "\u00DD\u0176\u0178\u0232\u1e8e\u1ef2\u1ef4\u1ef6\u1ef8",
- // Z
- "\u0179\u017B\u017D\u0224\u1e90\u1e92\u1e94"
-];
-
-const lower=[
- // a
- "\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5\u0101\u0103\u0105\u01ce\u01df\u01e1\u01fb\u0201\u0203\u0227\u1e01\u1e9a\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7",
- // b
- "\u0180\u0183\u0185\u1e03\u1e05\u1e07",
- // c
- "\u00e7\u0107\u0109\u010b\u010d\u0188\u1e09",
- // d
- "\u010f\u0111\u1e0b\u1e0d\u1e0f\u1e11\u1e13",
- // e
- "\u00e8\u00e9\u00ea\u00eb\u0113\u0115\u0117\u0119\u011b\u0205\u0207\u0229\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7",
- // f
- "\u1e1f",
- // g
- "\u011d\u011f\u0121\u0123\u01e5\u01e7\u01f5\u1e21",
- // h
- "\u0125\u0127\u021f\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e96",
- // i
- "\u00ec\u00ed\u00ee\u00ef\u0129\u012b\u012d\u012f\u0131\u01d0\u0209\u020b\u1e2d\u1e2f\u1ec9\u1ecb",
- // j
- "\u0135",
- // k
- "\u0137\u0138\u01e9\u1e31\u1e33\u1e35",
- // l
- "\u013a\u013c\u013e\u0140\u0142\u1e37\u1e39\u1e3b\u1e3d",
- // m
- "\u1e3f\u1e41\u1e43",
- // n
- "\u00f1\u0144\u0146\u0148\u0149\u014b\u01f9\u1e45\u1e47\u1e49\u1e4b",
- // o
- "\u00f2\u00f3\u00f4\u00f5\u00f6\u014d\u014f\u0151\u01d2\u01eb\u01ed\u020d\u020e\u022b\u022d\u022f\u0231\u1e4d\u1e4f\u1e51\u1e53\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3",
- // p
- "\u1e55\u1e57",
- // No q
- // r
- "\u0155\u0157\u0159\u0211\u0213\u1e59\u1e5b\u1e5d\u1e5f",
- // s
- "\u015b\u015d\u015f\u0161\u0219\u1e61\u1e63\u1e65\u1e67\u1e69",
- // t
- "\u0162\u0163\u0165\u0167\u021b\u1e6b\u1e6d\u1e6f\u1e71\u1e97",
- // u
- "\u00f9\u00fa\u00fb\u00fc\u0169\u016b\u016d\u016f\u0171\u0173\u01d4\u01d6\u01d8\u01da\u01dc\u0215\u0217\u1e73\u1e75\u1e77\u1e79\u1e7b\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1",
- // v
- "\u1e7d\u1e7f",
- // w
- "\u0175\u1e81\u1e83\u1e85\u1e87\u1e89\u1e98",
- // x
- "\u1e8b\u1e8d",
- // y
- "\u00fd\u00ff\u0177\u0233\u1e8f\u1e99\u1ef3\u1ef5\u1ef7\u1ef9",
- // z
- "\u017a\u017c\u017e\u0225\u1e91\u1e93\u1e95"
-];
-
-
-const symbol = "\u00a1\u00a2\u00a3\u00a4\u00a5\u20ac\u00a6\u00a7\u00a8\u00a9\u00aa\u00ab\u00ac\u00ae\u00af\u00b0\u00b1\u00b2\u00b3\u00b4\u00b5\u00b6\u00b7\u00b8\u00b9\u00ba\u00bb\u00bc\u00bd\u00be\u00bf\u00d7\u00f7";
-
-const otherupper = "\u00c6\u00d0\u00d8\u00de\u0132\u0152\u0186\u01c4\u01c5\u01c7\u01c8\u01ca\u01cb\u01F1\u01f2";
-
-const otherlower = "\u00e6\u00f0\u00f8\u00fe\u00df\u0133\u0153\u01c6\u01c9\u01cc\u01f3";
diff --git a/editor/ui/dialogs/content/EdInsertChars.xul b/editor/ui/dialogs/content/EdInsertChars.xul
deleted file mode 100644
index 3a2836af6..000000000
--- a/editor/ui/dialogs/content/EdInsertChars.xul
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorInsertChars.dtd">
-
-<dialog id="insertCharsDlg" title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload = "Startup()"
- onfocus = "onFocus()"
- buttonlabelaccept="&insertButton.label;"
- buttonlabelcancel="&closeButton.label;"
- ondialogaccept = "return onAccept();"
- ondialogcancel = "return onClose();"
- style = "width: 20em">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdInsertChars.js"/>
-
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
- <broadcaster id="args" value=""/>
-
- <groupbox><caption label="&category.label;"/>
- <radiogroup id="CatGrp" persist="category letter_index char_index">
- <radio id="AccentUpper" label="&accentUpper.label;" oncommand="ChangeCategory(this.id)"/>
- <radio id="AccentLower" label="&accentLower.label;" oncommand="ChangeCategory(this.id)"/>
- <radio id="Upper" label="&otherUpper.label;" oncommand="ChangeCategory(this.id)"/>
- <radio id="Lower" label="&otherLower.label;" oncommand="ChangeCategory(this.id)"/>
- <radio id="Symbol" label="&commonSymbols.label;" oncommand="ChangeCategory(this.id)"/>
- </radiogroup>
- <spacer class="spacer"/>
- </groupbox>
- <hbox equalsize="always">
- <vbox flex="1">
- <!-- value is set in JS from editor.properties strings -->
- <label id="LatinL_Label" control="LatinL" value="&letter.label;" accesskey="&letter.accessKey;"/>
- <menulist class="larger" flex="1" id="LatinL" oncommand="SelectLatinLetter()">
- <menupopup/>
- </menulist>
- </vbox>
- <vbox flex="1">
- <label id="LatinM_Label" control="LatinM" value="&character.label;" accesskey="&character.accessKey;"/>
- <menulist class="larger" flex="1" id="LatinM" oncommand="SelectLatinModifier()">
- <menupopup/>
- </menulist>
- </vbox>
- </hbox>
- <separator class="groove"/>
-</dialog>
diff --git a/editor/ui/dialogs/content/EdInsertMath.js b/editor/ui/dialogs/content/EdInsertMath.js
deleted file mode 100644
index c8c10b158..000000000
--- a/editor/ui/dialogs/content/EdInsertMath.js
+++ /dev/null
@@ -1,314 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Insert MathML dialog */
-
-var XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-
-function Startup()
-{
- var editor = GetCurrentEditor();
- if (!editor) {
- window.close();
- return;
- }
-
- // Create dialog object for easy access
- gDialog.accept = document.documentElement.getButton("accept");
- gDialog.mode = document.getElementById("optionMode");
- gDialog.direction = document.getElementById("optionDirection");
- gDialog.input = document.getElementById("input");
- gDialog.output = document.getElementById("output");
- gDialog.tabbox = document.getElementById("tabboxInsertLaTeXCommand");
-
- // Set initial focus
- gDialog.input.focus();
-
- // Load TeXZilla
- // TeXZilla.js contains non-ASCII characters and explicitly sets
- // window.TeXZilla, so we have to specify the charset parameter but don't
- // need to worry about the targetObj parameter.
- Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
- .getService(Components.interfaces.mozIJSSubScriptLoader)
- .loadSubScript("chrome://editor/content/TeXZilla.js", {}, "UTF-8");
-
- // Verify if the selection is on a <math> and initialize the dialog.
- gDialog.oldMath = editor.getElementOrParentByTagName("math", null);
- if (gDialog.oldMath) {
- // When these attributes are absent or invalid, they default to "inline" and "ltr" respectively.
- gDialog.mode.selectedIndex = gDialog.oldMath.getAttribute("display") == "block" ? 1 : 0;
- gDialog.direction.selectedIndex = gDialog.oldMath.getAttribute("dir") == "rtl" ? 1 : 0;
- gDialog.input.value = TeXZilla.getTeXSource(gDialog.oldMath);
- }
-
- // Create the tabbox with LaTeX commands.
- createCommandPanel({
- "√⅗²": ["{⋯}^{⋯}",
- "{⋯}_{⋯}",
- "{⋯}_{⋯}^{⋯}",
- "\\underset{⋯}{⋯}",
- "\\overset{⋯}{⋯}",
- "\\underoverset{⋯}{⋯}{⋯}",
- "\\left(⋯\\right)",
- "\\left[⋯\\right]",
- "\\frac{⋯}{⋯}",
- "\\binom{⋯}{⋯}",
- "\\sqrt{⋯}",
- "\\sqrt[⋯]{⋯}",
- "\\cos\\left({⋯}\\right)",
- "\\sin\\left({⋯}\\right)",
- "\\tan\\left({⋯}\\right)",
- "\\exp\\left({⋯}\\right)",
- "\\ln\\left({⋯}\\right)",
- "\\underbrace{⋯}",
- "\\underline{⋯}",
- "\\overbrace{⋯}",
- "\\widevec{⋯}",
- "\\widetilde{⋯}",
- "\\widehat{⋯}",
- "\\widecheck{⋯}",
- "\\widebar{⋯}",
- "\\dot{⋯}",
- "\\ddot{⋯}",
- "\\boxed{⋯}",
- "\\slash{⋯}"
- ],
- "(▦)": ["\\begin{matrix} ⋯ & ⋯ \\\\ ⋯ & ⋯ \\end{matrix}",
- "\\begin{pmatrix} ⋯ & ⋯ \\\\ ⋯ & ⋯ \\end{pmatrix}",
- "\\begin{bmatrix} ⋯ & ⋯ \\\\ ⋯ & ⋯ \\end{bmatrix}",
- "\\begin{Bmatrix} ⋯ & ⋯ \\\\ ⋯ & ⋯ \\end{Bmatrix}",
- "\\begin{vmatrix} ⋯ & ⋯ \\\\ ⋯ & ⋯ \\end{vmatrix}",
- "\\begin{Vmatrix} ⋯ & ⋯ \\\\ ⋯ & ⋯ \\end{Vmatrix}",
- "\\begin{cases} ⋯ \\\\ ⋯ \\end{cases}",
- "\\begin{aligned} ⋯ &= ⋯ \\\\ ⋯ &= ⋯ \\end{aligned}"
- ]
- });
- createSymbolPanels([
- "∏∐∑∫∬∭⨌∮⊎⊕⊖⊗⊘⊙⋀⋁⋂⋃⌈⌉⌊⌋⎰⎱⟨⟩⟪⟫∥⫼⨀⨁⨂⨄⨅⨆ðıȷℏℑℓ℘ℜℵℶ",
- "∀∃∄∅∉∊∋∌⊂⊃⊄⊅⊆⊇⊈⊈⊉⊊⊊⊋⊋⊏⊐⊑⊒⊓⊔⊥⋐⋑⋔⫅⫆⫋⫋⫌⫌…⋮⋯⋰⋱♭♮♯∂∇",
- "±×÷†‡•∓∔∗∘∝∠∡∢∧∨∴∵∼∽≁≃≅≇≈≈≊≍≎≏≐≑≒≓≖≗≜≡≢≬⊚⊛⊞⊡⊢⊣⊤⊥",
- "⊨⊩⊪⊫⊬⊭⊯⊲⊲⊳⊴⊵⊸⊻⋄⋅⋇⋈⋉⋊⋋⋌⋍⋎⋏⋒⋓⌅⌆⌣△▴▵▸▹▽▾▿◂◃◊○★♠♡♢♣⧫",
- "≦≧≨≩≩≪≫≮≯≰≱≲≳≶≷≺≻≼≽≾≿⊀⊁⋖⋗⋘⋙⋚⋛⋞⋟⋦⋧⋨⋩⩽⩾⪅⪆⪇⪈⪉⪊⪋⪌⪕⪯⪰⪷⪸⪹⪺",
- "←↑→↓↔↕↖↗↘↙↜↝↞↠↢↣↦↩↪↫↬↭↭↰↱↼↽↾↿⇀⇁⇂⇃⇄⇆⇇⇈⇉⇊⇋⇌⇐⇑⇒⇓⇕⇖⇗⇘⇙⟺",
- "αβγδϵ϶εζηθϑικϰλμνξℴπϖρϱσςτυϕφχψωΓΔΘΛΞΠΣϒΦΨΩϝ℧",
- "𝕒𝕓𝕔𝕕𝕖𝕗𝕘𝕙𝕚𝕛𝕜𝕝𝕞𝕟𝕠𝕡𝕢𝕣𝕤𝕥𝕦𝕧𝕨𝕩𝕪𝕫𝔸𝔹ℂ𝔻𝔼𝔽𝔾ℍ𝕀𝕁𝕂𝕃𝕄ℕ𝕆ℙℚℝ𝕊𝕋𝕌𝕍𝕎𝕏𝕐ℤ",
- "𝒶𝒷𝒸𝒹ℯ𝒻ℊ𝒽𝒾𝒿𝓀𝓁𝓂𝓃ℴ𝓅𝓆𝓇𝓈𝓉𝓊𝓋𝓌𝓍𝓎𝓏𝒜ℬ𝒞𝒟ℰℱ𝒢ℋℐ𝒥𝒦ℒℳ𝒩𝒪𝒫𝒬ℛ𝒮𝒯𝒰𝒱𝒲𝒳𝒴𝒵",
- "𝔞𝔟𝔠𝔡𝔢𝔣𝔤𝔥𝔦𝔧𝔨𝔩𝔪𝔫𝔬𝔭𝔮𝔯𝔰𝔱𝔲𝔳𝔴𝔵𝔶𝔷𝔄𝔅ℭ𝔇𝔈𝔉𝔊ℌℑ𝔍𝔎𝔏𝔐𝔑𝔒𝔓𝔔ℜ𝔖𝔗𝔘𝔙𝔚𝔛𝔜ℨ"
- ]);
- gDialog.tabbox.selectedIndex = 0;
-
- updateMath();
-
- SetWindowLocation();
-}
-
-function insertLaTeXCommand(aButton)
-{
- gDialog.input.focus();
-
- // For a single math symbol, just use the insertText command.
- if (aButton.label) {
- gDialog.input.editor.QueryInterface(Components.interfaces.nsIPlaintextEditor).insertText(aButton.label);
- return;
- }
-
- // Otherwise, it's a LaTeX command with at least one argument...
- var latex = TeXZilla.getTeXSource(aButton.firstChild);
- var selectionStart = gDialog.input.selectionStart;
- var selectionEnd = gDialog.input.selectionEnd;
-
- // If the selection is not empty, we replace the first argument of the LaTeX
- // command with the current selection.
- var selection = gDialog.input.value.substring(selectionStart, selectionEnd);
- if (selection != "") {
- latex = latex.replace("⋯", selection);
- }
-
- // Try and move to the next position.
- var latexNewStart = latex.indexOf("⋯"), latexNewEnd;
- if (latexNewStart == -1) {
- // This is a unary function and the selection was used as an argument above.
- // We select the expression again so that one can choose to apply further
- // command to it or just move the caret after that text.
- latexNewStart = 0;
- latexNewEnd = latex.length;
- } else {
- // Otherwise, select the dots representing the next argument.
- latexNewEnd = latexNewStart + 1;
- }
-
- // Update the input text and selection.
- gDialog.input.editor.QueryInterface(Components.interfaces.nsIPlaintextEditor).insertText(latex);
- gDialog.input.setSelectionRange(selectionStart + latexNewStart,
- selectionStart + latexNewEnd);
-
- updateMath();
-}
-
-function createCommandPanel(aCommandPanelList)
-{
- const columnCount = 10;
-
- for (var label in aCommandPanelList) {
-
- var commands = aCommandPanelList[label];
-
- // Create a <rows> element with some LaTeX commands.
- var rows = document.createElementNS(XULNS, "rows");
-
- var i = 0, row;
- for (var command of commands) {
- if (i % columnCount == 0) {
- // Create a new row.
- row = document.createElementNS(XULNS, "row");
- rows.appendChild(row);
- }
-
- // Create a new button to insert the symbol.
- var button = document.createElementNS(XULNS, "toolbarbutton");
- button.setAttribute("class", "tabbable");
- button.appendChild(TeXZilla.toMathML(command));
- row.appendChild(button);
-
- i++;
- }
-
- // Create a <columns> element with the desired number of columns.
- var columns = document.createElementNS(XULNS, "columns");
- for (i = 0; i < columnCount; i++) {
- var column = document.createElementNS(XULNS, "column");
- column.setAttribute("flex", "1");
- columns.appendChild(column);
- }
-
- // Create the <grid> element with the <rows> and <columns> children.
- var grid = document.createElementNS(XULNS, "grid");
- grid.appendChild(columns);
- grid.appendChild(rows);
-
- // Create a new <tab> element.
- var tab = document.createElementNS(XULNS, "tab");
- tab.setAttribute("label", label);
- gDialog.tabbox.tabs.appendChild(tab);
-
- // Append the new tab panel.
- gDialog.tabbox.tabpanels.appendChild(grid);
- }
-}
-
-function createSymbolPanels(aSymbolPanelList)
-{
- const columnCount = 13, tabLabelLength = 3
-
- for (var symbols of aSymbolPanelList) {
-
- // Create a <rows> element with the symbols of the i-th panel.
- var rows = document.createElementNS(XULNS, "rows");
- var i = 0, tabLabel = "", row;
- for (var symbol of symbols) {
- if (i % columnCount == 0) {
- // Create a new row.
- row = document.createElementNS(XULNS, "row");
- rows.appendChild(row);
- }
-
- // Build the tab label from the first symbols of this tab.
- if (i < tabLabelLength) {
- tabLabel += symbol;
- }
-
- // Create a new button to insert the symbol.
- var button = document.createElementNS(XULNS, "toolbarbutton");
- button.setAttribute("label", symbol);
- button.setAttribute("class", "tabbable");
- row.appendChild(button);
-
- i++;
- }
-
- // Create a <columns> element with the desired number of columns.
- var columns = document.createElementNS(XULNS, "columns");
- for (i = 0; i < columnCount; i++) {
- var column = document.createElementNS(XULNS, "column");
- column.setAttribute("flex", "1");
- columns.appendChild(column);
- }
-
- // Create the <grid> element with the <rows> and <columns> children.
- var grid = document.createElementNS(XULNS, "grid");
- grid.appendChild(columns);
- grid.appendChild(rows);
-
- // Create a new <tab> element with the label determined above.
- var tab = document.createElementNS(XULNS, "tab");
- tab.setAttribute("label", tabLabel);
- gDialog.tabbox.tabs.appendChild(tab);
-
- // Append the new tab panel.
- gDialog.tabbox.tabpanels.appendChild(grid);
- }
-}
-
-function onAccept()
-{
- if (gDialog.output.firstChild)
- {
- var editor = GetCurrentEditor();
- editor.beginTransaction();
-
- try {
- var newMath = editor.document.importNode(gDialog.output.firstChild, true);
- if (gDialog.oldMath) {
- // Replace the old <math> element with the new one.
- editor.selectElement(gDialog.oldMath);
- editor.insertElementAtSelection(newMath, true);
- } else {
- // Insert the new <math> element.
- editor.insertElementAtSelection(newMath, false);
- }
- } catch (e) {}
-
- editor.endTransaction();
- }
- else
- {
- dump("Null value -- not inserting in MathML Source dialog\n");
- return false;
- }
- SaveWindowLocation();
-
- return true;
-}
-
-function updateMath()
-{
- // Remove the preview, if any.
- if (gDialog.output.firstChild)
- gDialog.output.firstChild.remove();
-
- // Try to convert the LaTeX source into MathML using TeXZilla.
- // We use the placeholder text if no input is provided.
- try {
- var input = gDialog.input.value || gDialog.input.placeholder;
- var newMath = TeXZilla.toMathML(input, gDialog.mode.selectedIndex, gDialog.direction.selectedIndex, true);
- gDialog.output.appendChild(document.importNode(newMath, true));
- gDialog.output.style.opacity = gDialog.input.value ? 1 : .5;
- } catch (e) {
- }
- // Disable the accept button if parsing fails or when the placeholder is used.
- gDialog.accept.disabled = !gDialog.input.value || !gDialog.output.firstChild;
-}
-
-function updateMode()
-{
- if (gDialog.output.firstChild)
- gDialog.output.firstChild.setAttribute("display", gDialog.mode.selectedIndex ? "block" : "inline");
-}
-
-function updateDirection()
-{
- if (gDialog.output.firstChild)
- gDialog.output.firstChild.setAttribute("dir", gDialog.direction.selectedIndex ? "rtl" : "ltr");
-}
diff --git a/editor/ui/dialogs/content/EdInsertMath.xul b/editor/ui/dialogs/content/EdInsertMath.xul
deleted file mode 100644
index 93ae0e4bc..000000000
--- a/editor/ui/dialogs/content/EdInsertMath.xul
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-- License, v. 2.0. If a copy of the MPL was not distributed with this
-- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorInsertMath.dtd">
-
-<dialog title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="Startup();"
- buttonlabelaccept="&insertButton.label;"
- buttonaccesskeyaccept="&insertButton.accesskey;"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript"
- src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript"
- src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript"
- src="chrome://editor/content/EdInsertMath.js"/>
-
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
- <broadcaster id="args" value=""/>
-
- <label id="srcMessage" value="&sourceEditField.label;"/>
- <textbox id="input" rows="5" multiline="true" oninput="updateMath();"
- placeholder="\sqrt{x_1} + \frac{π^3}{2}"/>
- <vbox flex="1" style="overflow: auto; width: 30em; height: 5em;">
- <description id="output"/>
- </vbox>
- <tabbox id="tabboxInsertLaTeXCommand">
- <tabs/>
- <tabpanels oncommand="insertLaTeXCommand(event.target);"/>
- </tabbox>
- <spacer class="spacer"/>
- <groupbox>
- <caption label="&options.label;"/>
- <hbox>
- <radiogroup id="optionMode" oncommand="updateMode();">
- <radio label="&optionInline.label;"
- accesskey="&optionInline.accesskey;"/>
- <radio label="&optionDisplay.label;"
- accesskey="&optionDisplay.accesskey;"/>
- </radiogroup>
- <radiogroup id="optionDirection" oncommand="updateDirection();">
- <radio label="&optionLTR.label;"
- accesskey="&optionLTR.accesskey;"/>
- <radio label="&optionRTL.label;"
- accesskey="&optionRTL.accesskey;"/>
- </radiogroup>
- </hbox>
- </groupbox>
- <spacer class="spacer"/>
- <separator class="groove"/>
-</dialog>
diff --git a/editor/ui/dialogs/content/EdInsertTOC.js b/editor/ui/dialogs/content/EdInsertTOC.js
deleted file mode 100644
index 21b307135..000000000
--- a/editor/ui/dialogs/content/EdInsertTOC.js
+++ /dev/null
@@ -1,378 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// tocHeadersArray is the array containing the pairs tag/class
-// defining TOC entries
-var tocHeadersArray = new Array(6);
-
-// a global used when building the TOC
-var currentHeaderLevel = 0;
-
-// a global set to true if the TOC is to be readonly
-var readonly = false;
-
-// a global set to true if user wants indexes in the TOC
-var orderedList = true;
-
-// constants
-const kMozToc = "mozToc";
-const kMozTocLength = 6;
-const kMozTocIdPrefix = "mozTocId";
-const kMozTocIdPrefixLength = 8;
-const kMozTocClassPrefix = "mozToc";
-const kMozTocClassPrefixLength = 6;
-
-// Startup() is called when EdInsertTOC.xul is opened
-function Startup()
-{
- // early way out if if we have no editor
- if (!GetCurrentEditor()) {
- window.close();
- return;
- }
-
- var i, j;
- // clean the table of tag/class pairs we look for
- for (i = 0; i < 6; ++i)
- tocHeadersArray[i] = [ "", "" ];
-
- // reset all settings
- for (i = 1; i < 7; ++i) {
- var menulist = document.getElementById("header" + i + "Menulist");
- var menuitem = document.getElementById("header" + i + "none");
- var textbox = document.getElementById("header" + i + "Class");
- menulist.selectedItem = menuitem;
- textbox.setAttribute("disabled", "true");
- }
-
- var theDocument = GetCurrentEditor().document;
-
- // do we already have a TOC in the document ? It should have "mozToc" ID
- var toc = theDocument.getElementById(kMozToc);
-
- // default TOC definition, use h1-h6 for TOC entry levels 1-6
- var headers = "h1 1 h2 2 h3 3 h4 4 h5 5 h6 6";
-
- var orderedListCheckbox = document.getElementById("orderedListCheckbox");
- orderedListCheckbox.checked = true;
-
- if (toc) {
- // man, there is already a TOC here
-
- if (toc.getAttribute("class") == "readonly") {
- // and it's readonly
- var checkbox = document.getElementById("readOnlyCheckbox");
- checkbox.checked = true;
- readonly = true;
- }
-
- // let's see if it's an OL or an UL
- orderedList = (toc.nodeName.toLowerCase() == "ol");
- orderedListCheckbox.checked = orderedList;
-
- var nodeList = toc.childNodes;
- // let's look at the children of the TOC ; if we find a comment beginning
- // with "mozToc", it contains the TOC definition
- for (i = 0; i< nodeList.length; ++i) {
- if (nodeList.item(i).nodeType == Node.COMMENT_NODE &&
- nodeList.item(i).data.startsWith(kMozToc)) {
- // yep, there is already a definition here; parse it !
- headers = nodeList.item(i).data.substr(kMozTocLength + 1,
- nodeList.item(i).length - kMozTocLength - 1);
- break;
- }
- }
- }
-
- // let's get an array filled with the (tag.class, index level) pairs
- var headersArray = headers.split(" ");
-
- for (i = 0; i < headersArray.length; i += 2) {
- var tag = headersArray[i], className = "";
- var index = headersArray[i + 1];
- menulist = document.getElementById("header" + index + "Menulist");
- if (menulist) {
- var sep = tag.indexOf(".");
- if (sep != -1) {
- // the tag variable contains in fact "tag.className", let's parse
- // the class and get the real tag name
- var tmp = tag.substr(0, sep);
- className = tag.substr(sep + 1, tag.length - sep - 1);
- tag = tmp;
- }
-
- // update the dialog
- menuitem = document.getElementById("header" + index +
- tag.toUpperCase());
- textbox = document.getElementById("header" + index + "Class");
- menulist.selectedItem = menuitem;
- if (tag != "") {
- textbox.removeAttribute("disabled");
- }
- if (className != "") {
- textbox.value = className;
- }
- tocHeadersArray[index - 1] = [ tag, className ];
- }
- }
-}
-
-
-function BuildTOC(update)
-{
- // controlClass() is a node filter that accepts a node if
- // (a) we don't look for a class (b) we look for a class and
- // node has it
- function controlClass(node, index)
- {
- currentHeaderLevel = index + 1;
- if (tocHeadersArray[index][1] == "") {
- // we are not looking for a specific class, this node is ok
- return NodeFilter.FILTER_ACCEPT;
- }
- if (node.getAttribute("class")) {
- // yep, we look for a class, let's look at all the classes
- // the node has
- var classArray = node.getAttribute("class").split(" ");
- for (var j = 0; j < classArray.length; j++) {
- if (classArray[j] == tocHeadersArray[index][1]) {
- // hehe, we found it...
- return NodeFilter.FILTER_ACCEPT;
- }
- }
- }
- return NodeFilter.FILTER_SKIP;
- }
-
- // the main node filter for our node iterator
- // it selects the tag names as specified in the dialog
- // then calls the controlClass filter above
- function acceptNode(node)
- {
- switch (node.nodeName.toLowerCase())
- {
- case tocHeadersArray[0][0]:
- return controlClass(node, 0);
- break;
- case tocHeadersArray[1][0]:
- return controlClass(node, 1);
- break;
- case tocHeadersArray[2][0]:
- return controlClass(node, 2);
- break;
- case tocHeadersArray[3][0]:
- return controlClass(node, 3);
- break;
- case tocHeadersArray[4][0]:
- return controlClass(node, 4);
- break;
- case tocHeadersArray[5][0]:
- return controlClass(node, 5);
- break;
- default:
- return NodeFilter.FILTER_SKIP;
- break;
- }
- return NodeFilter.FILTER_SKIP; // placate the js compiler
- }
-
- var editor = GetCurrentEditor();
- var theDocument = editor.document;
- // let's create a TreeWalker to look for our nodes
- var treeWalker = theDocument.createTreeWalker(theDocument.documentElement,
- NodeFilter.SHOW_ELEMENT,
- acceptNode,
- true);
- // we need an array to store all TOC entries we find in the document
- var tocArray = new Array();
- if (treeWalker) {
- var tocSourceNode = treeWalker.nextNode();
- while (tocSourceNode) {
- var headerIndex = currentHeaderLevel;
-
- // we have a node, we need to get all its textual contents
- var textTreeWalker = theDocument.createTreeWalker(tocSourceNode,
- NodeFilter.SHOW_TEXT,
- null,
- true);
- var textNode = textTreeWalker.nextNode(), headerText = "";
- while (textNode) {
- headerText += textNode.data;
- textNode = textTreeWalker.nextNode();
- }
-
- var anchor = tocSourceNode.firstChild, id;
- // do we have a named anchor as 1st child of our node ?
- if (anchor.nodeName.toLowerCase() == "a" &&
- anchor.hasAttribute("name") &&
- anchor.getAttribute("name").startsWith(kMozTocIdPrefix)) {
- // yep, get its name
- id = anchor.getAttribute("name");
- }
- else {
- // no we don't and we need to create one
- anchor = theDocument.createElement("a");
- tocSourceNode.insertBefore(anchor, tocSourceNode.firstChild);
- // let's give it a random ID
- var c = 1000000 * Math.random();
- id = kMozTocIdPrefix + Math.round(c);
- anchor.setAttribute("name", id);
- anchor.setAttribute("class", kMozTocClassPrefix +
- tocSourceNode.nodeName.toUpperCase());
- }
- // and store that new entry in our array
- tocArray.push(headerIndex, headerText, id);
- tocSourceNode = treeWalker.nextNode();
- }
- }
-
- /* generate the TOC itself */
- headerIndex = 0;
- var item, toc;
- for (var i = 0; i < tocArray.length; i += 3) {
- if (!headerIndex) {
- // do we need to create an ol/ul container for the first entry ?
- ++headerIndex;
- toc = theDocument.getElementById(kMozToc);
- if (!toc || !update) {
- // we need to create a list container for the table of contents
- toc = GetCurrentEditor().createElementWithDefaults(orderedList ? "ol" : "ul");
- // grrr, we need to create a LI inside the list otherwise
- // Composer will refuse an empty list and will remove it !
- var pit = theDocument.createElement("li");
- toc.appendChild(pit);
- GetCurrentEditor().insertElementAtSelection(toc, true);
- // ah, now it's inserted so let's remove the useless list item...
- toc.removeChild(pit);
- // we need to recognize later that this list is our TOC
- toc.setAttribute("id", kMozToc);
- }
- else {
- // we have to update an existing TOC, is the existing TOC of the
- // desired type (ordered or not) ?
- if (orderedList != (toc.nodeName.toLowerCase() == "ol")) {
- // nope, we have to recreate the list
- var newToc = GetCurrentEditor().createElementWithDefaults(orderedList ? "ol" : "ul");
- toc.parentNode.insertBefore(newToc, toc);
- // and remove the old one
- toc.remove();
- toc = newToc;
- toc.setAttribute("id", kMozToc);
- }
- else {
- // we can keep the list itself but let's get rid of the TOC entries
- while (toc.hasChildNodes())
- toc.lastChild.remove();
- }
- }
- var commentText = "mozToc ";
- for (var j = 0; j < 6; j++) {
- if (tocHeadersArray[j][0] != "") {
- commentText += tocHeadersArray[j][0];
- if (tocHeadersArray[j][1] != "") {
- commentText += "." + tocHeadersArray[j][1];
- }
- commentText += " " + (j + 1) + " ";
- }
- }
- // important, we have to remove trailing spaces
- commentText = TrimStringRight(commentText);
-
- // forge a comment we'll insert in the TOC ; that comment will hold
- // the TOC definition for us
- var ct = theDocument.createComment(commentText);
- toc.appendChild(ct);
-
- // assign a special class to the TOC top element if the TOC is readonly
- // the definition of this class is in EditorOverride.css
- if (readonly) {
- toc.setAttribute("class", "readonly");
- }
- else {
- toc.removeAttribute("class");
- }
-
- // We need a new variable to hold the local ul/ol container
- // The toplevel TOC element is not the parent element of a
- // TOC entry if its depth is > 1...
- var tocList = toc;
- // create a list item
- var tocItem = theDocument.createElement("li");
- // and an anchor in this list item
- var tocAnchor = theDocument.createElement("a");
- // make it target the source of the TOC entry
- tocAnchor.setAttribute("href", "#" + tocArray[i + 2]);
- // and put the textual contents of the TOC entry in that anchor
- var tocEntry = theDocument.createTextNode(tocArray[i + 1]);
- // now, insert everything where it has to be inserted
- tocAnchor.appendChild(tocEntry);
- tocItem.appendChild(tocAnchor);
- tocList.appendChild(tocItem);
- item = tocList;
- }
- else {
- if (tocArray[i] < headerIndex) {
- // if the depth of the new TOC entry is less than the depth of the
- // last entry we created, find the good ul/ol ancestor
- for (j = headerIndex - tocArray[i]; j > 0; --j) {
- if (item != toc) {
- item = item.parentNode.parentNode;
- }
- }
- tocItem = theDocument.createElement("li");
- }
- else if (tocArray[i] > headerIndex) {
- // to the contrary, it's deeper than the last one
- // we need to create sub ul/ol's and li's
- for (j = tocArray[i] - headerIndex; j > 0; --j) {
- tocList = theDocument.createElement(orderedList ? "ol" : "ul");
- item.lastChild.appendChild(tocList);
- tocItem = theDocument.createElement("li");
- tocList.appendChild(tocItem);
- item = tocList;
- }
- }
- else {
- tocItem = theDocument.createElement("li");
- }
- tocAnchor = theDocument.createElement("a");
- tocAnchor.setAttribute("href", "#" + tocArray[i + 2]);
- tocEntry = theDocument.createTextNode(tocArray[i + 1]);
- tocAnchor.appendChild(tocEntry);
- tocItem.appendChild(tocAnchor);
- item.appendChild(tocItem);
- headerIndex = tocArray[i];
- }
- }
- SaveWindowLocation();
- return true;
-}
-
-function selectHeader(elt, index)
-{
- var tag = elt.value;
- tocHeadersArray[index - 1][0] = tag;
- var textbox = document.getElementById("header" + index + "Class");
- if (tag == "") {
- textbox.setAttribute("disabled", "true");
- }
- else {
- textbox.removeAttribute("disabled");
- }
-}
-
-function changeClass(elt, index)
-{
- tocHeadersArray[index - 1][1] = elt.value;
-}
-
-function ToggleReadOnlyToc(elt)
-{
- readonly = elt.checked;
-}
-
-function ToggleOrderedList(elt)
-{
- orderedList = elt.checked;
-}
diff --git a/editor/ui/dialogs/content/EdInsertTOC.xul b/editor/ui/dialogs/content/EdInsertTOC.xul
deleted file mode 100644
index b4d5697a3..000000000
--- a/editor/ui/dialogs/content/EdInsertTOC.xul
+++ /dev/null
@@ -1,227 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorInsertTOC.dtd">
-
-<dialog title="&Window.title;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:html="http://www.w3.org/1999/xhtml"
- onload="Startup();"
- ondialogaccept="return BuildTOC(true);"
- oncancel="window.close(); return true;">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
-
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdInsertTOC.js"/>
-
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
- <spacer id="dummy" style="display:none"/>
- <broadcaster id="args" value=""/>
- <vbox flex="1">
- <groupbox><caption label="&buildToc.label;"/>
- <grid>
- <columns><column/><column style="min-width: 6em"/><column/></columns>
- <rows>
- <row align="center">
- <spacer/>
- <label value="&tag.label;"/>
- <label value="&class.label;"/>
- </row>
- <row align="center">
- <label value="&header1.label;"/>
- <menulist id="header1Menulist">
- <menupopup>
- <menuitem id="header1none" label="--" value=""
- oncommand="selectHeader(this, 1)"/>
- <menuseparator/>
- <menuitem id="header1H1" label="h1" value="h1"
- oncommand="selectHeader(this, 1)"/>
- <menuitem id="header1H2" label="h2" value="h2"
- oncommand="selectHeader(this, 1)"/>
- <menuitem id="header1H3" label="h3" value="h3"
- oncommand="selectHeader(this, 1)"/>
- <menuitem id="header1H4" label="h4" value="h4"
- oncommand="selectHeader(this, 1)"/>
- <menuitem id="header1H5" label="h5" value="h5"
- oncommand="selectHeader(this, 1)"/>
- <menuitem id="header1H6" label="h6" value="h6"
- oncommand="selectHeader(this, 1)"/>
- <menuitem id="header1DIV" label="div" value="div"
- oncommand="selectHeader(this, 1)"/>
- <menuitem id="header1P" label="p" value="p"
- oncommand="selectHeader(this, 1)"/>
- </menupopup>
- </menulist>
- <textbox id="header1Class" size="10"
- oninput="changeClass(this, 1)"/>
- </row>
-
- <row align="center">
- <label value="&header2.label;"/>
- <menulist id="header2Menulist">
- <menupopup>
- <menuitem id="header2none" label="--" value=""
- oncommand="selectHeader(this, 2)"/>
- <menuseparator/>
- <menuitem id="header2H1" label="h1" value="h1"
- oncommand="selectHeader(this, 2)"/>
- <menuitem id="header2H2" label="h2" value="h2"
- oncommand="selectHeader(this, 2)"/>
- <menuitem id="header2H3" label="h3" value="h3"
- oncommand="selectHeader(this, 2)"/>
- <menuitem id="header2H4" label="h4" value="h4"
- oncommand="selectHeader(this, 2)"/>
- <menuitem id="header2H5" label="h5" value="h5"
- oncommand="selectHeader(this, 2)"/>
- <menuitem id="header2H6" label="h6" value="h6"
- oncommand="selectHeader(this, 2)"/>
- <menuitem id="header2DIV" label="div" value="div"
- oncommand="selectHeader(this, 2)"/>
- <menuitem id="header2P" label="p" value="p"
- oncommand="selectHeader(this, 2)"/>
- </menupopup>
- </menulist>
- <textbox id="header2Class" size="10"
- oninput="changeClass(this, 2)"/>
- </row>
-
- <row align="center">
- <label value="&header3.label;"/>
- <menulist id="header3Menulist">
- <menupopup>
- <menuitem id="header3none" label="--" value=""
- oncommand="selectHeader(this, 3)"/>
- <menuseparator/>
- <menuitem id="header3H1" label="h1" value="h1"
- oncommand="selectHeader(this, 3)"/>
- <menuitem id="header3H2" label="h2" value="h2"
- oncommand="selectHeader(this, 3)"/>
- <menuitem id="header3H3" label="h3" value="h3"
- oncommand="selectHeader(this, 3)"/>
- <menuitem id="header3H4" label="h4" value="h4"
- oncommand="selectHeader(this, 3)"/>
- <menuitem id="header3H5" label="h5" value="h5"
- oncommand="selectHeader(this, 3)"/>
- <menuitem id="header3H6" label="h6" value="h6"
- oncommand="selectHeader(this, 3)"/>
- <menuitem id="header3DIV" label="div" value="div"
- oncommand="selectHeader(this, 3)"/>
- <menuitem id="header3P" label="p" value="p"
- oncommand="selectHeader(this, 3)"/>
- </menupopup>
- </menulist>
- <textbox id="header3Class" size="10"
- oninput="changeClass(this, 3)"/>
- </row>
-
- <row align="center">
- <label value="&header4.label;"/>
- <menulist id="header4Menulist">
- <menupopup>
- <menuitem id="header4none" label="--" value=""
- oncommand="selectHeader(this, 4)"/>
- <menuseparator/>
- <menuitem id="header4H1" label="h1" value="h1"
- oncommand="selectHeader(this, 4)"/>
- <menuitem id="header4H2" label="h2" value="h2"
- oncommand="selectHeader(this, 4)"/>
- <menuitem id="header4H3" label="h3" value="h3"
- oncommand="selectHeader(this, 4)"/>
- <menuitem id="header4H4" label="h4" value="h4"
- oncommand="selectHeader(this, 4)"/>
- <menuitem id="header4H5" label="h5" value="h5"
- oncommand="selectHeader(this, 4)"/>
- <menuitem id="header4H6" label="h6" value="h6"
- oncommand="selectHeader(this, 4)"/>
- <menuitem id="header4DIV" label="div" value="div"
- oncommand="selectHeader(this, 4)"/>
- <menuitem id="header4P" label="p" value="p"
- oncommand="selectHeader(this, 4)"/>
- </menupopup>
- </menulist>
- <textbox id="header4Class" size="10"
- oninput="changeClass(this, 4)"/>
- </row>
-
- <row align="center">
- <label value="&header5.label;"/>
- <menulist id="header5Menulist">
- <menupopup>
- <menuitem id="header5none" label="--" value=""
- oncommand="selectHeader(this, 5)"/>
- <menuseparator/>
- <menuitem id="header5H1" label="h1" value="h1"
- oncommand="selectHeader(this, 5)"/>
- <menuitem id="header5H2" label="h2" value="h2"
- oncommand="selectHeader(this, 5)"/>
- <menuitem id="header5H3" label="h3" value="h3"
- oncommand="selectHeader(this, 5)"/>
- <menuitem id="header5H4" label="h4" value="h4"
- oncommand="selectHeader(this, 5)"/>
- <menuitem id="header5H5" label="h5" value="h5"
- oncommand="selectHeader(this, 5)"/>
- <menuitem id="header5H6" label="h6" value="h6"
- oncommand="selectHeader(this, 5)"/>
- <menuitem id="header5DIV" label="div" value="div"
- oncommand="selectHeader(this, 5)"/>
- <menuitem id="header5P" label="p" value="p"
- oncommand="selectHeader(this, 5)"/>
- </menupopup>
- </menulist>
- <textbox id="header5Class" size="10"
- oninput="changeClass(this, 5)"/>
- </row>
-
- <row align="center">
- <label value="&header6.label;"/>
- <menulist id="header6Menulist">
- <menupopup>
- <menuitem id="header6none" label="--" value=""
- oncommand="selectHeader(this, 6)"/>
- <menuseparator/>
- <menuitem id="header6H1" label="h1" value="h1"
- oncommand="selectHeader(this, 6)"/>
- <menuitem id="header6H2" label="h2" value="h2"
- oncommand="selectHeader(this, 6)"/>
- <menuitem id="header6H3" label="h3" value="h3"
- oncommand="selectHeader(this, 6)"/>
- <menuitem id="header6H4" label="h4" value="h4"
- oncommand="selectHeader(this, 6)"/>
- <menuitem id="header6H5" label="h5" value="h5"
- oncommand="selectHeader(this, 6)"/>
- <menuitem id="header6H6" label="h6" value="h6"
- oncommand="selectHeader(this, 6)"/>
- <menuitem id="header6DIV" label="div" value="div"
- oncommand="selectHeader(this, 6)"/>
- <menuitem id="header6P" label="p" value="p"
- oncommand="selectHeader(this, 6)"/>
- </menupopup>
- </menulist>
- <textbox id="header6Class" size="10"
- oninput="changeClass(this, 6)"/>
- </row>
- </rows>
- </grid>
- </groupbox>
- <vbox>
- <checkbox id="orderedListCheckbox"
- label="&orderedList.label;"
- oncommand="ToggleOrderedList(this)"/>
- <checkbox id="readOnlyCheckbox"
- label="&makeReadOnly.label;"
- oncommand="ToggleReadOnlyToc(this)"/>
- </vbox>
- <separator class="groove"/>
- </vbox>
-</dialog>
diff --git a/editor/ui/dialogs/content/EdInsertTable.js b/editor/ui/dialogs/content/EdInsertTable.js
deleted file mode 100644
index fbbad4cc5..000000000
--- a/editor/ui/dialogs/content/EdInsertTable.js
+++ /dev/null
@@ -1,220 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-//Cancel() is in EdDialogCommon.js
-
-var gTableElement = null;
-var gRows;
-var gColumns;
-var gActiveEditor;
-
-// dialog initialization code
-function Startup()
-{
- gActiveEditor = GetCurrentTableEditor();
- if (!gActiveEditor)
- {
- dump("Failed to get active editor!\n");
- window.close();
- return;
- }
-
- try {
- gTableElement = gActiveEditor.createElementWithDefaults("table");
- } catch (e) {}
-
- if(!gTableElement)
- {
- dump("Failed to create a new table!\n");
- window.close();
- return;
- }
- gDialog.rowsInput = document.getElementById("rowsInput");
- gDialog.columnsInput = document.getElementById("columnsInput");
- gDialog.widthInput = document.getElementById("widthInput");
- gDialog.borderInput = document.getElementById("borderInput");
- gDialog.widthPixelOrPercentMenulist = document.getElementById("widthPixelOrPercentMenulist");
- gDialog.OkButton = document.documentElement.getButton("accept");
-
- // Make a copy to use for AdvancedEdit
- globalElement = gTableElement.cloneNode(false);
- try {
- if (Services.prefs.getBoolPref("editor.use_css") && IsHTMLEditor()
- && !(gActiveEditor.flags & Components.interfaces.nsIPlaintextEditor.eEditorMailMask))
- {
- // only for Composer and not for htmlmail
- globalElement.setAttribute("style", "text-align: left;");
- }
- } catch (e) {}
-
- // Initialize all widgets with image attributes
- InitDialog();
-
- // Set initial number to 2 rows, 2 columns:
- // Note, these are not attributes on the table,
- // so don't put them in InitDialog(),
- // else the user's values will be trashed when they use
- // the Advanced Edit dialog
- gDialog.rowsInput.value = 2;
- gDialog.columnsInput.value = 2;
-
- // If no default value on the width, set to 100%
- if (gDialog.widthInput.value.length == 0)
- {
- gDialog.widthInput.value = "100";
- gDialog.widthPixelOrPercentMenulist.selectedIndex = 1;
- }
-
- SetTextboxFocusById("rowsInput");
-
- SetWindowLocation();
-}
-
-// Set dialog widgets with attribute data
-// We get them from globalElement copy so this can be used
-// by AdvancedEdit(), which is shared by all property dialogs
-function InitDialog()
-{
- // Get default attributes set on the created table:
- // Get the width attribute of the element, stripping out "%"
- // This sets contents of menu combobox list
- // 2nd param = null: Use current selection to find if parent is table cell or window
- gDialog.widthInput.value = InitPixelOrPercentMenulist(globalElement, null, "width", "widthPixelOrPercentMenulist", gPercent);
- gDialog.borderInput.value = globalElement.getAttribute("border");
-}
-
-function ChangeRowOrColumn(id)
-{
- // Allow only integers
- forceInteger(id);
-
- // Enable OK only if both rows and columns have a value > 0
- var enable = gDialog.rowsInput.value.length > 0 &&
- gDialog.rowsInput.value > 0 &&
- gDialog.columnsInput.value.length > 0 &&
- gDialog.columnsInput.value > 0;
-
- SetElementEnabled(gDialog.OkButton, enable);
- SetElementEnabledById("AdvancedEditButton1", enable);
-}
-
-
-// Get and validate data from widgets.
-// Set attributes on globalElement so they can be accessed by AdvancedEdit()
-function ValidateData()
-{
- gRows = ValidateNumber(gDialog.rowsInput, null, 1, gMaxRows, null, null, true)
- if (gValidationError)
- return false;
-
- gColumns = ValidateNumber(gDialog.columnsInput, null, 1, gMaxColumns, null, null, true)
- if (gValidationError)
- return false;
-
- // Set attributes: NOTE: These may be empty strings (last param = false)
- ValidateNumber(gDialog.borderInput, null, 0, gMaxPixels, globalElement, "border", false);
- // TODO: Deal with "BORDER" without value issue
- if (gValidationError) return false;
-
- ValidateNumber(gDialog.widthInput, gDialog.widthPixelOrPercentMenulist,
- 1, gMaxTableSize, globalElement, "width", false);
- if (gValidationError)
- return false;
-
- return true;
-}
-
-
-function onAccept()
-{
- if (ValidateData())
- {
- gActiveEditor.beginTransaction();
- try {
- gActiveEditor.cloneAttributes(gTableElement, globalElement);
-
- // Create necessary rows and cells for the table
- var tableBody = gActiveEditor.createElementWithDefaults("tbody");
- if (tableBody)
- {
- gTableElement.appendChild(tableBody);
-
- // Create necessary rows and cells for the table
- for (var i = 0; i < gRows; i++)
- {
- var newRow = gActiveEditor.createElementWithDefaults("tr");
- if (newRow)
- {
- tableBody.appendChild(newRow);
- for (var j = 0; j < gColumns; j++)
- {
- var newCell = gActiveEditor.createElementWithDefaults("td");
- if (newCell)
- {
- newRow.appendChild(newCell);
- }
- }
- }
- }
- }
- // Detect when entire cells are selected:
- // Get number of cells selected
- var tagNameObj = { value: "" };
- var countObj = { value: 0 };
- var element = gActiveEditor.getSelectedOrParentTableElement(tagNameObj, countObj);
- var deletePlaceholder = false;
-
- if (tagNameObj.value == "table")
- {
- //Replace entire selected table with new table, so delete the table
- gActiveEditor.deleteTable();
- }
- else if (tagNameObj.value == "td")
- {
- if (countObj.value >= 1)
- {
- if (countObj.value > 1)
- {
- // Assume user wants to replace a block of
- // contiguous cells with a table, so
- // join the selected cells
- gActiveEditor.joinTableCells(false);
-
- // Get the cell everything was merged into
- element = gActiveEditor.getFirstSelectedCell();
-
- // Collapse selection into just that cell
- gActiveEditor.selection.collapse(element,0);
- }
-
- if (element)
- {
- // Empty just the contents of the cell
- gActiveEditor.deleteTableCellContents();
-
- // Collapse selection to start of empty cell...
- gActiveEditor.selection.collapse(element,0);
- // ...but it will contain a <br> placeholder
- deletePlaceholder = true;
- }
- }
- }
-
- // true means delete selection when inserting
- gActiveEditor.insertElementAtSelection(gTableElement, true);
-
- if (deletePlaceholder && gTableElement && gTableElement.nextSibling)
- {
- // Delete the placeholder <br>
- gActiveEditor.deleteNode(gTableElement.nextSibling);
- }
- } catch (e) {}
-
- gActiveEditor.endTransaction();
-
- SaveWindowLocation();
- return true;
- }
- return false;
-}
diff --git a/editor/ui/dialogs/content/EdInsertTable.xul b/editor/ui/dialogs/content/EdInsertTable.xul
deleted file mode 100644
index a360cd19e..000000000
--- a/editor/ui/dialogs/content/EdInsertTable.xul
+++ /dev/null
@@ -1,72 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorInsertTable.dtd">
-
-<dialog title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload = "Startup()"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdInsertTable.js"/>
-
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
- <broadcaster id="args" value=""/>
- <groupbox><caption label="&size.label;"/>
- <grid>
- <columns>
- <column flex="1"/>
- <column flex="1"/>
- <column flex="6"/>
- </columns>
- <rows>
- <row align="center">
- <label control="rowsInput" class="align-right"
- value="&numRowsEditField.label;"
- accesskey="&numRowsEditField.accessKey;"/>
- <textbox class="narrow" id="rowsInput" oninput="ChangeRowOrColumn(this.id)" />
- <spacer/>
- </row>
- <row align="center">
- <label control="columnsInput" class="align-right"
- value="&numColumnsEditField.label;"
- accesskey="&numColumnsEditField.accessKey;"/>
- <textbox class="narrow" id="columnsInput" oninput="ChangeRowOrColumn(this.id)" />
- <spacer/>
- </row>
- <row align="center">
- <label control="widthInput" class="align-right"
- value="&widthEditField.label;"
- accesskey="&widthEditField.accessKey;"/>
- <textbox class="narrow" id="widthInput" oninput="forceInteger(this.id)" />
- <menulist id="widthPixelOrPercentMenulist" flex="1"/>
- <!-- child elements are appended by JS -->
- </row>
- </rows>
- </grid>
- <spacer class="spacer"/>
- </groupbox>
- <spacer class="spacer"/>
- <hbox align="center">
- <label control="borderInput" class="align-right"
- value="&borderEditField.label;"
- accesskey="&borderEditField.accessKey;"
- tooltiptext="&borderEditField.tooltip;" />
- <textbox class="narrow" id="borderInput" oninput="forceInteger(this.id)" />
- <label value="&pixels.label;"/>
- </hbox>
- <!-- from EdDialogOverlay -->
- <vbox id="AdvancedEdit"/>
-</dialog>
diff --git a/editor/ui/dialogs/content/EdLabelProps.js b/editor/ui/dialogs/content/EdLabelProps.js
deleted file mode 100644
index 98e3eddf8..000000000
--- a/editor/ui/dialogs/content/EdLabelProps.js
+++ /dev/null
@@ -1,108 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var labelElement;
-
-// dialog initialization code
-
-function Startup()
-{
- var editor = GetCurrentEditor();
- if (!editor)
- {
- dump("Failed to get active editor!\n");
- window.close();
- return;
- }
-
- gDialog.editText = document.getElementById("EditText");
- gDialog.labelText = document.getElementById("LabelText");
- gDialog.labelFor = document.getElementById("LabelFor");
- gDialog.labelAccessKey = document.getElementById("LabelAccessKey");
-
- labelElement = window.arguments[0];
-
- // Make a copy to use for AdvancedEdit
- globalElement = labelElement.cloneNode(false);
-
- InitDialog();
-
- var range = editor.document.createRange();
- range.selectNode(labelElement);
- gDialog.labelText.value = range.toString();
-
- if (labelElement.innerHTML.includes("<"))
- {
- gDialog.editText.checked = false;
- gDialog.editText.disabled = false;
- gDialog.labelText.disabled = true;
- gDialog.editText.addEventListener("command",
- () => Services.prompt.alert(window, GetString("Alert"), GetString("EditTextWarning")),
- {capture: false, once: true});
- SetTextboxFocus(gDialog.labelFor);
- }
- else
- SetTextboxFocus(gDialog.labelText);
-
- SetWindowLocation();
-}
-
-function InitDialog()
-{
- gDialog.labelFor.value = globalElement.getAttribute("for");
- gDialog.labelAccessKey.value = globalElement.getAttribute("accesskey");
-}
-
-function RemoveLabel()
-{
- RemoveContainer(labelElement);
- SaveWindowLocation();
- window.close();
-}
-
-function ValidateData()
-{
- if (gDialog.labelFor.value)
- globalElement.setAttribute("for", gDialog.labelFor.value);
- else
- globalElement.removeAttribute("for");
- if (gDialog.labelAccessKey.value)
- globalElement.setAttribute("accesskey", gDialog.labelAccessKey.value);
- else
- globalElement.removeAttribute("accesskey");
- return true;
-}
-
-function onAccept()
-{
- // All values are valid - copy to actual element in doc
- ValidateData();
-
- var editor = GetCurrentEditor();
-
- editor.beginTransaction();
-
- try {
- if (gDialog.editText.checked)
- {
- editor.setShouldTxnSetSelection(false);
-
- while (labelElement.firstChild)
- editor.deleteNode(labelElement.firstChild);
- if (gDialog.labelText.value)
- editor.insertNode(editor.document.createTextNode(gDialog.labelText.value), labelElement, 0);
-
- editor.setShouldTxnSetSelection(true);
- }
-
- editor.cloneAttributes(labelElement, globalElement);
- } catch(e) {}
-
- editor.endTransaction();
-
- SaveWindowLocation();
-
- return true;
-}
-
diff --git a/editor/ui/dialogs/content/EdLabelProps.xul b/editor/ui/dialogs/content/EdLabelProps.xul
deleted file mode 100644
index cb4a6c028..000000000
--- a/editor/ui/dialogs/content/EdLabelProps.xul
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorLabelProperties.dtd">
-<dialog title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="Startup();"
- buttons="accept,cancel"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdLabelProps.js"/>
-
- <broadcaster id="args" value=""/>
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
-
- <groupbox><caption label="&Settings.label;" accesskey="&Settings.accesskey;"/>
- <grid><columns><column/><column/></columns>
- <rows>
- <row align="center">
- <checkbox id="EditText" label="&EditLabelText.label;" accesskey="&EditLabelText.accesskey;" checked="true" disabled="true"
- oncommand="gDialog.labelText.disabled = !gDialog.editText.checked;"/>
- <textbox id="LabelText" accesskey="&Settings.accesskey;"/>
- </row>
- <row align="center">
- <label control="LabelFor" value="&LabelFor.label;" accesskey="&LabelFor.accesskey;"/>
- <textbox id="LabelFor"/>
- </row>
- <row align="center">
- <label control="LabelAccessKey" value="&AccessKey.label;" accesskey="&AccessKey.accesskey;"/>
- <hbox>
- <textbox id="LabelAccessKey" class="narrow"/>
- </hbox>
- </row>
- </rows>
- </grid>
- </groupbox>
-
- <!-- from EdDialogOverlay -->
- <hbox flex="1" style="margin-top: 0.2em">
- <button id="RemoveLabel" label="&RemoveLabel.label;" accesskey="&RemoveLabel.accesskey;" oncommand="RemoveLabel();"/>
- <!-- This will right-align the button -->
- <spacer flex="1"/>
- <button id="AdvancedEditButton"/>
- </hbox>
- <separator class="groove"/>
-
-</dialog>
diff --git a/editor/ui/dialogs/content/EdLinkProps.js b/editor/ui/dialogs/content/EdLinkProps.js
deleted file mode 100644
index 89d188246..000000000
--- a/editor/ui/dialogs/content/EdLinkProps.js
+++ /dev/null
@@ -1,340 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var gActiveEditor;
-var anchorElement = null;
-var imageElement = null;
-var insertNew = false;
-var replaceExistingLink = false;
-var insertLinkAtCaret;
-var needLinkText = false;
-var href;
-var newLinkText;
-var gHNodeArray = {};
-var gHaveNamedAnchors = false;
-var gHaveHeadings = false;
-var gCanChangeHeadingSelected = true;
-var gCanChangeAnchorSelected = true;
-var gHaveDocumentUrl = false;
-
-// NOTE: Use "href" instead of "a" to distinguish from Named Anchor
-// The returned node is has an "a" tagName
-var tagName = "href";
-
-// dialog initialization code
-function Startup()
-{
- gActiveEditor = GetCurrentEditor();
- if (!gActiveEditor)
- {
- dump("Failed to get active editor!\n");
- window.close();
- return;
- }
- // Message was wrapped in a <label> or <div>, so actual text is a child text node
- gDialog.linkTextCaption = document.getElementById("linkTextCaption");
- gDialog.linkTextMessage = document.getElementById("linkTextMessage");
- gDialog.linkTextInput = document.getElementById("linkTextInput");
- gDialog.hrefInput = document.getElementById("hrefInput");
- gDialog.makeRelativeLink = document.getElementById("MakeRelativeLink");
- gDialog.AdvancedEditSection = document.getElementById("AdvancedEdit");
-
- // See if we have a single selected image
- imageElement = gActiveEditor.getSelectedElement("img");
-
- if (imageElement)
- {
- // Get the parent link if it exists -- more efficient than GetSelectedElement()
- anchorElement = gActiveEditor.getElementOrParentByTagName("href", imageElement);
- if (anchorElement)
- {
- if (anchorElement.childNodes.length > 1)
- {
- // If there are other children, then we want to break
- // this image away by inserting a new link around it,
- // so make a new node and copy existing attributes
- anchorElement = anchorElement.cloneNode(false);
- //insertNew = true;
- replaceExistingLink = true;
- }
- }
- }
- else
- {
- // Get an anchor element if caret or
- // entire selection is within the link.
- anchorElement = gActiveEditor.getSelectedElement(tagName);
-
- if (anchorElement)
- {
- // Select the entire link
- gActiveEditor.selectElement(anchorElement);
- }
- else
- {
- // If selection starts in a link, but extends beyond it,
- // the user probably wants to extend existing link to new selection,
- // so check if either end of selection is within a link
- // POTENTIAL PROBLEM: This prevents user from selecting text in an existing
- // link and making 2 links.
- // Note that this isn't a problem with images, handled above
-
- anchorElement = gActiveEditor.getElementOrParentByTagName("href", gActiveEditor.selection.anchorNode);
- if (!anchorElement)
- anchorElement = gActiveEditor.getElementOrParentByTagName("href", gActiveEditor.selection.focusNode);
-
- if (anchorElement)
- {
- // But clone it for reinserting/merging around existing
- // link that only partially overlaps the selection
- anchorElement = anchorElement.cloneNode(false);
- //insertNew = true;
- replaceExistingLink = true;
- }
- }
- }
-
- if(!anchorElement)
- {
- // No existing link -- create a new one
- anchorElement = gActiveEditor.createElementWithDefaults(tagName);
- insertNew = true;
- // Hide message about removing existing link
- //document.getElementById("RemoveLinkMsg").hidden = true;
- }
- if(!anchorElement)
- {
- dump("Failed to get selected element or create a new one!\n");
- window.close();
- return;
- }
-
- // We insert at caret only when nothing is selected
- insertLinkAtCaret = gActiveEditor.selection.isCollapsed;
-
- var selectedText;
- if (insertLinkAtCaret)
- {
- // Groupbox caption:
- gDialog.linkTextCaption.setAttribute("label", GetString("LinkText"));
-
- // Message above input field:
- gDialog.linkTextMessage.setAttribute("value", GetString("EnterLinkText"));
- gDialog.linkTextMessage.setAttribute("accesskey", GetString("EnterLinkTextAccessKey"));
- }
- else
- {
- if (!imageElement)
- {
- // We get here if selection is exactly around a link node
- // Check if selection has some text - use that first
- selectedText = GetSelectionAsText();
- if (!selectedText)
- {
- // No text, look for first image in the selection
- var children = anchorElement.childNodes;
- if (children)
- {
- for(var i=0; i < children.length; i++)
- {
- var nodeName = children.item(i).nodeName.toLowerCase();
- if (nodeName == "img")
- {
- imageElement = children.item(i);
- break;
- }
- }
- }
- }
- }
- // Set "caption" for link source and the source text or image URL
- if (imageElement)
- {
- gDialog.linkTextCaption.setAttribute("label", GetString("LinkImage"));
- // Link source string is the source URL of image
- // TODO: THIS DOESN'T HANDLE MULTIPLE SELECTED IMAGES!
- gDialog.linkTextMessage.setAttribute("value", imageElement.src);
- } else {
- gDialog.linkTextCaption.setAttribute("label", GetString("LinkText"));
- if (selectedText)
- {
- // Use just the first 60 characters and add "..."
- gDialog.linkTextMessage.setAttribute("value", TruncateStringAtWordEnd(ReplaceWhitespace(selectedText, " "), 60, true));
- } else {
- gDialog.linkTextMessage.setAttribute("value", GetString("MixedSelection"));
- }
- }
- }
-
- // Make a copy to use for AdvancedEdit and onSaveDefault
- globalElement = anchorElement.cloneNode(false);
-
- // Get the list of existing named anchors and headings
- FillLinkMenulist(gDialog.hrefInput, gHNodeArray);
-
- // We only need to test for this once per dialog load
- gHaveDocumentUrl = GetDocumentBaseUrl();
-
- // Set data for the dialog controls
- InitDialog();
-
- // Search for a URI pattern in the selected text
- // as candidate href
- selectedText = TrimString(selectedText);
- if (!gDialog.hrefInput.value && TextIsURI(selectedText))
- gDialog.hrefInput.value = selectedText;
-
- // Set initial focus
- if (insertLinkAtCaret) {
- // We will be using the HREF inputbox, so text message
- SetTextboxFocus(gDialog.linkTextInput);
- } else {
- SetTextboxFocus(gDialog.hrefInput);
-
- // We will not insert a new link at caret, so remove link text input field
- gDialog.linkTextInput.hidden = true;
- gDialog.linkTextInput = null;
- }
-
- // This sets enable state on OK button
- doEnabling();
-
- SetWindowLocation();
-}
-
-// Set dialog widgets with attribute data
-// We get them from globalElement copy so this can be used
-// by AdvancedEdit(), which is shared by all property dialogs
-function InitDialog()
-{
- // Must use getAttribute, not "globalElement.href",
- // or foreign chars aren't coverted correctly!
- gDialog.hrefInput.value = globalElement.getAttribute("href");
-
- // Set "Relativize" checkbox according to current URL state
- SetRelativeCheckbox(gDialog.makeRelativeLink);
-}
-
-function doEnabling()
-{
- // We disable Ok button when there's no href text only if inserting a new link
- var enable = insertNew ? (TrimString(gDialog.hrefInput.value).length > 0) : true;
-
- // anon. content, so can't use SetElementEnabledById here
- var dialogNode = document.getElementById("linkDlg");
- dialogNode.getButton("accept").disabled = !enable;
-
- SetElementEnabledById( "AdvancedEditButton1", enable);
-}
-
-function ChangeLinkLocation()
-{
- SetRelativeCheckbox(gDialog.makeRelativeLink);
- // Set OK button enable state
- doEnabling();
-}
-
-// Get and validate data from widgets.
-// Set attributes on globalElement so they can be accessed by AdvancedEdit()
-function ValidateData()
-{
- href = TrimString(gDialog.hrefInput.value);
- if (href)
- {
- // Set the HREF directly on the editor document's anchor node
- // or on the newly-created node if insertNew is true
- globalElement.setAttribute("href",href);
- }
- else if (insertNew)
- {
- // We must have a URL to insert a new link
- //NOTE: We accept an empty HREF on existing link to indicate removing the link
- ShowInputErrorMessage(GetString("EmptyHREFError"));
- return false;
- }
- if (gDialog.linkTextInput)
- {
- // The text we will insert isn't really an attribute,
- // but it makes sense to validate it
- newLinkText = TrimString(gDialog.linkTextInput.value);
- if (!newLinkText)
- {
- if (href)
- newLinkText = href
- else
- {
- ShowInputErrorMessage(GetString("EmptyLinkTextError"));
- SetTextboxFocus(gDialog.linkTextInput);
- return false;
- }
- }
- }
- return true;
-}
-
-function onAccept()
-{
- if (ValidateData())
- {
- if (href.length > 0)
- {
- // Copy attributes to element we are changing or inserting
- gActiveEditor.cloneAttributes(anchorElement, globalElement);
-
- // Coalesce into one undo transaction
- gActiveEditor.beginTransaction();
-
- // Get text to use for a new link
- if (insertLinkAtCaret)
- {
- // Append the link text as the last child node
- // of the anchor node
- var textNode = gActiveEditor.document.createTextNode(newLinkText);
- if (textNode)
- anchorElement.appendChild(textNode);
- try {
- gActiveEditor.insertElementAtSelection(anchorElement, false);
- } catch (e) {
- dump("Exception occured in InsertElementAtSelection\n");
- return true;
- }
- } else if (insertNew || replaceExistingLink)
- {
- // Link source was supplied by the selection,
- // so insert a link node as parent of this
- // (may be text, image, or other inline content)
- try {
- gActiveEditor.insertLinkAroundSelection(anchorElement);
- } catch (e) {
- dump("Exception occured in InsertElementAtSelection\n");
- return true;
- }
- }
- // Check if the link was to a heading
- if (href in gHNodeArray)
- {
- var anchorNode = gActiveEditor.createElementWithDefaults("a");
- if (anchorNode)
- {
- anchorNode.name = href.substr(1);
-
- // Insert the anchor into the document,
- // but don't let the transaction change the selection
- gActiveEditor.setShouldTxnSetSelection(false);
- gActiveEditor.insertNode(anchorNode, gHNodeArray[href], 0);
- gActiveEditor.setShouldTxnSetSelection(true);
- }
- }
- gActiveEditor.endTransaction();
- }
- else if (!insertNew)
- {
- // We already had a link, but empty HREF means remove it
- EditorRemoveTextProperty("href", "");
- }
- SaveWindowLocation();
- return true;
- }
- return false;
-}
diff --git a/editor/ui/dialogs/content/EdLinkProps.xul b/editor/ui/dialogs/content/EdLinkProps.xul
deleted file mode 100644
index 82c0210d6..000000000
--- a/editor/ui/dialogs/content/EdLinkProps.xul
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorLinkProperties.dtd">
-
-<dialog id="linkDlg" title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload = "Startup()"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdLinkProps.js"/>
-
- <broadcaster id="args" value=""/>
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
-
- <vbox style="min-width: 20em">
- <groupbox><caption id="linkTextCaption"/>
- <vbox>
- <label id="linkTextMessage" control="linkTextInput"/>
- <textbox id="linkTextInput"/>
- </vbox>
- </groupbox>
-
- <groupbox id="LinkURLBox"><caption label="&LinkURLBox.label;"/>
- <vbox id="LinkLocationBox"/>
- <!-- mail compose will insert custom item here defined in mailComposeEditorOverlay.xul -->
- </groupbox>
- </vbox>
- <!-- from EdDialogOverlay -->
- <vbox id="AdvancedEdit"/>
-</dialog>
diff --git a/editor/ui/dialogs/content/EdListProps.js b/editor/ui/dialogs/content/EdListProps.js
deleted file mode 100644
index e886e72ed..000000000
--- a/editor/ui/dialogs/content/EdListProps.js
+++ /dev/null
@@ -1,441 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-//Cancel() is in EdDialogCommon.js
-var gBulletStyleType = "";
-var gNumberStyleType = "";
-var gListElement;
-var gOriginalListType = "";
-var gListType = "";
-var gMixedListSelection = false;
-var gStyleType = "";
-var gOriginalStyleType = "";
-const gOnesArray = ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"];
-const gTensArray = ["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"];
-const gHundredsArray = ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"];
-const gThousandsArray = ["", "M", "MM", "MMM", "MMMM", "MMMMM", "MMMMMM", "MMMMMMM", "MMMMMMMM", "MMMMMMMMM"];
-const gRomanDigits = {I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000};
-const A = "A".charCodeAt(0);
-const gArabic = "1";
-const gUpperRoman = "I";
-const gLowerRoman = "i";
-const gUpperLetters = "A";
-const gLowerLetters = "a";
-const gDecimalCSS = "decimal";
-const gUpperRomanCSS = "upper-roman";
-const gLowerRomanCSS = "lower-roman";
-const gUpperAlphaCSS = "upper-alpha";
-const gLowerAlphaCSS = "lower-alpha";
-
-// dialog initialization code
-function Startup()
-{
- var editor = GetCurrentEditor();
- if (!editor)
- {
- window.close();
- return;
- }
- gDialog.ListTypeList = document.getElementById("ListType");
- gDialog.BulletStyleList = document.getElementById("BulletStyle");
- gDialog.BulletStyleLabel = document.getElementById("BulletStyleLabel");
- gDialog.StartingNumberInput = document.getElementById("StartingNumber");
- gDialog.StartingNumberLabel = document.getElementById("StartingNumberLabel");
- gDialog.AdvancedEditButton = document.getElementById("AdvancedEditButton1");
- gDialog.RadioGroup = document.getElementById("RadioGroup");
- gDialog.ChangeAllRadio = document.getElementById("ChangeAll");
- gDialog.ChangeSelectedRadio = document.getElementById("ChangeSelected");
-
- // Try to get an existing list(s)
- var mixedObj = { value: null };
- try {
- gListType = editor.getListState(mixedObj, {}, {}, {} );
-
- // We may have mixed list and non-list, or > 1 list type in selection
- gMixedListSelection = mixedObj.value;
-
- // Get the list element at the anchor node
- gListElement = editor.getElementOrParentByTagName("list", null);
- } catch (e) {}
-
- // The copy to use in AdvancedEdit
- if (gListElement)
- globalElement = gListElement.cloneNode(false);
-
- // Show extra options for changing entire list if we have one already.
- gDialog.RadioGroup.collapsed = !gListElement;
- if (gListElement)
- {
- // Radio button index is persistent
- if (gDialog.RadioGroup.getAttribute("index") == "1")
- gDialog.RadioGroup.selectedItem = gDialog.ChangeSelectedRadio;
- else
- gDialog.RadioGroup.selectedItem = gDialog.ChangeAllRadio;
- }
-
- InitDialog();
-
- gOriginalListType = gListType;
-
- gDialog.ListTypeList.focus();
-
- SetWindowLocation();
-}
-
-function InitDialog()
-{
- // Note that if mixed, we we pay attention
- // only to the anchor node's list type
- // (i.e., don't confuse user with "mixed" designation)
- if (gListElement)
- gListType = gListElement.nodeName.toLowerCase();
- else
- gListType = "";
-
- gDialog.ListTypeList.value = gListType;
- gDialog.StartingNumberInput.value = "";
-
- // Last param = true means attribute value is case-sensitive
- var type = globalElement ? GetHTMLOrCSSStyleValue(globalElement, "type", "list-style-type") : null;
-
- var index = 0;
- if (gListType == "ul")
- {
- if (type)
- {
- type = type.toLowerCase();
- gBulletStyleType = type;
- gOriginalStyleType = type;
- }
- }
- else if (gListType == "ol")
- {
- // Translate CSS property strings
- switch (type.toLowerCase())
- {
- case gDecimalCSS:
- type = gArabic;
- break;
- case gUpperRomanCSS:
- type = gUpperRoman;
- break;
- case gLowerRomanCSS:
- type = gLowerRoman;
- break;
- case gUpperAlphaCSS:
- type = gUpperLetters;
- break;
- case gLowerAlphaCSS:
- type = gLowerLetters;
- break;
- }
- if (type)
- {
- gNumberStyleType = type;
- gOriginalStyleType = type;
- }
-
- // Convert attribute number to appropriate letter or roman numeral
- gDialog.StartingNumberInput.value =
- ConvertStartAttrToUserString(globalElement.getAttribute("start"), type);
- }
- BuildBulletStyleList();
-}
-
-// Convert attribute number to appropriate letter or roman numeral
-function ConvertStartAttrToUserString(startAttr, type)
-{
- switch (type)
- {
- case gUpperRoman:
- startAttr = ConvertArabicToRoman(startAttr);
- break;
- case gLowerRoman:
- startAttr = ConvertArabicToRoman(startAttr).toLowerCase();
- break;
- case gUpperLetters:
- startAttr = ConvertArabicToLetters(startAttr);
- break;
- case gLowerLetters:
- startAttr = ConvertArabicToLetters(startAttr).toLowerCase();
- break;
- }
- return startAttr;
-}
-
-function BuildBulletStyleList()
-{
- gDialog.BulletStyleList.removeAllItems();
- var label;
-
- if (gListType == "ul")
- {
- gDialog.BulletStyleList.removeAttribute("disabled");
- gDialog.BulletStyleLabel.removeAttribute("disabled");
- gDialog.StartingNumberInput.setAttribute("disabled", "true");
- gDialog.StartingNumberLabel.setAttribute("disabled", "true");
-
- label = GetString("BulletStyle");
-
- gDialog.BulletStyleList.appendItem(GetString("Automatic"), "");
- gDialog.BulletStyleList.appendItem(GetString("SolidCircle"), "disc");
- gDialog.BulletStyleList.appendItem(GetString("OpenCircle"), "circle");
- gDialog.BulletStyleList.appendItem(GetString("SolidSquare"), "square");
-
- gDialog.BulletStyleList.value = gBulletStyleType;
- }
- else if (gListType == "ol")
- {
- gDialog.BulletStyleList.removeAttribute("disabled");
- gDialog.BulletStyleLabel.removeAttribute("disabled");
- gDialog.StartingNumberInput.removeAttribute("disabled");
- gDialog.StartingNumberLabel.removeAttribute("disabled");
- label = GetString("NumberStyle");
-
- gDialog.BulletStyleList.appendItem(GetString("Automatic"), "");
- gDialog.BulletStyleList.appendItem(GetString("Style_1"), gArabic);
- gDialog.BulletStyleList.appendItem(GetString("Style_I"), gUpperRoman);
- gDialog.BulletStyleList.appendItem(GetString("Style_i"), gLowerRoman);
- gDialog.BulletStyleList.appendItem(GetString("Style_A"), gUpperLetters);
- gDialog.BulletStyleList.appendItem(GetString("Style_a"), gLowerLetters);
-
- gDialog.BulletStyleList.value = gNumberStyleType;
- }
- else
- {
- gDialog.BulletStyleList.setAttribute("disabled", "true");
- gDialog.BulletStyleLabel.setAttribute("disabled", "true");
- gDialog.StartingNumberInput.setAttribute("disabled", "true");
- gDialog.StartingNumberLabel.setAttribute("disabled", "true");
- }
-
- // Disable advanced edit button if changing to "normal"
- if (gListType)
- gDialog.AdvancedEditButton.removeAttribute("disabled");
- else
- gDialog.AdvancedEditButton.setAttribute("disabled", "true");
-
- if (label)
- gDialog.BulletStyleLabel.setAttribute("label",label);
-}
-
-function SelectListType()
-{
- // Each list type is stored in the "value" of each menuitem
- var NewType = gDialog.ListTypeList.value;
-
- if (NewType == "ol")
- SetTextboxFocus(gDialog.StartingNumberInput);
-
- if (gListType != NewType)
- {
- gListType = NewType;
-
- // Create a newlist object for Advanced Editing
- try {
- if (gListType)
- globalElement = GetCurrentEditor().createElementWithDefaults(gListType);
- } catch (e) {}
-
- BuildBulletStyleList();
- }
-}
-
-function SelectBulletStyle()
-{
- // Save the selected index so when user changes
- // list style, restore index to associated list
- // Each bullet or number type is stored in the "value" of each menuitem
- if (gListType == "ul")
- gBulletStyleType = gDialog.BulletStyleList.value;
- else if (gListType == "ol")
- {
- var type = gDialog.BulletStyleList.value;
- if (gNumberStyleType != type)
- {
- // Convert existing input value to attr number first,
- // then convert to the appropriate format for the newly-selected
- gDialog.StartingNumberInput.value =
- ConvertStartAttrToUserString( ConvertUserStringToStartAttr(gNumberStyleType), type);
-
- gNumberStyleType = type;
- SetTextboxFocus(gDialog.StartingNumberInput);
- }
- }
-}
-
-function ValidateData()
-{
- gBulletStyleType = gDialog.BulletStyleList.value;
- // globalElement should already be of the correct type
-
- if (globalElement)
- {
- var editor = GetCurrentEditor();
- if (gListType == "ul")
- {
- if (gBulletStyleType && gDialog.ChangeAllRadio.selected)
- globalElement.setAttribute("type", gBulletStyleType);
- else
- try {
- editor.removeAttributeOrEquivalent(globalElement, "type", true);
- } catch (e) {}
-
- }
- else if (gListType == "ol")
- {
- if (gBulletStyleType)
- globalElement.setAttribute("type", gBulletStyleType);
- else
- try {
- editor.removeAttributeOrEquivalent(globalElement, "type", true);
- } catch (e) {}
-
- var startingNumber = ConvertUserStringToStartAttr(gBulletStyleType);
- if (startingNumber)
- globalElement.setAttribute("start", startingNumber);
- else
- globalElement.removeAttribute("start");
- }
- }
- return true;
-}
-
-function ConvertUserStringToStartAttr(type)
-{
- var startingNumber = TrimString(gDialog.StartingNumberInput.value);
-
- switch (type)
- {
- case gUpperRoman:
- case gLowerRoman:
- // If the input isn't an integer, assume it's a roman numeral. Convert it.
- if (!Number(startingNumber))
- startingNumber = ConvertRomanToArabic(startingNumber);
- break;
- case gUpperLetters:
- case gLowerLetters:
- // Get the number equivalent of the letters
- if (!Number(startingNumber))
- startingNumber = ConvertLettersToArabic(startingNumber);
- break;
- }
- return startingNumber;
-}
-
-function ConvertRomanToArabic(num)
-{
- num = num.toUpperCase();
- if (num && !/[^MDCLXVI]/i.test(num))
- {
- var Arabic = 0;
- var last_digit = 1000;
- for (var i=0; i < num.length; i++)
- {
- var digit = gRomanDigits[num.charAt(i)];
- if (last_digit < digit)
- Arabic -= 2 * last_digit;
-
- last_digit = digit;
- Arabic += last_digit;
- }
- return Arabic;
- }
-
- return "";
-}
-
-function ConvertArabicToRoman(num)
-{
- if (/^\d{1,4}$/.test(num))
- {
- var digits = ("000" + num).substr(-4);
- return gThousandsArray[digits.charAt(0)] +
- gHundredsArray[digits.charAt(1)] +
- gTensArray[digits.charAt(2)] +
- gOnesArray[digits.charAt(3)];
- }
- return "";
-}
-
-function ConvertLettersToArabic(letters)
-{
- letters = letters.toUpperCase();
- if (!letters || /[^A-Z]/.test(letters))
- return "";
-
- var num = 0;
- for (var i = 0; i < letters.length; i++)
- num = num * 26 + letters.charCodeAt(i) - A + 1;
- return num;
-}
-
-function ConvertArabicToLetters(num)
-{
- var letters = "";
- while (num) {
- num--;
- letters = String.fromCharCode(A + (num % 26)) + letters;
- num = Math.floor(num / 26);
- }
- return letters;
-}
-
-function onAccept()
-{
- if (ValidateData())
- {
- // Coalesce into one undo transaction
- var editor = GetCurrentEditor();
-
- editor.beginTransaction();
-
- var changeEntireList = gDialog.RadioGroup.selectedItem == gDialog.ChangeAllRadio;
-
- // Remember which radio button was selected
- if (gListElement)
- gDialog.RadioGroup.setAttribute("index", changeEntireList ? "0" : "1");
-
- var changeList;
- if (gListElement && gDialog.ChangeAllRadio.selected)
- {
- changeList = true;
- }
- else
- changeList = gMixedListSelection || gListType != gOriginalListType ||
- gBulletStyleType != gOriginalStyleType;
- if (changeList)
- {
- try {
- if (gListType)
- {
- editor.makeOrChangeList(gListType, changeEntireList,
- (gBulletStyleType != gOriginalStyleType) ? gBulletStyleType : null);
-
- // Get the new list created:
- gListElement = editor.getElementOrParentByTagName(gListType, null);
-
- editor.cloneAttributes(gListElement, globalElement);
- }
- else
- {
- // Remove all existing lists
- if (gListElement && changeEntireList)
- editor.selectElement(gListElement);
-
- editor.removeList("ol");
- editor.removeList("ul");
- editor.removeList("dl");
- }
- } catch (e) {}
- }
-
- editor.endTransaction();
-
- SaveWindowLocation();
-
- return true;
- }
- return false;
-}
diff --git a/editor/ui/dialogs/content/EdListProps.xul b/editor/ui/dialogs/content/EdListProps.xul
deleted file mode 100644
index 308b1d8a5..000000000
--- a/editor/ui/dialogs/content/EdListProps.xul
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorListProperties.dtd">
-<dialog title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload = "Startup()"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdListProps.js"/>
-
- <broadcaster id="args" value=""/>
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
-
- <groupbox flex="1"><caption label="&ListType.label;"/>
- <menulist id="ListType" oncommand="SelectListType()">
- <menupopup>
- <menuitem label="&none.value;"/>
- <menuitem value="ul" label="&bulletList.value;"/>
- <menuitem value="ol" label="&numberList.value;"/>
- <menuitem value="dl" label="&definitionList.value;"/>
- </menupopup>
- </menulist>
- </groupbox>
- <spacer class="spacer"/>
-
- <!-- message text and list items are set in JS
- text value should be identical to string with id=BulletStyle in editor.properties
- -->
- <groupbox flex="1"><caption id="BulletStyleLabel" label="&bulletStyle.label;"/>
- <menulist class="MinWidth10em" id="BulletStyle" oncommand="SelectBulletStyle()">
- <menupopup/>
- </menulist>
- <spacer class="spacer"/>
- <hbox>
- <label id="StartingNumberLabel" control="StartingNumber"
- value="&startingNumber.label;" accesskey="&startingNumber.accessKey;"/>
- <textbox class="narrow" id="StartingNumber"/>
- <spacer/>
- </hbox>
- </groupbox>
- <radiogroup id="RadioGroup" index="0" persist="index">
- <radio id="ChangeAll" label="&changeEntireListRadio.label;" accesskey="&changeEntireListRadio.accessKey;"/>
- <radio id="ChangeSelected" label="&changeSelectedRadio.label;" accesskey="&changeSelectedRadio.accessKey;"/>
- </radiogroup>
- <!-- from EdDialogOverlay -->
- <vbox id="AdvancedEdit"/>
-</dialog>
diff --git a/editor/ui/dialogs/content/EdNamedAnchorProps.js b/editor/ui/dialogs/content/EdNamedAnchorProps.js
deleted file mode 100644
index 8ded1e94a..000000000
--- a/editor/ui/dialogs/content/EdNamedAnchorProps.js
+++ /dev/null
@@ -1,164 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var gInsertNew = true;
-var gAnchorElement = null;
-var gOriginalName = "";
-const kTagName = "anchor";
-
-// dialog initialization code
-function Startup()
-{
- var editor = GetCurrentEditor();
- if (!editor)
- {
- window.close();
- return;
- }
-
- gDialog.OkButton = document.documentElement.getButton("accept");
- gDialog.NameInput = document.getElementById("nameInput");
-
- // Get a single selected element of the desired type
- gAnchorElement = editor.getSelectedElement(kTagName);
-
- if (gAnchorElement) {
- // We found an element and don't need to insert one
- gInsertNew = false;
-
- // Make a copy to use for AdvancedEdit
- globalElement = gAnchorElement.cloneNode(false);
- gOriginalName = ConvertToCDATAString(gAnchorElement.name);
- } else {
- gInsertNew = true;
- // We don't have an element selected,
- // so create one with default attributes
- gAnchorElement = editor.createElementWithDefaults(kTagName);
- if (gAnchorElement) {
- // Use the current selection as suggested name
- var name = GetSelectionAsText();
- // Get 40 characters of the selected text and don't add "...",
- // replace whitespace with "_" and strip non-word characters
- name = ConvertToCDATAString(TruncateStringAtWordEnd(name, 40, false));
- //Be sure the name is unique to the document
- if (AnchorNameExists(name))
- name += "_"
-
- // Make a copy to use for AdvancedEdit
- globalElement = gAnchorElement.cloneNode(false);
- globalElement.setAttribute("name",name);
- }
- }
- if(!gAnchorElement)
- {
- dump("Failed to get selected element or create a new one!\n");
- window.close();
- return;
- }
-
- InitDialog();
-
- DoEnabling();
- SetTextboxFocus(gDialog.NameInput);
- SetWindowLocation();
-}
-
-function InitDialog()
-{
- gDialog.NameInput.value = globalElement.getAttribute("name");
-}
-
-function ChangeName()
-{
- if (gDialog.NameInput.value.length > 0)
- {
- // Replace spaces with "_" and strip other non-URL characters
- // Note: we could use ConvertAndEscape, but then we'd
- // have to UnEscapeAndConvert beforehand - too messy!
- gDialog.NameInput.value = ConvertToCDATAString(gDialog.NameInput.value);
- }
- DoEnabling();
-}
-
-function DoEnabling()
-{
- var enable = gDialog.NameInput.value.length > 0;
- SetElementEnabled(gDialog.OkButton, enable);
- SetElementEnabledById("AdvancedEditButton1", enable);
-}
-
-function AnchorNameExists(name)
-{
- var anchorList;
- try {
- anchorList = GetCurrentEditor().document.anchors;
- } catch (e) {}
-
- if (anchorList) {
- for (var i = 0; i < anchorList.length; i++) {
- if (anchorList[i].name == name)
- return true;
- }
- }
- return false;
-}
-
-// Get and validate data from widgets.
-// Set attributes on globalElement so they can be accessed by AdvancedEdit()
-function ValidateData()
-{
- var name = TrimString(gDialog.NameInput.value);
- if (!name)
- {
- ShowInputErrorMessage(GetString("MissingAnchorNameError"));
- SetTextboxFocus(gDialog.NameInput);
- return false;
- } else {
- // Replace spaces with "_" and strip other characters
- // Note: we could use ConvertAndEscape, but then we'd
- // have to UnConverAndEscape beforehand - too messy!
- name = ConvertToCDATAString(name);
-
- if (gOriginalName != name && AnchorNameExists(name))
- {
- ShowInputErrorMessage(GetString("DuplicateAnchorNameError").replace(/%name%/,name));
- SetTextboxFocus(gDialog.NameInput);
- return false;
- }
- globalElement.name = name;
- }
- return true;
-}
-
-function onAccept()
-{
- if (ValidateData())
- {
- if (gOriginalName != globalElement.name)
- {
- var editor = GetCurrentEditor();
- editor.beginTransaction();
-
- try {
- // "false" = don't delete selected text when inserting
- if (gInsertNew)
- {
- // We must insert element before copying CSS style attribute,
- // but we must set the name else it won't insert at all
- gAnchorElement.name = globalElement.name;
- editor.insertElementAtSelection(gAnchorElement, false);
- }
-
- // Copy attributes to element we are changing or inserting
- editor.cloneAttributes(gAnchorElement, globalElement);
-
- } catch (e) {}
-
- editor.endTransaction();
- }
- SaveWindowLocation();
- return true;
- }
- return false;
-}
diff --git a/editor/ui/dialogs/content/EdNamedAnchorProps.xul b/editor/ui/dialogs/content/EdNamedAnchorProps.xul
deleted file mode 100644
index e2685d21e..000000000
--- a/editor/ui/dialogs/content/EdNamedAnchorProps.xul
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EdNamedAnchorProperties.dtd">
-
-<dialog title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload = "Startup()"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdNamedAnchorProps.js"/>
-
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
-
- <label control="nameInput"
- value="&anchorNameEditField.label;"
- accesskey="&anchorNameEditField.accessKey;"/>
- <textbox class="MinWidth20em" id="nameInput" oninput="ChangeName()"
- tooltiptext="&nameInput.tooltip;"/>
- <spacer class="spacer"/>
- <!-- from EdDialogOverlay -->
- <vbox id="AdvancedEdit"/>
-</dialog>
diff --git a/editor/ui/dialogs/content/EdPageProps.js b/editor/ui/dialogs/content/EdPageProps.js
deleted file mode 100644
index 8a129b685..000000000
--- a/editor/ui/dialogs/content/EdPageProps.js
+++ /dev/null
@@ -1,166 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var gNewTitle = "";
-var gAuthor = "";
-var gDescription = "";
-var gAuthorElement;
-var gDescriptionElement;
-var gInsertNewAuthor = false;
-var gInsertNewDescription = false;
-var gTitleWasEdited = false;
-var gAuthorWasEdited = false;
-var gDescWasEdited = false;
-
-//Cancel() is in EdDialogCommon.js
-// dialog initialization code
-function Startup()
-{
- var editor = GetCurrentEditor();
- if (!editor)
- {
- window.close();
- return;
- }
-
- gDialog.PageLocation = document.getElementById("PageLocation");
- gDialog.PageModDate = document.getElementById("PageModDate");
- gDialog.TitleInput = document.getElementById("TitleInput");
- gDialog.AuthorInput = document.getElementById("AuthorInput");
- gDialog.DescriptionInput = document.getElementById("DescriptionInput");
-
- // Default string for new page is set from DTD string in XUL,
- // so set only if not new doc URL
- var location = GetDocumentUrl();
- var lastmodString = GetString("Unknown");
-
- if (!IsUrlAboutBlank(location))
- {
- // NEVER show username and password in clear text
- gDialog.PageLocation.setAttribute("value", StripPassword(location));
-
- // Get last-modified file date+time
- // TODO: Convert this to local time?
- var lastmod;
- try {
- lastmod = editor.document.lastModified; // get string of last modified date
- } catch (e) {}
- // Convert modified string to date (0 = unknown date or January 1, 1970 GMT)
- if(Date.parse(lastmod))
- {
- try {
- const nsScriptableDateFormat_CONTRACTID = "@mozilla.org/intl/scriptabledateformat;1";
- const nsIScriptableDateFormat = Components.interfaces.nsIScriptableDateFormat;
- var dateService = Components.classes[nsScriptableDateFormat_CONTRACTID]
- .getService(nsIScriptableDateFormat);
-
- var lastModDate = new Date();
- lastModDate.setTime(Date.parse(lastmod));
- lastmodString = dateService.FormatDateTime("",
- dateService.dateFormatLong,
- dateService.timeFormatSeconds,
- lastModDate.getFullYear(),
- lastModDate.getMonth()+1,
- lastModDate.getDate(),
- lastModDate.getHours(),
- lastModDate.getMinutes(),
- lastModDate.getSeconds());
- } catch (e) {}
- }
- }
- gDialog.PageModDate.value = lastmodString;
-
- gAuthorElement = GetMetaElementByAttribute("name", "author");
- if (!gAuthorElement)
- {
- gAuthorElement = CreateMetaElementWithAttribute("name", "author");
- if (!gAuthorElement)
- {
- window.close();
- return;
- }
- gInsertNewAuthor = true;
- }
-
- gDescriptionElement = GetMetaElementByAttribute("name", "description");
- if (!gDescriptionElement)
- {
- gDescriptionElement = CreateMetaElementWithAttribute("name", "description");
- if (!gDescriptionElement)
- window.close();
-
- gInsertNewDescription = true;
- }
-
- InitDialog();
-
- SetTextboxFocus(gDialog.TitleInput);
-
- SetWindowLocation();
-}
-
-function InitDialog()
-{
- gDialog.TitleInput.value = GetDocumentTitle();
-
- var gAuthor = TrimString(gAuthorElement.getAttribute("content"));
- if (!gAuthor)
- {
- // Fill in with value from editor prefs
- gAuthor = Services.prefs.getCharPref("editor.author");
- }
- gDialog.AuthorInput.value = gAuthor;
- gDialog.DescriptionInput.value = gDescriptionElement.getAttribute("content");
-}
-
-function TextboxChanged(ID)
-{
- switch(ID)
- {
- case "TitleInput":
- gTitleWasEdited = true;
- break;
- case "AuthorInput":
- gAuthorWasEdited = true;
- break;
- case "DescriptionInput":
- gDescWasEdited = true;
- break;
- }
-}
-
-function ValidateData()
-{
- gNewTitle = TrimString(gDialog.TitleInput.value);
- gAuthor = TrimString(gDialog.AuthorInput.value);
- gDescription = TrimString(gDialog.DescriptionInput.value);
- return true;
-}
-
-function onAccept()
-{
- if (ValidateData())
- {
- var editor = GetCurrentEditor();
- editor.beginTransaction();
-
- // Set title contents even if string is empty
- // because TITLE is a required HTML element
- if (gTitleWasEdited)
- SetDocumentTitle(gNewTitle);
-
- if (gAuthorWasEdited)
- SetMetaElementContent(gAuthorElement, gAuthor, gInsertNewAuthor, false);
-
- if (gDescWasEdited)
- SetMetaElementContent(gDescriptionElement, gDescription, gInsertNewDescription, false);
-
- editor.endTransaction();
-
- SaveWindowLocation();
- return true; // do close the window
- }
- return false;
-}
-
diff --git a/editor/ui/dialogs/content/EdPageProps.xul b/editor/ui/dialogs/content/EdPageProps.xul
deleted file mode 100644
index e5d666f83..000000000
--- a/editor/ui/dialogs/content/EdPageProps.xul
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorPageProperties.dtd">
-
-<dialog title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="Startup();"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdPageProps.js"/>
-
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
- <broadcaster id="args" value=""/>
- <grid>
- <columns><column flex="1"/><column flex="2"/></columns>
- <rows>
- <row>
- <label value="&location.label;"/>
- <label value="&locationNewPage.label;" id="PageLocation"/>
- </row>
- <row>
- <label value="&lastModified.label;"/>
- <label id="PageModDate"/>
- </row>
- <spacer class="spacer"/>
- <row align="center">
- <label value="&titleInput.label;" accesskey="&titleInput.accessKey;" control="TitleInput"/>
- <textbox class="MinWidth20em" id="TitleInput" oninput="TextboxChanged(this.id)"/>
- </row>
- <row align="center">
- <label value="&authorInput.label;" accesskey="&authorInput.accessKey;" control="AuthorInput"/>
- <textbox class="MinWidth20em" id="AuthorInput" oninput="TextboxChanged(this.id)"/>
- </row>
- <row align="center">
- <label value="&descriptionInput.label;" accesskey="&descriptionInput.accessKey;" control="DescriptionInput"/>
- <textbox class="MinWidth20em" id="DescriptionInput" oninput="TextboxChanged(this.id)"/>
- </row>
- </rows>
- </grid>
- <spacer class="bigspacer"/>
- <label value="&EditHEADSource1.label;"/>
- <description class="wrap" flex="1">&EditHEADSource2.label;</description>
- <separator class="groove"/>
-</dialog>
diff --git a/editor/ui/dialogs/content/EdReplace.js b/editor/ui/dialogs/content/EdReplace.js
deleted file mode 100644
index ee7b0d281..000000000
--- a/editor/ui/dialogs/content/EdReplace.js
+++ /dev/null
@@ -1,380 +0,0 @@
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var gReplaceDialog; // Quick access to document/form elements.
-var gFindInst; // nsIWebBrowserFind that we're going to use
-var gFindService; // Global service which remembers find params
-var gEditor; // the editor we're using
-
-function initDialogObject()
-{
- // Create gReplaceDialog object and initialize.
- gReplaceDialog = {};
- gReplaceDialog.findInput = document.getElementById("dialog.findInput");
- gReplaceDialog.replaceInput = document.getElementById("dialog.replaceInput");
- gReplaceDialog.caseSensitive = document.getElementById("dialog.caseSensitive");
- gReplaceDialog.wrap = document.getElementById("dialog.wrap");
- gReplaceDialog.searchBackwards = document.getElementById("dialog.searchBackwards");
- gReplaceDialog.findNext = document.getElementById("findNext");
- gReplaceDialog.replace = document.getElementById("replace");
- gReplaceDialog.replaceAndFind = document.getElementById("replaceAndFind");
- gReplaceDialog.replaceAll = document.getElementById("replaceAll");
-}
-
-function loadDialog()
-{
- // Set initial dialog field contents.
- // Set initial dialog field contents. Use the gFindInst attributes first,
- // this is necessary for window.find()
- gReplaceDialog.findInput.value = (gFindInst.searchString
- ? gFindInst.searchString
- : gFindService.searchString);
- gReplaceDialog.replaceInput.value = gFindService.replaceString;
- gReplaceDialog.caseSensitive.checked = (gFindInst.matchCase
- ? gFindInst.matchCase
- : gFindService.matchCase);
- gReplaceDialog.wrap.checked = (gFindInst.wrapFind
- ? gFindInst.wrapFind
- : gFindService.wrapFind);
- gReplaceDialog.searchBackwards.checked = (gFindInst.findBackwards
- ? gFindInst.findBackwards
- : gFindService.findBackwards);
-
- doEnabling();
-}
-
-function onLoad()
-{
- // Get the xul <editor> element:
- var editorElement = window.arguments[0];
-
- // If we don't get the editor, then we won't allow replacing.
- gEditor = editorElement.getEditor(editorElement.contentWindow);
- if (!gEditor)
- {
- window.close();
- return;
- }
-
- // Get the nsIWebBrowserFind service:
- gFindInst = editorElement.webBrowserFind;
-
- try {
- // get the find service, which stores global find state
- gFindService = Components.classes["@mozilla.org/find/find_service;1"]
- .getService(Components.interfaces.nsIFindService);
- } catch(e) { dump("No find service!\n"); gFindService = 0; }
-
- // Init gReplaceDialog.
- initDialogObject();
-
- // Change "OK" to "Find".
- //dialog.find.label = document.getElementById("fBLT").getAttribute("label");
-
- // Fill dialog.
- loadDialog();
-
- if (gReplaceDialog.findInput.value)
- gReplaceDialog.findInput.select();
- else
- gReplaceDialog.findInput.focus();
-}
-
-function onUnload() {
- // Disconnect context from this dialog.
- gFindReplaceData.replaceDialog = null;
-}
-
-function saveFindData()
-{
- // Set data attributes per user input.
- if (gFindService)
- {
- gFindService.searchString = gReplaceDialog.findInput.value;
- gFindService.matchCase = gReplaceDialog.caseSensitive.checked;
- gFindService.wrapFind = gReplaceDialog.wrap.checked;
- gFindService.findBackwards = gReplaceDialog.searchBackwards.checked;
- }
-}
-
-function setUpFindInst()
-{
- gFindInst.searchString = gReplaceDialog.findInput.value;
- gFindInst.matchCase = gReplaceDialog.caseSensitive.checked;
- gFindInst.wrapFind = gReplaceDialog.wrap.checked;
- gFindInst.findBackwards = gReplaceDialog.searchBackwards.checked;
-}
-
-function onFindNext()
-{
- // Transfer dialog contents to the find service.
- saveFindData();
- // set up the find instance
- setUpFindInst();
-
- // Search.
- var result = gFindInst.findNext();
-
- if (!result)
- {
- var bundle = document.getElementById("findBundle");
- Services.prompt.alert(window, GetString("Alert"), bundle.getString("notFoundWarning"));
- SetTextboxFocus(gReplaceDialog.findInput);
- gReplaceDialog.findInput.select();
- gReplaceDialog.findInput.focus();
- return false;
- }
- return true;
-}
-
-function onReplace()
-{
- if (!gEditor)
- return false;
-
- // Does the current selection match the find string?
- var selection = gEditor.selection;
-
- var selStr = selection.toString();
- var specStr = gReplaceDialog.findInput.value;
- if (!gReplaceDialog.caseSensitive.checked)
- {
- selStr = selStr.toLowerCase();
- specStr = specStr.toLowerCase();
- }
- // Unfortunately, because of whitespace we can't just check
- // whether (selStr == specStr), but have to loop ourselves.
- // N chars of whitespace in specStr can match any M >= N in selStr.
- var matches = true;
- var specLen = specStr.length;
- var selLen = selStr.length;
- if (selLen < specLen)
- matches = false;
- else
- {
- var specArray = specStr.match(/\S+|\s+/g);
- var selArray = selStr.match(/\S+|\s+/g);
- if ( specArray.length != selArray.length)
- matches = false;
- else
- {
- for (var i=0; i<selArray.length; i++)
- {
- if (selArray[i] != specArray[i])
- {
- if ( /\S/.test(selArray[i][0]) || /\S/.test(specArray[i][0]) )
- {
- // not a space chunk -- match fails
- matches = false;
- break;
- }
- else if ( selArray[i].length < specArray[i].length )
- {
- // if it's a space chunk then we only care that sel be
- // at least as long as spec
- matches = false;
- break;
- }
- }
- }
- }
- }
-
- // If the current selection doesn't match the pattern,
- // then we want to find the next match, but not do the replace.
- // That's what most other apps seem to do.
- // So here, just return.
- if (!matches)
- return false;
-
- // Transfer dialog contents to the find service.
- saveFindData();
-
- // For reverse finds, need to remember the caret position
- // before current selection
- var newRange;
- if (gReplaceDialog.searchBackwards.checked && selection.rangeCount > 0)
- {
- newRange = selection.getRangeAt(0).cloneRange();
- newRange.collapse(true);
- }
-
- // nsPlaintextEditor::InsertText fails if the string is empty,
- // so make that a special case:
- var replStr = gReplaceDialog.replaceInput.value;
- if (replStr == "")
- gEditor.deleteSelection(gEditor.eNone, gEditor.eStrip);
- else
- gEditor.insertText(replStr);
-
- // For reverse finds, need to move caret just before the replaced text
- if (gReplaceDialog.searchBackwards.checked && newRange)
- {
- gEditor.selection.removeAllRanges();
- gEditor.selection.addRange(newRange);
- }
-
- return true;
-}
-
-function onReplaceAll()
-{
- if (!gEditor)
- return;
-
- var findStr = gReplaceDialog.findInput.value;
- var repStr = gReplaceDialog.replaceInput.value;
-
- // Transfer dialog contents to the find service.
- saveFindData();
-
- var finder = Components.classes["@mozilla.org/embedcomp/rangefind;1"].createInstance().QueryInterface(Components.interfaces.nsIFind);
-
- finder.caseSensitive = gReplaceDialog.caseSensitive.checked;
- finder.findBackwards = gReplaceDialog.searchBackwards.checked;
-
- // We want the whole operation to be undoable in one swell foop,
- // so start a transaction:
- gEditor.beginTransaction();
-
- // and to make sure we close the transaction, guard against exceptions:
- try {
- // Make a range containing the current selection,
- // so we don't go past it when we wrap.
- var selection = gEditor.selection;
- var selecRange;
- if (selection.rangeCount > 0)
- selecRange = selection.getRangeAt(0);
- var origRange = selecRange.cloneRange();
-
- // We'll need a range for the whole document:
- var wholeDocRange = gEditor.document.createRange();
- var rootNode = gEditor.rootElement.QueryInterface(Components.interfaces.nsIDOMNode);
- wholeDocRange.selectNodeContents(rootNode);
-
- // And start and end points:
- var endPt = gEditor.document.createRange();
-
- if (gReplaceDialog.searchBackwards.checked)
- {
- endPt.setStart(wholeDocRange.startContainer, wholeDocRange.startOffset);
- endPt.setEnd(wholeDocRange.startContainer, wholeDocRange.startOffset);
- }
- else
- {
- endPt.setStart(wholeDocRange.endContainer, wholeDocRange.endOffset);
- endPt.setEnd(wholeDocRange.endContainer, wholeDocRange.endOffset);
- }
-
- // Find and replace from here to end (start) of document:
- var foundRange;
- var searchRange = wholeDocRange.cloneRange();
- while ((foundRange = finder.Find(findStr, searchRange,
- selecRange, endPt)) != null)
- {
- gEditor.selection.removeAllRanges();
- gEditor.selection.addRange(foundRange);
-
- // The editor will leave the caret at the end of the replaced text.
- // For reverse finds, we need it at the beginning,
- // so save the next position now.
- if (gReplaceDialog.searchBackwards.checked)
- {
- selecRange = foundRange.cloneRange();
- selecRange.setEnd(selecRange.startContainer, selecRange.startOffset);
- }
-
- // nsPlaintextEditor::InsertText fails if the string is empty,
- // so make that a special case:
- if (repStr == "")
- gEditor.deleteSelection(gEditor.eNone, gEditor.eStrip);
- else
- gEditor.insertText(repStr);
-
- // If we're going forward, we didn't save selecRange before, so do it now:
- if (!gReplaceDialog.searchBackwards.checked)
- {
- selection = gEditor.selection;
- if (selection.rangeCount <= 0) {
- gEditor.endTransaction();
- return;
- }
- selecRange = selection.getRangeAt(0).cloneRange();
- }
- }
-
- // If no wrapping, then we're done
- if (!gReplaceDialog.wrap.checked) {
- gEditor.endTransaction();
- return;
- }
-
- // If wrapping, find from start/end of document back to start point.
- if (gReplaceDialog.searchBackwards.checked)
- {
- // Collapse origRange to end
- origRange.setStart(origRange.endContainer, origRange.endOffset);
- // Set current position to document end
- selecRange.setEnd(wholeDocRange.endContainer, wholeDocRange.endOffset);
- selecRange.setStart(wholeDocRange.endContainer, wholeDocRange.endOffset);
- }
- else
- {
- // Collapse origRange to start
- origRange.setEnd(origRange.startContainer, origRange.startOffset);
- // Set current position to document start
- selecRange.setStart(wholeDocRange.startContainer,
- wholeDocRange.startOffset);
- selecRange.setEnd(wholeDocRange.startContainer, wholeDocRange.startOffset);
- }
-
- while ((foundRange = finder.Find(findStr, wholeDocRange,
- selecRange, origRange)) != null)
- {
- gEditor.selection.removeAllRanges();
- gEditor.selection.addRange(foundRange);
-
- // Save insert point for backward case
- if (gReplaceDialog.searchBackwards.checked)
- {
- selecRange = foundRange.cloneRange();
- selecRange.setEnd(selecRange.startContainer, selecRange.startOffset);
- }
-
- // nsPlaintextEditor::InsertText fails if the string is empty,
- // so make that a special case:
- if (repStr == "")
- gEditor.deleteSelection(gEditor.eNone, gEditor.eStrip);
- else
- gEditor.insertText(repStr);
-
- // Get insert point for forward case
- if (!gReplaceDialog.searchBackwards.checked)
- {
- selection = gEditor.selection;
- if (selection.rangeCount <= 0) {
- gEditor.endTransaction();
- return;
- }
- selecRange = selection.getRangeAt(0);
- }
- }
- } // end try
- catch (e) { }
-
- gEditor.endTransaction();
-}
-
-function doEnabling()
-{
- var findStr = gReplaceDialog.findInput.value;
- var repStr = gReplaceDialog.replaceInput.value;
- gReplaceDialog.enabled = findStr;
- gReplaceDialog.findNext.disabled = !findStr;
- gReplaceDialog.replace.disabled = !findStr;
- gReplaceDialog.replaceAndFind.disabled = !findStr;
- gReplaceDialog.replaceAll.disabled = !findStr;
-}
diff --git a/editor/ui/dialogs/content/EdReplace.xul b/editor/ui/dialogs/content/EdReplace.xul
deleted file mode 100644
index 307331e1a..000000000
--- a/editor/ui/dialogs/content/EdReplace.xul
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorReplace.dtd">
-
-<dialog id="replaceDlg" title="&replaceDialog.title;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- persist="screenX screenY"
- buttons="cancel"
- onload = "onLoad()"
- ondialogaccept="onFindNext(); return false">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdReplace.js"/>
- <stringbundle id="findBundle" src="chrome://global/locale/finddialog.properties"/>
-
- <hbox>
- <vbox>
- <spacer class="spacer"/>
- <grid align="start">
- <columns><column/><column/></columns>
- <rows>
- <row align="center">
- <label value="&findField.label;" accesskey="&findField.accesskey;" control="dialog.findInput"/>
- <textbox id="dialog.findInput" oninput="doEnabling();"/>
- </row>
- <row align="center">
- <label value="&replaceField.label;" accesskey="&replaceField.accesskey;" control="dialog.replaceInput"/>
- <textbox id="dialog.replaceInput" oninput="doEnabling();"/>
- </row>
- <row align="start">
- <spacer/>
- <vbox align="start">
- <spacer class="bigspacer"/>
- <checkbox id="dialog.caseSensitive" label="&caseSensitiveCheckbox.label;"
- accesskey="&caseSensitiveCheckbox.accesskey;"/>
- <checkbox id="dialog.wrap" label="&wrapCheckbox.label;"
- accesskey="&wrapCheckbox.accesskey;"/>
- <checkbox id="dialog.searchBackwards" label="&backwardsCheckbox.label;"
- accesskey="&backwardsCheckbox.accesskey;"/>
- </vbox>
- </row>
- </rows>
- </grid>
- </vbox>
- <vbox>
- <button id="findNext" label="&findNextButton.label;" accesskey="&findNextButton.accesskey;"
- oncommand="onFindNext();" default="true"/>
- <button id="replace" label="&replaceButton.label;" accesskey="&replaceButton.accesskey;"
- oncommand="onReplace();"/>
- <button id="replaceAndFind" label="&replaceAndFindButton.label;"
- accesskey="&replaceAndFindButton.accesskey;" oncommand="onReplace(); onFindNext();"/>
- <button id="replaceAll" label="&replaceAllButton.label;"
- accesskey="&replaceAllButton.accesskey;" oncommand="onReplaceAll();"/>
- <button dlgtype="cancel" label="&closeButton.label;"/>
- </vbox>
- </hbox>
-</dialog>
diff --git a/editor/ui/dialogs/content/EdSelectProps.js b/editor/ui/dialogs/content/EdSelectProps.js
deleted file mode 100644
index 0471f824c..000000000
--- a/editor/ui/dialogs/content/EdSelectProps.js
+++ /dev/null
@@ -1,752 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// Global variables
-
-var hasValue;
-var oldValue;
-var insertNew;
-var itemArray;
-var treeBoxObject;
-var treeSelection;
-var selectElement;
-var currentItem = null;
-var selectedOption = null;
-var selectedOptionCount = 0;
-
-// Utility functions
-
-function getParentIndex(index)
-{
- switch (itemArray[index].level)
- {
- case 0: return -1;
- case 1: return 0;
- }
- while (itemArray[--index].level > 1);
- return index;
-}
-
-function UpdateSelectMultiple()
-{
- if (selectedOptionCount > 1)
- {
- gDialog.selectMultiple.checked = true;
- gDialog.selectMultiple.disabled = true;
- }
- else
- gDialog.selectMultiple.disabled = false;
-}
-
-/* wrapper objects:
- * readonly attribute Node element; // DOM node (select/optgroup/option)
- * readonly attribute int level; // tree depth
- * readonly attribute boolean container; // can contain options
- * string getCellText(string col); // tree view helper
- * string cycleCell(int currentIndex); // tree view helper
- * void onFocus(); // load data into deck
- * void onBlur(); // save data from deck
- * boolean canDestroy(boolean prompt); // NB prompt not used
- * void destroy(); // post remove callback
- * void moveUp();
- * boolean canMoveDown();
- * void moveDown();
- * void appendOption(newElement, currentIndex);
- */
-
-// OPTION element wrapper object
-
-// Create a wrapper for the given element at the given level
-function optionObject(option, level)
-{
- // select an added option (when loading from document)
- if (option.hasAttribute("selected"))
- selectedOptionCount++;
- this.level = level;
- this.element = option;
-}
-
-optionObject.prototype.container = false;
-
-optionObject.prototype.getCellText = function getCellText(column)
-{
- if (column.id == "SelectSelCol")
- return "";
- if (column.id == "SelectValCol" && this.element.hasAttribute("value"))
- return this.element.getAttribute("value");
- return this.element.text;
-}
-
-optionObject.prototype.cycleCell = function cycleCell(index)
-{
- if (this.element.hasAttribute("selected"))
- {
- this.element.removeAttribute("selected");
- selectedOptionCount--;
- selectedOption = null;
- }
- else
- {
- // Different handling for multiselect lists
- if (gDialog.selectMultiple.checked || !selectedOption)
- selectedOptionCount++;
- else if (selectedOption)
- {
- selectedOption.removeAttribute("selected");
- var column = treeBoxObject.columns["SelectSelCol"];
- treeBoxObject.invalidateColumn(column);
- selectedOption = null;
- }
- this.element.setAttribute("selected", "");
- selectedOption = this.element;
- var column = treeBoxObject.columns["SelectSelCol"];
- treeBoxObject.invalidateCell(index, column);
- }
- if (currentItem == this)
- // Also update the deck
- gDialog.optionSelected.setAttribute("checked", this.element.hasAttribute("selected"));
- UpdateSelectMultiple();
-};
-
-optionObject.prototype.onFocus = function onFocus()
-{
- gDialog.optionText.value = this.element.text;
- hasValue = this.element.hasAttribute("value");
- oldValue = this.element.value;
- gDialog.optionHasValue.checked = hasValue;
- gDialog.optionValue.value = hasValue ? this.element.value : this.element.text;
- gDialog.optionSelected.checked = this.element.hasAttribute("selected");
- gDialog.optionDisabled.checked = this.element.hasAttribute("disabled");
- gDialog.selectDeck.setAttribute("selectedIndex", "2");
-};
-
-optionObject.prototype.onBlur = function onBlur()
-{
- this.element.text = gDialog.optionText.value;
- if (gDialog.optionHasValue.checked)
- this.element.value = gDialog.optionValue.value;
- else
- this.element.removeAttribute("value");
- if (gDialog.optionSelected.checked)
- this.element.setAttribute("selected", "");
- else
- this.element.removeAttribute("selected");
- if (gDialog.optionDisabled.checked)
- this.element.setAttribute("disabled", "");
- else
- this.element.removeAttribute("disabled");
-};
-
-optionObject.prototype.canDestroy = function canDestroy(prompt)
-{
- return true;
-/*return !prompt ||
- ConfirmWithTitle(GetString("DeleteOption"),
- GetString("DeleteOptionMsg"),
- GetString("DeleteOption"));*/
-};
-
-optionObject.prototype.destroy = function destroy()
-{
- // Deselect a removed option
- if (this.element.hasAttribute("selected"))
- {
- selectedOptionCount--;
- selectedOption = null;
- UpdateSelectMultiple();
- }
-};
-
-/* 4 cases:
- * a) optgroup -> optgroup
- * ... ...
- * option option
- * b) optgroup -> option
- * option optgroup
- * ... ...
- * c) option
- * option
- * d) option
- * option
- */
-
-optionObject.prototype.moveUp = function moveUp()
-{
- var i;
- var index = treeSelection.currentIndex;
- if (itemArray[index].level < itemArray[index - 1].level + itemArray[index - 1].container)
- {
- // we need to repaint the tree's lines
- treeBoxObject.invalidateRange(getParentIndex(index), index);
- // a) option is just after an optgroup, so it becomes the last child
- itemArray[index].level = 2;
- treeBoxObject.view.selectionChanged();
- }
- else
- {
- // otherwise new option level is now the same as the previous item
- itemArray[index].level = itemArray[index - 1].level;
- // swap the option with the previous item
- itemArray.splice(index, 0, itemArray.splice(--index, 1)[0]);
- }
- selectTreeIndex(index, true);
-}
-
-optionObject.prototype.canMoveDown = function canMoveDown()
-{
- // move down is not allowed on the last option if its level is 1
- return this.level > 1 || itemArray.length - treeSelection.currentIndex > 1;
-}
-
-optionObject.prototype.moveDown = function moveDown()
-{
- var i;
- var index = treeSelection.currentIndex;
- if (index + 1 == itemArray.length || itemArray[index].level > itemArray[index + 1].level)
- {
- // we need to repaint the tree's lines
- treeBoxObject.invalidateRange(getParentIndex(index), index);
- // a) option is last child of an optgroup, so it moves just after
- itemArray[index].level = 1;
- treeBoxObject.view.selectionChanged();
- }
- else
- {
- // level increases if the option was preceding an optgroup
- itemArray[index].level += itemArray[index + 1].container;
- // swap the option with the next item
- itemArray.splice(index, 0, itemArray.splice(++index, 1)[0]);
- }
- selectTreeIndex(index, true);
-}
-
-optionObject.prototype.appendOption = function appendOption(child, parent)
-{
- // special case quick check
- if (this.level == 1)
- return gDialog.appendOption(child, 0);
-
- // append the option to the parent element
- parent = getParentIndex(parent);
- return itemArray[parent].appendOption(child, parent);
-};
-
-// OPTGROUP element wrapper object
-
-function optgroupObject(optgroup)
-{
- this.element = optgroup;
-}
-
-optgroupObject.prototype.level = 1;
-
-optgroupObject.prototype.container = true;
-
-optgroupObject.prototype.getCellText = function getCellText(column)
-{
- return column.id == "SelectTextCol" ? this.element.label : "";
-}
-
-optgroupObject.prototype.cycleCell = function cycleCell(index)
-{
-};
-
-optgroupObject.prototype.onFocus = function onFocus()
-{
- gDialog.optgroupLabel.value = this.element.label;
- gDialog.optgroupDisabled.checked = this.element.disabled;
- gDialog.selectDeck.setAttribute("selectedIndex", "1");
-};
-
-optgroupObject.prototype.onBlur = function onBlur()
-{
- this.element.label = gDialog.optgroupLabel.value;
- this.element.disabled = gDialog.optgroupDisabled.checked;
-};
-
-optgroupObject.prototype.canDestroy = function canDestroy(prompt)
-{
- // Only removing empty option groups for now
- return gDialog.nextChild(treeSelection.currentIndex) - treeSelection.currentIndex == 1;
-/*&& (!prompt ||
- ConfirmWithTitle(GetString("DeleteOptGroup"),
- GetString("DeleteOptGroupMsg"),
- GetString("DeleteOptGroup")));
-*/
-};
-
-optgroupObject.prototype.destroy = function destroy()
-{
-};
-
-optgroupObject.prototype.moveUp = function moveUp()
-{
- // Find the index of the previous and next elements at the same level
- var index = treeSelection.currentIndex;
- var i = index;
- while (itemArray[--index].level > 1);
- var j = gDialog.nextChild(i);
- // Cut out the element, cut the array in two, then join together
- var movedItems = itemArray.splice(i, j - i);
- var endItems = itemArray.splice(index);
- itemArray = itemArray.concat(movedItems).concat(endItems);
- // Repaint the lot
- treeBoxObject.invalidateRange(index, j);
- selectTreeIndex(index, true);
-}
-
-optgroupObject.prototype.canMoveDown = function canMoveDown()
-{
- return gDialog.lastChild() > treeSelection.currentIndex;
-}
-
-optgroupObject.prototype.moveDown = function moveDown()
-{
- // Find the index of the next two elements at the same level
- var index = treeSelection.currentIndex;
- var i = gDialog.nextChild(index);
- var j = gDialog.nextChild(i);
- // Cut out the element, cut the array in two, then join together
- var movedItems = itemArray.splice(i, j - 1);
- var endItems = itemArray.splice(index);
- itemArray = itemArray.concat(movedItems).concat(endItems);
- // Repaint the lot
- treeBoxObject.invalidateRange(index, j);
- index += j - i;
- selectTreeIndex(index, true);
-}
-
-optgroupObject.prototype.appendOption = function appendOption(child, parent)
-{
- var index = gDialog.nextChild(parent);
- // XXX need to repaint the lines, tree won't do this
- var primaryCol = treeBoxObject.columns.getPrimaryColumn();
- treeBoxObject.invalidateCell(index - 1, primaryCol);
- // insert the wrapped object as the last child
- itemArray.splice(index, 0, new optionObject(child, 2));
- treeBoxObject.rowCountChanged(index, 1);
- selectTreeIndex(index, false);
-};
-
-// dialog initialization code
-
-function Startup()
-{
- var editor = GetCurrentEditor();
- if (!editor)
- {
- dump("Failed to get active editor!\n");
- window.close();
- return;
- }
-
- // Get a single selected select element
- const kTagName = "select";
- try {
- selectElement = editor.getSelectedElement(kTagName);
- } catch (e) {}
-
- if (selectElement)
- // We found an element and don't need to insert one
- insertNew = false;
- else
- {
- insertNew = true;
-
- // We don't have an element selected,
- // so create one with default attributes
- try {
- selectElement = editor.createElementWithDefaults(kTagName);
- } catch (e) {}
-
- if(!selectElement)
- {
- dump("Failed to get selected element or create a new one!\n");
- window.close();
- return;
- }
- }
-
- // SELECT element wrapper object
- gDialog = {
- // useful elements
- accept: document.documentElement.getButton("accept"),
- selectDeck: document.getElementById("SelectDeck"),
- selectName: document.getElementById("SelectName"),
- selectSize: document.getElementById("SelectSize"),
- selectMultiple: document.getElementById("SelectMultiple"),
- selectDisabled: document.getElementById("SelectDisabled"),
- selectTabIndex: document.getElementById("SelectTabIndex"),
- optgroupLabel: document.getElementById("OptGroupLabel"),
- optgroupDisabled: document.getElementById("OptGroupDisabled"),
- optionText: document.getElementById("OptionText"),
- optionHasValue: document.getElementById("OptionHasValue"),
- optionValue: document.getElementById("OptionValue"),
- optionSelected: document.getElementById("OptionSelected"),
- optionDisabled: document.getElementById("OptionDisabled"),
- removeButton: document.getElementById("RemoveButton"),
- previousButton: document.getElementById("PreviousButton"),
- nextButton: document.getElementById("NextButton"),
- tree: document.getElementById("SelectTree"),
- // wrapper methods (except MoveUp and MoveDown)
- element: selectElement.cloneNode(false),
- level: 0,
- container: true,
- getCellText: function getCellText(column)
- {
- return column.id == "SelectTextCol" ? this.element.getAttribute("name") : "";
- },
- cycleCell: function cycleCell(index) {},
- onFocus: function onFocus()
- {
- gDialog.selectName.value = this.element.getAttribute("name");
- gDialog.selectSize.value = this.element.getAttribute("size");
- gDialog.selectMultiple.checked = this.element.hasAttribute("multiple");
- gDialog.selectDisabled.checked = this.element.hasAttribute("disabled");
- gDialog.selectTabIndex.value = this.element.getAttribute("tabindex");
- this.selectDeck.setAttribute("selectedIndex", "0");
- onNameInput();
- },
- onBlur: function onBlur()
- {
- this.element.setAttribute("name", gDialog.selectName.value);
- if (gDialog.selectSize.value)
- this.element.setAttribute("size", gDialog.selectSize.value);
- else
- this.element.removeAttribute("size");
- if (gDialog.selectMultiple.checked)
- this.element.setAttribute("multiple", "");
- else
- this.element.removeAttribute("multiple");
- if (gDialog.selectDisabled.checked)
- this.element.setAttribute("disabled", "");
- else
- this.element.removeAttribute("disabled");
- if (gDialog.selectTabIndex.value)
- this.element.setAttribute("tabindex", gDialog.selectTabIndex.value);
- else
- this.element.removeAttribute("tabindex");
- },
- appendOption: function appendOption(child, parent)
- {
- var index = itemArray.length;
- // XXX need to repaint the lines, tree won't do this
- treeBoxObject.invalidateRange(this.lastChild(), index);
- // append the wrapped object
- itemArray.push(new optionObject(child, 1));
- treeBoxObject.rowCountChanged(index, 1);
- selectTreeIndex(index, false);
- },
- canDestroy: function canDestroy(prompt)
- {
- return false;
- },
- canMoveDown: function canMoveDown()
- {
- return false;
- },
- // helper methods
- // Find the index of the next immediate child of the select
- nextChild: function nextChild(index)
- {
- while (++index < itemArray.length && itemArray[index].level > 1);
- return index;
- },
- // Find the index of the last immediate child of the select
- lastChild: function lastChild()
- {
- var index = itemArray.length;
- while (itemArray[--index].level > 1);
- return index;
- }
- }
- // Start with the <select> wrapper
- itemArray = [gDialog];
-
- // We modify the actual option and optgroup elements so clone them first
- for (var child = selectElement.firstChild; child; child = child.nextSibling)
- {
- if (child.tagName == "OPTION")
- itemArray.push(new optionObject(child.cloneNode(true), 1));
- else if (child.tagName == "OPTGROUP")
- {
- itemArray.push(new optgroupObject(child.cloneNode(false)));
- for (var grandchild = child.firstChild; grandchild; grandchild = grandchild.nextSibling)
- if (grandchild.tagName == "OPTION")
- itemArray.push(new optionObject(grandchild.cloneNode(true), 2));
- }
- }
-
- UpdateSelectMultiple();
-
- // Define a custom view for the tree
- treeBoxObject = gDialog.tree.treeBoxObject;
- treeBoxObject.view = {
- QueryInterface : function QueryInterface(aIID)
- {
- if (aIID.equals(Components.interfaces.nsITreeView) ||
- aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
- aIID.equals(Components.interfaces.nsISupports))
- return this;
-
- throw Components.results.NS_ERROR_NO_INTERFACE;
- },
- // useful for debugging
- get wrappedJSObject() { return this; },
- get rowCount() { return itemArray.length; },
- get selection() { return treeSelection; },
- set selection(selection) { return treeSelection = selection; },
- getRowProperties: function getRowProperties(index) { return ""; },
- // could have used a wrapper for this
- getCellProperties: function getCellProperties(index, column)
- {
- if (column.id == "SelectSelCol" && !itemArray[index].container)
- return "checked-" + itemArray[index].element.hasAttribute("selected");
- return "";
- },
- getColumnProperties: function getColumnProperties(column) { return ""; },
- // get info from wrapper
- isContainer: function isContainer(index) { return itemArray[index].container; },
- isContainerOpen: function isContainerOpen(index) { return true; },
- isContainerEmpty: function isContainerEmpty(index) { return true; },
- isSeparator: function isSeparator(index) { return false; },
- isSorted: function isSorted() { return false; },
- // d&d not implemented yet!
- canDrop: function canDrop(index, orientation) { return false; },
- drop: function drop(index, orientation) { alert('drop:' + index + ',' + orientation); },
- // same as the global helper
- getParentIndex: getParentIndex,
- // tree needs to know when to paint lines
- hasNextSibling: function hasNextSibling(index, after)
- {
- if (!index)
- return false;
- var level = itemArray[index].level;
- while (++after < itemArray.length)
- switch (level - itemArray[after].level)
- {
- case 1: return false;
- case 0: return true;
- }
- return false;
- },
- getLevel: function getLevel(index) { return itemArray[index].level; },
- getImageSrc: function getImageSrc(index, column) { },
- getProgressMode : function getProgressMode(index,column) { },
- getCellValue: function getCellValue(index, column) { },
- getCellText: function getCellText(index, column) { return itemArray[index].getCellText(column); },
- setTree: function setTree(tree) { this.tree = tree; },
- toggleOpenState: function toggleOpenState(index) { },
- cycleHeader: function cycleHeader(col) { },
- selectionChanged: function selectionChanged()
- {
- // Save current values and update buttons and deck
- if (currentItem)
- currentItem.onBlur();
- var currentIndex = treeSelection.currentIndex;
- currentItem = itemArray[currentIndex];
- gDialog.removeButton.disabled = !currentItem.canDestroy();
- gDialog.previousButton.disabled = currentIndex < 2;
- gDialog.nextButton.disabled = !currentItem.canMoveDown();
- // For Advanced Edit
- globalElement = currentItem.element;
- currentItem.onFocus();
- },
- cycleCell: function cycleCell(index, column) { itemArray[index].cycleCell(index); },
- isEditable: function isEditable(index, column) { return false; },
- isSelectable: function isSelectable(index, column) { return false; },
- performAction: function performAction(action) { },
- performActionOnCell: function performActionOnCell(action, index, column) { }
- };
- treeSelection.select(0);
- currentItem = gDialog;
- //onNameInput();
-
- SetTextboxFocus(gDialog.selectName);
-
- SetWindowLocation();
-}
-
-// Called from Advanced Edit
-function InitDialog()
-{
- currentItem.onFocus();
-}
-
-// Called from Advanced Edit
-function ValidateData()
-{
- currentItem.onBlur();
- return true;
-}
-
-function onAccept()
-{
- // All values are valid - copy to actual element in doc or
- // element created to insert
- ValidateData();
-
- var editor = GetCurrentEditor();
-
- // Coalesce into one undo transaction
- editor.beginTransaction();
-
- try
- {
- editor.cloneAttributes(selectElement, gDialog.element);
-
- if (insertNew)
- // 'true' means delete the selection before inserting
- editor.insertElementAtSelection(selectElement, true);
-
- editor.setShouldTxnSetSelection(false);
-
- while (selectElement.lastChild)
- editor.deleteNode(selectElement.lastChild);
-
- var offset = 0;
- for (var i = 1; i < itemArray.length; i++)
- if (itemArray[i].level > 1)
- selectElement.lastChild.appendChild(itemArray[i].element);
- else
- editor.insertNode(itemArray[i].element, selectElement, offset++, true);
-
- editor.setShouldTxnSetSelection(true);
- }
- finally
- {
- editor.endTransaction();
- }
-
- SaveWindowLocation();
-
- return true;
-}
-
-// Button actions
-function AddOption()
-{
- currentItem.appendOption(GetCurrentEditor().createElementWithDefaults("option"), treeSelection.currentIndex);
- SetTextboxFocus(gDialog.optionText);
-}
-
-function AddOptGroup()
-{
- var optgroupElement = GetCurrentEditor().createElementWithDefaults("optgroup");
- var index = itemArray.length;
- // XXX need to repaint the lines, tree won't do this
- treeBoxObject.invalidateRange(gDialog.lastChild(), index);
- // append the wrapped object
- itemArray.push(new optgroupObject(optgroupElement));
- treeBoxObject.rowCountChanged(index, 1);
- selectTreeIndex(index, false);
- SetTextboxFocus(gDialog.optgroupLabel);
-}
-
-function RemoveElement()
-{
- if (currentItem.canDestroy(true))
- {
- // Only removing empty option groups for now
- var index = treeSelection.currentIndex;
- var level = itemArray[index].level;
- // Perform necessary cleanup and remove the wrapper
- itemArray[index].destroy();
- itemArray.splice(index, 1);
- --index;
- // XXX need to repaint the lines, tree won't do this
- if (level == 1) {
- var last = gDialog.lastChild();
- if (index > last)
- treeBoxObject.invalidateRange(last, index);
- }
- selectTreeIndex(index, true);
- treeBoxObject.rowCountChanged(++index, -1);
- }
-}
-
-// Event handler
-function onTreeKeyUp(event)
-{
- if (event.keyCode == event.DOM_VK_SPACE)
- currentItem.cycleCell();
-}
-
-function onNameInput()
-{
- var disabled = !gDialog.selectName.value;
- if (gDialog.accept.disabled != disabled)
- gDialog.accept.disabled = disabled;
- gDialog.element.setAttribute("name", gDialog.selectName.value);
- // repaint the tree
- var primaryCol = treeBoxObject.columns.getPrimaryColumn();
- treeBoxObject.invalidateCell(treeSelection.currentIndex, primaryCol);
-}
-
-function onLabelInput()
-{
- currentItem.element.setAttribute("label", gDialog.optgroupLabel.value);
- // repaint the tree
- var primaryCol = treeBoxObject.columns.getPrimaryColumn();
- treeBoxObject.invalidateCell(treeSelection.currentIndex, primaryCol);
-}
-
-function onTextInput()
-{
- currentItem.element.text = gDialog.optionText.value;
- // repaint the tree
- if (hasValue) {
- var primaryCol = treeBoxObject.columns.getPrimaryColumn();
- treeBoxObject.invalidateCell(treeSelection.currentIndex, primaryCol);
- }
- else
- {
- gDialog.optionValue.value = gDialog.optionText.value;
- treeBoxObject.invalidateRow(treeSelection.currentIndex);
- }
-}
-
-function onValueInput()
-{
- gDialog.optionHasValue.checked = hasValue = true;
- oldValue = gDialog.optionValue.value;
- currentItem.element.setAttribute("value", oldValue);
- // repaint the tree
- var column = treeBoxObject.columns["SelectValCol"];
- treeBoxObject.invalidateCell(treeSelection.currentIndex, column);
-}
-
-function onHasValueClick()
-{
- hasValue = gDialog.optionHasValue.checked;
- if (hasValue)
- {
- gDialog.optionValue.value = oldValue;
- currentItem.element.setAttribute("value", oldValue);
- }
- else
- {
- oldValue = gDialog.optionValue.value;
- gDialog.optionValue.value = gDialog.optionText.value;
- currentItem.element.removeAttribute("value");
- }
- // repaint the tree
- var column = treeBoxObject.columns["SelectValCol"];
- treeBoxObject.invalidateCell(treeSelection.currentIndex, column);
-}
-
-function onSelectMultipleClick()
-{
- // Recalculate the unique selected option if we need it and have lost it
- if (!gDialog.selectMultiple.checked && selectedOptionCount == 1 && !selectedOption)
- for (var i = 1; !(selectedOption = itemArray[i].element).hasAttribute("selected"); i++);
-}
-
-function selectTreeIndex(index, focus)
-{
- treeSelection.select(index);
- treeBoxObject.ensureRowIsVisible(index);
- if (focus)
- gDialog.tree.focus();
-}
diff --git a/editor/ui/dialogs/content/EdSelectProps.xul b/editor/ui/dialogs/content/EdSelectProps.xul
deleted file mode 100644
index 94786fe87..000000000
--- a/editor/ui/dialogs/content/EdSelectProps.xul
+++ /dev/null
@@ -1,129 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorSelectProperties.dtd">
-<dialog title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="Startup();"
- buttons="accept,cancel"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdSelectProps.js"/>
-
- <broadcaster id="args" value=""/>
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
-
- <!-- Setting rows="7" on tree isn't working, equalsize vbox sets tree height. -->
- <vbox equalsize="always">
- <tree id="SelectTree" onselect="treeBoxObject.view.selectionChanged();" onkeyup="onTreeKeyUp(event);">
- <treecols id="SelectCols">
- <treecol id="SelectTextCol" flex="3" label="&TextHeader.label;" primary="true"/>
- <splitter class="tree-splitter"/>
- <treecol id="SelectValCol" flex="2" label="&ValueHeader.label;"/>
- <treecol id="SelectSelCol" label="&SelectedHeader.label;" cycler="true"/>
- </treecols>
-
- <treechildren id="SelectTreeChildren"/>
- </tree>
-
- <hbox flex="1">
- <deck flex="1" id="SelectDeck" index="0">
- <groupbox flex="1"><caption label="&Select.label;"/>
- <grid flex="1"><columns><column flex="1"/><column/></columns>
- <rows>
- <row align="center">
- <label control="SelectName" value="&SelectName.label;" accesskey="&SelectName.accesskey;"/>
- <textbox id="SelectName" flex="1" oninput="onNameInput();"/>
- </row>
- <row align="center">
- <label control="SelectSize" value="&SelectSize.label;" accesskey="&SelectSize.accesskey;"/>
- <hbox>
- <textbox id="SelectSize" class="narrow" oninput="forceInteger(this.id);"/>
- </hbox>
- </row>
- <row>
- <spacer/>
- <checkbox id="SelectMultiple" flex="1" label="&SelectMultiple.label;" accesskey="&SelectMultiple.accesskey;" oncommand="onSelectMultipleClick();"/>
- </row>
- <row>
- <spacer/>
- <checkbox id="SelectDisabled" flex="1" label="&SelectDisabled.label;" accesskey="&SelectDisabled.accesskey;"/>
- </row>
- <row align="center">
- <label control="SelectTabIndex" value="&SelectTabIndex.label;" accesskey="&SelectTabIndex.accesskey;"/>
- <hbox>
- <textbox id="SelectTabIndex" class="narrow" oninput="forceInteger(this.id);"/>
- </hbox>
- </row>
- </rows>
- </grid>
- </groupbox>
-
- <groupbox flex="1"><caption label="&OptGroup.label;"/>
- <grid flex="1"><columns><column flex="1"/><column/></columns>
- <rows>
- <row align="center">
- <label control="OptGroupLabel" value="&OptGroupLabel.label;" accesskey="&OptGroupLabel.accesskey;"/>
- <textbox id="OptGroupLabel" oninput="onLabelInput();"/>
- </row>
- <row>
- <spacer/>
- <checkbox id="OptGroupDisabled" label="&OptGroupDisabled.label;" accesskey="&OptGroupDisabled.accesskey;"/>
- </row>
- </rows>
- </grid>
- </groupbox>
-
- <groupbox flex="1"><caption label="&Option.label;"/>
- <grid flex="1"><columns><column flex="1"/><column/></columns>
- <rows>
- <row align="center">
- <label control="OptionText" value="&OptionText.label;" accesskey="&OptionText.accesskey;"/>
- <textbox id="OptionText" oninput="onTextInput();"/>
- </row>
- <row align="center">
- <checkbox id="OptionHasValue" label="&OptionValue.label;" accesskey="&OptionValue.accesskey;" oncommand="onHasValueClick();"/>
- <textbox id="OptionValue" oninput="onValueInput();"/>
- </row>
- <row>
- <spacer/>
- <checkbox id="OptionSelected" label="&OptionSelected.label;" accesskey="&OptionSelected.accesskey;" oncommand="currentItem.cycleCell();"/>
- </row>
- <row>
- <spacer/>
- <checkbox id="OptionDisabled" label="&OptionDisabled.label;" accesskey="&OptionDisabled.accesskey;"/>
- </row>
- </rows>
- </grid>
- </groupbox>
- </deck>
-
- <vbox>
- <button label="&AddOption.label;" accesskey="&AddOption.accesskey;" oncommand="AddOption();"/>
- <button label="&AddOptGroup.label;" accesskey="&AddOptGroup.accesskey;" oncommand="AddOptGroup();"/>
- <button id="RemoveButton" label="&RemoveElement.label;" accesskey="&RemoveElement.accesskey;"
- oncommand="RemoveElement();" disabled="true"/>
- <button id="PreviousButton" label="&MoveElementUp.label;" accesskey="&MoveElementUp.accesskey;"
- oncommand="currentItem.moveUp();" disabled="true" type="row"/>
- <button id="NextButton" label="&MoveElementDown.label;" accesskey="&MoveElementDown.accesskey;"
- oncommand="currentItem.moveDown();" disabled="true" type="row"/>
- <spacer flex="1"/>
- <button id="AdvancedEditButton"/>
- </vbox>
- </hbox>
- </vbox>
-
- <separator class="groove"/>
-
-</dialog>
diff --git a/editor/ui/dialogs/content/EdSpellCheck.js b/editor/ui/dialogs/content/EdSpellCheck.js
deleted file mode 100644
index 7f355ac4c..000000000
--- a/editor/ui/dialogs/content/EdSpellCheck.js
+++ /dev/null
@@ -1,522 +0,0 @@
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-Components.utils.import("resource://gre/modules/InlineSpellChecker.jsm");
-
-var gMisspelledWord;
-var gSpellChecker = null;
-var gAllowSelectWord = true;
-var gPreviousReplaceWord = "";
-var gFirstTime = true;
-var gLastSelectedLang = null;
-var gDictCount = 0;
-
-function Startup()
-{
- var editor = GetCurrentEditor();
- if (!editor)
- {
- window.close();
- return;
- }
-
- // Get the spellChecker shell
- gSpellChecker = Components.classes['@mozilla.org/editor/editorspellchecker;1'].createInstance(Components.interfaces.nsIEditorSpellCheck);
- if (!gSpellChecker)
- {
- dump("SpellChecker not found!!!\n");
- window.close();
- return;
- }
-
- // Start the spell checker module.
- try {
- // TxtSrv Filter Contract Id
- var filterContractId;
- var skipBlockQuotes = window.arguments[1];
- var enableSelectionChecking = window.arguments[2];
-
- if (skipBlockQuotes)
- filterContractId = "@mozilla.org/editor/txtsrvfiltermail;1";
- else
- filterContractId = "@mozilla.org/editor/txtsrvfilter;1";
-
- gSpellChecker.setFilter(Components.classes[filterContractId].createInstance(Components.interfaces.nsITextServicesFilter));
- gSpellChecker.InitSpellChecker(editor, enableSelectionChecking, spellCheckStarted);
-
- }
- catch(ex) {
- dump("*** Exception error: InitSpellChecker\n");
- window.close();
- return;
- }
-}
-
-function spellCheckStarted() {
- gDialog.MisspelledWordLabel = document.getElementById("MisspelledWordLabel");
- gDialog.MisspelledWord = document.getElementById("MisspelledWord");
- gDialog.ReplaceButton = document.getElementById("Replace");
- gDialog.IgnoreButton = document.getElementById("Ignore");
- gDialog.StopButton = document.getElementById("Stop");
- gDialog.CloseButton = document.getElementById("Close");
- gDialog.ReplaceWordInput = document.getElementById("ReplaceWordInput");
- gDialog.SuggestedList = document.getElementById("SuggestedList");
- gDialog.LanguageMenulist = document.getElementById("LanguageMenulist");
-
- // Fill in the language menulist and sync it up
- // with the spellchecker's current language.
-
- var curLang;
-
- try {
- curLang = gSpellChecker.GetCurrentDictionary();
- } catch(ex) {
- curLang = "";
- }
-
- InitLanguageMenu(curLang);
-
- // Get the first misspelled word and setup all UI
- NextWord();
-
- // When startup param is true, setup different UI when spell checking
- // just before sending mail message
- if (window.arguments[0])
- {
- // If no misspelled words found, simply close dialog and send message
- if (!gMisspelledWord)
- {
- onClose();
- return;
- }
-
- // Hide "Close" button and use "Send" instead
- gDialog.CloseButton.hidden = true;
- gDialog.CloseButton = document.getElementById("Send");
- gDialog.CloseButton.hidden = false;
- }
- else
- {
- // Normal spell checking - hide the "Stop" button
- // (Note that this button is the "Cancel" button for
- // Esc keybinding and related window close actions)
- gDialog.StopButton.hidden = true;
- }
-
- // Clear flag that determines message when
- // no misspelled word is found
- // (different message when used for the first time)
- gFirstTime = false;
-
- window.sizeToContent();
-}
-
-function InitLanguageMenu(aCurLang)
-{
-
- var o1 = {};
- var o2 = {};
-
- // Get the list of dictionaries from
- // the spellchecker.
-
- try
- {
- gSpellChecker.GetDictionaryList(o1, o2);
- }
- catch(ex)
- {
- dump("Failed to get DictionaryList!\n");
- return;
- }
-
- var dictList = o1.value;
- var count = o2.value;
-
- // If we're not just starting up and dictionary count
- // hasn't changed then no need to update the menu.
- if (gDictCount == count)
- return;
-
- // Store current dictionary count.
- gDictCount = count;
-
- var inlineSpellChecker = new InlineSpellChecker();
- var sortedList = inlineSpellChecker.sortDictionaryList(dictList);
-
- // Remove any languages from the list.
- var languageMenuPopup = gDialog.LanguageMenulist.firstChild;
- while (languageMenuPopup.firstChild.localName != "menuseparator")
- languageMenuPopup.firstChild.remove();
-
- var defaultItem = null;
-
- for (var i = 0; i < count; i++)
- {
- var item = gDialog.LanguageMenulist.insertItemAt(i, sortedList[i].label, sortedList[i].id);
- if (aCurLang && sortedList[i].id == aCurLang)
- defaultItem = item;
- }
-
- // Now make sure the correct item in the menu list is selected.
- if (defaultItem)
- {
- gDialog.LanguageMenulist.selectedItem = defaultItem;
- gLastSelectedLang = defaultItem;
- }
-}
-
-function DoEnabling()
-{
- if (!gMisspelledWord)
- {
- // No more misspelled words
- gDialog.MisspelledWord.setAttribute("value",GetString( gFirstTime ? "NoMisspelledWord" : "CheckSpellingDone"));
-
- gDialog.ReplaceButton.removeAttribute("default");
- gDialog.IgnoreButton.removeAttribute("default");
-
- gDialog.CloseButton.setAttribute("default","true");
- // Shouldn't have to do this if "default" is true?
- gDialog.CloseButton.focus();
-
- SetElementEnabledById("MisspelledWordLabel", false);
- SetElementEnabledById("ReplaceWordLabel", false);
- SetElementEnabledById("ReplaceWordInput", false);
- SetElementEnabledById("CheckWord", false);
- SetElementEnabledById("SuggestedListLabel", false);
- SetElementEnabledById("SuggestedList", false);
- SetElementEnabledById("Ignore", false);
- SetElementEnabledById("IgnoreAll", false);
- SetElementEnabledById("Replace", false);
- SetElementEnabledById("ReplaceAll", false);
- SetElementEnabledById("AddToDictionary", false);
- } else {
- SetElementEnabledById("MisspelledWordLabel", true);
- SetElementEnabledById("ReplaceWordLabel", true);
- SetElementEnabledById("ReplaceWordInput", true);
- SetElementEnabledById("CheckWord", true);
- SetElementEnabledById("SuggestedListLabel", true);
- SetElementEnabledById("SuggestedList", true);
- SetElementEnabledById("Ignore", true);
- SetElementEnabledById("IgnoreAll", true);
- SetElementEnabledById("AddToDictionary", true);
-
- gDialog.CloseButton.removeAttribute("default");
- SetReplaceEnable();
- }
-}
-
-function NextWord()
-{
- gMisspelledWord = gSpellChecker.GetNextMisspelledWord();
- SetWidgetsForMisspelledWord();
-}
-
-function SetWidgetsForMisspelledWord()
-{
- gDialog.MisspelledWord.setAttribute("value", gMisspelledWord);
-
-
- // Initial replace word is misspelled word
- gDialog.ReplaceWordInput.value = gMisspelledWord;
- gPreviousReplaceWord = gMisspelledWord;
-
- // This sets gDialog.ReplaceWordInput to first suggested word in list
- FillSuggestedList(gMisspelledWord);
-
- DoEnabling();
-
- if (gMisspelledWord)
- SetTextboxFocus(gDialog.ReplaceWordInput);
-}
-
-function CheckWord()
-{
- var word = gDialog.ReplaceWordInput.value;
- if (word)
- {
- if (gSpellChecker.CheckCurrentWord(word))
- {
- FillSuggestedList(word);
- SetReplaceEnable();
- }
- else
- {
- ClearListbox(gDialog.SuggestedList);
- var item = gDialog.SuggestedList.appendItem(GetString("CorrectSpelling"), "");
- if (item) item.setAttribute("disabled", "true");
- // Suppress being able to select the message text
- gAllowSelectWord = false;
- }
- }
-}
-
-function SelectSuggestedWord()
-{
- if (gAllowSelectWord)
- {
- var selectedItem
- if (gDialog.SuggestedList.selectedItem)
- {
- var selValue = gDialog.SuggestedList.selectedItem.getAttribute("label");
- gDialog.ReplaceWordInput.value = selValue;
- gPreviousReplaceWord = selValue;
- }
- else
- {
- gDialog.ReplaceWordInput.value = gPreviousReplaceWord;
- }
- SetReplaceEnable();
- }
-}
-
-function ChangeReplaceWord()
-{
- // Calling this triggers SelectSuggestedWord(),
- // so temporarily suppress the effect of that
- var saveAllow = gAllowSelectWord;
- gAllowSelectWord = false;
-
- // Select matching word in list
- var newIndex = -1;
- var newSelectedItem;
- var replaceWord = TrimString(gDialog.ReplaceWordInput.value);
- if (replaceWord)
- {
- for (var i = 0; i < gDialog.SuggestedList.getRowCount(); i++)
- {
- var item = gDialog.SuggestedList.getItemAtIndex(i);
- if (item.getAttribute("label") == replaceWord)
- {
- newSelectedItem = item;
- break;
- }
- }
- }
- gDialog.SuggestedList.selectedItem = newSelectedItem;
-
- gAllowSelectWord = saveAllow;
-
- // Remember the new word
- gPreviousReplaceWord = gDialog.ReplaceWordInput.value;
-
- SetReplaceEnable();
-}
-
-function Ignore()
-{
- NextWord();
-}
-
-function IgnoreAll()
-{
- if (gMisspelledWord) {
- gSpellChecker.IgnoreWordAllOccurrences(gMisspelledWord);
- }
- NextWord();
-}
-
-function Replace(newWord)
-{
- if (!newWord)
- return;
-
- if (gMisspelledWord && gMisspelledWord != newWord)
- {
- var editor = GetCurrentEditor();
- editor.beginTransaction();
- try {
- gSpellChecker.ReplaceWord(gMisspelledWord, newWord, false);
- } catch (e) {}
- editor.endTransaction();
- }
- NextWord();
-}
-
-function ReplaceAll()
-{
- var newWord = gDialog.ReplaceWordInput.value;
- if (gMisspelledWord && gMisspelledWord != newWord)
- {
- var editor = GetCurrentEditor();
- editor.beginTransaction();
- try {
- gSpellChecker.ReplaceWord(gMisspelledWord, newWord, true);
- } catch (e) {}
- editor.endTransaction();
- }
- NextWord();
-}
-
-function AddToDictionary()
-{
- if (gMisspelledWord) {
- gSpellChecker.AddWordToDictionary(gMisspelledWord);
- }
- NextWord();
-}
-
-function EditDictionary()
-{
- window.openDialog("chrome://editor/content/EdDictionary.xul", "_blank", "chrome,close,titlebar,modal", "", gMisspelledWord);
-}
-
-function SelectLanguage()
-{
- var item = gDialog.LanguageMenulist.selectedItem;
- if (item.value != "more-cmd") {
- gSpellChecker.SetCurrentDictionary(item.value);
- // For compose windows we need to set the "lang" attribute so the
- // core editor uses the correct dictionary for the inline spell check.
- if (window.arguments[1]) {
- window.opener.document.documentElement.setAttribute("lang", item.value);
- }
- gLastSelectedLang = item;
- }
- else {
- openDictionaryList();
-
- if (gLastSelectedLang)
- gDialog.LanguageMenulist.selectedItem = gLastSelectedLang;
- }
-}
-
-function Recheck()
-{
- var recheckLanguage;
-
- function finishRecheck() {
- gSpellChecker.SetCurrentDictionary(recheckLanguage);
- gMisspelledWord = gSpellChecker.GetNextMisspelledWord();
- SetWidgetsForMisspelledWord();
- }
-
- //TODO: Should we bother to add a "Recheck" method to interface?
- try {
- recheckLanguage = gSpellChecker.GetCurrentDictionary();
- gSpellChecker.UninitSpellChecker();
- // Clear the ignore all list.
- Components.classes["@mozilla.org/spellchecker/personaldictionary;1"]
- .getService(Components.interfaces.mozIPersonalDictionary)
- .endSession();
- gSpellChecker.InitSpellChecker(GetCurrentEditor(), false, finishRecheck);
- } catch(ex) {
- Components.utils.reportError(ex);
- }
-}
-
-function FillSuggestedList(misspelledWord)
-{
- var list = gDialog.SuggestedList;
-
- // Clear the current contents of the list
- gAllowSelectWord = false;
- ClearListbox(list);
- var item;
-
- if (misspelledWord.length > 0)
- {
- // Get suggested words until an empty string is returned
- var count = 0;
- var firstWord = 0;
- do {
- var word = gSpellChecker.GetSuggestedWord();
- if (count==0)
- firstWord = word;
- if (word.length > 0)
- {
- list.appendItem(word, "");
- count++;
- }
- } while (word.length > 0);
-
- if (count == 0)
- {
- // No suggestions - show a message but don't let user select it
- item = list.appendItem(GetString("NoSuggestedWords"));
- if (item) item.setAttribute("disabled", "true");
- gAllowSelectWord = false;
- } else {
- gAllowSelectWord = true;
- // Initialize with first suggested list by selecting it
- gDialog.SuggestedList.selectedIndex = 0;
- }
- }
- else
- {
- item = list.appendItem("", "");
- if (item)
- item.setAttribute("disabled", "true");
- }
-}
-
-function SetReplaceEnable()
-{
- // Enable "Change..." buttons only if new word is different than misspelled
- var newWord = gDialog.ReplaceWordInput.value;
- var enable = newWord.length > 0 && newWord != gMisspelledWord;
- SetElementEnabledById("Replace", enable);
- SetElementEnabledById("ReplaceAll", enable);
- if (enable)
- {
- gDialog.ReplaceButton.setAttribute("default","true");
- gDialog.IgnoreButton.removeAttribute("default");
- }
- else
- {
- gDialog.IgnoreButton.setAttribute("default","true");
- gDialog.ReplaceButton.removeAttribute("default");
- }
-}
-
-function doDefault()
-{
- if (gDialog.ReplaceButton.getAttribute("default") == "true")
- Replace(gDialog.ReplaceWordInput.value);
- else if (gDialog.IgnoreButton.getAttribute("default") == "true")
- Ignore();
- else if (gDialog.CloseButton.getAttribute("default") == "true")
- onClose();
-
- return false;
-}
-
-function ExitSpellChecker()
-{
- if (gSpellChecker)
- {
- try
- {
- gSpellChecker.UninitSpellChecker();
- // now check the document over again with the new dictionary
- // if we have an inline spellchecker
- if (("InlineSpellCheckerUI" in window.opener) &&
- window.opener.InlineSpellCheckerUI.enabled)
- window.opener.InlineSpellCheckerUI.mInlineSpellChecker.spellCheckRange(null);
- }
- finally
- {
- gSpellChecker = null;
- }
- }
-}
-
-function CancelSpellCheck()
-{
- ExitSpellChecker();
-
- // Signal to calling window that we canceled
- window.opener.cancelSendMessage = true;
- return true;
-}
-
-function onClose()
-{
- ExitSpellChecker();
-
- window.opener.cancelSendMessage = false;
- window.close();
-}
diff --git a/editor/ui/dialogs/content/EdSpellCheck.xul b/editor/ui/dialogs/content/EdSpellCheck.xul
deleted file mode 100644
index c14647792..000000000
--- a/editor/ui/dialogs/content/EdSpellCheck.xul
+++ /dev/null
@@ -1,115 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorSpellCheck.dtd">
-
-<!-- dialog containing a control requiring initial setup -->
-<dialog id="spellCheckDlg" buttons="cancel" title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- persist="screenX screenY"
- onload = "Startup()"
- ondialogaccept="return doDefault();"
- ondialogcancel="return CancelSpellCheck();">
-
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://communicator/content/utilityOverlay.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdSpellCheck.js"/>
- <script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/>
-
- <broadcaster id="args" value=""/>
-
- <stringbundle id="languageBundle" src="chrome://global/locale/languageNames.properties"/>
- <stringbundle id="regionBundle" src="chrome://global/locale/regionNames.properties"/>
-
- <grid>
- <columns>
- <column class="spell-check"/>
- <column class="spell-check" flex="1"/>
- <column class="spell-check"/>
- </columns>
- <rows>
- <row align="center">
- <label id="MisspelledWordLabel" value="&misspelledWord.label;"/>
- <label class="bold" id="MisspelledWord" crop="end"/>
- <button class="spell-check" label="&recheckButton2.label;" oncommand="Recheck();"
- accesskey="&recheckButton2.accessKey;"/>
- </row>
- <row align="center">
- <label id="ReplaceWordLabel" value="&wordEditField.label;"
- control="ReplaceWordInput"
- accesskey="&wordEditField.accessKey;"/>
- <textbox id="ReplaceWordInput" oninput="ChangeReplaceWord()" flex="1"/>
- <button id="CheckWord" oncommand="CheckWord()" label="&checkwordButton.label;"
- accesskey="&checkwordButton.accessKey;"/>
- </row>
- </rows>
- </grid>
- <label id="SuggestedListLabel" value="&suggestions.label;"
- control="SuggestedList"
- accesskey="&suggestions.accessKey;"/>
- <grid flex="1">
- <columns><column flex="1"/><column/></columns>
- <rows>
- <row flex="1">
- <!-- BUG! setting class="MinWidth20em" on tree doesn't work (width=0) -->
- <listbox rows="6" id="SuggestedList" onselect="SelectSuggestedWord()"
- ondblclick="if (gAllowSelectWord) Replace(event.target.getAttribute('label'));"/>
- <vbox>
- <grid>
- <columns><column class="spell-check" flex="1"/><column class="spell-check" flex="1"/></columns>
- <rows>
- <row>
- <button id="Replace" label="&replaceButton.label;"
- oncommand="Replace(gDialog.ReplaceWordInput.value);"
- accesskey="&replaceButton.accessKey;"/>
- <button id="Ignore" oncommand="Ignore();" label="&ignoreButton.label;"
- accesskey="&ignoreButton.accessKey;"/>
- </row>
- <row>
- <button id="ReplaceAll" oncommand="ReplaceAll();" label="&replaceAllButton.label;"
- accesskey="&replaceAllButton.accessKey;"/>
- <button id="IgnoreAll" oncommand="IgnoreAll();" label="&ignoreAllButton.label;"
- accesskey="&ignoreAllButton.accessKey;"/>
- </row>
- </rows>
- </grid>
- <separator/>
- <label value="&userDictionary.label;"/>
- <hbox align="start">
- <button class="spell-check" id="AddToDictionary" oncommand="AddToDictionary()" label="&addToUserDictionaryButton.label;"
- accesskey="&addToUserDictionaryButton.accessKey;"/>
- <button class="spell-check" id="EditDictionary" oncommand="EditDictionary()" label="&editUserDictionaryButton.label;"
- accesskey="&editUserDictionaryButton.accessKey;"/>
- </hbox>
- </vbox>
- </row>
- <label value ="&languagePopup.label;"
- control="LanguageMenulist"
- accesskey="&languagePopup.accessKey;"/>
- <row>
- <menulist id="LanguageMenulist" oncommand="SelectLanguage()">
- <menupopup onpopupshowing="InitLanguageMenu(gDialog.LanguageMenulist.selectedItem.value);">
- <!-- dynamic content populated by JS -->
- <menuseparator/>
- <menuitem value="more-cmd" label="&moreDictionaries.label;"/>
- </menupopup>
- </menulist>
- <hbox flex="1">
- <button class="spell-check" dlgtype="cancel" id="Stop" label="&stopButton.label;" oncommand="CancelSpellCheck();"
- accesskey="&stopButton.accessKey;"/>
- <spacer flex="1"/>
- <button class="spell-check" id="Close" label="&closeButton.label;" oncommand="onClose();"
- accesskey="&closeButton.accessKey;"/>
- <button class="spell-check" id="Send" label="&sendButton.label;" oncommand="onClose();"
- accesskey="&sendButton.accessKey;" hidden="true"/>
- </hbox>
- </row>
- </rows>
- </grid>
-</dialog>
diff --git a/editor/ui/dialogs/content/EdTableProps.js b/editor/ui/dialogs/content/EdTableProps.js
deleted file mode 100644
index 8b0458c6e..000000000
--- a/editor/ui/dialogs/content/EdTableProps.js
+++ /dev/null
@@ -1,1273 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-//Cancel() is in EdDialogCommon.js
-
-var gTableElement;
-var gCellElement;
-var gTableCaptionElement;
-var globalCellElement;
-var globalTableElement
-var gValidateTab;
-const defHAlign = "left";
-const centerStr = "center"; //Index=1
-const rightStr = "right"; // 2
-const justifyStr = "justify"; // 3
-const charStr = "char"; // 4
-const defVAlign = "middle";
-const topStr = "top";
-const bottomStr = "bottom";
-const bgcolor = "bgcolor";
-var gTableColor;
-var gCellColor;
-
-const cssBackgroundColorStr = "background-color";
-
-var gRowCount = 1;
-var gColCount = 1;
-var gLastRowIndex;
-var gLastColIndex;
-var gNewRowCount;
-var gNewColCount;
-var gCurRowIndex;
-var gCurColIndex;
-var gCurColSpan;
-var gSelectedCellsType = 1;
-const SELECT_CELL = 1;
-const SELECT_ROW = 2;
-const SELECT_COLUMN = 3;
-const RESET_SELECTION = 0;
-var gCellData = { value:null, startRowIndex:0, startColIndex:0, rowSpan:0, colSpan:0,
- actualRowSpan:0, actualColSpan:0, isSelected:false
- };
-var gAdvancedEditUsed;
-var gAlignWasChar = false;
-
-/*
-From C++:
- 0 TABLESELECTION_TABLE
- 1 TABLESELECTION_CELL There are 1 or more cells selected
- but complete rows or columns are not selected
- 2 TABLESELECTION_ROW All cells are in 1 or more rows
- and in each row, all cells selected
- Note: This is the value if all rows (thus all cells) are selected
- 3 TABLESELECTION_COLUMN All cells are in 1 or more columns
-*/
-
-var gSelectedCellCount = 0;
-var gApplyUsed = false;
-var gSelection;
-var gCellDataChanged = false;
-var gCanDelete = false;
-var gUseCSS = true;
-var gActiveEditor;
-
-// dialog initialization code
-function Startup()
-{
- gActiveEditor = GetCurrentTableEditor();
- if (!gActiveEditor)
- {
- window.close();
- return;
- }
-
- try {
- gSelection = gActiveEditor.selection;
- } catch (e) {}
- if (!gSelection) return;
-
- // Get dialog widgets - Table Panel
- gDialog.TableRowsInput = document.getElementById("TableRowsInput");
- gDialog.TableColumnsInput = document.getElementById("TableColumnsInput");
- gDialog.TableWidthInput = document.getElementById("TableWidthInput");
- gDialog.TableWidthUnits = document.getElementById("TableWidthUnits");
- gDialog.TableHeightInput = document.getElementById("TableHeightInput");
- gDialog.TableHeightUnits = document.getElementById("TableHeightUnits");
- try {
- if (!Services.prefs.getBoolPref("editor.use_css") || (gActiveEditor.flags & 1))
- {
- gUseCSS = false;
- var tableHeightLabel = document.getElementById("TableHeightLabel");
- tableHeightLabel.remove();
- gDialog.TableHeightInput.remove();
- gDialog.TableHeightUnits.remove();
- }
- } catch (e) {}
- gDialog.BorderWidthInput = document.getElementById("BorderWidthInput");
- gDialog.SpacingInput = document.getElementById("SpacingInput");
- gDialog.PaddingInput = document.getElementById("PaddingInput");
- gDialog.TableAlignList = document.getElementById("TableAlignList");
- gDialog.TableCaptionList = document.getElementById("TableCaptionList");
- gDialog.TableInheritColor = document.getElementById("TableInheritColor");
- gDialog.TabBox = document.getElementById("TabBox");
-
- // Cell Panel
- gDialog.SelectionList = document.getElementById("SelectionList");
- gDialog.PreviousButton = document.getElementById("PreviousButton");
- gDialog.NextButton = document.getElementById("NextButton");
- // Currently, we always apply changes and load new attributes when changing selection
- // (Let's keep this for possible future use)
- //gDialog.ApplyBeforeMove = document.getElementById("ApplyBeforeMove");
- //gDialog.KeepCurrentData = document.getElementById("KeepCurrentData");
-
- gDialog.CellHeightInput = document.getElementById("CellHeightInput");
- gDialog.CellHeightUnits = document.getElementById("CellHeightUnits");
- gDialog.CellWidthInput = document.getElementById("CellWidthInput");
- gDialog.CellWidthUnits = document.getElementById("CellWidthUnits");
- gDialog.CellHAlignList = document.getElementById("CellHAlignList");
- gDialog.CellVAlignList = document.getElementById("CellVAlignList");
- gDialog.CellInheritColor = document.getElementById("CellInheritColor");
- gDialog.CellStyleList = document.getElementById("CellStyleList");
- gDialog.TextWrapList = document.getElementById("TextWrapList");
-
- // In cell panel, user must tell us which attributes to apply via checkboxes,
- // else we would apply values from one cell to ALL in selection
- // and that's probably not what they expect!
- gDialog.CellHeightCheckbox = document.getElementById("CellHeightCheckbox");
- gDialog.CellWidthCheckbox = document.getElementById("CellWidthCheckbox");
- gDialog.CellHAlignCheckbox = document.getElementById("CellHAlignCheckbox");
- gDialog.CellVAlignCheckbox = document.getElementById("CellVAlignCheckbox");
- gDialog.CellStyleCheckbox = document.getElementById("CellStyleCheckbox");
- gDialog.TextWrapCheckbox = document.getElementById("TextWrapCheckbox");
- gDialog.CellColorCheckbox = document.getElementById("CellColorCheckbox");
- gDialog.TableTab = document.getElementById("TableTab");
- gDialog.CellTab = document.getElementById("CellTab");
- gDialog.AdvancedEditCell = document.getElementById("AdvancedEditButton2");
- // Save "normal" tooltip message for Advanced Edit button
- gDialog.AdvancedEditCellToolTipText = gDialog.AdvancedEditCell.getAttribute("tooltiptext");
-
- try {
- gTableElement = gActiveEditor.getElementOrParentByTagName("table", null);
- } catch (e) {}
- if(!gTableElement)
- {
- dump("Failed to get table element!\n");
- window.close();
- return;
- }
- globalTableElement = gTableElement.cloneNode(false);
-
- var tagNameObj = { value: "" };
- var countObj = { value : 0 };
- var tableOrCellElement;
- try {
- tableOrCellElement = gActiveEditor.getSelectedOrParentTableElement(tagNameObj, countObj);
- } catch (e) {}
-
- if (tagNameObj.value == "td")
- {
- // We are in a cell
- gSelectedCellCount = countObj.value;
- gCellElement = tableOrCellElement;
- globalCellElement = gCellElement.cloneNode(false);
-
- // Tells us whether cell, row, or column is selected
- try {
- gSelectedCellsType = gActiveEditor.getSelectedCellsType(gTableElement);
- } catch (e) {}
-
- // Ignore types except Cell, Row, and Column
- if (gSelectedCellsType < SELECT_CELL || gSelectedCellsType > SELECT_COLUMN)
- gSelectedCellsType = SELECT_CELL;
-
- // Be sure at least 1 cell is selected.
- // (If the count is 0, then we were inside the cell.)
- if (gSelectedCellCount == 0)
- DoCellSelection();
-
- // Get location in the cell map
- var rowIndexObj = { value: 0 };
- var colIndexObj = { value: 0 };
- try {
- gActiveEditor.getCellIndexes(gCellElement, rowIndexObj, colIndexObj);
- } catch (e) {}
- gCurRowIndex = rowIndexObj.value;
- gCurColIndex = colIndexObj.value;
-
- // We save the current colspan to quickly
- // move selection from from cell to cell
- if (GetCellData(gCurRowIndex, gCurColIndex))
- gCurColSpan = gCellData.colSpan;
-
- // Starting TabPanel name is passed in
- if (window.arguments[1] == "CellPanel")
- gDialog.TabBox.selectedTab = gDialog.CellTab;
- }
-
- if (gDialog.TabBox.selectedTab == gDialog.TableTab)
- {
- // We may call this with table selected, but no cell,
- // so disable the Cell Properties tab
- if(!gCellElement)
- {
- // XXX: Disabling of tabs is currently broken, so for
- // now we'll just remove the tab completely.
- //gDialog.CellTab.disabled = true;
- gDialog.CellTab.remove();
- }
- }
-
- // Note: we must use gTableElement, not globalTableElement for these,
- // thus we should not put this in InitDialog.
- // Instead, monitor desired counts with separate globals
- var rowCountObj = { value: 0 };
- var colCountObj = { value: 0 };
- try {
- gActiveEditor.getTableSize(gTableElement, rowCountObj, colCountObj);
- } catch (e) {}
-
- gRowCount = rowCountObj.value;
- gLastRowIndex = gRowCount-1;
- gColCount = colCountObj.value;
- gLastColIndex = gColCount-1;
-
-
- // Set appropriate icons and enable state for the Previous/Next buttons
- SetSelectionButtons();
-
- // If only one cell in table, disable change-selection widgets
- if (gRowCount == 1 && gColCount == 1)
- gDialog.SelectionList.setAttribute("disabled", "true");
-
- // User can change these via textboxes
- gNewRowCount = gRowCount;
- gNewColCount = gColCount;
-
- // This flag is used to control whether set check state
- // on "set attribute" checkboxes
- // (Advanced Edit dialog use calls InitDialog when done)
- gAdvancedEditUsed = false;
- InitDialog();
- gAdvancedEditUsed = true;
-
- // If first initializing, we really aren't changing anything
- gCellDataChanged = false;
-
- SetWindowLocation();
-}
-
-
-function InitDialog()
-{
- // Get Table attributes
- gDialog.TableRowsInput.value = gRowCount;
- gDialog.TableColumnsInput.value = gColCount;
- gDialog.TableWidthInput.value = InitPixelOrPercentMenulist(globalTableElement, gTableElement, "width", "TableWidthUnits", gPercent);
- if (gUseCSS) {
- gDialog.TableHeightInput.value = InitPixelOrPercentMenulist(globalTableElement, gTableElement, "height",
- "TableHeightUnits", gPercent);
- }
- gDialog.BorderWidthInput.value = globalTableElement.border;
- gDialog.SpacingInput.value = globalTableElement.cellSpacing;
- gDialog.PaddingInput.value = globalTableElement.cellPadding;
-
- var marginLeft = GetHTMLOrCSSStyleValue(globalTableElement, "align", "margin-left");
- var marginRight = GetHTMLOrCSSStyleValue(globalTableElement, "align", "margin-right");
- var halign = marginLeft.toLowerCase() + " " + marginRight.toLowerCase();
- if (halign == "center center" || halign == "auto auto")
- gDialog.TableAlignList.value = "center";
- else if (halign == "right right" || halign == "auto 0px")
- gDialog.TableAlignList.value = "right";
- else // Default = left
- gDialog.TableAlignList.value = "left";
-
- // Be sure to get caption from table in doc, not the copied "globalTableElement"
- gTableCaptionElement = gTableElement.caption;
- if (gTableCaptionElement)
- {
- var align = GetHTMLOrCSSStyleValue(gTableCaptionElement, "align", "caption-side");
- if (align != "bottom" && align != "left" && align != "right")
- align = "top";
- gDialog.TableCaptionList.value = align;
- }
-
- gTableColor = GetHTMLOrCSSStyleValue(globalTableElement, bgcolor, cssBackgroundColorStr);
- gTableColor = ConvertRGBColorIntoHEXColor(gTableColor);
- SetColor("tableBackgroundCW", gTableColor);
-
- InitCellPanel();
-}
-
-function InitCellPanel()
-{
- // Get cell attributes
- if (globalCellElement)
- {
- // This assumes order of items is Cell, Row, Column
- gDialog.SelectionList.value = gSelectedCellsType;
-
- var previousValue = gDialog.CellHeightInput.value;
- gDialog.CellHeightInput.value = InitPixelOrPercentMenulist(globalCellElement, gCellElement, "height", "CellHeightUnits", gPixel);
- gDialog.CellHeightCheckbox.checked = gAdvancedEditUsed && previousValue != gDialog.CellHeightInput.value;
-
- previousValue= gDialog.CellWidthInput.value;
- gDialog.CellWidthInput.value = InitPixelOrPercentMenulist(globalCellElement, gCellElement, "width", "CellWidthUnits", gPixel);
- gDialog.CellWidthCheckbox.checked = gAdvancedEditUsed && previousValue != gDialog.CellWidthInput.value;
-
- var previousIndex = gDialog.CellVAlignList.selectedIndex;
- var valign = GetHTMLOrCSSStyleValue(globalCellElement, "valign", "vertical-align").toLowerCase();
- if (valign == topStr || valign == bottomStr)
- gDialog.CellVAlignList.value = valign;
- else // Default = middle
- gDialog.CellVAlignList.value = defVAlign;
-
- gDialog.CellVAlignCheckbox.checked = gAdvancedEditUsed && previousIndex != gDialog.CellVAlignList.selectedIndex;
-
- previousIndex = gDialog.CellHAlignList.selectedIndex;
-
- gAlignWasChar = false;
-
- var halign = GetHTMLOrCSSStyleValue(globalCellElement, "align", "text-align").toLowerCase();
- switch (halign)
- {
- case centerStr:
- case rightStr:
- case justifyStr:
- gDialog.CellHAlignList.value = halign;
- break;
- case charStr:
- // We don't support UI for this because layout doesn't work: bug 2212.
- // Remember that's what they had so we don't change it
- // unless they change the alignment by using the menulist
- gAlignWasChar = true;
- // Fall through to use show default alignment in menu
- default:
- // Default depends on cell type (TH is "center", TD is "left")
- gDialog.CellHAlignList.value =
- (globalCellElement.nodeName.toLowerCase() == "th") ? "center" : "left";
- break;
- }
-
- gDialog.CellHAlignCheckbox.checked = gAdvancedEditUsed &&
- previousIndex != gDialog.CellHAlignList.selectedIndex;
-
- previousIndex = gDialog.CellStyleList.selectedIndex;
- gDialog.CellStyleList.value = globalCellElement.nodeName.toLowerCase();
- gDialog.CellStyleCheckbox.checked = gAdvancedEditUsed && previousIndex != gDialog.CellStyleList.selectedIndex;
-
- previousIndex = gDialog.TextWrapList.selectedIndex;
- if (GetHTMLOrCSSStyleValue(globalCellElement, "nowrap", "white-space") == "nowrap")
- gDialog.TextWrapList.value = "nowrap";
- else
- gDialog.TextWrapList.value = "wrap";
- gDialog.TextWrapCheckbox.checked = gAdvancedEditUsed && previousIndex != gDialog.TextWrapList.selectedIndex;
-
- previousValue = gCellColor;
- gCellColor = GetHTMLOrCSSStyleValue(globalCellElement, bgcolor, cssBackgroundColorStr);
- gCellColor = ConvertRGBColorIntoHEXColor(gCellColor);
- SetColor("cellBackgroundCW", gCellColor);
- gDialog.CellColorCheckbox.checked = gAdvancedEditUsed && previousValue != gCellColor;
-
- // We want to set this true in case changes came
- // from Advanced Edit dialog session (must assume something changed)
- gCellDataChanged = true;
- }
-}
-
-function GetCellData(rowIndex, colIndex)
-{
- // Get actual rowspan and colspan
- var startRowIndexObj = { value: 0 };
- var startColIndexObj = { value: 0 };
- var rowSpanObj = { value: 0 };
- var colSpanObj = { value: 0 };
- var actualRowSpanObj = { value: 0 };
- var actualColSpanObj = { value: 0 };
- var isSelectedObj = { value: false };
-
- try {
- gActiveEditor.getCellDataAt(gTableElement, rowIndex, colIndex,
- gCellData,
- startRowIndexObj, startColIndexObj,
- rowSpanObj, colSpanObj,
- actualRowSpanObj, actualColSpanObj, isSelectedObj);
- // We didn't find a cell
- if (!gCellData.value) return false;
- }
- catch(ex) {
- return false;
- }
-
- gCellData.startRowIndex = startRowIndexObj.value;
- gCellData.startColIndex = startColIndexObj.value;
- gCellData.rowSpan = rowSpanObj.value;
- gCellData.colSpan = colSpanObj.value;
- gCellData.actualRowSpan = actualRowSpanObj.value;
- gCellData.actualColSpan = actualColSpanObj.value;
- gCellData.isSelected = isSelectedObj.value;
- return true;
-}
-
-function SelectCellHAlign()
-{
- SetCheckbox("CellHAlignCheckbox");
- // Once user changes the alignment,
- // we lose their original "CharAt" alignment"
- gAlignWasChar = false;
-}
-
-function GetColorAndUpdate(ColorWellID)
-{
- var colorWell = document.getElementById(ColorWellID);
- if (!colorWell) return;
-
- var colorObj = { Type:"", TableColor:0, CellColor:0, NoDefault:false, Cancel:false, BackgroundColor:0 };
-
- switch( ColorWellID )
- {
- case "tableBackgroundCW":
- colorObj.Type = "Table";
- colorObj.TableColor = gTableColor;
- break;
- case "cellBackgroundCW":
- colorObj.Type = "Cell";
- colorObj.CellColor = gCellColor;
- break;
- }
- window.openDialog("chrome://editor/content/EdColorPicker.xul", "_blank", "chrome,close,titlebar,modal", "", colorObj);
-
- // User canceled the dialog
- if (colorObj.Cancel)
- return;
-
- switch( ColorWellID )
- {
- case "tableBackgroundCW":
- gTableColor = colorObj.BackgroundColor;
- SetColor(ColorWellID, gTableColor);
- break;
- case "cellBackgroundCW":
- gCellColor = colorObj.BackgroundColor;
- SetColor(ColorWellID, gCellColor);
- SetCheckbox('CellColorCheckbox');
- break;
- }
-}
-
-function SetColor(ColorWellID, color)
-{
- // Save the color
- if (ColorWellID == "cellBackgroundCW")
- {
- if (color)
- {
- try {
- gActiveEditor.setAttributeOrEquivalent(globalCellElement, bgcolor,
- color, true);
- } catch(e) {}
- gDialog.CellInheritColor.collapsed = true;
- }
- else
- {
- try {
- gActiveEditor.removeAttributeOrEquivalent(globalCellElement, bgcolor, true);
- } catch(e) {}
- // Reveal addition message explaining "default" color
- gDialog.CellInheritColor.collapsed = false;
- }
- }
- else
- {
- if (color)
- {
- try {
- gActiveEditor.setAttributeOrEquivalent(globalTableElement, bgcolor,
- color, true);
- } catch(e) {}
- gDialog.TableInheritColor.collapsed = true;
- }
- else
- {
- try {
- gActiveEditor.removeAttributeOrEquivalent(globalTableElement, bgcolor, true);
- } catch(e) {}
- gDialog.TableInheritColor.collapsed = false;
- }
- SetCheckbox('CellColorCheckbox');
- }
-
- setColorWell(ColorWellID, color);
-}
-
-function ChangeSelectionToFirstCell()
-{
- if (!GetCellData(0,0))
- {
- dump("Can't find first cell in table!\n");
- return;
- }
- gCellElement = gCellData.value;
- globalCellElement = gCellElement;
-
- gCurRowIndex = 0;
- gCurColIndex = 0;
- ChangeSelection(RESET_SELECTION);
-}
-
-function ChangeSelection(newType)
-{
- newType = Number(newType);
-
- if (gSelectedCellsType == newType)
- return;
-
- if (newType == RESET_SELECTION)
- // Restore selection to existing focus cell
- gSelection.collapse(gCellElement,0);
- else
- gSelectedCellsType = newType;
-
- // Keep the same focus gCellElement, just change the type
- DoCellSelection();
- SetSelectionButtons();
-
- // Note: globalCellElement should still be a clone of gCellElement
-}
-
-function MoveSelection(forward)
-{
- var newRowIndex = gCurRowIndex;
- var newColIndex = gCurColIndex;
- var focusCell;
- var inRow = false;
-
- if (gSelectedCellsType == SELECT_ROW)
- {
- newRowIndex += (forward ? 1 : -1);
-
- // Wrap around if before first or after last row
- if (newRowIndex < 0)
- newRowIndex = gLastRowIndex;
- else if (newRowIndex > gLastRowIndex)
- newRowIndex = 0;
- inRow = true;
-
- // Use first cell in row for focus cell
- newColIndex = 0;
- }
- else
- {
- // Cell or column:
- if (!forward)
- newColIndex--;
-
- if (gSelectedCellsType == SELECT_CELL)
- {
- // Skip to next cell
- if (forward)
- newColIndex += gCurColSpan;
- }
- else // SELECT_COLUMN
- {
- // Use first cell in column for focus cell
- newRowIndex = 0;
-
- // Don't skip by colspan,
- // but find first cell in next cellmap column
- if (forward)
- newColIndex++;
- }
-
- if (newColIndex < 0)
- {
- // Request is before the first cell in column
-
- // Wrap to last cell in column
- newColIndex = gLastColIndex;
-
- if (gSelectedCellsType == SELECT_CELL)
- {
- // If moving by cell, also wrap to previous...
- if (newRowIndex > 0)
- newRowIndex -= 1;
- else
- // ...or the last row
- newRowIndex = gLastRowIndex;
-
- inRow = true;
- }
- }
- else if (newColIndex > gLastColIndex)
- {
- // Request is after the last cell in column
-
- // Wrap to first cell in column
- newColIndex = 0;
-
- if (gSelectedCellsType == SELECT_CELL)
- {
- // If moving by cell, also wrap to next...
- if (newRowIndex < gLastRowIndex)
- newRowIndex++;
- else
- // ...or the first row
- newRowIndex = 0;
-
- inRow = true;
- }
- }
- }
-
- // Get the cell at the new location
- do {
- if (!GetCellData(newRowIndex, newColIndex))
- {
- dump("MoveSelection: CELL NOT FOUND\n");
- return;
- }
- if (inRow)
- {
- if (gCellData.startRowIndex == newRowIndex)
- break;
- else
- // Cell spans from a row above, look for the next cell in row
- newRowIndex += gCellData.actualRowSpan;
- }
- else
- {
- if (gCellData.startColIndex == newColIndex)
- break;
- else
- // Cell spans from a Col above, look for the next cell in column
- newColIndex += gCellData.actualColSpan;
- }
- }
- while(true);
-
- // Save data for current selection before changing
- if (gCellDataChanged) // && gDialog.ApplyBeforeMove.checked)
- {
- if (!ValidateCellData())
- return;
-
- gActiveEditor.beginTransaction();
- // Apply changes to all selected cells
- ApplyCellAttributes();
- gActiveEditor.endTransaction();
-
- SetCloseButton();
- }
-
- // Set cell and other data for new selection
- gCellElement = gCellData.value;
-
- // Save globals for new current cell
- gCurRowIndex = gCellData.startRowIndex;
- gCurColIndex = gCellData.startColIndex;
- gCurColSpan = gCellData.actualColSpan;
-
- // Copy for new global cell
- globalCellElement = gCellElement.cloneNode(false);
-
- // Change the selection
- DoCellSelection();
-
- // Scroll page so new selection is visible
- // Using SELECTION_ANCHOR_REGION makes the upper-left corner of first selected cell
- // the point to bring into view.
- try {
- var selectionController = gActiveEditor.selectionController;
- selectionController.scrollSelectionIntoView(selectionController.SELECTION_NORMAL, selectionController.SELECTION_ANCHOR_REGION, true);
- } catch (e) {}
-
- // Reinitialize dialog using new cell
-// if (!gDialog.KeepCurrentData.checked)
- // Setting this false unchecks all "set attributes" checkboxes
- gAdvancedEditUsed = false;
- InitCellPanel();
- gAdvancedEditUsed = true;
-}
-
-
-function DoCellSelection()
-{
- // Collapse selection into to the focus cell
- // so editor uses that as start cell
- gSelection.collapse(gCellElement, 0);
-
- var tagNameObj = { value: "" };
- var countObj = { value: 0 };
- try {
- switch (gSelectedCellsType)
- {
- case SELECT_CELL:
- gActiveEditor.selectTableCell();
- break
- case SELECT_ROW:
- gActiveEditor.selectTableRow();
- break;
- default:
- gActiveEditor.selectTableColumn();
- break;
- }
- // Get number of cells selected
- var tableOrCellElement = gActiveEditor.getSelectedOrParentTableElement(tagNameObj, countObj);
- } catch (e) {}
-
- if (tagNameObj.value == "td")
- gSelectedCellCount = countObj.value;
- else
- gSelectedCellCount = 0;
-
- // Currently, we can only allow advanced editing on ONE cell element at a time
- // else we ignore CSS, JS, and HTML attributes not already in dialog
- SetElementEnabled(gDialog.AdvancedEditCell, gSelectedCellCount == 1);
-
- gDialog.AdvancedEditCell.setAttribute("tooltiptext",
- gSelectedCellCount > 1 ? GetString("AdvancedEditForCellMsg") :
- gDialog.AdvancedEditCellToolTipText);
-}
-
-function SetSelectionButtons()
-{
- if (gSelectedCellsType == SELECT_ROW)
- {
- // Trigger CSS to set images of up and down arrows
- gDialog.PreviousButton.setAttribute("type","row");
- gDialog.NextButton.setAttribute("type","row");
- }
- else
- {
- // or images of left and right arrows
- gDialog.PreviousButton.setAttribute("type","col");
- gDialog.NextButton.setAttribute("type","col");
- }
- DisableSelectionButtons((gSelectedCellsType == SELECT_ROW && gRowCount == 1) ||
- (gSelectedCellsType == SELECT_COLUMN && gColCount == 1) ||
- (gRowCount == 1 && gColCount == 1));
-}
-
-function DisableSelectionButtons( disable )
-{
- gDialog.PreviousButton.setAttribute("disabled", disable ? "true" : "false");
- gDialog.NextButton.setAttribute("disabled", disable ? "true" : "false");
-}
-
-function SwitchToValidatePanel()
-{
- if (gDialog.TabBox.selectedTab != gValidateTab)
- gDialog.TabBox.selectedTab = gValidateTab;
-}
-
-function SetAlign(listID, defaultValue, element, attName)
-{
- var value = document.getElementById(listID).value;
- if (value == defaultValue)
- {
- try {
- gActiveEditor.removeAttributeOrEquivalent(element, attName, true);
- } catch(e) {}
- }
- else
- {
- try {
- gActiveEditor.setAttributeOrEquivalent(element, attName, value, true);
- } catch(e) {}
- }
-}
-
-function ValidateTableData()
-{
- gValidateTab = gDialog.TableTab;
- gNewRowCount = Number(ValidateNumber(gDialog.TableRowsInput, null, 1, gMaxRows, null, true, true));
- if (gValidationError) return false;
-
- gNewColCount = Number(ValidateNumber(gDialog.TableColumnsInput, null, 1, gMaxColumns, null, true, true));
- if (gValidationError) return false;
-
- // If user is deleting any cells, get confirmation
- // (This is a global to the dialog and we ask only once per dialog session)
- if ( !gCanDelete &&
- (gNewRowCount < gRowCount ||
- gNewColCount < gColCount) )
- {
- if (ConfirmWithTitle(GetString("DeleteTableTitle"),
- GetString("DeleteTableMsg"),
- GetString("DeleteCells")) )
- {
- gCanDelete = true;
- }
- else
- {
- SetTextboxFocus(gNewRowCount < gRowCount ? gDialog.TableRowsInput : gDialog.TableColumnsInput);
- return false;
- }
- }
-
- ValidateNumber(gDialog.TableWidthInput, gDialog.TableWidthUnits,
- 1, gMaxTableSize, globalTableElement, "width");
- if (gValidationError) return false;
-
- if (gUseCSS) {
- ValidateNumber(gDialog.TableHeightInput, gDialog.TableHeightUnits,
- 1, gMaxTableSize, globalTableElement, "height");
- if (gValidationError) return false;
- }
-
- var border = ValidateNumber(gDialog.BorderWidthInput, null, 0, gMaxPixels, globalTableElement, "border");
- // TODO: Deal with "BORDER" without value issue
- if (gValidationError) return false;
-
- ValidateNumber(gDialog.SpacingInput, null, 0, gMaxPixels, globalTableElement, "cellspacing");
- if (gValidationError) return false;
-
- ValidateNumber(gDialog.PaddingInput, null, 0, gMaxPixels, globalTableElement, "cellpadding");
- if (gValidationError) return false;
-
- SetAlign("TableAlignList", defHAlign, globalTableElement, "align");
-
- // Color is set on globalCellElement immediately
- return true;
-}
-
-function ValidateCellData()
-{
-
- gValidateTab = gDialog.CellTab;
-
- if (gDialog.CellHeightCheckbox.checked)
- {
- ValidateNumber(gDialog.CellHeightInput, gDialog.CellHeightUnits,
- 1, gMaxTableSize, globalCellElement, "height");
- if (gValidationError) return false;
- }
-
- if (gDialog.CellWidthCheckbox.checked)
- {
- ValidateNumber(gDialog.CellWidthInput, gDialog.CellWidthUnits,
- 1, gMaxTableSize, globalCellElement, "width");
- if (gValidationError) return false;
- }
-
- if (gDialog.CellHAlignCheckbox.checked)
- {
- var hAlign = gDialog.CellHAlignList.value;
-
- // Horizontal alignment is complicated by "char" type
- // We don't change current values if user didn't edit alignment
- if (!gAlignWasChar)
- {
- globalCellElement.removeAttribute(charStr);
-
- // Always set "align" attribute,
- // so the default "left" is effective in a cell
- // when parent row has align set.
- globalCellElement.setAttribute("align", hAlign);
- }
- }
-
- if (gDialog.CellVAlignCheckbox.checked)
- {
- // Always set valign (no default in 2nd param) so
- // the default "middle" is effective in a cell
- // when parent row has valign set.
- SetAlign("CellVAlignList", "", globalCellElement, "valign");
- }
-
- if (gDialog.TextWrapCheckbox.checked)
- {
- if (gDialog.TextWrapList.value == "nowrap")
- try {
- gActiveEditor.setAttributeOrEquivalent(globalCellElement, "nowrap",
- "nowrap", true);
- } catch(e) {}
- else
- try {
- gActiveEditor.removeAttributeOrEquivalent(globalCellElement, "nowrap", true);
- } catch(e) {}
- }
-
- return true;
-}
-
-function ValidateData()
-{
- var result;
-
- // Validate current panel first
- if (gDialog.TabBox.selectedTab == gDialog.TableTab)
- {
- result = ValidateTableData();
- if (result)
- result = ValidateCellData();
- } else {
- result = ValidateCellData();
- if (result)
- result = ValidateTableData();
- }
- if(!result) return false;
-
- // Set global element for AdvancedEdit
- if(gDialog.TabBox.selectedTab == gDialog.TableTab)
- globalElement = globalTableElement;
- else
- globalElement = globalCellElement;
-
- return true;
-}
-
-function ChangeCellTextbox(textboxID)
-{
- // Filter input for just integers
- forceInteger(textboxID);
-
- if (gDialog.TabBox.selectedTab == gDialog.CellTab)
- gCellDataChanged = true;
-}
-
-// Call this when a textbox or menulist is changed
-// so the checkbox is automatically set
-function SetCheckbox(checkboxID)
-{
- if (checkboxID && checkboxID.length > 0)
- {
- // Set associated checkbox
- document.getElementById(checkboxID).checked = true;
- }
- gCellDataChanged = true;
-}
-
-function ChangeIntTextbox(textboxID, checkboxID)
-{
- // Filter input for just integers
- forceInteger(textboxID);
-
- // Set associated checkbox
- SetCheckbox(checkboxID);
-}
-
-function CloneAttribute(destElement, srcElement, attr)
-{
- var value = srcElement.getAttribute(attr);
- // Use editor methods since we are always
- // modifying a table in the document and
- // we need transaction system for undo
- try {
- if (!value || value.length == 0)
- gActiveEditor.removeAttributeOrEquivalent(destElement, attr, false);
- else
- gActiveEditor.setAttributeOrEquivalent(destElement, attr, value, false);
- } catch(e) {}
-}
-
-function ApplyTableAttributes()
-{
- var newAlign = gDialog.TableCaptionList.value;
- if (!newAlign) newAlign = "";
-
- if (gTableCaptionElement)
- {
- // Get current alignment
- var align = GetHTMLOrCSSStyleValue(gTableCaptionElement, "align", "caption-side").toLowerCase();
- // This is the default
- if (!align) align = "top";
-
- if (newAlign == "")
- {
- // Remove existing caption
- try {
- gActiveEditor.deleteNode(gTableCaptionElement);
- } catch(e) {}
- gTableCaptionElement = null;
- }
- else if(newAlign != align)
- {
- try {
- if (newAlign == "top") // This is default, so don't explicitly set it
- gActiveEditor.removeAttributeOrEquivalent(gTableCaptionElement, "align", false);
- else
- gActiveEditor.setAttributeOrEquivalent(gTableCaptionElement, "align", newAlign, false);
- } catch(e) {}
- }
- }
- else if (newAlign != "")
- {
- // Create and insert a caption:
- try {
- gTableCaptionElement = gActiveEditor.createElementWithDefaults("caption");
- } catch (e) {}
- if (gTableCaptionElement)
- {
- if (newAlign != "top")
- gTableCaptionElement.setAttribute("align", newAlign);
-
- // Insert it into the table - caption is always inserted as first child
- try {
- gActiveEditor.insertNode(gTableCaptionElement, gTableElement, 0);
- } catch(e) {}
-
- // Put selecton back where it was
- ChangeSelection(RESET_SELECTION);
- }
- }
-
- var countDelta;
- var foundCell;
- var i;
-
- if (gNewRowCount != gRowCount)
- {
- countDelta = gNewRowCount - gRowCount;
- if (gNewRowCount > gRowCount)
- {
- // Append new rows
- // Find first cell in last row
- if(GetCellData(gLastRowIndex, 0))
- {
- try {
- // Move selection to the last cell
- gSelection.collapse(gCellData.value,0);
- // Insert new rows after it
- gActiveEditor.insertTableRow(countDelta, true);
- gRowCount = gNewRowCount;
- gLastRowIndex = gRowCount - 1;
- // Put selecton back where it was
- ChangeSelection(RESET_SELECTION);
- }
- catch(ex) {
- dump("FAILED TO FIND FIRST CELL IN LAST ROW\n");
- }
- }
- }
- else
- {
- // Delete rows
- if (gCanDelete)
- {
- // Find first cell starting in first row we delete
- var firstDeleteRow = gRowCount + countDelta;
- foundCell = false;
- for ( i = 0; i <= gLastColIndex; i++)
- {
- if (!GetCellData(firstDeleteRow, i))
- break; // We failed to find a cell
-
- if (gCellData.startRowIndex == firstDeleteRow)
- {
- foundCell = true;
- break;
- }
- };
- if (foundCell)
- {
- try {
- // Move selection to the cell we found
- gSelection.collapse(gCellData.value, 0);
- gActiveEditor.deleteTableRow(-countDelta);
- gRowCount = gNewRowCount;
- gLastRowIndex = gRowCount - 1;
- if (gCurRowIndex > gLastRowIndex)
- // We are deleting our selection
- // move it to start of table
- ChangeSelectionToFirstCell()
- else
- // Put selecton back where it was
- ChangeSelection(RESET_SELECTION);
- }
- catch(ex) {
- dump("FAILED TO FIND FIRST CELL IN LAST ROW\n");
- }
- }
- }
- }
- }
-
- if (gNewColCount != gColCount)
- {
- countDelta = gNewColCount - gColCount;
-
- if (gNewColCount > gColCount)
- {
- // Append new columns
- // Find last cell in first column
- if(GetCellData(0, gLastColIndex))
- {
- try {
- // Move selection to the last cell
- gSelection.collapse(gCellData.value,0);
- gActiveEditor.insertTableColumn(countDelta, true);
- gColCount = gNewColCount;
- gLastColIndex = gColCount-1;
- // Restore selection
- ChangeSelection(RESET_SELECTION);
- }
- catch(ex) {
- dump("FAILED TO FIND FIRST CELL IN LAST COLUMN\n");
- }
- }
- }
- else
- {
- // Delete columns
- if (gCanDelete)
- {
- var firstDeleteCol = gColCount + countDelta;
- foundCell = false;
- for ( i = 0; i <= gLastRowIndex; i++)
- {
- // Find first cell starting in first column we delete
- if (!GetCellData(i, firstDeleteCol))
- break; // We failed to find a cell
-
- if (gCellData.startColIndex == firstDeleteCol)
- {
- foundCell = true;
- break;
- }
- };
- if (foundCell)
- {
- try {
- // Move selection to the cell we found
- gSelection.collapse(gCellData.value, 0);
- gActiveEditor.deleteTableColumn(-countDelta);
- gColCount = gNewColCount;
- gLastColIndex = gColCount-1;
- if (gCurColIndex > gLastColIndex)
- ChangeSelectionToFirstCell()
- else
- ChangeSelection(RESET_SELECTION);
- }
- catch(ex) {
- dump("FAILED TO FIND FIRST CELL IN LAST ROW\n");
- }
- }
- }
- }
- }
-
- // Clone all remaining attributes to pick up
- // anything changed by Advanced Edit Dialog
- try {
- gActiveEditor.cloneAttributes(gTableElement, globalTableElement);
- } catch(e) {}
-}
-
-function ApplyCellAttributes()
-{
- var rangeObj = { value: null };
- var selectedCell;
- try {
- selectedCell = gActiveEditor.getFirstSelectedCell(rangeObj);
- } catch(e) {}
-
- if (!selectedCell)
- return;
-
- if (gSelectedCellCount == 1)
- {
- // When only one cell is selected, simply clone entire element,
- // thus CSS and JS from Advanced edit is copied
- try {
- gActiveEditor.cloneAttributes(selectedCell, globalCellElement);
- } catch(e) {}
-
- if (gDialog.CellStyleCheckbox.checked)
- {
- var currentStyleIndex = (selectedCell.nodeName.toLowerCase() == "th") ? 1 : 0;
- if (gDialog.CellStyleList.selectedIndex != currentStyleIndex)
- {
- // Switch cell types
- // (replaces with new cell and copies attributes and contents)
- try {
- selectedCell = gActiveEditor.switchTableCellHeaderType(selectedCell);
- } catch(e) {}
- }
- }
- }
- else
- {
- // Apply changes to all selected cells
- //XXX THIS DOESN'T COPY ADVANCED EDIT CHANGES!
- try {
- while (selectedCell)
- {
- ApplyAttributesToOneCell(selectedCell);
- selectedCell = gActiveEditor.getNextSelectedCell(rangeObj);
- }
- } catch(e) {}
- }
- gCellDataChanged = false;
-}
-
-function ApplyAttributesToOneCell(destElement)
-{
- if (gDialog.CellHeightCheckbox.checked)
- CloneAttribute(destElement, globalCellElement, "height");
-
- if (gDialog.CellWidthCheckbox.checked)
- CloneAttribute(destElement, globalCellElement, "width");
-
- if (gDialog.CellHAlignCheckbox.checked)
- {
- CloneAttribute(destElement, globalCellElement, "align");
- CloneAttribute(destElement, globalCellElement, charStr);
- }
-
- if (gDialog.CellVAlignCheckbox.checked)
- CloneAttribute(destElement, globalCellElement, "valign");
-
- if (gDialog.TextWrapCheckbox.checked)
- CloneAttribute(destElement, globalCellElement, "nowrap");
-
- if (gDialog.CellStyleCheckbox.checked)
- {
- var newStyleIndex = gDialog.CellStyleList.selectedIndex;
- var currentStyleIndex = (destElement.nodeName.toLowerCase() == "th") ? 1 : 0;
-
- if (newStyleIndex != currentStyleIndex)
- {
- // Switch cell types
- // (replaces with new cell and copies attributes and contents)
- try {
- destElement = gActiveEditor.switchTableCellHeaderType(destElement);
- } catch(e) {}
- }
- }
-
- if (gDialog.CellColorCheckbox.checked)
- CloneAttribute(destElement, globalCellElement, "bgcolor");
-}
-
-function SetCloseButton()
-{
- // Change text on "Cancel" button after Apply is used
- if (!gApplyUsed)
- {
- document.documentElement.setAttribute("buttonlabelcancel",
- document.documentElement.getAttribute("buttonlabelclose"));
- gApplyUsed = true;
- }
-}
-
-function Apply()
-{
- if (ValidateData())
- {
- gActiveEditor.beginTransaction();
-
- ApplyTableAttributes();
-
- // We may have just a table, so check for cell element
- if (globalCellElement)
- ApplyCellAttributes();
-
- gActiveEditor.endTransaction();
-
- SetCloseButton();
- return true;
- }
- return false;
-}
-
-function onAccept()
-{
- // Do same as Apply and close window if ValidateData succeeded
- var retVal = Apply();
- if (retVal)
- SaveWindowLocation();
-
- return retVal;
-}
diff --git a/editor/ui/dialogs/content/EdTableProps.xul b/editor/ui/dialogs/content/EdTableProps.xul
deleted file mode 100644
index 126e53eca..000000000
--- a/editor/ui/dialogs/content/EdTableProps.xul
+++ /dev/null
@@ -1,266 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorTableProperties.dtd">
-
-<dialog title="&tableWindow.title;"
- id="tableDlg"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="Startup()"
- buttons="accept,extra1,cancel"
- buttonlabelclose="&closeButton.label;"
- buttonlabelextra1="&applyButton.label;"
- buttonaccesskeyextra1="&applyButton.accesskey;"
- ondialogaccept="return onAccept();"
- ondialogextra1="return Apply();"
- ondialogcancel="return onCancel();">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdTableProps.js"/>
-
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
- <broadcaster id="args" value=""/>
-
- <tabbox id="TabBox">
- <tabs flex="1">
- <tab id="TableTab" label="&tableTab.label;"/>
- <tab id="CellTab" label="&cellTab.label;"/>
- </tabs>
- <tabpanels>
-
- <!-- TABLE PANEL -->
- <vbox>
- <groupbox orient="horizontal"><caption label="&size.label;"/>
- <grid>
- <columns><column/><column/><column/><column/><column/></columns>
- <rows>
- <row align="center">
- <label value="&tableRows.label;" accesskey="&tableRows.accessKey;" control="TableRowsInput"/>
- <textbox class="narrow" id="TableRowsInput" oninput="forceInteger(this.id);"/>
- <spring class="bigspacer"/>
- <label value="&tableHeight.label;" accesskey="&tableHeight.accessKey;"
- id="TableHeightLabel" control="TableHeightInput"/>
- <textbox class="narrow" id="TableHeightInput" oninput="forceInteger(this.id);"/>
- <menulist id="TableHeightUnits"/>
- </row>
- <row align="center">
- <label value="&tableColumns.label;" accesskey="&tableColumns.accessKey;" control="TableColumnsInput"/>
- <textbox class="narrow" id="TableColumnsInput" oninput="forceInteger(this.id);"/>
- <spring class="bigspacer"/>
- <label value="&tableWidth.label;" accesskey="&tableWidth.accessKey;" control="TableWidthInput"/>
- <textbox class="narrow" id="TableWidthInput" oninput="forceInteger(this.id);"/>
- <menulist id="TableWidthUnits"/>
- </row>
- </rows>
- <!-- KEEP GRID LAYOUT here since we will be adding back support for table HEIGHT via CSS -->
- </grid>
- </groupbox>
- <groupbox><caption label="&tableBorderSpacing.label;"/>
- <grid>
- <columns><column/><column/><column/></columns>
- <rows>
- <row align="center">
- <label control="BorderWidthInput"
- value="&tableBorderWidth.label;"
- accesskey="&tableBorderWidth.accessKey;"/>
- <textbox class="narrow" id="BorderWidthInput" oninput="forceInteger(this.id);"/>
- <label align="left" value="&pixels.label;"/>
- </row>
- <row align="center">
- <label control="SpacingInput"
- value="&tableSpacing.label;"
- accesskey="&tableSpacing.accessKey;"/>
- <textbox class="narrow" id="SpacingInput" oninput="forceInteger(this.id);"/>
- <label value="&tablePxBetwCells.label;"/>
- </row>
- <row align="center">
- <label control="PaddingInput"
- value="&tablePadding.label;"
- accesskey="&tablePadding.accessKey;"/>
- <textbox class="narrow" id="PaddingInput" oninput="forceInteger(this.id);"/>
- <label value="&tablePxBetwBrdrCellContent.label;"/>
- </row>
- </rows>
- </grid>
- </groupbox>
- <!-- Table Alignment and Caption -->
- <hbox flex="1" align="center">
- <label control="TableAlignList"
- value="&tableAlignment.label;"
- accesskey="&tableAlignment.accessKey;"/>
- <menulist id="TableAlignList">
- <menupopup>
- <menuitem label="&AlignLeft.label;" value="left"/>
- <menuitem label="&AlignCenter.label;" value="center"/>
- <menuitem label="&AlignRight.label;" value="right"/>
- </menupopup>
- </menulist>
- <spacer class="spacer"/>
- <label control="TableCaptionList"
- value="&tableCaption.label;"
- accesskey="&tableCaption.accessKey;"/>
- <menulist id="TableCaptionList">
- <menupopup>
- <menuitem label="&tableCaptionNone.label;" value=""/>
- <menuitem label="&tableCaptionAbove.label;" value="top"/>
- <menuitem label="&tableCaptionBelow.label;" value="bottom"/>
- <menuitem label="&tableCaptionLeft.label;" value="left"/>
- <menuitem label="&tableCaptionRight.label;" value="right"/>
- </menupopup>
- </menulist>
- </hbox>
- <separator class="groove"/>
- <hbox align="center">
- <label value="&backgroundColor.label;"/>
- <button id="tableBackground" class="color-button" oncommand="GetColorAndUpdate('tableBackgroundCW');">
- <spacer id="tableBackgroundCW" class="color-well"/>
- </button>
- <spacer class="spacer"/>
- <label id="TableInheritColor" value="&tableInheritColor.label;" collapsed="true"/>
- </hbox>
- <separator class="groove"/>
- <hbox flex="1" align="center">
- <spacer flex="1"/>
- <!-- From EdDialogOvlerlay.xul -->
- <button id="AdvancedEditButton"/>
- </hbox>
- <spacer flex="1"/>
- </vbox><!-- Table Panel -->
-
- <!-- CELL PANEL -->
- <vbox>
- <groupbox orient="horizontal" align="center">
- <caption label="&cellSelection.label;"/>
- <vbox>
- <menulist id="SelectionList" oncommand="ChangeSelection(event.target.value)" flex="1">
- <menupopup>
- <!-- JS code assumes order is Cell, Row, Column -->
- <menuitem label="&cellSelectCell.label;" value="1"/>
- <menuitem label="&cellSelectRow.label;" value="2"/>
- <menuitem label="&cellSelectColumn.label;" value="3"/>
- </menupopup>
- </menulist>
- <hbox flex="1">
- <button id="PreviousButton"
- oncommand="MoveSelection(0)"
- flex="1">
- <image/>
- <label value="&cellSelectPrevious.label;"
- accesskey="&cellSelectPrevious.accessKey;"
- control="PreviousButton"/>
- </button>
- <button id="NextButton"
- oncommand="MoveSelection(1)"
- class="align-right"
- flex="1">
- <image/>
- <label value="&cellSelectNext.label;"
- accesskey="&cellSelectNext.accessKey;"
- control="NextButton"/>
- </button>
- </hbox>
- </vbox>
- <spacer class="bigspacer"/>
- <description class="wrap" flex="1">&applyBeforeChange.label;</description>
- </groupbox>
- <hbox align="center">
- <!-- cell size groupbox -->
- <groupbox><caption label="&size.label;"/>
- <grid>
- <columns><column/><column/><column flex="1"/></columns>
- <rows>
- <row align="center">
- <checkbox id="CellHeightCheckbox" label="&tableHeight.label;" accesskey="&tableHeight.accessKey;"/>
- <textbox class="narrow" id="CellHeightInput"
- oninput="ChangeIntTextbox(this.id,'CellHeightCheckbox');"/>
- <menulist id="CellHeightUnits" oncommand="SetCheckbox('CellHeightCheckbox');"/>
- </row>
- <row align="center">
- <checkbox id="CellWidthCheckbox" label="&tableWidth.label;" accesskey="&tableWidth.accessKey;"/>
- <textbox class="narrow" id="CellWidthInput"
- oninput="ChangeIntTextbox(this.id,'CellWidthCheckbox');"/>
- <menulist id="CellWidthUnits" oncommand="SetCheckbox('CellWidthCheckbox');"/>
- </row>
- </rows>
- </grid>
- <spacer class="bigspacer"/>
- </groupbox>
- <!-- Alignment -->
- <groupbox><caption label="&cellContentAlignment.label;"/>
- <grid>
- <columns><column/><column flex="1"/><column/></columns>
- <rows>
- <row align="center">
- <checkbox id="CellVAlignCheckbox" label="&cellVertical.label;" accesskey="&cellVertical.accessKey;"/>
- <menulist id="CellVAlignList" oncommand="SetCheckbox('CellVAlignCheckbox');">
- <menupopup>
- <menuitem label="&cellAlignTop.label;" value="top"/>
- <menuitem label="&cellAlignMiddle.label;" value="middle"/>
- <menuitem label="&cellAlignBottom.label;" value="bottom"/>
- </menupopup>
- </menulist>
- </row>
- <row align="center">
- <checkbox id="CellHAlignCheckbox" label="&cellHorizontal.label;" accesskey="&cellHorizontal.accessKey;"/>
- <menulist id="CellHAlignList" oncommand="SelectCellHAlign()">
- <menupopup>
- <menuitem label="&AlignLeft.label;" value="left"/>
- <menuitem label="&AlignCenter.label;" value="center"/>
- <menuitem label="&AlignRight.label;" value="right"/>
- <menuitem label="&cellAlignJustify.label;" value="justify"/>
- </menupopup>
- </menulist>
- </row>
- </rows>
- </grid>
- </groupbox>
- </hbox>
- <spacer class="spacer"/>
- <hbox align="center">
- <checkbox id="CellStyleCheckbox" label="&cellStyle.label;" accesskey="&cellStyle.accessKey;"/>
- <menulist id="CellStyleList" oncommand="SetCheckbox('CellStyleCheckbox');">
- <menupopup>
- <menuitem label="&cellNormal.label;" value="td"/>
- <menuitem label="&cellHeader.label;" value="th"/>
- </menupopup>
- </menulist>
- <spacer class="bigspacer"/>
- <checkbox id="TextWrapCheckbox" label="&cellTextWrap.label;" accesskey="&cellTextWrap.accessKey;"/>
- <menulist id="TextWrapList" oncommand="SetCheckbox('TextWrapCheckbox');">
- <menupopup>
- <menuitem label="&cellWrap.label;" value="wrap"/>
- <menuitem label="&cellNoWrap.label;" value="nowrap"/>
- </menupopup>
- </menulist>
- </hbox>
- <separator class="groove"/>
- <hbox align="center">
- <checkbox id="CellColorCheckbox" label="&backgroundColor.label;" accesskey="&backgroundColor.accessKey;"/>
- <button class="color-button" oncommand="GetColorAndUpdate('cellBackgroundCW');">
- <spacer id="cellBackgroundCW" class="color-well"/>
- </button>
- <spacer class="spacer"/>
- <label id="CellInheritColor" value="&cellInheritColor.label;" collapsed="true"/>
- </hbox>
- <separator class="groove"/>
- <hbox align="center">
- <description class="wrap" flex="1" style="width: 1em">&cellUseCheckboxHelp.label;</description>
- <!-- From EdDialogOvlerlay.xul -->
- <button id="AdvancedEditButton2"/>
- </hbox>
- <spacer flex="1"/>
- </vbox><!-- Cell Panel -->
- </tabpanels>
- </tabbox>
- <spacer class="spacer"/>
-</dialog>
diff --git a/editor/ui/dialogs/content/EdTextAreaProps.js b/editor/ui/dialogs/content/EdTextAreaProps.js
deleted file mode 100644
index 8e14b93f3..000000000
--- a/editor/ui/dialogs/content/EdTextAreaProps.js
+++ /dev/null
@@ -1,168 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var insertNew;
-var textareaElement;
-
-// dialog initialization code
-
-function Startup()
-{
- var editor = GetCurrentEditor();
- if (!editor)
- {
- dump("Failed to get active editor!\n");
- window.close();
- return;
- }
-
- gDialog = {
- accept: document.documentElement.getButton("accept"),
- textareaName: document.getElementById("TextAreaName"),
- textareaRows: document.getElementById("TextAreaRows"),
- textareaCols: document.getElementById("TextAreaCols"),
- textareaWrap: document.getElementById("TextAreaWrap"),
- textareaReadOnly: document.getElementById("TextAreaReadOnly"),
- textareaDisabled: document.getElementById("TextAreaDisabled"),
- textareaTabIndex: document.getElementById("TextAreaTabIndex"),
- textareaAccessKey: document.getElementById("TextAreaAccessKey"),
- textareaValue: document.getElementById("TextAreaValue"),
- MoreSection: document.getElementById("MoreSection"),
- MoreFewerButton: document.getElementById("MoreFewerButton")
- };
-
- // Get a single selected text area element
- const kTagName = "textarea";
- try {
- textareaElement = editor.getSelectedElement(kTagName);
- } catch (e) {}
-
- if (textareaElement) {
- // We found an element and don't need to insert one
- insertNew = false;
-
- gDialog.textareaValue.value = textareaElement.value;
- }
- else
- {
- insertNew = true;
-
- // We don't have an element selected,
- // so create one with default attributes
- try {
- textareaElement = editor.createElementWithDefaults(kTagName);
- } catch(e) {}
-
- if (!textareaElement)
- {
- dump("Failed to get selected element or create a new one!\n");
- window.close();
- return;
- }
- else
- gDialog.textareaValue.value = GetSelectionAsText();
- }
-
- // Make a copy to use for AdvancedEdit
- globalElement = textareaElement.cloneNode(false);
-
- InitDialog();
-
- InitMoreFewer();
-
- SetTextboxFocus(gDialog.textareaName);
-
- SetWindowLocation();
-}
-
-function InitDialog()
-{
- gDialog.textareaName.value = globalElement.getAttribute("name");
- gDialog.textareaRows.value = globalElement.getAttribute("rows");
- gDialog.textareaCols.value = globalElement.getAttribute("cols");
- gDialog.textareaWrap.value = GetHTMLOrCSSStyleValue(globalElement, "wrap", "white-space");
- gDialog.textareaReadOnly.checked = globalElement.hasAttribute("readonly");
- gDialog.textareaDisabled.checked = globalElement.hasAttribute("disabled");
- gDialog.textareaTabIndex.value = globalElement.getAttribute("tabindex");
- gDialog.textareaAccessKey.value = globalElement.getAttribute("accesskey");
- onInput();
-}
-
-function onInput()
-{
- var disabled = !gDialog.textareaName.value || !gDialog.textareaRows.value || !gDialog.textareaCols.value;
- if (gDialog.accept.disabled != disabled)
- gDialog.accept.disabled = disabled;
-}
-
-function ValidateData()
-{
- var attributes = {
- name: gDialog.textareaName.value,
- rows: gDialog.textareaRows.value,
- cols: gDialog.textareaCols.value,
- wrap: gDialog.textareaWrap.value,
- tabindex: gDialog.textareaTabIndex.value,
- accesskey: gDialog.textareaAccessKey.value
- };
- var flags = {
- readonly: gDialog.textareaReadOnly.checked,
- disabled: gDialog.textareaDisabled.checked
- };
- for (var a in attributes)
- {
- if (attributes[a])
- globalElement.setAttribute(a, attributes[a]);
- else
- globalElement.removeAttribute(a);
- }
- for (var f in flags)
- {
- if (flags[f])
- globalElement.setAttribute(f, "");
- else
- globalElement.removeAttribute(f);
- }
- return true;
-}
-
-function onAccept()
-{
- // All values are valid - copy to actual element in doc or
- // element created to insert
- ValidateData();
-
- var editor = GetCurrentEditor();
-
- editor.beginTransaction();
-
- try {
- editor.cloneAttributes(textareaElement, globalElement);
-
- if (insertNew)
- editor.insertElementAtSelection(textareaElement, true);
-
- // undoably set value
- var initialText = gDialog.textareaValue.value;
- if (initialText != textareaElement.value) {
- editor.setShouldTxnSetSelection(false);
-
- while (textareaElement.hasChildNodes())
- editor.deleteNode(textareaElement.lastChild);
- if (initialText) {
- var textNode = editor.document.createTextNode(initialText);
- editor.insertNode(textNode, textareaElement, 0);
- }
-
- editor.setShouldTxnSetSelection(true);
- }
- } finally {
- editor.endTransaction();
- }
-
- SaveWindowLocation();
-
- return true;
-}
-
diff --git a/editor/ui/dialogs/content/EdTextAreaProps.xul b/editor/ui/dialogs/content/EdTextAreaProps.xul
deleted file mode 100644
index 27fd32470..000000000
--- a/editor/ui/dialogs/content/EdTextAreaProps.xul
+++ /dev/null
@@ -1,103 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://editor/skin/editor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
-
-<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
-
-<!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorTextAreaProperties.dtd">
-<dialog title="&windowTitle.label;"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- onload="Startup();"
- buttons="accept,cancel"
- ondialogaccept="return onAccept();"
- ondialogcancel="return onCancel();">
-
- <!-- Methods common to all editor dialogs -->
- <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
- <script type="application/javascript" src="chrome://editor/content/EdTextAreaProps.js"/>
-
- <broadcaster id="args" value=""/>
- <spacer id="location" offsetY="50" persist="offsetX offsetY"/>
-
- <groupbox><caption label="&Settings.label;"/>
- <grid><columns><column/><column/></columns>
- <rows>
- <row align="center">
- <label control="TextAreaName" value="&TextAreaName.label;" accesskey="&TextAreaName.accessKey;"/>
- <textbox id="TextAreaName" oninput="onInput();"/>
- </row>
- <row align="center">
- <label control="TextAreaRows" value="&TextAreaRows.label;" accesskey="&TextAreaRows.accessKey;"/>
- <hbox>
- <textbox id="TextAreaRows" class="narrow" oninput="forceInteger(this.id);onInput();"/>
- </hbox>
- </row>
- <row align="center">
- <label control="TextAreaCols" value="&TextAreaCols.label;" accesskey="&TextAreaCols.accessKey;"/>
- <hbox>
- <textbox id="TextAreaCols" class="narrow" oninput="forceInteger(this.id);onInput();"/>
- </hbox>
- </row>
- </rows>
- </grid>
- <hbox>
- <button id="MoreFewerButton" oncommand="onMoreFewer();" persist="more"/>
- </hbox>
- <grid id="MoreSection"><columns><column/><column/></columns>
- <rows>
- <row align="center">
- <label control="TextAreaWrap" value="&TextAreaWrap.label;" accesskey="&TextAreaWrap.accessKey;"/>
- <menulist id="TextAreaWrap">
- <menupopup>
- <menuitem label="&WrapDefault.value;"/>
- <menuitem label="&WrapOff.value;" value="off"/>
- <menuseparator/>
- <menuitem label="&WrapSoft.value;" value="soft"/>
- <menuitem label="&WrapHard.value;" value="hard"/>
- <menuseparator/>
- <menuitem label="&WrapPhysical.value;" value="physical"/>
- <menuitem label="&WrapVirtual.value;" value="virtual"/>
- <menuseparator/>
- <menuitem label="normal" value="normal"/>
- <menuitem label="nowrap" value="nowrap"/>
- <menuitem label="pre" value="pre"/>
- </menupopup>
- </menulist>
- </row>
- <row>
- <spacer/>
- <checkbox id="TextAreaReadOnly" label="&TextAreaReadOnly.label;" accesskey="&TextAreaReadOnly.accessKey;"/>
- </row>
- <row>
- <spacer/>
- <checkbox id="TextAreaDisabled" label="&TextAreaDisabled.label;" accesskey="&TextAreaDisabled.accessKey;"/>
- </row>
- <row align="center">
- <label control="TextAreaTabIndex" value="&TextAreaTabIndex.label;" accesskey="&TextAreaTabIndex.accessKey;"/>
- <hbox>
- <textbox id="TextAreaTabIndex" class="narrow" oninput="forceInteger(this.id);"/>
- </hbox>
- </row>
- <row align="center">
- <label control="TextAreaAccessKey" value="&TextAreaAccessKey.label;" accesskey="&TextAreaAccessKey.accessKey;"/>
- <hbox>
- <textbox id="TextAreaAccessKey" class="narrow" maxlength="1"/>
- </hbox>
- </row>
- <row>
- <label control="TextAreaValue" value="&InitialText.label;" accesskey="&InitialText.accessKey;"/>
- </row>
- <textbox id="TextAreaValue" flex="1" multiline="true" rows="5"/>
- </rows>
- </grid>
- </groupbox>
-
- <!-- from EdDialogOverlay -->
- <vbox id="AdvancedEdit"/>
-
-</dialog>
diff --git a/editor/ui/editorUtilities.jsm b/editor/ui/editorUtilities.jsm
deleted file mode 100644
index f8e35b183..000000000
--- a/editor/ui/editorUtilities.jsm
+++ /dev/null
@@ -1,13 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var EXPORTED_SYMBOLS = ["GetNextUntitledValue"];
-
-var sUntitledCount = 1;
-
-function GetNextUntitledValue()
-{
- return sUntitledCount++;
-}
diff --git a/editor/ui/jar.mn b/editor/ui/jar.mn
deleted file mode 100644
index 91aec9909..000000000
--- a/editor/ui/jar.mn
+++ /dev/null
@@ -1,81 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-comm.jar:
-% content editor %content/editor/
-% overlay chrome://communicator/content/tasksOverlay.xul chrome://editor/content/editorTasksOverlay.xul
-% overlay chrome://messenger/content/mailWindowOverlay.xul chrome://editor/content/editorMailOverlay.xul
- content/editor/editor.js (composer/content/editor.js)
- content/editor/editorUtilities.js (composer/content/editorUtilities.js)
- content/editor/ComposerCommands.js (composer/content/ComposerCommands.js)
- content/editor/EditorContent.css (composer/content/EditorContent.css)
- content/editor/editorSmileyOverlay.xul (composer/content/editorSmileyOverlay.xul)
- content/editor/editorNavigatorOverlay.xul (composer/content/editorNavigatorOverlay.xul)
- content/editor/editorMailOverlay.xul (composer/content/editorMailOverlay.xul)
- content/editor/editorTasksOverlay.xul (composer/content/editorTasksOverlay.xul)
- content/editor/editorApplicationOverlay.js (composer/content/editorApplicationOverlay.js)
- content/editor/images/tag-anchor.gif (composer/content/images/tag-anchor.gif)
- content/editor/EdDialogCommon.js (dialogs/content/EdDialogCommon.js)
- content/editor/EdLinkProps.xul (dialogs/content/EdLinkProps.xul)
- content/editor/EdLinkProps.js (dialogs/content/EdLinkProps.js)
- content/editor/EdImageProps.xul (dialogs/content/EdImageProps.xul)
- content/editor/EdImageProps.js (dialogs/content/EdImageProps.js)
- content/editor/EdImageOverlay.xul (dialogs/content/EdImageOverlay.xul)
- content/editor/EdImageOverlay.js (dialogs/content/EdImageOverlay.js)
- content/editor/EdHLineProps.xul (dialogs/content/EdHLineProps.xul)
- content/editor/EdHLineProps.js (dialogs/content/EdHLineProps.js)
- content/editor/EdReplace.xul (dialogs/content/EdReplace.xul)
- content/editor/EdReplace.js (dialogs/content/EdReplace.js)
- content/editor/EdSpellCheck.xul (dialogs/content/EdSpellCheck.xul)
- content/editor/EdSpellCheck.js (dialogs/content/EdSpellCheck.js)
- content/editor/EdDictionary.xul (dialogs/content/EdDictionary.xul)
- content/editor/EdDictionary.js (dialogs/content/EdDictionary.js)
- content/editor/EdNamedAnchorProps.xul (dialogs/content/EdNamedAnchorProps.xul)
- content/editor/EdNamedAnchorProps.js (dialogs/content/EdNamedAnchorProps.js)
- content/editor/EdInsertTOC.xul (dialogs/content/EdInsertTOC.xul)
- content/editor/EdInsertTOC.js (dialogs/content/EdInsertTOC.js)
- content/editor/EdInsertTable.xul (dialogs/content/EdInsertTable.xul)
- content/editor/EdInsertTable.js (dialogs/content/EdInsertTable.js)
- content/editor/EdInsertMath.xul (dialogs/content/EdInsertMath.xul)
- content/editor/EdInsertMath.js (dialogs/content/EdInsertMath.js)
- content/editor/EdTableProps.xul (dialogs/content/EdTableProps.xul)
- content/editor/EdTableProps.js (dialogs/content/EdTableProps.js)
- content/editor/EdFormProps.xul (dialogs/content/EdFormProps.xul)
- content/editor/EdFormProps.js (dialogs/content/EdFormProps.js)
- content/editor/EdInputProps.xul (dialogs/content/EdInputProps.xul)
- content/editor/EdInputProps.js (dialogs/content/EdInputProps.js)
- content/editor/EdInputImage.xul (dialogs/content/EdInputImage.xul)
- content/editor/EdInputImage.js (dialogs/content/EdInputImage.js)
- content/editor/EdTextAreaProps.xul (dialogs/content/EdTextAreaProps.xul)
- content/editor/EdTextAreaProps.js (dialogs/content/EdTextAreaProps.js)
- content/editor/EdSelectProps.xul (dialogs/content/EdSelectProps.xul)
- content/editor/EdSelectProps.js (dialogs/content/EdSelectProps.js)
- content/editor/EdButtonProps.xul (dialogs/content/EdButtonProps.xul)
- content/editor/EdButtonProps.js (dialogs/content/EdButtonProps.js)
- content/editor/EdLabelProps.xul (dialogs/content/EdLabelProps.xul)
- content/editor/EdLabelProps.js (dialogs/content/EdLabelProps.js)
- content/editor/EdFieldSetProps.xul (dialogs/content/EdFieldSetProps.xul)
- content/editor/EdFieldSetProps.js (dialogs/content/EdFieldSetProps.js)
- content/editor/EdInsSrc.xul (dialogs/content/EdInsSrc.xul)
- content/editor/EdInsSrc.js (dialogs/content/EdInsSrc.js)
- content/editor/EdInsertChars.xul (dialogs/content/EdInsertChars.xul)
- content/editor/EdInsertChars.js (dialogs/content/EdInsertChars.js)
- content/editor/EdDialogOverlay.xul (dialogs/content/EdDialogOverlay.xul)
- content/editor/EdAdvancedEdit.xul (dialogs/content/EdAdvancedEdit.xul)
- content/editor/EdAdvancedEdit.js (dialogs/content/EdAdvancedEdit.js)
- content/editor/EdListProps.xul (dialogs/content/EdListProps.xul)
- content/editor/EdListProps.js (dialogs/content/EdListProps.js)
- content/editor/EdPageProps.xul (dialogs/content/EdPageProps.xul)
- content/editor/EdPageProps.js (dialogs/content/EdPageProps.js)
- content/editor/EdColorProps.xul (dialogs/content/EdColorProps.xul)
- content/editor/EdColorProps.js (dialogs/content/EdColorProps.js)
- content/editor/EdColorPicker.xul (dialogs/content/EdColorPicker.xul)
- content/editor/EdColorPicker.js (dialogs/content/EdColorPicker.js)
- content/editor/EdAECSSAttributes.js (dialogs/content/EdAECSSAttributes.js)
- content/editor/EdAEHTMLAttributes.js (dialogs/content/EdAEHTMLAttributes.js)
- content/editor/EdAEJSEAttributes.js (dialogs/content/EdAEJSEAttributes.js)
- content/editor/EdAEAttributes.js (dialogs/content/EdAEAttributes.js)
- content/editor/EdConvertToTable.xul (dialogs/content/EdConvertToTable.xul)
- content/editor/EdConvertToTable.js (dialogs/content/EdConvertToTable.js)
- content/editor/TeXZilla.js (texzilla/content/TeXZilla.js)
diff --git a/editor/ui/locales/en-US/chrome/composer/editor.properties b/editor/ui/locales/en-US/chrome/composer/editor.properties
deleted file mode 100644
index de482771a..000000000
--- a/editor/ui/locales/en-US/chrome/composer/editor.properties
+++ /dev/null
@@ -1,208 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-# LOCALIZATION NOTE FILE: embedded "\n" represent HTML breaks (<br>)
-# Don't translate embedded "\n".
-# Don't translate strings like this: %variable%
-# as they will be replaced using JavaScript
-#
-No=No
-Save=Save
-More=More
-Less=Less
-MoreProperties=More Properties
-FewerProperties=Fewer Properties
-PropertiesAccessKey=P
-None=None
-none=none
-OpenHTMLFile=Open HTML File
-OpenTextFile=Open Text File
-SelectImageFile=Select Image File
-SaveDocument=Save Page
-SaveDocumentAs=Save Page As
-SaveTextAs=Save Text As
-EditMode=Edit Mode
-Preview=Preview
-Publish=Publish
-PublishPage=Publish Page
-DontPublish=Don't Publish
-SavePassword=Use Password Manager to save this password
-CorrectSpelling=(correct spelling)
-NoSuggestedWords=(no suggested words)
-NoMisspelledWord=No misspelled words
-CheckSpellingDone=Completed spell checking.
-CheckSpelling=Check Spelling
-InputError=Error
-Alert=Alert
-CantEditFramesetMsg=Composer cannot edit HTML framesets, or pages with inline frames. For framesets, try editing the page for each frame separately. For pages with iframes, save a copy of the page and remove the <iframe> tag.
-CantEditMimeTypeMsg=This type of page can't be edited.
-CantEditDocumentMsg=This page can't be edited for an unknown reason.
-BeforeClosing=before closing
-BeforePreview=before viewing in the browser
-BeforeValidate=before validating the document
-# LOCALIZATION NOTE (SaveFilePrompt, PublishPrompt): Don't translate %title% and %reason% (this is the reason for asking user to close, such as "before closing")
-SaveFilePrompt=Save changes to "%title%" %reason%?
-PublishPrompt=Save changes to "%title%" %reason%?
-SaveFileFailed=Saving file failed!
-
-# Publishing error strings:
-# LOCALIZATION NOTE Don't translate %dir% or %file% in the Publishing error strings:
-FileNotFound=%file% not found.
-SubdirDoesNotExist=The subdirectory "%dir%" doesn't exist on this site or the filename "%file%" is already in use by another subdirectory.
-FilenameIsSubdir=The filename "%file%" is already in use by another subdirectory.
-ServerNotAvailable=The server is not available. Check your connection and try again later.
-Offline=You are currently offline. Click the icon near the lower-right corner of any window to go online.
-DiskFull=There is not enough disk space available to save the file "%file%."
-NameTooLong=The filename or subdirectory name is too long.
-AccessDenied=You do not have permission to publish to this location.
-UnknownPublishError=Unknown publishing error occurred.
-PublishFailed=Publishing failed.
-PublishCompleted=Publishing completed.
-AllFilesPublished=All files published
-# LOCALIZATION NOTE Don't translate %x% or %total%
-FailedFileMsg=%x% of %total% files failed to publish.
-# End-Publishing error strings
-Prompt=Prompt
-# LOCALIZATION NOTE (PromptFTPUsernamePassword): Don't translate %host%
-PromptFTPUsernamePassword=Enter username and password for FTP server at %host%
-RevertCaption=Revert To Last Saved
-Revert=Revert
-SendPageReason=before sending this page
-Send=Send
-## LOCALIZATION NOTE (PublishProgressCaption, PublishToSite, AbandonChanges): Don't translate %title%
-PublishProgressCaption=Publishing: %title%
-PublishToSite=Publishing to Site: %title%
-AbandonChanges=Abandon unsaved changes to "%title%" and reload page?
-DocumentTitle=Page Title
-NeedDocTitle=Please enter a title for the current page.
-DocTitleHelp=This identifies the page in the window title and bookmarks.
-CancelPublishTitle=Cancel publishing?
-## LOCALIZATION NOTE: "Continue" in this sentence must match the text for
-## the CancelPublishContinue key below
-CancelPublishMessage=Cancelling while publishing is in progress may result in your file(s) being incompletely transferred. Would you like to Continue or Cancel?
-CancelPublishContinue=Continue
-MissingImageError=Please enter or choose an image of type gif, jpg, or png.
-EmptyHREFError=Please choose a location to create a new link.
-LinkText=Link Text
-LinkImage=Link Image
-MixedSelection=[Mixed selection]
-Mixed=(mixed)
-# LOCALIZATION NOTE (NotInstalled): %S is the name of the font
-NotInstalled=%S (not installed)
-EnterLinkText=Enter text to display for the link:
-EnterLinkTextAccessKey=T
-EmptyLinkTextError=Please enter some text for this link.
-EditTextWarning=This will replace existing content.
-#LOCALIZATION NOTE (ValidateNumber):Don't translate: %n% %min% %max%
-ValidateRangeMsg=The number you entered (%n%) is outside of the allowed range.
-ValidateNumberMsg=Please enter a number between %min% and %max%.
-MissingAnchorNameError=Please enter a name for this anchor.
-#LOCALIZATION NOTE (DuplicateAnchorNameError): Don't translate %name%
-DuplicateAnchorNameError="%name%" already exists in this page. Please enter a different name.
-BulletStyle=Bullet Style
-SolidCircle=Solid circle
-OpenCircle=Open circle
-SolidSquare=Solid square
-NumberStyle=Number Style
-Automatic=Automatic
-Style_1=1, 2, 3…
-Style_I=I, II, III…
-Style_i=i, ii, iii…
-Style_A=A, B, C…
-Style_a=a, b, c…
-Pixels=pixels
-Percent=percent
-PercentOfCell=% of cell
-PercentOfWindow=% of window
-PercentOfTable=% of table
-#LOCALIZATION NOTE (untitledTitle): %S is the window #. No plural handling needed.
-untitledTitle=untitled-%S
-untitledDefaultFilename=untitled
-ShowToolbar=Show Toolbar
-HideToolbar=Hide Toolbar
-ImapError=Unable to load image
-ImapCheck=\nPlease select a new location (URL) and try again.
-SaveToUseRelativeUrl=Relative URLs can only be used on pages which have been saved
-NoNamedAnchorsOrHeadings=(No named anchors or headings in this page)
-TextColor=Text Color
-HighlightColor=Highlight Color
-PageColor=Page Background Color
-BlockColor=Block Background Color
-TableColor=Table Background Color
-CellColor=Cell Background Color
-TableOrCellColor=Table or Cell Color
-LinkColor=Link Text Color
-ActiveLinkColor=Active Link Color
-VisitedLinkColor=Visited Link Color
-NoColorError=Click on a color or enter a valid HTML color string
-Table=Table
-TableCell=Table Cell
-NestedTable=Nested Table
-HLine=Horizontal Line
-Link=Link
-Image=Image
-ImageAndLink=Image and Link
-NamedAnchor=Named Anchor
-List=List
-ListItem=List Item
-Form=Form
-InputTag=Form Field
-InputImage=Form Image
-TextArea=Text Area
-Select=Selection List
-Button=Button
-Label=Label
-FieldSet=Field Set
-Tag=Tag
-MissingSiteNameError=Please enter a name for this publishing site.
-MissingPublishUrlError=Please enter a location for publishing this page.
-MissingPublishFilename=Please enter a filename for the current page.
-#LOCALIZATION NOTE (DuplicateSiteNameError): Don't translate %name%
-DuplicateSiteNameError="%name%" already exists. Please enter a different site name.
-AdvancedProperties=Advanced Properties…
-AdvancedEditForCellMsg=Advanced Edit is unavailable when multiple cells are selected
-# LOCALIZATION NOTE (ObjectProperties):Don't translate "%obj%" it will be replaced with one of above object nouns
-ObjectProperties=%obj% Properties…
-# LOCALIZATION NOTE This character must be in the above string and not confict with other accesskeys in Format menu
-ObjectPropertiesAccessKey=o
-# LOCALIZATION NOTE (JoinSelectedCells): This variable should contain the "tableJoinCells.accesskey"
-# letter as defined in editorOverlay.dtd
-JoinSelectedCells=Join Selected Cells
-# LOCALIZATION NOTE (JoinCellToRight): This variable should contain the "tableJoinCells.accesskey"
-# letter as defined in editorOverlay.dtd
-JoinCellToRight=Join with Cell to the Right
-JoinCellAccesskey=j
-# LOCALIZATION NOTE (TableSelectKey): Ctrl key on a keyboard
-TableSelectKey=Ctrl+
-# LOCALIZATION NOTE (XulKeyMac): Command key on a Mac keyboard
-XulKeyMac=Cmd+
-# LOCALIZATION NOTE (Del): Del key on a keyboard
-Del=Del
-Delete=Delete
-DeleteCells=Delete Cells
-DeleteTableTitle=Delete Rows or Columns
-DeleteTableMsg=Reducing the number of rows or columns will delete table cells and their contents. Do you really want to do this?
-Clear=Clear
-#Mouse actions
-Click=Click
-Drag=Drag
-Unknown=Unknown
-#
-# LOCALIZATION NOTE "RemoveTextStylesAccesskey" is used for both
-# menu items: "RemoveTextStyles" and "StopTextStyles"
-RemoveTextStylesAccesskey=x
-RemoveTextStyles=Remove All Text Styles
-StopTextStyles=Discontinue Text Styles
-#
-# LOCALIZATION NOTE "RemoveLinksAccesskey" is used for both
-# menu items: "RemoveLinks" and "StopLinks"
-RemoveLinksAccesskey=n
-RemoveLinks=Remove Links
-StopLinks=Discontinue Link
-#
-NoFormAction=It is recommended that you enter an action for this form. Self-posting forms are an advanced technique that may not work consistently in all browsers.
-NoAltText=If the image is relevant to the content of the document, you must supply alternate text that will appear in text-only browsers, and that will appear in other browsers when an image is loading or when image loading is disabled.
-#
-Malformed=The source could not be converted back into the document because it is not valid XHTML.
-NoLinksToCheck=There are no elements with links to check
diff --git a/editor/ui/locales/en-US/chrome/composer/editorOverlay.dtd b/editor/ui/locales/en-US/chrome/composer/editorOverlay.dtd
deleted file mode 100644
index 9e4f8b065..000000000
--- a/editor/ui/locales/en-US/chrome/composer/editorOverlay.dtd
+++ /dev/null
@@ -1,346 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!-- Attn: Localization - some of the menus in this dialog directly affect mail also. -->
-
-<!-- File menu items -->
-<!ENTITY saveCmd.key "S">
-
-<!-- Edit menu items -->
-<!ENTITY pasteNoFormatting.label "Paste Without Formatting">
-<!ENTITY pasteNoFormatting.accesskey "n">
-<!ENTITY pasteNoFormatting.key "V">
-<!ENTITY pasteAs.label "Paste As">
-<!ENTITY pasteAs.accesskey "a">
-<!ENTITY pasteAsQuotationCmd.label "Paste As Quotation">
-<!ENTITY pasteAsQuotationCmd.accesskey "Q">
-<!ENTITY pasteAsQuotationCmd.key "o">
-<!ENTITY findBarCmd.label "Find…">
-<!ENTITY findReplaceCmd.label "Find and Replace…">
-<!ENTITY enableInlineSpellChecker.label "Spellcheck As You Type">
-<!ENTITY enableInlineSpellChecker.accesskey "S">
-<!ENTITY checkSpellingCmd2.label "Check Spelling…">
-<!ENTITY checkSpellingCmd2.accesskey "h">
-<!ENTITY checkSpellingCmd2.key "p">
-
-<!-- Insert menu items -->
-<!ENTITY insertMenu.label "Insert">
-<!ENTITY insertMenu.accesskey "I">
-<!ENTITY insertLinkCmd2.label "Link…">
-<!ENTITY insertLinkCmd2.accesskey "L">
-<!ENTITY insertLinkCmd2.key "K">
-<!ENTITY insertAnchorCmd.label "Named Anchor…">
-<!ENTITY insertAnchorCmd.accesskey "A">
-<!ENTITY insertImageCmd.label "Image…">
-<!ENTITY insertImageCmd.accesskey "I">
-<!ENTITY insertHLineCmd.label "Horizontal Line">
-<!ENTITY insertHLineCmd.accesskey "o">
-<!ENTITY insertTableCmd.label "Table…">
-<!ENTITY insertTableCmd.accesskey "T">
-<!ENTITY insertHTMLCmd.label "HTML…">
-<!ENTITY insertHTMLCmd.accesskey "H">
-<!ENTITY insertMathCmd.label "Math…">
-<!ENTITY insertMathCmd.accesskey "M">
-<!ENTITY insertCharsCmd.label "Characters and Symbols…">
-<!ENTITY insertCharsCmd.accesskey "C">
-<!ENTITY insertBreakAllCmd.label "Break Below Image(s)">
-<!ENTITY insertBreakAllCmd.accesskey "k">
-
-<!-- Used just in context popup. -->
-<!ENTITY createLinkCmd.label "Create Link…">
-<!ENTITY createLinkCmd.accesskey "k">
-<!ENTITY editLinkCmd.label "Edit Link in New Composer">
-<!ENTITY editLinkCmd.accesskey "i">
-
-<!-- Font Face SubMenu -->
-<!ENTITY FontFaceSelect.tooltip "Choose a font">
-<!ENTITY fontfaceMenu.label "Font">
-<!ENTITY fontfaceMenu.accesskey "F">
-<!ENTITY fontVarWidth.label "Variable Width">
-<!ENTITY fontVarWidth.accesskey "V">
-<!ENTITY fontFixedWidth.label "Fixed Width">
-<!ENTITY fontFixedWidth.accesskey "x">
-<!ENTITY fontFixedWidth.key "T">
-<!ENTITY fontHelvetica.label "Helvetica, Arial">
-<!ENTITY fontHelvetica.accesskey "l">
-<!ENTITY fontTimes.label "Times">
-<!ENTITY fontTimes.accesskey "T">
-<!ENTITY fontCourier.label "Courier">
-<!ENTITY fontCourier.accesskey "C">
-
-<!-- Font Size SubMenu -->
-<!ENTITY FontSizeSelect.tooltip "Choose a font size">
-<!ENTITY decreaseFontSize.label "Smaller">
-<!ENTITY decreaseFontSize.accesskey "r">
-<!ENTITY decrementFontSize.key "&lt;">
-<!ENTITY decrementFontSize.key2 ","> <!-- < is above this key on many keyboards -->
-<!ENTITY increaseFontSize.label "Larger">
-<!ENTITY increaseFontSize.accesskey "g">
-<!ENTITY incrementFontSize.key "&gt;">
-<!ENTITY incrementFontSize.key2 "."> <!-- > is above this key on many keyboards -->
-
-<!ENTITY fontSizeMenu.label "Size">
-<!ENTITY fontSizeMenu.accesskey "z">
-<!ENTITY size-tinyCmd.label "Tiny">
-<!ENTITY size-tinyCmd.accesskey "T">
-<!ENTITY size-smallCmd.label "Small">
-<!ENTITY size-smallCmd.accesskey "S">
-<!ENTITY size-mediumCmd.label "Medium">
-<!ENTITY size-mediumCmd.accesskey "M">
-<!ENTITY size-largeCmd.label "Large">
-<!ENTITY size-largeCmd.accesskey "L">
-<!ENTITY size-extraLargeCmd.label "Extra Large">
-<!ENTITY size-extraLargeCmd.accesskey "x">
-<!ENTITY size-hugeCmd.label "Huge">
-<!ENTITY size-hugeCmd.accesskey "H">
-
-<!-- Font Style SubMenu -->
-<!ENTITY fontStyleMenu.label "Text Style">
-<!ENTITY fontStyleMenu.accesskey "S">
-<!ENTITY styleBoldCmd.label "Bold">
-<!ENTITY styleBoldCmd.accesskey "B">
-<!ENTITY styleBoldCmd.key "B">
-<!ENTITY styleItalicCmd.label "Italic">
-<!ENTITY styleItalicCmd.accesskey "I">
-<!ENTITY styleItalicCmd.key "I">
-<!ENTITY styleUnderlineCmd.label "Underline">
-<!ENTITY styleUnderlineCmd.accesskey "U">
-<!ENTITY styleUnderlineCmd.key "U">
-<!ENTITY styleStrikeThruCmd.label "Strikethrough">
-<!ENTITY styleStrikeThruCmd.accesskey "k">
-<!ENTITY styleSuperscriptCmd.label "Superscript">
-<!ENTITY styleSuperscriptCmd.accesskey "p">
-<!ENTITY styleSubscriptCmd.label "Subscript">
-<!ENTITY styleSubscriptCmd.accesskey "S">
-<!ENTITY styleNonbreakingCmd.label "Nonbreaking">
-<!ENTITY styleNonbreakingCmd.accesskey "N">
-<!ENTITY styleEm.label "Emphasis">
-<!ENTITY styleEm.accesskey "E">
-<!ENTITY styleStrong.label "Stronger Emphasis">
-<!ENTITY styleStrong.accesskey "t">
-<!ENTITY styleCite.label "Citation">
-<!ENTITY styleCite.accesskey "C">
-<!ENTITY styleAbbr.label "Abbreviation">
-<!ENTITY styleAbbr.accesskey "A">
-<!ENTITY styleAcronym.label "Acronym">
-<!ENTITY styleAcronym.accesskey "r">
-<!ENTITY styleCode.label "Code">
-<!ENTITY styleCode.accesskey "o">
-<!ENTITY styleSamp.label "Sample Output">
-<!ENTITY styleSamp.accesskey "m">
-<!ENTITY styleVar.label "Variable">
-<!ENTITY styleVar.accesskey "V">
-
-<!ENTITY formatFontColor.label "Text Color…">
-<!ENTITY formatFontColor.accesskey "C">
-<!ENTITY tableOrCellColor.label "Table or Cell Background Color…">
-<!ENTITY tableOrCellColor.accesskey "B">
-
-<!ENTITY formatRemoveStyles.key "Y">
-<!ENTITY formatRemoveLinks.key "K">
-<!ENTITY formatRemoveNamedAnchors.label "Remove Named Anchors">
-<!ENTITY formatRemoveNamedAnchors.accesskey "R">
-<!ENTITY formatRemoveNamedAnchors2.key "R">
-
-<!ENTITY paragraphMenu.label "Paragraph">
-<!ENTITY paragraphMenu.accesskey "P">
-<!ENTITY paragraphParagraphCmd.label "Paragraph">
-<!ENTITY paragraphParagraphCmd.accesskey "P">
-<!ENTITY heading1Cmd.label "Heading 1">
-<!ENTITY heading1Cmd.accesskey "1">
-<!ENTITY heading2Cmd.label "Heading 2">
-<!ENTITY heading2Cmd.accesskey "2">
-<!ENTITY heading3Cmd.label "Heading 3">
-<!ENTITY heading3Cmd.accesskey "3">
-<!ENTITY heading4Cmd.label "Heading 4">
-<!ENTITY heading4Cmd.accesskey "4">
-<!ENTITY heading5Cmd.label "Heading 5">
-<!ENTITY heading5Cmd.accesskey "5">
-<!ENTITY heading6Cmd.label "Heading 6">
-<!ENTITY heading6Cmd.accesskey "6">
-<!ENTITY paragraphAddressCmd.label "Address">
-<!ENTITY paragraphAddressCmd.accesskey "A">
-<!ENTITY paragraphPreformatCmd.label "Preformat">
-<!ENTITY paragraphPreformatCmd.accesskey "f">
-
-<!-- List menu items -->
-<!ENTITY formatlistMenu.label "List">
-<!ENTITY formatlistMenu.accesskey "L">
-<!ENTITY noneCmd.label "None">
-<!ENTITY noneCmd.accesskey "N">
-<!ENTITY listBulletCmd.label "Bulleted">
-<!ENTITY listBulletCmd.accesskey "B">
-<!ENTITY listNumberedCmd.label "Numbered">
-<!ENTITY listNumberedCmd.accesskey "m">
-<!ENTITY listTermCmd.label "Term">
-<!ENTITY listTermCmd.accesskey "T">
-<!ENTITY listDefinitionCmd.label "Definition">
-<!ENTITY listDefinitionCmd.accesskey "D">
-<!ENTITY listPropsCmd.label "List Properties…">
-<!ENTITY listPropsCmd.accesskey "L">
-
-<!ENTITY ParagraphSelect.tooltip "Choose a paragraph format">
-<!-- Shared in Paragraph, and Toolbar menulist -->
-<!ENTITY bodyTextCmd.label "Body Text">
-<!ENTITY bodyTextCmd.accesskey "T">
-<!-- isn't used in menu now, but may be added in future -->
-<!ENTITY advancedPropertiesCmd.label "Advanced Properties">
-<!ENTITY advancedPropertiesCmd.accesskey "v">
-
-<!-- Align menu items -->
-<!ENTITY alignMenu.label "Align">
-<!ENTITY alignMenu.accesskey "A">
-<!ENTITY alignLeft.label "Left">
-<!ENTITY alignLeft.accesskey "L">
-<!ENTITY alignLeft.tooltip "Align Left">
-<!ENTITY alignCenter.label "Center">
-<!ENTITY alignCenter.accesskey "C">
-<!ENTITY alignCenter.tooltip "Align Center">
-<!ENTITY alignRight.label "Right">
-<!ENTITY alignRight.accesskey "R">
-<!ENTITY alignRight.tooltip "Align Right">
-<!ENTITY alignJustify.label "Justify">
-<!ENTITY alignJustify.accesskey "J">
-<!ENTITY alignJustify.tooltip "Align Justified">
-
-<!-- Layer toolbar items -->
-<!ENTITY layer.tooltip "Layer">
-<!ENTITY layerSendToBack.tooltip "Send to Back">
-<!ENTITY layerBringToFront.tooltip "Bring to Front">
-
-<!ENTITY increaseIndent.label "Increase Indent">
-<!ENTITY increaseIndent.accesskey "I">
-<!ENTITY increaseIndent.key "]">
-<!ENTITY decreaseIndent.label "Decrease Indent">
-<!ENTITY decreaseIndent.accesskey "D">
-<!ENTITY decreaseIndent.key "[">
-
-<!ENTITY colorsAndBackground.label "Page Colors and Background…">
-<!ENTITY colorsAndBackground.accesskey "u">
-
-<!-- Table Menu -->
-<!ENTITY tableMenu.label "Table">
-<!ENTITY tableMenu.accesskey "b">
-
-<!-- Select Submenu -->
-<!ENTITY tableSelectMenu.label "Select">
-<!ENTITY tableSelectMenu.accesskey "S">
-
-<!ENTITY tableSelectMenu2.label "Table Select">
-<!ENTITY tableSelectMenu2.accesskey "S">
-<!ENTITY tableInsertMenu2.label "Table Insert">
-<!ENTITY tableInsertMenu2.accesskey "I">
-<!ENTITY tableDeleteMenu2.label "Table Delete">
-<!ENTITY tableDeleteMenu2.accesskey "D">
-
-<!-- Insert SubMenu -->
-<!ENTITY tableInsertMenu.label "Insert">
-<!ENTITY tableInsertMenu.accesskey "I">
-<!ENTITY tableTable.label "Table">
-<!ENTITY tableTable.accesskey "T">
-<!ENTITY tableRow.label "Row">
-<!ENTITY tableRows.label "Row(s)">
-<!ENTITY tableRow.accesskey "R">
-<!ENTITY tableRowAbove.label "Row Above">
-<!ENTITY tableRowAbove.accesskey "R">
-<!ENTITY tableRowBelow.label "Row Below">
-<!ENTITY tableRowBelow.accesskey "B">
-<!ENTITY tableColumn.label "Column">
-<!ENTITY tableColumns.label "Column(s)">
-<!ENTITY tableColumn.accesskey "o">
-<!ENTITY tableColumnBefore.label "Column Before">
-<!ENTITY tableColumnBefore.accesskey "o">
-<!ENTITY tableColumnAfter.label "Column After">
-<!ENTITY tableColumnAfter.accesskey "A">
-<!ENTITY tableCell.label "Cell">
-<!ENTITY tableCells.label "Cell(s)">
-<!ENTITY tableCell.accesskey "C">
-<!ENTITY tableCellContents.label "Cell Contents">
-<!ENTITY tableCellContents.accesskey "n">
-<!ENTITY tableAllCells.label "All Cells">
-<!ENTITY tableAllCells.accesskey "A">
-<!ENTITY tableCellBefore.label "Cell Before">
-<!ENTITY tableCellBefore.accesskey "C">
-<!ENTITY tableCellAfter.label "Cell After">
-<!ENTITY tableCellAfter.accesskey "f">
-<!-- Delete SubMenu -->
-<!ENTITY tableDeleteMenu.label "Delete">
-<!ENTITY tableDeleteMenu.accesskey "D">
-
-<!-- text for "Join Cells" is in editor.properties
- ("JoinSelectedCells" and "JoinCellToRight")
- the access key must exist in both of those strings
- But value must be set here for accesskey to draw properly
--->
-<!ENTITY tableJoinCells.label "j">
-<!ENTITY tableJoinCells.accesskey "j">
-<!ENTITY tableSplitCell.label "Split Cell">
-<!ENTITY tableSplitCell.accesskey "C">
-<!ENTITY convertToTable.label "Create Table from Selection">
-<!ENTITY convertToTable.accesskey "r">
-<!ENTITY tableProperties.label "Table Properties…">
-<!ENTITY tableProperties.accesskey "o">
-
-<!-- Toolbar-only items -->
-<!ENTITY menuBar.tooltip "Menu Bar">
-<!ENTITY formatToolbar.tooltip "Formatting Toolbar">
-<!ENTITY cutToolbarCmd.tooltip "Cut">
-<!ENTITY copyToolbarCmd.tooltip "Copy">
-<!ENTITY pasteToolbarCmd.tooltip "Paste">
-<!ENTITY printToolbarCmd.label "Print">
-<!ENTITY printToolbarCmd.tooltip "Print this page">
-<!ENTITY findToolbarCmd.label "Find">
-<!ENTITY findToolbarCmd.tooltip "Find text in page">
-<!ENTITY spellToolbarCmd.label "Spell">
-<!ENTITY spellToolbarCmd.tooltip "Check spelling of selection or entire page">
-<!ENTITY imageToolbarCmd.label "Image">
-<!ENTITY imageToolbarCmd.tooltip "Insert new image or edit selected image's properties">
-<!ENTITY hruleToolbarCmd.label "H.Line">
-<!ENTITY hruleToolbarCmd.tooltip "Insert horizontal line or edit selected line's properties">
-<!ENTITY tableToolbarCmd.label "Table">
-<!ENTITY tableToolbarCmd.tooltip "Insert new table or edit selected table's properties">
-<!ENTITY linkToolbarCmd.label "Link">
-<!ENTITY linkToolbarCmd.tooltip "Insert new link or edit selected link's properties">
-<!ENTITY anchorToolbarCmd.label "Anchor">
-<!ENTITY anchorToolbarCmd.tooltip "Insert new named anchor or edit selected anchor's properties">
-<!ENTITY TextColorButton.tooltip "Choose color for text">
-<!ENTITY BackgroundColorButton.tooltip "Choose color for background">
-<!ENTITY throbber.tooltip "Go to the &vendorShortName; home page">
-<!ENTITY HighlightColorButton.tooltip "Choose highlight color for text">
-
-<!-- Editor toolbar -->
-<!ENTITY absoluteFontSizeToolbarCmd.tooltip "Set font size">
-<!ENTITY decreaseFontSizeToolbarCmd.tooltip "Smaller font size">
-<!ENTITY increaseFontSizeToolbarCmd.tooltip "Larger font size">
-<!ENTITY boldToolbarCmd.tooltip "Bold">
-<!ENTITY italicToolbarCmd.tooltip "Italic">
-<!ENTITY underlineToolbarCmd.tooltip "Underline">
-<!ENTITY bulletListToolbarCmd.tooltip "Apply or remove bulleted list">
-<!ENTITY numberListToolbarCmd.tooltip "Apply or remove numbered list">
-<!ENTITY outdentToolbarCmd.tooltip "Outdent text (move left)">
-<!ENTITY indentToolbarCmd.tooltip "Indent text (move right)">
-<!ENTITY AlignPopupButton.tooltip "Choose text alignment">
-<!ENTITY InsertPopupButton.tooltip "Insert a Link, Anchor, Image, Horizontal Line, or Table">
-<!ENTITY alignLeftButton.tooltip "Align text along left margin">
-<!ENTITY alignCenterButton.tooltip "Align text centered">
-<!ENTITY alignRightButton.tooltip "Align text along right margin">
-<!ENTITY alignJustifyButton.tooltip "Align text along left and right margins">
-
-<!-- Structure Toolbar Context Menu items -->
-<!ENTITY structSelect.label "Select">
-<!ENTITY structSelect.accesskey "s">
-<!ENTITY structRemoveTag.label "Remove tag">
-<!ENTITY structRemoveTag.accesskey "r">
-<!ENTITY structChangeTag.label "Change tag">
-<!ENTITY structChangeTag.accesskey "c">
-
-<!-- TOC manipulation -->
-<!ENTITY insertTOC.label "Insert">
-<!ENTITY insertTOC.accesskey "i">
-<!ENTITY updateTOC.label "Update">
-<!ENTITY updateTOC.accesskey "u">
-<!ENTITY removeTOC.label "Remove">
-<!ENTITY removeTOC.accesskey "r">
-<!ENTITY tocMenu.label "Table of Contents…">
-<!ENTITY tocMenu.accesskey "b">
diff --git a/editor/ui/locales/en-US/chrome/composer/editorSmileyOverlay.dtd b/editor/ui/locales/en-US/chrome/composer/editorSmileyOverlay.dtd
deleted file mode 100644
index 74c3269d7..000000000
--- a/editor/ui/locales/en-US/chrome/composer/editorSmileyOverlay.dtd
+++ /dev/null
@@ -1,58 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!-- Smiley Menu items -->
-<!ENTITY insertSmiley.label "Smiley">
-<!ENTITY insertSmiley.accesskey "S">
-
-<!ENTITY smiley1Cmd.label "Smile">
-<!ENTITY smiley1Cmd.accesskey "S">
-<!ENTITY smiley1Cmd.tooltip "Insert a smiley face">
-<!ENTITY smiley2Cmd.label "Frown">
-<!ENTITY smiley2Cmd.accesskey "F">
-<!ENTITY smiley2Cmd.tooltip "Insert a frown face">
-<!ENTITY smiley3Cmd.label "Wink">
-<!ENTITY smiley3Cmd.accesskey "W">
-<!ENTITY smiley3Cmd.tooltip "Insert a wink face">
-<!ENTITY smiley4Cmd.label "Tongue-out">
-<!ENTITY smiley4Cmd.accesskey "T">
-<!ENTITY smiley4Cmd.tooltip "Insert a tongue-out face">
-<!ENTITY smiley5Cmd.label "Laughing">
-<!ENTITY smiley5Cmd.accesskey "L">
-<!ENTITY smiley5Cmd.tooltip "Insert a laughing face">
-<!ENTITY smiley6Cmd.label "Embarrassed">
-<!ENTITY smiley6Cmd.accesskey "E">
-<!ENTITY smiley6Cmd.tooltip "Insert an embarrassed face">
-<!ENTITY smiley7Cmd.label "Undecided">
-<!ENTITY smiley7Cmd.accesskey "U">
-<!ENTITY smiley7Cmd.tooltip "Insert an undecided face">
-<!ENTITY smiley8Cmd.label "Surprise">
-<!ENTITY smiley8Cmd.accesskey "p">
-<!ENTITY smiley8Cmd.tooltip "Insert a surprised face">
-<!ENTITY smiley9Cmd.label "Kiss">
-<!ENTITY smiley9Cmd.accesskey "K">
-<!ENTITY smiley9Cmd.tooltip "Insert a kiss face">
-<!ENTITY smiley10Cmd.label "Yell">
-<!ENTITY smiley10Cmd.accesskey "Y">
-<!ENTITY smiley10Cmd.tooltip "Insert a yelling face">
-<!ENTITY smiley11Cmd.label "Cool">
-<!ENTITY smiley11Cmd.accesskey "C">
-<!ENTITY smiley11Cmd.tooltip "Insert a cool face">
-<!ENTITY smiley12Cmd.label "Money-Mouth">
-<!ENTITY smiley12Cmd.accesskey "M">
-<!ENTITY smiley12Cmd.tooltip "Insert a money-mouth face">
-<!ENTITY smiley13Cmd.label "Foot-in-Mouth">
-<!ENTITY smiley13Cmd.accesskey "o">
-<!ENTITY smiley13Cmd.tooltip "Insert a foot-in-mouth face">
-<!ENTITY smiley14Cmd.label "Innocent">
-<!ENTITY smiley14Cmd.accesskey "I">
-<!ENTITY smiley14Cmd.tooltip "Insert an innocent face">
-<!ENTITY smiley15Cmd.label "Cry">
-<!ENTITY smiley15Cmd.accesskey "r">
-<!ENTITY smiley15Cmd.tooltip "Insert a crying face">
-<!ENTITY smiley16Cmd.label "Lips-are-Sealed">
-<!ENTITY smiley16Cmd.accesskey "a">
-<!ENTITY smiley16Cmd.tooltip "Insert a lips-are-sealed face">
-<!ENTITY SmileButton.tooltip "Insert a smiley face">
-
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EdAdvancedEdit.dtd b/editor/ui/locales/en-US/chrome/dialogs/EdAdvancedEdit.dtd
deleted file mode 100644
index 83fcbd741..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EdAdvancedEdit.dtd
+++ /dev/null
@@ -1,18 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!ENTITY WindowTitle.label "Advanced Property Editor">
-<!ENTITY AttName.label "Attribute: ">
-<!ENTITY AttValue.label "Value: ">
-<!ENTITY PropertyName.label "Property: ">
-<!ENTITY currentattributesfor.label "Current attributes for: ">
-<!ENTITY tree.attributeHeader.label "Attribute">
-<!ENTITY tree.propertyHeader.label "Property">
-<!ENTITY tree.valueHeader.label "Value">
-<!ENTITY tabHTML.label "HTML Attributes">
-<!ENTITY tabCSS.label "Inline Style">
-<!ENTITY tabJSE.label "JavaScript Events">
-
-<!ENTITY editAttribute.label "Click on an item above to edit its value">
-<!ENTITY removeAttribute.label "Remove">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EdColorPicker.dtd b/editor/ui/locales/en-US/chrome/dialogs/EdColorPicker.dtd
deleted file mode 100644
index f1d9d447b..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EdColorPicker.dtd
+++ /dev/null
@@ -1,22 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!ENTITY windowTitle.label "Color">
-<!ENTITY lastPickedColor.label "Last-picked color">
-<!ENTITY lastPickedColor.accessKey "L">
-<!ENTITY setColor1.label "Click on a color or">
-<!ENTITY setColor2.label "enter an HTML color string">
-<!ENTITY setColor2.accessKey "H">
-<!ENTITY setColorExample.label "(e.g.: &quot;#0000ff&quot; or &quot;blue&quot;):">
-<!ENTITY default.label "Default">
-<!ENTITY default.accessKey "D">
-<!ENTITY palette.label "Palette:">
-<!ENTITY standardPalette.label "Standard">
-<!ENTITY webPalette.label "All web colors">
-<!ENTITY background.label "Background for:">
-<!ENTITY background.accessKey "B">
-<!ENTITY table.label "Table">
-<!ENTITY table.accessKey "T">
-<!ENTITY cell.label "Cell(s)">
-<!ENTITY cell.accessKey "C">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EdConvertToTable.dtd b/editor/ui/locales/en-US/chrome/dialogs/EdConvertToTable.dtd
deleted file mode 100644
index 044f60e49..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EdConvertToTable.dtd
+++ /dev/null
@@ -1,15 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-
-<!-- Window title -->
-<!ENTITY windowTitle.label "Convert To Table">
-<!ENTITY instructions1.label "Composer creates a new table row for each paragraph in the selection.">
-<!ENTITY instructions2.label "Choose the character used to separate the selection into columns:">
-<!ENTITY commaRadio.label "Comma">
-<!ENTITY spaceRadio.label "Space">
-<!ENTITY otherRadio.label "Other Character:">
-<!ENTITY deleteCharCheck.label "Delete separator character">
-<!ENTITY collapseSpaces.label "Ignore extra spaces">
-<!ENTITY collapseSpaces.tooltip "Convert adjacent spaces to one separator">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EdDialogOverlay.dtd b/editor/ui/locales/en-US/chrome/dialogs/EdDialogOverlay.dtd
deleted file mode 100644
index 99fd02a31..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EdDialogOverlay.dtd
+++ /dev/null
@@ -1,18 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!ENTITY AdvancedEditButton.label "Advanced Edit…">
-<!ENTITY AdvancedEditButton.accessKey "E">
-<!ENTITY AdvancedEditButton.tooltip "Add or modify HTML attributes, style attributes, and JavaScript">
-<!ENTITY chooseFileButton.label "Choose File...">
-<!ENTITY chooseFileButton.accessKey "F">
-<!ENTITY chooseFileLinkButton.label "Choose File...">
-<!ENTITY chooseFileLinkButton.accessKey "o">
-<!ENTITY makeUrlRelative.label "URL is relative to page location">
-<!ENTITY makeUrlRelative.accessKey "r">
-<!ENTITY makeUrlRelative.tooltip "Change between relative and absolute URL. You must first save the page to change this.">
-
-<!-- Shared by Link and Image dialogs -->
-<!ENTITY LinkURLEditField.label "Enter a web page location, a local file, or select a Named Anchor or Heading from the popup list:">
-<!ENTITY LinkURLEditField.accessKey "w">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EdNamedAnchorProperties.dtd b/editor/ui/locales/en-US/chrome/dialogs/EdNamedAnchorProperties.dtd
deleted file mode 100644
index faa1e1992..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EdNamedAnchorProperties.dtd
+++ /dev/null
@@ -1,10 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!ENTITY windowTitle.label "Named Anchor Properties">
-<!ENTITY anchorNameEditField.label "Anchor Name:">
-<!ENTITY anchorNameEditField.accessKey "N">
-<!ENTITY nameInput.tooltip "Enter a unique name for this named anchor (target)">
-
-
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorButtonProperties.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorButtonProperties.dtd
deleted file mode 100644
index efc6b400d..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorButtonProperties.dtd
+++ /dev/null
@@ -1,27 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!ENTITY windowTitle.label "Button Properties">
-
-<!ENTITY Settings.label "Settings">
-
-<!ENTITY ButtonType.label "Type">
-<!ENTITY ButtonType.accesskey "T">
-<!ENTITY submit.value "Submit">
-<!ENTITY reset.value "Reset">
-<!ENTITY button.value "Button">
-
-<!ENTITY ButtonName.label "Name:">
-<!ENTITY ButtonName.accesskey "N">
-<!ENTITY ButtonValue.label "Value:">
-<!ENTITY ButtonValue.accesskey "V">
-<!ENTITY tabIndex.label "Tab Index:">
-<!ENTITY tabIndex.accesskey "I">
-<!ENTITY ButtonDisabled.label "Disabled">
-<!ENTITY ButtonDisabled.accesskey "D">
-<!ENTITY AccessKey.label "Access Key:">
-<!ENTITY AccessKey.accesskey "K">
-
-<!ENTITY RemoveButton.label "Remove Button">
-<!ENTITY RemoveButton.accesskey "R">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorColorProperties.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorColorProperties.dtd
deleted file mode 100644
index 9d40d4de4..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorColorProperties.dtd
+++ /dev/null
@@ -1,28 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!-- Window title -->
-<!ENTITY windowTitle.label "Page Colors and Background">
-<!ENTITY pageColors.label "Page Colors">
-<!ENTITY defaultColorsRadio.label "Reader's default colors (Don't set colors in page)">
-<!ENTITY defaultColorsRadio.accessKey "D">
-<!ENTITY defaultColorsRadio.tooltip "Use the color settings from the viewer (reader's) browser only">
-<!ENTITY customColorsRadio.label "Use custom colors:">
-<!ENTITY customColorsRadio.accessKey "C">
-<!ENTITY customColorsRadio.tooltip "These color settings override the viewer's browser settings">
-
-<!ENTITY normalText.label "Normal text">
-<!ENTITY normalText.accessKey "N">
-<!ENTITY linkText.label "Link text">
-<!ENTITY linkText.accessKey "L">
-<!ENTITY activeLinkText.label "Active link text">
-<!ENTITY activeLinkText.accessKey "A">
-<!ENTITY visitedLinkText.label "Visited link text">
-<!ENTITY visitedLinkText.accessKey "V">
-<!ENTITY background.label "Background:">
-<!ENTITY background.accessKey "B">
-<!ENTITY colon.character ":">
-<!ENTITY backgroundImage.label "Background Image:">
-<!ENTITY backgroundImage.accessKey "m">
-<!ENTITY backgroundImage.tooltip "Use an image file as the background for your page">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorFieldSetProperties.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorFieldSetProperties.dtd
deleted file mode 100644
index a2db9d4e6..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorFieldSetProperties.dtd
+++ /dev/null
@@ -1,20 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!ENTITY windowTitle.label "Field Set Properties">
-
-<!ENTITY Legend.label "Legend">
-<!ENTITY Legend.accesskey "L">
-
-<!ENTITY EditLegendText.label "Edit Legend:">
-<!ENTITY EditLegendText.accesskey "T">
-<!ENTITY LegendAlign.label "Align Legend:">
-<!ENTITY LegendAlign.accesskey "A">
-<!ENTITY AlignDefault.label "Default">
-<!ENTITY AlignLeft.label "Left">
-<!ENTITY AlignCenter.label "Center">
-<!ENTITY AlignRight.label "Right">
-
-<!ENTITY RemoveFieldSet.label "Remove Field Set">
-<!ENTITY RemoveFieldSet.accesskey "R">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorFormProperties.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorFormProperties.dtd
deleted file mode 100644
index 2389adff2..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorFormProperties.dtd
+++ /dev/null
@@ -1,21 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!ENTITY windowTitle.label "Form Properties">
-
-<!ENTITY Settings.label "Settings">
-
-<!ENTITY FormName.label "Form Name:">
-<!ENTITY FormName.accesskey "N">
-<!ENTITY FormAction.label "Action URL:">
-<!ENTITY FormAction.accesskey "A">
-<!ENTITY FormMethod.label "Method:">
-<!ENTITY FormMethod.accesskey "M">
-<!ENTITY FormEncType.label "Encoding:">
-<!ENTITY FormEncType.accesskey "c">
-<!ENTITY FormTarget.label "Target Frame:">
-<!ENTITY FormTarget.accesskey "T">
-
-<!ENTITY RemoveForm.label "Remove Form">
-<!ENTITY RemoveForm.accesskey "R">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorHLineProperties.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorHLineProperties.dtd
deleted file mode 100644
index 9ad023dee..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorHLineProperties.dtd
+++ /dev/null
@@ -1,27 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-
-<!-- Window title -->
-<!ENTITY windowTitle.label "Horizontal Line Properties">
-
-<!ENTITY dimensionsBox.label "Dimensions">
-<!ENTITY heightEditField.label "Height:">
-<!ENTITY heightEditField.accessKey "G">
-<!ENTITY widthEditField.label "Width:">
-<!ENTITY widthEditField.accessKey "W">
-<!ENTITY pixelsPopup.value "pixels">
-<!ENTITY alignmentBox.label "Alignment">
-<!ENTITY leftRadio.label "Left">
-<!ENTITY leftRadio.accessKey "L">
-<!ENTITY centerRadio.label "Center">
-<!ENTITY centerRadio.accessKey "C">
-<!ENTITY rightRadio.label "Right">
-<!ENTITY rightRadio.accessKey "R">
-
-<!ENTITY threeDShading.label "3-D Shading">
-<!ENTITY threeDShading.accessKey "S">
-<!ENTITY saveSettings.label "Use as Default">
-<!ENTITY saveSettings.accessKey "D">
-<!ENTITY saveSettings.tooltip "Save these settings to use when inserting new horizontal lines">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorImageProperties.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorImageProperties.dtd
deleted file mode 100644
index 280af6df2..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorImageProperties.dtd
+++ /dev/null
@@ -1,79 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!-- These strings are for use specifically in the editor's image and form image dialogs. -->
-
-<!-- Window title -->
-<!ENTITY windowTitle.label "Image Properties">
-
-<!ENTITY pixelsPopup.value "pixels">
-
-<!-- These are in the Location tab panel -->
-<!ENTITY locationEditField.label "Image Location:">
-<!ENTITY locationEditField.accessKey "L">
-<!ENTITY locationEditField.tooltip "Type the image's filename or location">
-<!ENTITY locationEditField.shortenedDataURI "Shortened data URI (copy will place the full URI onto the clipboard)">
-<!ENTITY title.label "Tooltip:">
-<!ENTITY title.accessKey "T">
-<!ENTITY title.tooltip "The html 'title' attribute that displays as a tooltip">
-<!ENTITY altText.label "Alternate text:">
-<!ENTITY altText.accessKey "A">
-<!ENTITY altTextEditField.tooltip "Type text to display in place of the image">
-<!ENTITY noAltText.label "Don't use alternate text">
-<!ENTITY noAltText.accessKey "D">
-
-<!ENTITY previewBox.label "Image Preview">
-
-<!-- These controls are in the Dimensions tab panel -->
-<!-- actualSize.label should be same as actualSizeRadio.label + ":" -->
-<!ENTITY actualSize.label "Actual Size:">
-<!ENTITY actualSizeRadio.label "Actual Size">
-<!ENTITY actualSizeRadio.accessKey "A">
-<!ENTITY actualSizeRadio.tooltip "Revert to the image's actual size">
-<!ENTITY customSizeRadio.label "Custom Size">
-<!ENTITY customSizeRadio.accessKey "S">
-<!ENTITY customSizeRadio.tooltip "Change the image's size as displayed in the page">
-<!ENTITY heightEditField.label "Height:">
-<!ENTITY heightEditField.accessKey "G">
-<!ENTITY widthEditField.label "Width:">
-<!ENTITY widthEditField.accessKey "W">
-<!ENTITY constrainCheckbox.label "Constrain">
-<!ENTITY constrainCheckbox.accessKey "C">
-<!ENTITY constrainCheckbox.tooltip "Maintain the image's aspect ratio">
-
-<!-- These controls are in the Image Map box of the expanded area -->
-<!ENTITY imagemapBox.label "Image Map">
-<!ENTITY removeImageMapButton.label "Remove">
-<!ENTITY removeImageMapButton.accessKey "R">
-
-<!-- These are the options for image alignment -->
-<!ENTITY alignment.label "Align Text to Image">
-<!ENTITY bottomPopup.value "At the bottom">
-<!ENTITY topPopup.value "At the top">
-<!ENTITY centerPopup.value "In the center">
-<!ENTITY wrapRightPopup.value "Wrap to the right">
-<!ENTITY wrapLeftPopup.value "Wrap to the left">
-
-<!-- These controls are in the Spacing Box -->
-<!ENTITY spacingBox.label "Spacing">
-<!ENTITY leftRightEditField.label "Left and Right:">
-<!ENTITY leftRightEditField.accessKey "L">
-<!ENTITY topBottomEditField.label "Top and Bottom:">
-<!ENTITY topBottomEditField.accessKey "T">
-<!ENTITY borderEditField.label "Solid Border:">
-<!ENTITY borderEditField.accessKey "B">
-
-<!-- These controls are in the Link Box -->
-<!ENTITY showImageLinkBorder.label "Show border around linked image">
-<!ENTITY showImageLinkBorder.accessKey "B">
-<!ENTITY LinkAdvancedEditButton.label "Link Advanced Edit…">
-<!ENTITY LinkAdvancedEditButton.accessKey "L">
-<!ENTITY LinkAdvancedEditButton.tooltip "Add or modify HTML attributes, style attributes, and JavaScript">
-
-<!-- These tabs are currently used in the image input dialog -->
-<!ENTITY imageInputTab.label "Form">
-<!ENTITY imageLocationTab.label "Location">
-<!ENTITY imageDimensionsTab.label "Dimensions">
-<!ENTITY imageAppearanceTab.label "Appearance">
-<!ENTITY imageLinkTab.label "Link">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorInputProperties.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorInputProperties.dtd
deleted file mode 100644
index ea7d09c75..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorInputProperties.dtd
+++ /dev/null
@@ -1,50 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!ENTITY windowTitle.label "Form Field Properties">
-<!ENTITY windowTitleImage.label "Form Image Properties">
-
-<!ENTITY InputType.label "Field Type">
-<!ENTITY InputType.accesskey "T">
-<!ENTITY text.value "Text">
-<!ENTITY password.value "Password">
-<!ENTITY checkbox.value "Check Box">
-<!ENTITY radio.value "Radio Button">
-<!ENTITY submit.value "Submit Button">
-<!ENTITY reset.value "Reset Button">
-<!ENTITY file.value "File">
-<!ENTITY hidden.value "Hidden">
-<!ENTITY image.value "Image">
-<!ENTITY button.value "Button">
-
-<!ENTITY InputSettings.label "Field Settings">
-<!ENTITY InputName.label "Field Name:">
-<!ENTITY InputName.accesskey "N">
-<!ENTITY GroupName.label "Group Name:">
-<!ENTITY GroupName.accesskey "N">
-<!ENTITY InputValue.label "Field Value:">
-<!ENTITY InputValue.accesskey "V">
-<!ENTITY InitialValue.label "Initial Value:">
-<!ENTITY InitialValue.accesskey "V">
-<!ENTITY InputChecked.label "Initially Checked">
-<!ENTITY InputChecked.accesskey "C">
-<!ENTITY InputSelected.label "Initially Selected">
-<!ENTITY InputSelected.accesskey "S">
-<!ENTITY InputReadOnly.label "Read Only">
-<!ENTITY InputReadOnly.accesskey "R">
-<!ENTITY InputDisabled.label "Disabled">
-<!ENTITY InputDisabled.accesskey "D">
-<!ENTITY tabIndex.label "Tab Index:">
-<!ENTITY tabIndex.accesskey "I">
-<!ENTITY TextSize.label "Field Size:">
-<!ENTITY TextSize.accesskey "F">
-<!ENTITY TextLength.label "Maximum Length:">
-<!ENTITY TextLength.accesskey "L">
-<!ENTITY AccessKey.label "Access Key:">
-<!ENTITY AccessKey.accesskey "K">
-<!ENTITY Accept.label "Accept Types:">
-<!ENTITY Accept.accesskey "A">
-
-<!ENTITY ImageProperties.label "Image Properties…">
-<!ENTITY ImageProperties.accesskey "E">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorInsertChars.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorInsertChars.dtd
deleted file mode 100644
index 1755e499c..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorInsertChars.dtd
+++ /dev/null
@@ -1,19 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-
-<!-- Window title -->
-<!ENTITY windowTitle.label "Insert Character">
-<!ENTITY category.label "Category">
-<!ENTITY letter.label "Letter:">
-<!ENTITY letter.accessKey "L">
-<!ENTITY character.label "Character:">
-<!ENTITY character.accessKey "C">
-<!ENTITY accentUpper.label "Accent Uppercase">
-<!ENTITY accentLower.label "Accent Lowercase">
-<!ENTITY otherUpper.label "Other Uppercase">
-<!ENTITY otherLower.label "Other Lowercase">
-<!ENTITY commonSymbols.label "Common Symbols">
-<!ENTITY insertButton.label "Insert">
-<!ENTITY closeButton.label "Close">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorInsertMath.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorInsertMath.dtd
deleted file mode 100644
index 357ed0b20..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorInsertMath.dtd
+++ /dev/null
@@ -1,21 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!-- Window title -->
-<!ENTITY windowTitle.label "Insert Math">
-
-<!ENTITY sourceEditField.label "Enter LaTeX source code:">
-
-<!ENTITY options.label "Options">
-<!ENTITY optionInline.label "Inline mode">
-<!ENTITY optionInline.accesskey "N">
-<!ENTITY optionDisplay.label "Display mode">
-<!ENTITY optionDisplay.accesskey "D">
-<!ENTITY optionLTR.label "Left-to-right direction">
-<!ENTITY optionLTR.accesskey "L">
-<!ENTITY optionRTL.label "Right-to-left direction">
-<!ENTITY optionRTL.accesskey "R">
-
-<!ENTITY insertButton.label "Insert">
-<!ENTITY insertButton.accesskey "I">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorInsertSource.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorInsertSource.dtd
deleted file mode 100644
index 0b51a86c8..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorInsertSource.dtd
+++ /dev/null
@@ -1,15 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!-- Window title -->
-<!ENTITY windowTitle.label "Insert HTML">
-<!ENTITY sourceEditField.label "Enter HTML tags and text:">
-<!ENTITY example.label "Example: ">
-<!-- LOCALIZATION NOTE (exampleOpenTag.label): DONT_TRANSLATE: they are text for HTML tagnames: "<i>" and "</i>" -->
-<!ENTITY exampleOpenTag.label "&lt;i&gt;">
-<!-- LOCALIZATION NOTE (exampleCloseTag.label): DONT_TRANSLATE: they are text for HTML tagnames: "<i>" and "</i>" -->
-<!ENTITY exampleCloseTag.label "&lt;/i&gt;">
-<!ENTITY exampleText.label "Hello World!">
-<!ENTITY insertButton.label "Insert">
-<!ENTITY insertButton.accesskey "I">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorInsertTOC.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorInsertTOC.dtd
deleted file mode 100644
index f3285a357..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorInsertTOC.dtd
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!ENTITY Window.title "Table of Contents">
-<!ENTITY buildToc.label "Build table of contents from:">
-<!ENTITY tag.label "Tag:">
-<!ENTITY class.label "Class:">
-<!ENTITY header1.label "Level 1">
-<!ENTITY header2.label "Level 2">
-<!ENTITY header3.label "Level 3">
-<!ENTITY header4.label "Level 4">
-<!ENTITY header5.label "Level 5">
-<!ENTITY header6.label "Level 6">
-<!ENTITY makeReadOnly.label "Make the table of contents read-only">
-<!ENTITY orderedList.label "Number all entries in the table of contents">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorInsertTable.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorInsertTable.dtd
deleted file mode 100644
index 00b5d2d13..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorInsertTable.dtd
+++ /dev/null
@@ -1,18 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!-- Window title -->
-<!ENTITY windowTitle.label "Insert Table">
-
-<!ENTITY size.label "Size">
-<!ENTITY numRowsEditField.label "Rows:">
-<!ENTITY numRowsEditField.accessKey "R">
-<!ENTITY numColumnsEditField.label "Columns:">
-<!ENTITY numColumnsEditField.accessKey "C">
-<!ENTITY widthEditField.label "Width:">
-<!ENTITY widthEditField.accessKey "W">
-<!ENTITY borderEditField.label "Border:">
-<!ENTITY borderEditField.accessKey "B">
-<!ENTITY borderEditField.tooltip "Type a number for the table's border, or type zero (0) for no border">
-<!ENTITY pixels.label "pixels">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorLabelProperties.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorLabelProperties.dtd
deleted file mode 100644
index 5ed05aa63..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorLabelProperties.dtd
+++ /dev/null
@@ -1,18 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!ENTITY windowTitle.label "Label Properties">
-
-<!ENTITY Settings.label "Settings">
-<!ENTITY Settings.accesskey "S">
-
-<!ENTITY EditLabelText.label "Edit Text:">
-<!ENTITY EditLabelText.accesskey "T">
-<!ENTITY LabelFor.label "For Control:">
-<!ENTITY LabelFor.accesskey "F">
-<!ENTITY AccessKey.label "Access Key:">
-<!ENTITY AccessKey.accesskey "K">
-
-<!ENTITY RemoveLabel.label "Remove Label">
-<!ENTITY RemoveLabel.accesskey "R">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorLinkProperties.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorLinkProperties.dtd
deleted file mode 100644
index 09b3b0155..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorLinkProperties.dtd
+++ /dev/null
@@ -1,6 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!ENTITY windowTitle.label "Link Properties">
-<!ENTITY LinkURLBox.label "Link Location">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorListProperties.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorListProperties.dtd
deleted file mode 100644
index 249433000..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorListProperties.dtd
+++ /dev/null
@@ -1,20 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-
-<!-- Window title -->
-<!ENTITY windowTitle.label "List Properties">
-
-<!ENTITY ListType.label "List Type">
-<!ENTITY bulletStyle.label "Bullet Style:">
-<!ENTITY startingNumber.label "Start at:">
-<!ENTITY startingNumber.accessKey "S">
-<!ENTITY none.value "None">
-<!ENTITY bulletList.value "Bullet (Unnumbered) List">
-<!ENTITY numberList.value "Numbered List">
-<!ENTITY definitionList.value "Definition List">
-<!ENTITY changeEntireListRadio.label "Change entire list">
-<!ENTITY changeEntireListRadio.accessKey "C">
-<!ENTITY changeSelectedRadio.label "Change just selected items">
-<!ENTITY changeSelectedRadio.accessKey "I">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorPersonalDictionary.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorPersonalDictionary.dtd
deleted file mode 100644
index 2a8cf9b72..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorPersonalDictionary.dtd
+++ /dev/null
@@ -1,20 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!-- Window title -->
-<!ENTITY windowTitle.label "Personal Dictionary">
-
-<!ENTITY wordEditField.label "New word:">
-<!ENTITY wordEditField.accessKey "N">
-<!ENTITY AddButton.label "Add">
-<!ENTITY AddButton.accessKey "A">
-<!ENTITY DictionaryList.label "Words in dictionary:">
-<!ENTITY DictionaryList.accessKey "W">
-<!ENTITY ReplaceButton.label "Replace">
-<!ENTITY ReplaceButton.accessKey "R">
-<!ENTITY RemoveButton.label "Remove">
-<!ENTITY RemoveButton.accessKey "e">
-
-<!ENTITY CloseButton.label "Close">
-<!ENTITY CloseButton.accessKey "C">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorReplace.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorReplace.dtd
deleted file mode 100644
index 0bee6e40a..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorReplace.dtd
+++ /dev/null
@@ -1,26 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!-- extracted from EdReplace.xul -->
-
-<!ENTITY replaceDialog.title "Find and Replace">
-<!ENTITY findField.label "Find text:">
-<!ENTITY findField.accesskey "n">
-<!ENTITY replaceField.label "Replace with:">
-<!ENTITY replaceField.accesskey "e">
-<!ENTITY caseSensitiveCheckbox.label "Match exact case">
-<!ENTITY caseSensitiveCheckbox.accesskey "c">
-<!ENTITY wrapCheckbox.label "Wrap around">
-<!ENTITY wrapCheckbox.accesskey "W">
-<!ENTITY backwardsCheckbox.label "Search backwards">
-<!ENTITY backwardsCheckbox.accesskey "b">
-<!ENTITY findNextButton.label "Find Next">
-<!ENTITY findNextButton.accesskey "F">
-<!ENTITY replaceButton.label "Replace">
-<!ENTITY replaceButton.accesskey "R">
-<!ENTITY replaceAndFindButton.label "Replace and Find">
-<!ENTITY replaceAndFindButton.accesskey "d">
-<!ENTITY replaceAllButton.label "Replace All">
-<!ENTITY replaceAllButton.accesskey "A">
-<!ENTITY closeButton.label "Close">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorSelectProperties.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorSelectProperties.dtd
deleted file mode 100644
index e2eb20e69..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorSelectProperties.dtd
+++ /dev/null
@@ -1,48 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!ENTITY windowTitle.label "Selection List Properties">
-
-<!ENTITY Select.label "Selection List">
-<!ENTITY SelectName.label "List Name:">
-<!ENTITY SelectName.accesskey "N">
-<!ENTITY SelectSize.label "Height:">
-<!ENTITY SelectSize.accesskey "H">
-<!ENTITY SelectMultiple.label "Multiple Selection">
-<!ENTITY SelectMultiple.accesskey "M">
-<!ENTITY SelectDisabled.label "Disabled">
-<!ENTITY SelectDisabled.accesskey "D">
-<!ENTITY SelectTabIndex.label "Tab Index:">
-<!ENTITY SelectTabIndex.accesskey "I">
-
-<!ENTITY OptGroup.label "Option Group">
-<!ENTITY OptGroupLabel.label "Label:">
-<!ENTITY OptGroupLabel.accesskey "L">
-<!ENTITY OptGroupDisabled.label "Disabled">
-<!ENTITY OptGroupDisabled.accesskey "D">
-
-<!ENTITY Option.label "Option">
-<!ENTITY OptionText.label "Text:">
-<!ENTITY OptionText.accesskey "T">
-<!ENTITY OptionValue.label "Value:">
-<!ENTITY OptionValue.accesskey "V">
-<!ENTITY OptionSelected.label "Initially Selected">
-<!ENTITY OptionSelected.accesskey "S">
-<!ENTITY OptionDisabled.label "Disabled">
-<!ENTITY OptionDisabled.accesskey "D">
-
-<!ENTITY TextHeader.label "Text">
-<!ENTITY ValueHeader.label "Value">
-<!ENTITY SelectedHeader.label "Selected">
-
-<!ENTITY AddOption.label "Add Option">
-<!ENTITY AddOption.accesskey "O">
-<!ENTITY AddOptGroup.label "Add Group">
-<!ENTITY AddOptGroup.accesskey "G">
-<!ENTITY RemoveElement.label "Remove">
-<!ENTITY RemoveElement.accesskey "R">
-<!ENTITY MoveElementUp.label "Move Up">
-<!ENTITY MoveElementUp.accesskey "U">
-<!ENTITY MoveElementDown.label "Move Down">
-<!ENTITY MoveElementDown.accesskey "D">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorSpellCheck.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorSpellCheck.dtd
deleted file mode 100644
index 7d2915483..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorSpellCheck.dtd
+++ /dev/null
@@ -1,38 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!-- Window title -->
-<!ENTITY windowTitle.label "Check Spelling">
-
-<!ENTITY misspelledWord.label "Misspelled word:">
-<!ENTITY wordEditField.label "Replace with:">
-<!ENTITY wordEditField.accessKey "w">
-<!ENTITY checkwordButton.label "Check Word">
-<!ENTITY checkwordButton.accessKey "k">
-<!ENTITY suggestions.label "Suggestions:">
-<!ENTITY suggestions.accessKey "u">
-<!ENTITY ignoreButton.label "Ignore">
-<!ENTITY ignoreButton.accessKey "I">
-<!ENTITY ignoreAllButton.label "Ignore All">
-<!ENTITY ignoreAllButton.accessKey "n">
-<!ENTITY replaceButton.label "Replace">
-<!ENTITY replaceButton.accessKey "R">
-<!ENTITY replaceAllButton.label "Replace All">
-<!ENTITY replaceAllButton.accessKey "A">
-<!ENTITY stopButton.label "Stop">
-<!ENTITY stopButton.accessKey "o">
-<!ENTITY userDictionary.label "Personal Dictionary:">
-<!ENTITY moreDictionaries.label "Download more dictionaries…">
-<!ENTITY addToUserDictionaryButton.label "Add Word">
-<!ENTITY addToUserDictionaryButton.accessKey "d">
-<!ENTITY editUserDictionaryButton.label "Edit…">
-<!ENTITY editUserDictionaryButton.accessKey "E">
-<!ENTITY recheckButton2.label "Recheck Text">
-<!ENTITY recheckButton2.accessKey "T">
-<!ENTITY closeButton.label "Close">
-<!ENTITY closeButton.accessKey "C">
-<!ENTITY sendButton.label "Send">
-<!ENTITY sendButton.accessKey "S">
-<!ENTITY languagePopup.label "Language:">
-<!ENTITY languagePopup.accessKey "L">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorTableProperties.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorTableProperties.dtd
deleted file mode 100644
index 512734d7a..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorTableProperties.dtd
+++ /dev/null
@@ -1,75 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!ENTITY tableWindow.title "Table Properties">
-<!ENTITY applyButton.label "Apply">
-<!ENTITY applyButton.accesskey "A">
-<!ENTITY closeButton.label "Close">
-<!ENTITY tableTab.label "Table">
-<!ENTITY cellTab.label "Cells">
-<!ENTITY tableRows.label "Rows:">
-<!ENTITY tableRows.accessKey "R">
-<!ENTITY tableColumns.label "Columns:">
-<!ENTITY tableColumns.accessKey "C">
-<!ENTITY tableHeight.label "Height:">
-<!ENTITY tableHeight.accessKey "G">
-<!ENTITY tableWidth.label "Width:">
-<!ENTITY tableWidth.accessKey "W">
-<!ENTITY tableBorderSpacing.label "Borders and Spacing">
-<!ENTITY tableBorderWidth.label "Border:">
-<!ENTITY tableBorderWidth.accessKey "B">
-<!ENTITY tableSpacing.label "Spacing:">
-<!ENTITY tableSpacing.accessKey "S">
-<!ENTITY tablePadding.label "Padding:">
-<!ENTITY tablePadding.accessKey "P">
-<!ENTITY tablePxBetwCells.label "pixels between cells">
-<!ENTITY tablePxBetwBrdrCellContent.label "pixels between cell border and content">
-<!ENTITY tableAlignment.label "Table Alignment:">
-<!ENTITY tableAlignment.accessKey "T">
-<!ENTITY tableCaption.label "Caption:">
-<!ENTITY tableCaption.accessKey "N">
-<!ENTITY tableCaptionAbove.label "Above Table">
-<!ENTITY tableCaptionBelow.label "Below Table">
-<!ENTITY tableCaptionLeft.label "Left of Table">
-<!ENTITY tableCaptionRight.label "Right of table">
-<!ENTITY tableCaptionNone.label "None">
-<!ENTITY tableInheritColor.label "(Let page color show through)">
-
-<!ENTITY cellSelection.label "Selection">
-<!ENTITY cellSelectCell.label "Cell">
-<!ENTITY cellSelectRow.label "Row">
-<!ENTITY cellSelectColumn.label "Column">
-<!ENTITY cellSelectNext.label "Next">
-<!ENTITY cellSelectNext.accessKey "N">
-<!ENTITY cellSelectPrevious.label "Previous">
-<!ENTITY cellSelectPrevious.accessKey "P">
-<!ENTITY applyBeforeChange.label "Current changes will be applied before changing the selection.">
-<!ENTITY cellContentAlignment.label "Content Alignment">
-<!ENTITY cellHorizontal.label "Horizontal:">
-<!ENTITY cellHorizontal.accessKey "Z">
-<!ENTITY cellVertical.label "Vertical:">
-<!ENTITY cellVertical.accessKey "V">
-<!ENTITY cellStyle.label "Cell Style:">
-<!ENTITY cellStyle.accessKey "C">
-<!ENTITY cellNormal.label "Normal">
-<!ENTITY cellHeader.label "Header">
-<!ENTITY cellTextWrap.label "Text Wrap:">
-<!ENTITY cellTextWrap.accessKey "T">
-<!ENTITY cellWrap.label "Wrap">
-<!ENTITY cellNoWrap.label "Don't wrap">
-<!ENTITY cellAlignTop.label "Top">
-<!ENTITY cellAlignMiddle.label "Middle">
-<!ENTITY cellAlignBottom.label "Bottom">
-<!ENTITY cellAlignJustify.label "Justify">
-<!ENTITY cellInheritColor.label "(Let table color show through)">
-<!ENTITY cellUseCheckboxHelp.label "Use checkboxes to determine which properties are applied to all selected cells">
-
-<!-- Used in both Table and Cell panels -->
-<!ENTITY size.label "Size">
-<!ENTITY pixels.label "pixels">
-<!ENTITY backgroundColor.label "Background Color:">
-<!ENTITY backgroundColor.accessKey "B">
-<!ENTITY AlignLeft.label "Left">
-<!ENTITY AlignCenter.label "Center">
-<!ENTITY AlignRight.label "Right">
diff --git a/editor/ui/locales/en-US/chrome/dialogs/EditorTextAreaProperties.dtd b/editor/ui/locales/en-US/chrome/dialogs/EditorTextAreaProperties.dtd
deleted file mode 100644
index a1e8bbd03..000000000
--- a/editor/ui/locales/en-US/chrome/dialogs/EditorTextAreaProperties.dtd
+++ /dev/null
@@ -1,33 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!ENTITY windowTitle.label "Text Area Properties">
-
-<!ENTITY Settings.label "Settings">
-
-<!ENTITY TextAreaName.label "Field Name:">
-<!ENTITY TextAreaName.accessKey "N">
-<!ENTITY TextAreaRows.label "Rows:">
-<!ENTITY TextAreaRows.accessKey "R">
-<!ENTITY TextAreaCols.label "Columns:">
-<!ENTITY TextAreaCols.accessKey "C">
-<!ENTITY TextAreaReadOnly.label "Read Only">
-<!ENTITY TextAreaReadOnly.accessKey "O">
-<!ENTITY TextAreaDisabled.label "Disabled">
-<!ENTITY TextAreaDisabled.accessKey "D">
-<!ENTITY TextAreaTabIndex.label "Tab Index:">
-<!ENTITY TextAreaTabIndex.accessKey "I">
-<!ENTITY TextAreaAccessKey.label "Access Key:">
-<!ENTITY TextAreaAccessKey.accessKey "K">
-<!ENTITY InitialText.label "Initial Text:">
-<!ENTITY InitialText.accessKey "T">
-
-<!ENTITY TextAreaWrap.label "Wrap Mode:">
-<!ENTITY TextAreaWrap.accessKey "W">
-<!ENTITY WrapDefault.value "Default">
-<!ENTITY WrapOff.value "Off">
-<!ENTITY WrapHard.value "Hard">
-<!ENTITY WrapSoft.value "Soft">
-<!ENTITY WrapPhysical.value "Physical">
-<!ENTITY WrapVirtual.value "Virtual">
diff --git a/editor/ui/locales/jar.mn b/editor/ui/locales/jar.mn
deleted file mode 100644
index e0817a2eb..000000000
--- a/editor/ui/locales/jar.mn
+++ /dev/null
@@ -1,38 +0,0 @@
-#filter substitution
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-
-@AB_CD@.jar:
-% locale editor @AB_CD@ %locale/@AB_CD@/editor/
- locale/@AB_CD@/editor/editorSmileyOverlay.dtd (%chrome/composer/editorSmileyOverlay.dtd)
- locale/@AB_CD@/editor/editorOverlay.dtd (%chrome/composer/editorOverlay.dtd)
- locale/@AB_CD@/editor/editor.properties (%chrome/composer/editor.properties)
- locale/@AB_CD@/editor/EditorHLineProperties.dtd (%chrome/dialogs/EditorHLineProperties.dtd)
- locale/@AB_CD@/editor/EditorImageProperties.dtd (%chrome/dialogs/EditorImageProperties.dtd)
- locale/@AB_CD@/editor/EditorInsertSource.dtd (%chrome/dialogs/EditorInsertSource.dtd)
- locale/@AB_CD@/editor/EditorInsertMath.dtd (%chrome/dialogs/EditorInsertMath.dtd)
- locale/@AB_CD@/editor/EditorInsertChars.dtd (%chrome/dialogs/EditorInsertChars.dtd)
- locale/@AB_CD@/editor/EditorInsertTable.dtd (%chrome/dialogs/EditorInsertTable.dtd)
- locale/@AB_CD@/editor/EditorInsertTOC.dtd (%chrome/dialogs/EditorInsertTOC.dtd)
- locale/@AB_CD@/editor/EditorLinkProperties.dtd (%chrome/dialogs/EditorLinkProperties.dtd)
- locale/@AB_CD@/editor/EditorListProperties.dtd (%chrome/dialogs/EditorListProperties.dtd)
- locale/@AB_CD@/editor/EditorColorProperties.dtd (%chrome/dialogs/EditorColorProperties.dtd)
- locale/@AB_CD@/editor/EdColorPicker.dtd (%chrome/dialogs/EdColorPicker.dtd)
- locale/@AB_CD@/editor/EditorReplace.dtd (%chrome/dialogs/EditorReplace.dtd)
- locale/@AB_CD@/editor/EditorSpellCheck.dtd (%chrome/dialogs/EditorSpellCheck.dtd)
- locale/@AB_CD@/editor/EditorPersonalDictionary.dtd (%chrome/dialogs/EditorPersonalDictionary.dtd)
- locale/@AB_CD@/editor/EditorTableProperties.dtd (%chrome/dialogs/EditorTableProperties.dtd)
- locale/@AB_CD@/editor/EditorFormProperties.dtd (%chrome/dialogs/EditorFormProperties.dtd)
- locale/@AB_CD@/editor/EditorInputProperties.dtd (%chrome/dialogs/EditorInputProperties.dtd)
- locale/@AB_CD@/editor/EditorTextAreaProperties.dtd (%chrome/dialogs/EditorTextAreaProperties.dtd)
- locale/@AB_CD@/editor/EditorSelectProperties.dtd (%chrome/dialogs/EditorSelectProperties.dtd)
- locale/@AB_CD@/editor/EditorButtonProperties.dtd (%chrome/dialogs/EditorButtonProperties.dtd)
- locale/@AB_CD@/editor/EditorLabelProperties.dtd (%chrome/dialogs/EditorLabelProperties.dtd)
- locale/@AB_CD@/editor/EditorFieldSetProperties.dtd (%chrome/dialogs/EditorFieldSetProperties.dtd)
- locale/@AB_CD@/editor/EdNamedAnchorProperties.dtd (%chrome/dialogs/EdNamedAnchorProperties.dtd)
- locale/@AB_CD@/editor/EdDialogOverlay.dtd (%chrome/dialogs/EdDialogOverlay.dtd)
- locale/@AB_CD@/editor/EdAdvancedEdit.dtd (%chrome/dialogs/EdAdvancedEdit.dtd)
- locale/@AB_CD@/editor/EdConvertToTable.dtd (%chrome/dialogs/EdConvertToTable.dtd)
-
diff --git a/editor/ui/locales/moz.build b/editor/ui/locales/moz.build
deleted file mode 100644
index e0eb66aac..000000000
--- a/editor/ui/locales/moz.build
+++ /dev/null
@@ -1,6 +0,0 @@
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-JAR_MANIFESTS += ['jar.mn']
diff --git a/editor/ui/moz.build b/editor/ui/moz.build
deleted file mode 100644
index 5fc4d6eb0..000000000
--- a/editor/ui/moz.build
+++ /dev/null
@@ -1,8 +0,0 @@
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DIRS += ['locales']
-EXTRA_JS_MODULES += ['editorUtilities.jsm']
-JAR_MANIFESTS += ['jar.mn']
diff --git a/editor/ui/texzilla/content/TeXZilla.js b/editor/ui/texzilla/content/TeXZilla.js
deleted file mode 100644
index 290d34e79..000000000
--- a/editor/ui/texzilla/content/TeXZilla.js
+++ /dev/null
@@ -1,815 +0,0 @@
-/* THIS IS A GENERATED FILE. DO NOT EDIT THIS DIRECTLY. */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-var h=!0,n=null,p=!1,u=function(){function t(b){return b.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function B(b){b=b.trim();var a=/(-?[0-9]*(?:[0-9]\.?|\.[0-9])[0-9]*)(e[mx]|in|cm|mm|p[xtc]|%)?/.exec(b);if(a)return a[1]=parseFloat(a[1]),a[2]||(a[1]*=100,a[2]="%"),{j:a[1],l:a[2]};b="negativeveryverythinmathspace negativeverythinmathspace negativemediummathspace negativethickmathspace negativeverythickmathspace negativeveryverythickmathspace veryverythinmathspace verythinmathspace thinmathspace mediummathspace thickmathspace verythickmathspace veryverythickmathspace".split(" ").indexOf(b);
-return{j:(-1===b?0:b-6)/18,l:"em"}}function d(b,a,d){var e="<"+b;d&&(e+=" "+d);return e+(">"+a+"</"+b+">")}function f(b,a,d){var e="<mo";a&&(e+=' lspace="'+a+'"');d&&(e+=' rspace="'+d+'"');return e+=">"+t(b)+"</mo>"}function r(b,a,d,e){return b?!d?"<mover>"+a+e+"</mover>":!e?"<munder>"+a+d+"</munder>":"<munderover>"+a+d+e+"</munderover>":!d?"<msup>"+a+e+"</msup>":!e?"<msub>"+a+d+"</msub>":"<msubsup>"+a+d+e+"</msubsup>"}function k(b,a,d){var e;if(!a){if(1==b.length)return b[0];a="mrow"}e="<"+a;d&&
-(e+=" "+d);return e+=">"+b.join("")+"</"+a+">"}function w(b,a,d){var e='<math xmlns="'+x+'"';a&&(e+=' display="block"');e+="><semantics>"+k(b);e=e+'<annotation encoding="TeX">'+t(d);return e+="</annotation></semantics></math>"}function C(b){if(!b||b.namespaceURI!==x)return n;if("semantics"===b.tagName)for(b=b.firstElementChild;b;b=b.nextElementSibling){if(b.namespaceURI===x&&"annotation"===b.localName&&-1!==D.indexOf(b.getAttribute("encoding")))return b.textContent}else if(1===b.childElementCount)return C(b.firstElementChild);
-return n}function E(b){for(var a="",d,e,g=0;g<b.length;g++)d=b.charCodeAt(g),128>d?a+=b.charAt(g):55296<=d&&56319>=d?(g++,e=b.charCodeAt(g),a+="&#x"+(1024*(d-55296)+e-56320+65536).toString(16)+";"):a+="&#x"+d.toString(16)+";";return a}function F(b){throw Error(b.replace(/\nExpecting [^\n]*$/,"\n"));}function y(){this.f={}}var l={trace:function(){},f:{},la:{error:2,textOptArg:3,"[":4,TEXTOPTARG:5,"]":6,textArg:7,"{":8,TEXTARG:9,"}":10,lengthOptArg:11,lengthArg:12,attrOptArg:13,attrArg:14,tokenContent:15,
-arrayAlign:16,columnAlign:17,collayout:18,COLLAYOUT:19,colalign:20,COLALIGN:21,rowalign:22,ROWALIGN:23,rowspan:24,ROWSPAN:25,colspan:26,COLSPAN:27,align:28,ALIGN:29,eqrows:30,EQROWS:31,eqcols:32,EQCOLS:33,rowlines:34,ROWLINES:35,collines:36,COLLINES:37,frame:38,FRAME:39,padding:40,PADDING:41,cellopt:42,celloptList:43,rowopt:44,arrayopt:45,arrayoptList:46,rowoptList:47,left:48,LEFT:49,OPFS:50,".":51,right:52,RIGHT:53,closedTerm:54,styledExpression:55,BIG:56,BBIG:57,BIGG:58,BBIGG:59,BIGL:60,BBIGL:61,
-BIGGL:62,BBIGGL:63,TEXATOP:64,TEXOVER:65,TEXCHOOSE:66,NUM:67,TEXT:68,A:69,F:70,MI:71,MN:72,MO:73,OP:74,OPS:75,OPAS:76,MS:77,MTEXT:78,HIGH_SURROGATE:79,LOW_SURROGATE:80,BMP_CHARACTER:81,OPERATORNAME:82,MATHOP:83,MATHBIN:84,MATHREL:85,FRAC:86,ROOT:87,SQRT:88,UNDERSET:89,OVERSET:90,UNDEROVERSET:91,XARROW:92,MATHRLAP:93,MATHLLAP:94,MATHCLAP:95,PHANTOM:96,TFRAC:97,BINOM:98,TBINOM:99,PMOD:100,UNDERBRACE:101,UNDERLINE:102,OVERBRACE:103,ACCENT:104,ACCENTNS:105,BOXED:106,SLASH:107,QUAD:108,QQUAD:109,NEGSPACE:110,
-NEGMEDSPACE:111,NEGTHICKSPACE:112,THINSPACE:113,MEDSPACE:114,THICKSPACE:115,SPACE:116,MATHRAISEBOX:117,MATHBB:118,MATHBF:119,MATHBIT:120,MATHSCR:121,MATHBSCR:122,MATHSF:123,MATHFRAK:124,MATHIT:125,MATHTT:126,MATHRM:127,HREF:128,STATUSLINE:129,TOOLTIP:130,TOGGLE:131,BTOGGLE:132,closedTermList:133,ETOGGLE:134,TENSOR:135,subsupList:136,MULTI:137,BMATRIX:138,tableRowList:139,EMATRIX:140,BGATHERED:141,EGATHERED:142,BPMATRIX:143,EPMATRIX:144,BBMATRIX:145,EBMATRIX:146,BVMATRIX:147,EVMATRIX:148,BBBMATRIX:149,
-EBBMATRIX:150,BVVMATRIX:151,EVVMATRIX:152,BSMALLMATRIX:153,ESMALLMATRIX:154,BCASES:155,ECASES:156,BALIGNED:157,EALIGNED:158,BARRAY:159,EARRAY:160,SUBSTACK:161,ARRAY:162,ARRAYOPTS:163,compoundTerm:164,_:165,"^":166,OPP:167,opm:168,OPM:169,FM:170,compoundTermList:171,subsupTermScript:172,subsupTerm:173,textstyle:174,DISPLAYSTYLE:175,TEXTSTYLE:176,TEXTSIZE:177,SCRIPTSIZE:178,SCRIPTSCRIPTSIZE:179,COLOR:180,BGCOLOR:181,tableCell:182,CELLOPTS:183,tableCellList:184,COLSEP:185,tableRow:186,ROWOPTS:187,ROWSEP:188,
-document:189,documentItemList:190,EOF:191,documentItem:192,STARTMATH0:193,ENDMATH0:194,STARTMATH1:195,ENDMATH1:196,STARTMATH2:197,ENDMATH2:198,STARTMATH3:199,ENDMATH3:200,$accept:0,$end:1},B:{2:"error",4:"[",5:"TEXTOPTARG",6:"]",8:"{",9:"TEXTARG",10:"}",19:"COLLAYOUT",21:"COLALIGN",23:"ROWALIGN",25:"ROWSPAN",27:"COLSPAN",29:"ALIGN",31:"EQROWS",33:"EQCOLS",35:"ROWLINES",37:"COLLINES",39:"FRAME",41:"PADDING",49:"LEFT",50:"OPFS",51:".",53:"RIGHT",56:"BIG",57:"BBIG",58:"BIGG",59:"BBIGG",60:"BIGL",61:"BBIGL",
-62:"BIGGL",63:"BBIGGL",64:"TEXATOP",65:"TEXOVER",66:"TEXCHOOSE",67:"NUM",68:"TEXT",69:"A",70:"F",71:"MI",72:"MN",73:"MO",74:"OP",75:"OPS",76:"OPAS",77:"MS",78:"MTEXT",79:"HIGH_SURROGATE",80:"LOW_SURROGATE",81:"BMP_CHARACTER",82:"OPERATORNAME",83:"MATHOP",84:"MATHBIN",85:"MATHREL",86:"FRAC",87:"ROOT",88:"SQRT",89:"UNDERSET",90:"OVERSET",91:"UNDEROVERSET",92:"XARROW",93:"MATHRLAP",94:"MATHLLAP",95:"MATHCLAP",96:"PHANTOM",97:"TFRAC",98:"BINOM",99:"TBINOM",100:"PMOD",101:"UNDERBRACE",102:"UNDERLINE",
-103:"OVERBRACE",104:"ACCENT",105:"ACCENTNS",106:"BOXED",107:"SLASH",108:"QUAD",109:"QQUAD",110:"NEGSPACE",111:"NEGMEDSPACE",112:"NEGTHICKSPACE",113:"THINSPACE",114:"MEDSPACE",115:"THICKSPACE",116:"SPACE",117:"MATHRAISEBOX",118:"MATHBB",119:"MATHBF",120:"MATHBIT",121:"MATHSCR",122:"MATHBSCR",123:"MATHSF",124:"MATHFRAK",125:"MATHIT",126:"MATHTT",127:"MATHRM",128:"HREF",129:"STATUSLINE",130:"TOOLTIP",131:"TOGGLE",132:"BTOGGLE",134:"ETOGGLE",135:"TENSOR",137:"MULTI",138:"BMATRIX",140:"EMATRIX",141:"BGATHERED",
-142:"EGATHERED",143:"BPMATRIX",144:"EPMATRIX",145:"BBMATRIX",146:"EBMATRIX",147:"BVMATRIX",148:"EVMATRIX",149:"BBBMATRIX",150:"EBBMATRIX",151:"BVVMATRIX",152:"EVVMATRIX",153:"BSMALLMATRIX",154:"ESMALLMATRIX",155:"BCASES",156:"ECASES",157:"BALIGNED",158:"EALIGNED",159:"BARRAY",160:"EARRAY",161:"SUBSTACK",162:"ARRAY",163:"ARRAYOPTS",165:"_",166:"^",167:"OPP",169:"OPM",170:"FM",175:"DISPLAYSTYLE",176:"TEXTSTYLE",177:"TEXTSIZE",178:"SCRIPTSIZE",179:"SCRIPTSCRIPTSIZE",180:"COLOR",181:"BGCOLOR",183:"CELLOPTS",
-185:"COLSEP",187:"ROWOPTS",188:"ROWSEP",191:"EOF",193:"STARTMATH0",194:"ENDMATH0",195:"STARTMATH1",196:"ENDMATH1",197:"STARTMATH2",198:"ENDMATH2",199:"STARTMATH3",200:"ENDMATH3"},W:[0,[3,3],[7,3],[11,3],[12,3],[13,1],[14,1],[15,1],[16,1],[17,1],[18,2],[20,2],[22,2],[24,2],[26,2],[28,2],[30,2],[32,2],[34,2],[36,2],[38,2],[40,2],[42,1],[42,1],[42,1],[42,1],[43,1],[43,2],[44,1],[44,1],[45,1],[45,1],[45,1],[45,1],[45,1],[45,1],[45,1],[45,1],[45,1],[45,1],[46,1],[46,2],[47,1],[47,2],[48,2],[48,2],[52,
-2],[52,2],[54,2],[54,3],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,3],[54,5],[54,5],[54,5],[54,5],[54,5],[54,5],[54,1],[54,1],[54,1],[54,1],[54,2],[54,2],[54,2],[54,1],[54,1],[54,1],[54,1],[54,1],[54,2],[54,4],[54,2],[54,2],[54,1],[54,2],[54,2],[54,2],[54,2],[54,3],[54,3],[54,2],[54,5],[54,3],[54,3],[54,4],[54,5],[54,2],[54,2],[54,2],[54,2],[54,2],[54,3],[54,3],[54,3],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,
-4],[54,5],[54,4],[54,3],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,3],[54,3],[54,3],[54,3],[54,3],[54,5],[54,8],[54,7],[54,7],[54,3],[54,3],[54,3],[54,3],[54,3],[54,3],[54,3],[54,3],[54,3],[54,3],[54,5],[54,4],[54,4],[54,4],[54,8],[133,1],[133,2],[164,3],[164,5],[164,4],[164,5],[164,4],[164,3],[164,3],[164,2],[164,1],[164,5],[164,5],[164,3],[164,3],[164,1],[168,1],[168,1],[171,1],[171,2],[172,1],[172,1],[173,4],[173,2],[173,2],[173,3],[136,1],[136,2],[174,1],[174,1],
-[174,1],[174,1],[174,1],[174,2],[174,2],[55,2],[55,1],[182,0],[182,5],[182,1],[184,1],[184,3],[186,5],[186,1],[139,1],[139,3],[189,2],[190,1],[190,2],[192,1],[192,2],[192,3],[192,2],[192,3],[192,3],[192,3]],I:function(b,a,G,e,g,c){b=c.length-1;switch(g){case 1:this.b=c[b-1].replace(/\\[\\\]]/g,function(a){return a.slice(1)});this.b=t(this.b);break;case 2:this.b=c[b-1].replace(/\\[\\\}]/g,function(a){return a.slice(1)});this.b=t(this.b);break;case 3:this.b=B(c[b-1]);break;case 4:this.b=B(c[b-1]);break;
-case 5:this.b='"'+c[b].replace(/"/g,"&#x22;")+'"';break;case 6:this.b='"'+c[b].replace(/"/g,"&#x22;")+'"';break;case 7:this.b=c[b].replace(/\s+/g," ").replace(/^ | $/g," ");break;case 8:c[b]=c[b].trim();if("t"===c[b])this.b="axis 1";else if("c"===c[b])this.b="center";else if("b"===c[b])this.b="axis -1";else throw"Unknown array alignment";break;case 9:this.b="";c[b]=c[b].replace(/\s+/g,"");for(e=0;e<c[b].length;e++)"c"===c[b][e]?this.b+=" center":"l"===c[b][e]?this.b+=" left":"r"===c[b][e]&&(this.b+=
-" right");if(this.b.length)this.b=this.b.slice(1);else throw"Invalid column alignments";break;case 10:this.b="columnalign="+c[b];break;case 11:this.b="columnalign="+c[b];break;case 12:this.b="rowalign="+c[b];break;case 13:this.b="rowspan="+c[b];break;case 14:this.b="colspan="+c[b];break;case 15:this.b="align="+c[b];break;case 16:this.b="equalrows="+c[b];break;case 17:this.b="equalcolumns="+c[b];break;case 18:this.b="rowlines="+c[b];break;case 19:this.b="columnlines="+c[b];break;case 20:this.b="frame="+
-c[b];break;case 21:this.b="rowspacing="+c[b]+" columnspacing="+c[b];break;case 22:this.b=c[b];break;case 23:this.b=c[b];break;case 24:this.b=c[b];break;case 25:this.b=c[b];break;case 26:this.b=c[b];break;case 27:this.b=c[b-1]+" "+c[b];break;case 28:this.b=c[b];break;case 29:this.b=c[b];break;case 30:this.b=c[b];break;case 31:this.b=c[b];break;case 32:this.b=c[b];break;case 33:this.b=c[b];break;case 34:this.b=c[b];break;case 35:this.b=c[b];break;case 36:this.b=c[b];break;case 37:this.b=c[b];break;
-case 38:this.b=c[b];break;case 39:this.b=c[b];break;case 40:this.b=c[b];break;case 41:this.b=c[b-1]+" "+c[b];break;case 42:this.b=c[b];break;case 43:this.b=c[b-1]+" "+c[b];break;case 44:this.b=f(c[b]);break;case 45:this.b="";break;case 46:this.b=f(c[b]);break;case 47:this.b="";break;case 48:this.b="<mrow/>";break;case 49:this.b=k(c[b-1]);break;case 50:this.b=d("mo",c[b],'maxsize="1.2em" minsize="1.2em"');break;case 51:this.b=d("mo",c[b],'maxsize="1.8em" minsize="1.8em"');break;case 52:this.b=d("mo",
-c[b],'maxsize="2.4em" minsize="2.4em"');break;case 53:this.b=d("mo",c[b],'maxsize="3em" minsize="3em"');break;case 54:this.b=d("mo",c[b],'maxsize="1.2em" minsize="1.2em"');break;case 55:this.b=d("mo",c[b],'maxsize="1.8em" minsize="1.8em"');break;case 56:this.b=d("mo",c[b],'maxsize="2.4em" minsize="2.4em"');break;case 57:this.b=d("mo",c[b],'maxsize="3em" minsize="3em"');break;case 58:this.b=d("mrow",c[b-2]+k(c[b-1])+c[b]);break;case 59:this.b=d("mfrac",k(c[b-3])+k(c[b-1]),'linethickness="0"');break;
-case 60:this.b=d("mfrac",k(c[b-3])+k(c[b-1]),'linethickness="0"');this.b=d("mrow",c[b-4]+this.b+c[b-2]);break;case 61:this.b=d("mfrac",k(c[b-3])+k(c[b-1]));break;case 62:this.b=d("mfrac",k(c[b-3])+k(c[b-1]));this.b=d("mrow",c[b-4]+this.b+c[b-2]);break;case 63:this.b=d("mfrac",k(c[b-3])+k(c[b-1]),'linethickness="0"');this.b=d("mrow",f("(")+this.b+f(")"));break;case 64:this.b=d("mfrac",k(c[b-3])+k(c[b-1]),'linethickness="0"');this.b=d("mrow",c[b-4]+this.b+c[b-2]);this.b=d("mrow",f("(")+this.b+f(")"));
-break;case 65:this.b=d("mn",c[b]);break;case 66:this.b=d("mtext",c[b]);break;case 67:this.b=d("mi",t(c[b]));break;case 68:this.b=f(c[b],"0em","0em");break;case 69:this.b=d("mi",c[b]);break;case 70:this.b=d("mn",c[b]);break;case 71:this.b=f(c[b]);break;case 72:this.b=f(c[b]);break;case 73:this.b=f(c[b]);break;case 74:this.b=d("mo",c[b],'stretchy="false"');break;case 75:this.b=d("mo",c[b],'stretchy="false"');break;case 76:this.b=d("mo",c[b],'stretchy="false"');break;case 77:this.b=d("ms",c[b]);break;
-case 78:this.b=d("ms",c[b],"lquote="+c[b-2]+" rquote="+c[b-1]);break;case 79:this.b=d("mtext",c[b]);break;case 80:this.b=d("mtext",c[b-1]+c[b]);break;case 81:this.b=d("mtext",c[b]);break;case 82:this.b=f(c[b],"0em","thinmathspace");break;case 83:this.b=f(c[b],"thinmathspace","thinmathspace");break;case 84:this.b=f(c[b],"mediummathspace","mediummathspace");break;case 85:this.b=f(c[b],"thickmathspace","thickmathspace");break;case 86:this.b=d("mfrac",c[b-1]+c[b]);break;case 87:this.b=d("mroot",c[b]+
-c[b-1]);break;case 88:this.b=d("msqrt",c[b]);break;case 89:this.b=d("mroot",c[b]+k(c[b-2]));break;case 90:this.b=d("munder",c[b]+c[b-1]);break;case 91:this.b=d("mover",c[b]+c[b-1]);break;case 92:this.b=d("munderover",c[b]+c[b-2]+c[b-1]);break;case 93:this.b="<mrow/>"===c[b]?d("munder",f(c[b-4])+k(c[b-2])):d("munderover",f(c[b-4])+k(c[b-2])+c[b]);break;case 94:this.b=d("mover",f(c[b-1])+c[b]);break;case 95:this.b=d("mpadded",c[b],'width="0em"');break;case 96:this.b=d("mpadded",c[b],'width="0em" lspace="-100%width"');
-break;case 97:this.b=d("mpadded",c[b],'width="0em" lspace="-50%width"');break;case 98:this.b=d("mphantom",c[b]);break;case 99:this.b=d("mfrac",c[b-1]+c[b]);this.b=d("mstyle",this.b,'displaystyle="false"');break;case 100:this.b=d("mfrac",c[b-1]+c[b],'linethickness="0"');this.b=d("mrow",f("(")+this.b+f(")"));break;case 101:this.b=d("mfrac",c[b-1]+c[b],'linethickness="0"');this.b=d("mstyle",this.b,'displaystyle="false"');this.b=d("mrow",f("(")+this.b+f(")"));break;case 102:this.b='<mrow><mo lspace="mediummathspace">(</mo><mo rspace="thinmathspace">mod</mo>'+
-c[b]+'<mo rspace="mediummathspace">)</mo></mrow>';break;case 103:this.b=d("munder",c[b]+f("⏟"));break;case 104:this.b=d("munder",c[b]+f("_"));break;case 105:this.b=d("mover",c[b]+f("⏞"));break;case 106:this.b=d("mover",c[b]+f(c[b-1]));break;case 107:this.b=d("mover",c[b]+d("mo",c[b-1],'stretchy="false"'));break;case 108:this.b=d("menclose",c[b],'notation="box"');break;case 109:this.b=d("menclose",c[b],'notation="updiagonalstrike"');break;case 110:this.b='<mspace width="1em"/>';break;case 111:this.b=
-'<mspace width="2em"/>';break;case 112:this.b='<mspace width="negativethinmathspace"/>';break;case 113:this.b='<mspace width="negativemediummathspace"/>';break;case 114:this.b='<mspace width="negativethickmathspace"/>';break;case 115:this.b='<mspace width="thinmathspace"/>';break;case 116:this.b='<mspace width="mediummathspace"/>';break;case 117:this.b='<mspace width="thickmathspace"/>';break;case 118:this.b='<mspace height=".'+c[b-2]+'ex" depth=".'+c[b-1]+'ex" width=".'+c[b]+'em"/>';break;case 119:this.b=
-d("mpadded",c[b],'voffset="'+c[b-3].j+c[b-3].l+'" height="'+c[b-2].j+c[b-2].l+'" depth="'+c[b-1].j+c[b-1].l+'"');break;case 120:this.b=d("mpadded",c[b],'voffset="'+c[b-2].j+c[b-2].l+'" height="'+c[b-1].j+c[b-1].l+'" depth="'+(0>c[b-2].j?"+"+-c[b-2].j+c[b-2].l:"depth")+'"');break;case 121:this.b=d("mpadded",c[b],'voffset="'+c[b-1].j+c[b-1].l+'" '+(0<=c[b-1].j?'height="+'+c[b-1].j+c[b-1].l+'"':'height="0pt" depth="+'+-c[b-1].j+c[b-1].l+'"'));break;case 122:this.b=d("mstyle",c[b],'mathvariant="double-struck"');
-break;case 123:this.b=d("mstyle",c[b],'mathvariant="bold"');break;case 124:this.b=d("mstyle",c[b],'mathvariant="bold-italic"');break;case 125:this.b=d("mstyle",c[b],'mathvariant="script"');break;case 126:this.b=d("mstyle",c[b],'mathvariant="bold-script"');break;case 127:this.b=d("mstyle",c[b],'mathvariant="sans-serif"');break;case 128:this.b=d("mstyle",c[b],'mathvariant="fraktur"');break;case 129:this.b=d("mstyle",c[b],'mathvariant="italic"');break;case 130:this.b=d("mstyle",c[b],'mathvariant="monospace"');
-break;case 131:this.b=d("mstyle",c[b],'mathvariant="normal"');break;case 132:this.b=d("mrow",c[b],e.w?n:"href="+c[b-1]);break;case 133:this.b=e.w?c[b]:d("maction",c[b]+d("mtext",c[b-1]),'actiontype="statusline"');break;case 134:this.b=e.w?c[b]:d("maction",c[b]+d("mtext",c[b-1]),'actiontype="tooltip"');break;case 135:this.b=e.w?c[b]:d("maction",c[b-1]+c[b],'actiontype="toggle" selection="2"');break;case 136:this.b=e.w?d("mrow",c[b-1]):d("maction",c[b-1],'actiontype="toggle"');break;case 137:this.b=
-d("mmultiscripts",c[b-3]+c[b-1]);break;case 138:this.b=d("mmultiscripts",c[b-3]+c[b-1]+"<mprescripts/>"+c[b-5]);break;case 139:this.b=d("mmultiscripts",c[b-2]+"<mprescripts/>"+c[b-4]);break;case 140:this.b=d("mmultiscripts",c[b-3]+c[b-1]);break;case 141:this.b=d("mtable",c[b-1],'displaystyle="false" rowspacing="0.5ex"');break;case 142:this.b=d("mtable",c[b-1],'displaystyle="true" rowspacing="1.0ex"');break;case 143:this.b=d("mtable",c[b-1],'displaystyle="false" rowspacing="0.5ex"');this.b=d("mrow",
-f("(")+this.b+f(")"));break;case 144:this.b=d("mtable",c[b-1],'displaystyle="false" rowspacing="0.5ex"');this.b=d("mrow",f("[")+this.b+f("]"));break;case 145:this.b=d("mtable",c[b-1],'displaystyle="false" rowspacing="0.5ex"');this.b=d("mrow",f("|")+this.b+f("|"));break;case 146:this.b=d("mtable",c[b-1],'displaystyle="false" rowspacing="0.5ex"');this.b=d("mrow",f("{")+this.b+f("}"));break;case 147:this.b=d("mtable",c[b-1],'displaystyle="false" rowspacing="0.5ex"');this.b=d("mrow",f("‖")+this.b+f("‖"));
-break;case 148:this.b=d("mtable",c[b-1],'displaystyle="false" rowspacing="0.5ex"');this.b=d("mstyle",this.b,'scriptlevel="2"');break;case 149:this.b=d("mtable",c[b-1],'displaystyle="false" columnalign="left left"');this.b=d("mrow",f("{")+this.b);break;case 150:this.b=d("mtable",c[b-1],'displaystyle="true" columnalign="right left right left right left right left right left" columnspacing="0em"');break;case 151:this.b=d("mtable",c[b-1],'displaystyle="false" rowspacing="0.5ex" align="'+c[b-3]+'" columnalign="'+
-c[b-2]+'"');break;case 152:this.b=d("mtable",c[b-1],'displaystyle="false" rowspacing="0.5ex" columnalign="'+c[b-2]+'"');break;case 153:this.b=d("mtable",c[b-1],'displaystyle="false" columnalign="center" rowspacing="0.5ex"');break;case 154:this.b=d("mtable",c[b-1],'displaystyle="false"');break;case 155:this.b=d("mtable",c[b-1],'displaystyle="false" '+c[b-3]);break;case 156:this.b=c[b];break;case 157:this.b=c[b-1]+c[b];break;case 158:this.b=d("mmultiscripts",c[b-1]+c[b]);break;case 159:this.b=r(p,c[b-
-4],c[b-2],c[b]);break;case 160:this.b=r(p,c[b-3],c[b-1],f(c[b]));break;case 161:this.b=r(p,c[b-4],c[b],c[b-2]);break;case 162:this.b=r(p,c[b-3],c[b],f(c[b-2]));break;case 163:this.b=r(p,c[b-2],c[b],n);break;case 164:this.b=r(p,c[b-2],n,c[b]);break;case 165:this.b=r(p,c[b-1],n,f(c[b]));break;case 166:this.b=c[b];break;case 167:this.b=r(h,c[b-4],c[b-2],c[b]);break;case 168:this.b=r(h,c[b-4],c[b],c[b-2]);break;case 169:this.b=r(h,c[b-2],c[b],n);break;case 170:this.b=r(h,c[b-2],n,c[b]);break;case 171:this.b=
-c[b];break;case 172:this.b=f(c[b]);break;case 173:this.b=f(c[b],"0em","0em");break;case 174:this.b=[c[b]];break;case 175:c[b-1].push(c[b]);this.b=c[b-1];break;case 176:this.b=c[b];break;case 177:this.b=c[b];break;case 178:this.b=c[b-2]+c[b];break;case 179:this.b=c[b]+"<none/>";break;case 180:this.b="<none/>"+c[b];break;case 181:this.b="<none/>"+c[b];break;case 182:this.b=c[b];break;case 183:this.b=c[b-1]+c[b];break;case 184:this.b='displaystyle="true"';break;case 185:this.b='displaystyle="false"';
-break;case 186:this.b='scriptlevel="0"';break;case 187:this.b='scriptlevel="1"';break;case 188:this.b='scriptlevel="2"';break;case 189:this.b="mathcolor="+c[b];break;case 190:this.b="mathbackground="+c[b];break;case 191:this.b=[k(c[b],"mstyle",c[b-1])];break;case 192:this.b=c[b];break;case 193:this.b=d("mtd","");break;case 194:this.b=k(c[b],"mtd",c[b-2]);break;case 195:this.b=k(c[b],"mtd");break;case 196:this.b=c[b];break;case 197:this.b=c[b-2]+c[b];break;case 198:this.b=this.b=d("mtr",c[b],c[b-2]);
-break;case 199:this.b=d("mtr",c[b]);break;case 200:this.b=c[b];break;case 201:this.b=c[b-2]+c[b];break;case 202:return this.b=c[b-1];case 203:this.b=c[b];break;case 204:this.b=c[b-1]+c[b];break;case 205:this.b=c[b];break;case 206:this.b=w(["<mrow/>"],p,e.u);break;case 207:this.b=w(c[b-1],p,e.u);break;case 208:this.b=w(["<mrow/>"],h,e.u);break;case 209:this.b=w(c[b-1],h,e.u);break;case 210:this.b=w(c[b-1],p,e.u);break;case 211:this.b=w(c[b-1],h,e.u)}},ma:[{68:[1,4],189:1,190:2,192:3,193:[1,5],195:[1,
-6],197:[1,7],199:[1,8]},{1:[3]},{68:[1,4],191:[1,9],192:10,193:[1,5],195:[1,6],197:[1,7],199:[1,8]},{68:[2,203],191:[2,203],193:[2,203],195:[2,203],197:[2,203],199:[2,203]},{68:[2,205],191:[2,205],193:[2,205],195:[2,205],197:[2,205],199:[2,205]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:12,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,
-49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],
-127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21],194:[1,11]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:121,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,
-32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,
-84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],
-181:[1,21],196:[1,120]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:122,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,
-71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],
-161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:123,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],
-89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,
-104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21]},{1:[2,202]},{68:[2,204],191:[2,204],193:[2,204],195:[2,204],197:[2,204],199:[2,204]},{68:[2,206],191:[2,206],193:[2,206],195:[2,206],197:[2,206],199:[2,206]},{194:[1,124]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,
-55:125,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,
-78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,
-175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21]},{6:[2,192],8:[1,26],10:[2,192],48:35,49:[1,119],50:[1,47],51:[1,43],53:[2,192],54:24,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],64:[2,192],65:[2,192],66:[2,192],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,
-60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],140:[2,
-192],141:[1,105],142:[2,192],143:[1,106],144:[2,192],145:[1,107],146:[2,192],147:[1,108],148:[2,192],149:[1,109],150:[2,192],151:[1,110],152:[2,192],153:[1,111],154:[2,192],155:[1,112],156:[2,192],157:[1,113],158:[2,192],159:[1,114],160:[2,192],161:[1,115],162:[1,116],164:126,168:25,169:[1,117],170:[1,118],185:[2,192],188:[2,192],194:[2,192],196:[2,192],198:[2,192],200:[2,192]},{8:[2,184],49:[2,184],50:[2,184],51:[2,184],56:[2,184],57:[2,184],58:[2,184],59:[2,184],60:[2,184],61:[2,184],62:[2,184],
-63:[2,184],67:[2,184],68:[2,184],69:[2,184],70:[2,184],71:[2,184],72:[2,184],73:[2,184],74:[2,184],75:[2,184],76:[2,184],77:[2,184],78:[2,184],79:[2,184],81:[2,184],82:[2,184],83:[2,184],84:[2,184],85:[2,184],86:[2,184],87:[2,184],88:[2,184],89:[2,184],90:[2,184],91:[2,184],92:[2,184],93:[2,184],94:[2,184],95:[2,184],96:[2,184],97:[2,184],98:[2,184],99:[2,184],100:[2,184],101:[2,184],102:[2,184],103:[2,184],104:[2,184],105:[2,184],106:[2,184],107:[2,184],108:[2,184],109:[2,184],110:[2,184],111:[2,
-184],112:[2,184],113:[2,184],114:[2,184],115:[2,184],116:[2,184],117:[2,184],118:[2,184],119:[2,184],120:[2,184],121:[2,184],122:[2,184],123:[2,184],124:[2,184],125:[2,184],126:[2,184],127:[2,184],128:[2,184],129:[2,184],130:[2,184],131:[2,184],132:[2,184],135:[2,184],137:[2,184],138:[2,184],141:[2,184],143:[2,184],145:[2,184],147:[2,184],149:[2,184],151:[2,184],153:[2,184],155:[2,184],157:[2,184],159:[2,184],161:[2,184],162:[2,184],169:[2,184],170:[2,184],175:[2,184],176:[2,184],177:[2,184],178:[2,
-184],179:[2,184],180:[2,184],181:[2,184]},{8:[2,185],49:[2,185],50:[2,185],51:[2,185],56:[2,185],57:[2,185],58:[2,185],59:[2,185],60:[2,185],61:[2,185],62:[2,185],63:[2,185],67:[2,185],68:[2,185],69:[2,185],70:[2,185],71:[2,185],72:[2,185],73:[2,185],74:[2,185],75:[2,185],76:[2,185],77:[2,185],78:[2,185],79:[2,185],81:[2,185],82:[2,185],83:[2,185],84:[2,185],85:[2,185],86:[2,185],87:[2,185],88:[2,185],89:[2,185],90:[2,185],91:[2,185],92:[2,185],93:[2,185],94:[2,185],95:[2,185],96:[2,185],97:[2,185],
-98:[2,185],99:[2,185],100:[2,185],101:[2,185],102:[2,185],103:[2,185],104:[2,185],105:[2,185],106:[2,185],107:[2,185],108:[2,185],109:[2,185],110:[2,185],111:[2,185],112:[2,185],113:[2,185],114:[2,185],115:[2,185],116:[2,185],117:[2,185],118:[2,185],119:[2,185],120:[2,185],121:[2,185],122:[2,185],123:[2,185],124:[2,185],125:[2,185],126:[2,185],127:[2,185],128:[2,185],129:[2,185],130:[2,185],131:[2,185],132:[2,185],135:[2,185],137:[2,185],138:[2,185],141:[2,185],143:[2,185],145:[2,185],147:[2,185],
-149:[2,185],151:[2,185],153:[2,185],155:[2,185],157:[2,185],159:[2,185],161:[2,185],162:[2,185],169:[2,185],170:[2,185],175:[2,185],176:[2,185],177:[2,185],178:[2,185],179:[2,185],180:[2,185],181:[2,185]},{8:[2,186],49:[2,186],50:[2,186],51:[2,186],56:[2,186],57:[2,186],58:[2,186],59:[2,186],60:[2,186],61:[2,186],62:[2,186],63:[2,186],67:[2,186],68:[2,186],69:[2,186],70:[2,186],71:[2,186],72:[2,186],73:[2,186],74:[2,186],75:[2,186],76:[2,186],77:[2,186],78:[2,186],79:[2,186],81:[2,186],82:[2,186],
-83:[2,186],84:[2,186],85:[2,186],86:[2,186],87:[2,186],88:[2,186],89:[2,186],90:[2,186],91:[2,186],92:[2,186],93:[2,186],94:[2,186],95:[2,186],96:[2,186],97:[2,186],98:[2,186],99:[2,186],100:[2,186],101:[2,186],102:[2,186],103:[2,186],104:[2,186],105:[2,186],106:[2,186],107:[2,186],108:[2,186],109:[2,186],110:[2,186],111:[2,186],112:[2,186],113:[2,186],114:[2,186],115:[2,186],116:[2,186],117:[2,186],118:[2,186],119:[2,186],120:[2,186],121:[2,186],122:[2,186],123:[2,186],124:[2,186],125:[2,186],126:[2,
-186],127:[2,186],128:[2,186],129:[2,186],130:[2,186],131:[2,186],132:[2,186],135:[2,186],137:[2,186],138:[2,186],141:[2,186],143:[2,186],145:[2,186],147:[2,186],149:[2,186],151:[2,186],153:[2,186],155:[2,186],157:[2,186],159:[2,186],161:[2,186],162:[2,186],169:[2,186],170:[2,186],175:[2,186],176:[2,186],177:[2,186],178:[2,186],179:[2,186],180:[2,186],181:[2,186]},{8:[2,187],49:[2,187],50:[2,187],51:[2,187],56:[2,187],57:[2,187],58:[2,187],59:[2,187],60:[2,187],61:[2,187],62:[2,187],63:[2,187],67:[2,
-187],68:[2,187],69:[2,187],70:[2,187],71:[2,187],72:[2,187],73:[2,187],74:[2,187],75:[2,187],76:[2,187],77:[2,187],78:[2,187],79:[2,187],81:[2,187],82:[2,187],83:[2,187],84:[2,187],85:[2,187],86:[2,187],87:[2,187],88:[2,187],89:[2,187],90:[2,187],91:[2,187],92:[2,187],93:[2,187],94:[2,187],95:[2,187],96:[2,187],97:[2,187],98:[2,187],99:[2,187],100:[2,187],101:[2,187],102:[2,187],103:[2,187],104:[2,187],105:[2,187],106:[2,187],107:[2,187],108:[2,187],109:[2,187],110:[2,187],111:[2,187],112:[2,187],
-113:[2,187],114:[2,187],115:[2,187],116:[2,187],117:[2,187],118:[2,187],119:[2,187],120:[2,187],121:[2,187],122:[2,187],123:[2,187],124:[2,187],125:[2,187],126:[2,187],127:[2,187],128:[2,187],129:[2,187],130:[2,187],131:[2,187],132:[2,187],135:[2,187],137:[2,187],138:[2,187],141:[2,187],143:[2,187],145:[2,187],147:[2,187],149:[2,187],151:[2,187],153:[2,187],155:[2,187],157:[2,187],159:[2,187],161:[2,187],162:[2,187],169:[2,187],170:[2,187],175:[2,187],176:[2,187],177:[2,187],178:[2,187],179:[2,187],
-180:[2,187],181:[2,187]},{8:[2,188],49:[2,188],50:[2,188],51:[2,188],56:[2,188],57:[2,188],58:[2,188],59:[2,188],60:[2,188],61:[2,188],62:[2,188],63:[2,188],67:[2,188],68:[2,188],69:[2,188],70:[2,188],71:[2,188],72:[2,188],73:[2,188],74:[2,188],75:[2,188],76:[2,188],77:[2,188],78:[2,188],79:[2,188],81:[2,188],82:[2,188],83:[2,188],84:[2,188],85:[2,188],86:[2,188],87:[2,188],88:[2,188],89:[2,188],90:[2,188],91:[2,188],92:[2,188],93:[2,188],94:[2,188],95:[2,188],96:[2,188],97:[2,188],98:[2,188],99:[2,
-188],100:[2,188],101:[2,188],102:[2,188],103:[2,188],104:[2,188],105:[2,188],106:[2,188],107:[2,188],108:[2,188],109:[2,188],110:[2,188],111:[2,188],112:[2,188],113:[2,188],114:[2,188],115:[2,188],116:[2,188],117:[2,188],118:[2,188],119:[2,188],120:[2,188],121:[2,188],122:[2,188],123:[2,188],124:[2,188],125:[2,188],126:[2,188],127:[2,188],128:[2,188],129:[2,188],130:[2,188],131:[2,188],132:[2,188],135:[2,188],137:[2,188],138:[2,188],141:[2,188],143:[2,188],145:[2,188],147:[2,188],149:[2,188],151:[2,
-188],153:[2,188],155:[2,188],157:[2,188],159:[2,188],161:[2,188],162:[2,188],169:[2,188],170:[2,188],175:[2,188],176:[2,188],177:[2,188],178:[2,188],179:[2,188],180:[2,188],181:[2,188]},{7:128,8:[1,129],14:127},{7:128,8:[1,129],14:130},{6:[2,174],8:[2,174],10:[2,174],49:[2,174],50:[2,174],51:[2,174],53:[2,174],56:[2,174],57:[2,174],58:[2,174],59:[2,174],60:[2,174],61:[2,174],62:[2,174],63:[2,174],64:[2,174],65:[2,174],66:[2,174],67:[2,174],68:[2,174],69:[2,174],70:[2,174],71:[2,174],72:[2,174],73:[2,
-174],74:[2,174],75:[2,174],76:[2,174],77:[2,174],78:[2,174],79:[2,174],81:[2,174],82:[2,174],83:[2,174],84:[2,174],85:[2,174],86:[2,174],87:[2,174],88:[2,174],89:[2,174],90:[2,174],91:[2,174],92:[2,174],93:[2,174],94:[2,174],95:[2,174],96:[2,174],97:[2,174],98:[2,174],99:[2,174],100:[2,174],101:[2,174],102:[2,174],103:[2,174],104:[2,174],105:[2,174],106:[2,174],107:[2,174],108:[2,174],109:[2,174],110:[2,174],111:[2,174],112:[2,174],113:[2,174],114:[2,174],115:[2,174],116:[2,174],117:[2,174],118:[2,
-174],119:[2,174],120:[2,174],121:[2,174],122:[2,174],123:[2,174],124:[2,174],125:[2,174],126:[2,174],127:[2,174],128:[2,174],129:[2,174],130:[2,174],131:[2,174],132:[2,174],135:[2,174],137:[2,174],138:[2,174],140:[2,174],141:[2,174],142:[2,174],143:[2,174],144:[2,174],145:[2,174],146:[2,174],147:[2,174],148:[2,174],149:[2,174],150:[2,174],151:[2,174],152:[2,174],153:[2,174],154:[2,174],155:[2,174],156:[2,174],157:[2,174],158:[2,174],159:[2,174],160:[2,174],161:[2,174],162:[2,174],169:[2,174],170:[2,
-174],185:[2,174],188:[2,174],194:[2,174],196:[2,174],198:[2,174],200:[2,174]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:131,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],
-97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],
-153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{6:[2,166],8:[2,166],10:[2,166],49:[2,166],50:[2,166],51:[2,166],53:[2,166],56:[2,166],57:[2,166],58:[2,166],59:[2,166],60:[2,166],61:[2,166],62:[2,166],63:[2,166],64:[2,166],65:[2,166],66:[2,166],67:[2,166],68:[2,166],69:[2,166],70:[2,166],71:[2,166],72:[2,166],73:[2,166],74:[2,166],75:[2,166],76:[2,166],77:[2,166],78:[2,166],79:[2,166],81:[2,166],82:[2,166],83:[2,166],84:[2,166],85:[2,166],86:[2,166],87:[2,166],88:[2,166],
-89:[2,166],90:[2,166],91:[2,166],92:[2,166],93:[2,166],94:[2,166],95:[2,166],96:[2,166],97:[2,166],98:[2,166],99:[2,166],100:[2,166],101:[2,166],102:[2,166],103:[2,166],104:[2,166],105:[2,166],106:[2,166],107:[2,166],108:[2,166],109:[2,166],110:[2,166],111:[2,166],112:[2,166],113:[2,166],114:[2,166],115:[2,166],116:[2,166],117:[2,166],118:[2,166],119:[2,166],120:[2,166],121:[2,166],122:[2,166],123:[2,166],124:[2,166],125:[2,166],126:[2,166],127:[2,166],128:[2,166],129:[2,166],130:[2,166],131:[2,166],
-132:[2,166],135:[2,166],137:[2,166],138:[2,166],140:[2,166],141:[2,166],142:[2,166],143:[2,166],144:[2,166],145:[2,166],146:[2,166],147:[2,166],148:[2,166],149:[2,166],150:[2,166],151:[2,166],152:[2,166],153:[2,166],154:[2,166],155:[2,166],156:[2,166],157:[2,166],158:[2,166],159:[2,166],160:[2,166],161:[2,166],162:[2,166],165:[1,133],166:[1,134],167:[1,135],169:[2,166],170:[2,166],185:[2,166],188:[2,166],194:[2,166],196:[2,166],198:[2,166],200:[2,166]},{6:[2,171],8:[2,171],10:[2,171],49:[2,171],50:[2,
-171],51:[2,171],53:[2,171],56:[2,171],57:[2,171],58:[2,171],59:[2,171],60:[2,171],61:[2,171],62:[2,171],63:[2,171],64:[2,171],65:[2,171],66:[2,171],67:[2,171],68:[2,171],69:[2,171],70:[2,171],71:[2,171],72:[2,171],73:[2,171],74:[2,171],75:[2,171],76:[2,171],77:[2,171],78:[2,171],79:[2,171],81:[2,171],82:[2,171],83:[2,171],84:[2,171],85:[2,171],86:[2,171],87:[2,171],88:[2,171],89:[2,171],90:[2,171],91:[2,171],92:[2,171],93:[2,171],94:[2,171],95:[2,171],96:[2,171],97:[2,171],98:[2,171],99:[2,171],100:[2,
-171],101:[2,171],102:[2,171],103:[2,171],104:[2,171],105:[2,171],106:[2,171],107:[2,171],108:[2,171],109:[2,171],110:[2,171],111:[2,171],112:[2,171],113:[2,171],114:[2,171],115:[2,171],116:[2,171],117:[2,171],118:[2,171],119:[2,171],120:[2,171],121:[2,171],122:[2,171],123:[2,171],124:[2,171],125:[2,171],126:[2,171],127:[2,171],128:[2,171],129:[2,171],130:[2,171],131:[2,171],132:[2,171],135:[2,171],137:[2,171],138:[2,171],140:[2,171],141:[2,171],142:[2,171],143:[2,171],144:[2,171],145:[2,171],146:[2,
-171],147:[2,171],148:[2,171],149:[2,171],150:[2,171],151:[2,171],152:[2,171],153:[2,171],154:[2,171],155:[2,171],156:[2,171],157:[2,171],158:[2,171],159:[2,171],160:[2,171],161:[2,171],162:[2,171],165:[1,136],166:[1,137],169:[2,171],170:[2,171],185:[2,171],188:[2,171],194:[2,171],196:[2,171],198:[2,171],200:[2,171]},{8:[1,26],10:[1,138],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:139,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,
-39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],
-120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21]},{50:[1,140]},{50:[1,141]},{50:[1,142]},{50:[1,
-143]},{50:[1,144]},{50:[1,145]},{50:[1,146]},{50:[1,147]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:148,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,
-68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,
-112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21]},{6:[2,65],8:[2,65],10:[2,65],49:[2,65],50:[2,65],51:[2,65],53:[2,65],56:[2,65],57:[2,65],58:[2,65],59:[2,65],60:[2,65],61:[2,65],62:[2,65],63:[2,65],64:[2,65],65:[2,65],66:[2,65],67:[2,65],68:[2,65],69:[2,65],70:[2,65],71:[2,65],72:[2,65],73:[2,65],74:[2,65],75:[2,65],76:[2,65],77:[2,65],78:[2,65],79:[2,65],81:[2,65],
-82:[2,65],83:[2,65],84:[2,65],85:[2,65],86:[2,65],87:[2,65],88:[2,65],89:[2,65],90:[2,65],91:[2,65],92:[2,65],93:[2,65],94:[2,65],95:[2,65],96:[2,65],97:[2,65],98:[2,65],99:[2,65],100:[2,65],101:[2,65],102:[2,65],103:[2,65],104:[2,65],105:[2,65],106:[2,65],107:[2,65],108:[2,65],109:[2,65],110:[2,65],111:[2,65],112:[2,65],113:[2,65],114:[2,65],115:[2,65],116:[2,65],117:[2,65],118:[2,65],119:[2,65],120:[2,65],121:[2,65],122:[2,65],123:[2,65],124:[2,65],125:[2,65],126:[2,65],127:[2,65],128:[2,65],129:[2,
-65],130:[2,65],131:[2,65],132:[2,65],134:[2,65],135:[2,65],137:[2,65],138:[2,65],140:[2,65],141:[2,65],142:[2,65],143:[2,65],144:[2,65],145:[2,65],146:[2,65],147:[2,65],148:[2,65],149:[2,65],150:[2,65],151:[2,65],152:[2,65],153:[2,65],154:[2,65],155:[2,65],156:[2,65],157:[2,65],158:[2,65],159:[2,65],160:[2,65],161:[2,65],162:[2,65],165:[2,65],166:[2,65],167:[2,65],169:[2,65],170:[2,65],185:[2,65],188:[2,65],194:[2,65],196:[2,65],198:[2,65],200:[2,65]},{6:[2,66],8:[2,66],10:[2,66],49:[2,66],50:[2,
-66],51:[2,66],53:[2,66],56:[2,66],57:[2,66],58:[2,66],59:[2,66],60:[2,66],61:[2,66],62:[2,66],63:[2,66],64:[2,66],65:[2,66],66:[2,66],67:[2,66],68:[2,66],69:[2,66],70:[2,66],71:[2,66],72:[2,66],73:[2,66],74:[2,66],75:[2,66],76:[2,66],77:[2,66],78:[2,66],79:[2,66],81:[2,66],82:[2,66],83:[2,66],84:[2,66],85:[2,66],86:[2,66],87:[2,66],88:[2,66],89:[2,66],90:[2,66],91:[2,66],92:[2,66],93:[2,66],94:[2,66],95:[2,66],96:[2,66],97:[2,66],98:[2,66],99:[2,66],100:[2,66],101:[2,66],102:[2,66],103:[2,66],104:[2,
-66],105:[2,66],106:[2,66],107:[2,66],108:[2,66],109:[2,66],110:[2,66],111:[2,66],112:[2,66],113:[2,66],114:[2,66],115:[2,66],116:[2,66],117:[2,66],118:[2,66],119:[2,66],120:[2,66],121:[2,66],122:[2,66],123:[2,66],124:[2,66],125:[2,66],126:[2,66],127:[2,66],128:[2,66],129:[2,66],130:[2,66],131:[2,66],132:[2,66],134:[2,66],135:[2,66],137:[2,66],138:[2,66],140:[2,66],141:[2,66],142:[2,66],143:[2,66],144:[2,66],145:[2,66],146:[2,66],147:[2,66],148:[2,66],149:[2,66],150:[2,66],151:[2,66],152:[2,66],153:[2,
-66],154:[2,66],155:[2,66],156:[2,66],157:[2,66],158:[2,66],159:[2,66],160:[2,66],161:[2,66],162:[2,66],165:[2,66],166:[2,66],167:[2,66],169:[2,66],170:[2,66],185:[2,66],188:[2,66],194:[2,66],196:[2,66],198:[2,66],200:[2,66]},{6:[2,67],8:[2,67],10:[2,67],49:[2,67],50:[2,67],51:[2,67],53:[2,67],56:[2,67],57:[2,67],58:[2,67],59:[2,67],60:[2,67],61:[2,67],62:[2,67],63:[2,67],64:[2,67],65:[2,67],66:[2,67],67:[2,67],68:[2,67],69:[2,67],70:[2,67],71:[2,67],72:[2,67],73:[2,67],74:[2,67],75:[2,67],76:[2,67],
-77:[2,67],78:[2,67],79:[2,67],81:[2,67],82:[2,67],83:[2,67],84:[2,67],85:[2,67],86:[2,67],87:[2,67],88:[2,67],89:[2,67],90:[2,67],91:[2,67],92:[2,67],93:[2,67],94:[2,67],95:[2,67],96:[2,67],97:[2,67],98:[2,67],99:[2,67],100:[2,67],101:[2,67],102:[2,67],103:[2,67],104:[2,67],105:[2,67],106:[2,67],107:[2,67],108:[2,67],109:[2,67],110:[2,67],111:[2,67],112:[2,67],113:[2,67],114:[2,67],115:[2,67],116:[2,67],117:[2,67],118:[2,67],119:[2,67],120:[2,67],121:[2,67],122:[2,67],123:[2,67],124:[2,67],125:[2,
-67],126:[2,67],127:[2,67],128:[2,67],129:[2,67],130:[2,67],131:[2,67],132:[2,67],134:[2,67],135:[2,67],137:[2,67],138:[2,67],140:[2,67],141:[2,67],142:[2,67],143:[2,67],144:[2,67],145:[2,67],146:[2,67],147:[2,67],148:[2,67],149:[2,67],150:[2,67],151:[2,67],152:[2,67],153:[2,67],154:[2,67],155:[2,67],156:[2,67],157:[2,67],158:[2,67],159:[2,67],160:[2,67],161:[2,67],162:[2,67],165:[2,67],166:[2,67],167:[2,67],169:[2,67],170:[2,67],185:[2,67],188:[2,67],194:[2,67],196:[2,67],198:[2,67],200:[2,67]},{6:[2,
-68],8:[2,68],10:[2,68],49:[2,68],50:[2,68],51:[2,68],53:[2,68],56:[2,68],57:[2,68],58:[2,68],59:[2,68],60:[2,68],61:[2,68],62:[2,68],63:[2,68],64:[2,68],65:[2,68],66:[2,68],67:[2,68],68:[2,68],69:[2,68],70:[2,68],71:[2,68],72:[2,68],73:[2,68],74:[2,68],75:[2,68],76:[2,68],77:[2,68],78:[2,68],79:[2,68],81:[2,68],82:[2,68],83:[2,68],84:[2,68],85:[2,68],86:[2,68],87:[2,68],88:[2,68],89:[2,68],90:[2,68],91:[2,68],92:[2,68],93:[2,68],94:[2,68],95:[2,68],96:[2,68],97:[2,68],98:[2,68],99:[2,68],100:[2,68],
-101:[2,68],102:[2,68],103:[2,68],104:[2,68],105:[2,68],106:[2,68],107:[2,68],108:[2,68],109:[2,68],110:[2,68],111:[2,68],112:[2,68],113:[2,68],114:[2,68],115:[2,68],116:[2,68],117:[2,68],118:[2,68],119:[2,68],120:[2,68],121:[2,68],122:[2,68],123:[2,68],124:[2,68],125:[2,68],126:[2,68],127:[2,68],128:[2,68],129:[2,68],130:[2,68],131:[2,68],132:[2,68],134:[2,68],135:[2,68],137:[2,68],138:[2,68],140:[2,68],141:[2,68],142:[2,68],143:[2,68],144:[2,68],145:[2,68],146:[2,68],147:[2,68],148:[2,68],149:[2,
-68],150:[2,68],151:[2,68],152:[2,68],153:[2,68],154:[2,68],155:[2,68],156:[2,68],157:[2,68],158:[2,68],159:[2,68],160:[2,68],161:[2,68],162:[2,68],165:[2,68],166:[2,68],167:[2,68],169:[2,68],170:[2,68],185:[2,68],188:[2,68],194:[2,68],196:[2,68],198:[2,68],200:[2,68]},{7:150,8:[1,129],15:149},{7:150,8:[1,129],15:151},{7:150,8:[1,129],15:152},{6:[2,72],8:[2,72],10:[2,72],49:[2,72],50:[2,72],51:[2,72],53:[2,72],56:[2,72],57:[2,72],58:[2,72],59:[2,72],60:[2,72],61:[2,72],62:[2,72],63:[2,72],64:[2,72],
-65:[2,72],66:[2,72],67:[2,72],68:[2,72],69:[2,72],70:[2,72],71:[2,72],72:[2,72],73:[2,72],74:[2,72],75:[2,72],76:[2,72],77:[2,72],78:[2,72],79:[2,72],81:[2,72],82:[2,72],83:[2,72],84:[2,72],85:[2,72],86:[2,72],87:[2,72],88:[2,72],89:[2,72],90:[2,72],91:[2,72],92:[2,72],93:[2,72],94:[2,72],95:[2,72],96:[2,72],97:[2,72],98:[2,72],99:[2,72],100:[2,72],101:[2,72],102:[2,72],103:[2,72],104:[2,72],105:[2,72],106:[2,72],107:[2,72],108:[2,72],109:[2,72],110:[2,72],111:[2,72],112:[2,72],113:[2,72],114:[2,
-72],115:[2,72],116:[2,72],117:[2,72],118:[2,72],119:[2,72],120:[2,72],121:[2,72],122:[2,72],123:[2,72],124:[2,72],125:[2,72],126:[2,72],127:[2,72],128:[2,72],129:[2,72],130:[2,72],131:[2,72],132:[2,72],134:[2,72],135:[2,72],137:[2,72],138:[2,72],140:[2,72],141:[2,72],142:[2,72],143:[2,72],144:[2,72],145:[2,72],146:[2,72],147:[2,72],148:[2,72],149:[2,72],150:[2,72],151:[2,72],152:[2,72],153:[2,72],154:[2,72],155:[2,72],156:[2,72],157:[2,72],158:[2,72],159:[2,72],160:[2,72],161:[2,72],162:[2,72],165:[2,
-72],166:[2,72],167:[2,72],169:[2,72],170:[2,72],185:[2,72],188:[2,72],194:[2,72],196:[2,72],198:[2,72],200:[2,72]},{6:[2,73],8:[2,73],10:[2,73],49:[2,73],50:[2,73],51:[2,73],53:[2,73],56:[2,73],57:[2,73],58:[2,73],59:[2,73],60:[2,73],61:[2,73],62:[2,73],63:[2,73],64:[2,73],65:[2,73],66:[2,73],67:[2,73],68:[2,73],69:[2,73],70:[2,73],71:[2,73],72:[2,73],73:[2,73],74:[2,73],75:[2,73],76:[2,73],77:[2,73],78:[2,73],79:[2,73],81:[2,73],82:[2,73],83:[2,73],84:[2,73],85:[2,73],86:[2,73],87:[2,73],88:[2,73],
-89:[2,73],90:[2,73],91:[2,73],92:[2,73],93:[2,73],94:[2,73],95:[2,73],96:[2,73],97:[2,73],98:[2,73],99:[2,73],100:[2,73],101:[2,73],102:[2,73],103:[2,73],104:[2,73],105:[2,73],106:[2,73],107:[2,73],108:[2,73],109:[2,73],110:[2,73],111:[2,73],112:[2,73],113:[2,73],114:[2,73],115:[2,73],116:[2,73],117:[2,73],118:[2,73],119:[2,73],120:[2,73],121:[2,73],122:[2,73],123:[2,73],124:[2,73],125:[2,73],126:[2,73],127:[2,73],128:[2,73],129:[2,73],130:[2,73],131:[2,73],132:[2,73],134:[2,73],135:[2,73],137:[2,
-73],138:[2,73],140:[2,73],141:[2,73],142:[2,73],143:[2,73],144:[2,73],145:[2,73],146:[2,73],147:[2,73],148:[2,73],149:[2,73],150:[2,73],151:[2,73],152:[2,73],153:[2,73],154:[2,73],155:[2,73],156:[2,73],157:[2,73],158:[2,73],159:[2,73],160:[2,73],161:[2,73],162:[2,73],165:[2,73],166:[2,73],167:[2,73],169:[2,73],170:[2,73],185:[2,73],188:[2,73],194:[2,73],196:[2,73],198:[2,73],200:[2,73]},{6:[2,74],8:[2,74],10:[2,74],49:[2,74],50:[2,74],51:[2,74],53:[2,74],56:[2,74],57:[2,74],58:[2,74],59:[2,74],60:[2,
-74],61:[2,74],62:[2,74],63:[2,74],64:[2,74],65:[2,74],66:[2,74],67:[2,74],68:[2,74],69:[2,74],70:[2,74],71:[2,74],72:[2,74],73:[2,74],74:[2,74],75:[2,74],76:[2,74],77:[2,74],78:[2,74],79:[2,74],81:[2,74],82:[2,74],83:[2,74],84:[2,74],85:[2,74],86:[2,74],87:[2,74],88:[2,74],89:[2,74],90:[2,74],91:[2,74],92:[2,74],93:[2,74],94:[2,74],95:[2,74],96:[2,74],97:[2,74],98:[2,74],99:[2,74],100:[2,74],101:[2,74],102:[2,74],103:[2,74],104:[2,74],105:[2,74],106:[2,74],107:[2,74],108:[2,74],109:[2,74],110:[2,
-74],111:[2,74],112:[2,74],113:[2,74],114:[2,74],115:[2,74],116:[2,74],117:[2,74],118:[2,74],119:[2,74],120:[2,74],121:[2,74],122:[2,74],123:[2,74],124:[2,74],125:[2,74],126:[2,74],127:[2,74],128:[2,74],129:[2,74],130:[2,74],131:[2,74],132:[2,74],134:[2,74],135:[2,74],137:[2,74],138:[2,74],140:[2,74],141:[2,74],142:[2,74],143:[2,74],144:[2,74],145:[2,74],146:[2,74],147:[2,74],148:[2,74],149:[2,74],150:[2,74],151:[2,74],152:[2,74],153:[2,74],154:[2,74],155:[2,74],156:[2,74],157:[2,74],158:[2,74],159:[2,
-74],160:[2,74],161:[2,74],162:[2,74],165:[2,74],166:[2,74],167:[2,74],169:[2,74],170:[2,74],185:[2,74],188:[2,74],194:[2,74],196:[2,74],198:[2,74],200:[2,74]},{6:[2,75],8:[2,75],10:[2,75],49:[2,75],50:[2,75],51:[2,75],53:[2,75],56:[2,75],57:[2,75],58:[2,75],59:[2,75],60:[2,75],61:[2,75],62:[2,75],63:[2,75],64:[2,75],65:[2,75],66:[2,75],67:[2,75],68:[2,75],69:[2,75],70:[2,75],71:[2,75],72:[2,75],73:[2,75],74:[2,75],75:[2,75],76:[2,75],77:[2,75],78:[2,75],79:[2,75],81:[2,75],82:[2,75],83:[2,75],84:[2,
-75],85:[2,75],86:[2,75],87:[2,75],88:[2,75],89:[2,75],90:[2,75],91:[2,75],92:[2,75],93:[2,75],94:[2,75],95:[2,75],96:[2,75],97:[2,75],98:[2,75],99:[2,75],100:[2,75],101:[2,75],102:[2,75],103:[2,75],104:[2,75],105:[2,75],106:[2,75],107:[2,75],108:[2,75],109:[2,75],110:[2,75],111:[2,75],112:[2,75],113:[2,75],114:[2,75],115:[2,75],116:[2,75],117:[2,75],118:[2,75],119:[2,75],120:[2,75],121:[2,75],122:[2,75],123:[2,75],124:[2,75],125:[2,75],126:[2,75],127:[2,75],128:[2,75],129:[2,75],130:[2,75],131:[2,
-75],132:[2,75],134:[2,75],135:[2,75],137:[2,75],138:[2,75],140:[2,75],141:[2,75],142:[2,75],143:[2,75],144:[2,75],145:[2,75],146:[2,75],147:[2,75],148:[2,75],149:[2,75],150:[2,75],151:[2,75],152:[2,75],153:[2,75],154:[2,75],155:[2,75],156:[2,75],157:[2,75],158:[2,75],159:[2,75],160:[2,75],161:[2,75],162:[2,75],165:[2,75],166:[2,75],167:[2,75],169:[2,75],170:[2,75],185:[2,75],188:[2,75],194:[2,75],196:[2,75],198:[2,75],200:[2,75]},{6:[2,76],8:[2,76],10:[2,76],49:[2,76],50:[2,76],51:[2,76],53:[2,76],
-56:[2,76],57:[2,76],58:[2,76],59:[2,76],60:[2,76],61:[2,76],62:[2,76],63:[2,76],64:[2,76],65:[2,76],66:[2,76],67:[2,76],68:[2,76],69:[2,76],70:[2,76],71:[2,76],72:[2,76],73:[2,76],74:[2,76],75:[2,76],76:[2,76],77:[2,76],78:[2,76],79:[2,76],81:[2,76],82:[2,76],83:[2,76],84:[2,76],85:[2,76],86:[2,76],87:[2,76],88:[2,76],89:[2,76],90:[2,76],91:[2,76],92:[2,76],93:[2,76],94:[2,76],95:[2,76],96:[2,76],97:[2,76],98:[2,76],99:[2,76],100:[2,76],101:[2,76],102:[2,76],103:[2,76],104:[2,76],105:[2,76],106:[2,
-76],107:[2,76],108:[2,76],109:[2,76],110:[2,76],111:[2,76],112:[2,76],113:[2,76],114:[2,76],115:[2,76],116:[2,76],117:[2,76],118:[2,76],119:[2,76],120:[2,76],121:[2,76],122:[2,76],123:[2,76],124:[2,76],125:[2,76],126:[2,76],127:[2,76],128:[2,76],129:[2,76],130:[2,76],131:[2,76],132:[2,76],134:[2,76],135:[2,76],137:[2,76],138:[2,76],140:[2,76],141:[2,76],142:[2,76],143:[2,76],144:[2,76],145:[2,76],146:[2,76],147:[2,76],148:[2,76],149:[2,76],150:[2,76],151:[2,76],152:[2,76],153:[2,76],154:[2,76],155:[2,
-76],156:[2,76],157:[2,76],158:[2,76],159:[2,76],160:[2,76],161:[2,76],162:[2,76],165:[2,76],166:[2,76],167:[2,76],169:[2,76],170:[2,76],185:[2,76],188:[2,76],194:[2,76],196:[2,76],198:[2,76],200:[2,76]},{3:155,4:[1,156],7:150,8:[1,129],13:154,15:153},{7:150,8:[1,129],15:157},{80:[1,158]},{6:[2,81],8:[2,81],10:[2,81],49:[2,81],50:[2,81],51:[2,81],53:[2,81],56:[2,81],57:[2,81],58:[2,81],59:[2,81],60:[2,81],61:[2,81],62:[2,81],63:[2,81],64:[2,81],65:[2,81],66:[2,81],67:[2,81],68:[2,81],69:[2,81],70:[2,
-81],71:[2,81],72:[2,81],73:[2,81],74:[2,81],75:[2,81],76:[2,81],77:[2,81],78:[2,81],79:[2,81],81:[2,81],82:[2,81],83:[2,81],84:[2,81],85:[2,81],86:[2,81],87:[2,81],88:[2,81],89:[2,81],90:[2,81],91:[2,81],92:[2,81],93:[2,81],94:[2,81],95:[2,81],96:[2,81],97:[2,81],98:[2,81],99:[2,81],100:[2,81],101:[2,81],102:[2,81],103:[2,81],104:[2,81],105:[2,81],106:[2,81],107:[2,81],108:[2,81],109:[2,81],110:[2,81],111:[2,81],112:[2,81],113:[2,81],114:[2,81],115:[2,81],116:[2,81],117:[2,81],118:[2,81],119:[2,81],
-120:[2,81],121:[2,81],122:[2,81],123:[2,81],124:[2,81],125:[2,81],126:[2,81],127:[2,81],128:[2,81],129:[2,81],130:[2,81],131:[2,81],132:[2,81],134:[2,81],135:[2,81],137:[2,81],138:[2,81],140:[2,81],141:[2,81],142:[2,81],143:[2,81],144:[2,81],145:[2,81],146:[2,81],147:[2,81],148:[2,81],149:[2,81],150:[2,81],151:[2,81],152:[2,81],153:[2,81],154:[2,81],155:[2,81],156:[2,81],157:[2,81],158:[2,81],159:[2,81],160:[2,81],161:[2,81],162:[2,81],165:[2,81],166:[2,81],167:[2,81],169:[2,81],170:[2,81],185:[2,
-81],188:[2,81],194:[2,81],196:[2,81],198:[2,81],200:[2,81]},{7:159,8:[1,129]},{7:160,8:[1,129]},{7:161,8:[1,129]},{7:162,8:[1,129]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:163,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,
-61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,
-106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:164,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,
-62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,
-107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{4:[1,166],8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:165,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,
-62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,
-107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:167,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,
-63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],
-147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:168,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],
-94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,
-108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:169,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,
-64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],
-149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{4:[1,170],8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:171,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],
-94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,
-108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:172,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,
-64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],
-149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:173,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],
-95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,
-109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:174,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],
-96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],
-151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:175,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,
-66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,
-110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:176,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],
-97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],
-153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:177,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,
-67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,
-111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:178,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,
-68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,
-112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:179,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,
-69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],
-157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:180,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],
-100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,
-113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:181,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,
-70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],
-159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:182,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],
-101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,
-114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:183,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,
-71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],
-161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:184,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],
-102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,
-115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:185,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,
-72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],
-162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:186,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,
-73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,
-116]},{6:[2,110],8:[2,110],10:[2,110],49:[2,110],50:[2,110],51:[2,110],53:[2,110],56:[2,110],57:[2,110],58:[2,110],59:[2,110],60:[2,110],61:[2,110],62:[2,110],63:[2,110],64:[2,110],65:[2,110],66:[2,110],67:[2,110],68:[2,110],69:[2,110],70:[2,110],71:[2,110],72:[2,110],73:[2,110],74:[2,110],75:[2,110],76:[2,110],77:[2,110],78:[2,110],79:[2,110],81:[2,110],82:[2,110],83:[2,110],84:[2,110],85:[2,110],86:[2,110],87:[2,110],88:[2,110],89:[2,110],90:[2,110],91:[2,110],92:[2,110],93:[2,110],94:[2,110],95:[2,
-110],96:[2,110],97:[2,110],98:[2,110],99:[2,110],100:[2,110],101:[2,110],102:[2,110],103:[2,110],104:[2,110],105:[2,110],106:[2,110],107:[2,110],108:[2,110],109:[2,110],110:[2,110],111:[2,110],112:[2,110],113:[2,110],114:[2,110],115:[2,110],116:[2,110],117:[2,110],118:[2,110],119:[2,110],120:[2,110],121:[2,110],122:[2,110],123:[2,110],124:[2,110],125:[2,110],126:[2,110],127:[2,110],128:[2,110],129:[2,110],130:[2,110],131:[2,110],132:[2,110],134:[2,110],135:[2,110],137:[2,110],138:[2,110],140:[2,110],
-141:[2,110],142:[2,110],143:[2,110],144:[2,110],145:[2,110],146:[2,110],147:[2,110],148:[2,110],149:[2,110],150:[2,110],151:[2,110],152:[2,110],153:[2,110],154:[2,110],155:[2,110],156:[2,110],157:[2,110],158:[2,110],159:[2,110],160:[2,110],161:[2,110],162:[2,110],165:[2,110],166:[2,110],167:[2,110],169:[2,110],170:[2,110],185:[2,110],188:[2,110],194:[2,110],196:[2,110],198:[2,110],200:[2,110]},{6:[2,111],8:[2,111],10:[2,111],49:[2,111],50:[2,111],51:[2,111],53:[2,111],56:[2,111],57:[2,111],58:[2,
-111],59:[2,111],60:[2,111],61:[2,111],62:[2,111],63:[2,111],64:[2,111],65:[2,111],66:[2,111],67:[2,111],68:[2,111],69:[2,111],70:[2,111],71:[2,111],72:[2,111],73:[2,111],74:[2,111],75:[2,111],76:[2,111],77:[2,111],78:[2,111],79:[2,111],81:[2,111],82:[2,111],83:[2,111],84:[2,111],85:[2,111],86:[2,111],87:[2,111],88:[2,111],89:[2,111],90:[2,111],91:[2,111],92:[2,111],93:[2,111],94:[2,111],95:[2,111],96:[2,111],97:[2,111],98:[2,111],99:[2,111],100:[2,111],101:[2,111],102:[2,111],103:[2,111],104:[2,111],
-105:[2,111],106:[2,111],107:[2,111],108:[2,111],109:[2,111],110:[2,111],111:[2,111],112:[2,111],113:[2,111],114:[2,111],115:[2,111],116:[2,111],117:[2,111],118:[2,111],119:[2,111],120:[2,111],121:[2,111],122:[2,111],123:[2,111],124:[2,111],125:[2,111],126:[2,111],127:[2,111],128:[2,111],129:[2,111],130:[2,111],131:[2,111],132:[2,111],134:[2,111],135:[2,111],137:[2,111],138:[2,111],140:[2,111],141:[2,111],142:[2,111],143:[2,111],144:[2,111],145:[2,111],146:[2,111],147:[2,111],148:[2,111],149:[2,111],
-150:[2,111],151:[2,111],152:[2,111],153:[2,111],154:[2,111],155:[2,111],156:[2,111],157:[2,111],158:[2,111],159:[2,111],160:[2,111],161:[2,111],162:[2,111],165:[2,111],166:[2,111],167:[2,111],169:[2,111],170:[2,111],185:[2,111],188:[2,111],194:[2,111],196:[2,111],198:[2,111],200:[2,111]},{6:[2,112],8:[2,112],10:[2,112],49:[2,112],50:[2,112],51:[2,112],53:[2,112],56:[2,112],57:[2,112],58:[2,112],59:[2,112],60:[2,112],61:[2,112],62:[2,112],63:[2,112],64:[2,112],65:[2,112],66:[2,112],67:[2,112],68:[2,
-112],69:[2,112],70:[2,112],71:[2,112],72:[2,112],73:[2,112],74:[2,112],75:[2,112],76:[2,112],77:[2,112],78:[2,112],79:[2,112],81:[2,112],82:[2,112],83:[2,112],84:[2,112],85:[2,112],86:[2,112],87:[2,112],88:[2,112],89:[2,112],90:[2,112],91:[2,112],92:[2,112],93:[2,112],94:[2,112],95:[2,112],96:[2,112],97:[2,112],98:[2,112],99:[2,112],100:[2,112],101:[2,112],102:[2,112],103:[2,112],104:[2,112],105:[2,112],106:[2,112],107:[2,112],108:[2,112],109:[2,112],110:[2,112],111:[2,112],112:[2,112],113:[2,112],
-114:[2,112],115:[2,112],116:[2,112],117:[2,112],118:[2,112],119:[2,112],120:[2,112],121:[2,112],122:[2,112],123:[2,112],124:[2,112],125:[2,112],126:[2,112],127:[2,112],128:[2,112],129:[2,112],130:[2,112],131:[2,112],132:[2,112],134:[2,112],135:[2,112],137:[2,112],138:[2,112],140:[2,112],141:[2,112],142:[2,112],143:[2,112],144:[2,112],145:[2,112],146:[2,112],147:[2,112],148:[2,112],149:[2,112],150:[2,112],151:[2,112],152:[2,112],153:[2,112],154:[2,112],155:[2,112],156:[2,112],157:[2,112],158:[2,112],
-159:[2,112],160:[2,112],161:[2,112],162:[2,112],165:[2,112],166:[2,112],167:[2,112],169:[2,112],170:[2,112],185:[2,112],188:[2,112],194:[2,112],196:[2,112],198:[2,112],200:[2,112]},{6:[2,113],8:[2,113],10:[2,113],49:[2,113],50:[2,113],51:[2,113],53:[2,113],56:[2,113],57:[2,113],58:[2,113],59:[2,113],60:[2,113],61:[2,113],62:[2,113],63:[2,113],64:[2,113],65:[2,113],66:[2,113],67:[2,113],68:[2,113],69:[2,113],70:[2,113],71:[2,113],72:[2,113],73:[2,113],74:[2,113],75:[2,113],76:[2,113],77:[2,113],78:[2,
-113],79:[2,113],81:[2,113],82:[2,113],83:[2,113],84:[2,113],85:[2,113],86:[2,113],87:[2,113],88:[2,113],89:[2,113],90:[2,113],91:[2,113],92:[2,113],93:[2,113],94:[2,113],95:[2,113],96:[2,113],97:[2,113],98:[2,113],99:[2,113],100:[2,113],101:[2,113],102:[2,113],103:[2,113],104:[2,113],105:[2,113],106:[2,113],107:[2,113],108:[2,113],109:[2,113],110:[2,113],111:[2,113],112:[2,113],113:[2,113],114:[2,113],115:[2,113],116:[2,113],117:[2,113],118:[2,113],119:[2,113],120:[2,113],121:[2,113],122:[2,113],
-123:[2,113],124:[2,113],125:[2,113],126:[2,113],127:[2,113],128:[2,113],129:[2,113],130:[2,113],131:[2,113],132:[2,113],134:[2,113],135:[2,113],137:[2,113],138:[2,113],140:[2,113],141:[2,113],142:[2,113],143:[2,113],144:[2,113],145:[2,113],146:[2,113],147:[2,113],148:[2,113],149:[2,113],150:[2,113],151:[2,113],152:[2,113],153:[2,113],154:[2,113],155:[2,113],156:[2,113],157:[2,113],158:[2,113],159:[2,113],160:[2,113],161:[2,113],162:[2,113],165:[2,113],166:[2,113],167:[2,113],169:[2,113],170:[2,113],
-185:[2,113],188:[2,113],194:[2,113],196:[2,113],198:[2,113],200:[2,113]},{6:[2,114],8:[2,114],10:[2,114],49:[2,114],50:[2,114],51:[2,114],53:[2,114],56:[2,114],57:[2,114],58:[2,114],59:[2,114],60:[2,114],61:[2,114],62:[2,114],63:[2,114],64:[2,114],65:[2,114],66:[2,114],67:[2,114],68:[2,114],69:[2,114],70:[2,114],71:[2,114],72:[2,114],73:[2,114],74:[2,114],75:[2,114],76:[2,114],77:[2,114],78:[2,114],79:[2,114],81:[2,114],82:[2,114],83:[2,114],84:[2,114],85:[2,114],86:[2,114],87:[2,114],88:[2,114],
-89:[2,114],90:[2,114],91:[2,114],92:[2,114],93:[2,114],94:[2,114],95:[2,114],96:[2,114],97:[2,114],98:[2,114],99:[2,114],100:[2,114],101:[2,114],102:[2,114],103:[2,114],104:[2,114],105:[2,114],106:[2,114],107:[2,114],108:[2,114],109:[2,114],110:[2,114],111:[2,114],112:[2,114],113:[2,114],114:[2,114],115:[2,114],116:[2,114],117:[2,114],118:[2,114],119:[2,114],120:[2,114],121:[2,114],122:[2,114],123:[2,114],124:[2,114],125:[2,114],126:[2,114],127:[2,114],128:[2,114],129:[2,114],130:[2,114],131:[2,114],
-132:[2,114],134:[2,114],135:[2,114],137:[2,114],138:[2,114],140:[2,114],141:[2,114],142:[2,114],143:[2,114],144:[2,114],145:[2,114],146:[2,114],147:[2,114],148:[2,114],149:[2,114],150:[2,114],151:[2,114],152:[2,114],153:[2,114],154:[2,114],155:[2,114],156:[2,114],157:[2,114],158:[2,114],159:[2,114],160:[2,114],161:[2,114],162:[2,114],165:[2,114],166:[2,114],167:[2,114],169:[2,114],170:[2,114],185:[2,114],188:[2,114],194:[2,114],196:[2,114],198:[2,114],200:[2,114]},{6:[2,115],8:[2,115],10:[2,115],
-49:[2,115],50:[2,115],51:[2,115],53:[2,115],56:[2,115],57:[2,115],58:[2,115],59:[2,115],60:[2,115],61:[2,115],62:[2,115],63:[2,115],64:[2,115],65:[2,115],66:[2,115],67:[2,115],68:[2,115],69:[2,115],70:[2,115],71:[2,115],72:[2,115],73:[2,115],74:[2,115],75:[2,115],76:[2,115],77:[2,115],78:[2,115],79:[2,115],81:[2,115],82:[2,115],83:[2,115],84:[2,115],85:[2,115],86:[2,115],87:[2,115],88:[2,115],89:[2,115],90:[2,115],91:[2,115],92:[2,115],93:[2,115],94:[2,115],95:[2,115],96:[2,115],97:[2,115],98:[2,
-115],99:[2,115],100:[2,115],101:[2,115],102:[2,115],103:[2,115],104:[2,115],105:[2,115],106:[2,115],107:[2,115],108:[2,115],109:[2,115],110:[2,115],111:[2,115],112:[2,115],113:[2,115],114:[2,115],115:[2,115],116:[2,115],117:[2,115],118:[2,115],119:[2,115],120:[2,115],121:[2,115],122:[2,115],123:[2,115],124:[2,115],125:[2,115],126:[2,115],127:[2,115],128:[2,115],129:[2,115],130:[2,115],131:[2,115],132:[2,115],134:[2,115],135:[2,115],137:[2,115],138:[2,115],140:[2,115],141:[2,115],142:[2,115],143:[2,
-115],144:[2,115],145:[2,115],146:[2,115],147:[2,115],148:[2,115],149:[2,115],150:[2,115],151:[2,115],152:[2,115],153:[2,115],154:[2,115],155:[2,115],156:[2,115],157:[2,115],158:[2,115],159:[2,115],160:[2,115],161:[2,115],162:[2,115],165:[2,115],166:[2,115],167:[2,115],169:[2,115],170:[2,115],185:[2,115],188:[2,115],194:[2,115],196:[2,115],198:[2,115],200:[2,115]},{6:[2,116],8:[2,116],10:[2,116],49:[2,116],50:[2,116],51:[2,116],53:[2,116],56:[2,116],57:[2,116],58:[2,116],59:[2,116],60:[2,116],61:[2,
-116],62:[2,116],63:[2,116],64:[2,116],65:[2,116],66:[2,116],67:[2,116],68:[2,116],69:[2,116],70:[2,116],71:[2,116],72:[2,116],73:[2,116],74:[2,116],75:[2,116],76:[2,116],77:[2,116],78:[2,116],79:[2,116],81:[2,116],82:[2,116],83:[2,116],84:[2,116],85:[2,116],86:[2,116],87:[2,116],88:[2,116],89:[2,116],90:[2,116],91:[2,116],92:[2,116],93:[2,116],94:[2,116],95:[2,116],96:[2,116],97:[2,116],98:[2,116],99:[2,116],100:[2,116],101:[2,116],102:[2,116],103:[2,116],104:[2,116],105:[2,116],106:[2,116],107:[2,
-116],108:[2,116],109:[2,116],110:[2,116],111:[2,116],112:[2,116],113:[2,116],114:[2,116],115:[2,116],116:[2,116],117:[2,116],118:[2,116],119:[2,116],120:[2,116],121:[2,116],122:[2,116],123:[2,116],124:[2,116],125:[2,116],126:[2,116],127:[2,116],128:[2,116],129:[2,116],130:[2,116],131:[2,116],132:[2,116],134:[2,116],135:[2,116],137:[2,116],138:[2,116],140:[2,116],141:[2,116],142:[2,116],143:[2,116],144:[2,116],145:[2,116],146:[2,116],147:[2,116],148:[2,116],149:[2,116],150:[2,116],151:[2,116],152:[2,
-116],153:[2,116],154:[2,116],155:[2,116],156:[2,116],157:[2,116],158:[2,116],159:[2,116],160:[2,116],161:[2,116],162:[2,116],165:[2,116],166:[2,116],167:[2,116],169:[2,116],170:[2,116],185:[2,116],188:[2,116],194:[2,116],196:[2,116],198:[2,116],200:[2,116]},{6:[2,117],8:[2,117],10:[2,117],49:[2,117],50:[2,117],51:[2,117],53:[2,117],56:[2,117],57:[2,117],58:[2,117],59:[2,117],60:[2,117],61:[2,117],62:[2,117],63:[2,117],64:[2,117],65:[2,117],66:[2,117],67:[2,117],68:[2,117],69:[2,117],70:[2,117],71:[2,
-117],72:[2,117],73:[2,117],74:[2,117],75:[2,117],76:[2,117],77:[2,117],78:[2,117],79:[2,117],81:[2,117],82:[2,117],83:[2,117],84:[2,117],85:[2,117],86:[2,117],87:[2,117],88:[2,117],89:[2,117],90:[2,117],91:[2,117],92:[2,117],93:[2,117],94:[2,117],95:[2,117],96:[2,117],97:[2,117],98:[2,117],99:[2,117],100:[2,117],101:[2,117],102:[2,117],103:[2,117],104:[2,117],105:[2,117],106:[2,117],107:[2,117],108:[2,117],109:[2,117],110:[2,117],111:[2,117],112:[2,117],113:[2,117],114:[2,117],115:[2,117],116:[2,
-117],117:[2,117],118:[2,117],119:[2,117],120:[2,117],121:[2,117],122:[2,117],123:[2,117],124:[2,117],125:[2,117],126:[2,117],127:[2,117],128:[2,117],129:[2,117],130:[2,117],131:[2,117],132:[2,117],134:[2,117],135:[2,117],137:[2,117],138:[2,117],140:[2,117],141:[2,117],142:[2,117],143:[2,117],144:[2,117],145:[2,117],146:[2,117],147:[2,117],148:[2,117],149:[2,117],150:[2,117],151:[2,117],152:[2,117],153:[2,117],154:[2,117],155:[2,117],156:[2,117],157:[2,117],158:[2,117],159:[2,117],160:[2,117],161:[2,
-117],162:[2,117],165:[2,117],166:[2,117],167:[2,117],169:[2,117],170:[2,117],185:[2,117],188:[2,117],194:[2,117],196:[2,117],198:[2,117],200:[2,117]},{7:187,8:[1,129]},{8:[1,189],12:188},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:190,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],
-86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,
-102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:191,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,
-56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,
-132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:192,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,
-57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],
-137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:193,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],
-88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,
-103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:194,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,
-58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],
-138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:195,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],
-89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,
-104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:196,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],
-90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],
-141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:197,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,
-60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,
-105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:198,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],
-91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],
-143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:199,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,
-61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,
-106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{7:128,8:[1,129],14:200},{7:201,8:[1,129]},{7:202,8:[1,129]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:203,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],
-86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,
-102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:205,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,
-56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],133:204,
-135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,206]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:213,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],
-85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],
-132:[1,102],135:[1,23],137:[1,103],138:[1,104],139:207,140:[2,193],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21],182:211,183:[1,212],184:210,185:[2,193],186:208,187:[1,209],188:[2,193]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:213,56:[1,27],57:[1,28],58:[1,29],
-59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],
-112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],139:214,141:[1,105],142:[2,193],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,
-16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21],182:211,183:[1,212],184:210,185:[2,193],186:208,187:[1,209],188:[2,193]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:213,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],
-91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],139:215,141:[1,
-105],143:[1,106],144:[2,193],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21],182:211,183:[1,212],184:210,185:[2,193],186:208,187:[1,209],188:[2,193]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:213,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],
-68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,
-87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],139:216,141:[1,105],143:[1,106],145:[1,107],146:[2,193],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21],182:211,
-183:[1,212],184:210,185:[2,193],186:208,187:[1,209],188:[2,193]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:213,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,
-67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],139:217,141:[1,105],143:[1,106],145:[1,107],147:[1,108],148:[2,193],149:[1,109],
-151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21],182:211,183:[1,212],184:210,185:[2,193],186:208,187:[1,209],188:[2,193]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:213,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,
-44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,
-93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],139:218,141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],150:[2,193],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21],182:211,183:[1,212],184:210,185:[2,193],186:208,187:[1,209],188:[2,
-193]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:213,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,
-73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],139:219,141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],152:[2,193],153:[1,111],155:[1,112],157:[1,113],159:[1,114],
-161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21],182:211,183:[1,212],184:210,185:[2,193],186:208,187:[1,209],188:[2,193]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:213,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,
-51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],
-129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],139:220,141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],154:[2,193],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21],182:211,183:[1,212],184:210,185:[2,193],186:208,187:[1,209],188:[2,193]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,
-55:213,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,
-78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],139:221,141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],156:[2,193],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,
-118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21],182:211,183:[1,212],184:210,185:[2,193],186:208,187:[1,209],188:[2,193]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:213,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,
-57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],
-137:[1,103],138:[1,104],139:222,141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],158:[2,193],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21],182:211,183:[1,212],184:210,185:[2,193],186:208,187:[1,209],188:[2,193]},{3:225,4:[1,156],7:226,8:[1,129],16:223,17:224},{8:[1,227]},{8:[1,228]},{6:[2,172],8:[2,172],10:[2,172],49:[2,172],
-50:[2,172],51:[2,172],53:[2,172],56:[2,172],57:[2,172],58:[2,172],59:[2,172],60:[2,172],61:[2,172],62:[2,172],63:[2,172],64:[2,172],65:[2,172],66:[2,172],67:[2,172],68:[2,172],69:[2,172],70:[2,172],71:[2,172],72:[2,172],73:[2,172],74:[2,172],75:[2,172],76:[2,172],77:[2,172],78:[2,172],79:[2,172],81:[2,172],82:[2,172],83:[2,172],84:[2,172],85:[2,172],86:[2,172],87:[2,172],88:[2,172],89:[2,172],90:[2,172],91:[2,172],92:[2,172],93:[2,172],94:[2,172],95:[2,172],96:[2,172],97:[2,172],98:[2,172],99:[2,
-172],100:[2,172],101:[2,172],102:[2,172],103:[2,172],104:[2,172],105:[2,172],106:[2,172],107:[2,172],108:[2,172],109:[2,172],110:[2,172],111:[2,172],112:[2,172],113:[2,172],114:[2,172],115:[2,172],116:[2,172],117:[2,172],118:[2,172],119:[2,172],120:[2,172],121:[2,172],122:[2,172],123:[2,172],124:[2,172],125:[2,172],126:[2,172],127:[2,172],128:[2,172],129:[2,172],130:[2,172],131:[2,172],132:[2,172],135:[2,172],137:[2,172],138:[2,172],140:[2,172],141:[2,172],142:[2,172],143:[2,172],144:[2,172],145:[2,
-172],146:[2,172],147:[2,172],148:[2,172],149:[2,172],150:[2,172],151:[2,172],152:[2,172],153:[2,172],154:[2,172],155:[2,172],156:[2,172],157:[2,172],158:[2,172],159:[2,172],160:[2,172],161:[2,172],162:[2,172],165:[2,172],166:[2,172],169:[2,172],170:[2,172],185:[2,172],188:[2,172],194:[2,172],196:[2,172],198:[2,172],200:[2,172]},{6:[2,173],8:[2,173],10:[2,173],49:[2,173],50:[2,173],51:[2,173],53:[2,173],56:[2,173],57:[2,173],58:[2,173],59:[2,173],60:[2,173],61:[2,173],62:[2,173],63:[2,173],64:[2,173],
-65:[2,173],66:[2,173],67:[2,173],68:[2,173],69:[2,173],70:[2,173],71:[2,173],72:[2,173],73:[2,173],74:[2,173],75:[2,173],76:[2,173],77:[2,173],78:[2,173],79:[2,173],81:[2,173],82:[2,173],83:[2,173],84:[2,173],85:[2,173],86:[2,173],87:[2,173],88:[2,173],89:[2,173],90:[2,173],91:[2,173],92:[2,173],93:[2,173],94:[2,173],95:[2,173],96:[2,173],97:[2,173],98:[2,173],99:[2,173],100:[2,173],101:[2,173],102:[2,173],103:[2,173],104:[2,173],105:[2,173],106:[2,173],107:[2,173],108:[2,173],109:[2,173],110:[2,
-173],111:[2,173],112:[2,173],113:[2,173],114:[2,173],115:[2,173],116:[2,173],117:[2,173],118:[2,173],119:[2,173],120:[2,173],121:[2,173],122:[2,173],123:[2,173],124:[2,173],125:[2,173],126:[2,173],127:[2,173],128:[2,173],129:[2,173],130:[2,173],131:[2,173],132:[2,173],135:[2,173],137:[2,173],138:[2,173],140:[2,173],141:[2,173],142:[2,173],143:[2,173],144:[2,173],145:[2,173],146:[2,173],147:[2,173],148:[2,173],149:[2,173],150:[2,173],151:[2,173],152:[2,173],153:[2,173],154:[2,173],155:[2,173],156:[2,
-173],157:[2,173],158:[2,173],159:[2,173],160:[2,173],161:[2,173],162:[2,173],165:[2,173],166:[2,173],169:[2,173],170:[2,173],185:[2,173],188:[2,173],194:[2,173],196:[2,173],198:[2,173],200:[2,173]},{50:[1,229],51:[1,230]},{68:[2,208],191:[2,208],193:[2,208],195:[2,208],197:[2,208],199:[2,208]},{196:[1,231]},{198:[1,232]},{200:[1,233]},{68:[2,207],191:[2,207],193:[2,207],195:[2,207],197:[2,207],199:[2,207]},{6:[2,191],10:[2,191],53:[2,191],64:[2,191],65:[2,191],66:[2,191],140:[2,191],142:[2,191],144:[2,
-191],146:[2,191],148:[2,191],150:[2,191],152:[2,191],154:[2,191],156:[2,191],158:[2,191],160:[2,191],185:[2,191],188:[2,191],194:[2,191],196:[2,191],198:[2,191],200:[2,191]},{6:[2,175],8:[2,175],10:[2,175],49:[2,175],50:[2,175],51:[2,175],53:[2,175],56:[2,175],57:[2,175],58:[2,175],59:[2,175],60:[2,175],61:[2,175],62:[2,175],63:[2,175],64:[2,175],65:[2,175],66:[2,175],67:[2,175],68:[2,175],69:[2,175],70:[2,175],71:[2,175],72:[2,175],73:[2,175],74:[2,175],75:[2,175],76:[2,175],77:[2,175],78:[2,175],
-79:[2,175],81:[2,175],82:[2,175],83:[2,175],84:[2,175],85:[2,175],86:[2,175],87:[2,175],88:[2,175],89:[2,175],90:[2,175],91:[2,175],92:[2,175],93:[2,175],94:[2,175],95:[2,175],96:[2,175],97:[2,175],98:[2,175],99:[2,175],100:[2,175],101:[2,175],102:[2,175],103:[2,175],104:[2,175],105:[2,175],106:[2,175],107:[2,175],108:[2,175],109:[2,175],110:[2,175],111:[2,175],112:[2,175],113:[2,175],114:[2,175],115:[2,175],116:[2,175],117:[2,175],118:[2,175],119:[2,175],120:[2,175],121:[2,175],122:[2,175],123:[2,
-175],124:[2,175],125:[2,175],126:[2,175],127:[2,175],128:[2,175],129:[2,175],130:[2,175],131:[2,175],132:[2,175],135:[2,175],137:[2,175],138:[2,175],140:[2,175],141:[2,175],142:[2,175],143:[2,175],144:[2,175],145:[2,175],146:[2,175],147:[2,175],148:[2,175],149:[2,175],150:[2,175],151:[2,175],152:[2,175],153:[2,175],154:[2,175],155:[2,175],156:[2,175],157:[2,175],158:[2,175],159:[2,175],160:[2,175],161:[2,175],162:[2,175],169:[2,175],170:[2,175],185:[2,175],188:[2,175],194:[2,175],196:[2,175],198:[2,
-175],200:[2,175]},{8:[2,189],49:[2,189],50:[2,189],51:[2,189],56:[2,189],57:[2,189],58:[2,189],59:[2,189],60:[2,189],61:[2,189],62:[2,189],63:[2,189],67:[2,189],68:[2,189],69:[2,189],70:[2,189],71:[2,189],72:[2,189],73:[2,189],74:[2,189],75:[2,189],76:[2,189],77:[2,189],78:[2,189],79:[2,189],81:[2,189],82:[2,189],83:[2,189],84:[2,189],85:[2,189],86:[2,189],87:[2,189],88:[2,189],89:[2,189],90:[2,189],91:[2,189],92:[2,189],93:[2,189],94:[2,189],95:[2,189],96:[2,189],97:[2,189],98:[2,189],99:[2,189],
-100:[2,189],101:[2,189],102:[2,189],103:[2,189],104:[2,189],105:[2,189],106:[2,189],107:[2,189],108:[2,189],109:[2,189],110:[2,189],111:[2,189],112:[2,189],113:[2,189],114:[2,189],115:[2,189],116:[2,189],117:[2,189],118:[2,189],119:[2,189],120:[2,189],121:[2,189],122:[2,189],123:[2,189],124:[2,189],125:[2,189],126:[2,189],127:[2,189],128:[2,189],129:[2,189],130:[2,189],131:[2,189],132:[2,189],135:[2,189],137:[2,189],138:[2,189],141:[2,189],143:[2,189],145:[2,189],147:[2,189],149:[2,189],151:[2,189],
-153:[2,189],155:[2,189],157:[2,189],159:[2,189],161:[2,189],162:[2,189],169:[2,189],170:[2,189],175:[2,189],176:[2,189],177:[2,189],178:[2,189],179:[2,189],180:[2,189],181:[2,189]},{8:[2,6],10:[2,6],19:[2,6],21:[2,6],23:[2,6],25:[2,6],27:[2,6],29:[2,6],31:[2,6],33:[2,6],35:[2,6],37:[2,6],39:[2,6],41:[2,6],49:[2,6],50:[2,6],51:[2,6],56:[2,6],57:[2,6],58:[2,6],59:[2,6],60:[2,6],61:[2,6],62:[2,6],63:[2,6],67:[2,6],68:[2,6],69:[2,6],70:[2,6],71:[2,6],72:[2,6],73:[2,6],74:[2,6],75:[2,6],76:[2,6],77:[2,
-6],78:[2,6],79:[2,6],81:[2,6],82:[2,6],83:[2,6],84:[2,6],85:[2,6],86:[2,6],87:[2,6],88:[2,6],89:[2,6],90:[2,6],91:[2,6],92:[2,6],93:[2,6],94:[2,6],95:[2,6],96:[2,6],97:[2,6],98:[2,6],99:[2,6],100:[2,6],101:[2,6],102:[2,6],103:[2,6],104:[2,6],105:[2,6],106:[2,6],107:[2,6],108:[2,6],109:[2,6],110:[2,6],111:[2,6],112:[2,6],113:[2,6],114:[2,6],115:[2,6],116:[2,6],117:[2,6],118:[2,6],119:[2,6],120:[2,6],121:[2,6],122:[2,6],123:[2,6],124:[2,6],125:[2,6],126:[2,6],127:[2,6],128:[2,6],129:[2,6],130:[2,6],
-131:[2,6],132:[2,6],135:[2,6],137:[2,6],138:[2,6],141:[2,6],143:[2,6],145:[2,6],147:[2,6],149:[2,6],151:[2,6],153:[2,6],155:[2,6],157:[2,6],159:[2,6],161:[2,6],162:[2,6],169:[2,6],170:[2,6],175:[2,6],176:[2,6],177:[2,6],178:[2,6],179:[2,6],180:[2,6],181:[2,6]},{9:[1,234]},{8:[2,190],49:[2,190],50:[2,190],51:[2,190],56:[2,190],57:[2,190],58:[2,190],59:[2,190],60:[2,190],61:[2,190],62:[2,190],63:[2,190],67:[2,190],68:[2,190],69:[2,190],70:[2,190],71:[2,190],72:[2,190],73:[2,190],74:[2,190],75:[2,190],
-76:[2,190],77:[2,190],78:[2,190],79:[2,190],81:[2,190],82:[2,190],83:[2,190],84:[2,190],85:[2,190],86:[2,190],87:[2,190],88:[2,190],89:[2,190],90:[2,190],91:[2,190],92:[2,190],93:[2,190],94:[2,190],95:[2,190],96:[2,190],97:[2,190],98:[2,190],99:[2,190],100:[2,190],101:[2,190],102:[2,190],103:[2,190],104:[2,190],105:[2,190],106:[2,190],107:[2,190],108:[2,190],109:[2,190],110:[2,190],111:[2,190],112:[2,190],113:[2,190],114:[2,190],115:[2,190],116:[2,190],117:[2,190],118:[2,190],119:[2,190],120:[2,190],
-121:[2,190],122:[2,190],123:[2,190],124:[2,190],125:[2,190],126:[2,190],127:[2,190],128:[2,190],129:[2,190],130:[2,190],131:[2,190],132:[2,190],135:[2,190],137:[2,190],138:[2,190],141:[2,190],143:[2,190],145:[2,190],147:[2,190],149:[2,190],151:[2,190],153:[2,190],155:[2,190],157:[2,190],159:[2,190],161:[2,190],162:[2,190],169:[2,190],170:[2,190],175:[2,190],176:[2,190],177:[2,190],178:[2,190],179:[2,190],180:[2,190],181:[2,190]},{8:[1,236],136:235,165:[1,238],166:[1,239],173:237},{8:[1,26],48:35,
-49:[1,119],50:[1,47],51:[1,43],54:240,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],
-106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,
-119],50:[1,47],51:[1,43],54:241,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,
-76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],
-50:[1,47],51:[1,43],54:242,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],
-107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{6:[2,165],8:[2,165],10:[2,165],
-49:[2,165],50:[2,165],51:[2,165],53:[2,165],56:[2,165],57:[2,165],58:[2,165],59:[2,165],60:[2,165],61:[2,165],62:[2,165],63:[2,165],64:[2,165],65:[2,165],66:[2,165],67:[2,165],68:[2,165],69:[2,165],70:[2,165],71:[2,165],72:[2,165],73:[2,165],74:[2,165],75:[2,165],76:[2,165],77:[2,165],78:[2,165],79:[2,165],81:[2,165],82:[2,165],83:[2,165],84:[2,165],85:[2,165],86:[2,165],87:[2,165],88:[2,165],89:[2,165],90:[2,165],91:[2,165],92:[2,165],93:[2,165],94:[2,165],95:[2,165],96:[2,165],97:[2,165],98:[2,
-165],99:[2,165],100:[2,165],101:[2,165],102:[2,165],103:[2,165],104:[2,165],105:[2,165],106:[2,165],107:[2,165],108:[2,165],109:[2,165],110:[2,165],111:[2,165],112:[2,165],113:[2,165],114:[2,165],115:[2,165],116:[2,165],117:[2,165],118:[2,165],119:[2,165],120:[2,165],121:[2,165],122:[2,165],123:[2,165],124:[2,165],125:[2,165],126:[2,165],127:[2,165],128:[2,165],129:[2,165],130:[2,165],131:[2,165],132:[2,165],135:[2,165],137:[2,165],138:[2,165],140:[2,165],141:[2,165],142:[2,165],143:[2,165],144:[2,
-165],145:[2,165],146:[2,165],147:[2,165],148:[2,165],149:[2,165],150:[2,165],151:[2,165],152:[2,165],153:[2,165],154:[2,165],155:[2,165],156:[2,165],157:[2,165],158:[2,165],159:[2,165],160:[2,165],161:[2,165],162:[2,165],165:[1,243],169:[2,165],170:[2,165],185:[2,165],188:[2,165],194:[2,165],196:[2,165],198:[2,165],200:[2,165]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:244,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],
-71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,
-90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:245,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],
-72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],
-121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{6:[2,48],8:[2,48],10:[2,48],49:[2,48],50:[2,48],51:[2,48],53:[2,48],56:[2,48],57:[2,48],58:[2,48],59:[2,48],60:[2,48],61:[2,48],62:[2,48],63:[2,48],64:[2,48],65:[2,48],66:[2,48],67:[2,
-48],68:[2,48],69:[2,48],70:[2,48],71:[2,48],72:[2,48],73:[2,48],74:[2,48],75:[2,48],76:[2,48],77:[2,48],78:[2,48],79:[2,48],81:[2,48],82:[2,48],83:[2,48],84:[2,48],85:[2,48],86:[2,48],87:[2,48],88:[2,48],89:[2,48],90:[2,48],91:[2,48],92:[2,48],93:[2,48],94:[2,48],95:[2,48],96:[2,48],97:[2,48],98:[2,48],99:[2,48],100:[2,48],101:[2,48],102:[2,48],103:[2,48],104:[2,48],105:[2,48],106:[2,48],107:[2,48],108:[2,48],109:[2,48],110:[2,48],111:[2,48],112:[2,48],113:[2,48],114:[2,48],115:[2,48],116:[2,48],
-117:[2,48],118:[2,48],119:[2,48],120:[2,48],121:[2,48],122:[2,48],123:[2,48],124:[2,48],125:[2,48],126:[2,48],127:[2,48],128:[2,48],129:[2,48],130:[2,48],131:[2,48],132:[2,48],134:[2,48],135:[2,48],137:[2,48],138:[2,48],140:[2,48],141:[2,48],142:[2,48],143:[2,48],144:[2,48],145:[2,48],146:[2,48],147:[2,48],148:[2,48],149:[2,48],150:[2,48],151:[2,48],152:[2,48],153:[2,48],154:[2,48],155:[2,48],156:[2,48],157:[2,48],158:[2,48],159:[2,48],160:[2,48],161:[2,48],162:[2,48],165:[2,48],166:[2,48],167:[2,
-48],169:[2,48],170:[2,48],185:[2,48],188:[2,48],194:[2,48],196:[2,48],198:[2,48],200:[2,48]},{10:[1,246],64:[1,247],65:[1,248],66:[1,249]},{6:[2,50],8:[2,50],10:[2,50],49:[2,50],50:[2,50],51:[2,50],53:[2,50],56:[2,50],57:[2,50],58:[2,50],59:[2,50],60:[2,50],61:[2,50],62:[2,50],63:[2,50],64:[2,50],65:[2,50],66:[2,50],67:[2,50],68:[2,50],69:[2,50],70:[2,50],71:[2,50],72:[2,50],73:[2,50],74:[2,50],75:[2,50],76:[2,50],77:[2,50],78:[2,50],79:[2,50],81:[2,50],82:[2,50],83:[2,50],84:[2,50],85:[2,50],86:[2,
-50],87:[2,50],88:[2,50],89:[2,50],90:[2,50],91:[2,50],92:[2,50],93:[2,50],94:[2,50],95:[2,50],96:[2,50],97:[2,50],98:[2,50],99:[2,50],100:[2,50],101:[2,50],102:[2,50],103:[2,50],104:[2,50],105:[2,50],106:[2,50],107:[2,50],108:[2,50],109:[2,50],110:[2,50],111:[2,50],112:[2,50],113:[2,50],114:[2,50],115:[2,50],116:[2,50],117:[2,50],118:[2,50],119:[2,50],120:[2,50],121:[2,50],122:[2,50],123:[2,50],124:[2,50],125:[2,50],126:[2,50],127:[2,50],128:[2,50],129:[2,50],130:[2,50],131:[2,50],132:[2,50],134:[2,
-50],135:[2,50],137:[2,50],138:[2,50],140:[2,50],141:[2,50],142:[2,50],143:[2,50],144:[2,50],145:[2,50],146:[2,50],147:[2,50],148:[2,50],149:[2,50],150:[2,50],151:[2,50],152:[2,50],153:[2,50],154:[2,50],155:[2,50],156:[2,50],157:[2,50],158:[2,50],159:[2,50],160:[2,50],161:[2,50],162:[2,50],165:[2,50],166:[2,50],167:[2,50],169:[2,50],170:[2,50],185:[2,50],188:[2,50],194:[2,50],196:[2,50],198:[2,50],200:[2,50]},{6:[2,51],8:[2,51],10:[2,51],49:[2,51],50:[2,51],51:[2,51],53:[2,51],56:[2,51],57:[2,51],
-58:[2,51],59:[2,51],60:[2,51],61:[2,51],62:[2,51],63:[2,51],64:[2,51],65:[2,51],66:[2,51],67:[2,51],68:[2,51],69:[2,51],70:[2,51],71:[2,51],72:[2,51],73:[2,51],74:[2,51],75:[2,51],76:[2,51],77:[2,51],78:[2,51],79:[2,51],81:[2,51],82:[2,51],83:[2,51],84:[2,51],85:[2,51],86:[2,51],87:[2,51],88:[2,51],89:[2,51],90:[2,51],91:[2,51],92:[2,51],93:[2,51],94:[2,51],95:[2,51],96:[2,51],97:[2,51],98:[2,51],99:[2,51],100:[2,51],101:[2,51],102:[2,51],103:[2,51],104:[2,51],105:[2,51],106:[2,51],107:[2,51],108:[2,
-51],109:[2,51],110:[2,51],111:[2,51],112:[2,51],113:[2,51],114:[2,51],115:[2,51],116:[2,51],117:[2,51],118:[2,51],119:[2,51],120:[2,51],121:[2,51],122:[2,51],123:[2,51],124:[2,51],125:[2,51],126:[2,51],127:[2,51],128:[2,51],129:[2,51],130:[2,51],131:[2,51],132:[2,51],134:[2,51],135:[2,51],137:[2,51],138:[2,51],140:[2,51],141:[2,51],142:[2,51],143:[2,51],144:[2,51],145:[2,51],146:[2,51],147:[2,51],148:[2,51],149:[2,51],150:[2,51],151:[2,51],152:[2,51],153:[2,51],154:[2,51],155:[2,51],156:[2,51],157:[2,
-51],158:[2,51],159:[2,51],160:[2,51],161:[2,51],162:[2,51],165:[2,51],166:[2,51],167:[2,51],169:[2,51],170:[2,51],185:[2,51],188:[2,51],194:[2,51],196:[2,51],198:[2,51],200:[2,51]},{6:[2,52],8:[2,52],10:[2,52],49:[2,52],50:[2,52],51:[2,52],53:[2,52],56:[2,52],57:[2,52],58:[2,52],59:[2,52],60:[2,52],61:[2,52],62:[2,52],63:[2,52],64:[2,52],65:[2,52],66:[2,52],67:[2,52],68:[2,52],69:[2,52],70:[2,52],71:[2,52],72:[2,52],73:[2,52],74:[2,52],75:[2,52],76:[2,52],77:[2,52],78:[2,52],79:[2,52],81:[2,52],82:[2,
-52],83:[2,52],84:[2,52],85:[2,52],86:[2,52],87:[2,52],88:[2,52],89:[2,52],90:[2,52],91:[2,52],92:[2,52],93:[2,52],94:[2,52],95:[2,52],96:[2,52],97:[2,52],98:[2,52],99:[2,52],100:[2,52],101:[2,52],102:[2,52],103:[2,52],104:[2,52],105:[2,52],106:[2,52],107:[2,52],108:[2,52],109:[2,52],110:[2,52],111:[2,52],112:[2,52],113:[2,52],114:[2,52],115:[2,52],116:[2,52],117:[2,52],118:[2,52],119:[2,52],120:[2,52],121:[2,52],122:[2,52],123:[2,52],124:[2,52],125:[2,52],126:[2,52],127:[2,52],128:[2,52],129:[2,52],
-130:[2,52],131:[2,52],132:[2,52],134:[2,52],135:[2,52],137:[2,52],138:[2,52],140:[2,52],141:[2,52],142:[2,52],143:[2,52],144:[2,52],145:[2,52],146:[2,52],147:[2,52],148:[2,52],149:[2,52],150:[2,52],151:[2,52],152:[2,52],153:[2,52],154:[2,52],155:[2,52],156:[2,52],157:[2,52],158:[2,52],159:[2,52],160:[2,52],161:[2,52],162:[2,52],165:[2,52],166:[2,52],167:[2,52],169:[2,52],170:[2,52],185:[2,52],188:[2,52],194:[2,52],196:[2,52],198:[2,52],200:[2,52]},{6:[2,53],8:[2,53],10:[2,53],49:[2,53],50:[2,53],
-51:[2,53],53:[2,53],56:[2,53],57:[2,53],58:[2,53],59:[2,53],60:[2,53],61:[2,53],62:[2,53],63:[2,53],64:[2,53],65:[2,53],66:[2,53],67:[2,53],68:[2,53],69:[2,53],70:[2,53],71:[2,53],72:[2,53],73:[2,53],74:[2,53],75:[2,53],76:[2,53],77:[2,53],78:[2,53],79:[2,53],81:[2,53],82:[2,53],83:[2,53],84:[2,53],85:[2,53],86:[2,53],87:[2,53],88:[2,53],89:[2,53],90:[2,53],91:[2,53],92:[2,53],93:[2,53],94:[2,53],95:[2,53],96:[2,53],97:[2,53],98:[2,53],99:[2,53],100:[2,53],101:[2,53],102:[2,53],103:[2,53],104:[2,
-53],105:[2,53],106:[2,53],107:[2,53],108:[2,53],109:[2,53],110:[2,53],111:[2,53],112:[2,53],113:[2,53],114:[2,53],115:[2,53],116:[2,53],117:[2,53],118:[2,53],119:[2,53],120:[2,53],121:[2,53],122:[2,53],123:[2,53],124:[2,53],125:[2,53],126:[2,53],127:[2,53],128:[2,53],129:[2,53],130:[2,53],131:[2,53],132:[2,53],134:[2,53],135:[2,53],137:[2,53],138:[2,53],140:[2,53],141:[2,53],142:[2,53],143:[2,53],144:[2,53],145:[2,53],146:[2,53],147:[2,53],148:[2,53],149:[2,53],150:[2,53],151:[2,53],152:[2,53],153:[2,
-53],154:[2,53],155:[2,53],156:[2,53],157:[2,53],158:[2,53],159:[2,53],160:[2,53],161:[2,53],162:[2,53],165:[2,53],166:[2,53],167:[2,53],169:[2,53],170:[2,53],185:[2,53],188:[2,53],194:[2,53],196:[2,53],198:[2,53],200:[2,53]},{6:[2,54],8:[2,54],10:[2,54],49:[2,54],50:[2,54],51:[2,54],53:[2,54],56:[2,54],57:[2,54],58:[2,54],59:[2,54],60:[2,54],61:[2,54],62:[2,54],63:[2,54],64:[2,54],65:[2,54],66:[2,54],67:[2,54],68:[2,54],69:[2,54],70:[2,54],71:[2,54],72:[2,54],73:[2,54],74:[2,54],75:[2,54],76:[2,54],
-77:[2,54],78:[2,54],79:[2,54],81:[2,54],82:[2,54],83:[2,54],84:[2,54],85:[2,54],86:[2,54],87:[2,54],88:[2,54],89:[2,54],90:[2,54],91:[2,54],92:[2,54],93:[2,54],94:[2,54],95:[2,54],96:[2,54],97:[2,54],98:[2,54],99:[2,54],100:[2,54],101:[2,54],102:[2,54],103:[2,54],104:[2,54],105:[2,54],106:[2,54],107:[2,54],108:[2,54],109:[2,54],110:[2,54],111:[2,54],112:[2,54],113:[2,54],114:[2,54],115:[2,54],116:[2,54],117:[2,54],118:[2,54],119:[2,54],120:[2,54],121:[2,54],122:[2,54],123:[2,54],124:[2,54],125:[2,
-54],126:[2,54],127:[2,54],128:[2,54],129:[2,54],130:[2,54],131:[2,54],132:[2,54],134:[2,54],135:[2,54],137:[2,54],138:[2,54],140:[2,54],141:[2,54],142:[2,54],143:[2,54],144:[2,54],145:[2,54],146:[2,54],147:[2,54],148:[2,54],149:[2,54],150:[2,54],151:[2,54],152:[2,54],153:[2,54],154:[2,54],155:[2,54],156:[2,54],157:[2,54],158:[2,54],159:[2,54],160:[2,54],161:[2,54],162:[2,54],165:[2,54],166:[2,54],167:[2,54],169:[2,54],170:[2,54],185:[2,54],188:[2,54],194:[2,54],196:[2,54],198:[2,54],200:[2,54]},{6:[2,
-55],8:[2,55],10:[2,55],49:[2,55],50:[2,55],51:[2,55],53:[2,55],56:[2,55],57:[2,55],58:[2,55],59:[2,55],60:[2,55],61:[2,55],62:[2,55],63:[2,55],64:[2,55],65:[2,55],66:[2,55],67:[2,55],68:[2,55],69:[2,55],70:[2,55],71:[2,55],72:[2,55],73:[2,55],74:[2,55],75:[2,55],76:[2,55],77:[2,55],78:[2,55],79:[2,55],81:[2,55],82:[2,55],83:[2,55],84:[2,55],85:[2,55],86:[2,55],87:[2,55],88:[2,55],89:[2,55],90:[2,55],91:[2,55],92:[2,55],93:[2,55],94:[2,55],95:[2,55],96:[2,55],97:[2,55],98:[2,55],99:[2,55],100:[2,55],
-101:[2,55],102:[2,55],103:[2,55],104:[2,55],105:[2,55],106:[2,55],107:[2,55],108:[2,55],109:[2,55],110:[2,55],111:[2,55],112:[2,55],113:[2,55],114:[2,55],115:[2,55],116:[2,55],117:[2,55],118:[2,55],119:[2,55],120:[2,55],121:[2,55],122:[2,55],123:[2,55],124:[2,55],125:[2,55],126:[2,55],127:[2,55],128:[2,55],129:[2,55],130:[2,55],131:[2,55],132:[2,55],134:[2,55],135:[2,55],137:[2,55],138:[2,55],140:[2,55],141:[2,55],142:[2,55],143:[2,55],144:[2,55],145:[2,55],146:[2,55],147:[2,55],148:[2,55],149:[2,
-55],150:[2,55],151:[2,55],152:[2,55],153:[2,55],154:[2,55],155:[2,55],156:[2,55],157:[2,55],158:[2,55],159:[2,55],160:[2,55],161:[2,55],162:[2,55],165:[2,55],166:[2,55],167:[2,55],169:[2,55],170:[2,55],185:[2,55],188:[2,55],194:[2,55],196:[2,55],198:[2,55],200:[2,55]},{6:[2,56],8:[2,56],10:[2,56],49:[2,56],50:[2,56],51:[2,56],53:[2,56],56:[2,56],57:[2,56],58:[2,56],59:[2,56],60:[2,56],61:[2,56],62:[2,56],63:[2,56],64:[2,56],65:[2,56],66:[2,56],67:[2,56],68:[2,56],69:[2,56],70:[2,56],71:[2,56],72:[2,
-56],73:[2,56],74:[2,56],75:[2,56],76:[2,56],77:[2,56],78:[2,56],79:[2,56],81:[2,56],82:[2,56],83:[2,56],84:[2,56],85:[2,56],86:[2,56],87:[2,56],88:[2,56],89:[2,56],90:[2,56],91:[2,56],92:[2,56],93:[2,56],94:[2,56],95:[2,56],96:[2,56],97:[2,56],98:[2,56],99:[2,56],100:[2,56],101:[2,56],102:[2,56],103:[2,56],104:[2,56],105:[2,56],106:[2,56],107:[2,56],108:[2,56],109:[2,56],110:[2,56],111:[2,56],112:[2,56],113:[2,56],114:[2,56],115:[2,56],116:[2,56],117:[2,56],118:[2,56],119:[2,56],120:[2,56],121:[2,
-56],122:[2,56],123:[2,56],124:[2,56],125:[2,56],126:[2,56],127:[2,56],128:[2,56],129:[2,56],130:[2,56],131:[2,56],132:[2,56],134:[2,56],135:[2,56],137:[2,56],138:[2,56],140:[2,56],141:[2,56],142:[2,56],143:[2,56],144:[2,56],145:[2,56],146:[2,56],147:[2,56],148:[2,56],149:[2,56],150:[2,56],151:[2,56],152:[2,56],153:[2,56],154:[2,56],155:[2,56],156:[2,56],157:[2,56],158:[2,56],159:[2,56],160:[2,56],161:[2,56],162:[2,56],165:[2,56],166:[2,56],167:[2,56],169:[2,56],170:[2,56],185:[2,56],188:[2,56],194:[2,
-56],196:[2,56],198:[2,56],200:[2,56]},{6:[2,57],8:[2,57],10:[2,57],49:[2,57],50:[2,57],51:[2,57],53:[2,57],56:[2,57],57:[2,57],58:[2,57],59:[2,57],60:[2,57],61:[2,57],62:[2,57],63:[2,57],64:[2,57],65:[2,57],66:[2,57],67:[2,57],68:[2,57],69:[2,57],70:[2,57],71:[2,57],72:[2,57],73:[2,57],74:[2,57],75:[2,57],76:[2,57],77:[2,57],78:[2,57],79:[2,57],81:[2,57],82:[2,57],83:[2,57],84:[2,57],85:[2,57],86:[2,57],87:[2,57],88:[2,57],89:[2,57],90:[2,57],91:[2,57],92:[2,57],93:[2,57],94:[2,57],95:[2,57],96:[2,
-57],97:[2,57],98:[2,57],99:[2,57],100:[2,57],101:[2,57],102:[2,57],103:[2,57],104:[2,57],105:[2,57],106:[2,57],107:[2,57],108:[2,57],109:[2,57],110:[2,57],111:[2,57],112:[2,57],113:[2,57],114:[2,57],115:[2,57],116:[2,57],117:[2,57],118:[2,57],119:[2,57],120:[2,57],121:[2,57],122:[2,57],123:[2,57],124:[2,57],125:[2,57],126:[2,57],127:[2,57],128:[2,57],129:[2,57],130:[2,57],131:[2,57],132:[2,57],134:[2,57],135:[2,57],137:[2,57],138:[2,57],140:[2,57],141:[2,57],142:[2,57],143:[2,57],144:[2,57],145:[2,
-57],146:[2,57],147:[2,57],148:[2,57],149:[2,57],150:[2,57],151:[2,57],152:[2,57],153:[2,57],154:[2,57],155:[2,57],156:[2,57],157:[2,57],158:[2,57],159:[2,57],160:[2,57],161:[2,57],162:[2,57],165:[2,57],166:[2,57],167:[2,57],169:[2,57],170:[2,57],185:[2,57],188:[2,57],194:[2,57],196:[2,57],198:[2,57],200:[2,57]},{52:250,53:[1,254],64:[1,251],65:[1,252],66:[1,253]},{6:[2,69],8:[2,69],10:[2,69],49:[2,69],50:[2,69],51:[2,69],53:[2,69],56:[2,69],57:[2,69],58:[2,69],59:[2,69],60:[2,69],61:[2,69],62:[2,
-69],63:[2,69],64:[2,69],65:[2,69],66:[2,69],67:[2,69],68:[2,69],69:[2,69],70:[2,69],71:[2,69],72:[2,69],73:[2,69],74:[2,69],75:[2,69],76:[2,69],77:[2,69],78:[2,69],79:[2,69],81:[2,69],82:[2,69],83:[2,69],84:[2,69],85:[2,69],86:[2,69],87:[2,69],88:[2,69],89:[2,69],90:[2,69],91:[2,69],92:[2,69],93:[2,69],94:[2,69],95:[2,69],96:[2,69],97:[2,69],98:[2,69],99:[2,69],100:[2,69],101:[2,69],102:[2,69],103:[2,69],104:[2,69],105:[2,69],106:[2,69],107:[2,69],108:[2,69],109:[2,69],110:[2,69],111:[2,69],112:[2,
-69],113:[2,69],114:[2,69],115:[2,69],116:[2,69],117:[2,69],118:[2,69],119:[2,69],120:[2,69],121:[2,69],122:[2,69],123:[2,69],124:[2,69],125:[2,69],126:[2,69],127:[2,69],128:[2,69],129:[2,69],130:[2,69],131:[2,69],132:[2,69],134:[2,69],135:[2,69],137:[2,69],138:[2,69],140:[2,69],141:[2,69],142:[2,69],143:[2,69],144:[2,69],145:[2,69],146:[2,69],147:[2,69],148:[2,69],149:[2,69],150:[2,69],151:[2,69],152:[2,69],153:[2,69],154:[2,69],155:[2,69],156:[2,69],157:[2,69],158:[2,69],159:[2,69],160:[2,69],161:[2,
-69],162:[2,69],165:[2,69],166:[2,69],167:[2,69],169:[2,69],170:[2,69],185:[2,69],188:[2,69],194:[2,69],196:[2,69],198:[2,69],200:[2,69]},{6:[2,7],8:[2,7],10:[2,7],49:[2,7],50:[2,7],51:[2,7],53:[2,7],56:[2,7],57:[2,7],58:[2,7],59:[2,7],60:[2,7],61:[2,7],62:[2,7],63:[2,7],64:[2,7],65:[2,7],66:[2,7],67:[2,7],68:[2,7],69:[2,7],70:[2,7],71:[2,7],72:[2,7],73:[2,7],74:[2,7],75:[2,7],76:[2,7],77:[2,7],78:[2,7],79:[2,7],81:[2,7],82:[2,7],83:[2,7],84:[2,7],85:[2,7],86:[2,7],87:[2,7],88:[2,7],89:[2,7],90:[2,
-7],91:[2,7],92:[2,7],93:[2,7],94:[2,7],95:[2,7],96:[2,7],97:[2,7],98:[2,7],99:[2,7],100:[2,7],101:[2,7],102:[2,7],103:[2,7],104:[2,7],105:[2,7],106:[2,7],107:[2,7],108:[2,7],109:[2,7],110:[2,7],111:[2,7],112:[2,7],113:[2,7],114:[2,7],115:[2,7],116:[2,7],117:[2,7],118:[2,7],119:[2,7],120:[2,7],121:[2,7],122:[2,7],123:[2,7],124:[2,7],125:[2,7],126:[2,7],127:[2,7],128:[2,7],129:[2,7],130:[2,7],131:[2,7],132:[2,7],134:[2,7],135:[2,7],137:[2,7],138:[2,7],140:[2,7],141:[2,7],142:[2,7],143:[2,7],144:[2,
-7],145:[2,7],146:[2,7],147:[2,7],148:[2,7],149:[2,7],150:[2,7],151:[2,7],152:[2,7],153:[2,7],154:[2,7],155:[2,7],156:[2,7],157:[2,7],158:[2,7],159:[2,7],160:[2,7],161:[2,7],162:[2,7],165:[2,7],166:[2,7],167:[2,7],169:[2,7],170:[2,7],185:[2,7],188:[2,7],194:[2,7],196:[2,7],198:[2,7],200:[2,7]},{6:[2,70],8:[2,70],10:[2,70],49:[2,70],50:[2,70],51:[2,70],53:[2,70],56:[2,70],57:[2,70],58:[2,70],59:[2,70],60:[2,70],61:[2,70],62:[2,70],63:[2,70],64:[2,70],65:[2,70],66:[2,70],67:[2,70],68:[2,70],69:[2,70],
-70:[2,70],71:[2,70],72:[2,70],73:[2,70],74:[2,70],75:[2,70],76:[2,70],77:[2,70],78:[2,70],79:[2,70],81:[2,70],82:[2,70],83:[2,70],84:[2,70],85:[2,70],86:[2,70],87:[2,70],88:[2,70],89:[2,70],90:[2,70],91:[2,70],92:[2,70],93:[2,70],94:[2,70],95:[2,70],96:[2,70],97:[2,70],98:[2,70],99:[2,70],100:[2,70],101:[2,70],102:[2,70],103:[2,70],104:[2,70],105:[2,70],106:[2,70],107:[2,70],108:[2,70],109:[2,70],110:[2,70],111:[2,70],112:[2,70],113:[2,70],114:[2,70],115:[2,70],116:[2,70],117:[2,70],118:[2,70],119:[2,
-70],120:[2,70],121:[2,70],122:[2,70],123:[2,70],124:[2,70],125:[2,70],126:[2,70],127:[2,70],128:[2,70],129:[2,70],130:[2,70],131:[2,70],132:[2,70],134:[2,70],135:[2,70],137:[2,70],138:[2,70],140:[2,70],141:[2,70],142:[2,70],143:[2,70],144:[2,70],145:[2,70],146:[2,70],147:[2,70],148:[2,70],149:[2,70],150:[2,70],151:[2,70],152:[2,70],153:[2,70],154:[2,70],155:[2,70],156:[2,70],157:[2,70],158:[2,70],159:[2,70],160:[2,70],161:[2,70],162:[2,70],165:[2,70],166:[2,70],167:[2,70],169:[2,70],170:[2,70],185:[2,
-70],188:[2,70],194:[2,70],196:[2,70],198:[2,70],200:[2,70]},{6:[2,71],8:[2,71],10:[2,71],49:[2,71],50:[2,71],51:[2,71],53:[2,71],56:[2,71],57:[2,71],58:[2,71],59:[2,71],60:[2,71],61:[2,71],62:[2,71],63:[2,71],64:[2,71],65:[2,71],66:[2,71],67:[2,71],68:[2,71],69:[2,71],70:[2,71],71:[2,71],72:[2,71],73:[2,71],74:[2,71],75:[2,71],76:[2,71],77:[2,71],78:[2,71],79:[2,71],81:[2,71],82:[2,71],83:[2,71],84:[2,71],85:[2,71],86:[2,71],87:[2,71],88:[2,71],89:[2,71],90:[2,71],91:[2,71],92:[2,71],93:[2,71],94:[2,
-71],95:[2,71],96:[2,71],97:[2,71],98:[2,71],99:[2,71],100:[2,71],101:[2,71],102:[2,71],103:[2,71],104:[2,71],105:[2,71],106:[2,71],107:[2,71],108:[2,71],109:[2,71],110:[2,71],111:[2,71],112:[2,71],113:[2,71],114:[2,71],115:[2,71],116:[2,71],117:[2,71],118:[2,71],119:[2,71],120:[2,71],121:[2,71],122:[2,71],123:[2,71],124:[2,71],125:[2,71],126:[2,71],127:[2,71],128:[2,71],129:[2,71],130:[2,71],131:[2,71],132:[2,71],134:[2,71],135:[2,71],137:[2,71],138:[2,71],140:[2,71],141:[2,71],142:[2,71],143:[2,
-71],144:[2,71],145:[2,71],146:[2,71],147:[2,71],148:[2,71],149:[2,71],150:[2,71],151:[2,71],152:[2,71],153:[2,71],154:[2,71],155:[2,71],156:[2,71],157:[2,71],158:[2,71],159:[2,71],160:[2,71],161:[2,71],162:[2,71],165:[2,71],166:[2,71],167:[2,71],169:[2,71],170:[2,71],185:[2,71],188:[2,71],194:[2,71],196:[2,71],198:[2,71],200:[2,71]},{6:[2,77],8:[2,77],10:[2,77],49:[2,77],50:[2,77],51:[2,77],53:[2,77],56:[2,77],57:[2,77],58:[2,77],59:[2,77],60:[2,77],61:[2,77],62:[2,77],63:[2,77],64:[2,77],65:[2,77],
-66:[2,77],67:[2,77],68:[2,77],69:[2,77],70:[2,77],71:[2,77],72:[2,77],73:[2,77],74:[2,77],75:[2,77],76:[2,77],77:[2,77],78:[2,77],79:[2,77],81:[2,77],82:[2,77],83:[2,77],84:[2,77],85:[2,77],86:[2,77],87:[2,77],88:[2,77],89:[2,77],90:[2,77],91:[2,77],92:[2,77],93:[2,77],94:[2,77],95:[2,77],96:[2,77],97:[2,77],98:[2,77],99:[2,77],100:[2,77],101:[2,77],102:[2,77],103:[2,77],104:[2,77],105:[2,77],106:[2,77],107:[2,77],108:[2,77],109:[2,77],110:[2,77],111:[2,77],112:[2,77],113:[2,77],114:[2,77],115:[2,
-77],116:[2,77],117:[2,77],118:[2,77],119:[2,77],120:[2,77],121:[2,77],122:[2,77],123:[2,77],124:[2,77],125:[2,77],126:[2,77],127:[2,77],128:[2,77],129:[2,77],130:[2,77],131:[2,77],132:[2,77],134:[2,77],135:[2,77],137:[2,77],138:[2,77],140:[2,77],141:[2,77],142:[2,77],143:[2,77],144:[2,77],145:[2,77],146:[2,77],147:[2,77],148:[2,77],149:[2,77],150:[2,77],151:[2,77],152:[2,77],153:[2,77],154:[2,77],155:[2,77],156:[2,77],157:[2,77],158:[2,77],159:[2,77],160:[2,77],161:[2,77],162:[2,77],165:[2,77],166:[2,
-77],167:[2,77],169:[2,77],170:[2,77],185:[2,77],188:[2,77],194:[2,77],196:[2,77],198:[2,77],200:[2,77]},{3:155,4:[1,156],13:255},{4:[2,5],8:[2,5]},{5:[1,256]},{6:[2,79],8:[2,79],10:[2,79],49:[2,79],50:[2,79],51:[2,79],53:[2,79],56:[2,79],57:[2,79],58:[2,79],59:[2,79],60:[2,79],61:[2,79],62:[2,79],63:[2,79],64:[2,79],65:[2,79],66:[2,79],67:[2,79],68:[2,79],69:[2,79],70:[2,79],71:[2,79],72:[2,79],73:[2,79],74:[2,79],75:[2,79],76:[2,79],77:[2,79],78:[2,79],79:[2,79],81:[2,79],82:[2,79],83:[2,79],84:[2,
-79],85:[2,79],86:[2,79],87:[2,79],88:[2,79],89:[2,79],90:[2,79],91:[2,79],92:[2,79],93:[2,79],94:[2,79],95:[2,79],96:[2,79],97:[2,79],98:[2,79],99:[2,79],100:[2,79],101:[2,79],102:[2,79],103:[2,79],104:[2,79],105:[2,79],106:[2,79],107:[2,79],108:[2,79],109:[2,79],110:[2,79],111:[2,79],112:[2,79],113:[2,79],114:[2,79],115:[2,79],116:[2,79],117:[2,79],118:[2,79],119:[2,79],120:[2,79],121:[2,79],122:[2,79],123:[2,79],124:[2,79],125:[2,79],126:[2,79],127:[2,79],128:[2,79],129:[2,79],130:[2,79],131:[2,
-79],132:[2,79],134:[2,79],135:[2,79],137:[2,79],138:[2,79],140:[2,79],141:[2,79],142:[2,79],143:[2,79],144:[2,79],145:[2,79],146:[2,79],147:[2,79],148:[2,79],149:[2,79],150:[2,79],151:[2,79],152:[2,79],153:[2,79],154:[2,79],155:[2,79],156:[2,79],157:[2,79],158:[2,79],159:[2,79],160:[2,79],161:[2,79],162:[2,79],165:[2,79],166:[2,79],167:[2,79],169:[2,79],170:[2,79],185:[2,79],188:[2,79],194:[2,79],196:[2,79],198:[2,79],200:[2,79]},{6:[2,80],8:[2,80],10:[2,80],49:[2,80],50:[2,80],51:[2,80],53:[2,80],
-56:[2,80],57:[2,80],58:[2,80],59:[2,80],60:[2,80],61:[2,80],62:[2,80],63:[2,80],64:[2,80],65:[2,80],66:[2,80],67:[2,80],68:[2,80],69:[2,80],70:[2,80],71:[2,80],72:[2,80],73:[2,80],74:[2,80],75:[2,80],76:[2,80],77:[2,80],78:[2,80],79:[2,80],81:[2,80],82:[2,80],83:[2,80],84:[2,80],85:[2,80],86:[2,80],87:[2,80],88:[2,80],89:[2,80],90:[2,80],91:[2,80],92:[2,80],93:[2,80],94:[2,80],95:[2,80],96:[2,80],97:[2,80],98:[2,80],99:[2,80],100:[2,80],101:[2,80],102:[2,80],103:[2,80],104:[2,80],105:[2,80],106:[2,
-80],107:[2,80],108:[2,80],109:[2,80],110:[2,80],111:[2,80],112:[2,80],113:[2,80],114:[2,80],115:[2,80],116:[2,80],117:[2,80],118:[2,80],119:[2,80],120:[2,80],121:[2,80],122:[2,80],123:[2,80],124:[2,80],125:[2,80],126:[2,80],127:[2,80],128:[2,80],129:[2,80],130:[2,80],131:[2,80],132:[2,80],134:[2,80],135:[2,80],137:[2,80],138:[2,80],140:[2,80],141:[2,80],142:[2,80],143:[2,80],144:[2,80],145:[2,80],146:[2,80],147:[2,80],148:[2,80],149:[2,80],150:[2,80],151:[2,80],152:[2,80],153:[2,80],154:[2,80],155:[2,
-80],156:[2,80],157:[2,80],158:[2,80],159:[2,80],160:[2,80],161:[2,80],162:[2,80],165:[2,80],166:[2,80],167:[2,80],169:[2,80],170:[2,80],185:[2,80],188:[2,80],194:[2,80],196:[2,80],198:[2,80],200:[2,80]},{6:[2,82],8:[2,82],10:[2,82],49:[2,82],50:[2,82],51:[2,82],53:[2,82],56:[2,82],57:[2,82],58:[2,82],59:[2,82],60:[2,82],61:[2,82],62:[2,82],63:[2,82],64:[2,82],65:[2,82],66:[2,82],67:[2,82],68:[2,82],69:[2,82],70:[2,82],71:[2,82],72:[2,82],73:[2,82],74:[2,82],75:[2,82],76:[2,82],77:[2,82],78:[2,82],
-79:[2,82],81:[2,82],82:[2,82],83:[2,82],84:[2,82],85:[2,82],86:[2,82],87:[2,82],88:[2,82],89:[2,82],90:[2,82],91:[2,82],92:[2,82],93:[2,82],94:[2,82],95:[2,82],96:[2,82],97:[2,82],98:[2,82],99:[2,82],100:[2,82],101:[2,82],102:[2,82],103:[2,82],104:[2,82],105:[2,82],106:[2,82],107:[2,82],108:[2,82],109:[2,82],110:[2,82],111:[2,82],112:[2,82],113:[2,82],114:[2,82],115:[2,82],116:[2,82],117:[2,82],118:[2,82],119:[2,82],120:[2,82],121:[2,82],122:[2,82],123:[2,82],124:[2,82],125:[2,82],126:[2,82],127:[2,
-82],128:[2,82],129:[2,82],130:[2,82],131:[2,82],132:[2,82],134:[2,82],135:[2,82],137:[2,82],138:[2,82],140:[2,82],141:[2,82],142:[2,82],143:[2,82],144:[2,82],145:[2,82],146:[2,82],147:[2,82],148:[2,82],149:[2,82],150:[2,82],151:[2,82],152:[2,82],153:[2,82],154:[2,82],155:[2,82],156:[2,82],157:[2,82],158:[2,82],159:[2,82],160:[2,82],161:[2,82],162:[2,82],165:[2,82],166:[2,82],167:[2,82],169:[2,82],170:[2,82],185:[2,82],188:[2,82],194:[2,82],196:[2,82],198:[2,82],200:[2,82]},{6:[2,83],8:[2,83],10:[2,
-83],49:[2,83],50:[2,83],51:[2,83],53:[2,83],56:[2,83],57:[2,83],58:[2,83],59:[2,83],60:[2,83],61:[2,83],62:[2,83],63:[2,83],64:[2,83],65:[2,83],66:[2,83],67:[2,83],68:[2,83],69:[2,83],70:[2,83],71:[2,83],72:[2,83],73:[2,83],74:[2,83],75:[2,83],76:[2,83],77:[2,83],78:[2,83],79:[2,83],81:[2,83],82:[2,83],83:[2,83],84:[2,83],85:[2,83],86:[2,83],87:[2,83],88:[2,83],89:[2,83],90:[2,83],91:[2,83],92:[2,83],93:[2,83],94:[2,83],95:[2,83],96:[2,83],97:[2,83],98:[2,83],99:[2,83],100:[2,83],101:[2,83],102:[2,
-83],103:[2,83],104:[2,83],105:[2,83],106:[2,83],107:[2,83],108:[2,83],109:[2,83],110:[2,83],111:[2,83],112:[2,83],113:[2,83],114:[2,83],115:[2,83],116:[2,83],117:[2,83],118:[2,83],119:[2,83],120:[2,83],121:[2,83],122:[2,83],123:[2,83],124:[2,83],125:[2,83],126:[2,83],127:[2,83],128:[2,83],129:[2,83],130:[2,83],131:[2,83],132:[2,83],134:[2,83],135:[2,83],137:[2,83],138:[2,83],140:[2,83],141:[2,83],142:[2,83],143:[2,83],144:[2,83],145:[2,83],146:[2,83],147:[2,83],148:[2,83],149:[2,83],150:[2,83],151:[2,
-83],152:[2,83],153:[2,83],154:[2,83],155:[2,83],156:[2,83],157:[2,83],158:[2,83],159:[2,83],160:[2,83],161:[2,83],162:[2,83],165:[2,83],166:[2,83],167:[2,83],169:[2,83],170:[2,83],185:[2,83],188:[2,83],194:[2,83],196:[2,83],198:[2,83],200:[2,83]},{6:[2,84],8:[2,84],10:[2,84],49:[2,84],50:[2,84],51:[2,84],53:[2,84],56:[2,84],57:[2,84],58:[2,84],59:[2,84],60:[2,84],61:[2,84],62:[2,84],63:[2,84],64:[2,84],65:[2,84],66:[2,84],67:[2,84],68:[2,84],69:[2,84],70:[2,84],71:[2,84],72:[2,84],73:[2,84],74:[2,
-84],75:[2,84],76:[2,84],77:[2,84],78:[2,84],79:[2,84],81:[2,84],82:[2,84],83:[2,84],84:[2,84],85:[2,84],86:[2,84],87:[2,84],88:[2,84],89:[2,84],90:[2,84],91:[2,84],92:[2,84],93:[2,84],94:[2,84],95:[2,84],96:[2,84],97:[2,84],98:[2,84],99:[2,84],100:[2,84],101:[2,84],102:[2,84],103:[2,84],104:[2,84],105:[2,84],106:[2,84],107:[2,84],108:[2,84],109:[2,84],110:[2,84],111:[2,84],112:[2,84],113:[2,84],114:[2,84],115:[2,84],116:[2,84],117:[2,84],118:[2,84],119:[2,84],120:[2,84],121:[2,84],122:[2,84],123:[2,
-84],124:[2,84],125:[2,84],126:[2,84],127:[2,84],128:[2,84],129:[2,84],130:[2,84],131:[2,84],132:[2,84],134:[2,84],135:[2,84],137:[2,84],138:[2,84],140:[2,84],141:[2,84],142:[2,84],143:[2,84],144:[2,84],145:[2,84],146:[2,84],147:[2,84],148:[2,84],149:[2,84],150:[2,84],151:[2,84],152:[2,84],153:[2,84],154:[2,84],155:[2,84],156:[2,84],157:[2,84],158:[2,84],159:[2,84],160:[2,84],161:[2,84],162:[2,84],165:[2,84],166:[2,84],167:[2,84],169:[2,84],170:[2,84],185:[2,84],188:[2,84],194:[2,84],196:[2,84],198:[2,
-84],200:[2,84]},{6:[2,85],8:[2,85],10:[2,85],49:[2,85],50:[2,85],51:[2,85],53:[2,85],56:[2,85],57:[2,85],58:[2,85],59:[2,85],60:[2,85],61:[2,85],62:[2,85],63:[2,85],64:[2,85],65:[2,85],66:[2,85],67:[2,85],68:[2,85],69:[2,85],70:[2,85],71:[2,85],72:[2,85],73:[2,85],74:[2,85],75:[2,85],76:[2,85],77:[2,85],78:[2,85],79:[2,85],81:[2,85],82:[2,85],83:[2,85],84:[2,85],85:[2,85],86:[2,85],87:[2,85],88:[2,85],89:[2,85],90:[2,85],91:[2,85],92:[2,85],93:[2,85],94:[2,85],95:[2,85],96:[2,85],97:[2,85],98:[2,
-85],99:[2,85],100:[2,85],101:[2,85],102:[2,85],103:[2,85],104:[2,85],105:[2,85],106:[2,85],107:[2,85],108:[2,85],109:[2,85],110:[2,85],111:[2,85],112:[2,85],113:[2,85],114:[2,85],115:[2,85],116:[2,85],117:[2,85],118:[2,85],119:[2,85],120:[2,85],121:[2,85],122:[2,85],123:[2,85],124:[2,85],125:[2,85],126:[2,85],127:[2,85],128:[2,85],129:[2,85],130:[2,85],131:[2,85],132:[2,85],134:[2,85],135:[2,85],137:[2,85],138:[2,85],140:[2,85],141:[2,85],142:[2,85],143:[2,85],144:[2,85],145:[2,85],146:[2,85],147:[2,
-85],148:[2,85],149:[2,85],150:[2,85],151:[2,85],152:[2,85],153:[2,85],154:[2,85],155:[2,85],156:[2,85],157:[2,85],158:[2,85],159:[2,85],160:[2,85],161:[2,85],162:[2,85],165:[2,85],166:[2,85],167:[2,85],169:[2,85],170:[2,85],185:[2,85],188:[2,85],194:[2,85],196:[2,85],198:[2,85],200:[2,85]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:257,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,
-44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,
-93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:258,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],
-75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],
-124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{6:[2,88],8:[2,88],10:[2,88],49:[2,88],50:[2,88],51:[2,88],53:[2,88],56:[2,88],57:[2,88],58:[2,88],59:[2,88],60:[2,88],61:[2,88],62:[2,88],63:[2,88],64:[2,88],65:[2,88],66:[2,88],67:[2,88],68:[2,88],69:[2,88],70:[2,88],
-71:[2,88],72:[2,88],73:[2,88],74:[2,88],75:[2,88],76:[2,88],77:[2,88],78:[2,88],79:[2,88],81:[2,88],82:[2,88],83:[2,88],84:[2,88],85:[2,88],86:[2,88],87:[2,88],88:[2,88],89:[2,88],90:[2,88],91:[2,88],92:[2,88],93:[2,88],94:[2,88],95:[2,88],96:[2,88],97:[2,88],98:[2,88],99:[2,88],100:[2,88],101:[2,88],102:[2,88],103:[2,88],104:[2,88],105:[2,88],106:[2,88],107:[2,88],108:[2,88],109:[2,88],110:[2,88],111:[2,88],112:[2,88],113:[2,88],114:[2,88],115:[2,88],116:[2,88],117:[2,88],118:[2,88],119:[2,88],120:[2,
-88],121:[2,88],122:[2,88],123:[2,88],124:[2,88],125:[2,88],126:[2,88],127:[2,88],128:[2,88],129:[2,88],130:[2,88],131:[2,88],132:[2,88],134:[2,88],135:[2,88],137:[2,88],138:[2,88],140:[2,88],141:[2,88],142:[2,88],143:[2,88],144:[2,88],145:[2,88],146:[2,88],147:[2,88],148:[2,88],149:[2,88],150:[2,88],151:[2,88],152:[2,88],153:[2,88],154:[2,88],155:[2,88],156:[2,88],157:[2,88],158:[2,88],159:[2,88],160:[2,88],161:[2,88],162:[2,88],165:[2,88],166:[2,88],167:[2,88],169:[2,88],170:[2,88],185:[2,88],188:[2,
-88],194:[2,88],196:[2,88],198:[2,88],200:[2,88]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:259,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,
-69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],
-157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:260,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],
-87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,
-132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:261,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,
-57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],
-137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:262,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],
-88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,
-103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:263,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],
-88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,
-103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21]},{6:[2,94],8:[2,94],10:[2,94],49:[2,94],50:[2,94],51:[2,94],53:[2,94],56:[2,94],57:[2,94],58:[2,94],59:[2,94],60:[2,94],61:[2,94],62:[2,94],63:[2,94],64:[2,94],65:[2,94],66:[2,94],67:[2,94],68:[2,94],69:[2,94],70:[2,
-94],71:[2,94],72:[2,94],73:[2,94],74:[2,94],75:[2,94],76:[2,94],77:[2,94],78:[2,94],79:[2,94],81:[2,94],82:[2,94],83:[2,94],84:[2,94],85:[2,94],86:[2,94],87:[2,94],88:[2,94],89:[2,94],90:[2,94],91:[2,94],92:[2,94],93:[2,94],94:[2,94],95:[2,94],96:[2,94],97:[2,94],98:[2,94],99:[2,94],100:[2,94],101:[2,94],102:[2,94],103:[2,94],104:[2,94],105:[2,94],106:[2,94],107:[2,94],108:[2,94],109:[2,94],110:[2,94],111:[2,94],112:[2,94],113:[2,94],114:[2,94],115:[2,94],116:[2,94],117:[2,94],118:[2,94],119:[2,94],
-120:[2,94],121:[2,94],122:[2,94],123:[2,94],124:[2,94],125:[2,94],126:[2,94],127:[2,94],128:[2,94],129:[2,94],130:[2,94],131:[2,94],132:[2,94],134:[2,94],135:[2,94],137:[2,94],138:[2,94],140:[2,94],141:[2,94],142:[2,94],143:[2,94],144:[2,94],145:[2,94],146:[2,94],147:[2,94],148:[2,94],149:[2,94],150:[2,94],151:[2,94],152:[2,94],153:[2,94],154:[2,94],155:[2,94],156:[2,94],157:[2,94],158:[2,94],159:[2,94],160:[2,94],161:[2,94],162:[2,94],165:[2,94],166:[2,94],167:[2,94],169:[2,94],170:[2,94],185:[2,
-94],188:[2,94],194:[2,94],196:[2,94],198:[2,94],200:[2,94]},{6:[2,95],8:[2,95],10:[2,95],49:[2,95],50:[2,95],51:[2,95],53:[2,95],56:[2,95],57:[2,95],58:[2,95],59:[2,95],60:[2,95],61:[2,95],62:[2,95],63:[2,95],64:[2,95],65:[2,95],66:[2,95],67:[2,95],68:[2,95],69:[2,95],70:[2,95],71:[2,95],72:[2,95],73:[2,95],74:[2,95],75:[2,95],76:[2,95],77:[2,95],78:[2,95],79:[2,95],81:[2,95],82:[2,95],83:[2,95],84:[2,95],85:[2,95],86:[2,95],87:[2,95],88:[2,95],89:[2,95],90:[2,95],91:[2,95],92:[2,95],93:[2,95],94:[2,
-95],95:[2,95],96:[2,95],97:[2,95],98:[2,95],99:[2,95],100:[2,95],101:[2,95],102:[2,95],103:[2,95],104:[2,95],105:[2,95],106:[2,95],107:[2,95],108:[2,95],109:[2,95],110:[2,95],111:[2,95],112:[2,95],113:[2,95],114:[2,95],115:[2,95],116:[2,95],117:[2,95],118:[2,95],119:[2,95],120:[2,95],121:[2,95],122:[2,95],123:[2,95],124:[2,95],125:[2,95],126:[2,95],127:[2,95],128:[2,95],129:[2,95],130:[2,95],131:[2,95],132:[2,95],134:[2,95],135:[2,95],137:[2,95],138:[2,95],140:[2,95],141:[2,95],142:[2,95],143:[2,
-95],144:[2,95],145:[2,95],146:[2,95],147:[2,95],148:[2,95],149:[2,95],150:[2,95],151:[2,95],152:[2,95],153:[2,95],154:[2,95],155:[2,95],156:[2,95],157:[2,95],158:[2,95],159:[2,95],160:[2,95],161:[2,95],162:[2,95],165:[2,95],166:[2,95],167:[2,95],169:[2,95],170:[2,95],185:[2,95],188:[2,95],194:[2,95],196:[2,95],198:[2,95],200:[2,95]},{6:[2,96],8:[2,96],10:[2,96],49:[2,96],50:[2,96],51:[2,96],53:[2,96],56:[2,96],57:[2,96],58:[2,96],59:[2,96],60:[2,96],61:[2,96],62:[2,96],63:[2,96],64:[2,96],65:[2,96],
-66:[2,96],67:[2,96],68:[2,96],69:[2,96],70:[2,96],71:[2,96],72:[2,96],73:[2,96],74:[2,96],75:[2,96],76:[2,96],77:[2,96],78:[2,96],79:[2,96],81:[2,96],82:[2,96],83:[2,96],84:[2,96],85:[2,96],86:[2,96],87:[2,96],88:[2,96],89:[2,96],90:[2,96],91:[2,96],92:[2,96],93:[2,96],94:[2,96],95:[2,96],96:[2,96],97:[2,96],98:[2,96],99:[2,96],100:[2,96],101:[2,96],102:[2,96],103:[2,96],104:[2,96],105:[2,96],106:[2,96],107:[2,96],108:[2,96],109:[2,96],110:[2,96],111:[2,96],112:[2,96],113:[2,96],114:[2,96],115:[2,
-96],116:[2,96],117:[2,96],118:[2,96],119:[2,96],120:[2,96],121:[2,96],122:[2,96],123:[2,96],124:[2,96],125:[2,96],126:[2,96],127:[2,96],128:[2,96],129:[2,96],130:[2,96],131:[2,96],132:[2,96],134:[2,96],135:[2,96],137:[2,96],138:[2,96],140:[2,96],141:[2,96],142:[2,96],143:[2,96],144:[2,96],145:[2,96],146:[2,96],147:[2,96],148:[2,96],149:[2,96],150:[2,96],151:[2,96],152:[2,96],153:[2,96],154:[2,96],155:[2,96],156:[2,96],157:[2,96],158:[2,96],159:[2,96],160:[2,96],161:[2,96],162:[2,96],165:[2,96],166:[2,
-96],167:[2,96],169:[2,96],170:[2,96],185:[2,96],188:[2,96],194:[2,96],196:[2,96],198:[2,96],200:[2,96]},{6:[2,97],8:[2,97],10:[2,97],49:[2,97],50:[2,97],51:[2,97],53:[2,97],56:[2,97],57:[2,97],58:[2,97],59:[2,97],60:[2,97],61:[2,97],62:[2,97],63:[2,97],64:[2,97],65:[2,97],66:[2,97],67:[2,97],68:[2,97],69:[2,97],70:[2,97],71:[2,97],72:[2,97],73:[2,97],74:[2,97],75:[2,97],76:[2,97],77:[2,97],78:[2,97],79:[2,97],81:[2,97],82:[2,97],83:[2,97],84:[2,97],85:[2,97],86:[2,97],87:[2,97],88:[2,97],89:[2,97],
-90:[2,97],91:[2,97],92:[2,97],93:[2,97],94:[2,97],95:[2,97],96:[2,97],97:[2,97],98:[2,97],99:[2,97],100:[2,97],101:[2,97],102:[2,97],103:[2,97],104:[2,97],105:[2,97],106:[2,97],107:[2,97],108:[2,97],109:[2,97],110:[2,97],111:[2,97],112:[2,97],113:[2,97],114:[2,97],115:[2,97],116:[2,97],117:[2,97],118:[2,97],119:[2,97],120:[2,97],121:[2,97],122:[2,97],123:[2,97],124:[2,97],125:[2,97],126:[2,97],127:[2,97],128:[2,97],129:[2,97],130:[2,97],131:[2,97],132:[2,97],134:[2,97],135:[2,97],137:[2,97],138:[2,
-97],140:[2,97],141:[2,97],142:[2,97],143:[2,97],144:[2,97],145:[2,97],146:[2,97],147:[2,97],148:[2,97],149:[2,97],150:[2,97],151:[2,97],152:[2,97],153:[2,97],154:[2,97],155:[2,97],156:[2,97],157:[2,97],158:[2,97],159:[2,97],160:[2,97],161:[2,97],162:[2,97],165:[2,97],166:[2,97],167:[2,97],169:[2,97],170:[2,97],185:[2,97],188:[2,97],194:[2,97],196:[2,97],198:[2,97],200:[2,97]},{6:[2,98],8:[2,98],10:[2,98],49:[2,98],50:[2,98],51:[2,98],53:[2,98],56:[2,98],57:[2,98],58:[2,98],59:[2,98],60:[2,98],61:[2,
-98],62:[2,98],63:[2,98],64:[2,98],65:[2,98],66:[2,98],67:[2,98],68:[2,98],69:[2,98],70:[2,98],71:[2,98],72:[2,98],73:[2,98],74:[2,98],75:[2,98],76:[2,98],77:[2,98],78:[2,98],79:[2,98],81:[2,98],82:[2,98],83:[2,98],84:[2,98],85:[2,98],86:[2,98],87:[2,98],88:[2,98],89:[2,98],90:[2,98],91:[2,98],92:[2,98],93:[2,98],94:[2,98],95:[2,98],96:[2,98],97:[2,98],98:[2,98],99:[2,98],100:[2,98],101:[2,98],102:[2,98],103:[2,98],104:[2,98],105:[2,98],106:[2,98],107:[2,98],108:[2,98],109:[2,98],110:[2,98],111:[2,
-98],112:[2,98],113:[2,98],114:[2,98],115:[2,98],116:[2,98],117:[2,98],118:[2,98],119:[2,98],120:[2,98],121:[2,98],122:[2,98],123:[2,98],124:[2,98],125:[2,98],126:[2,98],127:[2,98],128:[2,98],129:[2,98],130:[2,98],131:[2,98],132:[2,98],134:[2,98],135:[2,98],137:[2,98],138:[2,98],140:[2,98],141:[2,98],142:[2,98],143:[2,98],144:[2,98],145:[2,98],146:[2,98],147:[2,98],148:[2,98],149:[2,98],150:[2,98],151:[2,98],152:[2,98],153:[2,98],154:[2,98],155:[2,98],156:[2,98],157:[2,98],158:[2,98],159:[2,98],160:[2,
-98],161:[2,98],162:[2,98],165:[2,98],166:[2,98],167:[2,98],169:[2,98],170:[2,98],185:[2,98],188:[2,98],194:[2,98],196:[2,98],198:[2,98],200:[2,98]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:264,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],
-90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],
-141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:265,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,
-60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,
-105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:266,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],
-91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],
-143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{6:[2,102],8:[2,102],10:[2,102],49:[2,102],50:[2,102],51:[2,102],53:[2,102],56:[2,102],57:[2,102],58:[2,102],59:[2,102],60:[2,102],61:[2,102],62:[2,102],63:[2,102],64:[2,102],65:[2,102],66:[2,102],67:[2,102],68:[2,102],69:[2,102],70:[2,102],71:[2,102],72:[2,102],73:[2,102],74:[2,102],75:[2,102],76:[2,102],77:[2,102],78:[2,102],79:[2,102],81:[2,102],82:[2,102],83:[2,
-102],84:[2,102],85:[2,102],86:[2,102],87:[2,102],88:[2,102],89:[2,102],90:[2,102],91:[2,102],92:[2,102],93:[2,102],94:[2,102],95:[2,102],96:[2,102],97:[2,102],98:[2,102],99:[2,102],100:[2,102],101:[2,102],102:[2,102],103:[2,102],104:[2,102],105:[2,102],106:[2,102],107:[2,102],108:[2,102],109:[2,102],110:[2,102],111:[2,102],112:[2,102],113:[2,102],114:[2,102],115:[2,102],116:[2,102],117:[2,102],118:[2,102],119:[2,102],120:[2,102],121:[2,102],122:[2,102],123:[2,102],124:[2,102],125:[2,102],126:[2,102],
-127:[2,102],128:[2,102],129:[2,102],130:[2,102],131:[2,102],132:[2,102],134:[2,102],135:[2,102],137:[2,102],138:[2,102],140:[2,102],141:[2,102],142:[2,102],143:[2,102],144:[2,102],145:[2,102],146:[2,102],147:[2,102],148:[2,102],149:[2,102],150:[2,102],151:[2,102],152:[2,102],153:[2,102],154:[2,102],155:[2,102],156:[2,102],157:[2,102],158:[2,102],159:[2,102],160:[2,102],161:[2,102],162:[2,102],165:[2,102],166:[2,102],167:[2,102],169:[2,102],170:[2,102],185:[2,102],188:[2,102],194:[2,102],196:[2,102],
-198:[2,102],200:[2,102]},{6:[2,103],8:[2,103],10:[2,103],49:[2,103],50:[2,103],51:[2,103],53:[2,103],56:[2,103],57:[2,103],58:[2,103],59:[2,103],60:[2,103],61:[2,103],62:[2,103],63:[2,103],64:[2,103],65:[2,103],66:[2,103],67:[2,103],68:[2,103],69:[2,103],70:[2,103],71:[2,103],72:[2,103],73:[2,103],74:[2,103],75:[2,103],76:[2,103],77:[2,103],78:[2,103],79:[2,103],81:[2,103],82:[2,103],83:[2,103],84:[2,103],85:[2,103],86:[2,103],87:[2,103],88:[2,103],89:[2,103],90:[2,103],91:[2,103],92:[2,103],93:[2,
-103],94:[2,103],95:[2,103],96:[2,103],97:[2,103],98:[2,103],99:[2,103],100:[2,103],101:[2,103],102:[2,103],103:[2,103],104:[2,103],105:[2,103],106:[2,103],107:[2,103],108:[2,103],109:[2,103],110:[2,103],111:[2,103],112:[2,103],113:[2,103],114:[2,103],115:[2,103],116:[2,103],117:[2,103],118:[2,103],119:[2,103],120:[2,103],121:[2,103],122:[2,103],123:[2,103],124:[2,103],125:[2,103],126:[2,103],127:[2,103],128:[2,103],129:[2,103],130:[2,103],131:[2,103],132:[2,103],134:[2,103],135:[2,103],137:[2,103],
-138:[2,103],140:[2,103],141:[2,103],142:[2,103],143:[2,103],144:[2,103],145:[2,103],146:[2,103],147:[2,103],148:[2,103],149:[2,103],150:[2,103],151:[2,103],152:[2,103],153:[2,103],154:[2,103],155:[2,103],156:[2,103],157:[2,103],158:[2,103],159:[2,103],160:[2,103],161:[2,103],162:[2,103],165:[2,103],166:[2,103],167:[2,103],169:[2,103],170:[2,103],185:[2,103],188:[2,103],194:[2,103],196:[2,103],198:[2,103],200:[2,103]},{6:[2,104],8:[2,104],10:[2,104],49:[2,104],50:[2,104],51:[2,104],53:[2,104],56:[2,
-104],57:[2,104],58:[2,104],59:[2,104],60:[2,104],61:[2,104],62:[2,104],63:[2,104],64:[2,104],65:[2,104],66:[2,104],67:[2,104],68:[2,104],69:[2,104],70:[2,104],71:[2,104],72:[2,104],73:[2,104],74:[2,104],75:[2,104],76:[2,104],77:[2,104],78:[2,104],79:[2,104],81:[2,104],82:[2,104],83:[2,104],84:[2,104],85:[2,104],86:[2,104],87:[2,104],88:[2,104],89:[2,104],90:[2,104],91:[2,104],92:[2,104],93:[2,104],94:[2,104],95:[2,104],96:[2,104],97:[2,104],98:[2,104],99:[2,104],100:[2,104],101:[2,104],102:[2,104],
-103:[2,104],104:[2,104],105:[2,104],106:[2,104],107:[2,104],108:[2,104],109:[2,104],110:[2,104],111:[2,104],112:[2,104],113:[2,104],114:[2,104],115:[2,104],116:[2,104],117:[2,104],118:[2,104],119:[2,104],120:[2,104],121:[2,104],122:[2,104],123:[2,104],124:[2,104],125:[2,104],126:[2,104],127:[2,104],128:[2,104],129:[2,104],130:[2,104],131:[2,104],132:[2,104],134:[2,104],135:[2,104],137:[2,104],138:[2,104],140:[2,104],141:[2,104],142:[2,104],143:[2,104],144:[2,104],145:[2,104],146:[2,104],147:[2,104],
-148:[2,104],149:[2,104],150:[2,104],151:[2,104],152:[2,104],153:[2,104],154:[2,104],155:[2,104],156:[2,104],157:[2,104],158:[2,104],159:[2,104],160:[2,104],161:[2,104],162:[2,104],165:[2,104],166:[2,104],167:[2,104],169:[2,104],170:[2,104],185:[2,104],188:[2,104],194:[2,104],196:[2,104],198:[2,104],200:[2,104]},{6:[2,105],8:[2,105],10:[2,105],49:[2,105],50:[2,105],51:[2,105],53:[2,105],56:[2,105],57:[2,105],58:[2,105],59:[2,105],60:[2,105],61:[2,105],62:[2,105],63:[2,105],64:[2,105],65:[2,105],66:[2,
-105],67:[2,105],68:[2,105],69:[2,105],70:[2,105],71:[2,105],72:[2,105],73:[2,105],74:[2,105],75:[2,105],76:[2,105],77:[2,105],78:[2,105],79:[2,105],81:[2,105],82:[2,105],83:[2,105],84:[2,105],85:[2,105],86:[2,105],87:[2,105],88:[2,105],89:[2,105],90:[2,105],91:[2,105],92:[2,105],93:[2,105],94:[2,105],95:[2,105],96:[2,105],97:[2,105],98:[2,105],99:[2,105],100:[2,105],101:[2,105],102:[2,105],103:[2,105],104:[2,105],105:[2,105],106:[2,105],107:[2,105],108:[2,105],109:[2,105],110:[2,105],111:[2,105],
-112:[2,105],113:[2,105],114:[2,105],115:[2,105],116:[2,105],117:[2,105],118:[2,105],119:[2,105],120:[2,105],121:[2,105],122:[2,105],123:[2,105],124:[2,105],125:[2,105],126:[2,105],127:[2,105],128:[2,105],129:[2,105],130:[2,105],131:[2,105],132:[2,105],134:[2,105],135:[2,105],137:[2,105],138:[2,105],140:[2,105],141:[2,105],142:[2,105],143:[2,105],144:[2,105],145:[2,105],146:[2,105],147:[2,105],148:[2,105],149:[2,105],150:[2,105],151:[2,105],152:[2,105],153:[2,105],154:[2,105],155:[2,105],156:[2,105],
-157:[2,105],158:[2,105],159:[2,105],160:[2,105],161:[2,105],162:[2,105],165:[2,105],166:[2,105],167:[2,105],169:[2,105],170:[2,105],185:[2,105],188:[2,105],194:[2,105],196:[2,105],198:[2,105],200:[2,105]},{6:[2,106],8:[2,106],10:[2,106],49:[2,106],50:[2,106],51:[2,106],53:[2,106],56:[2,106],57:[2,106],58:[2,106],59:[2,106],60:[2,106],61:[2,106],62:[2,106],63:[2,106],64:[2,106],65:[2,106],66:[2,106],67:[2,106],68:[2,106],69:[2,106],70:[2,106],71:[2,106],72:[2,106],73:[2,106],74:[2,106],75:[2,106],
-76:[2,106],77:[2,106],78:[2,106],79:[2,106],81:[2,106],82:[2,106],83:[2,106],84:[2,106],85:[2,106],86:[2,106],87:[2,106],88:[2,106],89:[2,106],90:[2,106],91:[2,106],92:[2,106],93:[2,106],94:[2,106],95:[2,106],96:[2,106],97:[2,106],98:[2,106],99:[2,106],100:[2,106],101:[2,106],102:[2,106],103:[2,106],104:[2,106],105:[2,106],106:[2,106],107:[2,106],108:[2,106],109:[2,106],110:[2,106],111:[2,106],112:[2,106],113:[2,106],114:[2,106],115:[2,106],116:[2,106],117:[2,106],118:[2,106],119:[2,106],120:[2,106],
-121:[2,106],122:[2,106],123:[2,106],124:[2,106],125:[2,106],126:[2,106],127:[2,106],128:[2,106],129:[2,106],130:[2,106],131:[2,106],132:[2,106],134:[2,106],135:[2,106],137:[2,106],138:[2,106],140:[2,106],141:[2,106],142:[2,106],143:[2,106],144:[2,106],145:[2,106],146:[2,106],147:[2,106],148:[2,106],149:[2,106],150:[2,106],151:[2,106],152:[2,106],153:[2,106],154:[2,106],155:[2,106],156:[2,106],157:[2,106],158:[2,106],159:[2,106],160:[2,106],161:[2,106],162:[2,106],165:[2,106],166:[2,106],167:[2,106],
-169:[2,106],170:[2,106],185:[2,106],188:[2,106],194:[2,106],196:[2,106],198:[2,106],200:[2,106]},{6:[2,107],8:[2,107],10:[2,107],49:[2,107],50:[2,107],51:[2,107],53:[2,107],56:[2,107],57:[2,107],58:[2,107],59:[2,107],60:[2,107],61:[2,107],62:[2,107],63:[2,107],64:[2,107],65:[2,107],66:[2,107],67:[2,107],68:[2,107],69:[2,107],70:[2,107],71:[2,107],72:[2,107],73:[2,107],74:[2,107],75:[2,107],76:[2,107],77:[2,107],78:[2,107],79:[2,107],81:[2,107],82:[2,107],83:[2,107],84:[2,107],85:[2,107],86:[2,107],
-87:[2,107],88:[2,107],89:[2,107],90:[2,107],91:[2,107],92:[2,107],93:[2,107],94:[2,107],95:[2,107],96:[2,107],97:[2,107],98:[2,107],99:[2,107],100:[2,107],101:[2,107],102:[2,107],103:[2,107],104:[2,107],105:[2,107],106:[2,107],107:[2,107],108:[2,107],109:[2,107],110:[2,107],111:[2,107],112:[2,107],113:[2,107],114:[2,107],115:[2,107],116:[2,107],117:[2,107],118:[2,107],119:[2,107],120:[2,107],121:[2,107],122:[2,107],123:[2,107],124:[2,107],125:[2,107],126:[2,107],127:[2,107],128:[2,107],129:[2,107],
-130:[2,107],131:[2,107],132:[2,107],134:[2,107],135:[2,107],137:[2,107],138:[2,107],140:[2,107],141:[2,107],142:[2,107],143:[2,107],144:[2,107],145:[2,107],146:[2,107],147:[2,107],148:[2,107],149:[2,107],150:[2,107],151:[2,107],152:[2,107],153:[2,107],154:[2,107],155:[2,107],156:[2,107],157:[2,107],158:[2,107],159:[2,107],160:[2,107],161:[2,107],162:[2,107],165:[2,107],166:[2,107],167:[2,107],169:[2,107],170:[2,107],185:[2,107],188:[2,107],194:[2,107],196:[2,107],198:[2,107],200:[2,107]},{6:[2,108],
-8:[2,108],10:[2,108],49:[2,108],50:[2,108],51:[2,108],53:[2,108],56:[2,108],57:[2,108],58:[2,108],59:[2,108],60:[2,108],61:[2,108],62:[2,108],63:[2,108],64:[2,108],65:[2,108],66:[2,108],67:[2,108],68:[2,108],69:[2,108],70:[2,108],71:[2,108],72:[2,108],73:[2,108],74:[2,108],75:[2,108],76:[2,108],77:[2,108],78:[2,108],79:[2,108],81:[2,108],82:[2,108],83:[2,108],84:[2,108],85:[2,108],86:[2,108],87:[2,108],88:[2,108],89:[2,108],90:[2,108],91:[2,108],92:[2,108],93:[2,108],94:[2,108],95:[2,108],96:[2,108],
-97:[2,108],98:[2,108],99:[2,108],100:[2,108],101:[2,108],102:[2,108],103:[2,108],104:[2,108],105:[2,108],106:[2,108],107:[2,108],108:[2,108],109:[2,108],110:[2,108],111:[2,108],112:[2,108],113:[2,108],114:[2,108],115:[2,108],116:[2,108],117:[2,108],118:[2,108],119:[2,108],120:[2,108],121:[2,108],122:[2,108],123:[2,108],124:[2,108],125:[2,108],126:[2,108],127:[2,108],128:[2,108],129:[2,108],130:[2,108],131:[2,108],132:[2,108],134:[2,108],135:[2,108],137:[2,108],138:[2,108],140:[2,108],141:[2,108],
-142:[2,108],143:[2,108],144:[2,108],145:[2,108],146:[2,108],147:[2,108],148:[2,108],149:[2,108],150:[2,108],151:[2,108],152:[2,108],153:[2,108],154:[2,108],155:[2,108],156:[2,108],157:[2,108],158:[2,108],159:[2,108],160:[2,108],161:[2,108],162:[2,108],165:[2,108],166:[2,108],167:[2,108],169:[2,108],170:[2,108],185:[2,108],188:[2,108],194:[2,108],196:[2,108],198:[2,108],200:[2,108]},{6:[2,109],8:[2,109],10:[2,109],49:[2,109],50:[2,109],51:[2,109],53:[2,109],56:[2,109],57:[2,109],58:[2,109],59:[2,109],
-60:[2,109],61:[2,109],62:[2,109],63:[2,109],64:[2,109],65:[2,109],66:[2,109],67:[2,109],68:[2,109],69:[2,109],70:[2,109],71:[2,109],72:[2,109],73:[2,109],74:[2,109],75:[2,109],76:[2,109],77:[2,109],78:[2,109],79:[2,109],81:[2,109],82:[2,109],83:[2,109],84:[2,109],85:[2,109],86:[2,109],87:[2,109],88:[2,109],89:[2,109],90:[2,109],91:[2,109],92:[2,109],93:[2,109],94:[2,109],95:[2,109],96:[2,109],97:[2,109],98:[2,109],99:[2,109],100:[2,109],101:[2,109],102:[2,109],103:[2,109],104:[2,109],105:[2,109],
-106:[2,109],107:[2,109],108:[2,109],109:[2,109],110:[2,109],111:[2,109],112:[2,109],113:[2,109],114:[2,109],115:[2,109],116:[2,109],117:[2,109],118:[2,109],119:[2,109],120:[2,109],121:[2,109],122:[2,109],123:[2,109],124:[2,109],125:[2,109],126:[2,109],127:[2,109],128:[2,109],129:[2,109],130:[2,109],131:[2,109],132:[2,109],134:[2,109],135:[2,109],137:[2,109],138:[2,109],140:[2,109],141:[2,109],142:[2,109],143:[2,109],144:[2,109],145:[2,109],146:[2,109],147:[2,109],148:[2,109],149:[2,109],150:[2,109],
-151:[2,109],152:[2,109],153:[2,109],154:[2,109],155:[2,109],156:[2,109],157:[2,109],158:[2,109],159:[2,109],160:[2,109],161:[2,109],162:[2,109],165:[2,109],166:[2,109],167:[2,109],169:[2,109],170:[2,109],185:[2,109],188:[2,109],194:[2,109],196:[2,109],198:[2,109],200:[2,109]},{7:267,8:[1,129]},{4:[1,270],8:[1,26],11:268,48:35,49:[1,119],50:[1,47],51:[1,43],54:269,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,
-41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,
-91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{9:[1,271]},{6:[2,122],8:[2,122],10:[2,122],49:[2,122],50:[2,122],51:[2,122],53:[2,122],56:[2,122],57:[2,122],58:[2,122],59:[2,122],60:[2,122],61:[2,122],62:[2,122],63:[2,122],64:[2,122],65:[2,
-122],66:[2,122],67:[2,122],68:[2,122],69:[2,122],70:[2,122],71:[2,122],72:[2,122],73:[2,122],74:[2,122],75:[2,122],76:[2,122],77:[2,122],78:[2,122],79:[2,122],81:[2,122],82:[2,122],83:[2,122],84:[2,122],85:[2,122],86:[2,122],87:[2,122],88:[2,122],89:[2,122],90:[2,122],91:[2,122],92:[2,122],93:[2,122],94:[2,122],95:[2,122],96:[2,122],97:[2,122],98:[2,122],99:[2,122],100:[2,122],101:[2,122],102:[2,122],103:[2,122],104:[2,122],105:[2,122],106:[2,122],107:[2,122],108:[2,122],109:[2,122],110:[2,122],111:[2,
-122],112:[2,122],113:[2,122],114:[2,122],115:[2,122],116:[2,122],117:[2,122],118:[2,122],119:[2,122],120:[2,122],121:[2,122],122:[2,122],123:[2,122],124:[2,122],125:[2,122],126:[2,122],127:[2,122],128:[2,122],129:[2,122],130:[2,122],131:[2,122],132:[2,122],134:[2,122],135:[2,122],137:[2,122],138:[2,122],140:[2,122],141:[2,122],142:[2,122],143:[2,122],144:[2,122],145:[2,122],146:[2,122],147:[2,122],148:[2,122],149:[2,122],150:[2,122],151:[2,122],152:[2,122],153:[2,122],154:[2,122],155:[2,122],156:[2,
-122],157:[2,122],158:[2,122],159:[2,122],160:[2,122],161:[2,122],162:[2,122],165:[2,122],166:[2,122],167:[2,122],169:[2,122],170:[2,122],185:[2,122],188:[2,122],194:[2,122],196:[2,122],198:[2,122],200:[2,122]},{6:[2,123],8:[2,123],10:[2,123],49:[2,123],50:[2,123],51:[2,123],53:[2,123],56:[2,123],57:[2,123],58:[2,123],59:[2,123],60:[2,123],61:[2,123],62:[2,123],63:[2,123],64:[2,123],65:[2,123],66:[2,123],67:[2,123],68:[2,123],69:[2,123],70:[2,123],71:[2,123],72:[2,123],73:[2,123],74:[2,123],75:[2,
-123],76:[2,123],77:[2,123],78:[2,123],79:[2,123],81:[2,123],82:[2,123],83:[2,123],84:[2,123],85:[2,123],86:[2,123],87:[2,123],88:[2,123],89:[2,123],90:[2,123],91:[2,123],92:[2,123],93:[2,123],94:[2,123],95:[2,123],96:[2,123],97:[2,123],98:[2,123],99:[2,123],100:[2,123],101:[2,123],102:[2,123],103:[2,123],104:[2,123],105:[2,123],106:[2,123],107:[2,123],108:[2,123],109:[2,123],110:[2,123],111:[2,123],112:[2,123],113:[2,123],114:[2,123],115:[2,123],116:[2,123],117:[2,123],118:[2,123],119:[2,123],120:[2,
-123],121:[2,123],122:[2,123],123:[2,123],124:[2,123],125:[2,123],126:[2,123],127:[2,123],128:[2,123],129:[2,123],130:[2,123],131:[2,123],132:[2,123],134:[2,123],135:[2,123],137:[2,123],138:[2,123],140:[2,123],141:[2,123],142:[2,123],143:[2,123],144:[2,123],145:[2,123],146:[2,123],147:[2,123],148:[2,123],149:[2,123],150:[2,123],151:[2,123],152:[2,123],153:[2,123],154:[2,123],155:[2,123],156:[2,123],157:[2,123],158:[2,123],159:[2,123],160:[2,123],161:[2,123],162:[2,123],165:[2,123],166:[2,123],167:[2,
-123],169:[2,123],170:[2,123],185:[2,123],188:[2,123],194:[2,123],196:[2,123],198:[2,123],200:[2,123]},{6:[2,124],8:[2,124],10:[2,124],49:[2,124],50:[2,124],51:[2,124],53:[2,124],56:[2,124],57:[2,124],58:[2,124],59:[2,124],60:[2,124],61:[2,124],62:[2,124],63:[2,124],64:[2,124],65:[2,124],66:[2,124],67:[2,124],68:[2,124],69:[2,124],70:[2,124],71:[2,124],72:[2,124],73:[2,124],74:[2,124],75:[2,124],76:[2,124],77:[2,124],78:[2,124],79:[2,124],81:[2,124],82:[2,124],83:[2,124],84:[2,124],85:[2,124],86:[2,
-124],87:[2,124],88:[2,124],89:[2,124],90:[2,124],91:[2,124],92:[2,124],93:[2,124],94:[2,124],95:[2,124],96:[2,124],97:[2,124],98:[2,124],99:[2,124],100:[2,124],101:[2,124],102:[2,124],103:[2,124],104:[2,124],105:[2,124],106:[2,124],107:[2,124],108:[2,124],109:[2,124],110:[2,124],111:[2,124],112:[2,124],113:[2,124],114:[2,124],115:[2,124],116:[2,124],117:[2,124],118:[2,124],119:[2,124],120:[2,124],121:[2,124],122:[2,124],123:[2,124],124:[2,124],125:[2,124],126:[2,124],127:[2,124],128:[2,124],129:[2,
-124],130:[2,124],131:[2,124],132:[2,124],134:[2,124],135:[2,124],137:[2,124],138:[2,124],140:[2,124],141:[2,124],142:[2,124],143:[2,124],144:[2,124],145:[2,124],146:[2,124],147:[2,124],148:[2,124],149:[2,124],150:[2,124],151:[2,124],152:[2,124],153:[2,124],154:[2,124],155:[2,124],156:[2,124],157:[2,124],158:[2,124],159:[2,124],160:[2,124],161:[2,124],162:[2,124],165:[2,124],166:[2,124],167:[2,124],169:[2,124],170:[2,124],185:[2,124],188:[2,124],194:[2,124],196:[2,124],198:[2,124],200:[2,124]},{6:[2,
-125],8:[2,125],10:[2,125],49:[2,125],50:[2,125],51:[2,125],53:[2,125],56:[2,125],57:[2,125],58:[2,125],59:[2,125],60:[2,125],61:[2,125],62:[2,125],63:[2,125],64:[2,125],65:[2,125],66:[2,125],67:[2,125],68:[2,125],69:[2,125],70:[2,125],71:[2,125],72:[2,125],73:[2,125],74:[2,125],75:[2,125],76:[2,125],77:[2,125],78:[2,125],79:[2,125],81:[2,125],82:[2,125],83:[2,125],84:[2,125],85:[2,125],86:[2,125],87:[2,125],88:[2,125],89:[2,125],90:[2,125],91:[2,125],92:[2,125],93:[2,125],94:[2,125],95:[2,125],96:[2,
-125],97:[2,125],98:[2,125],99:[2,125],100:[2,125],101:[2,125],102:[2,125],103:[2,125],104:[2,125],105:[2,125],106:[2,125],107:[2,125],108:[2,125],109:[2,125],110:[2,125],111:[2,125],112:[2,125],113:[2,125],114:[2,125],115:[2,125],116:[2,125],117:[2,125],118:[2,125],119:[2,125],120:[2,125],121:[2,125],122:[2,125],123:[2,125],124:[2,125],125:[2,125],126:[2,125],127:[2,125],128:[2,125],129:[2,125],130:[2,125],131:[2,125],132:[2,125],134:[2,125],135:[2,125],137:[2,125],138:[2,125],140:[2,125],141:[2,
-125],142:[2,125],143:[2,125],144:[2,125],145:[2,125],146:[2,125],147:[2,125],148:[2,125],149:[2,125],150:[2,125],151:[2,125],152:[2,125],153:[2,125],154:[2,125],155:[2,125],156:[2,125],157:[2,125],158:[2,125],159:[2,125],160:[2,125],161:[2,125],162:[2,125],165:[2,125],166:[2,125],167:[2,125],169:[2,125],170:[2,125],185:[2,125],188:[2,125],194:[2,125],196:[2,125],198:[2,125],200:[2,125]},{6:[2,126],8:[2,126],10:[2,126],49:[2,126],50:[2,126],51:[2,126],53:[2,126],56:[2,126],57:[2,126],58:[2,126],59:[2,
-126],60:[2,126],61:[2,126],62:[2,126],63:[2,126],64:[2,126],65:[2,126],66:[2,126],67:[2,126],68:[2,126],69:[2,126],70:[2,126],71:[2,126],72:[2,126],73:[2,126],74:[2,126],75:[2,126],76:[2,126],77:[2,126],78:[2,126],79:[2,126],81:[2,126],82:[2,126],83:[2,126],84:[2,126],85:[2,126],86:[2,126],87:[2,126],88:[2,126],89:[2,126],90:[2,126],91:[2,126],92:[2,126],93:[2,126],94:[2,126],95:[2,126],96:[2,126],97:[2,126],98:[2,126],99:[2,126],100:[2,126],101:[2,126],102:[2,126],103:[2,126],104:[2,126],105:[2,
-126],106:[2,126],107:[2,126],108:[2,126],109:[2,126],110:[2,126],111:[2,126],112:[2,126],113:[2,126],114:[2,126],115:[2,126],116:[2,126],117:[2,126],118:[2,126],119:[2,126],120:[2,126],121:[2,126],122:[2,126],123:[2,126],124:[2,126],125:[2,126],126:[2,126],127:[2,126],128:[2,126],129:[2,126],130:[2,126],131:[2,126],132:[2,126],134:[2,126],135:[2,126],137:[2,126],138:[2,126],140:[2,126],141:[2,126],142:[2,126],143:[2,126],144:[2,126],145:[2,126],146:[2,126],147:[2,126],148:[2,126],149:[2,126],150:[2,
-126],151:[2,126],152:[2,126],153:[2,126],154:[2,126],155:[2,126],156:[2,126],157:[2,126],158:[2,126],159:[2,126],160:[2,126],161:[2,126],162:[2,126],165:[2,126],166:[2,126],167:[2,126],169:[2,126],170:[2,126],185:[2,126],188:[2,126],194:[2,126],196:[2,126],198:[2,126],200:[2,126]},{6:[2,127],8:[2,127],10:[2,127],49:[2,127],50:[2,127],51:[2,127],53:[2,127],56:[2,127],57:[2,127],58:[2,127],59:[2,127],60:[2,127],61:[2,127],62:[2,127],63:[2,127],64:[2,127],65:[2,127],66:[2,127],67:[2,127],68:[2,127],
-69:[2,127],70:[2,127],71:[2,127],72:[2,127],73:[2,127],74:[2,127],75:[2,127],76:[2,127],77:[2,127],78:[2,127],79:[2,127],81:[2,127],82:[2,127],83:[2,127],84:[2,127],85:[2,127],86:[2,127],87:[2,127],88:[2,127],89:[2,127],90:[2,127],91:[2,127],92:[2,127],93:[2,127],94:[2,127],95:[2,127],96:[2,127],97:[2,127],98:[2,127],99:[2,127],100:[2,127],101:[2,127],102:[2,127],103:[2,127],104:[2,127],105:[2,127],106:[2,127],107:[2,127],108:[2,127],109:[2,127],110:[2,127],111:[2,127],112:[2,127],113:[2,127],114:[2,
-127],115:[2,127],116:[2,127],117:[2,127],118:[2,127],119:[2,127],120:[2,127],121:[2,127],122:[2,127],123:[2,127],124:[2,127],125:[2,127],126:[2,127],127:[2,127],128:[2,127],129:[2,127],130:[2,127],131:[2,127],132:[2,127],134:[2,127],135:[2,127],137:[2,127],138:[2,127],140:[2,127],141:[2,127],142:[2,127],143:[2,127],144:[2,127],145:[2,127],146:[2,127],147:[2,127],148:[2,127],149:[2,127],150:[2,127],151:[2,127],152:[2,127],153:[2,127],154:[2,127],155:[2,127],156:[2,127],157:[2,127],158:[2,127],159:[2,
-127],160:[2,127],161:[2,127],162:[2,127],165:[2,127],166:[2,127],167:[2,127],169:[2,127],170:[2,127],185:[2,127],188:[2,127],194:[2,127],196:[2,127],198:[2,127],200:[2,127]},{6:[2,128],8:[2,128],10:[2,128],49:[2,128],50:[2,128],51:[2,128],53:[2,128],56:[2,128],57:[2,128],58:[2,128],59:[2,128],60:[2,128],61:[2,128],62:[2,128],63:[2,128],64:[2,128],65:[2,128],66:[2,128],67:[2,128],68:[2,128],69:[2,128],70:[2,128],71:[2,128],72:[2,128],73:[2,128],74:[2,128],75:[2,128],76:[2,128],77:[2,128],78:[2,128],
-79:[2,128],81:[2,128],82:[2,128],83:[2,128],84:[2,128],85:[2,128],86:[2,128],87:[2,128],88:[2,128],89:[2,128],90:[2,128],91:[2,128],92:[2,128],93:[2,128],94:[2,128],95:[2,128],96:[2,128],97:[2,128],98:[2,128],99:[2,128],100:[2,128],101:[2,128],102:[2,128],103:[2,128],104:[2,128],105:[2,128],106:[2,128],107:[2,128],108:[2,128],109:[2,128],110:[2,128],111:[2,128],112:[2,128],113:[2,128],114:[2,128],115:[2,128],116:[2,128],117:[2,128],118:[2,128],119:[2,128],120:[2,128],121:[2,128],122:[2,128],123:[2,
-128],124:[2,128],125:[2,128],126:[2,128],127:[2,128],128:[2,128],129:[2,128],130:[2,128],131:[2,128],132:[2,128],134:[2,128],135:[2,128],137:[2,128],138:[2,128],140:[2,128],141:[2,128],142:[2,128],143:[2,128],144:[2,128],145:[2,128],146:[2,128],147:[2,128],148:[2,128],149:[2,128],150:[2,128],151:[2,128],152:[2,128],153:[2,128],154:[2,128],155:[2,128],156:[2,128],157:[2,128],158:[2,128],159:[2,128],160:[2,128],161:[2,128],162:[2,128],165:[2,128],166:[2,128],167:[2,128],169:[2,128],170:[2,128],185:[2,
-128],188:[2,128],194:[2,128],196:[2,128],198:[2,128],200:[2,128]},{6:[2,129],8:[2,129],10:[2,129],49:[2,129],50:[2,129],51:[2,129],53:[2,129],56:[2,129],57:[2,129],58:[2,129],59:[2,129],60:[2,129],61:[2,129],62:[2,129],63:[2,129],64:[2,129],65:[2,129],66:[2,129],67:[2,129],68:[2,129],69:[2,129],70:[2,129],71:[2,129],72:[2,129],73:[2,129],74:[2,129],75:[2,129],76:[2,129],77:[2,129],78:[2,129],79:[2,129],81:[2,129],82:[2,129],83:[2,129],84:[2,129],85:[2,129],86:[2,129],87:[2,129],88:[2,129],89:[2,129],
-90:[2,129],91:[2,129],92:[2,129],93:[2,129],94:[2,129],95:[2,129],96:[2,129],97:[2,129],98:[2,129],99:[2,129],100:[2,129],101:[2,129],102:[2,129],103:[2,129],104:[2,129],105:[2,129],106:[2,129],107:[2,129],108:[2,129],109:[2,129],110:[2,129],111:[2,129],112:[2,129],113:[2,129],114:[2,129],115:[2,129],116:[2,129],117:[2,129],118:[2,129],119:[2,129],120:[2,129],121:[2,129],122:[2,129],123:[2,129],124:[2,129],125:[2,129],126:[2,129],127:[2,129],128:[2,129],129:[2,129],130:[2,129],131:[2,129],132:[2,
-129],134:[2,129],135:[2,129],137:[2,129],138:[2,129],140:[2,129],141:[2,129],142:[2,129],143:[2,129],144:[2,129],145:[2,129],146:[2,129],147:[2,129],148:[2,129],149:[2,129],150:[2,129],151:[2,129],152:[2,129],153:[2,129],154:[2,129],155:[2,129],156:[2,129],157:[2,129],158:[2,129],159:[2,129],160:[2,129],161:[2,129],162:[2,129],165:[2,129],166:[2,129],167:[2,129],169:[2,129],170:[2,129],185:[2,129],188:[2,129],194:[2,129],196:[2,129],198:[2,129],200:[2,129]},{6:[2,130],8:[2,130],10:[2,130],49:[2,130],
-50:[2,130],51:[2,130],53:[2,130],56:[2,130],57:[2,130],58:[2,130],59:[2,130],60:[2,130],61:[2,130],62:[2,130],63:[2,130],64:[2,130],65:[2,130],66:[2,130],67:[2,130],68:[2,130],69:[2,130],70:[2,130],71:[2,130],72:[2,130],73:[2,130],74:[2,130],75:[2,130],76:[2,130],77:[2,130],78:[2,130],79:[2,130],81:[2,130],82:[2,130],83:[2,130],84:[2,130],85:[2,130],86:[2,130],87:[2,130],88:[2,130],89:[2,130],90:[2,130],91:[2,130],92:[2,130],93:[2,130],94:[2,130],95:[2,130],96:[2,130],97:[2,130],98:[2,130],99:[2,
-130],100:[2,130],101:[2,130],102:[2,130],103:[2,130],104:[2,130],105:[2,130],106:[2,130],107:[2,130],108:[2,130],109:[2,130],110:[2,130],111:[2,130],112:[2,130],113:[2,130],114:[2,130],115:[2,130],116:[2,130],117:[2,130],118:[2,130],119:[2,130],120:[2,130],121:[2,130],122:[2,130],123:[2,130],124:[2,130],125:[2,130],126:[2,130],127:[2,130],128:[2,130],129:[2,130],130:[2,130],131:[2,130],132:[2,130],134:[2,130],135:[2,130],137:[2,130],138:[2,130],140:[2,130],141:[2,130],142:[2,130],143:[2,130],144:[2,
-130],145:[2,130],146:[2,130],147:[2,130],148:[2,130],149:[2,130],150:[2,130],151:[2,130],152:[2,130],153:[2,130],154:[2,130],155:[2,130],156:[2,130],157:[2,130],158:[2,130],159:[2,130],160:[2,130],161:[2,130],162:[2,130],165:[2,130],166:[2,130],167:[2,130],169:[2,130],170:[2,130],185:[2,130],188:[2,130],194:[2,130],196:[2,130],198:[2,130],200:[2,130]},{6:[2,131],8:[2,131],10:[2,131],49:[2,131],50:[2,131],51:[2,131],53:[2,131],56:[2,131],57:[2,131],58:[2,131],59:[2,131],60:[2,131],61:[2,131],62:[2,
-131],63:[2,131],64:[2,131],65:[2,131],66:[2,131],67:[2,131],68:[2,131],69:[2,131],70:[2,131],71:[2,131],72:[2,131],73:[2,131],74:[2,131],75:[2,131],76:[2,131],77:[2,131],78:[2,131],79:[2,131],81:[2,131],82:[2,131],83:[2,131],84:[2,131],85:[2,131],86:[2,131],87:[2,131],88:[2,131],89:[2,131],90:[2,131],91:[2,131],92:[2,131],93:[2,131],94:[2,131],95:[2,131],96:[2,131],97:[2,131],98:[2,131],99:[2,131],100:[2,131],101:[2,131],102:[2,131],103:[2,131],104:[2,131],105:[2,131],106:[2,131],107:[2,131],108:[2,
-131],109:[2,131],110:[2,131],111:[2,131],112:[2,131],113:[2,131],114:[2,131],115:[2,131],116:[2,131],117:[2,131],118:[2,131],119:[2,131],120:[2,131],121:[2,131],122:[2,131],123:[2,131],124:[2,131],125:[2,131],126:[2,131],127:[2,131],128:[2,131],129:[2,131],130:[2,131],131:[2,131],132:[2,131],134:[2,131],135:[2,131],137:[2,131],138:[2,131],140:[2,131],141:[2,131],142:[2,131],143:[2,131],144:[2,131],145:[2,131],146:[2,131],147:[2,131],148:[2,131],149:[2,131],150:[2,131],151:[2,131],152:[2,131],153:[2,
-131],154:[2,131],155:[2,131],156:[2,131],157:[2,131],158:[2,131],159:[2,131],160:[2,131],161:[2,131],162:[2,131],165:[2,131],166:[2,131],167:[2,131],169:[2,131],170:[2,131],185:[2,131],188:[2,131],194:[2,131],196:[2,131],198:[2,131],200:[2,131]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:272,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,
-50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],
-128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:273,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],
-81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,
-98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:274,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,
-51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],
-129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:275,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],
-82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,
-99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:277,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,
-52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],
-130:[1,100],131:[1,101],132:[1,102],134:[1,276],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[2,156],49:[2,156],50:[2,156],51:[2,156],56:[2,156],57:[2,156],58:[2,156],59:[2,156],60:[2,156],61:[2,156],62:[2,156],63:[2,156],67:[2,156],68:[2,156],69:[2,156],70:[2,156],71:[2,156],72:[2,156],73:[2,156],74:[2,156],75:[2,156],76:[2,156],77:[2,156],78:[2,156],79:[2,156],
-81:[2,156],82:[2,156],83:[2,156],84:[2,156],85:[2,156],86:[2,156],87:[2,156],88:[2,156],89:[2,156],90:[2,156],91:[2,156],92:[2,156],93:[2,156],94:[2,156],95:[2,156],96:[2,156],97:[2,156],98:[2,156],99:[2,156],100:[2,156],101:[2,156],102:[2,156],103:[2,156],104:[2,156],105:[2,156],106:[2,156],107:[2,156],108:[2,156],109:[2,156],110:[2,156],111:[2,156],112:[2,156],113:[2,156],114:[2,156],115:[2,156],116:[2,156],117:[2,156],118:[2,156],119:[2,156],120:[2,156],121:[2,156],122:[2,156],123:[2,156],124:[2,
-156],125:[2,156],126:[2,156],127:[2,156],128:[2,156],129:[2,156],130:[2,156],131:[2,156],132:[2,156],134:[2,156],135:[2,156],137:[2,156],138:[2,156],141:[2,156],143:[2,156],145:[2,156],147:[2,156],149:[2,156],151:[2,156],153:[2,156],155:[2,156],157:[2,156],159:[2,156],161:[2,156],162:[2,156]},{10:[1,279],136:278,165:[1,238],166:[1,239],173:237},{140:[1,280],188:[1,281]},{10:[2,200],140:[2,200],142:[2,200],144:[2,200],146:[2,200],148:[2,200],150:[2,200],152:[2,200],154:[2,200],156:[2,200],158:[2,200],
-160:[2,200],188:[2,200]},{8:[1,282]},{10:[2,199],140:[2,199],142:[2,199],144:[2,199],146:[2,199],148:[2,199],150:[2,199],152:[2,199],154:[2,199],156:[2,199],158:[2,199],160:[2,199],185:[1,283],188:[2,199]},{10:[2,196],140:[2,196],142:[2,196],144:[2,196],146:[2,196],148:[2,196],150:[2,196],152:[2,196],154:[2,196],156:[2,196],158:[2,196],160:[2,196],185:[2,196],188:[2,196]},{8:[1,284]},{10:[2,195],140:[2,195],142:[2,195],144:[2,195],146:[2,195],148:[2,195],150:[2,195],152:[2,195],154:[2,195],156:[2,
-195],158:[2,195],160:[2,195],185:[2,195],188:[2,195]},{142:[1,285],188:[1,281]},{144:[1,286],188:[1,281]},{146:[1,287],188:[1,281]},{148:[1,288],188:[1,281]},{150:[1,289],188:[1,281]},{152:[1,290],188:[1,281]},{154:[1,291],188:[1,281]},{156:[1,292],188:[1,281]},{158:[1,293],188:[1,281]},{7:226,8:[1,129],17:294},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:213,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],
-72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],
-121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],139:295,141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],160:[2,193],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21],182:211,183:[1,212],184:210,185:[2,193],
-186:208,187:[1,209],188:[2,193]},{8:[2,8]},{8:[2,9],49:[2,9],50:[2,9],51:[2,9],56:[2,9],57:[2,9],58:[2,9],59:[2,9],60:[2,9],61:[2,9],62:[2,9],63:[2,9],67:[2,9],68:[2,9],69:[2,9],70:[2,9],71:[2,9],72:[2,9],73:[2,9],74:[2,9],75:[2,9],76:[2,9],77:[2,9],78:[2,9],79:[2,9],81:[2,9],82:[2,9],83:[2,9],84:[2,9],85:[2,9],86:[2,9],87:[2,9],88:[2,9],89:[2,9],90:[2,9],91:[2,9],92:[2,9],93:[2,9],94:[2,9],95:[2,9],96:[2,9],97:[2,9],98:[2,9],99:[2,9],100:[2,9],101:[2,9],102:[2,9],103:[2,9],104:[2,9],105:[2,9],106:[2,
-9],107:[2,9],108:[2,9],109:[2,9],110:[2,9],111:[2,9],112:[2,9],113:[2,9],114:[2,9],115:[2,9],116:[2,9],117:[2,9],118:[2,9],119:[2,9],120:[2,9],121:[2,9],122:[2,9],123:[2,9],124:[2,9],125:[2,9],126:[2,9],127:[2,9],128:[2,9],129:[2,9],130:[2,9],131:[2,9],132:[2,9],135:[2,9],137:[2,9],138:[2,9],141:[2,9],143:[2,9],145:[2,9],147:[2,9],149:[2,9],151:[2,9],153:[2,9],155:[2,9],157:[2,9],159:[2,9],160:[2,9],161:[2,9],162:[2,9],169:[2,9],170:[2,9],175:[2,9],176:[2,9],177:[2,9],178:[2,9],179:[2,9],180:[2,9],
-181:[2,9],183:[2,9],185:[2,9],187:[2,9],188:[2,9]},{8:[1,26],10:[2,193],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:213,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],
-98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],139:296,141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],
-153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21],182:211,183:[1,212],184:210,185:[2,193],186:208,187:[1,209],188:[2,193]},{8:[1,26],10:[2,193],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:213,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,
-44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,
-93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],139:297,141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],163:[1,298],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21],182:211,183:[1,212],184:210,185:[2,193],186:208,187:[1,209],188:[2,
-193]},{8:[2,44],49:[2,44],50:[2,44],51:[2,44],56:[2,44],57:[2,44],58:[2,44],59:[2,44],60:[2,44],61:[2,44],62:[2,44],63:[2,44],67:[2,44],68:[2,44],69:[2,44],70:[2,44],71:[2,44],72:[2,44],73:[2,44],74:[2,44],75:[2,44],76:[2,44],77:[2,44],78:[2,44],79:[2,44],81:[2,44],82:[2,44],83:[2,44],84:[2,44],85:[2,44],86:[2,44],87:[2,44],88:[2,44],89:[2,44],90:[2,44],91:[2,44],92:[2,44],93:[2,44],94:[2,44],95:[2,44],96:[2,44],97:[2,44],98:[2,44],99:[2,44],100:[2,44],101:[2,44],102:[2,44],103:[2,44],104:[2,44],
-105:[2,44],106:[2,44],107:[2,44],108:[2,44],109:[2,44],110:[2,44],111:[2,44],112:[2,44],113:[2,44],114:[2,44],115:[2,44],116:[2,44],117:[2,44],118:[2,44],119:[2,44],120:[2,44],121:[2,44],122:[2,44],123:[2,44],124:[2,44],125:[2,44],126:[2,44],127:[2,44],128:[2,44],129:[2,44],130:[2,44],131:[2,44],132:[2,44],135:[2,44],137:[2,44],138:[2,44],141:[2,44],143:[2,44],145:[2,44],147:[2,44],149:[2,44],151:[2,44],153:[2,44],155:[2,44],157:[2,44],159:[2,44],161:[2,44],162:[2,44],169:[2,44],170:[2,44],175:[2,
-44],176:[2,44],177:[2,44],178:[2,44],179:[2,44],180:[2,44],181:[2,44]},{8:[2,45],49:[2,45],50:[2,45],51:[2,45],56:[2,45],57:[2,45],58:[2,45],59:[2,45],60:[2,45],61:[2,45],62:[2,45],63:[2,45],67:[2,45],68:[2,45],69:[2,45],70:[2,45],71:[2,45],72:[2,45],73:[2,45],74:[2,45],75:[2,45],76:[2,45],77:[2,45],78:[2,45],79:[2,45],81:[2,45],82:[2,45],83:[2,45],84:[2,45],85:[2,45],86:[2,45],87:[2,45],88:[2,45],89:[2,45],90:[2,45],91:[2,45],92:[2,45],93:[2,45],94:[2,45],95:[2,45],96:[2,45],97:[2,45],98:[2,45],
-99:[2,45],100:[2,45],101:[2,45],102:[2,45],103:[2,45],104:[2,45],105:[2,45],106:[2,45],107:[2,45],108:[2,45],109:[2,45],110:[2,45],111:[2,45],112:[2,45],113:[2,45],114:[2,45],115:[2,45],116:[2,45],117:[2,45],118:[2,45],119:[2,45],120:[2,45],121:[2,45],122:[2,45],123:[2,45],124:[2,45],125:[2,45],126:[2,45],127:[2,45],128:[2,45],129:[2,45],130:[2,45],131:[2,45],132:[2,45],135:[2,45],137:[2,45],138:[2,45],141:[2,45],143:[2,45],145:[2,45],147:[2,45],149:[2,45],151:[2,45],153:[2,45],155:[2,45],157:[2,
-45],159:[2,45],161:[2,45],162:[2,45],169:[2,45],170:[2,45],175:[2,45],176:[2,45],177:[2,45],178:[2,45],179:[2,45],180:[2,45],181:[2,45]},{68:[2,209],191:[2,209],193:[2,209],195:[2,209],197:[2,209],199:[2,209]},{68:[2,210],191:[2,210],193:[2,210],195:[2,210],197:[2,210],199:[2,210]},{68:[2,211],191:[2,211],193:[2,211],195:[2,211],197:[2,211],199:[2,211]},{10:[1,299]},{6:[2,158],8:[2,158],10:[2,158],49:[2,158],50:[2,158],51:[2,158],53:[2,158],56:[2,158],57:[2,158],58:[2,158],59:[2,158],60:[2,158],61:[2,
-158],62:[2,158],63:[2,158],64:[2,158],65:[2,158],66:[2,158],67:[2,158],68:[2,158],69:[2,158],70:[2,158],71:[2,158],72:[2,158],73:[2,158],74:[2,158],75:[2,158],76:[2,158],77:[2,158],78:[2,158],79:[2,158],81:[2,158],82:[2,158],83:[2,158],84:[2,158],85:[2,158],86:[2,158],87:[2,158],88:[2,158],89:[2,158],90:[2,158],91:[2,158],92:[2,158],93:[2,158],94:[2,158],95:[2,158],96:[2,158],97:[2,158],98:[2,158],99:[2,158],100:[2,158],101:[2,158],102:[2,158],103:[2,158],104:[2,158],105:[2,158],106:[2,158],107:[2,
-158],108:[2,158],109:[2,158],110:[2,158],111:[2,158],112:[2,158],113:[2,158],114:[2,158],115:[2,158],116:[2,158],117:[2,158],118:[2,158],119:[2,158],120:[2,158],121:[2,158],122:[2,158],123:[2,158],124:[2,158],125:[2,158],126:[2,158],127:[2,158],128:[2,158],129:[2,158],130:[2,158],131:[2,158],132:[2,158],135:[2,158],137:[2,158],138:[2,158],140:[2,158],141:[2,158],142:[2,158],143:[2,158],144:[2,158],145:[2,158],146:[2,158],147:[2,158],148:[2,158],149:[2,158],150:[2,158],151:[2,158],152:[2,158],153:[2,
-158],154:[2,158],155:[2,158],156:[2,158],157:[2,158],158:[2,158],159:[2,158],160:[2,158],161:[2,158],162:[2,158],165:[1,238],166:[1,239],169:[2,158],170:[2,158],173:300,185:[2,158],188:[2,158],194:[2,158],196:[2,158],198:[2,158],200:[2,158]},{136:301,165:[1,238],166:[1,239],173:237},{6:[2,182],8:[2,182],10:[2,182],49:[2,182],50:[2,182],51:[2,182],53:[2,182],56:[2,182],57:[2,182],58:[2,182],59:[2,182],60:[2,182],61:[2,182],62:[2,182],63:[2,182],64:[2,182],65:[2,182],66:[2,182],67:[2,182],68:[2,182],
-69:[2,182],70:[2,182],71:[2,182],72:[2,182],73:[2,182],74:[2,182],75:[2,182],76:[2,182],77:[2,182],78:[2,182],79:[2,182],81:[2,182],82:[2,182],83:[2,182],84:[2,182],85:[2,182],86:[2,182],87:[2,182],88:[2,182],89:[2,182],90:[2,182],91:[2,182],92:[2,182],93:[2,182],94:[2,182],95:[2,182],96:[2,182],97:[2,182],98:[2,182],99:[2,182],100:[2,182],101:[2,182],102:[2,182],103:[2,182],104:[2,182],105:[2,182],106:[2,182],107:[2,182],108:[2,182],109:[2,182],110:[2,182],111:[2,182],112:[2,182],113:[2,182],114:[2,
-182],115:[2,182],116:[2,182],117:[2,182],118:[2,182],119:[2,182],120:[2,182],121:[2,182],122:[2,182],123:[2,182],124:[2,182],125:[2,182],126:[2,182],127:[2,182],128:[2,182],129:[2,182],130:[2,182],131:[2,182],132:[2,182],135:[2,182],137:[2,182],138:[2,182],140:[2,182],141:[2,182],142:[2,182],143:[2,182],144:[2,182],145:[2,182],146:[2,182],147:[2,182],148:[2,182],149:[2,182],150:[2,182],151:[2,182],152:[2,182],153:[2,182],154:[2,182],155:[2,182],156:[2,182],157:[2,182],158:[2,182],159:[2,182],160:[2,
-182],161:[2,182],162:[2,182],165:[2,182],166:[2,182],169:[2,182],170:[2,182],185:[2,182],188:[2,182],194:[2,182],196:[2,182],198:[2,182],200:[2,182]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:304,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],
-90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],
-141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],166:[1,303],168:305,169:[1,117],170:[1,118],172:302},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:304,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],
-85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],
-132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],168:305,169:[1,117],170:[1,118],172:306},{8:[1,236]},{6:[2,163],8:[2,163],10:[2,163],49:[2,163],50:[2,163],51:[2,163],53:[2,163],56:[2,163],57:[2,163],58:[2,163],59:[2,163],60:[2,163],61:[2,163],62:[2,163],63:[2,163],64:[2,163],65:[2,163],66:[2,163],67:[2,163],68:[2,163],69:[2,163],70:[2,163],71:[2,163],72:[2,
-163],73:[2,163],74:[2,163],75:[2,163],76:[2,163],77:[2,163],78:[2,163],79:[2,163],81:[2,163],82:[2,163],83:[2,163],84:[2,163],85:[2,163],86:[2,163],87:[2,163],88:[2,163],89:[2,163],90:[2,163],91:[2,163],92:[2,163],93:[2,163],94:[2,163],95:[2,163],96:[2,163],97:[2,163],98:[2,163],99:[2,163],100:[2,163],101:[2,163],102:[2,163],103:[2,163],104:[2,163],105:[2,163],106:[2,163],107:[2,163],108:[2,163],109:[2,163],110:[2,163],111:[2,163],112:[2,163],113:[2,163],114:[2,163],115:[2,163],116:[2,163],117:[2,
-163],118:[2,163],119:[2,163],120:[2,163],121:[2,163],122:[2,163],123:[2,163],124:[2,163],125:[2,163],126:[2,163],127:[2,163],128:[2,163],129:[2,163],130:[2,163],131:[2,163],132:[2,163],135:[2,163],137:[2,163],138:[2,163],140:[2,163],141:[2,163],142:[2,163],143:[2,163],144:[2,163],145:[2,163],146:[2,163],147:[2,163],148:[2,163],149:[2,163],150:[2,163],151:[2,163],152:[2,163],153:[2,163],154:[2,163],155:[2,163],156:[2,163],157:[2,163],158:[2,163],159:[2,163],160:[2,163],161:[2,163],162:[2,163],166:[1,
-307],167:[1,308],169:[2,163],170:[2,163],185:[2,163],188:[2,163],194:[2,163],196:[2,163],198:[2,163],200:[2,163]},{6:[2,164],8:[2,164],10:[2,164],49:[2,164],50:[2,164],51:[2,164],53:[2,164],56:[2,164],57:[2,164],58:[2,164],59:[2,164],60:[2,164],61:[2,164],62:[2,164],63:[2,164],64:[2,164],65:[2,164],66:[2,164],67:[2,164],68:[2,164],69:[2,164],70:[2,164],71:[2,164],72:[2,164],73:[2,164],74:[2,164],75:[2,164],76:[2,164],77:[2,164],78:[2,164],79:[2,164],81:[2,164],82:[2,164],83:[2,164],84:[2,164],85:[2,
-164],86:[2,164],87:[2,164],88:[2,164],89:[2,164],90:[2,164],91:[2,164],92:[2,164],93:[2,164],94:[2,164],95:[2,164],96:[2,164],97:[2,164],98:[2,164],99:[2,164],100:[2,164],101:[2,164],102:[2,164],103:[2,164],104:[2,164],105:[2,164],106:[2,164],107:[2,164],108:[2,164],109:[2,164],110:[2,164],111:[2,164],112:[2,164],113:[2,164],114:[2,164],115:[2,164],116:[2,164],117:[2,164],118:[2,164],119:[2,164],120:[2,164],121:[2,164],122:[2,164],123:[2,164],124:[2,164],125:[2,164],126:[2,164],127:[2,164],128:[2,
-164],129:[2,164],130:[2,164],131:[2,164],132:[2,164],135:[2,164],137:[2,164],138:[2,164],140:[2,164],141:[2,164],142:[2,164],143:[2,164],144:[2,164],145:[2,164],146:[2,164],147:[2,164],148:[2,164],149:[2,164],150:[2,164],151:[2,164],152:[2,164],153:[2,164],154:[2,164],155:[2,164],156:[2,164],157:[2,164],158:[2,164],159:[2,164],160:[2,164],161:[2,164],162:[2,164],165:[1,309],169:[2,164],170:[2,164],185:[2,164],188:[2,164],194:[2,164],196:[2,164],198:[2,164],200:[2,164]},{8:[1,26],48:35,49:[1,119],
-50:[1,47],51:[1,43],54:310,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],
-107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{6:[2,169],8:[2,169],10:[2,169],
-49:[2,169],50:[2,169],51:[2,169],53:[2,169],56:[2,169],57:[2,169],58:[2,169],59:[2,169],60:[2,169],61:[2,169],62:[2,169],63:[2,169],64:[2,169],65:[2,169],66:[2,169],67:[2,169],68:[2,169],69:[2,169],70:[2,169],71:[2,169],72:[2,169],73:[2,169],74:[2,169],75:[2,169],76:[2,169],77:[2,169],78:[2,169],79:[2,169],81:[2,169],82:[2,169],83:[2,169],84:[2,169],85:[2,169],86:[2,169],87:[2,169],88:[2,169],89:[2,169],90:[2,169],91:[2,169],92:[2,169],93:[2,169],94:[2,169],95:[2,169],96:[2,169],97:[2,169],98:[2,
-169],99:[2,169],100:[2,169],101:[2,169],102:[2,169],103:[2,169],104:[2,169],105:[2,169],106:[2,169],107:[2,169],108:[2,169],109:[2,169],110:[2,169],111:[2,169],112:[2,169],113:[2,169],114:[2,169],115:[2,169],116:[2,169],117:[2,169],118:[2,169],119:[2,169],120:[2,169],121:[2,169],122:[2,169],123:[2,169],124:[2,169],125:[2,169],126:[2,169],127:[2,169],128:[2,169],129:[2,169],130:[2,169],131:[2,169],132:[2,169],135:[2,169],137:[2,169],138:[2,169],140:[2,169],141:[2,169],142:[2,169],143:[2,169],144:[2,
-169],145:[2,169],146:[2,169],147:[2,169],148:[2,169],149:[2,169],150:[2,169],151:[2,169],152:[2,169],153:[2,169],154:[2,169],155:[2,169],156:[2,169],157:[2,169],158:[2,169],159:[2,169],160:[2,169],161:[2,169],162:[2,169],166:[1,311],169:[2,169],170:[2,169],185:[2,169],188:[2,169],194:[2,169],196:[2,169],198:[2,169],200:[2,169]},{6:[2,170],8:[2,170],10:[2,170],49:[2,170],50:[2,170],51:[2,170],53:[2,170],56:[2,170],57:[2,170],58:[2,170],59:[2,170],60:[2,170],61:[2,170],62:[2,170],63:[2,170],64:[2,170],
-65:[2,170],66:[2,170],67:[2,170],68:[2,170],69:[2,170],70:[2,170],71:[2,170],72:[2,170],73:[2,170],74:[2,170],75:[2,170],76:[2,170],77:[2,170],78:[2,170],79:[2,170],81:[2,170],82:[2,170],83:[2,170],84:[2,170],85:[2,170],86:[2,170],87:[2,170],88:[2,170],89:[2,170],90:[2,170],91:[2,170],92:[2,170],93:[2,170],94:[2,170],95:[2,170],96:[2,170],97:[2,170],98:[2,170],99:[2,170],100:[2,170],101:[2,170],102:[2,170],103:[2,170],104:[2,170],105:[2,170],106:[2,170],107:[2,170],108:[2,170],109:[2,170],110:[2,
-170],111:[2,170],112:[2,170],113:[2,170],114:[2,170],115:[2,170],116:[2,170],117:[2,170],118:[2,170],119:[2,170],120:[2,170],121:[2,170],122:[2,170],123:[2,170],124:[2,170],125:[2,170],126:[2,170],127:[2,170],128:[2,170],129:[2,170],130:[2,170],131:[2,170],132:[2,170],135:[2,170],137:[2,170],138:[2,170],140:[2,170],141:[2,170],142:[2,170],143:[2,170],144:[2,170],145:[2,170],146:[2,170],147:[2,170],148:[2,170],149:[2,170],150:[2,170],151:[2,170],152:[2,170],153:[2,170],154:[2,170],155:[2,170],156:[2,
-170],157:[2,170],158:[2,170],159:[2,170],160:[2,170],161:[2,170],162:[2,170],165:[1,312],169:[2,170],170:[2,170],185:[2,170],188:[2,170],194:[2,170],196:[2,170],198:[2,170],200:[2,170]},{6:[2,49],8:[2,49],10:[2,49],49:[2,49],50:[2,49],51:[2,49],53:[2,49],56:[2,49],57:[2,49],58:[2,49],59:[2,49],60:[2,49],61:[2,49],62:[2,49],63:[2,49],64:[2,49],65:[2,49],66:[2,49],67:[2,49],68:[2,49],69:[2,49],70:[2,49],71:[2,49],72:[2,49],73:[2,49],74:[2,49],75:[2,49],76:[2,49],77:[2,49],78:[2,49],79:[2,49],81:[2,
-49],82:[2,49],83:[2,49],84:[2,49],85:[2,49],86:[2,49],87:[2,49],88:[2,49],89:[2,49],90:[2,49],91:[2,49],92:[2,49],93:[2,49],94:[2,49],95:[2,49],96:[2,49],97:[2,49],98:[2,49],99:[2,49],100:[2,49],101:[2,49],102:[2,49],103:[2,49],104:[2,49],105:[2,49],106:[2,49],107:[2,49],108:[2,49],109:[2,49],110:[2,49],111:[2,49],112:[2,49],113:[2,49],114:[2,49],115:[2,49],116:[2,49],117:[2,49],118:[2,49],119:[2,49],120:[2,49],121:[2,49],122:[2,49],123:[2,49],124:[2,49],125:[2,49],126:[2,49],127:[2,49],128:[2,49],
-129:[2,49],130:[2,49],131:[2,49],132:[2,49],134:[2,49],135:[2,49],137:[2,49],138:[2,49],140:[2,49],141:[2,49],142:[2,49],143:[2,49],144:[2,49],145:[2,49],146:[2,49],147:[2,49],148:[2,49],149:[2,49],150:[2,49],151:[2,49],152:[2,49],153:[2,49],154:[2,49],155:[2,49],156:[2,49],157:[2,49],158:[2,49],159:[2,49],160:[2,49],161:[2,49],162:[2,49],165:[2,49],166:[2,49],167:[2,49],169:[2,49],170:[2,49],185:[2,49],188:[2,49],194:[2,49],196:[2,49],198:[2,49],200:[2,49]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,
-43],54:24,55:313,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,
-77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,
-174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:314,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,
-65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],
-151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:315,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],
-83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,
-100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21]},{6:[2,58],8:[2,58],10:[2,58],49:[2,58],50:[2,58],51:[2,58],53:[2,58],56:[2,58],57:[2,58],58:[2,58],59:[2,58],60:[2,58],61:[2,58],62:[2,58],63:[2,58],64:[2,58],65:[2,
-58],66:[2,58],67:[2,58],68:[2,58],69:[2,58],70:[2,58],71:[2,58],72:[2,58],73:[2,58],74:[2,58],75:[2,58],76:[2,58],77:[2,58],78:[2,58],79:[2,58],81:[2,58],82:[2,58],83:[2,58],84:[2,58],85:[2,58],86:[2,58],87:[2,58],88:[2,58],89:[2,58],90:[2,58],91:[2,58],92:[2,58],93:[2,58],94:[2,58],95:[2,58],96:[2,58],97:[2,58],98:[2,58],99:[2,58],100:[2,58],101:[2,58],102:[2,58],103:[2,58],104:[2,58],105:[2,58],106:[2,58],107:[2,58],108:[2,58],109:[2,58],110:[2,58],111:[2,58],112:[2,58],113:[2,58],114:[2,58],115:[2,
-58],116:[2,58],117:[2,58],118:[2,58],119:[2,58],120:[2,58],121:[2,58],122:[2,58],123:[2,58],124:[2,58],125:[2,58],126:[2,58],127:[2,58],128:[2,58],129:[2,58],130:[2,58],131:[2,58],132:[2,58],134:[2,58],135:[2,58],137:[2,58],138:[2,58],140:[2,58],141:[2,58],142:[2,58],143:[2,58],144:[2,58],145:[2,58],146:[2,58],147:[2,58],148:[2,58],149:[2,58],150:[2,58],151:[2,58],152:[2,58],153:[2,58],154:[2,58],155:[2,58],156:[2,58],157:[2,58],158:[2,58],159:[2,58],160:[2,58],161:[2,58],162:[2,58],165:[2,58],166:[2,
-58],167:[2,58],169:[2,58],170:[2,58],185:[2,58],188:[2,58],194:[2,58],196:[2,58],198:[2,58],200:[2,58]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:316,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],
-94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,
-108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:317,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],
-81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,
-98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:318,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,
-36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],
-117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21]},{50:[1,319],51:[1,
-320]},{7:150,8:[1,129],15:321},{6:[1,322]},{6:[2,86],8:[2,86],10:[2,86],49:[2,86],50:[2,86],51:[2,86],53:[2,86],56:[2,86],57:[2,86],58:[2,86],59:[2,86],60:[2,86],61:[2,86],62:[2,86],63:[2,86],64:[2,86],65:[2,86],66:[2,86],67:[2,86],68:[2,86],69:[2,86],70:[2,86],71:[2,86],72:[2,86],73:[2,86],74:[2,86],75:[2,86],76:[2,86],77:[2,86],78:[2,86],79:[2,86],81:[2,86],82:[2,86],83:[2,86],84:[2,86],85:[2,86],86:[2,86],87:[2,86],88:[2,86],89:[2,86],90:[2,86],91:[2,86],92:[2,86],93:[2,86],94:[2,86],95:[2,86],
-96:[2,86],97:[2,86],98:[2,86],99:[2,86],100:[2,86],101:[2,86],102:[2,86],103:[2,86],104:[2,86],105:[2,86],106:[2,86],107:[2,86],108:[2,86],109:[2,86],110:[2,86],111:[2,86],112:[2,86],113:[2,86],114:[2,86],115:[2,86],116:[2,86],117:[2,86],118:[2,86],119:[2,86],120:[2,86],121:[2,86],122:[2,86],123:[2,86],124:[2,86],125:[2,86],126:[2,86],127:[2,86],128:[2,86],129:[2,86],130:[2,86],131:[2,86],132:[2,86],134:[2,86],135:[2,86],137:[2,86],138:[2,86],140:[2,86],141:[2,86],142:[2,86],143:[2,86],144:[2,86],
-145:[2,86],146:[2,86],147:[2,86],148:[2,86],149:[2,86],150:[2,86],151:[2,86],152:[2,86],153:[2,86],154:[2,86],155:[2,86],156:[2,86],157:[2,86],158:[2,86],159:[2,86],160:[2,86],161:[2,86],162:[2,86],165:[2,86],166:[2,86],167:[2,86],169:[2,86],170:[2,86],185:[2,86],188:[2,86],194:[2,86],196:[2,86],198:[2,86],200:[2,86]},{6:[2,87],8:[2,87],10:[2,87],49:[2,87],50:[2,87],51:[2,87],53:[2,87],56:[2,87],57:[2,87],58:[2,87],59:[2,87],60:[2,87],61:[2,87],62:[2,87],63:[2,87],64:[2,87],65:[2,87],66:[2,87],67:[2,
-87],68:[2,87],69:[2,87],70:[2,87],71:[2,87],72:[2,87],73:[2,87],74:[2,87],75:[2,87],76:[2,87],77:[2,87],78:[2,87],79:[2,87],81:[2,87],82:[2,87],83:[2,87],84:[2,87],85:[2,87],86:[2,87],87:[2,87],88:[2,87],89:[2,87],90:[2,87],91:[2,87],92:[2,87],93:[2,87],94:[2,87],95:[2,87],96:[2,87],97:[2,87],98:[2,87],99:[2,87],100:[2,87],101:[2,87],102:[2,87],103:[2,87],104:[2,87],105:[2,87],106:[2,87],107:[2,87],108:[2,87],109:[2,87],110:[2,87],111:[2,87],112:[2,87],113:[2,87],114:[2,87],115:[2,87],116:[2,87],
-117:[2,87],118:[2,87],119:[2,87],120:[2,87],121:[2,87],122:[2,87],123:[2,87],124:[2,87],125:[2,87],126:[2,87],127:[2,87],128:[2,87],129:[2,87],130:[2,87],131:[2,87],132:[2,87],134:[2,87],135:[2,87],137:[2,87],138:[2,87],140:[2,87],141:[2,87],142:[2,87],143:[2,87],144:[2,87],145:[2,87],146:[2,87],147:[2,87],148:[2,87],149:[2,87],150:[2,87],151:[2,87],152:[2,87],153:[2,87],154:[2,87],155:[2,87],156:[2,87],157:[2,87],158:[2,87],159:[2,87],160:[2,87],161:[2,87],162:[2,87],165:[2,87],166:[2,87],167:[2,
-87],169:[2,87],170:[2,87],185:[2,87],188:[2,87],194:[2,87],196:[2,87],198:[2,87],200:[2,87]},{6:[1,323]},{6:[2,90],8:[2,90],10:[2,90],49:[2,90],50:[2,90],51:[2,90],53:[2,90],56:[2,90],57:[2,90],58:[2,90],59:[2,90],60:[2,90],61:[2,90],62:[2,90],63:[2,90],64:[2,90],65:[2,90],66:[2,90],67:[2,90],68:[2,90],69:[2,90],70:[2,90],71:[2,90],72:[2,90],73:[2,90],74:[2,90],75:[2,90],76:[2,90],77:[2,90],78:[2,90],79:[2,90],81:[2,90],82:[2,90],83:[2,90],84:[2,90],85:[2,90],86:[2,90],87:[2,90],88:[2,90],89:[2,90],
-90:[2,90],91:[2,90],92:[2,90],93:[2,90],94:[2,90],95:[2,90],96:[2,90],97:[2,90],98:[2,90],99:[2,90],100:[2,90],101:[2,90],102:[2,90],103:[2,90],104:[2,90],105:[2,90],106:[2,90],107:[2,90],108:[2,90],109:[2,90],110:[2,90],111:[2,90],112:[2,90],113:[2,90],114:[2,90],115:[2,90],116:[2,90],117:[2,90],118:[2,90],119:[2,90],120:[2,90],121:[2,90],122:[2,90],123:[2,90],124:[2,90],125:[2,90],126:[2,90],127:[2,90],128:[2,90],129:[2,90],130:[2,90],131:[2,90],132:[2,90],134:[2,90],135:[2,90],137:[2,90],138:[2,
-90],140:[2,90],141:[2,90],142:[2,90],143:[2,90],144:[2,90],145:[2,90],146:[2,90],147:[2,90],148:[2,90],149:[2,90],150:[2,90],151:[2,90],152:[2,90],153:[2,90],154:[2,90],155:[2,90],156:[2,90],157:[2,90],158:[2,90],159:[2,90],160:[2,90],161:[2,90],162:[2,90],165:[2,90],166:[2,90],167:[2,90],169:[2,90],170:[2,90],185:[2,90],188:[2,90],194:[2,90],196:[2,90],198:[2,90],200:[2,90]},{6:[2,91],8:[2,91],10:[2,91],49:[2,91],50:[2,91],51:[2,91],53:[2,91],56:[2,91],57:[2,91],58:[2,91],59:[2,91],60:[2,91],61:[2,
-91],62:[2,91],63:[2,91],64:[2,91],65:[2,91],66:[2,91],67:[2,91],68:[2,91],69:[2,91],70:[2,91],71:[2,91],72:[2,91],73:[2,91],74:[2,91],75:[2,91],76:[2,91],77:[2,91],78:[2,91],79:[2,91],81:[2,91],82:[2,91],83:[2,91],84:[2,91],85:[2,91],86:[2,91],87:[2,91],88:[2,91],89:[2,91],90:[2,91],91:[2,91],92:[2,91],93:[2,91],94:[2,91],95:[2,91],96:[2,91],97:[2,91],98:[2,91],99:[2,91],100:[2,91],101:[2,91],102:[2,91],103:[2,91],104:[2,91],105:[2,91],106:[2,91],107:[2,91],108:[2,91],109:[2,91],110:[2,91],111:[2,
-91],112:[2,91],113:[2,91],114:[2,91],115:[2,91],116:[2,91],117:[2,91],118:[2,91],119:[2,91],120:[2,91],121:[2,91],122:[2,91],123:[2,91],124:[2,91],125:[2,91],126:[2,91],127:[2,91],128:[2,91],129:[2,91],130:[2,91],131:[2,91],132:[2,91],134:[2,91],135:[2,91],137:[2,91],138:[2,91],140:[2,91],141:[2,91],142:[2,91],143:[2,91],144:[2,91],145:[2,91],146:[2,91],147:[2,91],148:[2,91],149:[2,91],150:[2,91],151:[2,91],152:[2,91],153:[2,91],154:[2,91],155:[2,91],156:[2,91],157:[2,91],158:[2,91],159:[2,91],160:[2,
-91],161:[2,91],162:[2,91],165:[2,91],166:[2,91],167:[2,91],169:[2,91],170:[2,91],185:[2,91],188:[2,91],194:[2,91],196:[2,91],198:[2,91],200:[2,91]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:324,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],
-90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],
-141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{6:[1,325]},{6:[2,99],8:[2,99],10:[2,99],49:[2,99],50:[2,99],51:[2,99],53:[2,99],56:[2,99],57:[2,99],58:[2,99],59:[2,99],60:[2,99],61:[2,99],62:[2,99],63:[2,99],64:[2,99],65:[2,99],66:[2,99],67:[2,99],68:[2,99],69:[2,99],70:[2,99],71:[2,99],72:[2,99],73:[2,99],74:[2,99],75:[2,99],76:[2,99],77:[2,99],78:[2,99],79:[2,99],81:[2,99],82:[2,99],83:[2,99],84:[2,
-99],85:[2,99],86:[2,99],87:[2,99],88:[2,99],89:[2,99],90:[2,99],91:[2,99],92:[2,99],93:[2,99],94:[2,99],95:[2,99],96:[2,99],97:[2,99],98:[2,99],99:[2,99],100:[2,99],101:[2,99],102:[2,99],103:[2,99],104:[2,99],105:[2,99],106:[2,99],107:[2,99],108:[2,99],109:[2,99],110:[2,99],111:[2,99],112:[2,99],113:[2,99],114:[2,99],115:[2,99],116:[2,99],117:[2,99],118:[2,99],119:[2,99],120:[2,99],121:[2,99],122:[2,99],123:[2,99],124:[2,99],125:[2,99],126:[2,99],127:[2,99],128:[2,99],129:[2,99],130:[2,99],131:[2,
-99],132:[2,99],134:[2,99],135:[2,99],137:[2,99],138:[2,99],140:[2,99],141:[2,99],142:[2,99],143:[2,99],144:[2,99],145:[2,99],146:[2,99],147:[2,99],148:[2,99],149:[2,99],150:[2,99],151:[2,99],152:[2,99],153:[2,99],154:[2,99],155:[2,99],156:[2,99],157:[2,99],158:[2,99],159:[2,99],160:[2,99],161:[2,99],162:[2,99],165:[2,99],166:[2,99],167:[2,99],169:[2,99],170:[2,99],185:[2,99],188:[2,99],194:[2,99],196:[2,99],198:[2,99],200:[2,99]},{6:[2,100],8:[2,100],10:[2,100],49:[2,100],50:[2,100],51:[2,100],53:[2,
-100],56:[2,100],57:[2,100],58:[2,100],59:[2,100],60:[2,100],61:[2,100],62:[2,100],63:[2,100],64:[2,100],65:[2,100],66:[2,100],67:[2,100],68:[2,100],69:[2,100],70:[2,100],71:[2,100],72:[2,100],73:[2,100],74:[2,100],75:[2,100],76:[2,100],77:[2,100],78:[2,100],79:[2,100],81:[2,100],82:[2,100],83:[2,100],84:[2,100],85:[2,100],86:[2,100],87:[2,100],88:[2,100],89:[2,100],90:[2,100],91:[2,100],92:[2,100],93:[2,100],94:[2,100],95:[2,100],96:[2,100],97:[2,100],98:[2,100],99:[2,100],100:[2,100],101:[2,100],
-102:[2,100],103:[2,100],104:[2,100],105:[2,100],106:[2,100],107:[2,100],108:[2,100],109:[2,100],110:[2,100],111:[2,100],112:[2,100],113:[2,100],114:[2,100],115:[2,100],116:[2,100],117:[2,100],118:[2,100],119:[2,100],120:[2,100],121:[2,100],122:[2,100],123:[2,100],124:[2,100],125:[2,100],126:[2,100],127:[2,100],128:[2,100],129:[2,100],130:[2,100],131:[2,100],132:[2,100],134:[2,100],135:[2,100],137:[2,100],138:[2,100],140:[2,100],141:[2,100],142:[2,100],143:[2,100],144:[2,100],145:[2,100],146:[2,100],
-147:[2,100],148:[2,100],149:[2,100],150:[2,100],151:[2,100],152:[2,100],153:[2,100],154:[2,100],155:[2,100],156:[2,100],157:[2,100],158:[2,100],159:[2,100],160:[2,100],161:[2,100],162:[2,100],165:[2,100],166:[2,100],167:[2,100],169:[2,100],170:[2,100],185:[2,100],188:[2,100],194:[2,100],196:[2,100],198:[2,100],200:[2,100]},{6:[2,101],8:[2,101],10:[2,101],49:[2,101],50:[2,101],51:[2,101],53:[2,101],56:[2,101],57:[2,101],58:[2,101],59:[2,101],60:[2,101],61:[2,101],62:[2,101],63:[2,101],64:[2,101],65:[2,
-101],66:[2,101],67:[2,101],68:[2,101],69:[2,101],70:[2,101],71:[2,101],72:[2,101],73:[2,101],74:[2,101],75:[2,101],76:[2,101],77:[2,101],78:[2,101],79:[2,101],81:[2,101],82:[2,101],83:[2,101],84:[2,101],85:[2,101],86:[2,101],87:[2,101],88:[2,101],89:[2,101],90:[2,101],91:[2,101],92:[2,101],93:[2,101],94:[2,101],95:[2,101],96:[2,101],97:[2,101],98:[2,101],99:[2,101],100:[2,101],101:[2,101],102:[2,101],103:[2,101],104:[2,101],105:[2,101],106:[2,101],107:[2,101],108:[2,101],109:[2,101],110:[2,101],111:[2,
-101],112:[2,101],113:[2,101],114:[2,101],115:[2,101],116:[2,101],117:[2,101],118:[2,101],119:[2,101],120:[2,101],121:[2,101],122:[2,101],123:[2,101],124:[2,101],125:[2,101],126:[2,101],127:[2,101],128:[2,101],129:[2,101],130:[2,101],131:[2,101],132:[2,101],134:[2,101],135:[2,101],137:[2,101],138:[2,101],140:[2,101],141:[2,101],142:[2,101],143:[2,101],144:[2,101],145:[2,101],146:[2,101],147:[2,101],148:[2,101],149:[2,101],150:[2,101],151:[2,101],152:[2,101],153:[2,101],154:[2,101],155:[2,101],156:[2,
-101],157:[2,101],158:[2,101],159:[2,101],160:[2,101],161:[2,101],162:[2,101],165:[2,101],166:[2,101],167:[2,101],169:[2,101],170:[2,101],185:[2,101],188:[2,101],194:[2,101],196:[2,101],198:[2,101],200:[2,101]},{7:326,8:[1,129]},{4:[1,270],8:[1,26],11:327,48:35,49:[1,119],50:[1,47],51:[1,43],54:328,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,
-50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],
-128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{6:[2,121],8:[2,121],10:[2,121],49:[2,121],50:[2,121],51:[2,121],53:[2,121],56:[2,121],57:[2,121],58:[2,121],59:[2,121],60:[2,121],61:[2,121],62:[2,121],63:[2,121],64:[2,121],65:[2,121],66:[2,121],67:[2,121],68:[2,121],69:[2,121],70:[2,121],71:[2,121],72:[2,121],
-73:[2,121],74:[2,121],75:[2,121],76:[2,121],77:[2,121],78:[2,121],79:[2,121],81:[2,121],82:[2,121],83:[2,121],84:[2,121],85:[2,121],86:[2,121],87:[2,121],88:[2,121],89:[2,121],90:[2,121],91:[2,121],92:[2,121],93:[2,121],94:[2,121],95:[2,121],96:[2,121],97:[2,121],98:[2,121],99:[2,121],100:[2,121],101:[2,121],102:[2,121],103:[2,121],104:[2,121],105:[2,121],106:[2,121],107:[2,121],108:[2,121],109:[2,121],110:[2,121],111:[2,121],112:[2,121],113:[2,121],114:[2,121],115:[2,121],116:[2,121],117:[2,121],
-118:[2,121],119:[2,121],120:[2,121],121:[2,121],122:[2,121],123:[2,121],124:[2,121],125:[2,121],126:[2,121],127:[2,121],128:[2,121],129:[2,121],130:[2,121],131:[2,121],132:[2,121],134:[2,121],135:[2,121],137:[2,121],138:[2,121],140:[2,121],141:[2,121],142:[2,121],143:[2,121],144:[2,121],145:[2,121],146:[2,121],147:[2,121],148:[2,121],149:[2,121],150:[2,121],151:[2,121],152:[2,121],153:[2,121],154:[2,121],155:[2,121],156:[2,121],157:[2,121],158:[2,121],159:[2,121],160:[2,121],161:[2,121],162:[2,121],
-165:[2,121],166:[2,121],167:[2,121],169:[2,121],170:[2,121],185:[2,121],188:[2,121],194:[2,121],196:[2,121],198:[2,121],200:[2,121]},{5:[1,329]},{10:[1,330]},{6:[2,132],8:[2,132],10:[2,132],49:[2,132],50:[2,132],51:[2,132],53:[2,132],56:[2,132],57:[2,132],58:[2,132],59:[2,132],60:[2,132],61:[2,132],62:[2,132],63:[2,132],64:[2,132],65:[2,132],66:[2,132],67:[2,132],68:[2,132],69:[2,132],70:[2,132],71:[2,132],72:[2,132],73:[2,132],74:[2,132],75:[2,132],76:[2,132],77:[2,132],78:[2,132],79:[2,132],81:[2,
-132],82:[2,132],83:[2,132],84:[2,132],85:[2,132],86:[2,132],87:[2,132],88:[2,132],89:[2,132],90:[2,132],91:[2,132],92:[2,132],93:[2,132],94:[2,132],95:[2,132],96:[2,132],97:[2,132],98:[2,132],99:[2,132],100:[2,132],101:[2,132],102:[2,132],103:[2,132],104:[2,132],105:[2,132],106:[2,132],107:[2,132],108:[2,132],109:[2,132],110:[2,132],111:[2,132],112:[2,132],113:[2,132],114:[2,132],115:[2,132],116:[2,132],117:[2,132],118:[2,132],119:[2,132],120:[2,132],121:[2,132],122:[2,132],123:[2,132],124:[2,132],
-125:[2,132],126:[2,132],127:[2,132],128:[2,132],129:[2,132],130:[2,132],131:[2,132],132:[2,132],134:[2,132],135:[2,132],137:[2,132],138:[2,132],140:[2,132],141:[2,132],142:[2,132],143:[2,132],144:[2,132],145:[2,132],146:[2,132],147:[2,132],148:[2,132],149:[2,132],150:[2,132],151:[2,132],152:[2,132],153:[2,132],154:[2,132],155:[2,132],156:[2,132],157:[2,132],158:[2,132],159:[2,132],160:[2,132],161:[2,132],162:[2,132],165:[2,132],166:[2,132],167:[2,132],169:[2,132],170:[2,132],185:[2,132],188:[2,132],
-194:[2,132],196:[2,132],198:[2,132],200:[2,132]},{6:[2,133],8:[2,133],10:[2,133],49:[2,133],50:[2,133],51:[2,133],53:[2,133],56:[2,133],57:[2,133],58:[2,133],59:[2,133],60:[2,133],61:[2,133],62:[2,133],63:[2,133],64:[2,133],65:[2,133],66:[2,133],67:[2,133],68:[2,133],69:[2,133],70:[2,133],71:[2,133],72:[2,133],73:[2,133],74:[2,133],75:[2,133],76:[2,133],77:[2,133],78:[2,133],79:[2,133],81:[2,133],82:[2,133],83:[2,133],84:[2,133],85:[2,133],86:[2,133],87:[2,133],88:[2,133],89:[2,133],90:[2,133],91:[2,
-133],92:[2,133],93:[2,133],94:[2,133],95:[2,133],96:[2,133],97:[2,133],98:[2,133],99:[2,133],100:[2,133],101:[2,133],102:[2,133],103:[2,133],104:[2,133],105:[2,133],106:[2,133],107:[2,133],108:[2,133],109:[2,133],110:[2,133],111:[2,133],112:[2,133],113:[2,133],114:[2,133],115:[2,133],116:[2,133],117:[2,133],118:[2,133],119:[2,133],120:[2,133],121:[2,133],122:[2,133],123:[2,133],124:[2,133],125:[2,133],126:[2,133],127:[2,133],128:[2,133],129:[2,133],130:[2,133],131:[2,133],132:[2,133],134:[2,133],
-135:[2,133],137:[2,133],138:[2,133],140:[2,133],141:[2,133],142:[2,133],143:[2,133],144:[2,133],145:[2,133],146:[2,133],147:[2,133],148:[2,133],149:[2,133],150:[2,133],151:[2,133],152:[2,133],153:[2,133],154:[2,133],155:[2,133],156:[2,133],157:[2,133],158:[2,133],159:[2,133],160:[2,133],161:[2,133],162:[2,133],165:[2,133],166:[2,133],167:[2,133],169:[2,133],170:[2,133],185:[2,133],188:[2,133],194:[2,133],196:[2,133],198:[2,133],200:[2,133]},{6:[2,134],8:[2,134],10:[2,134],49:[2,134],50:[2,134],51:[2,
-134],53:[2,134],56:[2,134],57:[2,134],58:[2,134],59:[2,134],60:[2,134],61:[2,134],62:[2,134],63:[2,134],64:[2,134],65:[2,134],66:[2,134],67:[2,134],68:[2,134],69:[2,134],70:[2,134],71:[2,134],72:[2,134],73:[2,134],74:[2,134],75:[2,134],76:[2,134],77:[2,134],78:[2,134],79:[2,134],81:[2,134],82:[2,134],83:[2,134],84:[2,134],85:[2,134],86:[2,134],87:[2,134],88:[2,134],89:[2,134],90:[2,134],91:[2,134],92:[2,134],93:[2,134],94:[2,134],95:[2,134],96:[2,134],97:[2,134],98:[2,134],99:[2,134],100:[2,134],
-101:[2,134],102:[2,134],103:[2,134],104:[2,134],105:[2,134],106:[2,134],107:[2,134],108:[2,134],109:[2,134],110:[2,134],111:[2,134],112:[2,134],113:[2,134],114:[2,134],115:[2,134],116:[2,134],117:[2,134],118:[2,134],119:[2,134],120:[2,134],121:[2,134],122:[2,134],123:[2,134],124:[2,134],125:[2,134],126:[2,134],127:[2,134],128:[2,134],129:[2,134],130:[2,134],131:[2,134],132:[2,134],134:[2,134],135:[2,134],137:[2,134],138:[2,134],140:[2,134],141:[2,134],142:[2,134],143:[2,134],144:[2,134],145:[2,134],
-146:[2,134],147:[2,134],148:[2,134],149:[2,134],150:[2,134],151:[2,134],152:[2,134],153:[2,134],154:[2,134],155:[2,134],156:[2,134],157:[2,134],158:[2,134],159:[2,134],160:[2,134],161:[2,134],162:[2,134],165:[2,134],166:[2,134],167:[2,134],169:[2,134],170:[2,134],185:[2,134],188:[2,134],194:[2,134],196:[2,134],198:[2,134],200:[2,134]},{6:[2,135],8:[2,135],10:[2,135],49:[2,135],50:[2,135],51:[2,135],53:[2,135],56:[2,135],57:[2,135],58:[2,135],59:[2,135],60:[2,135],61:[2,135],62:[2,135],63:[2,135],
-64:[2,135],65:[2,135],66:[2,135],67:[2,135],68:[2,135],69:[2,135],70:[2,135],71:[2,135],72:[2,135],73:[2,135],74:[2,135],75:[2,135],76:[2,135],77:[2,135],78:[2,135],79:[2,135],81:[2,135],82:[2,135],83:[2,135],84:[2,135],85:[2,135],86:[2,135],87:[2,135],88:[2,135],89:[2,135],90:[2,135],91:[2,135],92:[2,135],93:[2,135],94:[2,135],95:[2,135],96:[2,135],97:[2,135],98:[2,135],99:[2,135],100:[2,135],101:[2,135],102:[2,135],103:[2,135],104:[2,135],105:[2,135],106:[2,135],107:[2,135],108:[2,135],109:[2,135],
-110:[2,135],111:[2,135],112:[2,135],113:[2,135],114:[2,135],115:[2,135],116:[2,135],117:[2,135],118:[2,135],119:[2,135],120:[2,135],121:[2,135],122:[2,135],123:[2,135],124:[2,135],125:[2,135],126:[2,135],127:[2,135],128:[2,135],129:[2,135],130:[2,135],131:[2,135],132:[2,135],134:[2,135],135:[2,135],137:[2,135],138:[2,135],140:[2,135],141:[2,135],142:[2,135],143:[2,135],144:[2,135],145:[2,135],146:[2,135],147:[2,135],148:[2,135],149:[2,135],150:[2,135],151:[2,135],152:[2,135],153:[2,135],154:[2,135],
-155:[2,135],156:[2,135],157:[2,135],158:[2,135],159:[2,135],160:[2,135],161:[2,135],162:[2,135],165:[2,135],166:[2,135],167:[2,135],169:[2,135],170:[2,135],185:[2,135],188:[2,135],194:[2,135],196:[2,135],198:[2,135],200:[2,135]},{6:[2,136],8:[2,136],10:[2,136],49:[2,136],50:[2,136],51:[2,136],53:[2,136],56:[2,136],57:[2,136],58:[2,136],59:[2,136],60:[2,136],61:[2,136],62:[2,136],63:[2,136],64:[2,136],65:[2,136],66:[2,136],67:[2,136],68:[2,136],69:[2,136],70:[2,136],71:[2,136],72:[2,136],73:[2,136],
-74:[2,136],75:[2,136],76:[2,136],77:[2,136],78:[2,136],79:[2,136],81:[2,136],82:[2,136],83:[2,136],84:[2,136],85:[2,136],86:[2,136],87:[2,136],88:[2,136],89:[2,136],90:[2,136],91:[2,136],92:[2,136],93:[2,136],94:[2,136],95:[2,136],96:[2,136],97:[2,136],98:[2,136],99:[2,136],100:[2,136],101:[2,136],102:[2,136],103:[2,136],104:[2,136],105:[2,136],106:[2,136],107:[2,136],108:[2,136],109:[2,136],110:[2,136],111:[2,136],112:[2,136],113:[2,136],114:[2,136],115:[2,136],116:[2,136],117:[2,136],118:[2,136],
-119:[2,136],120:[2,136],121:[2,136],122:[2,136],123:[2,136],124:[2,136],125:[2,136],126:[2,136],127:[2,136],128:[2,136],129:[2,136],130:[2,136],131:[2,136],132:[2,136],134:[2,136],135:[2,136],137:[2,136],138:[2,136],140:[2,136],141:[2,136],142:[2,136],143:[2,136],144:[2,136],145:[2,136],146:[2,136],147:[2,136],148:[2,136],149:[2,136],150:[2,136],151:[2,136],152:[2,136],153:[2,136],154:[2,136],155:[2,136],156:[2,136],157:[2,136],158:[2,136],159:[2,136],160:[2,136],161:[2,136],162:[2,136],165:[2,136],
-166:[2,136],167:[2,136],169:[2,136],170:[2,136],185:[2,136],188:[2,136],194:[2,136],196:[2,136],198:[2,136],200:[2,136]},{8:[2,157],49:[2,157],50:[2,157],51:[2,157],56:[2,157],57:[2,157],58:[2,157],59:[2,157],60:[2,157],61:[2,157],62:[2,157],63:[2,157],67:[2,157],68:[2,157],69:[2,157],70:[2,157],71:[2,157],72:[2,157],73:[2,157],74:[2,157],75:[2,157],76:[2,157],77:[2,157],78:[2,157],79:[2,157],81:[2,157],82:[2,157],83:[2,157],84:[2,157],85:[2,157],86:[2,157],87:[2,157],88:[2,157],89:[2,157],90:[2,
-157],91:[2,157],92:[2,157],93:[2,157],94:[2,157],95:[2,157],96:[2,157],97:[2,157],98:[2,157],99:[2,157],100:[2,157],101:[2,157],102:[2,157],103:[2,157],104:[2,157],105:[2,157],106:[2,157],107:[2,157],108:[2,157],109:[2,157],110:[2,157],111:[2,157],112:[2,157],113:[2,157],114:[2,157],115:[2,157],116:[2,157],117:[2,157],118:[2,157],119:[2,157],120:[2,157],121:[2,157],122:[2,157],123:[2,157],124:[2,157],125:[2,157],126:[2,157],127:[2,157],128:[2,157],129:[2,157],130:[2,157],131:[2,157],132:[2,157],134:[2,
-157],135:[2,157],137:[2,157],138:[2,157],141:[2,157],143:[2,157],145:[2,157],147:[2,157],149:[2,157],151:[2,157],153:[2,157],155:[2,157],157:[2,157],159:[2,157],161:[2,157],162:[2,157]},{10:[1,331],165:[1,238],166:[1,239],173:300},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:332,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,
-51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],
-129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{6:[2,141],8:[2,141],10:[2,141],49:[2,141],50:[2,141],51:[2,141],53:[2,141],56:[2,141],57:[2,141],58:[2,141],59:[2,141],60:[2,141],61:[2,141],62:[2,141],63:[2,141],64:[2,141],65:[2,141],66:[2,141],67:[2,141],68:[2,141],69:[2,141],70:[2,141],71:[2,141],72:[2,141],73:[2,141],
-74:[2,141],75:[2,141],76:[2,141],77:[2,141],78:[2,141],79:[2,141],81:[2,141],82:[2,141],83:[2,141],84:[2,141],85:[2,141],86:[2,141],87:[2,141],88:[2,141],89:[2,141],90:[2,141],91:[2,141],92:[2,141],93:[2,141],94:[2,141],95:[2,141],96:[2,141],97:[2,141],98:[2,141],99:[2,141],100:[2,141],101:[2,141],102:[2,141],103:[2,141],104:[2,141],105:[2,141],106:[2,141],107:[2,141],108:[2,141],109:[2,141],110:[2,141],111:[2,141],112:[2,141],113:[2,141],114:[2,141],115:[2,141],116:[2,141],117:[2,141],118:[2,141],
-119:[2,141],120:[2,141],121:[2,141],122:[2,141],123:[2,141],124:[2,141],125:[2,141],126:[2,141],127:[2,141],128:[2,141],129:[2,141],130:[2,141],131:[2,141],132:[2,141],134:[2,141],135:[2,141],137:[2,141],138:[2,141],140:[2,141],141:[2,141],142:[2,141],143:[2,141],144:[2,141],145:[2,141],146:[2,141],147:[2,141],148:[2,141],149:[2,141],150:[2,141],151:[2,141],152:[2,141],153:[2,141],154:[2,141],155:[2,141],156:[2,141],157:[2,141],158:[2,141],159:[2,141],160:[2,141],161:[2,141],162:[2,141],165:[2,141],
-166:[2,141],167:[2,141],169:[2,141],170:[2,141],185:[2,141],188:[2,141],194:[2,141],196:[2,141],198:[2,141],200:[2,141]},{8:[1,26],10:[2,193],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:213,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],
-91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],140:[2,193],
-141:[1,105],142:[2,193],143:[1,106],144:[2,193],145:[1,107],146:[2,193],147:[1,108],148:[2,193],149:[1,109],150:[2,193],151:[1,110],152:[2,193],153:[1,111],154:[2,193],155:[1,112],156:[2,193],157:[1,113],158:[2,193],159:[1,114],160:[2,193],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21],182:211,183:[1,212],184:210,185:[2,193],186:333,187:[1,209],188:[2,193]},{20:336,21:[1,338],22:337,23:[1,339],
-44:335,47:334},{8:[1,26],10:[2,193],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:213,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,
-71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],140:[2,193],141:[1,105],142:[2,193],143:[1,106],144:[2,193],145:[1,107],146:[2,193],147:[1,108],148:[2,193],149:[1,109],
-150:[2,193],151:[1,110],152:[2,193],153:[1,111],154:[2,193],155:[1,112],156:[2,193],157:[1,113],158:[2,193],159:[1,114],160:[2,193],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21],182:340,183:[1,212],185:[2,193],188:[2,193]},{20:343,21:[1,338],22:344,23:[1,339],24:345,25:[1,347],26:346,27:[1,348],42:342,43:341},{6:[2,142],8:[2,142],10:[2,142],49:[2,142],50:[2,142],51:[2,142],53:[2,142],56:[2,142],
-57:[2,142],58:[2,142],59:[2,142],60:[2,142],61:[2,142],62:[2,142],63:[2,142],64:[2,142],65:[2,142],66:[2,142],67:[2,142],68:[2,142],69:[2,142],70:[2,142],71:[2,142],72:[2,142],73:[2,142],74:[2,142],75:[2,142],76:[2,142],77:[2,142],78:[2,142],79:[2,142],81:[2,142],82:[2,142],83:[2,142],84:[2,142],85:[2,142],86:[2,142],87:[2,142],88:[2,142],89:[2,142],90:[2,142],91:[2,142],92:[2,142],93:[2,142],94:[2,142],95:[2,142],96:[2,142],97:[2,142],98:[2,142],99:[2,142],100:[2,142],101:[2,142],102:[2,142],103:[2,
-142],104:[2,142],105:[2,142],106:[2,142],107:[2,142],108:[2,142],109:[2,142],110:[2,142],111:[2,142],112:[2,142],113:[2,142],114:[2,142],115:[2,142],116:[2,142],117:[2,142],118:[2,142],119:[2,142],120:[2,142],121:[2,142],122:[2,142],123:[2,142],124:[2,142],125:[2,142],126:[2,142],127:[2,142],128:[2,142],129:[2,142],130:[2,142],131:[2,142],132:[2,142],134:[2,142],135:[2,142],137:[2,142],138:[2,142],140:[2,142],141:[2,142],142:[2,142],143:[2,142],144:[2,142],145:[2,142],146:[2,142],147:[2,142],148:[2,
-142],149:[2,142],150:[2,142],151:[2,142],152:[2,142],153:[2,142],154:[2,142],155:[2,142],156:[2,142],157:[2,142],158:[2,142],159:[2,142],160:[2,142],161:[2,142],162:[2,142],165:[2,142],166:[2,142],167:[2,142],169:[2,142],170:[2,142],185:[2,142],188:[2,142],194:[2,142],196:[2,142],198:[2,142],200:[2,142]},{6:[2,143],8:[2,143],10:[2,143],49:[2,143],50:[2,143],51:[2,143],53:[2,143],56:[2,143],57:[2,143],58:[2,143],59:[2,143],60:[2,143],61:[2,143],62:[2,143],63:[2,143],64:[2,143],65:[2,143],66:[2,143],
-67:[2,143],68:[2,143],69:[2,143],70:[2,143],71:[2,143],72:[2,143],73:[2,143],74:[2,143],75:[2,143],76:[2,143],77:[2,143],78:[2,143],79:[2,143],81:[2,143],82:[2,143],83:[2,143],84:[2,143],85:[2,143],86:[2,143],87:[2,143],88:[2,143],89:[2,143],90:[2,143],91:[2,143],92:[2,143],93:[2,143],94:[2,143],95:[2,143],96:[2,143],97:[2,143],98:[2,143],99:[2,143],100:[2,143],101:[2,143],102:[2,143],103:[2,143],104:[2,143],105:[2,143],106:[2,143],107:[2,143],108:[2,143],109:[2,143],110:[2,143],111:[2,143],112:[2,
-143],113:[2,143],114:[2,143],115:[2,143],116:[2,143],117:[2,143],118:[2,143],119:[2,143],120:[2,143],121:[2,143],122:[2,143],123:[2,143],124:[2,143],125:[2,143],126:[2,143],127:[2,143],128:[2,143],129:[2,143],130:[2,143],131:[2,143],132:[2,143],134:[2,143],135:[2,143],137:[2,143],138:[2,143],140:[2,143],141:[2,143],142:[2,143],143:[2,143],144:[2,143],145:[2,143],146:[2,143],147:[2,143],148:[2,143],149:[2,143],150:[2,143],151:[2,143],152:[2,143],153:[2,143],154:[2,143],155:[2,143],156:[2,143],157:[2,
-143],158:[2,143],159:[2,143],160:[2,143],161:[2,143],162:[2,143],165:[2,143],166:[2,143],167:[2,143],169:[2,143],170:[2,143],185:[2,143],188:[2,143],194:[2,143],196:[2,143],198:[2,143],200:[2,143]},{6:[2,144],8:[2,144],10:[2,144],49:[2,144],50:[2,144],51:[2,144],53:[2,144],56:[2,144],57:[2,144],58:[2,144],59:[2,144],60:[2,144],61:[2,144],62:[2,144],63:[2,144],64:[2,144],65:[2,144],66:[2,144],67:[2,144],68:[2,144],69:[2,144],70:[2,144],71:[2,144],72:[2,144],73:[2,144],74:[2,144],75:[2,144],76:[2,144],
-77:[2,144],78:[2,144],79:[2,144],81:[2,144],82:[2,144],83:[2,144],84:[2,144],85:[2,144],86:[2,144],87:[2,144],88:[2,144],89:[2,144],90:[2,144],91:[2,144],92:[2,144],93:[2,144],94:[2,144],95:[2,144],96:[2,144],97:[2,144],98:[2,144],99:[2,144],100:[2,144],101:[2,144],102:[2,144],103:[2,144],104:[2,144],105:[2,144],106:[2,144],107:[2,144],108:[2,144],109:[2,144],110:[2,144],111:[2,144],112:[2,144],113:[2,144],114:[2,144],115:[2,144],116:[2,144],117:[2,144],118:[2,144],119:[2,144],120:[2,144],121:[2,
-144],122:[2,144],123:[2,144],124:[2,144],125:[2,144],126:[2,144],127:[2,144],128:[2,144],129:[2,144],130:[2,144],131:[2,144],132:[2,144],134:[2,144],135:[2,144],137:[2,144],138:[2,144],140:[2,144],141:[2,144],142:[2,144],143:[2,144],144:[2,144],145:[2,144],146:[2,144],147:[2,144],148:[2,144],149:[2,144],150:[2,144],151:[2,144],152:[2,144],153:[2,144],154:[2,144],155:[2,144],156:[2,144],157:[2,144],158:[2,144],159:[2,144],160:[2,144],161:[2,144],162:[2,144],165:[2,144],166:[2,144],167:[2,144],169:[2,
-144],170:[2,144],185:[2,144],188:[2,144],194:[2,144],196:[2,144],198:[2,144],200:[2,144]},{6:[2,145],8:[2,145],10:[2,145],49:[2,145],50:[2,145],51:[2,145],53:[2,145],56:[2,145],57:[2,145],58:[2,145],59:[2,145],60:[2,145],61:[2,145],62:[2,145],63:[2,145],64:[2,145],65:[2,145],66:[2,145],67:[2,145],68:[2,145],69:[2,145],70:[2,145],71:[2,145],72:[2,145],73:[2,145],74:[2,145],75:[2,145],76:[2,145],77:[2,145],78:[2,145],79:[2,145],81:[2,145],82:[2,145],83:[2,145],84:[2,145],85:[2,145],86:[2,145],87:[2,
-145],88:[2,145],89:[2,145],90:[2,145],91:[2,145],92:[2,145],93:[2,145],94:[2,145],95:[2,145],96:[2,145],97:[2,145],98:[2,145],99:[2,145],100:[2,145],101:[2,145],102:[2,145],103:[2,145],104:[2,145],105:[2,145],106:[2,145],107:[2,145],108:[2,145],109:[2,145],110:[2,145],111:[2,145],112:[2,145],113:[2,145],114:[2,145],115:[2,145],116:[2,145],117:[2,145],118:[2,145],119:[2,145],120:[2,145],121:[2,145],122:[2,145],123:[2,145],124:[2,145],125:[2,145],126:[2,145],127:[2,145],128:[2,145],129:[2,145],130:[2,
-145],131:[2,145],132:[2,145],134:[2,145],135:[2,145],137:[2,145],138:[2,145],140:[2,145],141:[2,145],142:[2,145],143:[2,145],144:[2,145],145:[2,145],146:[2,145],147:[2,145],148:[2,145],149:[2,145],150:[2,145],151:[2,145],152:[2,145],153:[2,145],154:[2,145],155:[2,145],156:[2,145],157:[2,145],158:[2,145],159:[2,145],160:[2,145],161:[2,145],162:[2,145],165:[2,145],166:[2,145],167:[2,145],169:[2,145],170:[2,145],185:[2,145],188:[2,145],194:[2,145],196:[2,145],198:[2,145],200:[2,145]},{6:[2,146],8:[2,
-146],10:[2,146],49:[2,146],50:[2,146],51:[2,146],53:[2,146],56:[2,146],57:[2,146],58:[2,146],59:[2,146],60:[2,146],61:[2,146],62:[2,146],63:[2,146],64:[2,146],65:[2,146],66:[2,146],67:[2,146],68:[2,146],69:[2,146],70:[2,146],71:[2,146],72:[2,146],73:[2,146],74:[2,146],75:[2,146],76:[2,146],77:[2,146],78:[2,146],79:[2,146],81:[2,146],82:[2,146],83:[2,146],84:[2,146],85:[2,146],86:[2,146],87:[2,146],88:[2,146],89:[2,146],90:[2,146],91:[2,146],92:[2,146],93:[2,146],94:[2,146],95:[2,146],96:[2,146],97:[2,
-146],98:[2,146],99:[2,146],100:[2,146],101:[2,146],102:[2,146],103:[2,146],104:[2,146],105:[2,146],106:[2,146],107:[2,146],108:[2,146],109:[2,146],110:[2,146],111:[2,146],112:[2,146],113:[2,146],114:[2,146],115:[2,146],116:[2,146],117:[2,146],118:[2,146],119:[2,146],120:[2,146],121:[2,146],122:[2,146],123:[2,146],124:[2,146],125:[2,146],126:[2,146],127:[2,146],128:[2,146],129:[2,146],130:[2,146],131:[2,146],132:[2,146],134:[2,146],135:[2,146],137:[2,146],138:[2,146],140:[2,146],141:[2,146],142:[2,
-146],143:[2,146],144:[2,146],145:[2,146],146:[2,146],147:[2,146],148:[2,146],149:[2,146],150:[2,146],151:[2,146],152:[2,146],153:[2,146],154:[2,146],155:[2,146],156:[2,146],157:[2,146],158:[2,146],159:[2,146],160:[2,146],161:[2,146],162:[2,146],165:[2,146],166:[2,146],167:[2,146],169:[2,146],170:[2,146],185:[2,146],188:[2,146],194:[2,146],196:[2,146],198:[2,146],200:[2,146]},{6:[2,147],8:[2,147],10:[2,147],49:[2,147],50:[2,147],51:[2,147],53:[2,147],56:[2,147],57:[2,147],58:[2,147],59:[2,147],60:[2,
-147],61:[2,147],62:[2,147],63:[2,147],64:[2,147],65:[2,147],66:[2,147],67:[2,147],68:[2,147],69:[2,147],70:[2,147],71:[2,147],72:[2,147],73:[2,147],74:[2,147],75:[2,147],76:[2,147],77:[2,147],78:[2,147],79:[2,147],81:[2,147],82:[2,147],83:[2,147],84:[2,147],85:[2,147],86:[2,147],87:[2,147],88:[2,147],89:[2,147],90:[2,147],91:[2,147],92:[2,147],93:[2,147],94:[2,147],95:[2,147],96:[2,147],97:[2,147],98:[2,147],99:[2,147],100:[2,147],101:[2,147],102:[2,147],103:[2,147],104:[2,147],105:[2,147],106:[2,
-147],107:[2,147],108:[2,147],109:[2,147],110:[2,147],111:[2,147],112:[2,147],113:[2,147],114:[2,147],115:[2,147],116:[2,147],117:[2,147],118:[2,147],119:[2,147],120:[2,147],121:[2,147],122:[2,147],123:[2,147],124:[2,147],125:[2,147],126:[2,147],127:[2,147],128:[2,147],129:[2,147],130:[2,147],131:[2,147],132:[2,147],134:[2,147],135:[2,147],137:[2,147],138:[2,147],140:[2,147],141:[2,147],142:[2,147],143:[2,147],144:[2,147],145:[2,147],146:[2,147],147:[2,147],148:[2,147],149:[2,147],150:[2,147],151:[2,
-147],152:[2,147],153:[2,147],154:[2,147],155:[2,147],156:[2,147],157:[2,147],158:[2,147],159:[2,147],160:[2,147],161:[2,147],162:[2,147],165:[2,147],166:[2,147],167:[2,147],169:[2,147],170:[2,147],185:[2,147],188:[2,147],194:[2,147],196:[2,147],198:[2,147],200:[2,147]},{6:[2,148],8:[2,148],10:[2,148],49:[2,148],50:[2,148],51:[2,148],53:[2,148],56:[2,148],57:[2,148],58:[2,148],59:[2,148],60:[2,148],61:[2,148],62:[2,148],63:[2,148],64:[2,148],65:[2,148],66:[2,148],67:[2,148],68:[2,148],69:[2,148],70:[2,
-148],71:[2,148],72:[2,148],73:[2,148],74:[2,148],75:[2,148],76:[2,148],77:[2,148],78:[2,148],79:[2,148],81:[2,148],82:[2,148],83:[2,148],84:[2,148],85:[2,148],86:[2,148],87:[2,148],88:[2,148],89:[2,148],90:[2,148],91:[2,148],92:[2,148],93:[2,148],94:[2,148],95:[2,148],96:[2,148],97:[2,148],98:[2,148],99:[2,148],100:[2,148],101:[2,148],102:[2,148],103:[2,148],104:[2,148],105:[2,148],106:[2,148],107:[2,148],108:[2,148],109:[2,148],110:[2,148],111:[2,148],112:[2,148],113:[2,148],114:[2,148],115:[2,148],
-116:[2,148],117:[2,148],118:[2,148],119:[2,148],120:[2,148],121:[2,148],122:[2,148],123:[2,148],124:[2,148],125:[2,148],126:[2,148],127:[2,148],128:[2,148],129:[2,148],130:[2,148],131:[2,148],132:[2,148],134:[2,148],135:[2,148],137:[2,148],138:[2,148],140:[2,148],141:[2,148],142:[2,148],143:[2,148],144:[2,148],145:[2,148],146:[2,148],147:[2,148],148:[2,148],149:[2,148],150:[2,148],151:[2,148],152:[2,148],153:[2,148],154:[2,148],155:[2,148],156:[2,148],157:[2,148],158:[2,148],159:[2,148],160:[2,148],
-161:[2,148],162:[2,148],165:[2,148],166:[2,148],167:[2,148],169:[2,148],170:[2,148],185:[2,148],188:[2,148],194:[2,148],196:[2,148],198:[2,148],200:[2,148]},{6:[2,149],8:[2,149],10:[2,149],49:[2,149],50:[2,149],51:[2,149],53:[2,149],56:[2,149],57:[2,149],58:[2,149],59:[2,149],60:[2,149],61:[2,149],62:[2,149],63:[2,149],64:[2,149],65:[2,149],66:[2,149],67:[2,149],68:[2,149],69:[2,149],70:[2,149],71:[2,149],72:[2,149],73:[2,149],74:[2,149],75:[2,149],76:[2,149],77:[2,149],78:[2,149],79:[2,149],81:[2,
-149],82:[2,149],83:[2,149],84:[2,149],85:[2,149],86:[2,149],87:[2,149],88:[2,149],89:[2,149],90:[2,149],91:[2,149],92:[2,149],93:[2,149],94:[2,149],95:[2,149],96:[2,149],97:[2,149],98:[2,149],99:[2,149],100:[2,149],101:[2,149],102:[2,149],103:[2,149],104:[2,149],105:[2,149],106:[2,149],107:[2,149],108:[2,149],109:[2,149],110:[2,149],111:[2,149],112:[2,149],113:[2,149],114:[2,149],115:[2,149],116:[2,149],117:[2,149],118:[2,149],119:[2,149],120:[2,149],121:[2,149],122:[2,149],123:[2,149],124:[2,149],
-125:[2,149],126:[2,149],127:[2,149],128:[2,149],129:[2,149],130:[2,149],131:[2,149],132:[2,149],134:[2,149],135:[2,149],137:[2,149],138:[2,149],140:[2,149],141:[2,149],142:[2,149],143:[2,149],144:[2,149],145:[2,149],146:[2,149],147:[2,149],148:[2,149],149:[2,149],150:[2,149],151:[2,149],152:[2,149],153:[2,149],154:[2,149],155:[2,149],156:[2,149],157:[2,149],158:[2,149],159:[2,149],160:[2,149],161:[2,149],162:[2,149],165:[2,149],166:[2,149],167:[2,149],169:[2,149],170:[2,149],185:[2,149],188:[2,149],
-194:[2,149],196:[2,149],198:[2,149],200:[2,149]},{6:[2,150],8:[2,150],10:[2,150],49:[2,150],50:[2,150],51:[2,150],53:[2,150],56:[2,150],57:[2,150],58:[2,150],59:[2,150],60:[2,150],61:[2,150],62:[2,150],63:[2,150],64:[2,150],65:[2,150],66:[2,150],67:[2,150],68:[2,150],69:[2,150],70:[2,150],71:[2,150],72:[2,150],73:[2,150],74:[2,150],75:[2,150],76:[2,150],77:[2,150],78:[2,150],79:[2,150],81:[2,150],82:[2,150],83:[2,150],84:[2,150],85:[2,150],86:[2,150],87:[2,150],88:[2,150],89:[2,150],90:[2,150],91:[2,
-150],92:[2,150],93:[2,150],94:[2,150],95:[2,150],96:[2,150],97:[2,150],98:[2,150],99:[2,150],100:[2,150],101:[2,150],102:[2,150],103:[2,150],104:[2,150],105:[2,150],106:[2,150],107:[2,150],108:[2,150],109:[2,150],110:[2,150],111:[2,150],112:[2,150],113:[2,150],114:[2,150],115:[2,150],116:[2,150],117:[2,150],118:[2,150],119:[2,150],120:[2,150],121:[2,150],122:[2,150],123:[2,150],124:[2,150],125:[2,150],126:[2,150],127:[2,150],128:[2,150],129:[2,150],130:[2,150],131:[2,150],132:[2,150],134:[2,150],
-135:[2,150],137:[2,150],138:[2,150],140:[2,150],141:[2,150],142:[2,150],143:[2,150],144:[2,150],145:[2,150],146:[2,150],147:[2,150],148:[2,150],149:[2,150],150:[2,150],151:[2,150],152:[2,150],153:[2,150],154:[2,150],155:[2,150],156:[2,150],157:[2,150],158:[2,150],159:[2,150],160:[2,150],161:[2,150],162:[2,150],165:[2,150],166:[2,150],167:[2,150],169:[2,150],170:[2,150],185:[2,150],188:[2,150],194:[2,150],196:[2,150],198:[2,150],200:[2,150]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:213,
-56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,
-79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],139:349,141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],160:[2,193],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,
-174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21],182:211,183:[1,212],184:210,185:[2,193],186:208,187:[1,209],188:[2,193]},{160:[1,350],188:[1,281]},{10:[1,351],188:[1,281]},{10:[1,352],188:[1,281]},{8:[1,353]},{6:[2,2],8:[2,2],10:[2,2],19:[2,2],21:[2,2],23:[2,2],25:[2,2],27:[2,2],29:[2,2],31:[2,2],33:[2,2],35:[2,2],37:[2,2],39:[2,2],41:[2,2],49:[2,2],50:[2,2],51:[2,2],53:[2,2],56:[2,2],57:[2,2],58:[2,2],59:[2,2],60:[2,2],61:[2,2],62:[2,2],63:[2,2],64:[2,2],65:[2,
-2],66:[2,2],67:[2,2],68:[2,2],69:[2,2],70:[2,2],71:[2,2],72:[2,2],73:[2,2],74:[2,2],75:[2,2],76:[2,2],77:[2,2],78:[2,2],79:[2,2],81:[2,2],82:[2,2],83:[2,2],84:[2,2],85:[2,2],86:[2,2],87:[2,2],88:[2,2],89:[2,2],90:[2,2],91:[2,2],92:[2,2],93:[2,2],94:[2,2],95:[2,2],96:[2,2],97:[2,2],98:[2,2],99:[2,2],100:[2,2],101:[2,2],102:[2,2],103:[2,2],104:[2,2],105:[2,2],106:[2,2],107:[2,2],108:[2,2],109:[2,2],110:[2,2],111:[2,2],112:[2,2],113:[2,2],114:[2,2],115:[2,2],116:[2,2],117:[2,2],118:[2,2],119:[2,2],120:[2,
-2],121:[2,2],122:[2,2],123:[2,2],124:[2,2],125:[2,2],126:[2,2],127:[2,2],128:[2,2],129:[2,2],130:[2,2],131:[2,2],132:[2,2],134:[2,2],135:[2,2],137:[2,2],138:[2,2],140:[2,2],141:[2,2],142:[2,2],143:[2,2],144:[2,2],145:[2,2],146:[2,2],147:[2,2],148:[2,2],149:[2,2],150:[2,2],151:[2,2],152:[2,2],153:[2,2],154:[2,2],155:[2,2],156:[2,2],157:[2,2],158:[2,2],159:[2,2],160:[2,2],161:[2,2],162:[2,2],165:[2,2],166:[2,2],167:[2,2],169:[2,2],170:[2,2],175:[2,2],176:[2,2],177:[2,2],178:[2,2],179:[2,2],180:[2,2],
-181:[2,2],183:[2,2],185:[2,2],187:[2,2],188:[2,2],194:[2,2],196:[2,2],198:[2,2],200:[2,2]},{6:[2,183],8:[2,183],10:[2,183],49:[2,183],50:[2,183],51:[2,183],53:[2,183],56:[2,183],57:[2,183],58:[2,183],59:[2,183],60:[2,183],61:[2,183],62:[2,183],63:[2,183],64:[2,183],65:[2,183],66:[2,183],67:[2,183],68:[2,183],69:[2,183],70:[2,183],71:[2,183],72:[2,183],73:[2,183],74:[2,183],75:[2,183],76:[2,183],77:[2,183],78:[2,183],79:[2,183],81:[2,183],82:[2,183],83:[2,183],84:[2,183],85:[2,183],86:[2,183],87:[2,
-183],88:[2,183],89:[2,183],90:[2,183],91:[2,183],92:[2,183],93:[2,183],94:[2,183],95:[2,183],96:[2,183],97:[2,183],98:[2,183],99:[2,183],100:[2,183],101:[2,183],102:[2,183],103:[2,183],104:[2,183],105:[2,183],106:[2,183],107:[2,183],108:[2,183],109:[2,183],110:[2,183],111:[2,183],112:[2,183],113:[2,183],114:[2,183],115:[2,183],116:[2,183],117:[2,183],118:[2,183],119:[2,183],120:[2,183],121:[2,183],122:[2,183],123:[2,183],124:[2,183],125:[2,183],126:[2,183],127:[2,183],128:[2,183],129:[2,183],130:[2,
-183],131:[2,183],132:[2,183],135:[2,183],137:[2,183],138:[2,183],140:[2,183],141:[2,183],142:[2,183],143:[2,183],144:[2,183],145:[2,183],146:[2,183],147:[2,183],148:[2,183],149:[2,183],150:[2,183],151:[2,183],152:[2,183],153:[2,183],154:[2,183],155:[2,183],156:[2,183],157:[2,183],158:[2,183],159:[2,183],160:[2,183],161:[2,183],162:[2,183],165:[2,183],166:[2,183],169:[2,183],170:[2,183],185:[2,183],188:[2,183],194:[2,183],196:[2,183],198:[2,183],200:[2,183]},{10:[1,354],165:[1,238],166:[1,239],173:300},
-{6:[2,179],8:[2,179],10:[2,179],49:[2,179],50:[2,179],51:[2,179],53:[2,179],56:[2,179],57:[2,179],58:[2,179],59:[2,179],60:[2,179],61:[2,179],62:[2,179],63:[2,179],64:[2,179],65:[2,179],66:[2,179],67:[2,179],68:[2,179],69:[2,179],70:[2,179],71:[2,179],72:[2,179],73:[2,179],74:[2,179],75:[2,179],76:[2,179],77:[2,179],78:[2,179],79:[2,179],81:[2,179],82:[2,179],83:[2,179],84:[2,179],85:[2,179],86:[2,179],87:[2,179],88:[2,179],89:[2,179],90:[2,179],91:[2,179],92:[2,179],93:[2,179],94:[2,179],95:[2,179],
-96:[2,179],97:[2,179],98:[2,179],99:[2,179],100:[2,179],101:[2,179],102:[2,179],103:[2,179],104:[2,179],105:[2,179],106:[2,179],107:[2,179],108:[2,179],109:[2,179],110:[2,179],111:[2,179],112:[2,179],113:[2,179],114:[2,179],115:[2,179],116:[2,179],117:[2,179],118:[2,179],119:[2,179],120:[2,179],121:[2,179],122:[2,179],123:[2,179],124:[2,179],125:[2,179],126:[2,179],127:[2,179],128:[2,179],129:[2,179],130:[2,179],131:[2,179],132:[2,179],135:[2,179],137:[2,179],138:[2,179],140:[2,179],141:[2,179],142:[2,
-179],143:[2,179],144:[2,179],145:[2,179],146:[2,179],147:[2,179],148:[2,179],149:[2,179],150:[2,179],151:[2,179],152:[2,179],153:[2,179],154:[2,179],155:[2,179],156:[2,179],157:[2,179],158:[2,179],159:[2,179],160:[2,179],161:[2,179],162:[2,179],165:[2,179],166:[1,355],169:[2,179],170:[2,179],185:[2,179],188:[2,179],194:[2,179],196:[2,179],198:[2,179],200:[2,179]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:304,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,
-36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],
-117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],168:305,169:[1,117],170:[1,118],172:356},{6:[2,176],8:[2,176],10:[2,176],49:[2,176],50:[2,176],51:[2,176],53:[2,176],56:[2,176],57:[2,176],58:[2,
-176],59:[2,176],60:[2,176],61:[2,176],62:[2,176],63:[2,176],64:[2,176],65:[2,176],66:[2,176],67:[2,176],68:[2,176],69:[2,176],70:[2,176],71:[2,176],72:[2,176],73:[2,176],74:[2,176],75:[2,176],76:[2,176],77:[2,176],78:[2,176],79:[2,176],81:[2,176],82:[2,176],83:[2,176],84:[2,176],85:[2,176],86:[2,176],87:[2,176],88:[2,176],89:[2,176],90:[2,176],91:[2,176],92:[2,176],93:[2,176],94:[2,176],95:[2,176],96:[2,176],97:[2,176],98:[2,176],99:[2,176],100:[2,176],101:[2,176],102:[2,176],103:[2,176],104:[2,176],
-105:[2,176],106:[2,176],107:[2,176],108:[2,176],109:[2,176],110:[2,176],111:[2,176],112:[2,176],113:[2,176],114:[2,176],115:[2,176],116:[2,176],117:[2,176],118:[2,176],119:[2,176],120:[2,176],121:[2,176],122:[2,176],123:[2,176],124:[2,176],125:[2,176],126:[2,176],127:[2,176],128:[2,176],129:[2,176],130:[2,176],131:[2,176],132:[2,176],135:[2,176],137:[2,176],138:[2,176],140:[2,176],141:[2,176],142:[2,176],143:[2,176],144:[2,176],145:[2,176],146:[2,176],147:[2,176],148:[2,176],149:[2,176],150:[2,176],
-151:[2,176],152:[2,176],153:[2,176],154:[2,176],155:[2,176],156:[2,176],157:[2,176],158:[2,176],159:[2,176],160:[2,176],161:[2,176],162:[2,176],165:[2,176],166:[2,176],169:[2,176],170:[2,176],185:[2,176],188:[2,176],194:[2,176],196:[2,176],198:[2,176],200:[2,176]},{6:[2,177],8:[2,177],10:[2,177],49:[2,177],50:[2,177],51:[2,177],53:[2,177],56:[2,177],57:[2,177],58:[2,177],59:[2,177],60:[2,177],61:[2,177],62:[2,177],63:[2,177],64:[2,177],65:[2,177],66:[2,177],67:[2,177],68:[2,177],69:[2,177],70:[2,
-177],71:[2,177],72:[2,177],73:[2,177],74:[2,177],75:[2,177],76:[2,177],77:[2,177],78:[2,177],79:[2,177],81:[2,177],82:[2,177],83:[2,177],84:[2,177],85:[2,177],86:[2,177],87:[2,177],88:[2,177],89:[2,177],90:[2,177],91:[2,177],92:[2,177],93:[2,177],94:[2,177],95:[2,177],96:[2,177],97:[2,177],98:[2,177],99:[2,177],100:[2,177],101:[2,177],102:[2,177],103:[2,177],104:[2,177],105:[2,177],106:[2,177],107:[2,177],108:[2,177],109:[2,177],110:[2,177],111:[2,177],112:[2,177],113:[2,177],114:[2,177],115:[2,177],
-116:[2,177],117:[2,177],118:[2,177],119:[2,177],120:[2,177],121:[2,177],122:[2,177],123:[2,177],124:[2,177],125:[2,177],126:[2,177],127:[2,177],128:[2,177],129:[2,177],130:[2,177],131:[2,177],132:[2,177],135:[2,177],137:[2,177],138:[2,177],140:[2,177],141:[2,177],142:[2,177],143:[2,177],144:[2,177],145:[2,177],146:[2,177],147:[2,177],148:[2,177],149:[2,177],150:[2,177],151:[2,177],152:[2,177],153:[2,177],154:[2,177],155:[2,177],156:[2,177],157:[2,177],158:[2,177],159:[2,177],160:[2,177],161:[2,177],
-162:[2,177],165:[2,177],166:[2,177],169:[2,177],170:[2,177],185:[2,177],188:[2,177],194:[2,177],196:[2,177],198:[2,177],200:[2,177]},{6:[2,180],8:[2,180],10:[2,180],49:[2,180],50:[2,180],51:[2,180],53:[2,180],56:[2,180],57:[2,180],58:[2,180],59:[2,180],60:[2,180],61:[2,180],62:[2,180],63:[2,180],64:[2,180],65:[2,180],66:[2,180],67:[2,180],68:[2,180],69:[2,180],70:[2,180],71:[2,180],72:[2,180],73:[2,180],74:[2,180],75:[2,180],76:[2,180],77:[2,180],78:[2,180],79:[2,180],81:[2,180],82:[2,180],83:[2,
-180],84:[2,180],85:[2,180],86:[2,180],87:[2,180],88:[2,180],89:[2,180],90:[2,180],91:[2,180],92:[2,180],93:[2,180],94:[2,180],95:[2,180],96:[2,180],97:[2,180],98:[2,180],99:[2,180],100:[2,180],101:[2,180],102:[2,180],103:[2,180],104:[2,180],105:[2,180],106:[2,180],107:[2,180],108:[2,180],109:[2,180],110:[2,180],111:[2,180],112:[2,180],113:[2,180],114:[2,180],115:[2,180],116:[2,180],117:[2,180],118:[2,180],119:[2,180],120:[2,180],121:[2,180],122:[2,180],123:[2,180],124:[2,180],125:[2,180],126:[2,180],
-127:[2,180],128:[2,180],129:[2,180],130:[2,180],131:[2,180],132:[2,180],135:[2,180],137:[2,180],138:[2,180],140:[2,180],141:[2,180],142:[2,180],143:[2,180],144:[2,180],145:[2,180],146:[2,180],147:[2,180],148:[2,180],149:[2,180],150:[2,180],151:[2,180],152:[2,180],153:[2,180],154:[2,180],155:[2,180],156:[2,180],157:[2,180],158:[2,180],159:[2,180],160:[2,180],161:[2,180],162:[2,180],165:[2,180],166:[2,180],169:[2,180],170:[2,180],185:[2,180],188:[2,180],194:[2,180],196:[2,180],198:[2,180],200:[2,180]},
-{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:357,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,
-74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{6:[2,
-160],8:[2,160],10:[2,160],49:[2,160],50:[2,160],51:[2,160],53:[2,160],56:[2,160],57:[2,160],58:[2,160],59:[2,160],60:[2,160],61:[2,160],62:[2,160],63:[2,160],64:[2,160],65:[2,160],66:[2,160],67:[2,160],68:[2,160],69:[2,160],70:[2,160],71:[2,160],72:[2,160],73:[2,160],74:[2,160],75:[2,160],76:[2,160],77:[2,160],78:[2,160],79:[2,160],81:[2,160],82:[2,160],83:[2,160],84:[2,160],85:[2,160],86:[2,160],87:[2,160],88:[2,160],89:[2,160],90:[2,160],91:[2,160],92:[2,160],93:[2,160],94:[2,160],95:[2,160],96:[2,
-160],97:[2,160],98:[2,160],99:[2,160],100:[2,160],101:[2,160],102:[2,160],103:[2,160],104:[2,160],105:[2,160],106:[2,160],107:[2,160],108:[2,160],109:[2,160],110:[2,160],111:[2,160],112:[2,160],113:[2,160],114:[2,160],115:[2,160],116:[2,160],117:[2,160],118:[2,160],119:[2,160],120:[2,160],121:[2,160],122:[2,160],123:[2,160],124:[2,160],125:[2,160],126:[2,160],127:[2,160],128:[2,160],129:[2,160],130:[2,160],131:[2,160],132:[2,160],135:[2,160],137:[2,160],138:[2,160],140:[2,160],141:[2,160],142:[2,
-160],143:[2,160],144:[2,160],145:[2,160],146:[2,160],147:[2,160],148:[2,160],149:[2,160],150:[2,160],151:[2,160],152:[2,160],153:[2,160],154:[2,160],155:[2,160],156:[2,160],157:[2,160],158:[2,160],159:[2,160],160:[2,160],161:[2,160],162:[2,160],169:[2,160],170:[2,160],185:[2,160],188:[2,160],194:[2,160],196:[2,160],198:[2,160],200:[2,160]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:358,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,
-38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],
-119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{6:[2,162],8:[2,162],10:[2,162],49:[2,162],50:[2,162],51:[2,162],53:[2,162],56:[2,162],57:[2,162],58:[2,162],59:[2,162],60:[2,162],61:[2,162],62:[2,162],63:[2,162],
-64:[2,162],65:[2,162],66:[2,162],67:[2,162],68:[2,162],69:[2,162],70:[2,162],71:[2,162],72:[2,162],73:[2,162],74:[2,162],75:[2,162],76:[2,162],77:[2,162],78:[2,162],79:[2,162],81:[2,162],82:[2,162],83:[2,162],84:[2,162],85:[2,162],86:[2,162],87:[2,162],88:[2,162],89:[2,162],90:[2,162],91:[2,162],92:[2,162],93:[2,162],94:[2,162],95:[2,162],96:[2,162],97:[2,162],98:[2,162],99:[2,162],100:[2,162],101:[2,162],102:[2,162],103:[2,162],104:[2,162],105:[2,162],106:[2,162],107:[2,162],108:[2,162],109:[2,162],
-110:[2,162],111:[2,162],112:[2,162],113:[2,162],114:[2,162],115:[2,162],116:[2,162],117:[2,162],118:[2,162],119:[2,162],120:[2,162],121:[2,162],122:[2,162],123:[2,162],124:[2,162],125:[2,162],126:[2,162],127:[2,162],128:[2,162],129:[2,162],130:[2,162],131:[2,162],132:[2,162],135:[2,162],137:[2,162],138:[2,162],140:[2,162],141:[2,162],142:[2,162],143:[2,162],144:[2,162],145:[2,162],146:[2,162],147:[2,162],148:[2,162],149:[2,162],150:[2,162],151:[2,162],152:[2,162],153:[2,162],154:[2,162],155:[2,162],
-156:[2,162],157:[2,162],158:[2,162],159:[2,162],160:[2,162],161:[2,162],162:[2,162],169:[2,162],170:[2,162],185:[2,162],188:[2,162],194:[2,162],196:[2,162],198:[2,162],200:[2,162]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:359,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,
-56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,
-132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:360,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,
-57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],
-137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{10:[1,361]},{10:[1,362]},{10:[1,363]},{52:364,53:[1,254]},{52:365,53:[1,254]},{52:366,53:[1,254]},{6:[2,46],8:[2,46],10:[2,46],49:[2,46],50:[2,46],51:[2,46],53:[2,46],56:[2,46],57:[2,46],58:[2,46],59:[2,46],60:[2,46],61:[2,46],62:[2,46],63:[2,46],64:[2,46],65:[2,46],66:[2,46],67:[2,46],68:[2,46],69:[2,46],70:[2,46],71:[2,46],72:[2,
-46],73:[2,46],74:[2,46],75:[2,46],76:[2,46],77:[2,46],78:[2,46],79:[2,46],81:[2,46],82:[2,46],83:[2,46],84:[2,46],85:[2,46],86:[2,46],87:[2,46],88:[2,46],89:[2,46],90:[2,46],91:[2,46],92:[2,46],93:[2,46],94:[2,46],95:[2,46],96:[2,46],97:[2,46],98:[2,46],99:[2,46],100:[2,46],101:[2,46],102:[2,46],103:[2,46],104:[2,46],105:[2,46],106:[2,46],107:[2,46],108:[2,46],109:[2,46],110:[2,46],111:[2,46],112:[2,46],113:[2,46],114:[2,46],115:[2,46],116:[2,46],117:[2,46],118:[2,46],119:[2,46],120:[2,46],121:[2,
-46],122:[2,46],123:[2,46],124:[2,46],125:[2,46],126:[2,46],127:[2,46],128:[2,46],129:[2,46],130:[2,46],131:[2,46],132:[2,46],134:[2,46],135:[2,46],137:[2,46],138:[2,46],140:[2,46],141:[2,46],142:[2,46],143:[2,46],144:[2,46],145:[2,46],146:[2,46],147:[2,46],148:[2,46],149:[2,46],150:[2,46],151:[2,46],152:[2,46],153:[2,46],154:[2,46],155:[2,46],156:[2,46],157:[2,46],158:[2,46],159:[2,46],160:[2,46],161:[2,46],162:[2,46],165:[2,46],166:[2,46],167:[2,46],169:[2,46],170:[2,46],185:[2,46],188:[2,46],194:[2,
-46],196:[2,46],198:[2,46],200:[2,46]},{6:[2,47],8:[2,47],10:[2,47],49:[2,47],50:[2,47],51:[2,47],53:[2,47],56:[2,47],57:[2,47],58:[2,47],59:[2,47],60:[2,47],61:[2,47],62:[2,47],63:[2,47],64:[2,47],65:[2,47],66:[2,47],67:[2,47],68:[2,47],69:[2,47],70:[2,47],71:[2,47],72:[2,47],73:[2,47],74:[2,47],75:[2,47],76:[2,47],77:[2,47],78:[2,47],79:[2,47],81:[2,47],82:[2,47],83:[2,47],84:[2,47],85:[2,47],86:[2,47],87:[2,47],88:[2,47],89:[2,47],90:[2,47],91:[2,47],92:[2,47],93:[2,47],94:[2,47],95:[2,47],96:[2,
-47],97:[2,47],98:[2,47],99:[2,47],100:[2,47],101:[2,47],102:[2,47],103:[2,47],104:[2,47],105:[2,47],106:[2,47],107:[2,47],108:[2,47],109:[2,47],110:[2,47],111:[2,47],112:[2,47],113:[2,47],114:[2,47],115:[2,47],116:[2,47],117:[2,47],118:[2,47],119:[2,47],120:[2,47],121:[2,47],122:[2,47],123:[2,47],124:[2,47],125:[2,47],126:[2,47],127:[2,47],128:[2,47],129:[2,47],130:[2,47],131:[2,47],132:[2,47],134:[2,47],135:[2,47],137:[2,47],138:[2,47],140:[2,47],141:[2,47],142:[2,47],143:[2,47],144:[2,47],145:[2,
-47],146:[2,47],147:[2,47],148:[2,47],149:[2,47],150:[2,47],151:[2,47],152:[2,47],153:[2,47],154:[2,47],155:[2,47],156:[2,47],157:[2,47],158:[2,47],159:[2,47],160:[2,47],161:[2,47],162:[2,47],165:[2,47],166:[2,47],167:[2,47],169:[2,47],170:[2,47],185:[2,47],188:[2,47],194:[2,47],196:[2,47],198:[2,47],200:[2,47]},{6:[2,78],8:[2,78],10:[2,78],49:[2,78],50:[2,78],51:[2,78],53:[2,78],56:[2,78],57:[2,78],58:[2,78],59:[2,78],60:[2,78],61:[2,78],62:[2,78],63:[2,78],64:[2,78],65:[2,78],66:[2,78],67:[2,78],
-68:[2,78],69:[2,78],70:[2,78],71:[2,78],72:[2,78],73:[2,78],74:[2,78],75:[2,78],76:[2,78],77:[2,78],78:[2,78],79:[2,78],81:[2,78],82:[2,78],83:[2,78],84:[2,78],85:[2,78],86:[2,78],87:[2,78],88:[2,78],89:[2,78],90:[2,78],91:[2,78],92:[2,78],93:[2,78],94:[2,78],95:[2,78],96:[2,78],97:[2,78],98:[2,78],99:[2,78],100:[2,78],101:[2,78],102:[2,78],103:[2,78],104:[2,78],105:[2,78],106:[2,78],107:[2,78],108:[2,78],109:[2,78],110:[2,78],111:[2,78],112:[2,78],113:[2,78],114:[2,78],115:[2,78],116:[2,78],117:[2,
-78],118:[2,78],119:[2,78],120:[2,78],121:[2,78],122:[2,78],123:[2,78],124:[2,78],125:[2,78],126:[2,78],127:[2,78],128:[2,78],129:[2,78],130:[2,78],131:[2,78],132:[2,78],134:[2,78],135:[2,78],137:[2,78],138:[2,78],140:[2,78],141:[2,78],142:[2,78],143:[2,78],144:[2,78],145:[2,78],146:[2,78],147:[2,78],148:[2,78],149:[2,78],150:[2,78],151:[2,78],152:[2,78],153:[2,78],154:[2,78],155:[2,78],156:[2,78],157:[2,78],158:[2,78],159:[2,78],160:[2,78],161:[2,78],162:[2,78],165:[2,78],166:[2,78],167:[2,78],169:[2,
-78],170:[2,78],185:[2,78],188:[2,78],194:[2,78],196:[2,78],198:[2,78],200:[2,78]},{4:[2,1],8:[2,1]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:367,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],
-95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,
-109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{6:[2,92],8:[2,92],10:[2,92],49:[2,92],50:[2,92],51:[2,92],53:[2,92],56:[2,92],57:[2,92],58:[2,92],59:[2,92],60:[2,92],61:[2,92],62:[2,92],63:[2,92],64:[2,92],65:[2,92],66:[2,92],67:[2,92],68:[2,92],69:[2,92],70:[2,92],71:[2,92],72:[2,92],73:[2,92],74:[2,92],75:[2,92],76:[2,92],77:[2,92],78:[2,92],79:[2,92],81:[2,92],82:[2,92],83:[2,92],84:[2,92],85:[2,92],86:[2,92],87:[2,92],88:[2,92],89:[2,92],90:[2,92],91:[2,
-92],92:[2,92],93:[2,92],94:[2,92],95:[2,92],96:[2,92],97:[2,92],98:[2,92],99:[2,92],100:[2,92],101:[2,92],102:[2,92],103:[2,92],104:[2,92],105:[2,92],106:[2,92],107:[2,92],108:[2,92],109:[2,92],110:[2,92],111:[2,92],112:[2,92],113:[2,92],114:[2,92],115:[2,92],116:[2,92],117:[2,92],118:[2,92],119:[2,92],120:[2,92],121:[2,92],122:[2,92],123:[2,92],124:[2,92],125:[2,92],126:[2,92],127:[2,92],128:[2,92],129:[2,92],130:[2,92],131:[2,92],132:[2,92],134:[2,92],135:[2,92],137:[2,92],138:[2,92],140:[2,92],
-141:[2,92],142:[2,92],143:[2,92],144:[2,92],145:[2,92],146:[2,92],147:[2,92],148:[2,92],149:[2,92],150:[2,92],151:[2,92],152:[2,92],153:[2,92],154:[2,92],155:[2,92],156:[2,92],157:[2,92],158:[2,92],159:[2,92],160:[2,92],161:[2,92],162:[2,92],165:[2,92],166:[2,92],167:[2,92],169:[2,92],170:[2,92],185:[2,92],188:[2,92],194:[2,92],196:[2,92],198:[2,92],200:[2,92]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:368,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,
-36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],
-117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{6:[2,118],8:[2,118],10:[2,118],49:[2,118],50:[2,118],51:[2,118],53:[2,118],56:[2,118],57:[2,118],58:[2,118],59:[2,118],60:[2,118],61:[2,118],
-62:[2,118],63:[2,118],64:[2,118],65:[2,118],66:[2,118],67:[2,118],68:[2,118],69:[2,118],70:[2,118],71:[2,118],72:[2,118],73:[2,118],74:[2,118],75:[2,118],76:[2,118],77:[2,118],78:[2,118],79:[2,118],81:[2,118],82:[2,118],83:[2,118],84:[2,118],85:[2,118],86:[2,118],87:[2,118],88:[2,118],89:[2,118],90:[2,118],91:[2,118],92:[2,118],93:[2,118],94:[2,118],95:[2,118],96:[2,118],97:[2,118],98:[2,118],99:[2,118],100:[2,118],101:[2,118],102:[2,118],103:[2,118],104:[2,118],105:[2,118],106:[2,118],107:[2,118],
-108:[2,118],109:[2,118],110:[2,118],111:[2,118],112:[2,118],113:[2,118],114:[2,118],115:[2,118],116:[2,118],117:[2,118],118:[2,118],119:[2,118],120:[2,118],121:[2,118],122:[2,118],123:[2,118],124:[2,118],125:[2,118],126:[2,118],127:[2,118],128:[2,118],129:[2,118],130:[2,118],131:[2,118],132:[2,118],134:[2,118],135:[2,118],137:[2,118],138:[2,118],140:[2,118],141:[2,118],142:[2,118],143:[2,118],144:[2,118],145:[2,118],146:[2,118],147:[2,118],148:[2,118],149:[2,118],150:[2,118],151:[2,118],152:[2,118],
-153:[2,118],154:[2,118],155:[2,118],156:[2,118],157:[2,118],158:[2,118],159:[2,118],160:[2,118],161:[2,118],162:[2,118],165:[2,118],166:[2,118],167:[2,118],169:[2,118],170:[2,118],185:[2,118],188:[2,118],194:[2,118],196:[2,118],198:[2,118],200:[2,118]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:369,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,
-49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],
-127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116]},{6:[2,120],8:[2,120],10:[2,120],49:[2,120],50:[2,120],51:[2,120],53:[2,120],56:[2,120],57:[2,120],58:[2,120],59:[2,120],60:[2,120],61:[2,120],62:[2,120],63:[2,120],64:[2,120],65:[2,120],66:[2,120],67:[2,120],68:[2,120],69:[2,120],70:[2,120],71:[2,120],
-72:[2,120],73:[2,120],74:[2,120],75:[2,120],76:[2,120],77:[2,120],78:[2,120],79:[2,120],81:[2,120],82:[2,120],83:[2,120],84:[2,120],85:[2,120],86:[2,120],87:[2,120],88:[2,120],89:[2,120],90:[2,120],91:[2,120],92:[2,120],93:[2,120],94:[2,120],95:[2,120],96:[2,120],97:[2,120],98:[2,120],99:[2,120],100:[2,120],101:[2,120],102:[2,120],103:[2,120],104:[2,120],105:[2,120],106:[2,120],107:[2,120],108:[2,120],109:[2,120],110:[2,120],111:[2,120],112:[2,120],113:[2,120],114:[2,120],115:[2,120],116:[2,120],
-117:[2,120],118:[2,120],119:[2,120],120:[2,120],121:[2,120],122:[2,120],123:[2,120],124:[2,120],125:[2,120],126:[2,120],127:[2,120],128:[2,120],129:[2,120],130:[2,120],131:[2,120],132:[2,120],134:[2,120],135:[2,120],137:[2,120],138:[2,120],140:[2,120],141:[2,120],142:[2,120],143:[2,120],144:[2,120],145:[2,120],146:[2,120],147:[2,120],148:[2,120],149:[2,120],150:[2,120],151:[2,120],152:[2,120],153:[2,120],154:[2,120],155:[2,120],156:[2,120],157:[2,120],158:[2,120],159:[2,120],160:[2,120],161:[2,120],
-162:[2,120],165:[2,120],166:[2,120],167:[2,120],169:[2,120],170:[2,120],185:[2,120],188:[2,120],194:[2,120],196:[2,120],198:[2,120],200:[2,120]},{6:[1,370]},{4:[2,4],8:[2,4],49:[2,4],50:[2,4],51:[2,4],56:[2,4],57:[2,4],58:[2,4],59:[2,4],60:[2,4],61:[2,4],62:[2,4],63:[2,4],67:[2,4],68:[2,4],69:[2,4],70:[2,4],71:[2,4],72:[2,4],73:[2,4],74:[2,4],75:[2,4],76:[2,4],77:[2,4],78:[2,4],79:[2,4],81:[2,4],82:[2,4],83:[2,4],84:[2,4],85:[2,4],86:[2,4],87:[2,4],88:[2,4],89:[2,4],90:[2,4],91:[2,4],92:[2,4],93:[2,
-4],94:[2,4],95:[2,4],96:[2,4],97:[2,4],98:[2,4],99:[2,4],100:[2,4],101:[2,4],102:[2,4],103:[2,4],104:[2,4],105:[2,4],106:[2,4],107:[2,4],108:[2,4],109:[2,4],110:[2,4],111:[2,4],112:[2,4],113:[2,4],114:[2,4],115:[2,4],116:[2,4],117:[2,4],118:[2,4],119:[2,4],120:[2,4],121:[2,4],122:[2,4],123:[2,4],124:[2,4],125:[2,4],126:[2,4],127:[2,4],128:[2,4],129:[2,4],130:[2,4],131:[2,4],132:[2,4],135:[2,4],137:[2,4],138:[2,4],141:[2,4],143:[2,4],145:[2,4],147:[2,4],149:[2,4],151:[2,4],153:[2,4],155:[2,4],157:[2,
-4],159:[2,4],161:[2,4],162:[2,4]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:371,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,
-71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],
-161:[1,115],162:[1,116]},{8:[1,372]},{10:[2,201],140:[2,201],142:[2,201],144:[2,201],146:[2,201],148:[2,201],150:[2,201],152:[2,201],154:[2,201],156:[2,201],158:[2,201],160:[2,201],188:[2,201]},{10:[1,373],20:336,21:[1,338],22:337,23:[1,339],44:374},{10:[2,42],21:[2,42],23:[2,42]},{10:[2,28],21:[2,28],23:[2,28]},{10:[2,29],21:[2,29],23:[2,29]},{7:128,8:[1,129],14:375},{7:128,8:[1,129],14:376},{10:[2,197],140:[2,197],142:[2,197],144:[2,197],146:[2,197],148:[2,197],150:[2,197],152:[2,197],154:[2,197],
-156:[2,197],158:[2,197],160:[2,197],185:[2,197],188:[2,197]},{10:[1,377],20:343,21:[1,338],22:344,23:[1,339],24:345,25:[1,347],26:346,27:[1,348],42:378},{10:[2,26],21:[2,26],23:[2,26],25:[2,26],27:[2,26]},{10:[2,22],21:[2,22],23:[2,22],25:[2,22],27:[2,22]},{10:[2,23],21:[2,23],23:[2,23],25:[2,23],27:[2,23]},{10:[2,24],21:[2,24],23:[2,24],25:[2,24],27:[2,24]},{10:[2,25],21:[2,25],23:[2,25],25:[2,25],27:[2,25]},{7:128,8:[1,129],14:379},{7:128,8:[1,129],14:380},{160:[1,381],188:[1,281]},{6:[2,152],8:[2,
-152],10:[2,152],49:[2,152],50:[2,152],51:[2,152],53:[2,152],56:[2,152],57:[2,152],58:[2,152],59:[2,152],60:[2,152],61:[2,152],62:[2,152],63:[2,152],64:[2,152],65:[2,152],66:[2,152],67:[2,152],68:[2,152],69:[2,152],70:[2,152],71:[2,152],72:[2,152],73:[2,152],74:[2,152],75:[2,152],76:[2,152],77:[2,152],78:[2,152],79:[2,152],81:[2,152],82:[2,152],83:[2,152],84:[2,152],85:[2,152],86:[2,152],87:[2,152],88:[2,152],89:[2,152],90:[2,152],91:[2,152],92:[2,152],93:[2,152],94:[2,152],95:[2,152],96:[2,152],97:[2,
-152],98:[2,152],99:[2,152],100:[2,152],101:[2,152],102:[2,152],103:[2,152],104:[2,152],105:[2,152],106:[2,152],107:[2,152],108:[2,152],109:[2,152],110:[2,152],111:[2,152],112:[2,152],113:[2,152],114:[2,152],115:[2,152],116:[2,152],117:[2,152],118:[2,152],119:[2,152],120:[2,152],121:[2,152],122:[2,152],123:[2,152],124:[2,152],125:[2,152],126:[2,152],127:[2,152],128:[2,152],129:[2,152],130:[2,152],131:[2,152],132:[2,152],134:[2,152],135:[2,152],137:[2,152],138:[2,152],140:[2,152],141:[2,152],142:[2,
-152],143:[2,152],144:[2,152],145:[2,152],146:[2,152],147:[2,152],148:[2,152],149:[2,152],150:[2,152],151:[2,152],152:[2,152],153:[2,152],154:[2,152],155:[2,152],156:[2,152],157:[2,152],158:[2,152],159:[2,152],160:[2,152],161:[2,152],162:[2,152],165:[2,152],166:[2,152],167:[2,152],169:[2,152],170:[2,152],185:[2,152],188:[2,152],194:[2,152],196:[2,152],198:[2,152],200:[2,152]},{6:[2,153],8:[2,153],10:[2,153],49:[2,153],50:[2,153],51:[2,153],53:[2,153],56:[2,153],57:[2,153],58:[2,153],59:[2,153],60:[2,
-153],61:[2,153],62:[2,153],63:[2,153],64:[2,153],65:[2,153],66:[2,153],67:[2,153],68:[2,153],69:[2,153],70:[2,153],71:[2,153],72:[2,153],73:[2,153],74:[2,153],75:[2,153],76:[2,153],77:[2,153],78:[2,153],79:[2,153],81:[2,153],82:[2,153],83:[2,153],84:[2,153],85:[2,153],86:[2,153],87:[2,153],88:[2,153],89:[2,153],90:[2,153],91:[2,153],92:[2,153],93:[2,153],94:[2,153],95:[2,153],96:[2,153],97:[2,153],98:[2,153],99:[2,153],100:[2,153],101:[2,153],102:[2,153],103:[2,153],104:[2,153],105:[2,153],106:[2,
-153],107:[2,153],108:[2,153],109:[2,153],110:[2,153],111:[2,153],112:[2,153],113:[2,153],114:[2,153],115:[2,153],116:[2,153],117:[2,153],118:[2,153],119:[2,153],120:[2,153],121:[2,153],122:[2,153],123:[2,153],124:[2,153],125:[2,153],126:[2,153],127:[2,153],128:[2,153],129:[2,153],130:[2,153],131:[2,153],132:[2,153],134:[2,153],135:[2,153],137:[2,153],138:[2,153],140:[2,153],141:[2,153],142:[2,153],143:[2,153],144:[2,153],145:[2,153],146:[2,153],147:[2,153],148:[2,153],149:[2,153],150:[2,153],151:[2,
-153],152:[2,153],153:[2,153],154:[2,153],155:[2,153],156:[2,153],157:[2,153],158:[2,153],159:[2,153],160:[2,153],161:[2,153],162:[2,153],165:[2,153],166:[2,153],167:[2,153],169:[2,153],170:[2,153],185:[2,153],188:[2,153],194:[2,153],196:[2,153],198:[2,153],200:[2,153]},{6:[2,154],8:[2,154],10:[2,154],49:[2,154],50:[2,154],51:[2,154],53:[2,154],56:[2,154],57:[2,154],58:[2,154],59:[2,154],60:[2,154],61:[2,154],62:[2,154],63:[2,154],64:[2,154],65:[2,154],66:[2,154],67:[2,154],68:[2,154],69:[2,154],70:[2,
-154],71:[2,154],72:[2,154],73:[2,154],74:[2,154],75:[2,154],76:[2,154],77:[2,154],78:[2,154],79:[2,154],81:[2,154],82:[2,154],83:[2,154],84:[2,154],85:[2,154],86:[2,154],87:[2,154],88:[2,154],89:[2,154],90:[2,154],91:[2,154],92:[2,154],93:[2,154],94:[2,154],95:[2,154],96:[2,154],97:[2,154],98:[2,154],99:[2,154],100:[2,154],101:[2,154],102:[2,154],103:[2,154],104:[2,154],105:[2,154],106:[2,154],107:[2,154],108:[2,154],109:[2,154],110:[2,154],111:[2,154],112:[2,154],113:[2,154],114:[2,154],115:[2,154],
-116:[2,154],117:[2,154],118:[2,154],119:[2,154],120:[2,154],121:[2,154],122:[2,154],123:[2,154],124:[2,154],125:[2,154],126:[2,154],127:[2,154],128:[2,154],129:[2,154],130:[2,154],131:[2,154],132:[2,154],134:[2,154],135:[2,154],137:[2,154],138:[2,154],140:[2,154],141:[2,154],142:[2,154],143:[2,154],144:[2,154],145:[2,154],146:[2,154],147:[2,154],148:[2,154],149:[2,154],150:[2,154],151:[2,154],152:[2,154],153:[2,154],154:[2,154],155:[2,154],156:[2,154],157:[2,154],158:[2,154],159:[2,154],160:[2,154],
-161:[2,154],162:[2,154],165:[2,154],166:[2,154],167:[2,154],169:[2,154],170:[2,154],185:[2,154],188:[2,154],194:[2,154],196:[2,154],198:[2,154],200:[2,154]},{18:384,19:[1,394],20:385,21:[1,338],22:386,23:[1,339],28:387,29:[1,395],30:388,31:[1,396],32:389,33:[1,397],34:390,35:[1,398],36:391,37:[1,399],38:392,39:[1,400],40:393,41:[1,401],45:383,46:382},{6:[2,137],8:[2,137],10:[2,137],49:[2,137],50:[2,137],51:[2,137],53:[2,137],56:[2,137],57:[2,137],58:[2,137],59:[2,137],60:[2,137],61:[2,137],62:[2,
-137],63:[2,137],64:[2,137],65:[2,137],66:[2,137],67:[2,137],68:[2,137],69:[2,137],70:[2,137],71:[2,137],72:[2,137],73:[2,137],74:[2,137],75:[2,137],76:[2,137],77:[2,137],78:[2,137],79:[2,137],81:[2,137],82:[2,137],83:[2,137],84:[2,137],85:[2,137],86:[2,137],87:[2,137],88:[2,137],89:[2,137],90:[2,137],91:[2,137],92:[2,137],93:[2,137],94:[2,137],95:[2,137],96:[2,137],97:[2,137],98:[2,137],99:[2,137],100:[2,137],101:[2,137],102:[2,137],103:[2,137],104:[2,137],105:[2,137],106:[2,137],107:[2,137],108:[2,
-137],109:[2,137],110:[2,137],111:[2,137],112:[2,137],113:[2,137],114:[2,137],115:[2,137],116:[2,137],117:[2,137],118:[2,137],119:[2,137],120:[2,137],121:[2,137],122:[2,137],123:[2,137],124:[2,137],125:[2,137],126:[2,137],127:[2,137],128:[2,137],129:[2,137],130:[2,137],131:[2,137],132:[2,137],134:[2,137],135:[2,137],137:[2,137],138:[2,137],140:[2,137],141:[2,137],142:[2,137],143:[2,137],144:[2,137],145:[2,137],146:[2,137],147:[2,137],148:[2,137],149:[2,137],150:[2,137],151:[2,137],152:[2,137],153:[2,
-137],154:[2,137],155:[2,137],156:[2,137],157:[2,137],158:[2,137],159:[2,137],160:[2,137],161:[2,137],162:[2,137],165:[2,137],166:[2,137],167:[2,137],169:[2,137],170:[2,137],185:[2,137],188:[2,137],194:[2,137],196:[2,137],198:[2,137],200:[2,137]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:304,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,
-50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],
-128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,132],137:[1,103],138:[1,104],141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],168:305,169:[1,117],170:[1,118],172:402},{6:[2,181],8:[2,181],10:[2,181],49:[2,181],50:[2,181],51:[2,181],53:[2,181],56:[2,181],57:[2,181],58:[2,181],59:[2,181],60:[2,181],61:[2,181],62:[2,181],63:[2,181],64:[2,181],65:[2,181],66:[2,181],67:[2,181],68:[2,181],69:[2,
-181],70:[2,181],71:[2,181],72:[2,181],73:[2,181],74:[2,181],75:[2,181],76:[2,181],77:[2,181],78:[2,181],79:[2,181],81:[2,181],82:[2,181],83:[2,181],84:[2,181],85:[2,181],86:[2,181],87:[2,181],88:[2,181],89:[2,181],90:[2,181],91:[2,181],92:[2,181],93:[2,181],94:[2,181],95:[2,181],96:[2,181],97:[2,181],98:[2,181],99:[2,181],100:[2,181],101:[2,181],102:[2,181],103:[2,181],104:[2,181],105:[2,181],106:[2,181],107:[2,181],108:[2,181],109:[2,181],110:[2,181],111:[2,181],112:[2,181],113:[2,181],114:[2,181],
-115:[2,181],116:[2,181],117:[2,181],118:[2,181],119:[2,181],120:[2,181],121:[2,181],122:[2,181],123:[2,181],124:[2,181],125:[2,181],126:[2,181],127:[2,181],128:[2,181],129:[2,181],130:[2,181],131:[2,181],132:[2,181],135:[2,181],137:[2,181],138:[2,181],140:[2,181],141:[2,181],142:[2,181],143:[2,181],144:[2,181],145:[2,181],146:[2,181],147:[2,181],148:[2,181],149:[2,181],150:[2,181],151:[2,181],152:[2,181],153:[2,181],154:[2,181],155:[2,181],156:[2,181],157:[2,181],158:[2,181],159:[2,181],160:[2,181],
-161:[2,181],162:[2,181],165:[2,181],166:[2,181],169:[2,181],170:[2,181],185:[2,181],188:[2,181],194:[2,181],196:[2,181],198:[2,181],200:[2,181]},{6:[2,159],8:[2,159],10:[2,159],49:[2,159],50:[2,159],51:[2,159],53:[2,159],56:[2,159],57:[2,159],58:[2,159],59:[2,159],60:[2,159],61:[2,159],62:[2,159],63:[2,159],64:[2,159],65:[2,159],66:[2,159],67:[2,159],68:[2,159],69:[2,159],70:[2,159],71:[2,159],72:[2,159],73:[2,159],74:[2,159],75:[2,159],76:[2,159],77:[2,159],78:[2,159],79:[2,159],81:[2,159],82:[2,
-159],83:[2,159],84:[2,159],85:[2,159],86:[2,159],87:[2,159],88:[2,159],89:[2,159],90:[2,159],91:[2,159],92:[2,159],93:[2,159],94:[2,159],95:[2,159],96:[2,159],97:[2,159],98:[2,159],99:[2,159],100:[2,159],101:[2,159],102:[2,159],103:[2,159],104:[2,159],105:[2,159],106:[2,159],107:[2,159],108:[2,159],109:[2,159],110:[2,159],111:[2,159],112:[2,159],113:[2,159],114:[2,159],115:[2,159],116:[2,159],117:[2,159],118:[2,159],119:[2,159],120:[2,159],121:[2,159],122:[2,159],123:[2,159],124:[2,159],125:[2,159],
-126:[2,159],127:[2,159],128:[2,159],129:[2,159],130:[2,159],131:[2,159],132:[2,159],135:[2,159],137:[2,159],138:[2,159],140:[2,159],141:[2,159],142:[2,159],143:[2,159],144:[2,159],145:[2,159],146:[2,159],147:[2,159],148:[2,159],149:[2,159],150:[2,159],151:[2,159],152:[2,159],153:[2,159],154:[2,159],155:[2,159],156:[2,159],157:[2,159],158:[2,159],159:[2,159],160:[2,159],161:[2,159],162:[2,159],169:[2,159],170:[2,159],185:[2,159],188:[2,159],194:[2,159],196:[2,159],198:[2,159],200:[2,159]},{6:[2,161],
-8:[2,161],10:[2,161],49:[2,161],50:[2,161],51:[2,161],53:[2,161],56:[2,161],57:[2,161],58:[2,161],59:[2,161],60:[2,161],61:[2,161],62:[2,161],63:[2,161],64:[2,161],65:[2,161],66:[2,161],67:[2,161],68:[2,161],69:[2,161],70:[2,161],71:[2,161],72:[2,161],73:[2,161],74:[2,161],75:[2,161],76:[2,161],77:[2,161],78:[2,161],79:[2,161],81:[2,161],82:[2,161],83:[2,161],84:[2,161],85:[2,161],86:[2,161],87:[2,161],88:[2,161],89:[2,161],90:[2,161],91:[2,161],92:[2,161],93:[2,161],94:[2,161],95:[2,161],96:[2,161],
-97:[2,161],98:[2,161],99:[2,161],100:[2,161],101:[2,161],102:[2,161],103:[2,161],104:[2,161],105:[2,161],106:[2,161],107:[2,161],108:[2,161],109:[2,161],110:[2,161],111:[2,161],112:[2,161],113:[2,161],114:[2,161],115:[2,161],116:[2,161],117:[2,161],118:[2,161],119:[2,161],120:[2,161],121:[2,161],122:[2,161],123:[2,161],124:[2,161],125:[2,161],126:[2,161],127:[2,161],128:[2,161],129:[2,161],130:[2,161],131:[2,161],132:[2,161],135:[2,161],137:[2,161],138:[2,161],140:[2,161],141:[2,161],142:[2,161],
-143:[2,161],144:[2,161],145:[2,161],146:[2,161],147:[2,161],148:[2,161],149:[2,161],150:[2,161],151:[2,161],152:[2,161],153:[2,161],154:[2,161],155:[2,161],156:[2,161],157:[2,161],158:[2,161],159:[2,161],160:[2,161],161:[2,161],162:[2,161],169:[2,161],170:[2,161],185:[2,161],188:[2,161],194:[2,161],196:[2,161],198:[2,161],200:[2,161]},{6:[2,167],8:[2,167],10:[2,167],49:[2,167],50:[2,167],51:[2,167],53:[2,167],56:[2,167],57:[2,167],58:[2,167],59:[2,167],60:[2,167],61:[2,167],62:[2,167],63:[2,167],
-64:[2,167],65:[2,167],66:[2,167],67:[2,167],68:[2,167],69:[2,167],70:[2,167],71:[2,167],72:[2,167],73:[2,167],74:[2,167],75:[2,167],76:[2,167],77:[2,167],78:[2,167],79:[2,167],81:[2,167],82:[2,167],83:[2,167],84:[2,167],85:[2,167],86:[2,167],87:[2,167],88:[2,167],89:[2,167],90:[2,167],91:[2,167],92:[2,167],93:[2,167],94:[2,167],95:[2,167],96:[2,167],97:[2,167],98:[2,167],99:[2,167],100:[2,167],101:[2,167],102:[2,167],103:[2,167],104:[2,167],105:[2,167],106:[2,167],107:[2,167],108:[2,167],109:[2,167],
-110:[2,167],111:[2,167],112:[2,167],113:[2,167],114:[2,167],115:[2,167],116:[2,167],117:[2,167],118:[2,167],119:[2,167],120:[2,167],121:[2,167],122:[2,167],123:[2,167],124:[2,167],125:[2,167],126:[2,167],127:[2,167],128:[2,167],129:[2,167],130:[2,167],131:[2,167],132:[2,167],135:[2,167],137:[2,167],138:[2,167],140:[2,167],141:[2,167],142:[2,167],143:[2,167],144:[2,167],145:[2,167],146:[2,167],147:[2,167],148:[2,167],149:[2,167],150:[2,167],151:[2,167],152:[2,167],153:[2,167],154:[2,167],155:[2,167],
-156:[2,167],157:[2,167],158:[2,167],159:[2,167],160:[2,167],161:[2,167],162:[2,167],169:[2,167],170:[2,167],185:[2,167],188:[2,167],194:[2,167],196:[2,167],198:[2,167],200:[2,167]},{6:[2,168],8:[2,168],10:[2,168],49:[2,168],50:[2,168],51:[2,168],53:[2,168],56:[2,168],57:[2,168],58:[2,168],59:[2,168],60:[2,168],61:[2,168],62:[2,168],63:[2,168],64:[2,168],65:[2,168],66:[2,168],67:[2,168],68:[2,168],69:[2,168],70:[2,168],71:[2,168],72:[2,168],73:[2,168],74:[2,168],75:[2,168],76:[2,168],77:[2,168],78:[2,
-168],79:[2,168],81:[2,168],82:[2,168],83:[2,168],84:[2,168],85:[2,168],86:[2,168],87:[2,168],88:[2,168],89:[2,168],90:[2,168],91:[2,168],92:[2,168],93:[2,168],94:[2,168],95:[2,168],96:[2,168],97:[2,168],98:[2,168],99:[2,168],100:[2,168],101:[2,168],102:[2,168],103:[2,168],104:[2,168],105:[2,168],106:[2,168],107:[2,168],108:[2,168],109:[2,168],110:[2,168],111:[2,168],112:[2,168],113:[2,168],114:[2,168],115:[2,168],116:[2,168],117:[2,168],118:[2,168],119:[2,168],120:[2,168],121:[2,168],122:[2,168],
-123:[2,168],124:[2,168],125:[2,168],126:[2,168],127:[2,168],128:[2,168],129:[2,168],130:[2,168],131:[2,168],132:[2,168],135:[2,168],137:[2,168],138:[2,168],140:[2,168],141:[2,168],142:[2,168],143:[2,168],144:[2,168],145:[2,168],146:[2,168],147:[2,168],148:[2,168],149:[2,168],150:[2,168],151:[2,168],152:[2,168],153:[2,168],154:[2,168],155:[2,168],156:[2,168],157:[2,168],158:[2,168],159:[2,168],160:[2,168],161:[2,168],162:[2,168],169:[2,168],170:[2,168],185:[2,168],188:[2,168],194:[2,168],196:[2,168],
-198:[2,168],200:[2,168]},{6:[2,59],8:[2,59],10:[2,59],49:[2,59],50:[2,59],51:[2,59],53:[2,59],56:[2,59],57:[2,59],58:[2,59],59:[2,59],60:[2,59],61:[2,59],62:[2,59],63:[2,59],64:[2,59],65:[2,59],66:[2,59],67:[2,59],68:[2,59],69:[2,59],70:[2,59],71:[2,59],72:[2,59],73:[2,59],74:[2,59],75:[2,59],76:[2,59],77:[2,59],78:[2,59],79:[2,59],81:[2,59],82:[2,59],83:[2,59],84:[2,59],85:[2,59],86:[2,59],87:[2,59],88:[2,59],89:[2,59],90:[2,59],91:[2,59],92:[2,59],93:[2,59],94:[2,59],95:[2,59],96:[2,59],97:[2,59],
-98:[2,59],99:[2,59],100:[2,59],101:[2,59],102:[2,59],103:[2,59],104:[2,59],105:[2,59],106:[2,59],107:[2,59],108:[2,59],109:[2,59],110:[2,59],111:[2,59],112:[2,59],113:[2,59],114:[2,59],115:[2,59],116:[2,59],117:[2,59],118:[2,59],119:[2,59],120:[2,59],121:[2,59],122:[2,59],123:[2,59],124:[2,59],125:[2,59],126:[2,59],127:[2,59],128:[2,59],129:[2,59],130:[2,59],131:[2,59],132:[2,59],134:[2,59],135:[2,59],137:[2,59],138:[2,59],140:[2,59],141:[2,59],142:[2,59],143:[2,59],144:[2,59],145:[2,59],146:[2,59],
-147:[2,59],148:[2,59],149:[2,59],150:[2,59],151:[2,59],152:[2,59],153:[2,59],154:[2,59],155:[2,59],156:[2,59],157:[2,59],158:[2,59],159:[2,59],160:[2,59],161:[2,59],162:[2,59],165:[2,59],166:[2,59],167:[2,59],169:[2,59],170:[2,59],185:[2,59],188:[2,59],194:[2,59],196:[2,59],198:[2,59],200:[2,59]},{6:[2,61],8:[2,61],10:[2,61],49:[2,61],50:[2,61],51:[2,61],53:[2,61],56:[2,61],57:[2,61],58:[2,61],59:[2,61],60:[2,61],61:[2,61],62:[2,61],63:[2,61],64:[2,61],65:[2,61],66:[2,61],67:[2,61],68:[2,61],69:[2,
-61],70:[2,61],71:[2,61],72:[2,61],73:[2,61],74:[2,61],75:[2,61],76:[2,61],77:[2,61],78:[2,61],79:[2,61],81:[2,61],82:[2,61],83:[2,61],84:[2,61],85:[2,61],86:[2,61],87:[2,61],88:[2,61],89:[2,61],90:[2,61],91:[2,61],92:[2,61],93:[2,61],94:[2,61],95:[2,61],96:[2,61],97:[2,61],98:[2,61],99:[2,61],100:[2,61],101:[2,61],102:[2,61],103:[2,61],104:[2,61],105:[2,61],106:[2,61],107:[2,61],108:[2,61],109:[2,61],110:[2,61],111:[2,61],112:[2,61],113:[2,61],114:[2,61],115:[2,61],116:[2,61],117:[2,61],118:[2,61],
-119:[2,61],120:[2,61],121:[2,61],122:[2,61],123:[2,61],124:[2,61],125:[2,61],126:[2,61],127:[2,61],128:[2,61],129:[2,61],130:[2,61],131:[2,61],132:[2,61],134:[2,61],135:[2,61],137:[2,61],138:[2,61],140:[2,61],141:[2,61],142:[2,61],143:[2,61],144:[2,61],145:[2,61],146:[2,61],147:[2,61],148:[2,61],149:[2,61],150:[2,61],151:[2,61],152:[2,61],153:[2,61],154:[2,61],155:[2,61],156:[2,61],157:[2,61],158:[2,61],159:[2,61],160:[2,61],161:[2,61],162:[2,61],165:[2,61],166:[2,61],167:[2,61],169:[2,61],170:[2,
-61],185:[2,61],188:[2,61],194:[2,61],196:[2,61],198:[2,61],200:[2,61]},{6:[2,63],8:[2,63],10:[2,63],49:[2,63],50:[2,63],51:[2,63],53:[2,63],56:[2,63],57:[2,63],58:[2,63],59:[2,63],60:[2,63],61:[2,63],62:[2,63],63:[2,63],64:[2,63],65:[2,63],66:[2,63],67:[2,63],68:[2,63],69:[2,63],70:[2,63],71:[2,63],72:[2,63],73:[2,63],74:[2,63],75:[2,63],76:[2,63],77:[2,63],78:[2,63],79:[2,63],81:[2,63],82:[2,63],83:[2,63],84:[2,63],85:[2,63],86:[2,63],87:[2,63],88:[2,63],89:[2,63],90:[2,63],91:[2,63],92:[2,63],93:[2,
-63],94:[2,63],95:[2,63],96:[2,63],97:[2,63],98:[2,63],99:[2,63],100:[2,63],101:[2,63],102:[2,63],103:[2,63],104:[2,63],105:[2,63],106:[2,63],107:[2,63],108:[2,63],109:[2,63],110:[2,63],111:[2,63],112:[2,63],113:[2,63],114:[2,63],115:[2,63],116:[2,63],117:[2,63],118:[2,63],119:[2,63],120:[2,63],121:[2,63],122:[2,63],123:[2,63],124:[2,63],125:[2,63],126:[2,63],127:[2,63],128:[2,63],129:[2,63],130:[2,63],131:[2,63],132:[2,63],134:[2,63],135:[2,63],137:[2,63],138:[2,63],140:[2,63],141:[2,63],142:[2,63],
-143:[2,63],144:[2,63],145:[2,63],146:[2,63],147:[2,63],148:[2,63],149:[2,63],150:[2,63],151:[2,63],152:[2,63],153:[2,63],154:[2,63],155:[2,63],156:[2,63],157:[2,63],158:[2,63],159:[2,63],160:[2,63],161:[2,63],162:[2,63],165:[2,63],166:[2,63],167:[2,63],169:[2,63],170:[2,63],185:[2,63],188:[2,63],194:[2,63],196:[2,63],198:[2,63],200:[2,63]},{6:[2,60],8:[2,60],10:[2,60],49:[2,60],50:[2,60],51:[2,60],53:[2,60],56:[2,60],57:[2,60],58:[2,60],59:[2,60],60:[2,60],61:[2,60],62:[2,60],63:[2,60],64:[2,60],
-65:[2,60],66:[2,60],67:[2,60],68:[2,60],69:[2,60],70:[2,60],71:[2,60],72:[2,60],73:[2,60],74:[2,60],75:[2,60],76:[2,60],77:[2,60],78:[2,60],79:[2,60],81:[2,60],82:[2,60],83:[2,60],84:[2,60],85:[2,60],86:[2,60],87:[2,60],88:[2,60],89:[2,60],90:[2,60],91:[2,60],92:[2,60],93:[2,60],94:[2,60],95:[2,60],96:[2,60],97:[2,60],98:[2,60],99:[2,60],100:[2,60],101:[2,60],102:[2,60],103:[2,60],104:[2,60],105:[2,60],106:[2,60],107:[2,60],108:[2,60],109:[2,60],110:[2,60],111:[2,60],112:[2,60],113:[2,60],114:[2,
-60],115:[2,60],116:[2,60],117:[2,60],118:[2,60],119:[2,60],120:[2,60],121:[2,60],122:[2,60],123:[2,60],124:[2,60],125:[2,60],126:[2,60],127:[2,60],128:[2,60],129:[2,60],130:[2,60],131:[2,60],132:[2,60],134:[2,60],135:[2,60],137:[2,60],138:[2,60],140:[2,60],141:[2,60],142:[2,60],143:[2,60],144:[2,60],145:[2,60],146:[2,60],147:[2,60],148:[2,60],149:[2,60],150:[2,60],151:[2,60],152:[2,60],153:[2,60],154:[2,60],155:[2,60],156:[2,60],157:[2,60],158:[2,60],159:[2,60],160:[2,60],161:[2,60],162:[2,60],165:[2,
-60],166:[2,60],167:[2,60],169:[2,60],170:[2,60],185:[2,60],188:[2,60],194:[2,60],196:[2,60],198:[2,60],200:[2,60]},{6:[2,62],8:[2,62],10:[2,62],49:[2,62],50:[2,62],51:[2,62],53:[2,62],56:[2,62],57:[2,62],58:[2,62],59:[2,62],60:[2,62],61:[2,62],62:[2,62],63:[2,62],64:[2,62],65:[2,62],66:[2,62],67:[2,62],68:[2,62],69:[2,62],70:[2,62],71:[2,62],72:[2,62],73:[2,62],74:[2,62],75:[2,62],76:[2,62],77:[2,62],78:[2,62],79:[2,62],81:[2,62],82:[2,62],83:[2,62],84:[2,62],85:[2,62],86:[2,62],87:[2,62],88:[2,62],
-89:[2,62],90:[2,62],91:[2,62],92:[2,62],93:[2,62],94:[2,62],95:[2,62],96:[2,62],97:[2,62],98:[2,62],99:[2,62],100:[2,62],101:[2,62],102:[2,62],103:[2,62],104:[2,62],105:[2,62],106:[2,62],107:[2,62],108:[2,62],109:[2,62],110:[2,62],111:[2,62],112:[2,62],113:[2,62],114:[2,62],115:[2,62],116:[2,62],117:[2,62],118:[2,62],119:[2,62],120:[2,62],121:[2,62],122:[2,62],123:[2,62],124:[2,62],125:[2,62],126:[2,62],127:[2,62],128:[2,62],129:[2,62],130:[2,62],131:[2,62],132:[2,62],134:[2,62],135:[2,62],137:[2,
-62],138:[2,62],140:[2,62],141:[2,62],142:[2,62],143:[2,62],144:[2,62],145:[2,62],146:[2,62],147:[2,62],148:[2,62],149:[2,62],150:[2,62],151:[2,62],152:[2,62],153:[2,62],154:[2,62],155:[2,62],156:[2,62],157:[2,62],158:[2,62],159:[2,62],160:[2,62],161:[2,62],162:[2,62],165:[2,62],166:[2,62],167:[2,62],169:[2,62],170:[2,62],185:[2,62],188:[2,62],194:[2,62],196:[2,62],198:[2,62],200:[2,62]},{6:[2,64],8:[2,64],10:[2,64],49:[2,64],50:[2,64],51:[2,64],53:[2,64],56:[2,64],57:[2,64],58:[2,64],59:[2,64],60:[2,
-64],61:[2,64],62:[2,64],63:[2,64],64:[2,64],65:[2,64],66:[2,64],67:[2,64],68:[2,64],69:[2,64],70:[2,64],71:[2,64],72:[2,64],73:[2,64],74:[2,64],75:[2,64],76:[2,64],77:[2,64],78:[2,64],79:[2,64],81:[2,64],82:[2,64],83:[2,64],84:[2,64],85:[2,64],86:[2,64],87:[2,64],88:[2,64],89:[2,64],90:[2,64],91:[2,64],92:[2,64],93:[2,64],94:[2,64],95:[2,64],96:[2,64],97:[2,64],98:[2,64],99:[2,64],100:[2,64],101:[2,64],102:[2,64],103:[2,64],104:[2,64],105:[2,64],106:[2,64],107:[2,64],108:[2,64],109:[2,64],110:[2,
-64],111:[2,64],112:[2,64],113:[2,64],114:[2,64],115:[2,64],116:[2,64],117:[2,64],118:[2,64],119:[2,64],120:[2,64],121:[2,64],122:[2,64],123:[2,64],124:[2,64],125:[2,64],126:[2,64],127:[2,64],128:[2,64],129:[2,64],130:[2,64],131:[2,64],132:[2,64],134:[2,64],135:[2,64],137:[2,64],138:[2,64],140:[2,64],141:[2,64],142:[2,64],143:[2,64],144:[2,64],145:[2,64],146:[2,64],147:[2,64],148:[2,64],149:[2,64],150:[2,64],151:[2,64],152:[2,64],153:[2,64],154:[2,64],155:[2,64],156:[2,64],157:[2,64],158:[2,64],159:[2,
-64],160:[2,64],161:[2,64],162:[2,64],165:[2,64],166:[2,64],167:[2,64],169:[2,64],170:[2,64],185:[2,64],188:[2,64],194:[2,64],196:[2,64],198:[2,64],200:[2,64]},{6:[2,89],8:[2,89],10:[2,89],49:[2,89],50:[2,89],51:[2,89],53:[2,89],56:[2,89],57:[2,89],58:[2,89],59:[2,89],60:[2,89],61:[2,89],62:[2,89],63:[2,89],64:[2,89],65:[2,89],66:[2,89],67:[2,89],68:[2,89],69:[2,89],70:[2,89],71:[2,89],72:[2,89],73:[2,89],74:[2,89],75:[2,89],76:[2,89],77:[2,89],78:[2,89],79:[2,89],81:[2,89],82:[2,89],83:[2,89],84:[2,
-89],85:[2,89],86:[2,89],87:[2,89],88:[2,89],89:[2,89],90:[2,89],91:[2,89],92:[2,89],93:[2,89],94:[2,89],95:[2,89],96:[2,89],97:[2,89],98:[2,89],99:[2,89],100:[2,89],101:[2,89],102:[2,89],103:[2,89],104:[2,89],105:[2,89],106:[2,89],107:[2,89],108:[2,89],109:[2,89],110:[2,89],111:[2,89],112:[2,89],113:[2,89],114:[2,89],115:[2,89],116:[2,89],117:[2,89],118:[2,89],119:[2,89],120:[2,89],121:[2,89],122:[2,89],123:[2,89],124:[2,89],125:[2,89],126:[2,89],127:[2,89],128:[2,89],129:[2,89],130:[2,89],131:[2,
-89],132:[2,89],134:[2,89],135:[2,89],137:[2,89],138:[2,89],140:[2,89],141:[2,89],142:[2,89],143:[2,89],144:[2,89],145:[2,89],146:[2,89],147:[2,89],148:[2,89],149:[2,89],150:[2,89],151:[2,89],152:[2,89],153:[2,89],154:[2,89],155:[2,89],156:[2,89],157:[2,89],158:[2,89],159:[2,89],160:[2,89],161:[2,89],162:[2,89],165:[2,89],166:[2,89],167:[2,89],169:[2,89],170:[2,89],185:[2,89],188:[2,89],194:[2,89],196:[2,89],198:[2,89],200:[2,89]},{6:[2,93],8:[2,93],10:[2,93],49:[2,93],50:[2,93],51:[2,93],53:[2,93],
-56:[2,93],57:[2,93],58:[2,93],59:[2,93],60:[2,93],61:[2,93],62:[2,93],63:[2,93],64:[2,93],65:[2,93],66:[2,93],67:[2,93],68:[2,93],69:[2,93],70:[2,93],71:[2,93],72:[2,93],73:[2,93],74:[2,93],75:[2,93],76:[2,93],77:[2,93],78:[2,93],79:[2,93],81:[2,93],82:[2,93],83:[2,93],84:[2,93],85:[2,93],86:[2,93],87:[2,93],88:[2,93],89:[2,93],90:[2,93],91:[2,93],92:[2,93],93:[2,93],94:[2,93],95:[2,93],96:[2,93],97:[2,93],98:[2,93],99:[2,93],100:[2,93],101:[2,93],102:[2,93],103:[2,93],104:[2,93],105:[2,93],106:[2,
-93],107:[2,93],108:[2,93],109:[2,93],110:[2,93],111:[2,93],112:[2,93],113:[2,93],114:[2,93],115:[2,93],116:[2,93],117:[2,93],118:[2,93],119:[2,93],120:[2,93],121:[2,93],122:[2,93],123:[2,93],124:[2,93],125:[2,93],126:[2,93],127:[2,93],128:[2,93],129:[2,93],130:[2,93],131:[2,93],132:[2,93],134:[2,93],135:[2,93],137:[2,93],138:[2,93],140:[2,93],141:[2,93],142:[2,93],143:[2,93],144:[2,93],145:[2,93],146:[2,93],147:[2,93],148:[2,93],149:[2,93],150:[2,93],151:[2,93],152:[2,93],153:[2,93],154:[2,93],155:[2,
-93],156:[2,93],157:[2,93],158:[2,93],159:[2,93],160:[2,93],161:[2,93],162:[2,93],165:[2,93],166:[2,93],167:[2,93],169:[2,93],170:[2,93],185:[2,93],188:[2,93],194:[2,93],196:[2,93],198:[2,93],200:[2,93]},{6:[2,119],8:[2,119],10:[2,119],49:[2,119],50:[2,119],51:[2,119],53:[2,119],56:[2,119],57:[2,119],58:[2,119],59:[2,119],60:[2,119],61:[2,119],62:[2,119],63:[2,119],64:[2,119],65:[2,119],66:[2,119],67:[2,119],68:[2,119],69:[2,119],70:[2,119],71:[2,119],72:[2,119],73:[2,119],74:[2,119],75:[2,119],76:[2,
-119],77:[2,119],78:[2,119],79:[2,119],81:[2,119],82:[2,119],83:[2,119],84:[2,119],85:[2,119],86:[2,119],87:[2,119],88:[2,119],89:[2,119],90:[2,119],91:[2,119],92:[2,119],93:[2,119],94:[2,119],95:[2,119],96:[2,119],97:[2,119],98:[2,119],99:[2,119],100:[2,119],101:[2,119],102:[2,119],103:[2,119],104:[2,119],105:[2,119],106:[2,119],107:[2,119],108:[2,119],109:[2,119],110:[2,119],111:[2,119],112:[2,119],113:[2,119],114:[2,119],115:[2,119],116:[2,119],117:[2,119],118:[2,119],119:[2,119],120:[2,119],121:[2,
-119],122:[2,119],123:[2,119],124:[2,119],125:[2,119],126:[2,119],127:[2,119],128:[2,119],129:[2,119],130:[2,119],131:[2,119],132:[2,119],134:[2,119],135:[2,119],137:[2,119],138:[2,119],140:[2,119],141:[2,119],142:[2,119],143:[2,119],144:[2,119],145:[2,119],146:[2,119],147:[2,119],148:[2,119],149:[2,119],150:[2,119],151:[2,119],152:[2,119],153:[2,119],154:[2,119],155:[2,119],156:[2,119],157:[2,119],158:[2,119],159:[2,119],160:[2,119],161:[2,119],162:[2,119],165:[2,119],166:[2,119],167:[2,119],169:[2,
-119],170:[2,119],185:[2,119],188:[2,119],194:[2,119],196:[2,119],198:[2,119],200:[2,119]},{4:[2,3],8:[2,3],49:[2,3],50:[2,3],51:[2,3],56:[2,3],57:[2,3],58:[2,3],59:[2,3],60:[2,3],61:[2,3],62:[2,3],63:[2,3],67:[2,3],68:[2,3],69:[2,3],70:[2,3],71:[2,3],72:[2,3],73:[2,3],74:[2,3],75:[2,3],76:[2,3],77:[2,3],78:[2,3],79:[2,3],81:[2,3],82:[2,3],83:[2,3],84:[2,3],85:[2,3],86:[2,3],87:[2,3],88:[2,3],89:[2,3],90:[2,3],91:[2,3],92:[2,3],93:[2,3],94:[2,3],95:[2,3],96:[2,3],97:[2,3],98:[2,3],99:[2,3],100:[2,
-3],101:[2,3],102:[2,3],103:[2,3],104:[2,3],105:[2,3],106:[2,3],107:[2,3],108:[2,3],109:[2,3],110:[2,3],111:[2,3],112:[2,3],113:[2,3],114:[2,3],115:[2,3],116:[2,3],117:[2,3],118:[2,3],119:[2,3],120:[2,3],121:[2,3],122:[2,3],123:[2,3],124:[2,3],125:[2,3],126:[2,3],127:[2,3],128:[2,3],129:[2,3],130:[2,3],131:[2,3],132:[2,3],135:[2,3],137:[2,3],138:[2,3],141:[2,3],143:[2,3],145:[2,3],147:[2,3],149:[2,3],151:[2,3],153:[2,3],155:[2,3],157:[2,3],159:[2,3],161:[2,3],162:[2,3]},{8:[1,403]},{136:404,165:[1,
-238],166:[1,239],173:237},{8:[1,26],10:[2,193],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:213,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,
-70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],140:[2,193],141:[1,105],142:[2,193],143:[1,106],144:[2,193],145:[1,107],146:[2,193],147:[1,108],148:[2,193],
-149:[1,109],150:[2,193],151:[1,110],152:[2,193],153:[1,111],154:[2,193],155:[1,112],156:[2,193],157:[1,113],158:[2,193],159:[1,114],160:[2,193],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21],182:211,183:[1,212],184:405,185:[2,193],188:[2,193]},{10:[2,43],21:[2,43],23:[2,43]},{10:[2,11],19:[2,11],21:[2,11],23:[2,11],25:[2,11],27:[2,11],29:[2,11],31:[2,11],33:[2,11],35:[2,11],37:[2,11],39:[2,11],
-41:[2,11]},{10:[2,12],19:[2,12],21:[2,12],23:[2,12],25:[2,12],27:[2,12],29:[2,12],31:[2,12],33:[2,12],35:[2,12],37:[2,12],39:[2,12],41:[2,12]},{8:[1,26],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:406,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],
-90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],
-141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21]},{10:[2,27],21:[2,27],23:[2,27],25:[2,27],27:[2,27]},{10:[2,13],21:[2,13],23:[2,13],25:[2,13],27:[2,13]},{10:[2,14],21:[2,14],23:[2,14],25:[2,14],27:[2,14]},{6:[2,151],8:[2,151],10:[2,151],49:[2,151],50:[2,151],51:[2,151],53:[2,
-151],56:[2,151],57:[2,151],58:[2,151],59:[2,151],60:[2,151],61:[2,151],62:[2,151],63:[2,151],64:[2,151],65:[2,151],66:[2,151],67:[2,151],68:[2,151],69:[2,151],70:[2,151],71:[2,151],72:[2,151],73:[2,151],74:[2,151],75:[2,151],76:[2,151],77:[2,151],78:[2,151],79:[2,151],81:[2,151],82:[2,151],83:[2,151],84:[2,151],85:[2,151],86:[2,151],87:[2,151],88:[2,151],89:[2,151],90:[2,151],91:[2,151],92:[2,151],93:[2,151],94:[2,151],95:[2,151],96:[2,151],97:[2,151],98:[2,151],99:[2,151],100:[2,151],101:[2,151],
-102:[2,151],103:[2,151],104:[2,151],105:[2,151],106:[2,151],107:[2,151],108:[2,151],109:[2,151],110:[2,151],111:[2,151],112:[2,151],113:[2,151],114:[2,151],115:[2,151],116:[2,151],117:[2,151],118:[2,151],119:[2,151],120:[2,151],121:[2,151],122:[2,151],123:[2,151],124:[2,151],125:[2,151],126:[2,151],127:[2,151],128:[2,151],129:[2,151],130:[2,151],131:[2,151],132:[2,151],134:[2,151],135:[2,151],137:[2,151],138:[2,151],140:[2,151],141:[2,151],142:[2,151],143:[2,151],144:[2,151],145:[2,151],146:[2,151],
-147:[2,151],148:[2,151],149:[2,151],150:[2,151],151:[2,151],152:[2,151],153:[2,151],154:[2,151],155:[2,151],156:[2,151],157:[2,151],158:[2,151],159:[2,151],160:[2,151],161:[2,151],162:[2,151],165:[2,151],166:[2,151],167:[2,151],169:[2,151],170:[2,151],185:[2,151],188:[2,151],194:[2,151],196:[2,151],198:[2,151],200:[2,151]},{10:[1,407],18:384,19:[1,394],20:385,21:[1,338],22:386,23:[1,339],28:387,29:[1,395],30:388,31:[1,396],32:389,33:[1,397],34:390,35:[1,398],36:391,37:[1,399],38:392,39:[1,400],40:393,
-41:[1,401],45:408},{10:[2,40],19:[2,40],21:[2,40],23:[2,40],29:[2,40],31:[2,40],33:[2,40],35:[2,40],37:[2,40],39:[2,40],41:[2,40]},{10:[2,30],19:[2,30],21:[2,30],23:[2,30],29:[2,30],31:[2,30],33:[2,30],35:[2,30],37:[2,30],39:[2,30],41:[2,30]},{10:[2,31],19:[2,31],21:[2,31],23:[2,31],29:[2,31],31:[2,31],33:[2,31],35:[2,31],37:[2,31],39:[2,31],41:[2,31]},{10:[2,32],19:[2,32],21:[2,32],23:[2,32],29:[2,32],31:[2,32],33:[2,32],35:[2,32],37:[2,32],39:[2,32],41:[2,32]},{10:[2,33],19:[2,33],21:[2,33],23:[2,
-33],29:[2,33],31:[2,33],33:[2,33],35:[2,33],37:[2,33],39:[2,33],41:[2,33]},{10:[2,34],19:[2,34],21:[2,34],23:[2,34],29:[2,34],31:[2,34],33:[2,34],35:[2,34],37:[2,34],39:[2,34],41:[2,34]},{10:[2,35],19:[2,35],21:[2,35],23:[2,35],29:[2,35],31:[2,35],33:[2,35],35:[2,35],37:[2,35],39:[2,35],41:[2,35]},{10:[2,36],19:[2,36],21:[2,36],23:[2,36],29:[2,36],31:[2,36],33:[2,36],35:[2,36],37:[2,36],39:[2,36],41:[2,36]},{10:[2,37],19:[2,37],21:[2,37],23:[2,37],29:[2,37],31:[2,37],33:[2,37],35:[2,37],37:[2,37],
-39:[2,37],41:[2,37]},{10:[2,38],19:[2,38],21:[2,38],23:[2,38],29:[2,38],31:[2,38],33:[2,38],35:[2,38],37:[2,38],39:[2,38],41:[2,38]},{10:[2,39],19:[2,39],21:[2,39],23:[2,39],29:[2,39],31:[2,39],33:[2,39],35:[2,39],37:[2,39],39:[2,39],41:[2,39]},{7:128,8:[1,129],14:409},{7:128,8:[1,129],14:410},{7:128,8:[1,129],14:411},{7:128,8:[1,129],14:412},{7:128,8:[1,129],14:413},{7:128,8:[1,129],14:414},{7:128,8:[1,129],14:415},{7:128,8:[1,129],14:416},{6:[2,178],8:[2,178],10:[2,178],49:[2,178],50:[2,178],51:[2,
-178],53:[2,178],56:[2,178],57:[2,178],58:[2,178],59:[2,178],60:[2,178],61:[2,178],62:[2,178],63:[2,178],64:[2,178],65:[2,178],66:[2,178],67:[2,178],68:[2,178],69:[2,178],70:[2,178],71:[2,178],72:[2,178],73:[2,178],74:[2,178],75:[2,178],76:[2,178],77:[2,178],78:[2,178],79:[2,178],81:[2,178],82:[2,178],83:[2,178],84:[2,178],85:[2,178],86:[2,178],87:[2,178],88:[2,178],89:[2,178],90:[2,178],91:[2,178],92:[2,178],93:[2,178],94:[2,178],95:[2,178],96:[2,178],97:[2,178],98:[2,178],99:[2,178],100:[2,178],
-101:[2,178],102:[2,178],103:[2,178],104:[2,178],105:[2,178],106:[2,178],107:[2,178],108:[2,178],109:[2,178],110:[2,178],111:[2,178],112:[2,178],113:[2,178],114:[2,178],115:[2,178],116:[2,178],117:[2,178],118:[2,178],119:[2,178],120:[2,178],121:[2,178],122:[2,178],123:[2,178],124:[2,178],125:[2,178],126:[2,178],127:[2,178],128:[2,178],129:[2,178],130:[2,178],131:[2,178],132:[2,178],135:[2,178],137:[2,178],138:[2,178],140:[2,178],141:[2,178],142:[2,178],143:[2,178],144:[2,178],145:[2,178],146:[2,178],
-147:[2,178],148:[2,178],149:[2,178],150:[2,178],151:[2,178],152:[2,178],153:[2,178],154:[2,178],155:[2,178],156:[2,178],157:[2,178],158:[2,178],159:[2,178],160:[2,178],161:[2,178],162:[2,178],165:[2,178],166:[2,178],169:[2,178],170:[2,178],185:[2,178],188:[2,178],194:[2,178],196:[2,178],198:[2,178],200:[2,178]},{10:[1,418],136:417,165:[1,238],166:[1,239],173:237},{10:[1,419],165:[1,238],166:[1,239],173:300},{10:[2,198],140:[2,198],142:[2,198],144:[2,198],146:[2,198],148:[2,198],150:[2,198],152:[2,
-198],154:[2,198],156:[2,198],158:[2,198],160:[2,198],185:[1,283],188:[2,198]},{10:[2,194],140:[2,194],142:[2,194],144:[2,194],146:[2,194],148:[2,194],150:[2,194],152:[2,194],154:[2,194],156:[2,194],158:[2,194],160:[2,194],185:[2,194],188:[2,194]},{8:[1,26],10:[2,193],48:35,49:[1,119],50:[1,47],51:[1,43],54:24,55:213,56:[1,27],57:[1,28],58:[1,29],59:[1,30],60:[1,31],61:[1,32],62:[1,33],63:[1,34],67:[1,36],68:[1,37],69:[1,38],70:[1,39],71:[1,40],72:[1,41],73:[1,42],74:[1,44],75:[1,45],76:[1,46],77:[1,
-48],78:[1,49],79:[1,50],81:[1,51],82:[1,52],83:[1,53],84:[1,54],85:[1,55],86:[1,56],87:[1,57],88:[1,58],89:[1,59],90:[1,60],91:[1,61],92:[1,62],93:[1,63],94:[1,64],95:[1,65],96:[1,66],97:[1,67],98:[1,68],99:[1,69],100:[1,70],101:[1,71],102:[1,72],103:[1,73],104:[1,74],105:[1,75],106:[1,76],107:[1,77],108:[1,78],109:[1,79],110:[1,80],111:[1,81],112:[1,82],113:[1,83],114:[1,84],115:[1,85],116:[1,86],117:[1,87],118:[1,88],119:[1,89],120:[1,90],121:[1,91],122:[1,92],123:[1,93],124:[1,94],125:[1,95],126:[1,
-96],127:[1,97],128:[1,98],129:[1,99],130:[1,100],131:[1,101],132:[1,102],135:[1,23],137:[1,103],138:[1,104],139:420,141:[1,105],143:[1,106],145:[1,107],147:[1,108],149:[1,109],151:[1,110],153:[1,111],155:[1,112],157:[1,113],159:[1,114],161:[1,115],162:[1,116],164:22,168:25,169:[1,117],170:[1,118],171:14,174:13,175:[1,15],176:[1,16],177:[1,17],178:[1,18],179:[1,19],180:[1,20],181:[1,21],182:211,183:[1,212],184:210,185:[2,193],186:208,187:[1,209],188:[2,193]},{10:[2,41],19:[2,41],21:[2,41],23:[2,41],
-29:[2,41],31:[2,41],33:[2,41],35:[2,41],37:[2,41],39:[2,41],41:[2,41]},{10:[2,10],19:[2,10],21:[2,10],23:[2,10],29:[2,10],31:[2,10],33:[2,10],35:[2,10],37:[2,10],39:[2,10],41:[2,10]},{10:[2,15],19:[2,15],21:[2,15],23:[2,15],29:[2,15],31:[2,15],33:[2,15],35:[2,15],37:[2,15],39:[2,15],41:[2,15]},{10:[2,16],19:[2,16],21:[2,16],23:[2,16],29:[2,16],31:[2,16],33:[2,16],35:[2,16],37:[2,16],39:[2,16],41:[2,16]},{10:[2,17],19:[2,17],21:[2,17],23:[2,17],29:[2,17],31:[2,17],33:[2,17],35:[2,17],37:[2,17],39:[2,
-17],41:[2,17]},{10:[2,18],19:[2,18],21:[2,18],23:[2,18],29:[2,18],31:[2,18],33:[2,18],35:[2,18],37:[2,18],39:[2,18],41:[2,18]},{10:[2,19],19:[2,19],21:[2,19],23:[2,19],29:[2,19],31:[2,19],33:[2,19],35:[2,19],37:[2,19],39:[2,19],41:[2,19]},{10:[2,20],19:[2,20],21:[2,20],23:[2,20],29:[2,20],31:[2,20],33:[2,20],35:[2,20],37:[2,20],39:[2,20],41:[2,20]},{10:[2,21],19:[2,21],21:[2,21],23:[2,21],29:[2,21],31:[2,21],33:[2,21],35:[2,21],37:[2,21],39:[2,21],41:[2,21]},{10:[1,421],165:[1,238],166:[1,239],173:300},
-{6:[2,139],8:[2,139],10:[2,139],49:[2,139],50:[2,139],51:[2,139],53:[2,139],56:[2,139],57:[2,139],58:[2,139],59:[2,139],60:[2,139],61:[2,139],62:[2,139],63:[2,139],64:[2,139],65:[2,139],66:[2,139],67:[2,139],68:[2,139],69:[2,139],70:[2,139],71:[2,139],72:[2,139],73:[2,139],74:[2,139],75:[2,139],76:[2,139],77:[2,139],78:[2,139],79:[2,139],81:[2,139],82:[2,139],83:[2,139],84:[2,139],85:[2,139],86:[2,139],87:[2,139],88:[2,139],89:[2,139],90:[2,139],91:[2,139],92:[2,139],93:[2,139],94:[2,139],95:[2,139],
-96:[2,139],97:[2,139],98:[2,139],99:[2,139],100:[2,139],101:[2,139],102:[2,139],103:[2,139],104:[2,139],105:[2,139],106:[2,139],107:[2,139],108:[2,139],109:[2,139],110:[2,139],111:[2,139],112:[2,139],113:[2,139],114:[2,139],115:[2,139],116:[2,139],117:[2,139],118:[2,139],119:[2,139],120:[2,139],121:[2,139],122:[2,139],123:[2,139],124:[2,139],125:[2,139],126:[2,139],127:[2,139],128:[2,139],129:[2,139],130:[2,139],131:[2,139],132:[2,139],134:[2,139],135:[2,139],137:[2,139],138:[2,139],140:[2,139],141:[2,
-139],142:[2,139],143:[2,139],144:[2,139],145:[2,139],146:[2,139],147:[2,139],148:[2,139],149:[2,139],150:[2,139],151:[2,139],152:[2,139],153:[2,139],154:[2,139],155:[2,139],156:[2,139],157:[2,139],158:[2,139],159:[2,139],160:[2,139],161:[2,139],162:[2,139],165:[2,139],166:[2,139],167:[2,139],169:[2,139],170:[2,139],185:[2,139],188:[2,139],194:[2,139],196:[2,139],198:[2,139],200:[2,139]},{6:[2,140],8:[2,140],10:[2,140],49:[2,140],50:[2,140],51:[2,140],53:[2,140],56:[2,140],57:[2,140],58:[2,140],59:[2,
-140],60:[2,140],61:[2,140],62:[2,140],63:[2,140],64:[2,140],65:[2,140],66:[2,140],67:[2,140],68:[2,140],69:[2,140],70:[2,140],71:[2,140],72:[2,140],73:[2,140],74:[2,140],75:[2,140],76:[2,140],77:[2,140],78:[2,140],79:[2,140],81:[2,140],82:[2,140],83:[2,140],84:[2,140],85:[2,140],86:[2,140],87:[2,140],88:[2,140],89:[2,140],90:[2,140],91:[2,140],92:[2,140],93:[2,140],94:[2,140],95:[2,140],96:[2,140],97:[2,140],98:[2,140],99:[2,140],100:[2,140],101:[2,140],102:[2,140],103:[2,140],104:[2,140],105:[2,
-140],106:[2,140],107:[2,140],108:[2,140],109:[2,140],110:[2,140],111:[2,140],112:[2,140],113:[2,140],114:[2,140],115:[2,140],116:[2,140],117:[2,140],118:[2,140],119:[2,140],120:[2,140],121:[2,140],122:[2,140],123:[2,140],124:[2,140],125:[2,140],126:[2,140],127:[2,140],128:[2,140],129:[2,140],130:[2,140],131:[2,140],132:[2,140],134:[2,140],135:[2,140],137:[2,140],138:[2,140],140:[2,140],141:[2,140],142:[2,140],143:[2,140],144:[2,140],145:[2,140],146:[2,140],147:[2,140],148:[2,140],149:[2,140],150:[2,
-140],151:[2,140],152:[2,140],153:[2,140],154:[2,140],155:[2,140],156:[2,140],157:[2,140],158:[2,140],159:[2,140],160:[2,140],161:[2,140],162:[2,140],165:[2,140],166:[2,140],167:[2,140],169:[2,140],170:[2,140],185:[2,140],188:[2,140],194:[2,140],196:[2,140],198:[2,140],200:[2,140]},{10:[1,422],188:[1,281]},{6:[2,138],8:[2,138],10:[2,138],49:[2,138],50:[2,138],51:[2,138],53:[2,138],56:[2,138],57:[2,138],58:[2,138],59:[2,138],60:[2,138],61:[2,138],62:[2,138],63:[2,138],64:[2,138],65:[2,138],66:[2,138],
-67:[2,138],68:[2,138],69:[2,138],70:[2,138],71:[2,138],72:[2,138],73:[2,138],74:[2,138],75:[2,138],76:[2,138],77:[2,138],78:[2,138],79:[2,138],81:[2,138],82:[2,138],83:[2,138],84:[2,138],85:[2,138],86:[2,138],87:[2,138],88:[2,138],89:[2,138],90:[2,138],91:[2,138],92:[2,138],93:[2,138],94:[2,138],95:[2,138],96:[2,138],97:[2,138],98:[2,138],99:[2,138],100:[2,138],101:[2,138],102:[2,138],103:[2,138],104:[2,138],105:[2,138],106:[2,138],107:[2,138],108:[2,138],109:[2,138],110:[2,138],111:[2,138],112:[2,
-138],113:[2,138],114:[2,138],115:[2,138],116:[2,138],117:[2,138],118:[2,138],119:[2,138],120:[2,138],121:[2,138],122:[2,138],123:[2,138],124:[2,138],125:[2,138],126:[2,138],127:[2,138],128:[2,138],129:[2,138],130:[2,138],131:[2,138],132:[2,138],134:[2,138],135:[2,138],137:[2,138],138:[2,138],140:[2,138],141:[2,138],142:[2,138],143:[2,138],144:[2,138],145:[2,138],146:[2,138],147:[2,138],148:[2,138],149:[2,138],150:[2,138],151:[2,138],152:[2,138],153:[2,138],154:[2,138],155:[2,138],156:[2,138],157:[2,
-138],158:[2,138],159:[2,138],160:[2,138],161:[2,138],162:[2,138],165:[2,138],166:[2,138],167:[2,138],169:[2,138],170:[2,138],185:[2,138],188:[2,138],194:[2,138],196:[2,138],198:[2,138],200:[2,138]},{6:[2,155],8:[2,155],10:[2,155],49:[2,155],50:[2,155],51:[2,155],53:[2,155],56:[2,155],57:[2,155],58:[2,155],59:[2,155],60:[2,155],61:[2,155],62:[2,155],63:[2,155],64:[2,155],65:[2,155],66:[2,155],67:[2,155],68:[2,155],69:[2,155],70:[2,155],71:[2,155],72:[2,155],73:[2,155],74:[2,155],75:[2,155],76:[2,155],
-77:[2,155],78:[2,155],79:[2,155],81:[2,155],82:[2,155],83:[2,155],84:[2,155],85:[2,155],86:[2,155],87:[2,155],88:[2,155],89:[2,155],90:[2,155],91:[2,155],92:[2,155],93:[2,155],94:[2,155],95:[2,155],96:[2,155],97:[2,155],98:[2,155],99:[2,155],100:[2,155],101:[2,155],102:[2,155],103:[2,155],104:[2,155],105:[2,155],106:[2,155],107:[2,155],108:[2,155],109:[2,155],110:[2,155],111:[2,155],112:[2,155],113:[2,155],114:[2,155],115:[2,155],116:[2,155],117:[2,155],118:[2,155],119:[2,155],120:[2,155],121:[2,
-155],122:[2,155],123:[2,155],124:[2,155],125:[2,155],126:[2,155],127:[2,155],128:[2,155],129:[2,155],130:[2,155],131:[2,155],132:[2,155],134:[2,155],135:[2,155],137:[2,155],138:[2,155],140:[2,155],141:[2,155],142:[2,155],143:[2,155],144:[2,155],145:[2,155],146:[2,155],147:[2,155],148:[2,155],149:[2,155],150:[2,155],151:[2,155],152:[2,155],153:[2,155],154:[2,155],155:[2,155],156:[2,155],157:[2,155],158:[2,155],159:[2,155],160:[2,155],161:[2,155],162:[2,155],165:[2,155],166:[2,155],167:[2,155],169:[2,
-155],170:[2,155],185:[2,155],188:[2,155],194:[2,155],196:[2,155],198:[2,155],200:[2,155]}],O:{9:[2,202],225:[2,8]},parseError:function(b,a){if(a.va)this.trace(b);else throw Error(b);},parse:function(b){var a=[0],d=[n],e=[],g=this.ma,c="",f=0,k=0,l=0,r=e.slice.call(arguments,1);this.d.ga(b);this.d.f=this.f;this.f.d=this.d;this.f.V=this;"undefined"==typeof this.d.c&&(this.d.c={});var t=this.d.c;e.push(t);var w=this.d.options&&this.d.options.z;this.parseError=F;for(var m,x,v,q,z={},A,s;;){v=a[a.length-
-1];if(this.O[v])q=this.O[v];else{if(m===n||"undefined"==typeof m)m=void 0,m=this.d.S()||1,"number"!==typeof m&&(m=this.la[m]||m);q=g[v]&&g[v][m]}if("undefined"===typeof q||!q.length||!q[0]){var y="";s=[];for(A in g[v])this.B[A]&&2<A&&s.push("'"+this.B[A]+"'");y=this.d.G?"Parse error on line "+(f+1)+":\n"+this.d.G()+"\nExpecting "+s.join(", ")+", got '"+(this.B[m]||m)+"'":"Parse error on line "+(f+1)+": Unexpected "+(1==m?"end of input":"'"+(this.B[m]||m)+"'");this.parseError(y,{text:this.d.match,
-$:this.B[m]||m,T:this.d.g,ta:t,qa:s})}if(q[0]instanceof Array&&1<q.length)throw Error("Parse Error: multiple actions possible at state: "+v+", token: "+m);switch(q[0]){case 1:a.push(m);d.push(this.d.a);e.push(this.d.c);a.push(q[1]);m=n;x?(m=x,x=n):(k=this.d.r,c=this.d.a,f=this.d.g,t=this.d.c,0<l&&l--);break;case 2:s=this.W[q[1]][1];z.b=d[d.length-s];z.L={s:e[e.length-(s||1)].s,p:e[e.length-1].p,m:e[e.length-(s||1)].m,n:e[e.length-1].n};w&&(z.L.o=[e[e.length-(s||1)].o[0],e[e.length-1].o[1]]);v=this.I.apply(z,
-[c,k,f,this.f,q[1],d,e].concat(r));if("undefined"!==typeof v)return v;s&&(a=a.slice(0,-2*s),d=d.slice(0,-1*s),e=e.slice(0,-1*s));a.push(this.W[q[1]][0]);d.push(z.b);e.push(z.L);q=g[a[a.length-2]][a[a.length-1]];a.push(q);break;case 3:return h}}return h}},x="http://www.w3.org/1998/Math/MathML",D="TeX LaTeX text/x-tex text/x-latex application/x-tex application/x-latex".split(" ");try{l.D=new DOMParser}catch(H){l.D={parseFromString:function(){throw"DOMParser undefined. Did you call TeXZilla.setDOMParser?";
-}}}l.fa=function(b){this.D=b};try{l.H=new XMLSerializer}catch(I){l.H={serializeToString:function(){throw"XMLSerializer undefined. Did you call TeXZilla.setXMLSerializer?";}}}l.ja=function(b){this.H=b};l.U=function(b){return this.D.parseFromString(b,"application/xml").documentElement};l.ia=function(b){this.f.w=b};l.ha=function(b){this.f.da=b};l.ca=function(b){"string"===typeof b&&(b=this.U(b));return C(b)};l.Z=function(b,a,d,e){var g;try{g=this.parse("\\("+b+"\\)")}catch(c){if(e)throw c;g=w(["<merror><mtext>"+
-t(c.message)+"</mtext></merror>"],p,b)}d&&(g=g.replace(/^<math/,'<math dir="rtl"'));a&&(g=g.replace(/^<math/,'<math display="block"'));return g};l.Y=function(b,a,d,e){return this.U(this.Z(b,a,d,e))};l.na=function(b,a,d,e,g){var c,f;void 0===e&&(e=64);void 0===g&&(g=window.document);a=this.Y(b,h,a);a.setAttribute("mathsize",e+"px");e=document.createElement("div");e.style.visibility="hidden";e.style.position="absolute";e.appendChild(a);g.body.appendChild(e);c=a.getBoundingClientRect();g.body.removeChild(e);
-e.removeChild(a);d?(d=Math.pow(2,Math.ceil(Math.log(c.width)/Math.LN2)),g=Math.pow(2,Math.ceil(Math.log(c.height)/Math.LN2))):(d=Math.ceil(c.width),g=Math.ceil(c.height));f=document.createElementNS("http://www.w3.org/2000/svg","svg");f.setAttribute("width",d+"px");f.setAttribute("height",g+"px");e=document.createElementNS("http://www.w3.org/2000/svg","g");e.setAttribute("transform","translate("+(d-c.width)/2+","+(g-c.height)/2+")");f.appendChild(e);e=document.createElementNS("http://www.w3.org/2000/svg",
-"foreignObject");e.setAttribute("width",c.width);e.setAttribute("height",c.height);e.appendChild(a);f.firstChild.appendChild(e);a=new Image;a.src="data:image/svg+xml;base64,"+window.btoa(E(this.H.serializeToString(f)));a.width=d;a.height=g;a.alt=t(b);return a};l.R=function(b,a){try{return this.parse(b)}catch(d){if(a)throw d;return b}};l.Q=function(b,a){var d,e,f;for(f=b.firstChild;f;f=f.nextSibling)switch(f.nodeType){case 1:this.Q(f,a);break;case 3:this.f.P=h;d=this.D.parseFromString("<root>"+u.R(f.data,
-a)+"</root>","application/xml").documentElement;for(this.f.P=p;e=d.firstChild;)b.insertBefore(d.removeChild(e),f);e=f.previousSibling;b.removeChild(f);f=e}};l.d=function(){return{K:1,parseError:function(b,a){if(this.f.V)this.f.V.parseError(b,a);else throw Error(b);},ga:function(b){this.h=b;this.v=this.C=this.t=p;this.g=this.r=0;this.a=this.i=this.match="";this.e=["INITIAL"];this.c={s:1,m:0,p:1,n:0};this.options.z&&(this.c.o=[0,0]);this.offset=0;return this},input:function(){var b=this.h[0];this.a+=
-b;this.r++;this.offset++;this.match+=b;this.i+=b;b.match(/(?:\r\n?|\n).*/g)?(this.g++,this.c.p++):this.c.n++;this.options.z&&this.c.o[1]++;this.h=this.h.slice(1);return b},J:function(b){var a=b.length,d=b.split(/(?:\r\n?|\n)/g);this.h=b+this.h;this.a=this.a.substr(0,this.a.length-a-1);this.offset-=a;b=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1);this.i=this.i.substr(0,this.i.length-1);d.length-1&&(this.g-=d.length-1);var e=this.c.o;this.c={s:this.c.s,p:this.g+
-1,m:this.c.m,n:d?(d.length===b.length?this.c.m:0)+b[b.length-d.length].length-d[0].length:this.c.m-a};this.options.z&&(this.c.o=[e[0],e[0]+this.r-a]);this.r=this.a.length;return this},ua:function(){this.v=h;return this},wa:function(){if(this.options.M)this.C=h;else return this.parseError("Lexical error on line "+(this.g+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.G(),{text:"",$:n,T:this.g});return this},
-sa:function(b){this.J(this.match.slice(b))},ea:function(){var b=this.i.substr(0,this.i.length-this.match.length);return(20<b.length?"...":"")+b.substr(-20).replace(/\n/g,"")},oa:function(){var b=this.match;20>b.length&&(b+=this.h.substr(0,20-b.length));return(b.substr(0,20)+(20<b.length?"...":"")).replace(/\n/g,"")},G:function(){var b=this.ea(),a=Array(b.length+1).join("-");return b+this.oa()+"\n"+a+"^"},X:function(b,a){var d,e;this.options.M&&(e={g:this.g,c:{s:this.c.s,p:this.p,m:this.c.m,n:this.c.n},
-a:this.a,match:this.match,matches:this.matches,i:this.i,r:this.r,offset:this.offset,v:this.v,h:this.h,f:this.f,e:this.e.slice(0),t:this.t},this.options.z&&(e.c.o=this.c.o.slice(0)));if(d=b[0].match(/(?:\r\n?|\n).*/g))this.g+=d.length;this.c={s:this.c.p,p:this.g+1,m:this.c.n,n:d?d[d.length-1].length-d[d.length-1].match(/\r?\n?/)[0].length:this.c.n+b[0].length};this.a+=b[0];this.match+=b[0];this.matches=b;this.r=this.a.length;this.options.z&&(this.c.o=[this.offset,this.offset+=this.r]);this.C=this.v=
-p;this.h=this.h.slice(b[0].length);this.i+=b[0];d=this.I.call(this,this.f,this,a,this.e[this.e.length-1]);this.t&&this.h&&(this.t=p);if(d)return d;if(this.C)for(var f in e)this[f]=e[f];return p},next:function(){if(this.t)return this.K;this.h||(this.t=h);var b,a,d;this.v||(this.match=this.a="");for(var e=this.aa(),f=0;f<e.length;f++)if((a=this.h.match(this.rules[e[f]]))&&(!b||a[0].length>b[0].length))if(b=a,d=f,this.options.M){b=this.X(a,e[f]);if(b!==p)return b;if(this.C)b=p;else return p}else if(!this.options.ra)break;
-return b?(b=this.X(b,e[d]),b!==p?b:p):""===this.h?this.K:this.parseError("Lexical error on line "+(this.g+1)+". Unrecognized text.\n"+this.G(),{text:"",$:n,T:this.g})},S:function(){var b=this.next();return b?b:this.S()},k:function(b){this.e.push(b)},q:function(){return 0<this.e.length-1?this.e.pop():this.e[0]},aa:function(){return this.e.length&&this.e[this.e.length-1]?this.N[this.e[this.e.length-1]].rules:this.N.INITIAL.rules},ya:function(b){b=this.e.length-1-Math.abs(b||0);return 0<=b?this.e[b]:
-"INITIAL"},pushState:function(b){this.k(b)},xa:function(){return this.e.length},options:{},I:function(b,a,d){switch(d){case 0:this.J(a.a);this.pushState("DOCUMENT");break;case 1:return this.pushState("MATH"+(0+!!b.da)),b.ka=this.i.length,"STARTMATH"+(2*("$"==a.a[0])+("$"==a.a[1]||"["==a.a[1]));case 2:return this.q(),"EOF";case 3:return a.a=a.a[1],"TEXT";case 4:return b.P&&(a.a=t(a.a)),"TEXT";case 5:return"TEXT";case 6:return this.q(),"[";case 7:this.J(a.a);this.q();this.q();break;case 8:return"TEXTOPTARG";
-case 9:return this.q(),"]";case 10:return"{";case 11:return"TEXTARG";case 12:return this.q(),"}";case 13:return this.q(),"]";case 15:return this.q(),b.ba=this.i.length-this.match.length,b.u=this.i.substring(b.ka,b.ba),"ENDMATH"+(2*("$"==a.a[0])+("$"==a.a[1]||"]"==a.a[1]));case 16:return"{";case 17:return"}";case 18:return"^";case 19:return"_";case 20:return".";case 21:return"COLSEP";case 22:return"ROWSEP";case 23:return"NUM";case 24:return"A";case 25:return a.a="Ζ","A";case 26:return a.a="ζ","A";
-case 27:return this.pushState("OPTARG"),this.pushState("TRYOPTARG"),a.a="⇌","XARROW";case 28:return this.pushState("OPTARG"),this.pushState("TRYOPTARG"),a.a="⇒","XARROW";case 29:return this.pushState("OPTARG"),this.pushState("TRYOPTARG"),a.a="→","XARROW";case 30:return this.pushState("OPTARG"),this.pushState("TRYOPTARG"),a.a="↦","XARROW";case 31:return this.pushState("OPTARG"),this.pushState("TRYOPTARG"),a.a="⇋","XARROW";case 32:return this.pushState("OPTARG"),this.pushState("TRYOPTARG"),a.a="⇔",
-"XARROW";case 33:return this.pushState("OPTARG"),this.pushState("TRYOPTARG"),a.a="↔","XARROW";case 34:return this.pushState("OPTARG"),this.pushState("TRYOPTARG"),a.a="⇐","XARROW";case 35:return this.pushState("OPTARG"),this.pushState("TRYOPTARG"),a.a="←","XARROW";case 36:return a.a="Ξ","A";case 37:return a.a="ξ","A";case 38:return this.pushState("OPTARG"),this.pushState("TRYOPTARG"),a.a="↪","XARROW";case 39:return this.pushState("OPTARG"),this.pushState("TRYOPTARG"),a.a="↩","XARROW";case 40:return a.a=
-"≀","OP";case 41:return a.a="℘","A";case 42:return a.a="⇀","ACCENT";case 43:return a.a="˜","ACCENT";case 44:return a.a="^","ACCENT";case 45:return a.a="ˇ","ACCENT";case 46:return a.a="¯","ACCENT";case 47:return a.a="≙","OP";case 48:return a.a="⋀","OPM";case 49:return a.a="∧","OP";case 50:return a.a="⦀","OPFS";case 51:return a.a="⊪","OP";case 52:return a.a="‖","OPFS";case 53:return a.a="|","OPFS";case 54:return a.a="⊻","OP";case 55:return a.a="⋁","OPM";case 56:return a.a="∨","OP";case 57:return a.a=
-"⇀","ACCENTNS";case 58:return a.a="⋮","OP";case 59:return a.a="⊫","OP";case 60:return a.a="⊩","OP";case 61:return a.a="⊨","OP";case 62:return a.a="⊢","OP";case 63:return a.a="⫫","OP";case 64:return a.a="⊳","OP";case 65:return a.a="⊲","OP";case 66:return a.a="▵","OP";case 67:return a.a="ϑ","A";case 68:return a.a="⫌︀","OP";case 69:return a.a="⊋︀","OP";case 70:return a.a="⫋︀","OP";case 71:return a.a="⊊︀","OP";case 72:return a.a="⊊︀","OP";case 73:return a.a="ς","A";case 74:return a.a="ϱ","A";case 75:return a.a=
-"∝","OP";case 76:return a.a="ϖ","A";case 77:return a.a="φ","A";case 78:return a.a="∅","A";case 79:return a.a="ϰ","A";case 80:return a.a="ε","A";case 81:return a.a="⤊","OPS";case 82:return a.a="⇈","OPS";case 83:return a.a="ϒ","A";case 84:return a.a="υ","A";case 85:return a.a="ϒ","A";case 86:return a.a="⊎","OP";case 87:return a.a="⨛","OP";case 88:return a.a="↿","OPS";case 89:return a.a="↾","OPS";case 90:return a.a="⇕","OPS";case 91:return a.a="↕","OPS";case 92:return a.a="↕","OPS";case 93:return a.a=
-"⇑","OPS";case 94:return a.a="↑","OPS";case 95:return a.a="↑","OPS";case 96:return a.a="⊵","OP";case 97:return a.a="⊴","OP";case 98:return a.a="⋃","OPM";case 99:return a.a="∪","OP";case 100:return"UNDERSET";case 101:return"UNDEROVERSET";case 102:return"UNDERLINE";case 103:return"UNDERBRACE";case 104:return a.a="⋰","OP";case 105:return"OP";case 106:return"OP";case 107:return"OP";case 108:return"OP";case 109:return"OP";case 110:return"OP";case 111:return"OP";case 112:return"OP";case 113:return"OP";
-case 114:return"OP";case 115:return"OP";case 116:return"OP";case 117:return"OP";case 118:return"OP";case 119:return"OP";case 120:return"OP";case 121:return"OP";case 122:return"OP";case 123:return"OP";case 124:return"OP";case 125:return"OP";case 126:return"OP";case 127:return"OP";case 128:return"OP";case 129:return"OP";case 130:return"OP";case 131:return"OP";case 132:return"OP";case 133:return"OP";case 134:return"OP";case 135:return"OP";case 136:return"OP";case 137:return"OP";case 138:return"OPFS";
-case 139:return"OPFS";case 140:return"OP";case 141:return"OP";case 142:return"OP";case 143:return"OP";case 144:return"OP";case 145:return"OP";case 146:return"OP";case 147:return"OP";case 148:return"OP";case 149:return"OP";case 150:return"OP";case 151:return"OP";case 152:return"OP";case 153:return"OP";case 154:return"OP";case 155:return"OP";case 156:return"OP";case 157:return"OP";case 158:return"OP";case 159:return"OP";case 160:return"OP";case 161:return a.a="⤖","OP";case 162:return a.a="↠","OPS";
-case 163:return a.a="↞","OPS";case 164:return a.a="∭","OP";case 165:return a.a="⊵","OP";case 166:return a.a="▹","OP";case 167:return a.a="≜","OP";case 168:return a.a="⊴","OP";case 169:return a.a="◃","OP";case 170:return a.a="▿","OP";case 171:return a.a="▵","OP";case 172:return a.a="⤪","OP";case 173:return a.a="⤩","OP";case 174:return a.a="⊤","OP";case 175:return this.pushState("TEXTARG"),"TOOLTIP";case 176:return a.a="⤧","OP";case 177:return"TOGGLE";case 178:return a.a="⤨","OP";case 179:return a.a=
-"→","OPS";case 180:return a.a="⊠","OP";case 181:return a.a="×","OP";case 182:return a.a="˜","ACCENTNS";case 183:return"THINSPACE";case 184:return"THICKSPACE";case 185:return a.a="∼","OP";case 186:return a.a="≈","OP";case 187:return a.a="Θ","A";case 188:return a.a="θ","A";case 189:return a.a="∴","OP";case 190:return"TFRAC";case 191:return"TEXTSTYLE";case 192:return"TEXTSIZE";case 193:return a.a="”","OPF";case 194:return a.a="“","OPF";case 195:return a.a="~","OPS";case 196:return a.a="`","OP";case 197:return a.a=
-"^","OPS";case 198:return a.a="´","OP";case 199:return this.k("TEXTARG"),"MTEXT";case 200:return"TENSOR";case 201:return"TBINOM";case 202:return a.a="Τ","A";case 203:return a.a="τ","A";case 204:return a.a="⇙","OPS";case 205:return a.a="↙","OPS";case 206:return a.a="⇙","OPS";case 207:return a.a="↙","OPS";case 208:return a.a="√","OPS";case 209:return a.a="⫌","OP";case 210:return a.a="⊋","OP";case 211:return a.a="⫆","OP";case 212:return a.a="⊇","OP";case 213:return a.a="⋑","OP";case 214:return a.a="⊃",
-"OP";case 215:return a.a="∑","OPM";case 216:return a.a="≿","OP";case 217:return a.a="⋩","OP";case 218:return a.a="⪶","OP";case 219:return a.a="⪺","OP";case 220:return a.a="⪰","OP";case 221:return a.a="≽","OP";case 222:return a.a="⪸","OP";case 223:return a.a="≻","OP";case 224:return"SUBSTACK";case 225:return a.a="⫋","OP";case 226:return a.a="⊊","OP";case 227:return a.a="⫅","OP";case 228:return a.a="⊆","OP";case 229:return a.a="⋐","OP";case 230:return a.a="⊂","OP";case 231:return this.pushState("TEXTARG"),
-"STATUSLINE";case 232:return a.a="⋆","OP";case 233:return"OVERSET";case 234:return a.a="⫽","OP";case 235:return a.a="□","OP";case 236:return a.a="⊒","OP";case 237:return a.a="⊐","OP";case 238:return a.a="⊑","OP";case 239:return a.a="⊏","OP";case 240:return this.pushState("OPTARG"),this.pushState("TRYOPTARG"),"SQRT";case 241:return a.a="⊔","OP";case 242:return a.a="⊓","OP";case 243:return a.a="∢","OP";case 244:return a.a="♠","OP";case 245:return this.pushState("TEXTARG"),this.pushState("TEXTARG"),
-this.pushState("TEXTARG"),"SPACE";case 246:return a.a="⌣","OP";case 247:return a.a="⌣","OP";case 248:return a.a="∖","OP";case 249:return a.a="⌢","OP";case 250:return"SLASH";case 251:return a.a="≃","OP";case 252:return a.a="∼","OP";case 253:return a.a="Σ","A";case 254:return a.a="σ","A";case 255:return a.a="⧢","OP";case 256:return a.a="∥","OP";case 257:return a.a="∣","OP";case 258:return a.a="♯","OP";case 259:return a.a="∖","OP";case 260:return a.a="⤭","OP";case 261:return a.a="⇘","OPS";case 262:return a.a=
-"↘","OPS";case 263:return a.a="⇘","OPS";case 264:return a.a="↘","OPS";case 265:return"SCRIPTSIZE";case 266:return"SCRIPTSCRIPTSIZE";case 267:return a.a="⋊","OP";case 268:return a.a="↱","OPS";case 269:return a.a="⇛","OPS";case 270:return a.a="⟫","OPFS";case 271:return a.a="’","OPF";case 272:return this.k("TEXTARG"),"ROWSPAN";case 273:return"ROWOPTS";case 274:return this.pushState("TEXTARG"),"ROWLINES";case 275:return this.k("TEXTARG"),"ROWALIGN";case 276:return"ROOT";case 277:return a.a="⎱","OP";case 278:return a.a=
-"≓","OP";case 279:return a.a="⟲","OP";case 280:return a.a="⋌","OP";case 281:return a.a="↝","OPS";case 282:return a.a="⇉","OPS";case 283:return a.a="⇌","OPS";case 284:return a.a="⇄","OPS";case 285:return a.a="⇀","OPS";case 286:return a.a="⇁","OPS";case 287:return a.a="⇾","OPS";case 288:return a.a="↣","OPS";case 289:return a.a="⇒","OPS";case 290:return a.a="→","OPS";case 291:return"RIGHT";case 292:return a.a="Ρ","A";case 293:return a.a="ρ","A";case 294:return a.a="⊳","OP";case 295:return a.a="⌋","OPFS";
-case 296:return a.a="ℜ","A";case 297:return a.a="⤰","OP";case 298:return a.a="⤫","OP";case 299:return a.a="⌉","OPFS";case 300:return a.a="]","OPFS";case 301:return a.a="}","OPFS";case 302:return a.a="⟩","OPFS";case 303:return a.a="⟩","OPFS";case 304:return a.a="≟","OP";case 305:return a.a="⨌","OP";case 306:return"QUAD";case 307:return"QQUAD";case 308:return a.a="▪","OP";case 309:return a.a="Ψ","A";case 310:return a.a="ψ","A";case 311:return a.a="∝","OP";case 312:return a.a="∏","OPM";case 313:return a.a=
-"∏","OPM";case 314:return a.a="′","OPP";case 315:return a.a="≾","OP";case 316:return a.a="⋨","OP";case 317:return a.a="⪵","OP";case 318:return a.a="⪹","OP";case 319:return a.a="⪯","OP";case 320:return a.a="≼","OP";case 321:return a.a="⪷","OP";case 322:return a.a="≺","OP";case 323:return"PMOD";case 324:return a.a="±","OP";case 325:return a.a="⨥","OP";case 326:return a.a="⊞","OP";case 327:return a.a="⋔","OP";case 328:return a.a="Π","A";case 329:return a.a="π","A";case 330:return a.a="Φ","A";case 331:return a.a=
-"ϕ","A";case 332:return"PHANTOM";case 333:return a.a="⫫","OP";case 334:return a.a="⊥","OP";case 335:return a.a="⪣","OP";case 336:return a.a="∂","OP";case 337:return a.a="⅋","OP";case 338:return a.a="∥","OP";case 339:return this.pushState("TEXTARG"),"PADDING";case 340:return"OVERSET";case 341:return a.a="¯","ACCENT";case 342:return"OVERBRACE";case 343:return"TEXOVER";case 344:return a.a="⨴","OP";case 345:return a.a="⊗","OP";case 346:return a.a="⊘","OP";case 347:return"OPS";case 348:return"OPP";case 349:return"OPM";
-case 350:return a.a="⨭","OP";case 351:return a.a="⊕","OP";case 352:return"OPFS";case 353:return"OPF";case 354:return this.k("TEXTARG"),"OPERATORNAME";case 355:return"OP";case 356:return a.a="⊖","OP";case 357:return a.a="ℴ","A";case 358:return a.a="Ω","A";case 359:return a.a="ω","A";case 360:return a.a="∮","OP";case 361:return a.a="∯","OP";case 362:return a.a="∰","OP";case 363:return a.a="⊙","OP";case 364:return a.a="⊝","OP";case 365:return a.a="⦸","OP";case 366:return a.a="⤲","OP";case 367:return a.a=
-"⇖","OPS";case 368:return a.a="↖","OPS";case 369:return a.a="⇖","OPS";case 370:return a.a="↖","OPS";case 371:return a.a="⊯","OP";case 372:return a.a="⊮","OP";case 373:return a.a="⊭","OP";case 374:return a.a="⊬","OP";case 375:return"NUM";case 376:return a.a="Ν","A";case 377:return a.a="ν","A";case 378:return a.a="⋭","OP";case 379:return a.a="⋫","OP";case 380:return a.a="⋬","OP";case 381:return a.a="⋪","OP";case 382:return a.a="⊉","OP";case 383:return a.a="⊅","OP";case 384:return a.a="≿̸","OP";case 385:return a.a=
-"⪰̸","OP";case 386:return a.a="⊁","OP";case 387:return a.a="⊈","OP";case 388:return a.a="⊈","OP";case 389:return a.a="⊄","OP";case 390:return a.a="≄","OP";case 391:return a.a="≁","OP";case 392:return a.a="∦","OP";case 393:return a.a="∤","OP";case 394:return a.a="⇏","OP";case 395:return a.a="↛","OP";case 396:return a.a="⪯̸","OP";case 397:return a.a="⊀","OP";case 398:return a.a="∦","OP";case 399:return a.a="∌","OP";case 400:return a.a="∉","OP";case 401:return a.a="¬","OP";case 402:return a.a="∤","OP";
-case 403:return a.a="≮","OP";case 404:return a.a="⩽̸","OP";case 405:return a.a="⩽̸","OP";case 406:return a.a="≰","OP";case 407:return a.a="⇎","OP";case 408:return a.a="↮","OP";case 409:return a.a="⇍","OP";case 410:return a.a="↚","OP";case 411:return a.a="∋","OP";case 412:return a.a="≯","OP";case 413:return a.a="⩾̸","OP";case 414:return a.a="⩾̸","OP";case 415:return a.a="≱","OP";case 416:return a.a="∄","OP";case 417:return a.a="≢","OP";case 418:return a.a="≂̸","OP";case 419:return a.a="≠","OP";case 420:return a.a=
-"⤮","OP";case 421:return a.a="⤱","OP";case 422:return"NEGTHICKSPACE";case 423:return"NEGSPACE";case 424:return"NEGMEDSPACE";case 425:return a.a="¬","OP";case 426:return a.a="⇗","OPS";case 427:return a.a="↗","OPS";case 428:return a.a="⇗","OPS";case 429:return a.a="↗","OPS";case 430:return a.a="≠","OP";case 431:return a.a="≇","OP";case 432:return a.a="≎̸","OP";case 433:return a.a="≏̸","OP";case 434:return a.a="♮","OP";case 435:return a.a="≉","OP";case 436:return a.a="∇","OP";case 437:return"MULTI";
-case 438:return a.a="⊸","OP";case 439:return a.a="Μ","A";case 440:return a.a="μ","A";case 441:return this.k("TEXTARG"),"MTEXT";case 442:return this.pushState("TEXTARG"),this.pushState("TEXTOPTARG"),this.pushState("TRYOPTARG"),this.pushState("TEXTOPTARG"),this.pushState("TRYOPTARG"),"MS";case 443:return a.a="∓","OP";case 444:return a.a="⊧","OP";case 445:return a.a="mod","MO";case 446:return this.pushState("TEXTARG"),"MO";case 447:return this.pushState("TEXTARG"),"MN";case 448:return a.a="⫛","OP";case 449:return a.a=
-"⨪","OP";case 450:return a.a="⊟","OP";case 451:return a.a="−","OP";case 452:return a.a=a.a.slice(1),"FM";case 453:return a.a="∣","OP";case 454:return this.pushState("TEXTARG"),"MI";case 455:return a.a="℧","A";case 456:return a.a="℧","A";case 457:return"MEDSPACE";case 458:return a.a="∡","OP";case 459:return"MATHTT";case 460:return"MATHSF";case 461:return"MATHSCR";case 462:return"MATHRM";case 463:return"MATHRLAP";case 464:return this.k("TEXTARG"),"MATHREL";case 465:return this.pushState("TEXTOPTARG"),
-this.pushState("TRYOPTARG"),this.pushState("TEXTOPTARG"),this.pushState("TRYOPTARG"),this.pushState("TEXTARG"),"MATHRAISEBOX";case 466:return this.k("TEXTARG"),"MATHOP";case 467:return"MATHIT";case 468:return"MATHLLAP";case 469:return"MATHIT";case 470:return"MATHFRAK";case 471:return"MATHFRAK";case 472:return"MATHCLAP";case 473:return"MATHSCR";case 474:return"MATHBSCR";case 475:return"MATHBIT";case 476:return this.k("TEXTARG"),"MATHBIN";case 477:return"MATHBF";case 478:return"MATHBSCR";case 479:return"MATHBB";
-case 480:return a.a="⤇","OP";case 481:return a.a="↦","OPS";case 482:return a.a="⤆","OP";case 483:return a.a="↦","OPS";case 484:return a.a="≨︀","OP";case 485:return a.a="≨︀","OP";case 486:return a.a="⋉","OP";case 487:return a.a="<","OP";case 488:return a.a="↰","OPS";case 489:return a.a="‘","OPF";case 490:return a.a="◊","OP";case 491:return a.a="⨜","OP";case 492:return a.a="↬","OPS";case 493:return a.a="↫","OPS";case 494:return a.a="⟹","OPS";case 495:return a.a="⟶","OPS";case 496:return a.a="⟼","OPS";
-case 497:return a.a="⟺","OPS";case 498:return a.a="⟷","OPS";case 499:return a.a="⟸","OPS";case 500:return a.a="⟵","OPS";case 501:return a.a="⋦","OP";case 502:return a.a="≨","OP";case 503:return a.a="⪇","OP";case 504:return a.a="⪉","OP";case 505:return a.a="⎰","OP";case 506:return a.a="⋘","OP";case 507:return a.a="⇚","OPS";case 508:return a.a="⟪","OPFS";case 509:return a.a="≪","OP";case 510:return a.a="⊲","OP";case 511:return a.a="⌊","OPFS";case 512:return a.a="≲","OP";case 513:return a.a="≶","OP";
-case 514:return a.a="⪋","OP";case 515:return a.a="⋚","OP";case 516:return a.a="⋖","OP";case 517:return a.a="⪅","OP";case 518:return a.a="<","OP";case 519:return a.a="⩽","OP";case 520:return a.a="≦","OP";case 521:return a.a="≤","OP";case 522:return a.a="⟳","OP";case 523:return a.a="⋋","OP";case 524:return a.a="↜","OPS";case 525:return a.a="↭","OPS";case 526:return a.a="⇋","OPS";case 527:return a.a="⇿","OPS";case 528:return a.a="⇆","OPS";case 529:return a.a="⇔","OPS";case 530:return a.a="↔","OPS";case 531:return a.a=
-"⇇","OPS";case 532:return a.a="↼","OPS";case 533:return a.a="↽","OPS";case 534:return a.a="⇽","OPS";case 535:return a.a="↢","OPS";case 536:return a.a="⇐","OPS";case 537:return a.a="←","OPS";case 538:return"LEFT";case 539:return a.a="≤","OP";case 540:return a.a="…","OP";case 541:return a.a="⌈","OPFS";case 542:return a.a="[","OPFS";case 543:return a.a="{","OPFS";case 544:return a.a="⟨","OPFS";case 545:return a.a="⟨","OPFS";case 546:return a.a="Λ","A";case 547:return a.a="λ","A";case 548:return a.a=
-"∻","OP";case 549:return a.a="Κ","A";case 550:return a.a="κ","A";case 551:return a.a="ȷ","A";case 552:return this.pushState("TEXTARG"),"MN";case 553:return a.a="Ι","A";case 554:return a.a="ι","A";case 555:return a.a="⅋","OP";case 556:return a.a="⨘","OP";case 557:return a.a="⨽","OP";case 558:return a.a="⨼","OP";case 559:return a.a="⋂","OPM";case 560:return a.a="∩","OP";case 561:return a.a="⫴","OP";case 562:return a.a="⊺","OP";case 563:return a.a="∫","OP";case 564:return a.a="⨚","OP";case 565:return a.a=
-"⨙","OP";case 566:return a.a="⨎","OP";case 567:return a.a="⨍","OP";case 568:return a.a="∫","OP";case 569:return a.a="∞","NUM";case 570:return a.a="∞","NUM";case 571:return a.a=a.a.slice(1),"FM";case 572:return a.a="∊","OP";case 573:return a.a="⇒","OPS";case 574:return a.a="⇐","OPS";case 575:return a.a="ı","A";case 576:return a.a="ℑ","A";case 577:return a.a="∬","OP";case 578:return a.a="∭","OP";case 579:return a.a="⨌","OP";case 580:return a.a="⟺","OPS";case 581:return a.a="ℏ","A";case 582:return this.pushState("TEXTARG"),
-"HREF";case 583:return a.a="↪","OPS";case 584:return a.a="↩","OPS";case 585:return a.a="⤦","OP";case 586:return a.a="⤥","OP";case 587:return a.a="♡","OP";case 588:return a.a="ℏ","A";case 589:return a.a="^","ACCENTNS";case 590:return a.a="≩︀","OP";case 591:return a.a="≩︀","OP";case 592:return a.a="≳","OP";case 593:return a.a="≷","OP";case 594:return a.a="⪌","OP";case 595:return a.a="⋛","OP";case 596:return a.a="⋗","OP";case 597:return a.a="⪆","OP";case 598:return a.a=">","OP";case 599:return a.a=">",
-"OP";case 600:return a.a="⋧","OP";case 601:return a.a="≩","OP";case 602:return a.a="⪈","OP";case 603:return a.a="⪊","OP";case 604:return a.a="ℷ","A";case 605:return a.a="⋙","OP";case 606:return a.a="≫","OP";case 607:return a.a="⩾","OP";case 608:return a.a="≧","OP";case 609:return a.a="≥","OP";case 610:return a.a="≥","OP";case 611:return a.a="Γ","A";case 612:return a.a="γ","A";case 613:return a.a="⌢","OP";case 614:return this.pushState("TEXTARG"),"FRAME";case 615:return"FRAC";case 616:return a.a="⫝",
-"OP";case 617:return a.a="⫝̸","OP";case 618:return a.a="∀","OP";case 619:return a.a="♭","OP";case 620:return a.a="⤬","OP";case 621:return a.a="⤯","OP";case 622:return a.a="≒","OP";case 623:return a.a="∃","OP";case 624:return a.a="ð","A";case 625:return a.a="ð","A";case 626:return a.a="Η","A";case 627:return a.a="η","A";case 628:return a.a="≡","OP";case 629:return this.pushState("TEXTARG"),"EQROWS";case 630:return this.pushState("TEXTARG"),"EQCOLS";case 631:return a.a="⪕","OP";case 632:return a.a=
-"⪖","OP";case 633:return a.a="≂","OP";case 634:return a.a="=∷","OP";case 635:return a.a="≕","OP";case 636:return a.a="−∷","OP";case 637:return a.a="=∷","OP";case 638:return a.a="=∷","OP";case 639:return a.a="=∷","OP";case 640:return a.a="≕","OP";case 641:return a.a="≖","OP";case 642:return a.a="ϵ","A";case 643:return"EVVMATRIX";case 644:return"EVMATRIX";case 645:return"ETOGGLE";case 646:return"EALIGNED";case 647:return"ESMALLMATRIX";case 648:return"EPMATRIX";case 649:return"EMATRIX";case 650:return"EGATHERED";
-case 651:return"ECASES";case 652:return"EBBMATRIX";case 653:return"EBMATRIX";case 654:return"EARRAY";case 655:return"EALIGNED";case 656:return a.a="∅","A";case 657:return a.a="∅","A";case 658:return a.a="↪","OPS";case 659:return a.a="ℓ","A";case 660:return a.a="↕","OPS";case 661:return a.a="⧟","OP";case 662:return a.a="⤐","OPS";case 663:return a.a="↕","OPS";case 664:return a.a="⇂","OPS";case 665:return a.a="⇃","OPS";case 666:return a.a="⇊","OPS";case 667:return a.a="⇓","OPS";case 668:return a.a="↓",
-"OPS";case 669:return a.a="∬","OP";case 670:return a.a="⌆","OP";case 671:return a.a="⌆","OP";case 672:return a.a="…","OP";case 673:return a.a="∔","OP";case 674:return a.a="∸","OP";case 675:return a.a="≑","OP";case 676:return a.a="≑","OP";case 677:return a.a="≐","OP";case 678:return a.a="˙","ACCENT";case 679:return a.a="⋇","OP";case 680:return a.a="÷","OP";case 681:return"DISPLAYSTYLE";case 682:return a.a="⨈","OPM";case 683:return a.a="ϝ","A";case 684:return a.a="♢","OP";case 685:return a.a="⋄","OP";
-case 686:return a.a="⋄","OP";case 687:return a.a=a.a.slice(1),"FM";case 688:return a.a="Δ","A";case 689:return a.a="δ","A";case 690:return a.a="∇","OP";case 691:return a.a="°","OP";case 692:return a.a="⤋","OPS";case 693:return a.a="⩷","OP";case 694:return a.a="⋱","OP";case 695:return a.a="̈","ACCENT";case 696:return a.a="⃛","OP";case 697:return a.a="⃛","ACCENT";case 698:return a.a="⃜","OP";case 699:return a.a="⃜","ACCENT";case 700:return a.a="‡","OP";case 701:return a.a="∷","OP";case 702:return a.a=
-"⤏","OPS";case 703:return a.a="⫤","OP";case 704:return a.a="⫣","OP";case 705:return a.a="⊣","OP";case 706:return a.a="⤏","OPS";case 707:return a.a="⤎","OPS";case 708:return a.a="↓","OPS";case 709:return a.a="ℸ","A";case 710:return a.a="†","OP";case 711:return a.a="↷","OP";case 712:return a.a="↶","OP";case 713:return a.a="⤻","OP";case 714:return a.a="⋏","OP";case 715:return a.a="⋎","OP";case 716:return a.a="⋟","OP";case 717:return a.a="⋞","OP";case 718:return a.a="⊍","OP";case 719:return a.a="⋓","OP";
-case 720:return a.a="∪","OP";case 721:return a.a="∐","OPM";case 722:return a.a="∐","OPM";case 723:return a.a="∮","OP";case 724:return a.a="⨇","OPM";case 725:return a.a="∮","OP";case 726:return a.a="≅","OP";case 727:return a.a="∁","OP";case 728:return this.k("TEXTARG"),"COLSPAN";case 729:return this.pushState("TEXTARG"),"COLOR";case 730:return a.a="∷∼","OP";case 731:return a.a="∶∼","OP";case 732:return a.a="⩴","OP";case 733:return a.a="≔","OP";case 734:return a.a="∷−","OP";case 735:return a.a="≔",
-"OP";case 736:return a.a="∷≈","OP";case 737:return a.a="∶≈","OP";case 738:return a.a="∷","OP";case 739:return a.a=":","OP";case 740:return this.pushState("TEXTARG"),"COLLINES";case 741:return this.pushState("TEXTARG"),"COLLAYOUT";case 742:return this.k("TEXTARG"),"COLALIGN";case 743:return a.a="♣","OP";case 744:return a.a="¯","ACCENT";case 745:return a.a="⊝","OP";case 746:return a.a="⊚","OP";case 747:return a.a="⊛","OP";case 748:return a.a="⥁","OP";case 749:return a.a="⥀","OP";case 750:return a.a=
-"≗","OP";case 751:return a.a="∘","OP";case 752:return"TEXCHOOSE";case 753:return a.a="χ","A";case 754:return a.a="ˇ","ACCENTNS";case 755:return"CELLOPTS";case 756:return a.a="⋯","OP";case 757:return a.a="·","OP";case 758:return a.a="⋅","OP";case 759:return a.a="⋒","OP";case 760:return a.a="∩","OP";case 761:return a.a="⪮","OP";case 762:return a.a="≎","OP";case 763:return a.a="≏","OP";case 764:return a.a="•","OP";case 765:return a.a="⨲","OP";case 766:return a.a="⊠","OP";case 767:return a.a="⊞","OP";
-case 768:return a.a="⊟","OP";case 769:return"BOXED";case 770:return a.a="⊡","OP";case 771:return a.a="⧄","OP";case 772:return a.a="⧇","OP";case 773:return a.a="⧅","OP";case 774:return a.a="⧆","OP";case 775:return a.a="□","OP";case 776:return a.a="⋈","OP";case 777:return a.a="⊥","OP";case 778:return a.a="⊥","OP";case 779:return"MATHBF";case 780:return a.a="▸","OP";case 781:return a.a="◂","OP";case 782:return a.a="▾","OP";case 783:return a.a="▴","OP";case 784:return a.a="■","OP";case 785:return a.a=
-"⧫","OP";case 786:return a.a="⤍","OPS";case 787:return"BINOM";case 788:return a.a="⋀","OPM";case 789:return a.a="⋁","OPM";case 790:return a.a="⨄","OPM";case 791:return a.a="△","OP";case 792:return a.a="▽","OP";case 793:return a.a="⨉","OPM";case 794:return a.a="★","OP";case 795:return a.a="⨆","OPM";case 796:return a.a="⨅","OPM";case 797:return"BBIG";case 798:return"BIG";case 799:return a.a="⨂","OPM";case 800:return a.a="⨁","OPM";case 801:return a.a="⨀","OPM";case 802:return"BBIGL";case 803:return"BIGL";
-case 804:return a.a="⫼","OPM";case 805:return"BBIGG";case 806:return"BIGG";case 807:return"BBIGGL";case 808:return"BIGGL";case 809:return"BBIGG";case 810:return"BIGG";case 811:return a.a="⨃","OPM";case 812:return a.a="⋃","OPM";case 813:return a.a="○","OP";case 814:return a.a="⋂","OPM";case 815:return"BBIG";case 816:return"BIG";case 817:return this.pushState("TEXTARG"),"BGCOLOR";case 818:return a.a="≬","OP";case 819:return a.a="ℶ","A";case 820:return a.a="Β","A";case 821:return a.a="β","A";case 822:return"BVVMATRIX";
-case 823:return"BVMATRIX";case 824:return"BTOGGLE";case 825:return"BALIGNED";case 826:return"BSMALLMATRIX";case 827:return"BPMATRIX";case 828:return"BMATRIX";case 829:return"BGATHERED";case 830:return"BCASES";case 831:return"BBBMATRIX";case 832:return"BBMATRIX";case 833:return this.pushState("TEXTARG"),this.pushState("TEXTOPTARG"),this.pushState("TRYOPTARG"),"BARRAY";case 834:return"BALIGNED";case 835:return a.a="∵","OP";case 836:return a.a="ℿ","A";case 837:return a.a="⌅","OP";case 838:return a.a=
-"¯","ACCENTNS";case 839:return a.a="\\","OP";case 840:return a.a="⋍","OP";case 841:return a.a="∽","OP";case 842:return a.a="‵","OPP";case 843:return a.a="϶","OP";case 844:return"TEXATOP";case 845:return a.a="≍","OP";case 846:return a.a="∗","OP";case 847:return"ARRAYOPTS";case 848:return"ARRAY";case 849:return a.a=a.a.slice(1),"F";case 850:return a.a="≊","OP";case 851:return a.a="≈","OP";case 852:return a.a="∠","OP";case 853:return a.a="⨿","OP";case 854:return a.a="Α","A";case 855:return a.a="α","A";
-case 856:return this.pushState("TEXTARG"),"ALIGN";case 857:return a.a="ℵ","A";case 858:return a.a="⋰","OP";case 859:return a.a="Å","A";case 860:return"A";case 861:return a.a="%","A";case 862:return a.a="#","OP";case 863:return a.a="&","A";case 864:return a.a="$","A";case 865:return a.a="}","OPFS";case 866:return a.a="{","OPFS";case 867:return"NEGSPACE";case 868:return"MEDSPACE";case 869:return"THICKSPACE";case 870:return"THINSPACE";case 871:return a.a="‖","OPFS";case 872:return a.a="⁗","OPP";case 873:return a.a=
-"‴","OPP";case 874:return a.a="″","OPP";case 875:return a.a="′","OPP";case 876:return"HIGH_SURROGATE";case 877:return"LOW_SURROGATE";case 878:return"BMP_CHARACTER"}},rules:[/^(?:.)/,/^(?:\$\$|\\\[|\$|\\\()/,/^(?:$)/,/^(?:\\[$\\])/,/^(?:[<&>])/,/^(?:[^])/,/^(?:\s*\[)/,/^(?:.)/,/^(?:([^\\\]]|(\\[\\\]]))+)/,/^(?:\])/,/^(?:\s*\{)/,/^(?:([^\\\}]|(\\[\\\}]))+)/,/^(?:\})/,/^(?:\])/,/^(?:\s+)/,/^(?:\$\$|\\\]|\$|\\\))/,/^(?:\{)/,/^(?:\})/,/^(?:\^)/,/^(?:_)/,/^(?:\.)/,/^(?:&)/,/^(?:\\\\)/,/^(?:[0-9]+(?:\.[0-9]+)?|[\u0660-\u0669]+(?:\u066B[\u0660-\u0669]+)?|(?:\uD835[\uDFCE-\uDFD7])+|(?:\uD835[\uDFCE-\uDFD7])+|(?:\uD835[\uDFD8-\uDFE1])+|(?:\uD835[\uDFE2-\uDFEB])+|(?:\uD835[\uDFEC-\uDFF5])+|(?:\uD835[\uDFF6-\uDFFF])+)/,
-/^(?:[a-zA-Z]+)/,/^(?:\\Zeta)/,/^(?:\\zeta)/,/^(?:\\xrightleftharpoons)/,/^(?:\\xRightarrow)/,/^(?:\\xrightarrow)/,/^(?:\\xmapsto)/,/^(?:\\xleftrightharpoons)/,/^(?:\\xLeftrightarrow)/,/^(?:\\xleftrightarrow)/,/^(?:\\xLeftarrow)/,/^(?:\\xleftarrow)/,/^(?:\\Xi)/,/^(?:\\xi)/,/^(?:\\xhookrightarrow)/,/^(?:\\xhookleftarrow)/,/^(?:\\wr)/,/^(?:\\wp)/,/^(?:\\widevec)/,/^(?:\\widetilde)/,/^(?:\\widehat)/,/^(?:\\widecheck)/,/^(?:\\widebar)/,/^(?:\\wedgeq)/,/^(?:\\Wedge)/,/^(?:\\wedge)/,/^(?:\\Vvert)/,/^(?:\\Vvdash)/,
-/^(?:\\Vert)/,/^(?:\\vert)/,/^(?:\\veebar)/,/^(?:\\Vee)/,/^(?:\\vee)/,/^(?:\\vec)/,/^(?:\\vdots)/,/^(?:\\VDash)/,/^(?:\\Vdash)/,/^(?:\\vDash)/,/^(?:\\vdash)/,/^(?:\\Vbar)/,/^(?:\\vartriangleright)/,/^(?:\\vartriangleleft)/,/^(?:\\vartriangle)/,/^(?:\\vartheta)/,/^(?:\\varsupsetneqq)/,/^(?:\\varsupsetneq)/,/^(?:\\varsubsetneqq)/,/^(?:\\varsubsetneqq)/,/^(?:\\varsubsetneq)/,/^(?:\\varsigma)/,/^(?:\\varrho)/,/^(?:\\varpropto)/,/^(?:\\varpi)/,/^(?:\\varphi)/,/^(?:\\varnothing)/,/^(?:\\varkappa)/,/^(?:\\varepsilon)/,
-/^(?:\\Uuparrow)/,/^(?:\\upuparrows)/,/^(?:\\Upsilon)/,/^(?:\\upsilon)/,/^(?:\\Upsi)/,/^(?:\\uplus)/,/^(?:\\upint)/,/^(?:\\upharpoonright)/,/^(?:\\upharpoonleft)/,/^(?:\\Updownarrow)/,/^(?:\\updownarrow)/,/^(?:\\updarr)/,/^(?:\\Uparrow)/,/^(?:\\uparrow)/,/^(?:\\uparr)/,/^(?:\\unrhd)/,/^(?:\\unlhd)/,/^(?:\\Union)/,/^(?:\\union)/,/^(?:\\underset)/,/^(?:\\underoverset)/,/^(?:\\underline)/,/^(?:\\underbrace)/,/^(?:\\udots)/,/^(?:\u2ADD\u0338)/,/^(?:\u2ACC\uFE00)/,/^(?:\u2ACB\uFE00)/,/^(?:\u2AB0\u0338)/,
-/^(?:\u2AAF\u0338)/,/^(?:\u2AA2\u0338)/,/^(?:\u2AA1\u0338)/,/^(?:\u2A7E\u0338)/,/^(?:\u2A7D\u0338)/,/^(?:\u29D0\u0338)/,/^(?:\u29CF\u0338)/,/^(?:\u2290\u0338)/,/^(?:\u228F\u0338)/,/^(?:\u228B\uFE00)/,/^(?:\u228A\uFE00)/,/^(?:\u2283\u20D2)/,/^(?:\u2282\u20D2)/,/^(?:\u227F\u0338)/,/^(?:\u226B\u0338)/,/^(?:\u226A\u0338)/,/^(?:\u2269\uFE00)/,/^(?:\u2268\uFE00)/,/^(?:\u2266\u0338)/,/^(?:\u224F\u0338)/,/^(?:\u224E\u0338)/,/^(?:\u2242\u0338)/,/^(?:\u223D\u0331)/,/^(?:\u2237\u2248)/,/^(?:\u2237\u223C)/,/^(?:\u2237\u2212)/,
-/^(?:\u2236\u2248)/,/^(?:\u2236\u223C)/,/^(?:\u2212\u2237)/,/^(?:\u007C\u007C\u007C)/,/^(?:\u007C\u007C)/,/^(?:\u003E\u003D)/,/^(?:\u003D\u2237)/,/^(?:\u003D\u2237)/,/^(?:\u003D\u003D)/,/^(?:\u003C\u003E)/,/^(?:\u003C\u003D)/,/^(?:\u003A\u003D)/,/^(?:\u002F\u003D)/,/^(?:\u002F\u002F)/,/^(?:\u002E\u002E\u002E)/,/^(?:\u002E\u002E)/,/^(?:\u002D\u003E)/,/^(?:\u002D\u003D)/,/^(?:\u002D\u002D)/,/^(?:\u002B\u003D)/,/^(?:\u002B\u002B)/,/^(?:\u002A\u003D)/,/^(?:\u002A\u002A)/,/^(?:\u0026\u0026)/,/^(?:\u0021\u003D)/,
-/^(?:\u0021\u0021)/,/^(?:\\twoheadrightarrowtail)/,/^(?:\\twoheadrightarrow)/,/^(?:\\twoheadleftarrow)/,/^(?:\\tripleintegral)/,/^(?:\\trianglerighteq)/,/^(?:\\triangleright)/,/^(?:\\triangleq)/,/^(?:\\trianglelefteq)/,/^(?:\\triangleleft)/,/^(?:\\triangledown)/,/^(?:\\triangle)/,/^(?:\\towa)/,/^(?:\\tosa)/,/^(?:\\top)/,/^(?:\\tooltip)/,/^(?:\\tona)/,/^(?:\\toggle)/,/^(?:\\toea)/,/^(?:\\to)/,/^(?:\\timesb)/,/^(?:\\times)/,/^(?:\\tilde)/,/^(?:\\thinspace)/,/^(?:\\thickspace)/,/^(?:\\thicksim)/,/^(?:\\thickapprox)/,
-/^(?:\\Theta)/,/^(?:\\theta)/,/^(?:\\therefore)/,/^(?:\\tfrac)/,/^(?:\\textstyle)/,/^(?:\\textsize)/,/^(?:\\textquotedblright)/,/^(?:\\textquotedblleft)/,/^(?:\\textasciitilde)/,/^(?:\\textasciigrave)/,/^(?:\\textasciicircumflex)/,/^(?:\\textasciiacute)/,/^(?:\\text)/,/^(?:\\tensor)/,/^(?:\\tbinom)/,/^(?:\\Tau)/,/^(?:\\tau)/,/^(?:\\swArrow)/,/^(?:\\swarrow)/,/^(?:\\swArr)/,/^(?:\\swarr)/,/^(?:\\surd)/,/^(?:\\supsetneqq)/,/^(?:\\supsetneq)/,/^(?:\\supseteqq)/,/^(?:\\supseteq)/,/^(?:\\Supset)/,/^(?:\\supset)/,
-/^(?:\\sum)/,/^(?:\\succsim)/,/^(?:\\succnsim)/,/^(?:\\succneqq)/,/^(?:\\succnapprox)/,/^(?:\\succeq)/,/^(?:\\succcurlyeq)/,/^(?:\\succapprox)/,/^(?:\\succ)/,/^(?:\\substack)/,/^(?:\\subsetneqq)/,/^(?:\\subsetneq)/,/^(?:\\subseteqq)/,/^(?:\\subseteq)/,/^(?:\\Subset)/,/^(?:\\subset)/,/^(?:\\statusline)/,/^(?:\\star)/,/^(?:\\stackrel)/,/^(?:\\sslash)/,/^(?:\\square)/,/^(?:\\sqsupseteq)/,/^(?:\\sqsupset)/,/^(?:\\sqsubseteq)/,/^(?:\\sqsubset)/,/^(?:\\sqrt)/,/^(?:\\sqcup)/,/^(?:\\sqcap)/,/^(?:\\sphericalangle)/,
-/^(?:\\spadesuit)/,/^(?:\\space)/,/^(?:\\smile)/,/^(?:\\smallsmile)/,/^(?:\\smallsetminus)/,/^(?:\\smallfrown)/,/^(?:\\slash)/,/^(?:\\simeq)/,/^(?:\\sim)/,/^(?:\\Sigma)/,/^(?:\\sigma)/,/^(?:\\shuffle)/,/^(?:\\shortparallel)/,/^(?:\\shortmid)/,/^(?:\\sharp)/,/^(?:\\setminus)/,/^(?:\\seovnearrow)/,/^(?:\\seArrow)/,/^(?:\\searrow)/,/^(?:\\seArr)/,/^(?:\\searr)/,/^(?:\\scriptsize)/,/^(?:\\scriptscriptsize)/,/^(?:\\rtimes)/,/^(?:\\Rsh)/,/^(?:\\Rrightarrow)/,/^(?:\\rrangle)/,/^(?:\\rq)/,/^(?:\\rowspan)/,
-/^(?:\\rowopts)/,/^(?:\\rowlines)/,/^(?:\\rowalign)/,/^(?:\\root)/,/^(?:\\rmoustache)/,/^(?:\\risingdotseq)/,/^(?:\\righttoleftarrow)/,/^(?:\\rightthreetimes)/,/^(?:\\rightsquigarrow)/,/^(?:\\rightrightarrows)/,/^(?:\\rightleftharpoons)/,/^(?:\\rightleftarrows)/,/^(?:\\rightharpoonup)/,/^(?:\\rightharpoondown)/,/^(?:\\rightarrowtriangle)/,/^(?:\\rightarrowtail)/,/^(?:\\Rightarrow)/,/^(?:\\rightarrow)/,/^(?:\\right)/,/^(?:\\Rho)/,/^(?:\\rho)/,/^(?:\\rhd)/,/^(?:\\rfloor)/,/^(?:\\Re)/,/^(?:\\rdiagovsearrow)/,
-/^(?:\\rdiagovfdiag)/,/^(?:\\rceil)/,/^(?:\\rbrack)/,/^(?:\\rbrace)/,/^(?:\\rangle)/,/^(?:\\rang)/,/^(?:\\questeq)/,/^(?:\\quadrupleintegral)/,/^(?:\\quad)/,/^(?:\\qquad)/,/^(?:\\qed)/,/^(?:\\Psi)/,/^(?:\\psi)/,/^(?:\\propto)/,/^(?:\\product)/,/^(?:\\prod)/,/^(?:\\prime)/,/^(?:\\precsim)/,/^(?:\\precnsim)/,/^(?:\\precneqq)/,/^(?:\\precnapprox)/,/^(?:\\preceq)/,/^(?:\\preccurlyeq)/,/^(?:\\precapprox)/,/^(?:\\prec)/,/^(?:\\pmod)/,/^(?:\\pm)/,/^(?:\\plusdot)/,/^(?:\\plusb)/,/^(?:\\pitchfork)/,/^(?:\\Pi)/,
-/^(?:\\pi)/,/^(?:\\Phi)/,/^(?:\\phi)/,/^(?:\\phantom)/,/^(?:\\Perp)/,/^(?:\\perp)/,/^(?:\\partialmeetcontraction)/,/^(?:\\partial)/,/^(?:\\parr)/,/^(?:\\parallel)/,/^(?:\\padding)/,/^(?:\\overset)/,/^(?:\\overline)/,/^(?:\\overbrace)/,/^(?:\\over)/,/^(?:\\Otimes)/,/^(?:\\otimes)/,/^(?:\\oslash)/,/^(?:[\u007E\u00AF\u02C6\u02C7\u02C9\u02CD\u02DC\u02F7\u0302\u203E\u2044\u2190-\u2199\u219C-\u21AD\u21AF-\u21B5\u21B9\u21BC-\u21CC\u21D0-\u21DD\u21E0-\u21F0\u21F3\u21F5\u21F6\u21FD-\u21FF\u2215\u221A\u23B4\u23B5\u23DC-\u23E1\u27F0\u27F1\u27F5-\u27FF\u290A-\u2910\u2912\u2913\u2921\u2922\u294E-\u2961\u296E\u296F\u2B45\u2B46])/,
-/^(?:[\u2032-\u2035\u2057])/,/^(?:[\u220F-\u2211\u22C0-\u22C3\u2A00-\u2A0A\u2A10-\u2A14\u2AFC\u2AFF])/,/^(?:\\Oplus)/,/^(?:\\oplus)/,/^(?:[\u0028\u0029\u005B\u005D\u007C\u2016\u2308-\u230B\u2329\u232A\u2772\u2773\u27E6-\u27EF\u2980\u2983-\u2998\u29FC\u29FD])/,/^(?:[\u2018\u2019\u201C\u201D])/,/^(?:\\operatorname)/,/^(?:[\u0021-\u0023\u002A-\u002D\u002F\u003A-\u0040\u0060\u00A8\u00AA\u00AC\u00B0-\u00B4\u00B7-\u00BA\u00D7\u00F7\u02CA\u02CB\u02D8-\u02DA\u02DD\u0311\u03F6\u201A\u201B\u201E-\u2022\u2026\u2036\u2037\u2043\u2061-\u2064\u20DB\u20DC\u2145\u2146\u214B\u219A\u219B\u21AE\u21B6-\u21B8\u21BA\u21BB\u21CD-\u21CF\u21DE\u21DF\u21F1\u21F2\u21F4\u21F7-\u21FC\u2200-\u2204\u2206-\u220E\u2212-\u2214\u2216-\u2219\u221B-\u221D\u221F-\u22BF\u22C4-\u22FF\u2305\u2306\u2322\u2323\u23B0\u23B1\u25A0\u25A1\u25AA\u25AB\u25AD-\u25B9\u25BC-\u25CF\u25D6\u25D7\u25E6\u2605\u2660-\u2663\u266D-\u266F\u2758\u27F2\u27F3\u2900-\u2909\u2911\u2914-\u2920\u2923-\u294D\u2962-\u296D\u2970-\u297F\u2981\u2982\u2999-\u29D9\u29DB-\u29FB\u29FE\u29FF\u2A0B-\u2A0F\u2A15-\u2ADB\u2ADD-\u2AFB\u2AFD\u2AFE])/,
-/^(?:\\ominus)/,/^(?:\\omicron)/,/^(?:\\Omega)/,/^(?:\\omega)/,/^(?:\\oint)/,/^(?:\\oiint)/,/^(?:\\oiiint)/,/^(?:\\odot)/,/^(?:\\odash)/,/^(?:\\obslash)/,/^(?:\\nwovnearrow)/,/^(?:\\nwArrow)/,/^(?:\\nwarrow)/,/^(?:\\nwArr)/,/^(?:\\nwarr)/,/^(?:\\nVDash)/,/^(?:\\nVdash)/,/^(?:\\nvDash)/,/^(?:\\nvdash)/,/^(?:\u221E)/,/^(?:\\Nu)/,/^(?:\\nu)/,/^(?:\\ntrianglerighteq)/,/^(?:\\ntriangleright)/,/^(?:\\ntrianglelefteq)/,/^(?:\\ntriangleleft)/,/^(?:\\nsupseteq)/,/^(?:\\nsupset)/,/^(?:\\nsuccsim)/,/^(?:\\nsucceq)/,
-/^(?:\\nsucc)/,/^(?:\\nsubseteqq)/,/^(?:\\nsubseteq)/,/^(?:\\nsubset)/,/^(?:\\nsime)/,/^(?:\\nsim)/,/^(?:\\nshortparallel)/,/^(?:\\nshortmid)/,/^(?:\\nRightarrow)/,/^(?:\\nrightarrow)/,/^(?:\\npreceq)/,/^(?:\\nprec)/,/^(?:\\nparallel)/,/^(?:\\notni)/,/^(?:\\notin)/,/^(?:\\not)/,/^(?:\\nmid)/,/^(?:\\nless)/,/^(?:\\nleqslant)/,/^(?:\\nleqq)/,/^(?:\\nleq)/,/^(?:\\nLeftrightarrow)/,/^(?:\\nleftrightarrow)/,/^(?:\\nLeftarrow)/,/^(?:\\nleftarrow)/,/^(?:\\ni)/,/^(?:\\ngtr)/,/^(?:\\ngeqslant)/,/^(?:\\ngeqq)/,
-/^(?:\\ngeq)/,/^(?:\\nexists)/,/^(?:\\nequiv)/,/^(?:\\neqsim)/,/^(?:\\neq)/,/^(?:\\neovsearrow)/,/^(?:\\neovnwarrow)/,/^(?:\\negthickspace)/,/^(?:\\negspace)/,/^(?:\\negmedspace)/,/^(?:\\neg)/,/^(?:\\neArrow)/,/^(?:\\nearrow)/,/^(?:\\neArr)/,/^(?:\\nearr)/,/^(?:\\ne)/,/^(?:\\ncong)/,/^(?:\\nBumpeq)/,/^(?:\\nbumpeq)/,/^(?:\\natural)/,/^(?:\\napprox)/,/^(?:\\nabla)/,/^(?:\\multiscripts)/,/^(?:\\multimap)/,/^(?:\\Mu)/,/^(?:\\mu)/,/^(?:\\mtext)/,/^(?:\\ms)/,/^(?:\\mp)/,/^(?:\\models)/,/^(?:\\mod)/,/^(?:\\mo)/,
-/^(?:\\mn)/,/^(?:\\mlcp)/,/^(?:\\minusdot)/,/^(?:\\minusb)/,/^(?:\\minus)/,/^(?:\\min)/,/^(?:\\mid)/,/^(?:\\mi)/,/^(?:\\mho)/,/^(?:\\mho)/,/^(?:\\medspace)/,/^(?:\\measuredangle)/,/^(?:\\mathtt)/,/^(?:\\mathsf)/,/^(?:\\mathscr)/,/^(?:\\mathrm)/,/^(?:\\mathrlap)/,/^(?:\\mathrel)/,/^(?:\\mathraisebox)/,/^(?:\\mathop)/,/^(?:\\mathmit)/,/^(?:\\mathllap)/,/^(?:\\mathit)/,/^(?:\\mathfrak)/,/^(?:\\mathfr)/,/^(?:\\mathclap)/,/^(?:\\mathcal)/,/^(?:\\mathbscr)/,/^(?:\\mathbit)/,/^(?:\\mathbin)/,/^(?:\\mathbf)/,
-/^(?:\\mathbcal)/,/^(?:\\mathbb)/,/^(?:\\Mapsto)/,/^(?:\\mapsto)/,/^(?:\\Mapsfrom)/,/^(?:\\map)/,/^(?:\\lvertneqq)/,/^(?:\\lvertneqq)/,/^(?:\\ltimes)/,/^(?:\\lt)/,/^(?:\\Lsh)/,/^(?:\\lq)/,/^(?:\\lozenge)/,/^(?:\\lowint)/,/^(?:\\looparrowright)/,/^(?:\\looparrowleft)/,/^(?:\\Longrightarrow)/,/^(?:\\longrightarrow)/,/^(?:\\longmapsto)/,/^(?:\\Longleftrightarrow)/,/^(?:\\longleftrightarrow)/,/^(?:\\Longleftarrow)/,/^(?:\\longleftarrow)/,/^(?:\\lnsim)/,/^(?:\\lneqq)/,/^(?:\\lneq)/,/^(?:\\lnapprox)/,/^(?:\\lmoustache)/,
-/^(?:\\lll)/,/^(?:\\Lleftarrow)/,/^(?:\\llangle)/,/^(?:\\ll)/,/^(?:\\lhd)/,/^(?:\\lfloor)/,/^(?:\\lesssim)/,/^(?:\\lessgtr)/,/^(?:\\lesseqqgtr)/,/^(?:\\lesseqgtr)/,/^(?:\\lessdot)/,/^(?:\\lessapprox)/,/^(?:\\less)/,/^(?:\\leqslant)/,/^(?:\\leqq)/,/^(?:\\leq)/,/^(?:\\lefttorightarrow)/,/^(?:\\leftthreetimes)/,/^(?:\\leftsquigarrow)/,/^(?:\\leftrightsquigarrow)/,/^(?:\\leftrightharpoons)/,/^(?:\\leftrightarrowtria\*)/,/^(?:\\leftrightarrows)/,/^(?:\\Leftrightarrow)/,/^(?:\\leftrightarrow)/,/^(?:\\leftleftarrows)/,
-/^(?:\\leftharpoonup)/,/^(?:\\leftharpoondown)/,/^(?:\\leftarrowtriangle)/,/^(?:\\leftarrowtail)/,/^(?:\\Leftarrow)/,/^(?:\\leftarrow)/,/^(?:\\left)/,/^(?:\\le)/,/^(?:\\ldots)/,/^(?:\\lceil)/,/^(?:\\lbrack)/,/^(?:\\lbrace)/,/^(?:\\langle)/,/^(?:\\lang)/,/^(?:\\Lambda)/,/^(?:\\lambda)/,/^(?:\\kernelcontraction)/,/^(?:\\Kappa)/,/^(?:\\kappa)/,/^(?:\\jmath)/,/^(?:\\itexnum)/,/^(?:\\Iota)/,/^(?:\\iota)/,/^(?:\\invamp)/,/^(?:\\intx)/,/^(?:\\intprodr)/,/^(?:\\intprod)/,/^(?:\\Intersection)/,/^(?:\\intersection)/,
-/^(?:\\interleave)/,/^(?:\\intercal)/,/^(?:\\integral)/,/^(?:\\intcup)/,/^(?:\\intcap)/,/^(?:\\intBar)/,/^(?:\\intbar)/,/^(?:\\int)/,/^(?:\\infty)/,/^(?:\\infinity)/,/^(?:\\inf)/,/^(?:\\in)/,/^(?:\\implies)/,/^(?:\\impliedby)/,/^(?:\\imath)/,/^(?:\\Im)/,/^(?:\\iint)/,/^(?:\\iiint)/,/^(?:\\iiiint)/,/^(?:\\iff)/,/^(?:\\hslash)/,/^(?:\\href)/,/^(?:\\hookrightarrow)/,/^(?:\\hookleftarrow)/,/^(?:\\hkswarow)/,/^(?:\\hksearow)/,/^(?:\\heartsuit)/,/^(?:\\hbar)/,/^(?:\\hat)/,/^(?:\\gvertneqq)/,/^(?:\\gvertneqq)/,
-/^(?:\\gtrsim)/,/^(?:\\gtrless)/,/^(?:\\gtreqqless)/,/^(?:\\gtreqless)/,/^(?:\\gtrdot)/,/^(?:\\gtrapprox)/,/^(?:\\gt)/,/^(?:\\greater)/,/^(?:\\gnsim)/,/^(?:\\gneqq)/,/^(?:\\gneq)/,/^(?:\\gnapprox)/,/^(?:\\gimel)/,/^(?:\\ggg)/,/^(?:\\gg)/,/^(?:\\geqslant)/,/^(?:\\geqq)/,/^(?:\\geq)/,/^(?:\\ge)/,/^(?:\\Gamma)/,/^(?:\\gamma)/,/^(?:\\frown)/,/^(?:\\frame)/,/^(?:\\frac)/,/^(?:\\forksnot)/,/^(?:\\forks)/,/^(?:\\forall)/,/^(?:\\flat)/,/^(?:\\fdiagovrdiag)/,/^(?:\\fdiagovnearrow)/,/^(?:\\fallingdotseq)/,
-/^(?:\\exists)/,/^(?:\\eth)/,/^(?:\\eth)/,/^(?:\\Eta)/,/^(?:\\eta)/,/^(?:\\equiv)/,/^(?:\\equalrows)/,/^(?:\\equalcols)/,/^(?:\\eqslantless)/,/^(?:\\eqslantgtr)/,/^(?:\\eqsim)/,/^(?:\\Eqqcolon)/,/^(?:\\eqqcolon)/,/^(?:\\Eqcolon)/,/^(?:\\Eqcolon)/,/^(?:\\Eqcolon)/,/^(?:\\Eqcolon)/,/^(?:\\eqcolon)/,/^(?:\\eqcirc)/,/^(?:\\epsilon)/,/^(?:\\end\{Vmatrix\})/,/^(?:\\end\{vmatrix\})/,/^(?:\\endtoggle)/,/^(?:\\end\{split\})/,/^(?:\\end\{smallmatrix\})/,/^(?:\\end\{pmatrix\})/,/^(?:\\end\{matrix\})/,/^(?:\\end\{gathered\})/,
-/^(?:\\end\{cases\})/,/^(?:\\end\{Bmatrix\})/,/^(?:\\end\{bmatrix\})/,/^(?:\\end\{array\})/,/^(?:\\end\{aligned\})/,/^(?:\\emptyset)/,/^(?:\\empty)/,/^(?:\\embedsin)/,/^(?:\\ell)/,/^(?:\\duparr)/,/^(?:\\dualmap)/,/^(?:\\drbkarrow)/,/^(?:\\downuparrow)/,/^(?:\\downharpoonright)/,/^(?:\\downharpoonleft)/,/^(?:\\downdownarrows)/,/^(?:\\Downarrow)/,/^(?:\\downarrow)/,/^(?:\\doubleintegral)/,/^(?:\\doublebarwedge)/,/^(?:\\doublebarwedge)/,/^(?:\\dots)/,/^(?:\\dotplus)/,/^(?:\\dotminus)/,/^(?:\\doteqdot)/,
-/^(?:\\Doteq)/,/^(?:\\doteq)/,/^(?:\\dot)/,/^(?:\\divideontimes)/,/^(?:\\div)/,/^(?:\\displaystyle)/,/^(?:\\disjquant)/,/^(?:\\digamma)/,/^(?:\\diamondsuit)/,/^(?:\\Diamond)/,/^(?:\\diamond)/,/^(?:\\det|\\gcd|\\liminf|\\limsup|\\lim|\\max|\\Pr|\\sup)/,/^(?:\\Delta)/,/^(?:\\delta)/,/^(?:\\Del)/,/^(?:\\degree)/,/^(?:\\Ddownarrow)/,/^(?:\\ddotseq)/,/^(?:\\ddots)/,/^(?:\\ddot)/,/^(?:\\dddot)/,/^(?:\\dddot)/,/^(?:\\ddddot)/,/^(?:\\ddddot)/,/^(?:\\ddagger)/,/^(?:\\dblcolon)/,/^(?:\\dbkarow)/,/^(?:\\Dashv)/,
-/^(?:\\dashV)/,/^(?:\\dashv)/,/^(?:\\dashrightarrow)/,/^(?:\\dashleftarrow)/,/^(?:\\darr)/,/^(?:\\daleth)/,/^(?:\\dagger)/,/^(?:\\curvearrowright)/,/^(?:\\curvearrowleft)/,/^(?:\\curvearrowbotright)/,/^(?:\\curlywedge)/,/^(?:\\curlyvee)/,/^(?:\\curlyeqsucc)/,/^(?:\\curlyeqprec)/,/^(?:\\cupdot)/,/^(?:\\Cup)/,/^(?:\\cup)/,/^(?:\\coproduct)/,/^(?:\\coprod)/,/^(?:\\contourintegral)/,/^(?:\\conjquant)/,/^(?:\\conint)/,/^(?:\\cong)/,/^(?:\\complement)/,/^(?:\\colspan)/,/^(?:\\color)/,/^(?:\\Colonsim)/,
-/^(?:\\colonsim)/,/^(?:\\Coloneqq)/,/^(?:\\coloneqq)/,/^(?:\\Coloneq)/,/^(?:\\coloneq)/,/^(?:\\Colonapprox)/,/^(?:\\colonapprox)/,/^(?:\\Colon)/,/^(?:\\colon)/,/^(?:\\collines)/,/^(?:\\collayout)/,/^(?:\\colalign)/,/^(?:\\clubsuit)/,/^(?:\\closure)/,/^(?:\\circleddash)/,/^(?:\\circledcirc)/,/^(?:\\circledast)/,/^(?:\\circlearrowright)/,/^(?:\\circlearrowleft)/,/^(?:\\circeq)/,/^(?:\\circ)/,/^(?:\\choose)/,/^(?:\\chi)/,/^(?:\\check)/,/^(?:\\cellopts)/,/^(?:\\cdots)/,/^(?:\\cdotp)/,/^(?:\\cdot)/,/^(?:\\Cap)/,
-/^(?:\\cap)/,/^(?:\\bumpeqq)/,/^(?:\\Bumpeq)/,/^(?:\\bumpeq)/,/^(?:\\bullet)/,/^(?:\\btimes)/,/^(?:\\boxtimes)/,/^(?:\\boxplus)/,/^(?:\\boxminus)/,/^(?:\\boxed)/,/^(?:\\boxdot)/,/^(?:\\boxdiag)/,/^(?:\\boxcircle)/,/^(?:\\boxbslash)/,/^(?:\\boxast)/,/^(?:\\Box)/,/^(?:\\bowtie)/,/^(?:\\bottom)/,/^(?:\\bot)/,/^(?:\\boldsymbol)/,/^(?:\\blacktriangleright)/,/^(?:\\blacktriangleleft)/,/^(?:\\blacktriangledown)/,/^(?:\\blacktriangle)/,/^(?:\\blacksquare)/,/^(?:\\blacklozenge)/,/^(?:\\bkarow)/,/^(?:\\binom)/,
-/^(?:\\bigwedge)/,/^(?:\\bigvee)/,/^(?:\\biguplus)/,/^(?:\\bigtriangleup)/,/^(?:\\bigtriangledown)/,/^(?:\\bigtimes)/,/^(?:\\bigstar)/,/^(?:\\bigsqcup)/,/^(?:\\bigsqcap)/,/^(?:\\Bigr)/,/^(?:\\bigr)/,/^(?:\\bigotimes)/,/^(?:\\bigoplus)/,/^(?:\\bigodot)/,/^(?:\\Bigl)/,/^(?:\\bigl)/,/^(?:\\biginterleave)/,/^(?:\\Biggr)/,/^(?:\\biggr)/,/^(?:\\Biggl)/,/^(?:\\biggl)/,/^(?:\\Bigg)/,/^(?:\\bigg)/,/^(?:\\bigcupdot)/,/^(?:\\bigcup)/,/^(?:\\bigcirc)/,/^(?:\\bigcap)/,/^(?:\\Big)/,/^(?:\\big)/,/^(?:\\bgcolor)/,
-/^(?:\\between)/,/^(?:\\beth)/,/^(?:\\Beta)/,/^(?:\\beta)/,/^(?:\\begin\{Vmatrix\})/,/^(?:\\begin\{vmatrix\})/,/^(?:\\begintoggle)/,/^(?:\\begin\{split\})/,/^(?:\\begin\{smallmatrix\})/,/^(?:\\begin\{pmatrix\})/,/^(?:\\begin\{matrix\})/,/^(?:\\begin\{gathered\})/,/^(?:\\begin\{cases\})/,/^(?:\\begin\{Bmatrix\})/,/^(?:\\begin\{bmatrix\})/,/^(?:\\begin\{array\})/,/^(?:\\begin\{aligned\})/,/^(?:\\because)/,/^(?:\\BbbPi)/,/^(?:\\barwedge)/,/^(?:\\bar)/,/^(?:\\backslash)/,/^(?:\\backsimeq)/,/^(?:\\backsim)/,
-/^(?:\\backprime)/,/^(?:\\backepsilon)/,/^(?:\\atop)/,/^(?:\\asymp)/,/^(?:\\ast)/,/^(?:\\arrayopts)/,/^(?:\\array)/,/^(?:\\arccos|\\arcsin|\\arctan|\\arg|\\cosh|\\cos|\\coth|\\cot|\\csc|\\deg|\\dim|\\exp|\\hom|\\ker|\\lg|\\ln|\\log|\\sec|\\sinh|\\sin|\\tanh|\\tan)/,/^(?:\\approxeq)/,/^(?:\\approx)/,/^(?:\\angle)/,/^(?:\\amalg)/,/^(?:\\Alpha)/,/^(?:\\alpha)/,/^(?:\\align)/,/^(?:\\aleph)/,/^(?:\\adots)/,/^(?:\\AA)/,/^(?:[\u0041-\u005A\u0061-\u007A\u00F0\u0131\u0237\u0391-\u03A1\u03A3\u03A4\u03A6-\u03A9\u03B1-\u03C9\u03D0-\u03D2\u03D5\u03D6\u03DA-\u03DD\u03E0\u03E1\u03F0\u03F1\u03F4\u03F5\u0428\u0608\u0627-\u063A\u2102\u210A-\u210D\u210F-\u2113\u2115\u2118-\u211D\u2124\u2127\u2128\u212B-\u212D\u212F-\u2131\u2133-\u2138\u213C\u213D\u213F\u2205]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB\uDEF0\uDEF1]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDFCB])/,
-/^(?:\\%)/,/^(?:\\#)/,/^(?:\\&)/,/^(?:\\\$)/,/^(?:\\\})/,/^(?:\\\{)/,/^(?:\\!)/,/^(?:\\:)/,/^(?:\\;)/,/^(?:\\,)/,/^(?:\\\|)/,/^(?:'''')/,/^(?:''')/,/^(?:'')/,/^(?:')/,/^(?:[\uD800-\uDBFF])/,/^(?:[\uDC00-\uDFFF])/,/^(?:.)/],N:{MATH0:{rules:[14,15,16,17,18,19,20,21,22,23,25,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,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,
-102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,
-228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,
-354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,
-480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,
-606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,
-732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,
-858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878],inclusive:h},MATH1:{rules:[14,15,16,17,18,19,20,21,22,23,24,25,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,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,
-133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,
-259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,
-385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,
-511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,
-637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,
-763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878],inclusive:h},OPTARG:{rules:[13,14,15,
-16,17,18,19,20,21,22,23,25,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,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,
-163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,
-289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,
-415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,
-541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,
-667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,
-793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878],inclusive:h},DOCUMENT:{rules:[1,2,3,4,5],inclusive:p},TRYOPTARG:{rules:[6,7],inclusive:p},TEXTOPTARG:{rules:[8,9],inclusive:p},TEXTARG:{rules:[10,11,12],inclusive:p},
-INITIAL:{rules:[0,14,15,16,17,18,19,20,21,22,23,25,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,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,
-157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,
-283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,
-409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,
-535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,
-661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,
-787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878],inclusive:h}}}}();y.prototype=l;l.pa=y;return new y}();window.TeXZilla=u;window.TeXZilla.setDOMParser=u.fa;
-window.TeXZilla.setXMLSerializer=u.ja;window.TeXZilla.setSafeMode=u.ia;window.TeXZilla.setItexIdentifierMode=u.ha;window.TeXZilla.getTeXSource=u.ca;window.TeXZilla.toMathMLString=u.Z;window.TeXZilla.toMathML=u.Y;window.TeXZilla.toImage=u.na;window.TeXZilla.filterString=u.R;window.TeXZilla.filterElement=u.Q;