EditorBase.cpp 158 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "mozilla/EditorBase.h"
  6. #include "mozilla/DebugOnly.h" // for DebugOnly
  7. #include <stdio.h> // for nullptr, stdout
  8. #include <string.h> // for strcmp
  9. #include "ChangeAttributeTransaction.h" // for ChangeAttributeTransaction
  10. #include "CompositionTransaction.h" // for CompositionTransaction
  11. #include "CreateElementTransaction.h" // for CreateElementTransaction
  12. #include "DeleteNodeTransaction.h" // for DeleteNodeTransaction
  13. #include "DeleteRangeTransaction.h" // for DeleteRangeTransaction
  14. #include "DeleteTextTransaction.h" // for DeleteTextTransaction
  15. #include "EditAggregateTransaction.h" // for EditAggregateTransaction
  16. #include "EditorEventListener.h" // for EditorEventListener
  17. #include "InsertNodeTransaction.h" // for InsertNodeTransaction
  18. #include "InsertTextTransaction.h" // for InsertTextTransaction
  19. #include "JoinNodeTransaction.h" // for JoinNodeTransaction
  20. #include "PlaceholderTransaction.h" // for PlaceholderTransaction
  21. #include "SplitNodeTransaction.h" // for SplitNodeTransaction
  22. #include "StyleSheetTransactions.h" // for AddStyleSheetTransaction, etc.
  23. #include "TextEditUtils.h" // for TextEditUtils
  24. #include "mozFlushType.h" // for mozFlushType::Flush_Frames
  25. #include "mozInlineSpellChecker.h" // for mozInlineSpellChecker
  26. #include "mozilla/CheckedInt.h" // for CheckedInt
  27. #include "mozilla/EditorUtils.h" // for AutoRules, etc.
  28. #include "mozilla/EditTransactionBase.h" // for EditTransactionBase
  29. #include "mozilla/IMEStateManager.h" // for IMEStateManager
  30. #include "mozilla/Preferences.h" // for Preferences
  31. #include "mozilla/dom/Selection.h" // for Selection, etc.
  32. #include "mozilla/Services.h" // for GetObserverService
  33. #include "mozilla/TextComposition.h" // for TextComposition
  34. #include "mozilla/TextEvents.h"
  35. #include "mozilla/dom/Element.h" // for Element, nsINode::AsElement
  36. #include "mozilla/dom/HTMLBodyElement.h"
  37. #include "mozilla/dom/Text.h"
  38. #include "mozilla/dom/Event.h"
  39. #include "mozilla/mozalloc.h" // for operator new, etc.
  40. #include "nsAString.h" // for nsAString_internal::Length, etc.
  41. #include "nsCCUncollectableMarker.h" // for nsCCUncollectableMarker
  42. #include "nsCaret.h" // for nsCaret
  43. #include "nsCaseTreatment.h"
  44. #include "nsCharTraits.h" // for NS_IS_HIGH_SURROGATE, etc.
  45. #include "nsComponentManagerUtils.h" // for do_CreateInstance
  46. #include "nsComputedDOMStyle.h" // for nsComputedDOMStyle
  47. #include "nsContentUtils.h" // for nsContentUtils
  48. #include "nsDOMString.h" // for DOMStringIsNull
  49. #include "nsDebug.h" // for NS_ENSURE_TRUE, etc.
  50. #include "nsError.h" // for NS_OK, etc.
  51. #include "nsFocusManager.h" // for nsFocusManager
  52. #include "nsFrameSelection.h" // for nsFrameSelection
  53. #include "nsGkAtoms.h" // for nsGkAtoms, nsGkAtoms::dir
  54. #include "nsIAbsorbingTransaction.h" // for nsIAbsorbingTransaction
  55. #include "nsIAtom.h" // for nsIAtom
  56. #include "nsIContent.h" // for nsIContent
  57. #include "nsIDOMAttr.h" // for nsIDOMAttr
  58. #include "nsIDOMCharacterData.h" // for nsIDOMCharacterData
  59. #include "nsIDOMDocument.h" // for nsIDOMDocument
  60. #include "nsIDOMElement.h" // for nsIDOMElement
  61. #include "nsIDOMEvent.h" // for nsIDOMEvent
  62. #include "nsIDOMEventListener.h" // for nsIDOMEventListener
  63. #include "nsIDOMEventTarget.h" // for nsIDOMEventTarget
  64. #include "nsIDOMHTMLElement.h" // for nsIDOMHTMLElement
  65. #include "nsIDOMKeyEvent.h" // for nsIDOMKeyEvent, etc.
  66. #include "nsIDOMMozNamedAttrMap.h" // for nsIDOMMozNamedAttrMap
  67. #include "nsIDOMMouseEvent.h" // for nsIDOMMouseEvent
  68. #include "nsIDOMNode.h" // for nsIDOMNode, etc.
  69. #include "nsIDOMNodeList.h" // for nsIDOMNodeList
  70. #include "nsIDOMText.h" // for nsIDOMText
  71. #include "nsIDocumentStateListener.h" // for nsIDocumentStateListener
  72. #include "nsIEditActionListener.h" // for nsIEditActionListener
  73. #include "nsIEditorObserver.h" // for nsIEditorObserver
  74. #include "nsIEditorSpellCheck.h" // for nsIEditorSpellCheck
  75. #include "nsIFrame.h" // for nsIFrame
  76. #include "nsIHTMLDocument.h" // for nsIHTMLDocument
  77. #include "nsIInlineSpellChecker.h" // for nsIInlineSpellChecker, etc.
  78. #include "nsNameSpaceManager.h" // for kNameSpaceID_None, etc.
  79. #include "nsINode.h" // for nsINode, etc.
  80. #include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc.
  81. #include "nsIPresShell.h" // for nsIPresShell
  82. #include "nsISelectionController.h" // for nsISelectionController, etc.
  83. #include "nsISelectionDisplay.h" // for nsISelectionDisplay, etc.
  84. #include "nsISupportsBase.h" // for nsISupports
  85. #include "nsISupportsUtils.h" // for NS_ADDREF, NS_IF_ADDREF
  86. #include "nsITransaction.h" // for nsITransaction
  87. #include "nsITransactionManager.h"
  88. #include "nsIWeakReference.h" // for nsISupportsWeakReference
  89. #include "nsIWidget.h" // for nsIWidget, IMEState, etc.
  90. #include "nsPIDOMWindow.h" // for nsPIDOMWindow
  91. #include "nsPresContext.h" // for nsPresContext
  92. #include "nsRange.h" // for nsRange
  93. #include "nsReadableUtils.h" // for EmptyString, ToNewCString
  94. #include "nsString.h" // for nsAutoString, nsString, etc.
  95. #include "nsStringFwd.h" // for nsAFlatString
  96. #include "nsStyleConsts.h" // for NS_STYLE_DIRECTION_RTL, etc.
  97. #include "nsStyleContext.h" // for nsStyleContext
  98. #include "nsStyleStruct.h" // for nsStyleDisplay, nsStyleText, etc.
  99. #include "nsStyleStructFwd.h" // for nsIFrame::StyleUIReset, etc.
  100. #include "nsTextNode.h" // for nsTextNode
  101. #include "nsThreadUtils.h" // for nsRunnable
  102. #include "nsTransactionManager.h" // for nsTransactionManager
  103. #include "prtime.h" // for PR_Now
  104. class nsIOutputStream;
  105. class nsITransferable;
  106. #ifdef DEBUG
  107. #include "nsIDOMHTMLDocument.h" // for nsIDOMHTMLDocument
  108. #endif
  109. namespace mozilla {
  110. using namespace dom;
  111. using namespace widget;
  112. /*****************************************************************************
  113. * mozilla::EditorBase
  114. *****************************************************************************/
  115. EditorBase::EditorBase()
  116. : mPlaceholderName(nullptr)
  117. , mSelState(nullptr)
  118. , mPhonetic(nullptr)
  119. , mModCount(0)
  120. , mFlags(0)
  121. , mUpdateCount(0)
  122. , mPlaceholderBatch(0)
  123. , mAction(EditAction::none)
  124. , mIMETextOffset(0)
  125. , mIMETextLength(0)
  126. , mDirection(eNone)
  127. , mDocDirtyState(-1)
  128. , mSpellcheckCheckboxState(eTriUnset)
  129. , mShouldTxnSetSelection(true)
  130. , mDidPreDestroy(false)
  131. , mDidPostCreate(false)
  132. , mDispatchInputEvent(true)
  133. , mIsInEditAction(false)
  134. , mHidingCaret(false)
  135. {
  136. }
  137. EditorBase::~EditorBase()
  138. {
  139. MOZ_ASSERT(!IsInitialized() || mDidPreDestroy,
  140. "Why PreDestroy hasn't been called?");
  141. if (mComposition) {
  142. mComposition->OnEditorDestroyed();
  143. mComposition = nullptr;
  144. }
  145. // If this editor is still hiding the caret, we need to restore it.
  146. HideCaret(false);
  147. mTxnMgr = nullptr;
  148. delete mPhonetic;
  149. }
  150. NS_IMPL_CYCLE_COLLECTION_CLASS(EditorBase)
  151. NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(EditorBase)
  152. NS_IMPL_CYCLE_COLLECTION_UNLINK(mRootElement)
  153. NS_IMPL_CYCLE_COLLECTION_UNLINK(mInlineSpellChecker)
  154. NS_IMPL_CYCLE_COLLECTION_UNLINK(mTxnMgr)
  155. NS_IMPL_CYCLE_COLLECTION_UNLINK(mIMETextNode)
  156. NS_IMPL_CYCLE_COLLECTION_UNLINK(mActionListeners)
  157. NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditorObservers)
  158. NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocStateListeners)
  159. NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventTarget)
  160. if (tmp->mEventListener) {
  161. EditorEventListener* listener =
  162. reinterpret_cast<EditorEventListener*>(tmp->mEventListener.get());
  163. listener->Disconnect();
  164. tmp->mEventListener = nullptr;
  165. }
  166. NS_IMPL_CYCLE_COLLECTION_UNLINK(mSavedSel);
  167. NS_IMPL_CYCLE_COLLECTION_UNLINK(mRangeUpdater);
  168. NS_IMPL_CYCLE_COLLECTION_UNLINK_END
  169. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(EditorBase)
  170. nsIDocument* currentDoc =
  171. tmp->mRootElement ? tmp->mRootElement->GetUncomposedDoc() : nullptr;
  172. if (currentDoc &&
  173. nsCCUncollectableMarker::InGeneration(cb, currentDoc->GetMarkedCCGeneration())) {
  174. return NS_SUCCESS_INTERRUPTED_TRAVERSE;
  175. }
  176. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRootElement)
  177. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInlineSpellChecker)
  178. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTxnMgr)
  179. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIMETextNode)
  180. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mActionListeners)
  181. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEditorObservers)
  182. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocStateListeners)
  183. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventTarget)
  184. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventListener)
  185. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSavedSel);
  186. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRangeUpdater);
  187. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
  188. NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EditorBase)
  189. NS_INTERFACE_MAP_ENTRY(nsIPhonetic)
  190. NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
  191. NS_INTERFACE_MAP_ENTRY(nsIEditorIMESupport)
  192. NS_INTERFACE_MAP_ENTRY(nsIEditor)
  193. NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIEditor)
  194. NS_INTERFACE_MAP_END
  195. NS_IMPL_CYCLE_COLLECTING_ADDREF(EditorBase)
  196. NS_IMPL_CYCLE_COLLECTING_RELEASE(EditorBase)
  197. NS_IMETHODIMP
  198. EditorBase::Init(nsIDOMDocument* aDOMDocument,
  199. nsIContent* aRoot,
  200. nsISelectionController* aSelectionController,
  201. uint32_t aFlags,
  202. const nsAString& aValue)
  203. {
  204. MOZ_ASSERT(mAction == EditAction::none,
  205. "Initializing during an edit action is an error");
  206. MOZ_ASSERT(aDOMDocument);
  207. if (!aDOMDocument) {
  208. return NS_ERROR_NULL_POINTER;
  209. }
  210. // First only set flags, but other stuff shouldn't be initialized now.
  211. // Don't move this call after initializing mDocumentWeak.
  212. // SetFlags() can check whether it's called during initialization or not by
  213. // them. Note that SetFlags() will be called by PostCreate().
  214. #ifdef DEBUG
  215. nsresult rv =
  216. #endif
  217. SetFlags(aFlags);
  218. NS_ASSERTION(NS_SUCCEEDED(rv), "SetFlags() failed");
  219. nsCOMPtr<nsIDocument> document = do_QueryInterface(aDOMDocument);
  220. mDocumentWeak = document.get();
  221. // HTML editors currently don't have their own selection controller,
  222. // so they'll pass null as aSelCon, and we'll get the selection controller
  223. // off of the presshell.
  224. nsCOMPtr<nsISelectionController> selectionController;
  225. if (aSelectionController) {
  226. mSelectionControllerWeak = aSelectionController;
  227. selectionController = aSelectionController;
  228. } else {
  229. nsCOMPtr<nsIPresShell> presShell = GetPresShell();
  230. selectionController = do_QueryInterface(presShell);
  231. }
  232. MOZ_ASSERT(selectionController,
  233. "Selection controller should be available at this point");
  234. //set up root element if we are passed one.
  235. if (aRoot)
  236. mRootElement = do_QueryInterface(aRoot);
  237. mUpdateCount=0;
  238. // If this is an editor for <input> or <textarea>, mIMETextNode is always
  239. // recreated with same content. Therefore, we need to forget mIMETextNode,
  240. // but we need to keep storing mIMETextOffset and mIMETextLength becuase
  241. // they are necessary to restore IME selection and replacing composing string
  242. // when this receives eCompositionChange event next time.
  243. if (mIMETextNode && !mIMETextNode->IsInComposedDoc()) {
  244. mIMETextNode = nullptr;
  245. }
  246. // Show the caret.
  247. selectionController->SetCaretReadOnly(false);
  248. selectionController->SetDisplaySelection(
  249. nsISelectionController::SELECTION_ON);
  250. // Show all the selection reflected to user.
  251. selectionController->SetSelectionFlags(nsISelectionDisplay::DISPLAY_ALL);
  252. MOZ_ASSERT(IsInitialized());
  253. // Make sure that the editor will be destroyed properly
  254. mDidPreDestroy = false;
  255. // Make sure that the ediotr will be created properly
  256. mDidPostCreate = false;
  257. return NS_OK;
  258. }
  259. NS_IMETHODIMP
  260. EditorBase::PostCreate()
  261. {
  262. // Synchronize some stuff for the flags. SetFlags() will initialize
  263. // something by the flag difference. This is first time of that, so, all
  264. // initializations must be run. For such reason, we need to invert mFlags
  265. // value first.
  266. mFlags = ~mFlags;
  267. nsresult rv = SetFlags(~mFlags);
  268. NS_ENSURE_SUCCESS(rv, rv);
  269. // These operations only need to happen on the first PostCreate call
  270. if (!mDidPostCreate) {
  271. mDidPostCreate = true;
  272. // Set up listeners
  273. CreateEventListeners();
  274. rv = InstallEventListeners();
  275. NS_ENSURE_SUCCESS(rv, rv);
  276. // nuke the modification count, so the doc appears unmodified
  277. // do this before we notify listeners
  278. ResetModificationCount();
  279. // update the UI with our state
  280. NotifyDocumentListeners(eDocumentCreated);
  281. NotifyDocumentListeners(eDocumentStateChanged);
  282. }
  283. // update nsTextStateManager and caret if we have focus
  284. nsCOMPtr<nsIContent> focusedContent = GetFocusedContent();
  285. if (focusedContent) {
  286. nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(focusedContent);
  287. if (target) {
  288. InitializeSelection(target);
  289. }
  290. // If the text control gets reframed during focus, Focus() would not be
  291. // called, so take a chance here to see if we need to spell check the text
  292. // control.
  293. EditorEventListener* listener =
  294. reinterpret_cast<EditorEventListener*>(mEventListener.get());
  295. listener->SpellCheckIfNeeded();
  296. IMEState newState;
  297. rv = GetPreferredIMEState(&newState);
  298. NS_ENSURE_SUCCESS(rv, NS_OK);
  299. nsCOMPtr<nsIContent> content = GetFocusedContentForIME();
  300. IMEStateManager::UpdateIMEState(newState, content, *this);
  301. }
  302. // FYI: This call might cause destroying this editor.
  303. IMEStateManager::OnEditorInitialized(this);
  304. return NS_OK;
  305. }
  306. void
  307. EditorBase::CreateEventListeners()
  308. {
  309. // Don't create the handler twice
  310. if (!mEventListener) {
  311. mEventListener = new EditorEventListener();
  312. }
  313. }
  314. nsresult
  315. EditorBase::InstallEventListeners()
  316. {
  317. if (NS_WARN_IF(!IsInitialized()) || NS_WARN_IF(!mEventListener)) {
  318. return NS_ERROR_NOT_INITIALIZED;
  319. }
  320. // Initialize the event target.
  321. nsCOMPtr<nsIContent> rootContent = GetRoot();
  322. NS_ENSURE_TRUE(rootContent, NS_ERROR_NOT_AVAILABLE);
  323. mEventTarget = do_QueryInterface(rootContent->GetParent());
  324. NS_ENSURE_TRUE(mEventTarget, NS_ERROR_NOT_AVAILABLE);
  325. EditorEventListener* listener =
  326. reinterpret_cast<EditorEventListener*>(mEventListener.get());
  327. nsresult rv = listener->Connect(this);
  328. if (mComposition) {
  329. // Restart to handle composition with new editor contents.
  330. mComposition->StartHandlingComposition(this);
  331. }
  332. return rv;
  333. }
  334. void
  335. EditorBase::RemoveEventListeners()
  336. {
  337. if (!IsInitialized() || !mEventListener) {
  338. return;
  339. }
  340. reinterpret_cast<EditorEventListener*>(mEventListener.get())->Disconnect();
  341. if (mComposition) {
  342. // Even if this is called, don't release mComposition because this is
  343. // may be reused after reframing.
  344. mComposition->EndHandlingComposition(this);
  345. }
  346. mEventTarget = nullptr;
  347. }
  348. bool
  349. EditorBase::GetDesiredSpellCheckState()
  350. {
  351. // Check user override on this element
  352. if (mSpellcheckCheckboxState != eTriUnset) {
  353. return (mSpellcheckCheckboxState == eTriTrue);
  354. }
  355. // Check user preferences
  356. int32_t spellcheckLevel = Preferences::GetInt("layout.spellcheckDefault", 1);
  357. if (!spellcheckLevel) {
  358. return false; // Spellchecking forced off globally
  359. }
  360. if (!CanEnableSpellCheck()) {
  361. return false;
  362. }
  363. nsCOMPtr<nsIPresShell> presShell = GetPresShell();
  364. if (presShell) {
  365. nsPresContext* context = presShell->GetPresContext();
  366. if (context && !context->IsDynamic()) {
  367. return false;
  368. }
  369. }
  370. // Check DOM state
  371. nsCOMPtr<nsIContent> content = GetExposedRoot();
  372. if (!content) {
  373. return false;
  374. }
  375. nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(content);
  376. if (!element) {
  377. return false;
  378. }
  379. if (!IsPlaintextEditor()) {
  380. // Some of the page content might be editable and some not, if spellcheck=
  381. // is explicitly set anywhere, so if there's anything editable on the page,
  382. // return true and let the spellchecker figure it out.
  383. nsCOMPtr<nsIHTMLDocument> doc = do_QueryInterface(content->GetUncomposedDoc());
  384. return doc && doc->IsEditingOn();
  385. }
  386. bool enable;
  387. element->GetSpellcheck(&enable);
  388. return enable;
  389. }
  390. NS_IMETHODIMP
  391. EditorBase::PreDestroy(bool aDestroyingFrames)
  392. {
  393. if (mDidPreDestroy)
  394. return NS_OK;
  395. IMEStateManager::OnEditorDestroying(this);
  396. // Let spellchecker clean up its observers etc. It is important not to
  397. // actually free the spellchecker here, since the spellchecker could have
  398. // caused flush notifications, which could have gotten here if a textbox
  399. // is being removed. Setting the spellchecker to nullptr could free the
  400. // object that is still in use! It will be freed when the editor is
  401. // destroyed.
  402. if (mInlineSpellChecker)
  403. mInlineSpellChecker->Cleanup(aDestroyingFrames);
  404. // tell our listeners that the doc is going away
  405. NotifyDocumentListeners(eDocumentToBeDestroyed);
  406. // Unregister event listeners
  407. RemoveEventListeners();
  408. // If this editor is still hiding the caret, we need to restore it.
  409. HideCaret(false);
  410. mActionListeners.Clear();
  411. mEditorObservers.Clear();
  412. mDocStateListeners.Clear();
  413. mInlineSpellChecker = nullptr;
  414. mSpellcheckCheckboxState = eTriUnset;
  415. mRootElement = nullptr;
  416. // Transaction may grab this instance. Therefore, they should be released
  417. // here for stopping the circular reference with this instance.
  418. if (mTxnMgr) {
  419. mTxnMgr->Clear();
  420. mTxnMgr = nullptr;
  421. }
  422. mDidPreDestroy = true;
  423. return NS_OK;
  424. }
  425. NS_IMETHODIMP
  426. EditorBase::GetFlags(uint32_t* aFlags)
  427. {
  428. *aFlags = mFlags;
  429. return NS_OK;
  430. }
  431. NS_IMETHODIMP
  432. EditorBase::SetFlags(uint32_t aFlags)
  433. {
  434. if (mFlags == aFlags) {
  435. return NS_OK;
  436. }
  437. bool spellcheckerWasEnabled = CanEnableSpellCheck();
  438. mFlags = aFlags;
  439. if (!IsInitialized()) {
  440. // If we're initializing, we shouldn't do anything now.
  441. // SetFlags() will be called by PostCreate(),
  442. // we should synchronize some stuff for the flags at that time.
  443. return NS_OK;
  444. }
  445. // The flag change may cause the spellchecker state change
  446. if (CanEnableSpellCheck() != spellcheckerWasEnabled) {
  447. nsresult rv = SyncRealTimeSpell();
  448. NS_ENSURE_SUCCESS(rv, rv);
  449. }
  450. // If this is called from PostCreate(), it will update the IME state if it's
  451. // necessary.
  452. if (!mDidPostCreate) {
  453. return NS_OK;
  454. }
  455. // Might be changing editable state, so, we need to reset current IME state
  456. // if we're focused and the flag change causes IME state change.
  457. nsCOMPtr<nsIContent> focusedContent = GetFocusedContent();
  458. if (focusedContent) {
  459. IMEState newState;
  460. nsresult rv = GetPreferredIMEState(&newState);
  461. if (NS_SUCCEEDED(rv)) {
  462. // NOTE: When the enabled state isn't going to be modified, this method
  463. // is going to do nothing.
  464. nsCOMPtr<nsIContent> content = GetFocusedContentForIME();
  465. IMEStateManager::UpdateIMEState(newState, content, *this);
  466. }
  467. }
  468. return NS_OK;
  469. }
  470. NS_IMETHODIMP
  471. EditorBase::GetIsSelectionEditable(bool* aIsSelectionEditable)
  472. {
  473. NS_ENSURE_ARG_POINTER(aIsSelectionEditable);
  474. // get current selection
  475. RefPtr<Selection> selection = GetSelection();
  476. NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
  477. // XXX we just check that the anchor node is editable at the moment
  478. // we should check that all nodes in the selection are editable
  479. nsCOMPtr<nsINode> anchorNode = selection->GetAnchorNode();
  480. *aIsSelectionEditable = anchorNode && IsEditable(anchorNode);
  481. return NS_OK;
  482. }
  483. NS_IMETHODIMP
  484. EditorBase::GetIsDocumentEditable(bool* aIsDocumentEditable)
  485. {
  486. NS_ENSURE_ARG_POINTER(aIsDocumentEditable);
  487. nsCOMPtr<nsIDocument> doc = GetDocument();
  488. *aIsDocumentEditable = !!doc;
  489. return NS_OK;
  490. }
  491. already_AddRefed<nsIDocument>
  492. EditorBase::GetDocument()
  493. {
  494. nsCOMPtr<nsIDocument> document = mDocumentWeak.get();
  495. return document.forget();
  496. }
  497. already_AddRefed<nsIDOMDocument>
  498. EditorBase::GetDOMDocument()
  499. {
  500. nsCOMPtr<nsIDOMDocument> domDocument = do_QueryInterface(mDocumentWeak);
  501. return domDocument.forget();
  502. }
  503. NS_IMETHODIMP
  504. EditorBase::GetDocument(nsIDOMDocument** aDoc)
  505. {
  506. *aDoc = GetDOMDocument().take();
  507. return *aDoc ? NS_OK : NS_ERROR_NOT_INITIALIZED;
  508. }
  509. already_AddRefed<nsIPresShell>
  510. EditorBase::GetPresShell()
  511. {
  512. nsCOMPtr<nsIDocument> document = GetDocument();
  513. if (NS_WARN_IF(!document)) {
  514. return nullptr;
  515. }
  516. nsCOMPtr<nsIPresShell> presShell = document->GetShell();
  517. return presShell.forget();
  518. }
  519. already_AddRefed<nsIWidget>
  520. EditorBase::GetWidget()
  521. {
  522. nsCOMPtr<nsIPresShell> ps = GetPresShell();
  523. NS_ENSURE_TRUE(ps, nullptr);
  524. nsPresContext* pc = ps->GetPresContext();
  525. NS_ENSURE_TRUE(pc, nullptr);
  526. nsCOMPtr<nsIWidget> widget = pc->GetRootWidget();
  527. NS_ENSURE_TRUE(widget.get(), nullptr);
  528. return widget.forget();
  529. }
  530. NS_IMETHODIMP
  531. EditorBase::GetContentsMIMEType(char** aContentsMIMEType)
  532. {
  533. NS_ENSURE_ARG_POINTER(aContentsMIMEType);
  534. *aContentsMIMEType = ToNewCString(mContentMIMEType);
  535. return NS_OK;
  536. }
  537. NS_IMETHODIMP
  538. EditorBase::SetContentsMIMEType(const char* aContentsMIMEType)
  539. {
  540. mContentMIMEType.Assign(aContentsMIMEType ? aContentsMIMEType : "");
  541. return NS_OK;
  542. }
  543. NS_IMETHODIMP
  544. EditorBase::GetSelectionController(nsISelectionController** aSel)
  545. {
  546. NS_ENSURE_TRUE(aSel, NS_ERROR_NULL_POINTER);
  547. *aSel = nullptr; // init out param
  548. nsCOMPtr<nsISelectionController> selCon = GetSelectionController();
  549. if (NS_WARN_IF(!selCon)) {
  550. return NS_ERROR_NOT_INITIALIZED;
  551. }
  552. selCon.forget(aSel);
  553. return NS_OK;
  554. }
  555. already_AddRefed<nsISelectionController>
  556. EditorBase::GetSelectionController()
  557. {
  558. nsCOMPtr<nsISelectionController> selectionController;
  559. if (mSelectionControllerWeak) {
  560. selectionController = mSelectionControllerWeak.get();
  561. } else {
  562. nsCOMPtr<nsIPresShell> presShell = GetPresShell();
  563. selectionController = do_QueryInterface(presShell);
  564. }
  565. return selectionController.forget();
  566. }
  567. NS_IMETHODIMP
  568. EditorBase::DeleteSelection(EDirection aAction,
  569. EStripWrappers aStripWrappers)
  570. {
  571. MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
  572. return DeleteSelectionImpl(aAction, aStripWrappers);
  573. }
  574. NS_IMETHODIMP
  575. EditorBase::GetSelection(nsISelection** aSelection)
  576. {
  577. return GetSelection(SelectionType::eNormal, aSelection);
  578. }
  579. nsresult
  580. EditorBase::GetSelection(SelectionType aSelectionType,
  581. nsISelection** aSelection)
  582. {
  583. NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
  584. *aSelection = nullptr;
  585. nsCOMPtr<nsISelectionController> selcon = GetSelectionController();
  586. if (!selcon) {
  587. return NS_ERROR_NOT_INITIALIZED;
  588. }
  589. return selcon->GetSelection(ToRawSelectionType(aSelectionType), aSelection);
  590. }
  591. Selection*
  592. EditorBase::GetSelection(SelectionType aSelectionType)
  593. {
  594. nsCOMPtr<nsISelection> sel;
  595. nsresult rv = GetSelection(aSelectionType, getter_AddRefs(sel));
  596. if (NS_WARN_IF(NS_FAILED(rv)) || NS_WARN_IF(!sel)) {
  597. return nullptr;
  598. }
  599. return sel->AsSelection();
  600. }
  601. NS_IMETHODIMP
  602. EditorBase::DoTransaction(nsITransaction* aTxn)
  603. {
  604. if (mPlaceholderBatch && !mPlaceholderTransactionWeak) {
  605. RefPtr<PlaceholderTransaction> placeholderTransaction =
  606. new PlaceholderTransaction(*this, mPlaceholderName, Move(mSelState));
  607. // Save off weak reference to placeholder transaction
  608. mPlaceholderTransactionWeak = placeholderTransaction;
  609. // We will recurse, but will not hit this case in the nested call
  610. DoTransaction(placeholderTransaction);
  611. if (mTxnMgr) {
  612. nsCOMPtr<nsITransaction> topTransaction = mTxnMgr->PeekUndoStack();
  613. nsCOMPtr<nsIAbsorbingTransaction> topAbsorbingTransaction =
  614. do_QueryInterface(topTransaction);
  615. if (topAbsorbingTransaction) {
  616. RefPtr<PlaceholderTransaction> topPlaceholderTransaction =
  617. topAbsorbingTransaction->AsPlaceholderTransaction();
  618. if (topPlaceholderTransaction) {
  619. // there is a placeholder transaction on top of the undo stack. It
  620. // is either the one we just created, or an earlier one that we are
  621. // now merging into. From here on out remember this placeholder
  622. // instead of the one we just created.
  623. mPlaceholderTransactionWeak = topPlaceholderTransaction;
  624. }
  625. }
  626. }
  627. }
  628. if (aTxn) {
  629. // XXX: Why are we doing selection specific batching stuff here?
  630. // XXX: Most entry points into the editor have auto variables that
  631. // XXX: should trigger Begin/EndUpdateViewBatch() calls that will make
  632. // XXX: these selection batch calls no-ops.
  633. // XXX:
  634. // XXX: I suspect that this was placed here to avoid multiple
  635. // XXX: selection changed notifications from happening until after
  636. // XXX: the transaction was done. I suppose that can still happen
  637. // XXX: if an embedding application called DoTransaction() directly
  638. // XXX: to pump its own transactions through the system, but in that
  639. // XXX: case, wouldn't we want to use Begin/EndUpdateViewBatch() or
  640. // XXX: its auto equivalent AutoUpdateViewBatch to ensure that
  641. // XXX: selection listeners have access to accurate frame data?
  642. // XXX:
  643. // XXX: Note that if we did add Begin/EndUpdateViewBatch() calls
  644. // XXX: we will need to make sure that they are disabled during
  645. // XXX: the init of the editor for text widgets to avoid layout
  646. // XXX: re-entry during initial reflow. - kin
  647. // get the selection and start a batch change
  648. RefPtr<Selection> selection = GetSelection();
  649. NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
  650. selection->StartBatchChanges();
  651. nsresult rv;
  652. if (mTxnMgr) {
  653. RefPtr<nsTransactionManager> txnMgr = mTxnMgr;
  654. rv = txnMgr->DoTransaction(aTxn);
  655. } else {
  656. rv = aTxn->DoTransaction();
  657. }
  658. if (NS_SUCCEEDED(rv)) {
  659. DoAfterDoTransaction(aTxn);
  660. }
  661. // no need to check rv here, don't lose result of operation
  662. selection->EndBatchChanges();
  663. NS_ENSURE_SUCCESS(rv, rv);
  664. }
  665. return NS_OK;
  666. }
  667. NS_IMETHODIMP
  668. EditorBase::EnableUndo(bool aEnable)
  669. {
  670. if (aEnable) {
  671. if (!mTxnMgr) {
  672. mTxnMgr = new nsTransactionManager();
  673. }
  674. mTxnMgr->SetMaxTransactionCount(-1);
  675. } else if (mTxnMgr) {
  676. // disable the transaction manager if it is enabled
  677. mTxnMgr->Clear();
  678. mTxnMgr->SetMaxTransactionCount(0);
  679. }
  680. return NS_OK;
  681. }
  682. NS_IMETHODIMP
  683. EditorBase::GetNumberOfUndoItems(int32_t* aNumItems)
  684. {
  685. *aNumItems = 0;
  686. return mTxnMgr ? mTxnMgr->GetNumberOfUndoItems(aNumItems) : NS_OK;
  687. }
  688. NS_IMETHODIMP
  689. EditorBase::GetNumberOfRedoItems(int32_t* aNumItems)
  690. {
  691. *aNumItems = 0;
  692. return mTxnMgr ? mTxnMgr->GetNumberOfRedoItems(aNumItems) : NS_OK;
  693. }
  694. NS_IMETHODIMP
  695. EditorBase::GetTransactionManager(nsITransactionManager** aTxnManager)
  696. {
  697. NS_ENSURE_ARG_POINTER(aTxnManager);
  698. *aTxnManager = nullptr;
  699. NS_ENSURE_TRUE(mTxnMgr, NS_ERROR_FAILURE);
  700. NS_ADDREF(*aTxnManager = mTxnMgr);
  701. return NS_OK;
  702. }
  703. NS_IMETHODIMP
  704. EditorBase::SetTransactionManager(nsITransactionManager* aTxnManager)
  705. {
  706. NS_ENSURE_TRUE(aTxnManager, NS_ERROR_FAILURE);
  707. // nsITransactionManager is builtinclass, so this is safe
  708. mTxnMgr = static_cast<nsTransactionManager*>(aTxnManager);
  709. return NS_OK;
  710. }
  711. NS_IMETHODIMP
  712. EditorBase::Undo(uint32_t aCount)
  713. {
  714. ForceCompositionEnd();
  715. bool hasTxnMgr, hasTransaction = false;
  716. CanUndo(&hasTxnMgr, &hasTransaction);
  717. NS_ENSURE_TRUE(hasTransaction, NS_OK);
  718. AutoRules beginRulesSniffing(this, EditAction::undo, nsIEditor::eNone);
  719. if (!mTxnMgr) {
  720. return NS_OK;
  721. }
  722. RefPtr<nsTransactionManager> txnMgr = mTxnMgr;
  723. for (uint32_t i = 0; i < aCount; ++i) {
  724. nsresult rv = txnMgr->UndoTransaction();
  725. NS_ENSURE_SUCCESS(rv, rv);
  726. DoAfterUndoTransaction();
  727. }
  728. return NS_OK;
  729. }
  730. NS_IMETHODIMP
  731. EditorBase::CanUndo(bool* aIsEnabled,
  732. bool* aCanUndo)
  733. {
  734. NS_ENSURE_TRUE(aIsEnabled && aCanUndo, NS_ERROR_NULL_POINTER);
  735. *aIsEnabled = !!mTxnMgr;
  736. if (*aIsEnabled) {
  737. int32_t numTxns = 0;
  738. mTxnMgr->GetNumberOfUndoItems(&numTxns);
  739. *aCanUndo = !!numTxns;
  740. } else {
  741. *aCanUndo = false;
  742. }
  743. return NS_OK;
  744. }
  745. NS_IMETHODIMP
  746. EditorBase::Redo(uint32_t aCount)
  747. {
  748. bool hasTxnMgr, hasTransaction = false;
  749. CanRedo(&hasTxnMgr, &hasTransaction);
  750. NS_ENSURE_TRUE(hasTransaction, NS_OK);
  751. AutoRules beginRulesSniffing(this, EditAction::redo, nsIEditor::eNone);
  752. if (!mTxnMgr) {
  753. return NS_OK;
  754. }
  755. RefPtr<nsTransactionManager> txnMgr = mTxnMgr;
  756. for (uint32_t i = 0; i < aCount; ++i) {
  757. nsresult rv = txnMgr->RedoTransaction();
  758. NS_ENSURE_SUCCESS(rv, rv);
  759. DoAfterRedoTransaction();
  760. }
  761. return NS_OK;
  762. }
  763. NS_IMETHODIMP
  764. EditorBase::CanRedo(bool* aIsEnabled, bool* aCanRedo)
  765. {
  766. NS_ENSURE_TRUE(aIsEnabled && aCanRedo, NS_ERROR_NULL_POINTER);
  767. *aIsEnabled = !!mTxnMgr;
  768. if (*aIsEnabled) {
  769. int32_t numTxns = 0;
  770. mTxnMgr->GetNumberOfRedoItems(&numTxns);
  771. *aCanRedo = !!numTxns;
  772. } else {
  773. *aCanRedo = false;
  774. }
  775. return NS_OK;
  776. }
  777. NS_IMETHODIMP
  778. EditorBase::BeginTransaction()
  779. {
  780. BeginUpdateViewBatch();
  781. if (mTxnMgr) {
  782. RefPtr<nsTransactionManager> txnMgr = mTxnMgr;
  783. txnMgr->BeginBatch(nullptr);
  784. }
  785. return NS_OK;
  786. }
  787. NS_IMETHODIMP
  788. EditorBase::EndTransaction()
  789. {
  790. if (mTxnMgr) {
  791. RefPtr<nsTransactionManager> txnMgr = mTxnMgr;
  792. txnMgr->EndBatch(false);
  793. }
  794. EndUpdateViewBatch();
  795. return NS_OK;
  796. }
  797. // These two routines are similar to the above, but do not use
  798. // the transaction managers batching feature. Instead we use
  799. // a placeholder transaction to wrap up any further transaction
  800. // while the batch is open. The advantage of this is that
  801. // placeholder transactions can later merge, if needed. Merging
  802. // is unavailable between transaction manager batches.
  803. NS_IMETHODIMP
  804. EditorBase::BeginPlaceHolderTransaction(nsIAtom* aName)
  805. {
  806. MOZ_ASSERT(mPlaceholderBatch >= 0, "negative placeholder batch count!");
  807. if (!mPlaceholderBatch) {
  808. NotifyEditorObservers(eNotifyEditorObserversOfBefore);
  809. // time to turn on the batch
  810. BeginUpdateViewBatch();
  811. mPlaceholderTransactionWeak = nullptr;
  812. mPlaceholderName = aName;
  813. RefPtr<Selection> selection = GetSelection();
  814. if (selection) {
  815. mSelState = MakeUnique<SelectionState>();
  816. mSelState->SaveSelection(selection);
  817. // Composition transaction can modify multiple nodes and it merges text
  818. // node for ime into single text node.
  819. // So if current selection is into IME text node, it might be failed
  820. // to restore selection by UndoTransaction.
  821. // So we need update selection by range updater.
  822. if (mPlaceholderName == nsGkAtoms::IMETxnName) {
  823. mRangeUpdater.RegisterSelectionState(*mSelState);
  824. }
  825. }
  826. }
  827. mPlaceholderBatch++;
  828. return NS_OK;
  829. }
  830. NS_IMETHODIMP
  831. EditorBase::EndPlaceHolderTransaction()
  832. {
  833. MOZ_ASSERT(mPlaceholderBatch > 0,
  834. "zero or negative placeholder batch count when ending batch!");
  835. if (mPlaceholderBatch == 1) {
  836. RefPtr<Selection> selection = GetSelection();
  837. // By making the assumption that no reflow happens during the calls
  838. // to EndUpdateViewBatch and ScrollSelectionIntoView, we are able to
  839. // allow the selection to cache a frame offset which is used by the
  840. // caret drawing code. We only enable this cache here; at other times,
  841. // we have no way to know whether reflow invalidates it
  842. // See bugs 35296 and 199412.
  843. if (selection) {
  844. selection->SetCanCacheFrameOffset(true);
  845. }
  846. {
  847. // Hide the caret here to avoid hiding it twice, once in EndUpdateViewBatch
  848. // and once in ScrollSelectionIntoView.
  849. RefPtr<nsCaret> caret;
  850. nsCOMPtr<nsIPresShell> presShell = GetPresShell();
  851. if (presShell) {
  852. caret = presShell->GetCaret();
  853. }
  854. // time to turn off the batch
  855. EndUpdateViewBatch();
  856. // make sure selection is in view
  857. // After ScrollSelectionIntoView(), the pending notifications might be
  858. // flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
  859. ScrollSelectionIntoView(false);
  860. }
  861. // cached for frame offset are Not available now
  862. if (selection) {
  863. selection->SetCanCacheFrameOffset(false);
  864. }
  865. if (mSelState) {
  866. // we saved the selection state, but never got to hand it to placeholder
  867. // (else we ould have nulled out this pointer), so destroy it to prevent leaks.
  868. if (mPlaceholderName == nsGkAtoms::IMETxnName) {
  869. mRangeUpdater.DropSelectionState(*mSelState);
  870. }
  871. mSelState = nullptr;
  872. }
  873. // We might have never made a placeholder if no action took place.
  874. if (mPlaceholderTransactionWeak) {
  875. RefPtr<PlaceholderTransaction> placeholderTransaction =
  876. mPlaceholderTransactionWeak.get();
  877. placeholderTransaction->EndPlaceHolderBatch();
  878. // notify editor observers of action but if composing, it's done by
  879. // compositionchange event handler.
  880. if (!mComposition) {
  881. NotifyEditorObservers(eNotifyEditorObserversOfEnd);
  882. }
  883. } else {
  884. NotifyEditorObservers(eNotifyEditorObserversOfCancel);
  885. }
  886. }
  887. mPlaceholderBatch--;
  888. return NS_OK;
  889. }
  890. NS_IMETHODIMP
  891. EditorBase::ShouldTxnSetSelection(bool* aResult)
  892. {
  893. NS_ENSURE_TRUE(aResult, NS_ERROR_NULL_POINTER);
  894. *aResult = mShouldTxnSetSelection;
  895. return NS_OK;
  896. }
  897. NS_IMETHODIMP
  898. EditorBase::SetShouldTxnSetSelection(bool aShould)
  899. {
  900. mShouldTxnSetSelection = aShould;
  901. return NS_OK;
  902. }
  903. NS_IMETHODIMP
  904. EditorBase::GetDocumentIsEmpty(bool* aDocumentIsEmpty)
  905. {
  906. *aDocumentIsEmpty = true;
  907. dom::Element* root = GetRoot();
  908. NS_ENSURE_TRUE(root, NS_ERROR_NULL_POINTER);
  909. *aDocumentIsEmpty = !root->HasChildren();
  910. return NS_OK;
  911. }
  912. // XXX: The rule system should tell us which node to select all on (ie, the
  913. // root, or the body)
  914. NS_IMETHODIMP
  915. EditorBase::SelectAll()
  916. {
  917. // XXX Why doesn't this check if the document is alive?
  918. if (!IsInitialized()) {
  919. return NS_ERROR_NOT_INITIALIZED;
  920. }
  921. ForceCompositionEnd();
  922. RefPtr<Selection> selection = GetSelection();
  923. NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
  924. return SelectEntireDocument(selection);
  925. }
  926. NS_IMETHODIMP
  927. EditorBase::BeginningOfDocument()
  928. {
  929. // XXX Why doesn't this check if the document is alive?
  930. if (!IsInitialized()) {
  931. return NS_ERROR_NOT_INITIALIZED;
  932. }
  933. // get the selection
  934. RefPtr<Selection> selection = GetSelection();
  935. NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
  936. // get the root element
  937. dom::Element* rootElement = GetRoot();
  938. NS_ENSURE_TRUE(rootElement, NS_ERROR_NULL_POINTER);
  939. // find first editable thingy
  940. nsCOMPtr<nsINode> firstNode = GetFirstEditableNode(rootElement);
  941. if (!firstNode) {
  942. // just the root node, set selection to inside the root
  943. return selection->CollapseNative(rootElement, 0);
  944. }
  945. if (firstNode->NodeType() == nsIDOMNode::TEXT_NODE) {
  946. // If firstNode is text, set selection to beginning of the text node.
  947. return selection->CollapseNative(firstNode, 0);
  948. }
  949. // Otherwise, it's a leaf node and we set the selection just in front of it.
  950. nsCOMPtr<nsIContent> parent = firstNode->GetParent();
  951. if (!parent) {
  952. return NS_ERROR_NULL_POINTER;
  953. }
  954. int32_t offsetInParent = parent->IndexOf(firstNode);
  955. return selection->CollapseNative(parent, offsetInParent);
  956. }
  957. NS_IMETHODIMP
  958. EditorBase::EndOfDocument()
  959. {
  960. // XXX Why doesn't this check if the document is alive?
  961. if (NS_WARN_IF(!IsInitialized())) {
  962. return NS_ERROR_NOT_INITIALIZED;
  963. }
  964. // get selection
  965. RefPtr<Selection> selection = GetSelection();
  966. NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
  967. // get the root element
  968. nsINode* node = GetRoot();
  969. NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
  970. nsINode* child = node->GetLastChild();
  971. while (child && IsContainer(child->AsDOMNode())) {
  972. node = child;
  973. child = node->GetLastChild();
  974. }
  975. uint32_t length = node->Length();
  976. return selection->CollapseNative(node, int32_t(length));
  977. }
  978. NS_IMETHODIMP
  979. EditorBase::GetDocumentModified(bool* outDocModified)
  980. {
  981. NS_ENSURE_TRUE(outDocModified, NS_ERROR_NULL_POINTER);
  982. int32_t modCount = 0;
  983. GetModificationCount(&modCount);
  984. *outDocModified = (modCount != 0);
  985. return NS_OK;
  986. }
  987. NS_IMETHODIMP
  988. EditorBase::GetDocumentCharacterSet(nsACString& characterSet)
  989. {
  990. nsCOMPtr<nsIDocument> document = GetDocument();
  991. if (NS_WARN_IF(!document)) {
  992. return NS_ERROR_UNEXPECTED;
  993. }
  994. characterSet = document->GetDocumentCharacterSet();
  995. return NS_OK;
  996. }
  997. NS_IMETHODIMP
  998. EditorBase::SetDocumentCharacterSet(const nsACString& characterSet)
  999. {
  1000. nsCOMPtr<nsIDocument> document = GetDocument();
  1001. if (NS_WARN_IF(!document)) {
  1002. return NS_ERROR_UNEXPECTED;
  1003. }
  1004. document->SetDocumentCharacterSet(characterSet);
  1005. return NS_OK;
  1006. }
  1007. NS_IMETHODIMP
  1008. EditorBase::Cut()
  1009. {
  1010. return NS_ERROR_NOT_IMPLEMENTED;
  1011. }
  1012. NS_IMETHODIMP
  1013. EditorBase::CanCut(bool* aCanCut)
  1014. {
  1015. return NS_ERROR_NOT_IMPLEMENTED;
  1016. }
  1017. NS_IMETHODIMP
  1018. EditorBase::Copy()
  1019. {
  1020. return NS_ERROR_NOT_IMPLEMENTED;
  1021. }
  1022. NS_IMETHODIMP
  1023. EditorBase::CanCopy(bool* aCanCut)
  1024. {
  1025. return NS_ERROR_NOT_IMPLEMENTED;
  1026. }
  1027. NS_IMETHODIMP
  1028. EditorBase::CanDelete(bool* aCanDelete)
  1029. {
  1030. return NS_ERROR_NOT_IMPLEMENTED;
  1031. }
  1032. NS_IMETHODIMP
  1033. EditorBase::Paste(int32_t aSelectionType)
  1034. {
  1035. return NS_ERROR_NOT_IMPLEMENTED;
  1036. }
  1037. NS_IMETHODIMP
  1038. EditorBase::PasteTransferable(nsITransferable* aTransferable)
  1039. {
  1040. return NS_ERROR_NOT_IMPLEMENTED;
  1041. }
  1042. NS_IMETHODIMP
  1043. EditorBase::CanPaste(int32_t aSelectionType, bool* aCanPaste)
  1044. {
  1045. return NS_ERROR_NOT_IMPLEMENTED;
  1046. }
  1047. NS_IMETHODIMP
  1048. EditorBase::CanPasteTransferable(nsITransferable* aTransferable,
  1049. bool* aCanPaste)
  1050. {
  1051. return NS_ERROR_NOT_IMPLEMENTED;
  1052. }
  1053. NS_IMETHODIMP
  1054. EditorBase::SetAttribute(nsIDOMElement* aElement,
  1055. const nsAString& aAttribute,
  1056. const nsAString& aValue)
  1057. {
  1058. if (NS_WARN_IF(aAttribute.IsEmpty())) {
  1059. return NS_ERROR_FAILURE;
  1060. }
  1061. nsCOMPtr<Element> element = do_QueryInterface(aElement);
  1062. NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
  1063. nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
  1064. return SetAttribute(element, attribute, aValue);
  1065. }
  1066. nsresult
  1067. EditorBase::SetAttribute(Element* aElement,
  1068. nsIAtom* aAttribute,
  1069. const nsAString& aValue)
  1070. {
  1071. RefPtr<ChangeAttributeTransaction> transaction =
  1072. CreateTxnForSetAttribute(*aElement, *aAttribute, aValue);
  1073. return DoTransaction(transaction);
  1074. }
  1075. NS_IMETHODIMP
  1076. EditorBase::GetAttributeValue(nsIDOMElement* aElement,
  1077. const nsAString& aAttribute,
  1078. nsAString& aResultValue,
  1079. bool* aResultIsSet)
  1080. {
  1081. NS_ENSURE_TRUE(aResultIsSet, NS_ERROR_NULL_POINTER);
  1082. *aResultIsSet = false;
  1083. if (!aElement) {
  1084. return NS_OK;
  1085. }
  1086. nsAutoString value;
  1087. nsresult rv = aElement->GetAttribute(aAttribute, value);
  1088. NS_ENSURE_SUCCESS(rv, rv);
  1089. if (!DOMStringIsNull(value)) {
  1090. *aResultIsSet = true;
  1091. aResultValue = value;
  1092. }
  1093. return rv;
  1094. }
  1095. NS_IMETHODIMP
  1096. EditorBase::RemoveAttribute(nsIDOMElement* aElement,
  1097. const nsAString& aAttribute)
  1098. {
  1099. if (NS_WARN_IF(aAttribute.IsEmpty())) {
  1100. return NS_ERROR_FAILURE;
  1101. }
  1102. nsCOMPtr<Element> element = do_QueryInterface(aElement);
  1103. NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
  1104. nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
  1105. return RemoveAttribute(element, attribute);
  1106. }
  1107. nsresult
  1108. EditorBase::RemoveAttribute(Element* aElement,
  1109. nsIAtom* aAttribute)
  1110. {
  1111. RefPtr<ChangeAttributeTransaction> transaction =
  1112. CreateTxnForRemoveAttribute(*aElement, *aAttribute);
  1113. return DoTransaction(transaction);
  1114. }
  1115. bool
  1116. EditorBase::OutputsMozDirty()
  1117. {
  1118. // Return true for Composer (!eEditorAllowInteraction) or mail
  1119. // (eEditorMailMask), but false for webpages.
  1120. return !(mFlags & nsIPlaintextEditor::eEditorAllowInteraction) ||
  1121. (mFlags & nsIPlaintextEditor::eEditorMailMask);
  1122. }
  1123. NS_IMETHODIMP
  1124. EditorBase::MarkNodeDirty(nsIDOMNode* aNode)
  1125. {
  1126. // Mark the node dirty, but not for webpages (bug 599983)
  1127. if (!OutputsMozDirty()) {
  1128. return NS_OK;
  1129. }
  1130. nsCOMPtr<dom::Element> element = do_QueryInterface(aNode);
  1131. if (element) {
  1132. element->SetAttr(kNameSpaceID_None, nsGkAtoms::mozdirty,
  1133. EmptyString(), false);
  1134. }
  1135. return NS_OK;
  1136. }
  1137. NS_IMETHODIMP
  1138. EditorBase::GetInlineSpellChecker(bool autoCreate,
  1139. nsIInlineSpellChecker** aInlineSpellChecker)
  1140. {
  1141. NS_ENSURE_ARG_POINTER(aInlineSpellChecker);
  1142. if (mDidPreDestroy) {
  1143. // Don't allow people to get or create the spell checker once the editor
  1144. // is going away.
  1145. *aInlineSpellChecker = nullptr;
  1146. return autoCreate ? NS_ERROR_NOT_AVAILABLE : NS_OK;
  1147. }
  1148. // We don't want to show the spell checking UI if there are no spell check dictionaries available.
  1149. bool canSpell = mozInlineSpellChecker::CanEnableInlineSpellChecking();
  1150. if (!canSpell) {
  1151. *aInlineSpellChecker = nullptr;
  1152. return NS_ERROR_FAILURE;
  1153. }
  1154. nsresult rv;
  1155. if (!mInlineSpellChecker && autoCreate) {
  1156. mInlineSpellChecker = do_CreateInstance(MOZ_INLINESPELLCHECKER_CONTRACTID, &rv);
  1157. NS_ENSURE_SUCCESS(rv, rv);
  1158. }
  1159. if (mInlineSpellChecker) {
  1160. rv = mInlineSpellChecker->Init(this);
  1161. if (NS_FAILED(rv)) {
  1162. mInlineSpellChecker = nullptr;
  1163. }
  1164. NS_ENSURE_SUCCESS(rv, rv);
  1165. }
  1166. NS_IF_ADDREF(*aInlineSpellChecker = mInlineSpellChecker);
  1167. return NS_OK;
  1168. }
  1169. NS_IMETHODIMP
  1170. EditorBase::SyncRealTimeSpell()
  1171. {
  1172. bool enable = GetDesiredSpellCheckState();
  1173. // Initializes mInlineSpellChecker
  1174. nsCOMPtr<nsIInlineSpellChecker> spellChecker;
  1175. GetInlineSpellChecker(enable, getter_AddRefs(spellChecker));
  1176. if (mInlineSpellChecker) {
  1177. // We might have a mInlineSpellChecker even if there are no dictionaries
  1178. // available since we don't destroy the mInlineSpellChecker when the last
  1179. // dictionariy is removed, but in that case spellChecker is null
  1180. mInlineSpellChecker->SetEnableRealTimeSpell(enable && spellChecker);
  1181. }
  1182. return NS_OK;
  1183. }
  1184. NS_IMETHODIMP
  1185. EditorBase::SetSpellcheckUserOverride(bool enable)
  1186. {
  1187. mSpellcheckCheckboxState = enable ? eTriTrue : eTriFalse;
  1188. return SyncRealTimeSpell();
  1189. }
  1190. NS_IMETHODIMP
  1191. EditorBase::CreateNode(const nsAString& aTag,
  1192. nsIDOMNode* aParent,
  1193. int32_t aPosition,
  1194. nsIDOMNode** aNewNode)
  1195. {
  1196. nsCOMPtr<nsIAtom> tag = NS_Atomize(aTag);
  1197. nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
  1198. NS_ENSURE_STATE(parent);
  1199. *aNewNode = GetAsDOMNode(CreateNode(tag, parent, aPosition).take());
  1200. NS_ENSURE_STATE(*aNewNode);
  1201. return NS_OK;
  1202. }
  1203. already_AddRefed<Element>
  1204. EditorBase::CreateNode(nsIAtom* aTag,
  1205. nsINode* aParent,
  1206. int32_t aPosition)
  1207. {
  1208. MOZ_ASSERT(aTag && aParent);
  1209. AutoRules beginRulesSniffing(this, EditAction::createNode, nsIEditor::eNext);
  1210. {
  1211. AutoActionListenerArray listeners(mActionListeners);
  1212. for (auto& listener : listeners) {
  1213. listener->WillCreateNode(nsDependentAtomString(aTag),
  1214. GetAsDOMNode(aParent), aPosition);
  1215. }
  1216. }
  1217. nsCOMPtr<Element> ret;
  1218. RefPtr<CreateElementTransaction> transaction =
  1219. CreateTxnForCreateElement(*aTag, *aParent, aPosition);
  1220. nsresult rv = DoTransaction(transaction);
  1221. if (NS_SUCCEEDED(rv)) {
  1222. ret = transaction->GetNewNode();
  1223. MOZ_ASSERT(ret);
  1224. }
  1225. mRangeUpdater.SelAdjCreateNode(aParent, aPosition);
  1226. {
  1227. AutoActionListenerArray listeners(mActionListeners);
  1228. for (auto& listener : listeners) {
  1229. listener->DidCreateNode(nsDependentAtomString(aTag), GetAsDOMNode(ret),
  1230. GetAsDOMNode(aParent), aPosition, rv);
  1231. }
  1232. }
  1233. return ret.forget();
  1234. }
  1235. NS_IMETHODIMP
  1236. EditorBase::InsertNode(nsIDOMNode* aNode,
  1237. nsIDOMNode* aParent,
  1238. int32_t aPosition)
  1239. {
  1240. nsCOMPtr<nsIContent> node = do_QueryInterface(aNode);
  1241. nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
  1242. NS_ENSURE_TRUE(node && parent, NS_ERROR_NULL_POINTER);
  1243. return InsertNode(*node, *parent, aPosition);
  1244. }
  1245. nsresult
  1246. EditorBase::InsertNode(nsIContent& aNode,
  1247. nsINode& aParent,
  1248. int32_t aPosition)
  1249. {
  1250. AutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext);
  1251. {
  1252. AutoActionListenerArray listeners(mActionListeners);
  1253. for (auto& listener : listeners) {
  1254. listener->WillInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(),
  1255. aPosition);
  1256. }
  1257. }
  1258. RefPtr<InsertNodeTransaction> transaction =
  1259. CreateTxnForInsertNode(aNode, aParent, aPosition);
  1260. nsresult rv = DoTransaction(transaction);
  1261. mRangeUpdater.SelAdjInsertNode(aParent.AsDOMNode(), aPosition);
  1262. {
  1263. AutoActionListenerArray listeners(mActionListeners);
  1264. for (auto& listener : listeners) {
  1265. listener->DidInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(), aPosition,
  1266. rv);
  1267. }
  1268. }
  1269. return rv;
  1270. }
  1271. NS_IMETHODIMP
  1272. EditorBase::SplitNode(nsIDOMNode* aNode,
  1273. int32_t aOffset,
  1274. nsIDOMNode** aNewLeftNode)
  1275. {
  1276. nsCOMPtr<nsIContent> node = do_QueryInterface(aNode);
  1277. NS_ENSURE_STATE(node);
  1278. ErrorResult rv;
  1279. nsCOMPtr<nsIContent> newNode = SplitNode(*node, aOffset, rv);
  1280. *aNewLeftNode = GetAsDOMNode(newNode.forget().take());
  1281. return rv.StealNSResult();
  1282. }
  1283. nsIContent*
  1284. EditorBase::SplitNode(nsIContent& aNode,
  1285. int32_t aOffset,
  1286. ErrorResult& aResult)
  1287. {
  1288. AutoRules beginRulesSniffing(this, EditAction::splitNode, nsIEditor::eNext);
  1289. {
  1290. AutoActionListenerArray listeners(mActionListeners);
  1291. for (auto& listener : listeners) {
  1292. listener->WillSplitNode(aNode.AsDOMNode(), aOffset);
  1293. }
  1294. }
  1295. RefPtr<SplitNodeTransaction> transaction =
  1296. CreateTxnForSplitNode(aNode, aOffset);
  1297. aResult = DoTransaction(transaction);
  1298. nsCOMPtr<nsIContent> newNode = aResult.Failed() ? nullptr
  1299. : transaction->GetNewNode();
  1300. mRangeUpdater.SelAdjSplitNode(aNode, aOffset, newNode);
  1301. nsresult rv = aResult.StealNSResult();
  1302. {
  1303. AutoActionListenerArray listeners(mActionListeners);
  1304. for (auto& listener : listeners) {
  1305. listener->DidSplitNode(aNode.AsDOMNode(), aOffset, GetAsDOMNode(newNode),
  1306. rv);
  1307. }
  1308. }
  1309. // Note: result might be a success code, so we can't use Throw() to
  1310. // set it on aResult.
  1311. aResult = rv;
  1312. return newNode;
  1313. }
  1314. NS_IMETHODIMP
  1315. EditorBase::JoinNodes(nsIDOMNode* aLeftNode,
  1316. nsIDOMNode* aRightNode,
  1317. nsIDOMNode*)
  1318. {
  1319. nsCOMPtr<nsINode> leftNode = do_QueryInterface(aLeftNode);
  1320. nsCOMPtr<nsINode> rightNode = do_QueryInterface(aRightNode);
  1321. NS_ENSURE_STATE(leftNode && rightNode && leftNode->GetParentNode());
  1322. return JoinNodes(*leftNode, *rightNode);
  1323. }
  1324. nsresult
  1325. EditorBase::JoinNodes(nsINode& aLeftNode,
  1326. nsINode& aRightNode)
  1327. {
  1328. nsCOMPtr<nsINode> parent = aLeftNode.GetParentNode();
  1329. MOZ_ASSERT(parent);
  1330. AutoRules beginRulesSniffing(this, EditAction::joinNode,
  1331. nsIEditor::ePrevious);
  1332. // Remember some values; later used for saved selection updating.
  1333. // Find the offset between the nodes to be joined.
  1334. int32_t offset = parent->IndexOf(&aRightNode);
  1335. // Find the number of children of the lefthand node
  1336. uint32_t oldLeftNodeLen = aLeftNode.Length();
  1337. {
  1338. AutoActionListenerArray listeners(mActionListeners);
  1339. for (auto& listener : listeners) {
  1340. listener->WillJoinNodes(aLeftNode.AsDOMNode(), aRightNode.AsDOMNode(),
  1341. parent->AsDOMNode());
  1342. }
  1343. }
  1344. nsresult rv = NS_OK;
  1345. RefPtr<JoinNodeTransaction> transaction =
  1346. CreateTxnForJoinNode(aLeftNode, aRightNode);
  1347. if (transaction) {
  1348. rv = DoTransaction(transaction);
  1349. }
  1350. mRangeUpdater.SelAdjJoinNodes(aLeftNode, aRightNode, *parent, offset,
  1351. (int32_t)oldLeftNodeLen);
  1352. {
  1353. AutoActionListenerArray listeners(mActionListeners);
  1354. for (auto& listener : listeners) {
  1355. listener->DidJoinNodes(aLeftNode.AsDOMNode(), aRightNode.AsDOMNode(),
  1356. parent->AsDOMNode(), rv);
  1357. }
  1358. }
  1359. return rv;
  1360. }
  1361. NS_IMETHODIMP
  1362. EditorBase::DeleteNode(nsIDOMNode* aNode)
  1363. {
  1364. nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
  1365. NS_ENSURE_STATE(node);
  1366. return DeleteNode(node);
  1367. }
  1368. nsresult
  1369. EditorBase::DeleteNode(nsINode* aNode)
  1370. {
  1371. AutoRules beginRulesSniffing(this, EditAction::createNode,
  1372. nsIEditor::ePrevious);
  1373. // save node location for selection updating code.
  1374. {
  1375. AutoActionListenerArray listeners(mActionListeners);
  1376. for (auto& listener : listeners) {
  1377. listener->WillDeleteNode(aNode->AsDOMNode());
  1378. }
  1379. }
  1380. RefPtr<DeleteNodeTransaction> transaction;
  1381. nsresult rv = CreateTxnForDeleteNode(aNode, getter_AddRefs(transaction));
  1382. if (NS_SUCCEEDED(rv)) {
  1383. rv = DoTransaction(transaction);
  1384. }
  1385. {
  1386. AutoActionListenerArray listeners(mActionListeners);
  1387. for (auto& listener : listeners) {
  1388. listener->DidDeleteNode(aNode->AsDOMNode(), rv);
  1389. }
  1390. }
  1391. NS_ENSURE_SUCCESS(rv, rv);
  1392. return NS_OK;
  1393. }
  1394. /**
  1395. * ReplaceContainer() replaces inNode with a new node (outNode) which is
  1396. * constructed to be of type aNodeType. Put inNodes children into outNode.
  1397. * Callers responsibility to make sure inNode's children can go in outNode.
  1398. */
  1399. already_AddRefed<Element>
  1400. EditorBase::ReplaceContainer(Element* aOldContainer,
  1401. nsIAtom* aNodeType,
  1402. nsIAtom* aAttribute,
  1403. const nsAString* aValue,
  1404. ECloneAttributes aCloneAttributes)
  1405. {
  1406. MOZ_ASSERT(aOldContainer && aNodeType);
  1407. nsCOMPtr<nsIContent> parent = aOldContainer->GetParent();
  1408. NS_ENSURE_TRUE(parent, nullptr);
  1409. int32_t offset = parent->IndexOf(aOldContainer);
  1410. // create new container
  1411. nsCOMPtr<Element> ret = CreateHTMLContent(aNodeType);
  1412. NS_ENSURE_TRUE(ret, nullptr);
  1413. // set attribute if needed
  1414. if (aAttribute && aValue && aAttribute != nsGkAtoms::_empty) {
  1415. nsresult rv = ret->SetAttr(kNameSpaceID_None, aAttribute, *aValue, true);
  1416. NS_ENSURE_SUCCESS(rv, nullptr);
  1417. }
  1418. if (aCloneAttributes == eCloneAttributes) {
  1419. CloneAttributes(ret, aOldContainer);
  1420. }
  1421. // notify our internal selection state listener
  1422. // (Note: An AutoSelectionRestorer object must be created
  1423. // before calling this to initialize mRangeUpdater)
  1424. AutoReplaceContainerSelNotify selStateNotify(mRangeUpdater, aOldContainer,
  1425. ret);
  1426. {
  1427. AutoTransactionsConserveSelection conserveSelection(this);
  1428. while (aOldContainer->HasChildren()) {
  1429. nsCOMPtr<nsIContent> child = aOldContainer->GetFirstChild();
  1430. nsresult rv = DeleteNode(child);
  1431. NS_ENSURE_SUCCESS(rv, nullptr);
  1432. rv = InsertNode(*child, *ret, -1);
  1433. NS_ENSURE_SUCCESS(rv, nullptr);
  1434. }
  1435. }
  1436. // insert new container into tree
  1437. nsresult rv = InsertNode(*ret, *parent, offset);
  1438. NS_ENSURE_SUCCESS(rv, nullptr);
  1439. // delete old container
  1440. rv = DeleteNode(aOldContainer);
  1441. NS_ENSURE_SUCCESS(rv, nullptr);
  1442. return ret.forget();
  1443. }
  1444. /**
  1445. * RemoveContainer() removes inNode, reparenting its children (if any) into the
  1446. * parent of inNode.
  1447. */
  1448. nsresult
  1449. EditorBase::RemoveContainer(nsIContent* aNode)
  1450. {
  1451. MOZ_ASSERT(aNode);
  1452. nsCOMPtr<nsINode> parent = aNode->GetParentNode();
  1453. NS_ENSURE_STATE(parent);
  1454. int32_t offset = parent->IndexOf(aNode);
  1455. // Loop through the children of inNode and promote them into inNode's parent
  1456. uint32_t nodeOrigLen = aNode->GetChildCount();
  1457. // notify our internal selection state listener
  1458. AutoRemoveContainerSelNotify selNotify(mRangeUpdater, aNode, parent,
  1459. offset, nodeOrigLen);
  1460. while (aNode->HasChildren()) {
  1461. nsCOMPtr<nsIContent> child = aNode->GetLastChild();
  1462. nsresult rv = DeleteNode(child);
  1463. NS_ENSURE_SUCCESS(rv, rv);
  1464. rv = InsertNode(*child, *parent, offset);
  1465. NS_ENSURE_SUCCESS(rv, rv);
  1466. }
  1467. return DeleteNode(aNode);
  1468. }
  1469. /**
  1470. * InsertContainerAbove() inserts a new parent for inNode, which is contructed
  1471. * to be of type aNodeType. outNode becomes a child of inNode's earlier
  1472. * parent. Caller's responsibility to make sure inNode's can be child of
  1473. * outNode, and outNode can be child of old parent.
  1474. */
  1475. already_AddRefed<Element>
  1476. EditorBase::InsertContainerAbove(nsIContent* aNode,
  1477. nsIAtom* aNodeType,
  1478. nsIAtom* aAttribute,
  1479. const nsAString* aValue)
  1480. {
  1481. MOZ_ASSERT(aNode && aNodeType);
  1482. nsCOMPtr<nsIContent> parent = aNode->GetParent();
  1483. NS_ENSURE_TRUE(parent, nullptr);
  1484. int32_t offset = parent->IndexOf(aNode);
  1485. // Create new container
  1486. nsCOMPtr<Element> newContent = CreateHTMLContent(aNodeType);
  1487. NS_ENSURE_TRUE(newContent, nullptr);
  1488. // Set attribute if needed
  1489. if (aAttribute && aValue && aAttribute != nsGkAtoms::_empty) {
  1490. nsresult rv =
  1491. newContent->SetAttr(kNameSpaceID_None, aAttribute, *aValue, true);
  1492. NS_ENSURE_SUCCESS(rv, nullptr);
  1493. }
  1494. // Notify our internal selection state listener
  1495. AutoInsertContainerSelNotify selNotify(mRangeUpdater);
  1496. // Put inNode in new parent, outNode
  1497. nsresult rv = DeleteNode(aNode);
  1498. NS_ENSURE_SUCCESS(rv, nullptr);
  1499. {
  1500. AutoTransactionsConserveSelection conserveSelection(this);
  1501. rv = InsertNode(*aNode, *newContent, 0);
  1502. NS_ENSURE_SUCCESS(rv, nullptr);
  1503. }
  1504. // Put new parent in doc
  1505. rv = InsertNode(*newContent, *parent, offset);
  1506. NS_ENSURE_SUCCESS(rv, nullptr);
  1507. return newContent.forget();
  1508. }
  1509. /**
  1510. * MoveNode() moves aNode to {aParent,aOffset}.
  1511. */
  1512. nsresult
  1513. EditorBase::MoveNode(nsIContent* aNode,
  1514. nsINode* aParent,
  1515. int32_t aOffset)
  1516. {
  1517. MOZ_ASSERT(aNode);
  1518. MOZ_ASSERT(aParent);
  1519. MOZ_ASSERT(aOffset == -1 ||
  1520. (0 <= aOffset &&
  1521. AssertedCast<uint32_t>(aOffset) <= aParent->Length()));
  1522. nsCOMPtr<nsINode> oldParent = aNode->GetParentNode();
  1523. int32_t oldOffset = oldParent ? oldParent->IndexOf(aNode) : -1;
  1524. if (aOffset == -1) {
  1525. // Magic value meaning "move to end of aParent"
  1526. aOffset = AssertedCast<int32_t>(aParent->Length());
  1527. }
  1528. // Don't do anything if it's already in right place
  1529. if (aParent == oldParent && aOffset == oldOffset) {
  1530. return NS_OK;
  1531. }
  1532. // Notify our internal selection state listener
  1533. AutoMoveNodeSelNotify selNotify(mRangeUpdater, oldParent, oldOffset,
  1534. aParent, aOffset);
  1535. // Need to adjust aOffset if we're moving aNode later in its current parent
  1536. if (aParent == oldParent && oldOffset < aOffset) {
  1537. // When we delete aNode, it will make the offsets after it off by one
  1538. aOffset--;
  1539. }
  1540. // Hold a reference so aNode doesn't go away when we remove it (bug 772282)
  1541. nsCOMPtr<nsINode> kungFuDeathGrip = aNode;
  1542. nsresult rv = DeleteNode(aNode);
  1543. NS_ENSURE_SUCCESS(rv, rv);
  1544. return InsertNode(*aNode, *aParent, aOffset);
  1545. }
  1546. NS_IMETHODIMP
  1547. EditorBase::AddEditorObserver(nsIEditorObserver* aObserver)
  1548. {
  1549. // we don't keep ownership of the observers. They must
  1550. // remove themselves as observers before they are destroyed.
  1551. NS_ENSURE_TRUE(aObserver, NS_ERROR_NULL_POINTER);
  1552. // Make sure the listener isn't already on the list
  1553. if (!mEditorObservers.Contains(aObserver)) {
  1554. mEditorObservers.AppendElement(*aObserver);
  1555. }
  1556. return NS_OK;
  1557. }
  1558. NS_IMETHODIMP
  1559. EditorBase::RemoveEditorObserver(nsIEditorObserver* aObserver)
  1560. {
  1561. NS_ENSURE_TRUE(aObserver, NS_ERROR_FAILURE);
  1562. mEditorObservers.RemoveElement(aObserver);
  1563. return NS_OK;
  1564. }
  1565. class EditorInputEventDispatcher final : public Runnable
  1566. {
  1567. public:
  1568. EditorInputEventDispatcher(EditorBase* aEditorBase,
  1569. nsIContent* aTarget,
  1570. bool aIsComposing)
  1571. : mEditorBase(aEditorBase)
  1572. , mTarget(aTarget)
  1573. , mIsComposing(aIsComposing)
  1574. {
  1575. }
  1576. NS_IMETHOD Run() override
  1577. {
  1578. // Note that we don't need to check mDispatchInputEvent here. We need
  1579. // to check it only when the editor requests to dispatch the input event.
  1580. if (!mTarget->IsInComposedDoc()) {
  1581. return NS_OK;
  1582. }
  1583. nsCOMPtr<nsIPresShell> ps = mEditorBase->GetPresShell();
  1584. if (!ps) {
  1585. return NS_OK;
  1586. }
  1587. nsCOMPtr<nsIWidget> widget = mEditorBase->GetWidget();
  1588. if (!widget) {
  1589. return NS_OK;
  1590. }
  1591. // Even if the change is caused by untrusted event, we need to dispatch
  1592. // trusted input event since it's a fact.
  1593. InternalEditorInputEvent inputEvent(true, eEditorInput, widget);
  1594. inputEvent.mTime = static_cast<uint64_t>(PR_Now() / 1000);
  1595. inputEvent.mIsComposing = mIsComposing;
  1596. nsEventStatus status = nsEventStatus_eIgnore;
  1597. nsresult rv =
  1598. ps->HandleEventWithTarget(&inputEvent, nullptr, mTarget, &status);
  1599. NS_ENSURE_SUCCESS(rv, NS_OK); // print the warning if error
  1600. return NS_OK;
  1601. }
  1602. private:
  1603. RefPtr<EditorBase> mEditorBase;
  1604. nsCOMPtr<nsIContent> mTarget;
  1605. bool mIsComposing;
  1606. };
  1607. void
  1608. EditorBase::NotifyEditorObservers(NotificationForEditorObservers aNotification)
  1609. {
  1610. // Copy the observers since EditAction()s can modify mEditorObservers.
  1611. AutoEditorObserverArray observers(mEditorObservers);
  1612. switch (aNotification) {
  1613. case eNotifyEditorObserversOfEnd:
  1614. mIsInEditAction = false;
  1615. for (auto& observer : observers) {
  1616. observer->EditAction();
  1617. }
  1618. if (!mDispatchInputEvent) {
  1619. return;
  1620. }
  1621. FireInputEvent();
  1622. break;
  1623. case eNotifyEditorObserversOfBefore:
  1624. if (NS_WARN_IF(mIsInEditAction)) {
  1625. break;
  1626. }
  1627. mIsInEditAction = true;
  1628. for (auto& observer : observers) {
  1629. observer->BeforeEditAction();
  1630. }
  1631. break;
  1632. case eNotifyEditorObserversOfCancel:
  1633. mIsInEditAction = false;
  1634. for (auto& observer : observers) {
  1635. observer->CancelEditAction();
  1636. }
  1637. break;
  1638. default:
  1639. MOZ_CRASH("Handle all notifications here");
  1640. break;
  1641. }
  1642. }
  1643. void
  1644. EditorBase::FireInputEvent()
  1645. {
  1646. // We don't need to dispatch multiple input events if there is a pending
  1647. // input event. However, it may have different event target. If we resolved
  1648. // this issue, we need to manage the pending events in an array. But it's
  1649. // overwork. We don't need to do it for the very rare case.
  1650. nsCOMPtr<nsIContent> target = GetInputEventTargetContent();
  1651. NS_ENSURE_TRUE_VOID(target);
  1652. // NOTE: Don't refer IsIMEComposing() because it returns false even before
  1653. // compositionend. However, DOM Level 3 Events defines it should be
  1654. // true after compositionstart and before compositionend.
  1655. nsContentUtils::AddScriptRunner(
  1656. new EditorInputEventDispatcher(this, target, !!GetComposition()));
  1657. }
  1658. NS_IMETHODIMP
  1659. EditorBase::AddEditActionListener(nsIEditActionListener* aListener)
  1660. {
  1661. NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER);
  1662. // Make sure the listener isn't already on the list
  1663. if (!mActionListeners.Contains(aListener)) {
  1664. mActionListeners.AppendElement(*aListener);
  1665. }
  1666. return NS_OK;
  1667. }
  1668. NS_IMETHODIMP
  1669. EditorBase::RemoveEditActionListener(nsIEditActionListener* aListener)
  1670. {
  1671. NS_ENSURE_TRUE(aListener, NS_ERROR_FAILURE);
  1672. mActionListeners.RemoveElement(aListener);
  1673. return NS_OK;
  1674. }
  1675. NS_IMETHODIMP
  1676. EditorBase::AddDocumentStateListener(nsIDocumentStateListener* aListener)
  1677. {
  1678. NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER);
  1679. if (!mDocStateListeners.Contains(aListener)) {
  1680. mDocStateListeners.AppendElement(*aListener);
  1681. }
  1682. return NS_OK;
  1683. }
  1684. NS_IMETHODIMP
  1685. EditorBase::RemoveDocumentStateListener(nsIDocumentStateListener* aListener)
  1686. {
  1687. NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER);
  1688. mDocStateListeners.RemoveElement(aListener);
  1689. return NS_OK;
  1690. }
  1691. NS_IMETHODIMP
  1692. EditorBase::OutputToString(const nsAString& aFormatType,
  1693. uint32_t aFlags,
  1694. nsAString& aOutputString)
  1695. {
  1696. // these should be implemented by derived classes.
  1697. return NS_ERROR_NOT_IMPLEMENTED;
  1698. }
  1699. NS_IMETHODIMP
  1700. EditorBase::OutputToStream(nsIOutputStream* aOutputStream,
  1701. const nsAString& aFormatType,
  1702. const nsACString& aCharsetOverride,
  1703. uint32_t aFlags)
  1704. {
  1705. // these should be implemented by derived classes.
  1706. return NS_ERROR_NOT_IMPLEMENTED;
  1707. }
  1708. NS_IMETHODIMP
  1709. EditorBase::DumpContentTree()
  1710. {
  1711. #ifdef DEBUG
  1712. if (mRootElement) {
  1713. mRootElement->List(stdout);
  1714. }
  1715. #endif
  1716. return NS_OK;
  1717. }
  1718. NS_IMETHODIMP
  1719. EditorBase::DebugDumpContent()
  1720. {
  1721. #ifdef DEBUG
  1722. nsCOMPtr<nsIDocument> document = GetDocument();
  1723. if (NS_WARN_IF(!document)) {
  1724. return NS_ERROR_NOT_INITIALIZED;
  1725. }
  1726. nsCOMPtr<nsIDOMHTMLDocument> domHTMLDocument = do_QueryInterface(document);
  1727. if (NS_WARN_IF(!domHTMLDocument)) {
  1728. return NS_ERROR_NOT_INITIALIZED;
  1729. }
  1730. nsCOMPtr<nsIDOMHTMLElement> bodyElement;
  1731. domHTMLDocument->GetBody(getter_AddRefs(bodyElement));
  1732. nsCOMPtr<nsIContent> content = do_QueryInterface(bodyElement);
  1733. if (content) {
  1734. content->List();
  1735. }
  1736. #endif
  1737. return NS_OK;
  1738. }
  1739. NS_IMETHODIMP
  1740. EditorBase::DebugUnitTests(int32_t* outNumTests,
  1741. int32_t* outNumTestsFailed)
  1742. {
  1743. #ifdef DEBUG
  1744. NS_NOTREACHED("This should never get called. Overridden by subclasses");
  1745. #endif
  1746. return NS_OK;
  1747. }
  1748. bool
  1749. EditorBase::ArePreservingSelection()
  1750. {
  1751. return !(mSavedSel.IsEmpty());
  1752. }
  1753. void
  1754. EditorBase::PreserveSelectionAcrossActions(Selection* aSel)
  1755. {
  1756. mSavedSel.SaveSelection(aSel);
  1757. mRangeUpdater.RegisterSelectionState(mSavedSel);
  1758. }
  1759. nsresult
  1760. EditorBase::RestorePreservedSelection(Selection* aSel)
  1761. {
  1762. if (mSavedSel.IsEmpty()) {
  1763. return NS_ERROR_FAILURE;
  1764. }
  1765. mSavedSel.RestoreSelection(aSel);
  1766. StopPreservingSelection();
  1767. return NS_OK;
  1768. }
  1769. void
  1770. EditorBase::StopPreservingSelection()
  1771. {
  1772. mRangeUpdater.DropSelectionState(mSavedSel);
  1773. mSavedSel.MakeEmpty();
  1774. }
  1775. bool
  1776. EditorBase::EnsureComposition(WidgetCompositionEvent* aCompositionEvent)
  1777. {
  1778. if (mComposition) {
  1779. return true;
  1780. }
  1781. // The compositionstart event must cause creating new TextComposition
  1782. // instance at being dispatched by IMEStateManager.
  1783. mComposition = IMEStateManager::GetTextCompositionFor(aCompositionEvent);
  1784. if (!mComposition) {
  1785. // However, TextComposition may be committed before the composition
  1786. // event comes here.
  1787. return false;
  1788. }
  1789. mComposition->StartHandlingComposition(this);
  1790. return true;
  1791. }
  1792. nsresult
  1793. EditorBase::BeginIMEComposition(WidgetCompositionEvent* aCompositionEvent)
  1794. {
  1795. MOZ_ASSERT(!mComposition, "There is composition already");
  1796. if (!EnsureComposition(aCompositionEvent)) {
  1797. return NS_OK;
  1798. }
  1799. if (mPhonetic) {
  1800. mPhonetic->Truncate(0);
  1801. }
  1802. return NS_OK;
  1803. }
  1804. void
  1805. EditorBase::EndIMEComposition()
  1806. {
  1807. NS_ENSURE_TRUE_VOID(mComposition); // nothing to do
  1808. // commit the IME transaction..we can get at it via the transaction mgr.
  1809. // Note that this means IME won't work without an undo stack!
  1810. if (mTxnMgr) {
  1811. nsCOMPtr<nsITransaction> txn = mTxnMgr->PeekUndoStack();
  1812. nsCOMPtr<nsIAbsorbingTransaction> plcTxn = do_QueryInterface(txn);
  1813. if (plcTxn) {
  1814. DebugOnly<nsresult> rv = plcTxn->Commit();
  1815. NS_ASSERTION(NS_SUCCEEDED(rv),
  1816. "nsIAbsorbingTransaction::Commit() failed");
  1817. }
  1818. }
  1819. // Composition string may have hidden the caret. Therefore, we need to
  1820. // cancel it here.
  1821. HideCaret(false);
  1822. /* reset the data we need to construct a transaction */
  1823. mIMETextNode = nullptr;
  1824. mIMETextOffset = 0;
  1825. mIMETextLength = 0;
  1826. mComposition->EndHandlingComposition(this);
  1827. mComposition = nullptr;
  1828. // notify editor observers of action
  1829. NotifyEditorObservers(eNotifyEditorObserversOfEnd);
  1830. }
  1831. NS_IMETHODIMP
  1832. EditorBase::GetPhonetic(nsAString& aPhonetic)
  1833. {
  1834. if (mPhonetic) {
  1835. aPhonetic = *mPhonetic;
  1836. } else {
  1837. aPhonetic.Truncate(0);
  1838. }
  1839. return NS_OK;
  1840. }
  1841. NS_IMETHODIMP
  1842. EditorBase::ForceCompositionEnd()
  1843. {
  1844. nsCOMPtr<nsIPresShell> ps = GetPresShell();
  1845. if (!ps) {
  1846. return NS_ERROR_NOT_AVAILABLE;
  1847. }
  1848. nsPresContext* pc = ps->GetPresContext();
  1849. if (!pc) {
  1850. return NS_ERROR_NOT_AVAILABLE;
  1851. }
  1852. return mComposition ?
  1853. IMEStateManager::NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, pc) : NS_OK;
  1854. }
  1855. NS_IMETHODIMP
  1856. EditorBase::GetPreferredIMEState(IMEState* aState)
  1857. {
  1858. NS_ENSURE_ARG_POINTER(aState);
  1859. aState->mEnabled = IMEState::ENABLED;
  1860. aState->mOpen = IMEState::DONT_CHANGE_OPEN_STATE;
  1861. if (IsReadonly() || IsDisabled()) {
  1862. aState->mEnabled = IMEState::DISABLED;
  1863. return NS_OK;
  1864. }
  1865. nsCOMPtr<nsIContent> content = GetRoot();
  1866. NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
  1867. nsIFrame* frame = content->GetPrimaryFrame();
  1868. NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
  1869. switch (frame->StyleUIReset()->mIMEMode) {
  1870. case NS_STYLE_IME_MODE_AUTO:
  1871. if (IsPasswordEditor())
  1872. aState->mEnabled = IMEState::PASSWORD;
  1873. break;
  1874. case NS_STYLE_IME_MODE_DISABLED:
  1875. // we should use password state for |ime-mode: disabled;|.
  1876. aState->mEnabled = IMEState::PASSWORD;
  1877. break;
  1878. case NS_STYLE_IME_MODE_ACTIVE:
  1879. aState->mOpen = IMEState::OPEN;
  1880. break;
  1881. case NS_STYLE_IME_MODE_INACTIVE:
  1882. aState->mOpen = IMEState::CLOSED;
  1883. break;
  1884. }
  1885. return NS_OK;
  1886. }
  1887. NS_IMETHODIMP
  1888. EditorBase::GetComposing(bool* aResult)
  1889. {
  1890. NS_ENSURE_ARG_POINTER(aResult);
  1891. *aResult = IsIMEComposing();
  1892. return NS_OK;
  1893. }
  1894. NS_IMETHODIMP
  1895. EditorBase::GetRootElement(nsIDOMElement** aRootElement)
  1896. {
  1897. NS_ENSURE_ARG_POINTER(aRootElement);
  1898. NS_ENSURE_TRUE(mRootElement, NS_ERROR_NOT_AVAILABLE);
  1899. nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(mRootElement);
  1900. rootElement.forget(aRootElement);
  1901. return NS_OK;
  1902. }
  1903. /**
  1904. * All editor operations which alter the doc should be prefaced
  1905. * with a call to StartOperation, naming the action and direction.
  1906. */
  1907. NS_IMETHODIMP
  1908. EditorBase::StartOperation(EditAction opID,
  1909. nsIEditor::EDirection aDirection)
  1910. {
  1911. mAction = opID;
  1912. mDirection = aDirection;
  1913. return NS_OK;
  1914. }
  1915. /**
  1916. * All editor operations which alter the doc should be followed
  1917. * with a call to EndOperation.
  1918. */
  1919. NS_IMETHODIMP
  1920. EditorBase::EndOperation()
  1921. {
  1922. mAction = EditAction::none;
  1923. mDirection = eNone;
  1924. return NS_OK;
  1925. }
  1926. NS_IMETHODIMP
  1927. EditorBase::CloneAttribute(const nsAString& aAttribute,
  1928. nsIDOMNode* aDestNode,
  1929. nsIDOMNode* aSourceNode)
  1930. {
  1931. NS_ENSURE_TRUE(aDestNode && aSourceNode, NS_ERROR_NULL_POINTER);
  1932. if (NS_WARN_IF(aAttribute.IsEmpty())) {
  1933. return NS_ERROR_FAILURE;
  1934. }
  1935. nsCOMPtr<Element> destElement = do_QueryInterface(aDestNode);
  1936. nsCOMPtr<Element> sourceElement = do_QueryInterface(aSourceNode);
  1937. NS_ENSURE_TRUE(destElement && sourceElement, NS_ERROR_NO_INTERFACE);
  1938. nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
  1939. return CloneAttribute(attribute, destElement, sourceElement);
  1940. }
  1941. nsresult
  1942. EditorBase::CloneAttribute(nsIAtom* aAttribute,
  1943. Element* aDestElement,
  1944. Element* aSourceElement)
  1945. {
  1946. nsAutoString attrValue;
  1947. if (aSourceElement->GetAttr(kNameSpaceID_None, aAttribute, attrValue)) {
  1948. return SetAttribute(aDestElement, aAttribute, attrValue);
  1949. }
  1950. return RemoveAttribute(aDestElement, aAttribute);
  1951. }
  1952. /**
  1953. * @param aDest Must be a DOM element.
  1954. * @param aSource Must be a DOM element.
  1955. */
  1956. NS_IMETHODIMP
  1957. EditorBase::CloneAttributes(nsIDOMNode* aDest,
  1958. nsIDOMNode* aSource)
  1959. {
  1960. NS_ENSURE_TRUE(aDest && aSource, NS_ERROR_NULL_POINTER);
  1961. nsCOMPtr<Element> dest = do_QueryInterface(aDest);
  1962. nsCOMPtr<Element> source = do_QueryInterface(aSource);
  1963. NS_ENSURE_TRUE(dest && source, NS_ERROR_NO_INTERFACE);
  1964. CloneAttributes(dest, source);
  1965. return NS_OK;
  1966. }
  1967. void
  1968. EditorBase::CloneAttributes(Element* aDest,
  1969. Element* aSource)
  1970. {
  1971. MOZ_ASSERT(aDest && aSource);
  1972. AutoEditBatch beginBatching(this);
  1973. // Use transaction system for undo only if destination is already in the
  1974. // document
  1975. NS_ENSURE_TRUE(GetRoot(), );
  1976. bool destInBody = GetRoot()->Contains(aDest);
  1977. // Clear existing attributes
  1978. RefPtr<nsDOMAttributeMap> destAttributes = aDest->Attributes();
  1979. while (RefPtr<Attr> attr = destAttributes->Item(0)) {
  1980. if (destInBody) {
  1981. RemoveAttribute(aDest, attr->NodeInfo()->NameAtom());
  1982. } else {
  1983. aDest->UnsetAttr(kNameSpaceID_None, attr->NodeInfo()->NameAtom(), true);
  1984. }
  1985. }
  1986. // Set just the attributes that the source element has
  1987. RefPtr<nsDOMAttributeMap> sourceAttributes = aSource->Attributes();
  1988. uint32_t sourceCount = sourceAttributes->Length();
  1989. for (uint32_t i = 0; i < sourceCount; i++) {
  1990. RefPtr<Attr> attr = sourceAttributes->Item(i);
  1991. nsAutoString value;
  1992. attr->GetValue(value);
  1993. if (destInBody) {
  1994. SetAttributeOrEquivalent(aDest, attr->NodeInfo()->NameAtom(), value,
  1995. false);
  1996. } else {
  1997. // The element is not inserted in the document yet, we don't want to put
  1998. // a transaction on the UndoStack
  1999. SetAttributeOrEquivalent(aDest, attr->NodeInfo()->NameAtom(), value,
  2000. true);
  2001. }
  2002. }
  2003. }
  2004. NS_IMETHODIMP
  2005. EditorBase::ScrollSelectionIntoView(bool aScrollToAnchor)
  2006. {
  2007. nsCOMPtr<nsISelectionController> selectionController =
  2008. GetSelectionController();
  2009. if (!selectionController) {
  2010. return NS_OK;
  2011. }
  2012. int16_t region = nsISelectionController::SELECTION_FOCUS_REGION;
  2013. if (aScrollToAnchor) {
  2014. region = nsISelectionController::SELECTION_ANCHOR_REGION;
  2015. }
  2016. selectionController->ScrollSelectionIntoView(
  2017. nsISelectionController::SELECTION_NORMAL,
  2018. region,
  2019. nsISelectionController::SCROLL_OVERFLOW_HIDDEN);
  2020. return NS_OK;
  2021. }
  2022. void
  2023. EditorBase::FindBetterInsertionPoint(nsCOMPtr<nsIDOMNode>& aNode,
  2024. int32_t& aOffset)
  2025. {
  2026. nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
  2027. FindBetterInsertionPoint(node, aOffset);
  2028. aNode = do_QueryInterface(node);
  2029. }
  2030. void
  2031. EditorBase::FindBetterInsertionPoint(nsCOMPtr<nsINode>& aNode,
  2032. int32_t& aOffset)
  2033. {
  2034. if (aNode->IsNodeOfType(nsINode::eTEXT)) {
  2035. // There is no "better" insertion point.
  2036. return;
  2037. }
  2038. if (!IsPlaintextEditor()) {
  2039. // We cannot find "better" insertion point in HTML editor.
  2040. // WARNING: When you add some code to find better node in HTML editor,
  2041. // you need to call this before calling InsertTextImpl() in
  2042. // HTMLEditRules.
  2043. return;
  2044. }
  2045. nsCOMPtr<nsINode> node = aNode;
  2046. int32_t offset = aOffset;
  2047. nsCOMPtr<nsINode> root = GetRoot();
  2048. if (aNode == root) {
  2049. // In some cases, aNode is the anonymous DIV, and offset is 0. To avoid
  2050. // injecting unneeded text nodes, we first look to see if we have one
  2051. // available. In that case, we'll just adjust node and offset accordingly.
  2052. if (!offset && node->HasChildren() &&
  2053. node->GetFirstChild()->IsNodeOfType(nsINode::eTEXT)) {
  2054. aNode = node->GetFirstChild();
  2055. aOffset = 0;
  2056. return;
  2057. }
  2058. // In some other cases, aNode is the anonymous DIV, and offset points to the
  2059. // terminating mozBR. In that case, we'll adjust aInOutNode and
  2060. // aInOutOffset to the preceding text node, if any.
  2061. if (offset > 0 && node->GetChildAt(offset - 1) &&
  2062. node->GetChildAt(offset - 1)->IsNodeOfType(nsINode::eTEXT)) {
  2063. NS_ENSURE_TRUE_VOID(node->Length() <= INT32_MAX);
  2064. aNode = node->GetChildAt(offset - 1);
  2065. aOffset = static_cast<int32_t>(aNode->Length());
  2066. return;
  2067. }
  2068. }
  2069. // Sometimes, aNode is the mozBR element itself. In that case, we'll adjust
  2070. // the insertion point to the previous text node, if one exists, or to the
  2071. // parent anonymous DIV.
  2072. if (TextEditUtils::IsMozBR(node) && !offset) {
  2073. if (node->GetPreviousSibling() &&
  2074. node->GetPreviousSibling()->IsNodeOfType(nsINode::eTEXT)) {
  2075. NS_ENSURE_TRUE_VOID(node->Length() <= INT32_MAX);
  2076. aNode = node->GetPreviousSibling();
  2077. aOffset = static_cast<int32_t>(aNode->Length());
  2078. return;
  2079. }
  2080. if (node->GetParentNode() && node->GetParentNode() == root) {
  2081. aNode = node->GetParentNode();
  2082. aOffset = 0;
  2083. return;
  2084. }
  2085. }
  2086. }
  2087. nsresult
  2088. EditorBase::InsertTextImpl(const nsAString& aStringToInsert,
  2089. nsCOMPtr<nsINode>* aInOutNode,
  2090. int32_t* aInOutOffset,
  2091. nsIDocument* aDoc)
  2092. {
  2093. // NOTE: caller *must* have already used AutoTransactionsConserveSelection
  2094. // stack-based class to turn off txn selection updating. Caller also turned
  2095. // on rules sniffing if desired.
  2096. NS_ENSURE_TRUE(aInOutNode && *aInOutNode && aInOutOffset && aDoc,
  2097. NS_ERROR_NULL_POINTER);
  2098. if (!ShouldHandleIMEComposition() && aStringToInsert.IsEmpty()) {
  2099. return NS_OK;
  2100. }
  2101. // This method doesn't support over INT32_MAX length text since aInOutOffset
  2102. // is int32_t*.
  2103. CheckedInt<int32_t> lengthToInsert(aStringToInsert.Length());
  2104. NS_ENSURE_TRUE(lengthToInsert.isValid(), NS_ERROR_INVALID_ARG);
  2105. nsCOMPtr<nsINode> node = *aInOutNode;
  2106. int32_t offset = *aInOutOffset;
  2107. // In some cases, the node may be the anonymous div elemnt or a mozBR
  2108. // element. Let's try to look for better insertion point in the nearest
  2109. // text node if there is.
  2110. FindBetterInsertionPoint(node, offset);
  2111. if (ShouldHandleIMEComposition()) {
  2112. CheckedInt<int32_t> newOffset;
  2113. if (!node->IsNodeOfType(nsINode::eTEXT)) {
  2114. // create a text node
  2115. RefPtr<nsTextNode> newNode = aDoc->CreateTextNode(EmptyString());
  2116. // then we insert it into the dom tree
  2117. nsresult rv = InsertNode(*newNode, *node, offset);
  2118. NS_ENSURE_SUCCESS(rv, rv);
  2119. node = newNode;
  2120. offset = 0;
  2121. newOffset = lengthToInsert;
  2122. } else {
  2123. newOffset = lengthToInsert + offset;
  2124. NS_ENSURE_TRUE(newOffset.isValid(), NS_ERROR_FAILURE);
  2125. }
  2126. nsresult rv =
  2127. InsertTextIntoTextNodeImpl(aStringToInsert, *node->GetAsText(), offset);
  2128. NS_ENSURE_SUCCESS(rv, rv);
  2129. offset = newOffset.value();
  2130. } else {
  2131. if (node->IsNodeOfType(nsINode::eTEXT)) {
  2132. CheckedInt<int32_t> newOffset = lengthToInsert + offset;
  2133. NS_ENSURE_TRUE(newOffset.isValid(), NS_ERROR_FAILURE);
  2134. // we are inserting text into an existing text node.
  2135. nsresult rv =
  2136. InsertTextIntoTextNodeImpl(aStringToInsert, *node->GetAsText(), offset);
  2137. NS_ENSURE_SUCCESS(rv, rv);
  2138. offset = newOffset.value();
  2139. } else {
  2140. // we are inserting text into a non-text node. first we have to create a
  2141. // textnode (this also populates it with the text)
  2142. RefPtr<nsTextNode> newNode = aDoc->CreateTextNode(aStringToInsert);
  2143. // then we insert it into the dom tree
  2144. nsresult rv = InsertNode(*newNode, *node, offset);
  2145. NS_ENSURE_SUCCESS(rv, rv);
  2146. node = newNode;
  2147. offset = lengthToInsert.value();
  2148. }
  2149. }
  2150. *aInOutNode = node;
  2151. *aInOutOffset = offset;
  2152. return NS_OK;
  2153. }
  2154. nsresult
  2155. EditorBase::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
  2156. Text& aTextNode,
  2157. int32_t aOffset,
  2158. bool aSuppressIME)
  2159. {
  2160. RefPtr<EditTransactionBase> transaction;
  2161. bool isIMETransaction = false;
  2162. RefPtr<Text> insertedTextNode = &aTextNode;
  2163. int32_t insertedOffset = aOffset;
  2164. // aSuppressIME is used when editor must insert text, yet this text is not
  2165. // part of the current IME operation. Example: adjusting whitespace around an
  2166. // IME insertion.
  2167. if (ShouldHandleIMEComposition() && !aSuppressIME) {
  2168. if (!mIMETextNode) {
  2169. mIMETextNode = &aTextNode;
  2170. mIMETextOffset = aOffset;
  2171. }
  2172. // Modify mPhonetic with raw text input clauses.
  2173. const TextRangeArray* ranges = mComposition->GetRanges();
  2174. for (uint32_t i = 0; i < (ranges ? ranges->Length() : 0); ++i) {
  2175. const TextRange& textRange = ranges->ElementAt(i);
  2176. if (!textRange.Length() ||
  2177. textRange.mRangeType != TextRangeType::eRawClause) {
  2178. continue;
  2179. }
  2180. if (!mPhonetic) {
  2181. mPhonetic = new nsString();
  2182. }
  2183. nsAutoString stringToInsert(aStringToInsert);
  2184. stringToInsert.Mid(*mPhonetic,
  2185. textRange.mStartOffset, textRange.Length());
  2186. }
  2187. transaction = CreateTxnForComposition(aStringToInsert);
  2188. isIMETransaction = true;
  2189. // All characters of the composition string will be replaced with
  2190. // aStringToInsert. So, we need to emulate to remove the composition
  2191. // string.
  2192. insertedTextNode = mIMETextNode;
  2193. insertedOffset = mIMETextOffset;
  2194. mIMETextLength = aStringToInsert.Length();
  2195. } else {
  2196. transaction = CreateTxnForInsertText(aStringToInsert, aTextNode, aOffset);
  2197. }
  2198. // Let listeners know what's up
  2199. {
  2200. AutoActionListenerArray listeners(mActionListeners);
  2201. for (auto& listener : listeners) {
  2202. listener->WillInsertText(
  2203. static_cast<nsIDOMCharacterData*>(insertedTextNode->AsDOMNode()),
  2204. insertedOffset, aStringToInsert);
  2205. }
  2206. }
  2207. // XXX We may not need these view batches anymore. This is handled at a
  2208. // higher level now I believe.
  2209. BeginUpdateViewBatch();
  2210. nsresult rv = DoTransaction(transaction);
  2211. EndUpdateViewBatch();
  2212. // let listeners know what happened
  2213. {
  2214. AutoActionListenerArray listeners(mActionListeners);
  2215. for (auto& listener : listeners) {
  2216. listener->DidInsertText(
  2217. static_cast<nsIDOMCharacterData*>(insertedTextNode->AsDOMNode()),
  2218. insertedOffset, aStringToInsert, rv);
  2219. }
  2220. }
  2221. // Added some cruft here for bug 43366. Layout was crashing because we left
  2222. // an empty text node lying around in the document. So I delete empty text
  2223. // nodes caused by IME. I have to mark the IME transaction as "fixed", which
  2224. // means that furure IME txns won't merge with it. This is because we don't
  2225. // want future IME txns trying to put their text into a node that is no
  2226. // longer in the document. This does not break undo/redo, because all these
  2227. // txns are wrapped in a parent PlaceHolder txn, and placeholder txns are
  2228. // already savvy to having multiple ime txns inside them.
  2229. // Delete empty IME text node if there is one
  2230. if (isIMETransaction && mIMETextNode) {
  2231. uint32_t len = mIMETextNode->Length();
  2232. if (!len) {
  2233. DeleteNode(mIMETextNode);
  2234. mIMETextNode = nullptr;
  2235. static_cast<CompositionTransaction*>(transaction.get())->MarkFixed();
  2236. }
  2237. }
  2238. return rv;
  2239. }
  2240. nsresult
  2241. EditorBase::SelectEntireDocument(Selection* aSelection)
  2242. {
  2243. if (!aSelection) {
  2244. return NS_ERROR_NULL_POINTER;
  2245. }
  2246. nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(GetRoot());
  2247. if (!rootElement) {
  2248. return NS_ERROR_NOT_INITIALIZED;
  2249. }
  2250. return aSelection->SelectAllChildren(rootElement);
  2251. }
  2252. nsINode*
  2253. EditorBase::GetFirstEditableNode(nsINode* aRoot)
  2254. {
  2255. MOZ_ASSERT(aRoot);
  2256. nsIContent* node = GetLeftmostChild(aRoot);
  2257. if (node && !IsEditable(node)) {
  2258. node = GetNextNode(node, /* aEditableNode = */ true);
  2259. }
  2260. return (node != aRoot) ? node : nullptr;
  2261. }
  2262. NS_IMETHODIMP
  2263. EditorBase::NotifyDocumentListeners(
  2264. TDocumentListenerNotification aNotificationType)
  2265. {
  2266. if (!mDocStateListeners.Length()) {
  2267. // Maybe there just aren't any.
  2268. return NS_OK;
  2269. }
  2270. AutoDocumentStateListenerArray listeners(mDocStateListeners);
  2271. nsresult rv = NS_OK;
  2272. switch (aNotificationType) {
  2273. case eDocumentCreated:
  2274. for (auto& listener : listeners) {
  2275. rv = listener->NotifyDocumentCreated();
  2276. if (NS_FAILED(rv)) {
  2277. break;
  2278. }
  2279. }
  2280. break;
  2281. case eDocumentToBeDestroyed:
  2282. for (auto& listener : listeners) {
  2283. rv = listener->NotifyDocumentWillBeDestroyed();
  2284. if (NS_FAILED(rv)) {
  2285. break;
  2286. }
  2287. }
  2288. break;
  2289. case eDocumentStateChanged: {
  2290. bool docIsDirty;
  2291. rv = GetDocumentModified(&docIsDirty);
  2292. NS_ENSURE_SUCCESS(rv, rv);
  2293. if (static_cast<int8_t>(docIsDirty) == mDocDirtyState) {
  2294. return NS_OK;
  2295. }
  2296. mDocDirtyState = docIsDirty;
  2297. for (auto& listener : listeners) {
  2298. rv = listener->NotifyDocumentStateChanged(mDocDirtyState);
  2299. if (NS_FAILED(rv)) {
  2300. break;
  2301. }
  2302. }
  2303. break;
  2304. }
  2305. default:
  2306. NS_NOTREACHED("Unknown notification");
  2307. }
  2308. return rv;
  2309. }
  2310. already_AddRefed<InsertTextTransaction>
  2311. EditorBase::CreateTxnForInsertText(const nsAString& aStringToInsert,
  2312. Text& aTextNode,
  2313. int32_t aOffset)
  2314. {
  2315. RefPtr<InsertTextTransaction> transaction =
  2316. new InsertTextTransaction(aTextNode, aOffset, aStringToInsert, *this,
  2317. &mRangeUpdater);
  2318. return transaction.forget();
  2319. }
  2320. nsresult
  2321. EditorBase::DeleteText(nsGenericDOMDataNode& aCharData,
  2322. uint32_t aOffset,
  2323. uint32_t aLength)
  2324. {
  2325. RefPtr<DeleteTextTransaction> transaction =
  2326. CreateTxnForDeleteText(aCharData, aOffset, aLength);
  2327. NS_ENSURE_STATE(transaction);
  2328. AutoRules beginRulesSniffing(this, EditAction::deleteText,
  2329. nsIEditor::ePrevious);
  2330. // Let listeners know what's up
  2331. {
  2332. AutoActionListenerArray listeners(mActionListeners);
  2333. for (auto& listener : listeners) {
  2334. listener->WillDeleteText(
  2335. static_cast<nsIDOMCharacterData*>(GetAsDOMNode(&aCharData)), aOffset,
  2336. aLength);
  2337. }
  2338. }
  2339. nsresult rv = DoTransaction(transaction);
  2340. // Let listeners know what happened
  2341. {
  2342. AutoActionListenerArray listeners(mActionListeners);
  2343. for (auto& listener : listeners) {
  2344. listener->DidDeleteText(
  2345. static_cast<nsIDOMCharacterData*>(GetAsDOMNode(&aCharData)), aOffset,
  2346. aLength, rv);
  2347. }
  2348. }
  2349. return rv;
  2350. }
  2351. already_AddRefed<DeleteTextTransaction>
  2352. EditorBase::CreateTxnForDeleteText(nsGenericDOMDataNode& aCharData,
  2353. uint32_t aOffset,
  2354. uint32_t aLength)
  2355. {
  2356. RefPtr<DeleteTextTransaction> transaction =
  2357. new DeleteTextTransaction(*this, aCharData, aOffset, aLength,
  2358. &mRangeUpdater);
  2359. nsresult rv = transaction->Init();
  2360. NS_ENSURE_SUCCESS(rv, nullptr);
  2361. return transaction.forget();
  2362. }
  2363. already_AddRefed<SplitNodeTransaction>
  2364. EditorBase::CreateTxnForSplitNode(nsIContent& aNode,
  2365. uint32_t aOffset)
  2366. {
  2367. RefPtr<SplitNodeTransaction> transaction =
  2368. new SplitNodeTransaction(*this, aNode, aOffset);
  2369. return transaction.forget();
  2370. }
  2371. already_AddRefed<JoinNodeTransaction>
  2372. EditorBase::CreateTxnForJoinNode(nsINode& aLeftNode,
  2373. nsINode& aRightNode)
  2374. {
  2375. RefPtr<JoinNodeTransaction> transaction =
  2376. new JoinNodeTransaction(*this, aLeftNode, aRightNode);
  2377. NS_ENSURE_SUCCESS(transaction->CheckValidity(), nullptr);
  2378. return transaction.forget();
  2379. }
  2380. struct SavedRange final
  2381. {
  2382. RefPtr<Selection> mSelection;
  2383. nsCOMPtr<nsINode> mStartNode;
  2384. nsCOMPtr<nsINode> mEndNode;
  2385. int32_t mStartOffset;
  2386. int32_t mEndOffset;
  2387. };
  2388. nsresult
  2389. EditorBase::SplitNodeImpl(nsIContent& aExistingRightNode,
  2390. int32_t aOffset,
  2391. nsIContent& aNewLeftNode)
  2392. {
  2393. // Remember all selection points.
  2394. AutoTArray<SavedRange, 10> savedRanges;
  2395. for (size_t i = 0; i < kPresentSelectionTypeCount; ++i) {
  2396. SelectionType selectionType(ToSelectionType(1 << i));
  2397. SavedRange range;
  2398. range.mSelection = GetSelection(selectionType);
  2399. if (selectionType == SelectionType::eNormal) {
  2400. NS_ENSURE_TRUE(range.mSelection, NS_ERROR_NULL_POINTER);
  2401. } else if (!range.mSelection) {
  2402. // For non-normal selections, skip over the non-existing ones.
  2403. continue;
  2404. }
  2405. for (uint32_t j = 0; j < range.mSelection->RangeCount(); ++j) {
  2406. RefPtr<nsRange> r = range.mSelection->GetRangeAt(j);
  2407. MOZ_ASSERT(r->IsPositioned());
  2408. range.mStartNode = r->GetStartParent();
  2409. range.mStartOffset = r->StartOffset();
  2410. range.mEndNode = r->GetEndParent();
  2411. range.mEndOffset = r->EndOffset();
  2412. savedRanges.AppendElement(range);
  2413. }
  2414. }
  2415. nsCOMPtr<nsINode> parent = aExistingRightNode.GetParentNode();
  2416. NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
  2417. ErrorResult rv;
  2418. nsCOMPtr<nsINode> refNode = &aExistingRightNode;
  2419. parent->InsertBefore(aNewLeftNode, refNode, rv);
  2420. NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult());
  2421. // Split the children between the two nodes. At this point,
  2422. // aExistingRightNode has all the children. Move all the children whose
  2423. // index is < aOffset to aNewLeftNode.
  2424. if (aOffset < 0) {
  2425. // This means move no children
  2426. return NS_OK;
  2427. }
  2428. // If it's a text node, just shuffle around some text
  2429. if (aExistingRightNode.GetAsText() && aNewLeftNode.GetAsText()) {
  2430. // Fix right node
  2431. nsAutoString leftText;
  2432. aExistingRightNode.GetAsText()->SubstringData(0, aOffset, leftText);
  2433. aExistingRightNode.GetAsText()->DeleteData(0, aOffset);
  2434. // Fix left node
  2435. aNewLeftNode.GetAsText()->SetData(leftText);
  2436. } else {
  2437. // Otherwise it's an interior node, so shuffle around the children. Go
  2438. // through list backwards so deletes don't interfere with the iteration.
  2439. nsCOMPtr<nsINodeList> childNodes = aExistingRightNode.ChildNodes();
  2440. for (int32_t i = aOffset - 1; i >= 0; i--) {
  2441. nsCOMPtr<nsIContent> childNode = childNodes->Item(i);
  2442. if (childNode) {
  2443. aExistingRightNode.RemoveChild(*childNode, rv);
  2444. if (!rv.Failed()) {
  2445. nsCOMPtr<nsIContent> firstChild = aNewLeftNode.GetFirstChild();
  2446. aNewLeftNode.InsertBefore(*childNode, firstChild, rv);
  2447. }
  2448. }
  2449. if (rv.Failed()) {
  2450. break;
  2451. }
  2452. }
  2453. }
  2454. // Handle selection
  2455. nsCOMPtr<nsIPresShell> ps = GetPresShell();
  2456. if (ps) {
  2457. ps->FlushPendingNotifications(Flush_Frames);
  2458. }
  2459. bool shouldSetSelection = GetShouldTxnSetSelection();
  2460. RefPtr<Selection> previousSelection;
  2461. for (size_t i = 0; i < savedRanges.Length(); ++i) {
  2462. // Adjust the selection if needed.
  2463. SavedRange& range = savedRanges[i];
  2464. // If we have not seen the selection yet, clear all of its ranges.
  2465. if (range.mSelection != previousSelection) {
  2466. nsresult rv = range.mSelection->RemoveAllRanges();
  2467. NS_ENSURE_SUCCESS(rv, rv);
  2468. previousSelection = range.mSelection;
  2469. }
  2470. if (shouldSetSelection &&
  2471. range.mSelection->Type() == SelectionType::eNormal) {
  2472. // If the editor should adjust the selection, don't bother restoring
  2473. // the ranges for the normal selection here.
  2474. continue;
  2475. }
  2476. // Split the selection into existing node and new node.
  2477. if (range.mStartNode == &aExistingRightNode) {
  2478. if (range.mStartOffset < aOffset) {
  2479. range.mStartNode = &aNewLeftNode;
  2480. } else {
  2481. range.mStartOffset -= aOffset;
  2482. }
  2483. }
  2484. if (range.mEndNode == &aExistingRightNode) {
  2485. if (range.mEndOffset < aOffset) {
  2486. range.mEndNode = &aNewLeftNode;
  2487. } else {
  2488. range.mEndOffset -= aOffset;
  2489. }
  2490. }
  2491. RefPtr<nsRange> newRange;
  2492. nsresult rv = nsRange::CreateRange(range.mStartNode, range.mStartOffset,
  2493. range.mEndNode, range.mEndOffset,
  2494. getter_AddRefs(newRange));
  2495. NS_ENSURE_SUCCESS(rv, rv);
  2496. rv = range.mSelection->AddRange(newRange);
  2497. NS_ENSURE_SUCCESS(rv, rv);
  2498. }
  2499. if (shouldSetSelection) {
  2500. // Editor wants us to set selection at split point.
  2501. RefPtr<Selection> selection = GetSelection();
  2502. NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
  2503. selection->Collapse(&aNewLeftNode, aOffset);
  2504. }
  2505. return NS_OK;
  2506. }
  2507. nsresult
  2508. EditorBase::JoinNodesImpl(nsINode* aNodeToKeep,
  2509. nsINode* aNodeToJoin,
  2510. nsINode* aParent)
  2511. {
  2512. MOZ_ASSERT(aNodeToKeep);
  2513. MOZ_ASSERT(aNodeToJoin);
  2514. MOZ_ASSERT(aParent);
  2515. uint32_t firstNodeLength = aNodeToJoin->Length();
  2516. int32_t joinOffset;
  2517. GetNodeLocation(aNodeToJoin, &joinOffset);
  2518. int32_t keepOffset;
  2519. nsINode* parent = GetNodeLocation(aNodeToKeep, &keepOffset);
  2520. // Remember all selection points.
  2521. AutoTArray<SavedRange, 10> savedRanges;
  2522. for (size_t i = 0; i < kPresentSelectionTypeCount; ++i) {
  2523. SelectionType selectionType(ToSelectionType(1 << i));
  2524. SavedRange range;
  2525. range.mSelection = GetSelection(selectionType);
  2526. if (selectionType == SelectionType::eNormal) {
  2527. NS_ENSURE_TRUE(range.mSelection, NS_ERROR_NULL_POINTER);
  2528. } else if (!range.mSelection) {
  2529. // For non-normal selections, skip over the non-existing ones.
  2530. continue;
  2531. }
  2532. for (uint32_t j = 0; j < range.mSelection->RangeCount(); ++j) {
  2533. RefPtr<nsRange> r = range.mSelection->GetRangeAt(j);
  2534. MOZ_ASSERT(r->IsPositioned());
  2535. range.mStartNode = r->GetStartParent();
  2536. range.mStartOffset = r->StartOffset();
  2537. range.mEndNode = r->GetEndParent();
  2538. range.mEndOffset = r->EndOffset();
  2539. // If selection endpoint is between the nodes, remember it as being
  2540. // in the one that is going away instead. This simplifies later selection
  2541. // adjustment logic at end of this method.
  2542. if (range.mStartNode) {
  2543. if (range.mStartNode == parent &&
  2544. joinOffset < range.mStartOffset &&
  2545. range.mStartOffset <= keepOffset) {
  2546. range.mStartNode = aNodeToJoin;
  2547. range.mStartOffset = firstNodeLength;
  2548. }
  2549. if (range.mEndNode == parent &&
  2550. joinOffset < range.mEndOffset &&
  2551. range.mEndOffset <= keepOffset) {
  2552. range.mEndNode = aNodeToJoin;
  2553. range.mEndOffset = firstNodeLength;
  2554. }
  2555. }
  2556. savedRanges.AppendElement(range);
  2557. }
  2558. }
  2559. // OK, ready to do join now.
  2560. // If it's a text node, just shuffle around some text.
  2561. nsCOMPtr<nsIDOMCharacterData> keepNodeAsText( do_QueryInterface(aNodeToKeep) );
  2562. nsCOMPtr<nsIDOMCharacterData> joinNodeAsText( do_QueryInterface(aNodeToJoin) );
  2563. if (keepNodeAsText && joinNodeAsText) {
  2564. nsAutoString rightText;
  2565. nsAutoString leftText;
  2566. keepNodeAsText->GetData(rightText);
  2567. joinNodeAsText->GetData(leftText);
  2568. leftText += rightText;
  2569. keepNodeAsText->SetData(leftText);
  2570. } else {
  2571. // Otherwise it's an interior node, so shuffle around the children.
  2572. nsCOMPtr<nsINodeList> childNodes = aNodeToJoin->ChildNodes();
  2573. MOZ_ASSERT(childNodes);
  2574. // Remember the first child in aNodeToKeep, we'll insert all the children of aNodeToJoin in front of it
  2575. // GetFirstChild returns nullptr firstNode if aNodeToKeep has no children, that's OK.
  2576. nsCOMPtr<nsIContent> firstNode = aNodeToKeep->GetFirstChild();
  2577. // Have to go through the list backwards to keep deletes from interfering with iteration.
  2578. for (uint32_t i = childNodes->Length(); i; --i) {
  2579. nsCOMPtr<nsIContent> childNode = childNodes->Item(i - 1);
  2580. if (childNode) {
  2581. // prepend children of aNodeToJoin
  2582. ErrorResult err;
  2583. aNodeToKeep->InsertBefore(*childNode, firstNode, err);
  2584. NS_ENSURE_TRUE(!err.Failed(), err.StealNSResult());
  2585. firstNode = childNode.forget();
  2586. }
  2587. }
  2588. }
  2589. // Delete the extra node.
  2590. ErrorResult err;
  2591. aParent->RemoveChild(*aNodeToJoin, err);
  2592. bool shouldSetSelection = GetShouldTxnSetSelection();
  2593. RefPtr<Selection> previousSelection;
  2594. for (size_t i = 0; i < savedRanges.Length(); ++i) {
  2595. // And adjust the selection if needed.
  2596. SavedRange& range = savedRanges[i];
  2597. // If we have not seen the selection yet, clear all of its ranges.
  2598. if (range.mSelection != previousSelection) {
  2599. nsresult rv = range.mSelection->RemoveAllRanges();
  2600. NS_ENSURE_SUCCESS(rv, rv);
  2601. previousSelection = range.mSelection;
  2602. }
  2603. if (shouldSetSelection &&
  2604. range.mSelection->Type() == SelectionType::eNormal) {
  2605. // If the editor should adjust the selection, don't bother restoring
  2606. // the ranges for the normal selection here.
  2607. continue;
  2608. }
  2609. // Check to see if we joined nodes where selection starts.
  2610. if (range.mStartNode == aNodeToJoin) {
  2611. range.mStartNode = aNodeToKeep;
  2612. } else if (range.mStartNode == aNodeToKeep) {
  2613. range.mStartOffset += firstNodeLength;
  2614. }
  2615. // Check to see if we joined nodes where selection ends.
  2616. if (range.mEndNode == aNodeToJoin) {
  2617. range.mEndNode = aNodeToKeep;
  2618. } else if (range.mEndNode == aNodeToKeep) {
  2619. range.mEndOffset += firstNodeLength;
  2620. }
  2621. RefPtr<nsRange> newRange;
  2622. nsresult rv = nsRange::CreateRange(range.mStartNode, range.mStartOffset,
  2623. range.mEndNode, range.mEndOffset,
  2624. getter_AddRefs(newRange));
  2625. NS_ENSURE_SUCCESS(rv, rv);
  2626. rv = range.mSelection->AddRange(newRange);
  2627. NS_ENSURE_SUCCESS(rv, rv);
  2628. }
  2629. if (shouldSetSelection) {
  2630. // Editor wants us to set selection at join point.
  2631. RefPtr<Selection> selection = GetSelection();
  2632. NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
  2633. selection->Collapse(aNodeToKeep, AssertedCast<int32_t>(firstNodeLength));
  2634. }
  2635. return err.StealNSResult();
  2636. }
  2637. int32_t
  2638. EditorBase::GetChildOffset(nsIDOMNode* aChild,
  2639. nsIDOMNode* aParent)
  2640. {
  2641. MOZ_ASSERT(aChild && aParent);
  2642. nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
  2643. nsCOMPtr<nsINode> child = do_QueryInterface(aChild);
  2644. MOZ_ASSERT(parent && child);
  2645. int32_t idx = parent->IndexOf(child);
  2646. MOZ_ASSERT(idx != -1);
  2647. return idx;
  2648. }
  2649. // static
  2650. already_AddRefed<nsIDOMNode>
  2651. EditorBase::GetNodeLocation(nsIDOMNode* aChild,
  2652. int32_t* outOffset)
  2653. {
  2654. MOZ_ASSERT(aChild && outOffset);
  2655. NS_ENSURE_TRUE(aChild && outOffset, nullptr);
  2656. *outOffset = -1;
  2657. nsCOMPtr<nsIDOMNode> parent;
  2658. MOZ_ALWAYS_SUCCEEDS(aChild->GetParentNode(getter_AddRefs(parent)));
  2659. if (parent) {
  2660. *outOffset = GetChildOffset(aChild, parent);
  2661. }
  2662. return parent.forget();
  2663. }
  2664. nsINode*
  2665. EditorBase::GetNodeLocation(nsINode* aChild,
  2666. int32_t* aOffset)
  2667. {
  2668. MOZ_ASSERT(aChild);
  2669. MOZ_ASSERT(aOffset);
  2670. nsINode* parent = aChild->GetParentNode();
  2671. if (parent) {
  2672. *aOffset = parent->IndexOf(aChild);
  2673. MOZ_ASSERT(*aOffset != -1);
  2674. } else {
  2675. *aOffset = -1;
  2676. }
  2677. return parent;
  2678. }
  2679. /**
  2680. * Returns the number of things inside aNode. If aNode is text, returns number
  2681. * of characters. If not, returns number of children nodes.
  2682. */
  2683. nsresult
  2684. EditorBase::GetLengthOfDOMNode(nsIDOMNode* aNode,
  2685. uint32_t& aCount)
  2686. {
  2687. aCount = 0;
  2688. nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
  2689. NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
  2690. aCount = node->Length();
  2691. return NS_OK;
  2692. }
  2693. nsIContent*
  2694. EditorBase::GetPriorNode(nsINode* aParentNode,
  2695. int32_t aOffset,
  2696. bool aEditableNode,
  2697. bool aNoBlockCrossing)
  2698. {
  2699. MOZ_ASSERT(aParentNode);
  2700. // If we are at the beginning of the node, or it is a text node, then just
  2701. // look before it.
  2702. if (!aOffset || aParentNode->NodeType() == nsIDOMNode::TEXT_NODE) {
  2703. if (aNoBlockCrossing && IsBlockNode(aParentNode)) {
  2704. // If we aren't allowed to cross blocks, don't look before this block.
  2705. return nullptr;
  2706. }
  2707. return GetPriorNode(aParentNode, aEditableNode, aNoBlockCrossing);
  2708. }
  2709. // else look before the child at 'aOffset'
  2710. if (nsIContent* child = aParentNode->GetChildAt(aOffset)) {
  2711. return GetPriorNode(child, aEditableNode, aNoBlockCrossing);
  2712. }
  2713. // unless there isn't one, in which case we are at the end of the node
  2714. // and want the deep-right child.
  2715. nsIContent* resultNode = GetRightmostChild(aParentNode, aNoBlockCrossing);
  2716. if (!resultNode || !aEditableNode || IsEditable(resultNode)) {
  2717. return resultNode;
  2718. }
  2719. // restart the search from the non-editable node we just found
  2720. return GetPriorNode(resultNode, aEditableNode, aNoBlockCrossing);
  2721. }
  2722. nsIContent*
  2723. EditorBase::GetNextNode(nsINode* aParentNode,
  2724. int32_t aOffset,
  2725. bool aEditableNode,
  2726. bool aNoBlockCrossing)
  2727. {
  2728. MOZ_ASSERT(aParentNode);
  2729. // if aParentNode is a text node, use its location instead
  2730. if (aParentNode->NodeType() == nsIDOMNode::TEXT_NODE) {
  2731. nsINode* parent = aParentNode->GetParentNode();
  2732. NS_ENSURE_TRUE(parent, nullptr);
  2733. aOffset = parent->IndexOf(aParentNode) + 1; // _after_ the text node
  2734. aParentNode = parent;
  2735. }
  2736. // look at the child at 'aOffset'
  2737. nsIContent* child = aParentNode->GetChildAt(aOffset);
  2738. if (child) {
  2739. if (aNoBlockCrossing && IsBlockNode(child)) {
  2740. return child;
  2741. }
  2742. nsIContent* resultNode = GetLeftmostChild(child, aNoBlockCrossing);
  2743. if (!resultNode) {
  2744. return child;
  2745. }
  2746. if (!IsDescendantOfEditorRoot(resultNode)) {
  2747. return nullptr;
  2748. }
  2749. if (!aEditableNode || IsEditable(resultNode)) {
  2750. return resultNode;
  2751. }
  2752. // restart the search from the non-editable node we just found
  2753. return GetNextNode(resultNode, aEditableNode, aNoBlockCrossing);
  2754. }
  2755. // unless there isn't one, in which case we are at the end of the node
  2756. // and want the next one.
  2757. if (aNoBlockCrossing && IsBlockNode(aParentNode)) {
  2758. // don't cross out of parent block
  2759. return nullptr;
  2760. }
  2761. return GetNextNode(aParentNode, aEditableNode, aNoBlockCrossing);
  2762. }
  2763. nsIContent*
  2764. EditorBase::GetPriorNode(nsINode* aCurrentNode,
  2765. bool aEditableNode,
  2766. bool aNoBlockCrossing /* = false */)
  2767. {
  2768. MOZ_ASSERT(aCurrentNode);
  2769. if (!IsDescendantOfEditorRoot(aCurrentNode)) {
  2770. return nullptr;
  2771. }
  2772. return FindNode(aCurrentNode, false, aEditableNode, aNoBlockCrossing);
  2773. }
  2774. nsIContent*
  2775. EditorBase::FindNextLeafNode(nsINode* aCurrentNode,
  2776. bool aGoForward,
  2777. bool bNoBlockCrossing)
  2778. {
  2779. // called only by GetPriorNode so we don't need to check params.
  2780. NS_PRECONDITION(IsDescendantOfEditorRoot(aCurrentNode) &&
  2781. !IsEditorRoot(aCurrentNode),
  2782. "Bogus arguments");
  2783. nsINode* cur = aCurrentNode;
  2784. for (;;) {
  2785. // if aCurrentNode has a sibling in the right direction, return
  2786. // that sibling's closest child (or itself if it has no children)
  2787. nsIContent* sibling =
  2788. aGoForward ? cur->GetNextSibling() : cur->GetPreviousSibling();
  2789. if (sibling) {
  2790. if (bNoBlockCrossing && IsBlockNode(sibling)) {
  2791. // don't look inside prevsib, since it is a block
  2792. return sibling;
  2793. }
  2794. nsIContent *leaf =
  2795. aGoForward ? GetLeftmostChild(sibling, bNoBlockCrossing) :
  2796. GetRightmostChild(sibling, bNoBlockCrossing);
  2797. if (!leaf) {
  2798. return sibling;
  2799. }
  2800. return leaf;
  2801. }
  2802. nsINode *parent = cur->GetParentNode();
  2803. if (!parent) {
  2804. return nullptr;
  2805. }
  2806. NS_ASSERTION(IsDescendantOfEditorRoot(parent),
  2807. "We started with a proper descendant of root, and should stop "
  2808. "if we ever hit the root, so we better have a descendant of "
  2809. "root now!");
  2810. if (IsEditorRoot(parent) ||
  2811. (bNoBlockCrossing && IsBlockNode(parent))) {
  2812. return nullptr;
  2813. }
  2814. cur = parent;
  2815. }
  2816. NS_NOTREACHED("What part of for(;;) do you not understand?");
  2817. return nullptr;
  2818. }
  2819. nsIContent*
  2820. EditorBase::GetNextNode(nsINode* aCurrentNode,
  2821. bool aEditableNode,
  2822. bool bNoBlockCrossing)
  2823. {
  2824. MOZ_ASSERT(aCurrentNode);
  2825. if (!IsDescendantOfEditorRoot(aCurrentNode)) {
  2826. return nullptr;
  2827. }
  2828. return FindNode(aCurrentNode, true, aEditableNode, bNoBlockCrossing);
  2829. }
  2830. nsIContent*
  2831. EditorBase::FindNode(nsINode* aCurrentNode,
  2832. bool aGoForward,
  2833. bool aEditableNode,
  2834. bool bNoBlockCrossing)
  2835. {
  2836. if (IsEditorRoot(aCurrentNode)) {
  2837. // Don't allow traversal above the root node! This helps
  2838. // prevent us from accidentally editing browser content
  2839. // when the editor is in a text widget.
  2840. return nullptr;
  2841. }
  2842. nsCOMPtr<nsIContent> candidate =
  2843. FindNextLeafNode(aCurrentNode, aGoForward, bNoBlockCrossing);
  2844. if (!candidate) {
  2845. return nullptr;
  2846. }
  2847. if (!aEditableNode || IsEditable(candidate)) {
  2848. return candidate;
  2849. }
  2850. return FindNode(candidate, aGoForward, aEditableNode, bNoBlockCrossing);
  2851. }
  2852. nsIContent*
  2853. EditorBase::GetRightmostChild(nsINode* aCurrentNode,
  2854. bool bNoBlockCrossing)
  2855. {
  2856. NS_ENSURE_TRUE(aCurrentNode, nullptr);
  2857. nsIContent *cur = aCurrentNode->GetLastChild();
  2858. if (!cur) {
  2859. return nullptr;
  2860. }
  2861. for (;;) {
  2862. if (bNoBlockCrossing && IsBlockNode(cur)) {
  2863. return cur;
  2864. }
  2865. nsIContent* next = cur->GetLastChild();
  2866. if (!next) {
  2867. return cur;
  2868. }
  2869. cur = next;
  2870. }
  2871. NS_NOTREACHED("What part of for(;;) do you not understand?");
  2872. return nullptr;
  2873. }
  2874. nsIContent*
  2875. EditorBase::GetLeftmostChild(nsINode* aCurrentNode,
  2876. bool bNoBlockCrossing)
  2877. {
  2878. NS_ENSURE_TRUE(aCurrentNode, nullptr);
  2879. nsIContent *cur = aCurrentNode->GetFirstChild();
  2880. if (!cur) {
  2881. return nullptr;
  2882. }
  2883. for (;;) {
  2884. if (bNoBlockCrossing && IsBlockNode(cur)) {
  2885. return cur;
  2886. }
  2887. nsIContent *next = cur->GetFirstChild();
  2888. if (!next) {
  2889. return cur;
  2890. }
  2891. cur = next;
  2892. }
  2893. NS_NOTREACHED("What part of for(;;) do you not understand?");
  2894. return nullptr;
  2895. }
  2896. bool
  2897. EditorBase::IsBlockNode(nsINode* aNode)
  2898. {
  2899. // stub to be overridden in HTMLEditor.
  2900. // screwing around with the class hierarchy here in order
  2901. // to not duplicate the code in GetNextNode/GetPrevNode
  2902. // across both EditorBase/HTMLEditor.
  2903. return false;
  2904. }
  2905. bool
  2906. EditorBase::CanContain(nsINode& aParent,
  2907. nsIContent& aChild)
  2908. {
  2909. switch (aParent.NodeType()) {
  2910. case nsIDOMNode::ELEMENT_NODE:
  2911. case nsIDOMNode::DOCUMENT_FRAGMENT_NODE:
  2912. return TagCanContain(*aParent.NodeInfo()->NameAtom(), aChild);
  2913. }
  2914. return false;
  2915. }
  2916. bool
  2917. EditorBase::CanContainTag(nsINode& aParent,
  2918. nsIAtom& aChildTag)
  2919. {
  2920. switch (aParent.NodeType()) {
  2921. case nsIDOMNode::ELEMENT_NODE:
  2922. case nsIDOMNode::DOCUMENT_FRAGMENT_NODE:
  2923. return TagCanContainTag(*aParent.NodeInfo()->NameAtom(), aChildTag);
  2924. }
  2925. return false;
  2926. }
  2927. bool
  2928. EditorBase::TagCanContain(nsIAtom& aParentTag,
  2929. nsIContent& aChild)
  2930. {
  2931. switch (aChild.NodeType()) {
  2932. case nsIDOMNode::TEXT_NODE:
  2933. case nsIDOMNode::ELEMENT_NODE:
  2934. case nsIDOMNode::DOCUMENT_FRAGMENT_NODE:
  2935. return TagCanContainTag(aParentTag, *aChild.NodeInfo()->NameAtom());
  2936. }
  2937. return false;
  2938. }
  2939. bool
  2940. EditorBase::TagCanContainTag(nsIAtom& aParentTag,
  2941. nsIAtom& aChildTag)
  2942. {
  2943. return true;
  2944. }
  2945. bool
  2946. EditorBase::IsRoot(nsIDOMNode* inNode)
  2947. {
  2948. NS_ENSURE_TRUE(inNode, false);
  2949. nsCOMPtr<nsIDOMNode> rootNode = do_QueryInterface(GetRoot());
  2950. return inNode == rootNode;
  2951. }
  2952. bool
  2953. EditorBase::IsRoot(nsINode* inNode)
  2954. {
  2955. NS_ENSURE_TRUE(inNode, false);
  2956. nsCOMPtr<nsINode> rootNode = GetRoot();
  2957. return inNode == rootNode;
  2958. }
  2959. bool
  2960. EditorBase::IsEditorRoot(nsINode* aNode)
  2961. {
  2962. NS_ENSURE_TRUE(aNode, false);
  2963. nsCOMPtr<nsINode> rootNode = GetEditorRoot();
  2964. return aNode == rootNode;
  2965. }
  2966. bool
  2967. EditorBase::IsDescendantOfRoot(nsIDOMNode* inNode)
  2968. {
  2969. nsCOMPtr<nsINode> node = do_QueryInterface(inNode);
  2970. return IsDescendantOfRoot(node);
  2971. }
  2972. bool
  2973. EditorBase::IsDescendantOfRoot(nsINode* inNode)
  2974. {
  2975. NS_ENSURE_TRUE(inNode, false);
  2976. nsCOMPtr<nsIContent> root = GetRoot();
  2977. NS_ENSURE_TRUE(root, false);
  2978. return nsContentUtils::ContentIsDescendantOf(inNode, root);
  2979. }
  2980. bool
  2981. EditorBase::IsDescendantOfEditorRoot(nsINode* aNode)
  2982. {
  2983. NS_ENSURE_TRUE(aNode, false);
  2984. nsCOMPtr<nsIContent> root = GetEditorRoot();
  2985. NS_ENSURE_TRUE(root, false);
  2986. return nsContentUtils::ContentIsDescendantOf(aNode, root);
  2987. }
  2988. bool
  2989. EditorBase::IsContainer(nsINode* aNode)
  2990. {
  2991. return aNode ? true : false;
  2992. }
  2993. bool
  2994. EditorBase::IsContainer(nsIDOMNode* aNode)
  2995. {
  2996. return aNode ? true : false;
  2997. }
  2998. static inline bool
  2999. IsElementVisible(Element* aElement)
  3000. {
  3001. if (aElement->GetPrimaryFrame()) {
  3002. // It's visible, for our purposes
  3003. return true;
  3004. }
  3005. nsIContent *cur = aElement;
  3006. for (;;) {
  3007. // Walk up the tree looking for the nearest ancestor with a frame.
  3008. // The state of the child right below it will determine whether
  3009. // we might possibly have a frame or not.
  3010. bool haveLazyBitOnChild = cur->HasFlag(NODE_NEEDS_FRAME);
  3011. cur = cur->GetFlattenedTreeParent();
  3012. if (!cur) {
  3013. if (!haveLazyBitOnChild) {
  3014. // None of our ancestors have lazy bits set, so we shouldn't
  3015. // have a frame
  3016. return false;
  3017. }
  3018. // The root has a lazy frame construction bit. We need to check
  3019. // our style.
  3020. break;
  3021. }
  3022. if (cur->GetPrimaryFrame()) {
  3023. if (!haveLazyBitOnChild) {
  3024. // Our ancestor directly under |cur| doesn't have lazy bits;
  3025. // that means we won't get a frame
  3026. return false;
  3027. }
  3028. if (cur->GetPrimaryFrame()->IsLeaf()) {
  3029. // Nothing under here will ever get frames
  3030. return false;
  3031. }
  3032. // Otherwise, we might end up with a frame when that lazy bit is
  3033. // processed. Figure out our actual style.
  3034. break;
  3035. }
  3036. }
  3037. // Now it might be that we have no frame because we're in a
  3038. // display:none subtree, or it might be that we're just dealing with
  3039. // lazy frame construction and it hasn't happened yet. Check which
  3040. // one it is.
  3041. RefPtr<nsStyleContext> styleContext =
  3042. nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement,
  3043. nullptr, nullptr);
  3044. if (styleContext) {
  3045. return styleContext->StyleDisplay()->mDisplay != StyleDisplay::None;
  3046. }
  3047. return false;
  3048. }
  3049. bool
  3050. EditorBase::IsEditable(nsIDOMNode* aNode)
  3051. {
  3052. nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
  3053. return IsEditable(content);
  3054. }
  3055. bool
  3056. EditorBase::IsEditable(nsINode* aNode)
  3057. {
  3058. NS_ENSURE_TRUE(aNode, false);
  3059. if (!aNode->IsNodeOfType(nsINode::eCONTENT) || IsMozEditorBogusNode(aNode) ||
  3060. !IsModifiableNode(aNode)) {
  3061. return false;
  3062. }
  3063. // see if it has a frame. If so, we'll edit it.
  3064. // special case for textnodes: frame must have width.
  3065. if (aNode->IsElement() && !IsElementVisible(aNode->AsElement())) {
  3066. // If the element has no frame, it's not editable. Note that we
  3067. // need to check IsElement() here, because some of our tests
  3068. // rely on frameless textnodes being visible.
  3069. return false;
  3070. }
  3071. switch (aNode->NodeType()) {
  3072. case nsIDOMNode::ELEMENT_NODE:
  3073. case nsIDOMNode::TEXT_NODE:
  3074. return true; // element or text node; not invisible
  3075. default:
  3076. return false;
  3077. }
  3078. }
  3079. bool
  3080. EditorBase::IsMozEditorBogusNode(nsINode* element)
  3081. {
  3082. return element && element->IsElement() &&
  3083. element->AsElement()->AttrValueIs(kNameSpaceID_None,
  3084. kMOZEditorBogusNodeAttrAtom, kMOZEditorBogusNodeValue,
  3085. eCaseMatters);
  3086. }
  3087. uint32_t
  3088. EditorBase::CountEditableChildren(nsINode* aNode)
  3089. {
  3090. MOZ_ASSERT(aNode);
  3091. uint32_t count = 0;
  3092. for (nsIContent* child = aNode->GetFirstChild();
  3093. child;
  3094. child = child->GetNextSibling()) {
  3095. if (IsEditable(child)) {
  3096. ++count;
  3097. }
  3098. }
  3099. return count;
  3100. }
  3101. NS_IMETHODIMP
  3102. EditorBase::IncrementModificationCount(int32_t inNumMods)
  3103. {
  3104. uint32_t oldModCount = mModCount;
  3105. mModCount += inNumMods;
  3106. if ((!oldModCount && mModCount) ||
  3107. (oldModCount && !mModCount)) {
  3108. NotifyDocumentListeners(eDocumentStateChanged);
  3109. }
  3110. return NS_OK;
  3111. }
  3112. NS_IMETHODIMP
  3113. EditorBase::GetModificationCount(int32_t* outModCount)
  3114. {
  3115. NS_ENSURE_ARG_POINTER(outModCount);
  3116. *outModCount = mModCount;
  3117. return NS_OK;
  3118. }
  3119. NS_IMETHODIMP
  3120. EditorBase::ResetModificationCount()
  3121. {
  3122. bool doNotify = (mModCount != 0);
  3123. mModCount = 0;
  3124. if (doNotify) {
  3125. NotifyDocumentListeners(eDocumentStateChanged);
  3126. }
  3127. return NS_OK;
  3128. }
  3129. nsIAtom*
  3130. EditorBase::GetTag(nsIDOMNode* aNode)
  3131. {
  3132. nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
  3133. if (!content) {
  3134. NS_ASSERTION(aNode, "null node passed to EditorBase::GetTag()");
  3135. return nullptr;
  3136. }
  3137. return content->NodeInfo()->NameAtom();
  3138. }
  3139. nsresult
  3140. EditorBase::GetTagString(nsIDOMNode* aNode,
  3141. nsAString& outString)
  3142. {
  3143. if (!aNode) {
  3144. NS_NOTREACHED("null node passed to EditorBase::GetTagString()");
  3145. return NS_ERROR_NULL_POINTER;
  3146. }
  3147. nsIAtom *atom = GetTag(aNode);
  3148. if (!atom) {
  3149. return NS_ERROR_FAILURE;
  3150. }
  3151. atom->ToString(outString);
  3152. return NS_OK;
  3153. }
  3154. bool
  3155. EditorBase::NodesSameType(nsIDOMNode* aNode1,
  3156. nsIDOMNode* aNode2)
  3157. {
  3158. if (!aNode1 || !aNode2) {
  3159. NS_NOTREACHED("null node passed to EditorBase::NodesSameType()");
  3160. return false;
  3161. }
  3162. nsCOMPtr<nsIContent> content1 = do_QueryInterface(aNode1);
  3163. NS_ENSURE_TRUE(content1, false);
  3164. nsCOMPtr<nsIContent> content2 = do_QueryInterface(aNode2);
  3165. NS_ENSURE_TRUE(content2, false);
  3166. return AreNodesSameType(content1, content2);
  3167. }
  3168. bool
  3169. EditorBase::AreNodesSameType(nsIContent* aNode1,
  3170. nsIContent* aNode2)
  3171. {
  3172. MOZ_ASSERT(aNode1);
  3173. MOZ_ASSERT(aNode2);
  3174. return aNode1->NodeInfo()->NameAtom() == aNode2->NodeInfo()->NameAtom();
  3175. }
  3176. bool
  3177. EditorBase::IsTextNode(nsIDOMNode* aNode)
  3178. {
  3179. if (!aNode) {
  3180. NS_NOTREACHED("null node passed to IsTextNode()");
  3181. return false;
  3182. }
  3183. uint16_t nodeType;
  3184. aNode->GetNodeType(&nodeType);
  3185. return (nodeType == nsIDOMNode::TEXT_NODE);
  3186. }
  3187. bool
  3188. EditorBase::IsTextNode(nsINode* aNode)
  3189. {
  3190. return aNode->NodeType() == nsIDOMNode::TEXT_NODE;
  3191. }
  3192. nsCOMPtr<nsIDOMNode>
  3193. EditorBase::GetChildAt(nsIDOMNode* aParent, int32_t aOffset)
  3194. {
  3195. nsCOMPtr<nsIDOMNode> resultNode;
  3196. nsCOMPtr<nsIContent> parent = do_QueryInterface(aParent);
  3197. NS_ENSURE_TRUE(parent, resultNode);
  3198. resultNode = do_QueryInterface(parent->GetChildAt(aOffset));
  3199. return resultNode;
  3200. }
  3201. /**
  3202. * GetNodeAtRangeOffsetPoint() returns the node at this position in a range,
  3203. * assuming that aParentOrNode is the node itself if it's a text node, or
  3204. * the node's parent otherwise.
  3205. */
  3206. nsIContent*
  3207. EditorBase::GetNodeAtRangeOffsetPoint(nsIDOMNode* aParentOrNode,
  3208. int32_t aOffset)
  3209. {
  3210. nsCOMPtr<nsINode> parentOrNode = do_QueryInterface(aParentOrNode);
  3211. NS_ENSURE_TRUE(parentOrNode || !aParentOrNode, nullptr);
  3212. if (parentOrNode->GetAsText()) {
  3213. return parentOrNode->AsContent();
  3214. }
  3215. return parentOrNode->GetChildAt(aOffset);
  3216. }
  3217. /**
  3218. * GetStartNodeAndOffset() returns whatever the start parent & offset is of
  3219. * the first range in the selection.
  3220. */
  3221. nsresult
  3222. EditorBase::GetStartNodeAndOffset(Selection* aSelection,
  3223. nsIDOMNode** outStartNode,
  3224. int32_t* outStartOffset)
  3225. {
  3226. NS_ENSURE_TRUE(outStartNode && outStartOffset && aSelection, NS_ERROR_NULL_POINTER);
  3227. nsCOMPtr<nsINode> startNode;
  3228. nsresult rv = GetStartNodeAndOffset(aSelection, getter_AddRefs(startNode),
  3229. outStartOffset);
  3230. if (NS_FAILED(rv)) {
  3231. return rv;
  3232. }
  3233. if (startNode) {
  3234. NS_ADDREF(*outStartNode = startNode->AsDOMNode());
  3235. } else {
  3236. *outStartNode = nullptr;
  3237. }
  3238. return NS_OK;
  3239. }
  3240. nsresult
  3241. EditorBase::GetStartNodeAndOffset(Selection* aSelection,
  3242. nsINode** aStartNode,
  3243. int32_t* aStartOffset)
  3244. {
  3245. MOZ_ASSERT(aSelection);
  3246. MOZ_ASSERT(aStartNode);
  3247. MOZ_ASSERT(aStartOffset);
  3248. *aStartNode = nullptr;
  3249. *aStartOffset = 0;
  3250. if (!aSelection->RangeCount()) {
  3251. return NS_ERROR_FAILURE;
  3252. }
  3253. const nsRange* range = aSelection->GetRangeAt(0);
  3254. NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
  3255. NS_ENSURE_TRUE(range->IsPositioned(), NS_ERROR_FAILURE);
  3256. NS_IF_ADDREF(*aStartNode = range->GetStartParent());
  3257. *aStartOffset = range->StartOffset();
  3258. return NS_OK;
  3259. }
  3260. /**
  3261. * GetEndNodeAndOffset() returns whatever the end parent & offset is of
  3262. * the first range in the selection.
  3263. */
  3264. nsresult
  3265. EditorBase::GetEndNodeAndOffset(Selection* aSelection,
  3266. nsIDOMNode** outEndNode,
  3267. int32_t* outEndOffset)
  3268. {
  3269. NS_ENSURE_TRUE(outEndNode && outEndOffset && aSelection, NS_ERROR_NULL_POINTER);
  3270. nsCOMPtr<nsINode> endNode;
  3271. nsresult rv = GetEndNodeAndOffset(aSelection, getter_AddRefs(endNode),
  3272. outEndOffset);
  3273. NS_ENSURE_SUCCESS(rv, rv);
  3274. if (endNode) {
  3275. NS_ADDREF(*outEndNode = endNode->AsDOMNode());
  3276. } else {
  3277. *outEndNode = nullptr;
  3278. }
  3279. return NS_OK;
  3280. }
  3281. nsresult
  3282. EditorBase::GetEndNodeAndOffset(Selection* aSelection,
  3283. nsINode** aEndNode,
  3284. int32_t* aEndOffset)
  3285. {
  3286. MOZ_ASSERT(aSelection);
  3287. MOZ_ASSERT(aEndNode);
  3288. MOZ_ASSERT(aEndOffset);
  3289. *aEndNode = nullptr;
  3290. *aEndOffset = 0;
  3291. NS_ENSURE_TRUE(aSelection->RangeCount(), NS_ERROR_FAILURE);
  3292. const nsRange* range = aSelection->GetRangeAt(0);
  3293. NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
  3294. NS_ENSURE_TRUE(range->IsPositioned(), NS_ERROR_FAILURE);
  3295. NS_IF_ADDREF(*aEndNode = range->GetEndParent());
  3296. *aEndOffset = range->EndOffset();
  3297. return NS_OK;
  3298. }
  3299. /**
  3300. * IsPreformatted() checks the style info for the node for the preformatted
  3301. * text style.
  3302. */
  3303. nsresult
  3304. EditorBase::IsPreformatted(nsIDOMNode* aNode,
  3305. bool* aResult)
  3306. {
  3307. nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
  3308. NS_ENSURE_TRUE(aResult && content, NS_ERROR_NULL_POINTER);
  3309. nsCOMPtr<nsIPresShell> ps = GetPresShell();
  3310. NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
  3311. // Look at the node (and its parent if it's not an element), and grab its style context
  3312. RefPtr<nsStyleContext> elementStyle;
  3313. if (!content->IsElement()) {
  3314. content = content->GetParent();
  3315. }
  3316. if (content && content->IsElement()) {
  3317. elementStyle = nsComputedDOMStyle::GetStyleContextForElementNoFlush(content->AsElement(),
  3318. nullptr,
  3319. ps);
  3320. }
  3321. if (!elementStyle) {
  3322. // Consider nodes without a style context to be NOT preformatted:
  3323. // For instance, this is true of JS tags inside the body (which show
  3324. // up as #text nodes but have no style context).
  3325. *aResult = false;
  3326. return NS_OK;
  3327. }
  3328. const nsStyleText* styleText = elementStyle->StyleText();
  3329. *aResult = styleText->WhiteSpaceIsSignificant();
  3330. return NS_OK;
  3331. }
  3332. /**
  3333. * This splits a node "deeply", splitting children as appropriate. The place
  3334. * to split is represented by a DOM point at {splitPointParent,
  3335. * splitPointOffset}. That DOM point must be inside aNode, which is the node
  3336. * to split. We return the offset in the parent of aNode where the split
  3337. * terminates - where you would want to insert a new element, for instance, if
  3338. * that's why you were splitting the node.
  3339. *
  3340. * -1 is returned on failure, in unlikely cases like the selection being
  3341. * unavailable or cloning the node failing. Make sure not to use the returned
  3342. * offset for anything without checking that it's valid! If you're not using
  3343. * the offset, it's okay to ignore the return value.
  3344. */
  3345. int32_t
  3346. EditorBase::SplitNodeDeep(nsIContent& aNode,
  3347. nsIContent& aSplitPointParent,
  3348. int32_t aSplitPointOffset,
  3349. EmptyContainers aEmptyContainers,
  3350. nsIContent** aOutLeftNode,
  3351. nsIContent** aOutRightNode)
  3352. {
  3353. MOZ_ASSERT(&aSplitPointParent == &aNode ||
  3354. EditorUtils::IsDescendantOf(&aSplitPointParent, &aNode));
  3355. int32_t offset = aSplitPointOffset;
  3356. nsCOMPtr<nsIContent> leftNode, rightNode;
  3357. OwningNonNull<nsIContent> nodeToSplit = aSplitPointParent;
  3358. while (true) {
  3359. // Need to insert rules code call here to do things like not split a list
  3360. // if you are after the last <li> or before the first, etc. For now we
  3361. // just have some smarts about unneccessarily splitting text nodes, which
  3362. // should be universal enough to put straight in this EditorBase routine.
  3363. bool didSplit = false;
  3364. if ((aEmptyContainers == EmptyContainers::yes &&
  3365. !nodeToSplit->GetAsText()) ||
  3366. (offset && offset != (int32_t)nodeToSplit->Length())) {
  3367. didSplit = true;
  3368. ErrorResult rv;
  3369. nsCOMPtr<nsIContent> newLeftNode = SplitNode(nodeToSplit, offset, rv);
  3370. NS_ENSURE_TRUE(!NS_FAILED(rv.StealNSResult()), -1);
  3371. rightNode = nodeToSplit;
  3372. leftNode = newLeftNode;
  3373. }
  3374. NS_ENSURE_TRUE(nodeToSplit->GetParent(), -1);
  3375. OwningNonNull<nsIContent> parentNode = *nodeToSplit->GetParent();
  3376. if (!didSplit && offset) {
  3377. // Must be "end of text node" case, we didn't split it, just move past it
  3378. offset = parentNode->IndexOf(nodeToSplit) + 1;
  3379. leftNode = nodeToSplit;
  3380. } else {
  3381. offset = parentNode->IndexOf(nodeToSplit);
  3382. rightNode = nodeToSplit;
  3383. }
  3384. if (nodeToSplit == &aNode) {
  3385. // we split all the way up to (and including) aNode; we're done
  3386. break;
  3387. }
  3388. nodeToSplit = parentNode;
  3389. }
  3390. if (aOutLeftNode) {
  3391. leftNode.forget(aOutLeftNode);
  3392. }
  3393. if (aOutRightNode) {
  3394. rightNode.forget(aOutRightNode);
  3395. }
  3396. return offset;
  3397. }
  3398. /**
  3399. * This joins two like nodes "deeply", joining children as appropriate.
  3400. * Returns the point of the join, or (nullptr, -1) in case of error.
  3401. */
  3402. EditorDOMPoint
  3403. EditorBase::JoinNodeDeep(nsIContent& aLeftNode,
  3404. nsIContent& aRightNode)
  3405. {
  3406. // While the rightmost children and their descendants of the left node match
  3407. // the leftmost children and their descendants of the right node, join them
  3408. // up.
  3409. nsCOMPtr<nsIContent> leftNodeToJoin = &aLeftNode;
  3410. nsCOMPtr<nsIContent> rightNodeToJoin = &aRightNode;
  3411. nsCOMPtr<nsINode> parentNode = aRightNode.GetParentNode();
  3412. EditorDOMPoint ret;
  3413. while (leftNodeToJoin && rightNodeToJoin && parentNode &&
  3414. AreNodesSameType(leftNodeToJoin, rightNodeToJoin)) {
  3415. uint32_t length = leftNodeToJoin->Length();
  3416. ret.node = rightNodeToJoin;
  3417. ret.offset = length;
  3418. // Do the join
  3419. nsresult rv = JoinNodes(*leftNodeToJoin, *rightNodeToJoin);
  3420. NS_ENSURE_SUCCESS(rv, EditorDOMPoint());
  3421. if (parentNode->GetAsText()) {
  3422. // We've joined all the way down to text nodes, we're done!
  3423. return ret;
  3424. }
  3425. // Get new left and right nodes, and begin anew
  3426. parentNode = rightNodeToJoin;
  3427. leftNodeToJoin = parentNode->GetChildAt(length - 1);
  3428. rightNodeToJoin = parentNode->GetChildAt(length);
  3429. // Skip over non-editable nodes
  3430. while (leftNodeToJoin && !IsEditable(leftNodeToJoin)) {
  3431. leftNodeToJoin = leftNodeToJoin->GetPreviousSibling();
  3432. }
  3433. if (!leftNodeToJoin) {
  3434. return ret;
  3435. }
  3436. while (rightNodeToJoin && !IsEditable(rightNodeToJoin)) {
  3437. rightNodeToJoin = rightNodeToJoin->GetNextSibling();
  3438. }
  3439. if (!rightNodeToJoin) {
  3440. return ret;
  3441. }
  3442. }
  3443. return ret;
  3444. }
  3445. void
  3446. EditorBase::BeginUpdateViewBatch()
  3447. {
  3448. NS_PRECONDITION(mUpdateCount >= 0, "bad state");
  3449. if (!mUpdateCount) {
  3450. // Turn off selection updates and notifications.
  3451. RefPtr<Selection> selection = GetSelection();
  3452. if (selection) {
  3453. selection->StartBatchChanges();
  3454. }
  3455. }
  3456. mUpdateCount++;
  3457. }
  3458. nsresult
  3459. EditorBase::EndUpdateViewBatch()
  3460. {
  3461. NS_PRECONDITION(mUpdateCount > 0, "bad state");
  3462. if (mUpdateCount <= 0) {
  3463. mUpdateCount = 0;
  3464. return NS_ERROR_FAILURE;
  3465. }
  3466. mUpdateCount--;
  3467. if (!mUpdateCount) {
  3468. // Turn selection updating and notifications back on.
  3469. RefPtr<Selection> selection = GetSelection();
  3470. if (selection) {
  3471. selection->EndBatchChanges();
  3472. }
  3473. }
  3474. return NS_OK;
  3475. }
  3476. bool
  3477. EditorBase::GetShouldTxnSetSelection()
  3478. {
  3479. return mShouldTxnSetSelection;
  3480. }
  3481. NS_IMETHODIMP
  3482. EditorBase::DeleteSelectionImpl(EDirection aAction,
  3483. EStripWrappers aStripWrappers)
  3484. {
  3485. MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
  3486. RefPtr<Selection> selection = GetSelection();
  3487. NS_ENSURE_STATE(selection);
  3488. RefPtr<EditAggregateTransaction> transaction;
  3489. nsCOMPtr<nsINode> deleteNode;
  3490. int32_t deleteCharOffset = 0, deleteCharLength = 0;
  3491. nsresult rv = CreateTxnForDeleteSelection(aAction,
  3492. getter_AddRefs(transaction),
  3493. getter_AddRefs(deleteNode),
  3494. &deleteCharOffset,
  3495. &deleteCharLength);
  3496. nsCOMPtr<nsIDOMCharacterData> deleteCharData(do_QueryInterface(deleteNode));
  3497. if (NS_SUCCEEDED(rv)) {
  3498. AutoRules beginRulesSniffing(this, EditAction::deleteSelection, aAction);
  3499. // Notify nsIEditActionListener::WillDelete[Selection|Text|Node]
  3500. {
  3501. AutoActionListenerArray listeners(mActionListeners);
  3502. if (!deleteNode) {
  3503. for (auto& listener : listeners) {
  3504. listener->WillDeleteSelection(selection);
  3505. }
  3506. } else if (deleteCharData) {
  3507. for (auto& listener : listeners) {
  3508. listener->WillDeleteText(deleteCharData, deleteCharOffset, 1);
  3509. }
  3510. } else {
  3511. for (auto& listener : listeners) {
  3512. listener->WillDeleteNode(deleteNode->AsDOMNode());
  3513. }
  3514. }
  3515. }
  3516. // Delete the specified amount
  3517. rv = DoTransaction(transaction);
  3518. // Notify nsIEditActionListener::DidDelete[Selection|Text|Node]
  3519. {
  3520. AutoActionListenerArray listeners(mActionListeners);
  3521. if (!deleteNode) {
  3522. for (auto& listener : mActionListeners) {
  3523. listener->DidDeleteSelection(selection);
  3524. }
  3525. } else if (deleteCharData) {
  3526. for (auto& listener : mActionListeners) {
  3527. listener->DidDeleteText(deleteCharData, deleteCharOffset, 1, rv);
  3528. }
  3529. } else {
  3530. for (auto& listener : mActionListeners) {
  3531. listener->DidDeleteNode(deleteNode->AsDOMNode(), rv);
  3532. }
  3533. }
  3534. }
  3535. }
  3536. return rv;
  3537. }
  3538. already_AddRefed<Element>
  3539. EditorBase::DeleteSelectionAndCreateElement(nsIAtom& aTag)
  3540. {
  3541. nsresult rv = DeleteSelectionAndPrepareToCreateNode();
  3542. NS_ENSURE_SUCCESS(rv, nullptr);
  3543. RefPtr<Selection> selection = GetSelection();
  3544. NS_ENSURE_TRUE(selection, nullptr);
  3545. nsCOMPtr<nsINode> node = selection->GetAnchorNode();
  3546. uint32_t offset = selection->AnchorOffset();
  3547. nsCOMPtr<Element> newElement = CreateNode(&aTag, node, offset);
  3548. // We want the selection to be just after the new node
  3549. rv = selection->Collapse(node, offset + 1);
  3550. NS_ENSURE_SUCCESS(rv, nullptr);
  3551. return newElement.forget();
  3552. }
  3553. TextComposition*
  3554. EditorBase::GetComposition() const
  3555. {
  3556. return mComposition;
  3557. }
  3558. bool
  3559. EditorBase::IsIMEComposing() const
  3560. {
  3561. return mComposition && mComposition->IsComposing();
  3562. }
  3563. bool
  3564. EditorBase::ShouldHandleIMEComposition() const
  3565. {
  3566. // When the editor is being reframed, the old value may be restored with
  3567. // InsertText(). In this time, the text should be inserted as not a part
  3568. // of the composition.
  3569. return mComposition && mDidPostCreate;
  3570. }
  3571. nsresult
  3572. EditorBase::DeleteSelectionAndPrepareToCreateNode()
  3573. {
  3574. RefPtr<Selection> selection = GetSelection();
  3575. NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
  3576. MOZ_ASSERT(selection->GetAnchorFocusRange());
  3577. if (!selection->GetAnchorFocusRange()->Collapsed()) {
  3578. nsresult rv = DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
  3579. NS_ENSURE_SUCCESS(rv, rv);
  3580. MOZ_ASSERT(selection->GetAnchorFocusRange() &&
  3581. selection->GetAnchorFocusRange()->Collapsed(),
  3582. "Selection not collapsed after delete");
  3583. }
  3584. // If the selection is a chardata node, split it if necessary and compute
  3585. // where to put the new node
  3586. nsCOMPtr<nsINode> node = selection->GetAnchorNode();
  3587. MOZ_ASSERT(node, "Selection has no ranges in it");
  3588. if (node && node->IsNodeOfType(nsINode::eDATA_NODE)) {
  3589. NS_ASSERTION(node->GetParentNode(),
  3590. "It's impossible to insert into chardata with no parent -- "
  3591. "fix the caller");
  3592. NS_ENSURE_STATE(node->GetParentNode());
  3593. uint32_t offset = selection->AnchorOffset();
  3594. if (!offset) {
  3595. nsresult rv = selection->Collapse(node->GetParentNode(),
  3596. node->GetParentNode()->IndexOf(node));
  3597. MOZ_ASSERT(NS_SUCCEEDED(rv));
  3598. NS_ENSURE_SUCCESS(rv, rv);
  3599. } else if (offset == node->Length()) {
  3600. nsresult rv =
  3601. selection->Collapse(node->GetParentNode(),
  3602. node->GetParentNode()->IndexOf(node) + 1);
  3603. MOZ_ASSERT(NS_SUCCEEDED(rv));
  3604. NS_ENSURE_SUCCESS(rv, rv);
  3605. } else {
  3606. nsCOMPtr<nsIDOMNode> tmp;
  3607. nsresult rv = SplitNode(node->AsDOMNode(), offset, getter_AddRefs(tmp));
  3608. NS_ENSURE_SUCCESS(rv, rv);
  3609. rv = selection->Collapse(node->GetParentNode(),
  3610. node->GetParentNode()->IndexOf(node));
  3611. MOZ_ASSERT(NS_SUCCEEDED(rv));
  3612. NS_ENSURE_SUCCESS(rv, rv);
  3613. }
  3614. }
  3615. return NS_OK;
  3616. }
  3617. void
  3618. EditorBase::DoAfterDoTransaction(nsITransaction* aTxn)
  3619. {
  3620. bool isTransientTransaction;
  3621. MOZ_ALWAYS_SUCCEEDS(aTxn->GetIsTransient(&isTransientTransaction));
  3622. if (!isTransientTransaction) {
  3623. // we need to deal here with the case where the user saved after some
  3624. // edits, then undid one or more times. Then, the undo count is -ve,
  3625. // but we can't let a do take it back to zero. So we flip it up to
  3626. // a +ve number.
  3627. int32_t modCount;
  3628. GetModificationCount(&modCount);
  3629. if (modCount < 0) {
  3630. modCount = -modCount;
  3631. }
  3632. // don't count transient transactions
  3633. MOZ_ALWAYS_SUCCEEDS(IncrementModificationCount(1));
  3634. }
  3635. }
  3636. void
  3637. EditorBase::DoAfterUndoTransaction()
  3638. {
  3639. // all undoable transactions are non-transient
  3640. MOZ_ALWAYS_SUCCEEDS(IncrementModificationCount(-1));
  3641. }
  3642. void
  3643. EditorBase::DoAfterRedoTransaction()
  3644. {
  3645. // all redoable transactions are non-transient
  3646. MOZ_ALWAYS_SUCCEEDS(IncrementModificationCount(1));
  3647. }
  3648. already_AddRefed<ChangeAttributeTransaction>
  3649. EditorBase::CreateTxnForSetAttribute(Element& aElement,
  3650. nsIAtom& aAttribute,
  3651. const nsAString& aValue)
  3652. {
  3653. RefPtr<ChangeAttributeTransaction> transaction =
  3654. new ChangeAttributeTransaction(aElement, aAttribute, &aValue);
  3655. return transaction.forget();
  3656. }
  3657. already_AddRefed<ChangeAttributeTransaction>
  3658. EditorBase::CreateTxnForRemoveAttribute(Element& aElement,
  3659. nsIAtom& aAttribute)
  3660. {
  3661. RefPtr<ChangeAttributeTransaction> transaction =
  3662. new ChangeAttributeTransaction(aElement, aAttribute, nullptr);
  3663. return transaction.forget();
  3664. }
  3665. already_AddRefed<CreateElementTransaction>
  3666. EditorBase::CreateTxnForCreateElement(nsIAtom& aTag,
  3667. nsINode& aParent,
  3668. int32_t aPosition)
  3669. {
  3670. RefPtr<CreateElementTransaction> transaction =
  3671. new CreateElementTransaction(*this, aTag, aParent, aPosition);
  3672. return transaction.forget();
  3673. }
  3674. already_AddRefed<InsertNodeTransaction>
  3675. EditorBase::CreateTxnForInsertNode(nsIContent& aNode,
  3676. nsINode& aParent,
  3677. int32_t aPosition)
  3678. {
  3679. RefPtr<InsertNodeTransaction> transaction =
  3680. new InsertNodeTransaction(aNode, aParent, aPosition, *this);
  3681. return transaction.forget();
  3682. }
  3683. nsresult
  3684. EditorBase::CreateTxnForDeleteNode(nsINode* aNode,
  3685. DeleteNodeTransaction** aTransaction)
  3686. {
  3687. NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
  3688. RefPtr<DeleteNodeTransaction> transaction = new DeleteNodeTransaction();
  3689. nsresult rv = transaction->Init(this, aNode, &mRangeUpdater);
  3690. NS_ENSURE_SUCCESS(rv, rv);
  3691. transaction.forget(aTransaction);
  3692. return NS_OK;
  3693. }
  3694. already_AddRefed<CompositionTransaction>
  3695. EditorBase::CreateTxnForComposition(const nsAString& aStringToInsert)
  3696. {
  3697. MOZ_ASSERT(mIMETextNode);
  3698. // During handling IME composition, mComposition must have been initialized.
  3699. // TODO: We can simplify CompositionTransaction::Init() with TextComposition
  3700. // class.
  3701. RefPtr<CompositionTransaction> transaction =
  3702. new CompositionTransaction(*mIMETextNode, mIMETextOffset, mIMETextLength,
  3703. mComposition->GetRanges(), aStringToInsert,
  3704. *this, &mRangeUpdater);
  3705. return transaction.forget();
  3706. }
  3707. NS_IMETHODIMP
  3708. EditorBase::CreateTxnForAddStyleSheet(StyleSheet* aSheet,
  3709. AddStyleSheetTransaction** aTransaction)
  3710. {
  3711. RefPtr<AddStyleSheetTransaction> transaction = new AddStyleSheetTransaction();
  3712. nsresult rv = transaction->Init(this, aSheet);
  3713. if (NS_SUCCEEDED(rv)) {
  3714. transaction.forget(aTransaction);
  3715. }
  3716. return rv;
  3717. }
  3718. NS_IMETHODIMP
  3719. EditorBase::CreateTxnForRemoveStyleSheet(
  3720. StyleSheet* aSheet,
  3721. RemoveStyleSheetTransaction** aTransaction)
  3722. {
  3723. RefPtr<RemoveStyleSheetTransaction> transaction =
  3724. new RemoveStyleSheetTransaction();
  3725. nsresult rv = transaction->Init(this, aSheet);
  3726. if (NS_SUCCEEDED(rv)) {
  3727. transaction.forget(aTransaction);
  3728. }
  3729. return rv;
  3730. }
  3731. nsresult
  3732. EditorBase::CreateTxnForDeleteSelection(EDirection aAction,
  3733. EditAggregateTransaction** aTransaction,
  3734. nsINode** aNode,
  3735. int32_t* aOffset,
  3736. int32_t* aLength)
  3737. {
  3738. MOZ_ASSERT(aTransaction);
  3739. *aTransaction = nullptr;
  3740. RefPtr<Selection> selection = GetSelection();
  3741. NS_ENSURE_STATE(selection);
  3742. // Check whether the selection is collapsed and we should do nothing:
  3743. if (selection->Collapsed() && aAction == eNone) {
  3744. return NS_OK;
  3745. }
  3746. // allocate the out-param transaction
  3747. RefPtr<EditAggregateTransaction> aggregateTransaction =
  3748. new EditAggregateTransaction();
  3749. for (uint32_t rangeIdx = 0; rangeIdx < selection->RangeCount(); ++rangeIdx) {
  3750. RefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
  3751. NS_ENSURE_STATE(range);
  3752. // Same with range as with selection; if it is collapsed and action
  3753. // is eNone, do nothing.
  3754. if (!range->Collapsed()) {
  3755. RefPtr<DeleteRangeTransaction> transaction = new DeleteRangeTransaction();
  3756. transaction->Init(this, range, &mRangeUpdater);
  3757. aggregateTransaction->AppendChild(transaction);
  3758. } else if (aAction != eNone) {
  3759. // we have an insertion point. delete the thing in front of it or
  3760. // behind it, depending on aAction
  3761. nsresult rv = CreateTxnForDeleteInsertionPoint(range, aAction,
  3762. aggregateTransaction,
  3763. aNode, aOffset, aLength);
  3764. NS_ENSURE_SUCCESS(rv, rv);
  3765. }
  3766. }
  3767. aggregateTransaction.forget(aTransaction);
  3768. return NS_OK;
  3769. }
  3770. already_AddRefed<DeleteTextTransaction>
  3771. EditorBase::CreateTxnForDeleteCharacter(nsGenericDOMDataNode& aData,
  3772. uint32_t aOffset,
  3773. EDirection aDirection)
  3774. {
  3775. NS_ASSERTION(aDirection == eNext || aDirection == ePrevious,
  3776. "Invalid direction");
  3777. nsAutoString data;
  3778. aData.GetData(data);
  3779. NS_ASSERTION(data.Length(), "Trying to delete from a zero-length node");
  3780. NS_ENSURE_TRUE(data.Length(), nullptr);
  3781. uint32_t segOffset = aOffset, segLength = 1;
  3782. if (aDirection == eNext) {
  3783. if (segOffset + 1 < data.Length() &&
  3784. NS_IS_HIGH_SURROGATE(data[segOffset]) &&
  3785. NS_IS_LOW_SURROGATE(data[segOffset+1])) {
  3786. // Delete both halves of the surrogate pair
  3787. ++segLength;
  3788. }
  3789. } else if (aOffset > 0) {
  3790. --segOffset;
  3791. if (segOffset > 0 &&
  3792. NS_IS_LOW_SURROGATE(data[segOffset]) &&
  3793. NS_IS_HIGH_SURROGATE(data[segOffset-1])) {
  3794. ++segLength;
  3795. --segOffset;
  3796. }
  3797. } else {
  3798. return nullptr;
  3799. }
  3800. return CreateTxnForDeleteText(aData, segOffset, segLength);
  3801. }
  3802. //XXX: currently, this doesn't handle edge conditions because GetNext/GetPrior
  3803. //are not implemented
  3804. nsresult
  3805. EditorBase::CreateTxnForDeleteInsertionPoint(
  3806. nsRange* aRange,
  3807. EDirection aAction,
  3808. EditAggregateTransaction* aTransaction,
  3809. nsINode** aNode,
  3810. int32_t* aOffset,
  3811. int32_t* aLength)
  3812. {
  3813. MOZ_ASSERT(aAction != eNone);
  3814. // get the node and offset of the insertion point
  3815. nsCOMPtr<nsINode> node = aRange->GetStartParent();
  3816. NS_ENSURE_STATE(node);
  3817. int32_t offset = aRange->StartOffset();
  3818. // determine if the insertion point is at the beginning, middle, or end of
  3819. // the node
  3820. uint32_t count = node->Length();
  3821. bool isFirst = !offset;
  3822. bool isLast = (count == (uint32_t)offset);
  3823. // XXX: if isFirst && isLast, then we'll need to delete the node
  3824. // as well as the 1 child
  3825. // build a transaction for deleting the appropriate data
  3826. // XXX: this has to come from rule section
  3827. if (aAction == ePrevious && isFirst) {
  3828. // we're backspacing from the beginning of the node. Delete the first
  3829. // thing to our left
  3830. nsCOMPtr<nsIContent> priorNode = GetPriorNode(node, true);
  3831. NS_ENSURE_STATE(priorNode);
  3832. // there is a priorNode, so delete its last child (if chardata, delete the
  3833. // last char). if it has no children, delete it
  3834. if (priorNode->IsNodeOfType(nsINode::eDATA_NODE)) {
  3835. RefPtr<nsGenericDOMDataNode> priorNodeAsCharData =
  3836. static_cast<nsGenericDOMDataNode*>(priorNode.get());
  3837. uint32_t length = priorNode->Length();
  3838. // Bail out for empty chardata XXX: Do we want to do something else?
  3839. NS_ENSURE_STATE(length);
  3840. RefPtr<DeleteTextTransaction> transaction =
  3841. CreateTxnForDeleteCharacter(*priorNodeAsCharData, length, ePrevious);
  3842. NS_ENSURE_STATE(transaction);
  3843. *aOffset = transaction->GetOffset();
  3844. *aLength = transaction->GetNumCharsToDelete();
  3845. aTransaction->AppendChild(transaction);
  3846. } else {
  3847. // priorNode is not chardata, so tell its parent to delete it
  3848. RefPtr<DeleteNodeTransaction> transaction;
  3849. nsresult rv =
  3850. CreateTxnForDeleteNode(priorNode, getter_AddRefs(transaction));
  3851. NS_ENSURE_SUCCESS(rv, rv);
  3852. aTransaction->AppendChild(transaction);
  3853. }
  3854. NS_ADDREF(*aNode = priorNode);
  3855. return NS_OK;
  3856. }
  3857. if (aAction == eNext && isLast) {
  3858. // we're deleting from the end of the node. Delete the first thing to our
  3859. // right
  3860. nsCOMPtr<nsIContent> nextNode = GetNextNode(node, true);
  3861. NS_ENSURE_STATE(nextNode);
  3862. // there is a nextNode, so delete its first child (if chardata, delete the
  3863. // first char). if it has no children, delete it
  3864. if (nextNode->IsNodeOfType(nsINode::eDATA_NODE)) {
  3865. RefPtr<nsGenericDOMDataNode> nextNodeAsCharData =
  3866. static_cast<nsGenericDOMDataNode*>(nextNode.get());
  3867. uint32_t length = nextNode->Length();
  3868. // Bail out for empty chardata XXX: Do we want to do something else?
  3869. NS_ENSURE_STATE(length);
  3870. RefPtr<DeleteTextTransaction> transaction =
  3871. CreateTxnForDeleteCharacter(*nextNodeAsCharData, 0, eNext);
  3872. NS_ENSURE_STATE(transaction);
  3873. *aOffset = transaction->GetOffset();
  3874. *aLength = transaction->GetNumCharsToDelete();
  3875. aTransaction->AppendChild(transaction);
  3876. } else {
  3877. // nextNode is not chardata, so tell its parent to delete it
  3878. RefPtr<DeleteNodeTransaction> transaction;
  3879. nsresult rv =
  3880. CreateTxnForDeleteNode(nextNode, getter_AddRefs(transaction));
  3881. NS_ENSURE_SUCCESS(rv, rv);
  3882. aTransaction->AppendChild(transaction);
  3883. }
  3884. NS_ADDREF(*aNode = nextNode);
  3885. return NS_OK;
  3886. }
  3887. if (node->IsNodeOfType(nsINode::eDATA_NODE)) {
  3888. RefPtr<nsGenericDOMDataNode> nodeAsCharData =
  3889. static_cast<nsGenericDOMDataNode*>(node.get());
  3890. // we have chardata, so delete a char at the proper offset
  3891. RefPtr<DeleteTextTransaction> transaction =
  3892. CreateTxnForDeleteCharacter(*nodeAsCharData, offset, aAction);
  3893. NS_ENSURE_STATE(transaction);
  3894. aTransaction->AppendChild(transaction);
  3895. NS_ADDREF(*aNode = node);
  3896. *aOffset = transaction->GetOffset();
  3897. *aLength = transaction->GetNumCharsToDelete();
  3898. } else {
  3899. // we're either deleting a node or chardata, need to dig into the next/prev
  3900. // node to find out
  3901. nsCOMPtr<nsINode> selectedNode;
  3902. if (aAction == ePrevious) {
  3903. selectedNode = GetPriorNode(node, offset, true);
  3904. } else if (aAction == eNext) {
  3905. selectedNode = GetNextNode(node, offset, true);
  3906. }
  3907. while (selectedNode &&
  3908. selectedNode->IsNodeOfType(nsINode::eDATA_NODE) &&
  3909. !selectedNode->Length()) {
  3910. // Can't delete an empty chardata node (bug 762183)
  3911. if (aAction == ePrevious) {
  3912. selectedNode = GetPriorNode(selectedNode, true);
  3913. } else if (aAction == eNext) {
  3914. selectedNode = GetNextNode(selectedNode, true);
  3915. }
  3916. }
  3917. NS_ENSURE_STATE(selectedNode);
  3918. if (selectedNode->IsNodeOfType(nsINode::eDATA_NODE)) {
  3919. RefPtr<nsGenericDOMDataNode> selectedNodeAsCharData =
  3920. static_cast<nsGenericDOMDataNode*>(selectedNode.get());
  3921. // we are deleting from a chardata node, so do a character deletion
  3922. uint32_t position = 0;
  3923. if (aAction == ePrevious) {
  3924. position = selectedNode->Length();
  3925. }
  3926. RefPtr<DeleteTextTransaction> deleteTextTransaction =
  3927. CreateTxnForDeleteCharacter(*selectedNodeAsCharData, position,
  3928. aAction);
  3929. NS_ENSURE_TRUE(deleteTextTransaction, NS_ERROR_NULL_POINTER);
  3930. aTransaction->AppendChild(deleteTextTransaction);
  3931. *aOffset = deleteTextTransaction->GetOffset();
  3932. *aLength = deleteTextTransaction->GetNumCharsToDelete();
  3933. } else {
  3934. RefPtr<DeleteNodeTransaction> deleteNodeTransaction;
  3935. nsresult rv =
  3936. CreateTxnForDeleteNode(selectedNode,
  3937. getter_AddRefs(deleteNodeTransaction));
  3938. NS_ENSURE_SUCCESS(rv, rv);
  3939. NS_ENSURE_TRUE(deleteNodeTransaction, NS_ERROR_NULL_POINTER);
  3940. aTransaction->AppendChild(deleteNodeTransaction);
  3941. }
  3942. NS_ADDREF(*aNode = selectedNode);
  3943. }
  3944. return NS_OK;
  3945. }
  3946. nsresult
  3947. EditorBase::CreateRange(nsIDOMNode* aStartParent,
  3948. int32_t aStartOffset,
  3949. nsIDOMNode* aEndParent,
  3950. int32_t aEndOffset,
  3951. nsRange** aRange)
  3952. {
  3953. return nsRange::CreateRange(aStartParent, aStartOffset, aEndParent,
  3954. aEndOffset, aRange);
  3955. }
  3956. nsresult
  3957. EditorBase::AppendNodeToSelectionAsRange(nsIDOMNode* aNode)
  3958. {
  3959. NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
  3960. RefPtr<Selection> selection = GetSelection();
  3961. NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
  3962. nsCOMPtr<nsIDOMNode> parentNode;
  3963. nsresult rv = aNode->GetParentNode(getter_AddRefs(parentNode));
  3964. NS_ENSURE_SUCCESS(rv, rv);
  3965. NS_ENSURE_TRUE(parentNode, NS_ERROR_NULL_POINTER);
  3966. int32_t offset = GetChildOffset(aNode, parentNode);
  3967. RefPtr<nsRange> range;
  3968. rv = CreateRange(parentNode, offset, parentNode, offset + 1,
  3969. getter_AddRefs(range));
  3970. NS_ENSURE_SUCCESS(rv, rv);
  3971. NS_ENSURE_TRUE(range, NS_ERROR_NULL_POINTER);
  3972. return selection->AddRange(range);
  3973. }
  3974. nsresult
  3975. EditorBase::ClearSelection()
  3976. {
  3977. RefPtr<Selection> selection = GetSelection();
  3978. NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
  3979. return selection->RemoveAllRanges();
  3980. }
  3981. already_AddRefed<Element>
  3982. EditorBase::CreateHTMLContent(nsIAtom* aTag)
  3983. {
  3984. MOZ_ASSERT(aTag);
  3985. nsCOMPtr<nsIDocument> doc = GetDocument();
  3986. if (!doc) {
  3987. return nullptr;
  3988. }
  3989. // XXX Wallpaper over editor bug (editor tries to create elements with an
  3990. // empty nodename).
  3991. if (aTag == nsGkAtoms::_empty) {
  3992. NS_ERROR("Don't pass an empty tag to EditorBase::CreateHTMLContent, "
  3993. "check caller.");
  3994. return nullptr;
  3995. }
  3996. return doc->CreateElem(nsDependentAtomString(aTag), nullptr,
  3997. kNameSpaceID_XHTML);
  3998. }
  3999. NS_IMETHODIMP
  4000. EditorBase::SetAttributeOrEquivalent(nsIDOMElement* aElement,
  4001. const nsAString& aAttribute,
  4002. const nsAString& aValue,
  4003. bool aSuppressTransaction)
  4004. {
  4005. nsCOMPtr<Element> element = do_QueryInterface(aElement);
  4006. if (NS_WARN_IF(!element)) {
  4007. return NS_ERROR_NULL_POINTER;
  4008. }
  4009. nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
  4010. return SetAttributeOrEquivalent(element, attribute, aValue,
  4011. aSuppressTransaction);
  4012. }
  4013. NS_IMETHODIMP
  4014. EditorBase::RemoveAttributeOrEquivalent(nsIDOMElement* aElement,
  4015. const nsAString& aAttribute,
  4016. bool aSuppressTransaction)
  4017. {
  4018. nsCOMPtr<Element> element = do_QueryInterface(aElement);
  4019. if (NS_WARN_IF(!element)) {
  4020. return NS_ERROR_NULL_POINTER;
  4021. }
  4022. nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
  4023. return RemoveAttributeOrEquivalent(element, attribute, aSuppressTransaction);
  4024. }
  4025. nsresult
  4026. EditorBase::HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent)
  4027. {
  4028. // NOTE: When you change this method, you should also change:
  4029. // * editor/libeditor/tests/test_texteditor_keyevent_handling.html
  4030. // * editor/libeditor/tests/test_htmleditor_keyevent_handling.html
  4031. //
  4032. // And also when you add new key handling, you need to change the subclass's
  4033. // HandleKeyPressEvent()'s switch statement.
  4034. WidgetKeyboardEvent* nativeKeyEvent =
  4035. aKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
  4036. NS_ENSURE_TRUE(nativeKeyEvent, NS_ERROR_UNEXPECTED);
  4037. NS_ASSERTION(nativeKeyEvent->mMessage == eKeyPress,
  4038. "HandleKeyPressEvent gets non-keypress event");
  4039. // if we are readonly or disabled, then do nothing.
  4040. if (IsReadonly() || IsDisabled()) {
  4041. // consume backspace for disabled and readonly textfields, to prevent
  4042. // back in history, which could be confusing to users
  4043. if (nativeKeyEvent->mKeyCode == NS_VK_BACK) {
  4044. aKeyEvent->AsEvent()->PreventDefault();
  4045. }
  4046. return NS_OK;
  4047. }
  4048. switch (nativeKeyEvent->mKeyCode) {
  4049. case NS_VK_META:
  4050. case NS_VK_WIN:
  4051. case NS_VK_SHIFT:
  4052. case NS_VK_CONTROL:
  4053. case NS_VK_ALT:
  4054. aKeyEvent->AsEvent()->PreventDefault(); // consumed
  4055. return NS_OK;
  4056. case NS_VK_BACK:
  4057. if (nativeKeyEvent->IsControl() || nativeKeyEvent->IsAlt() ||
  4058. nativeKeyEvent->IsMeta() || nativeKeyEvent->IsOS()) {
  4059. return NS_OK;
  4060. }
  4061. DeleteSelection(nsIEditor::ePrevious, nsIEditor::eStrip);
  4062. aKeyEvent->AsEvent()->PreventDefault(); // consumed
  4063. return NS_OK;
  4064. case NS_VK_DELETE:
  4065. // on certain platforms (such as windows) the shift key
  4066. // modifies what delete does (cmd_cut in this case).
  4067. // bailing here to allow the keybindings to do the cut.
  4068. if (nativeKeyEvent->IsShift() || nativeKeyEvent->IsControl() ||
  4069. nativeKeyEvent->IsAlt() || nativeKeyEvent->IsMeta() ||
  4070. nativeKeyEvent->IsOS()) {
  4071. return NS_OK;
  4072. }
  4073. DeleteSelection(nsIEditor::eNext, nsIEditor::eStrip);
  4074. aKeyEvent->AsEvent()->PreventDefault(); // consumed
  4075. return NS_OK;
  4076. }
  4077. return NS_OK;
  4078. }
  4079. nsresult
  4080. EditorBase::HandleInlineSpellCheck(EditAction action,
  4081. Selection* aSelection,
  4082. nsIDOMNode* previousSelectedNode,
  4083. int32_t previousSelectedOffset,
  4084. nsIDOMNode* aStartNode,
  4085. int32_t aStartOffset,
  4086. nsIDOMNode* aEndNode,
  4087. int32_t aEndOffset)
  4088. {
  4089. // Have to cast action here because this method is from an IDL
  4090. return mInlineSpellChecker ? mInlineSpellChecker->SpellCheckAfterEditorChange(
  4091. (int32_t)action, aSelection,
  4092. previousSelectedNode, previousSelectedOffset,
  4093. aStartNode, aStartOffset, aEndNode,
  4094. aEndOffset)
  4095. : NS_OK;
  4096. }
  4097. already_AddRefed<nsIContent>
  4098. EditorBase::FindSelectionRoot(nsINode* aNode)
  4099. {
  4100. nsCOMPtr<nsIContent> rootContent = GetRoot();
  4101. return rootContent.forget();
  4102. }
  4103. nsresult
  4104. EditorBase::InitializeSelection(nsIDOMEventTarget* aFocusEventTarget)
  4105. {
  4106. nsCOMPtr<nsINode> targetNode = do_QueryInterface(aFocusEventTarget);
  4107. NS_ENSURE_TRUE(targetNode, NS_ERROR_INVALID_ARG);
  4108. nsCOMPtr<nsIContent> selectionRootContent = FindSelectionRoot(targetNode);
  4109. if (!selectionRootContent) {
  4110. return NS_OK;
  4111. }
  4112. bool isTargetDoc =
  4113. targetNode->NodeType() == nsIDOMNode::DOCUMENT_NODE &&
  4114. targetNode->HasFlag(NODE_IS_EDITABLE);
  4115. RefPtr<Selection> selection = GetSelection();
  4116. NS_ENSURE_STATE(selection);
  4117. nsCOMPtr<nsIPresShell> presShell = GetPresShell();
  4118. NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_INITIALIZED);
  4119. nsCOMPtr<nsISelectionController> selectionController =
  4120. GetSelectionController();
  4121. if (NS_WARN_IF(!selectionController)) {
  4122. return NS_ERROR_FAILURE;
  4123. }
  4124. // Init the caret
  4125. RefPtr<nsCaret> caret = presShell->GetCaret();
  4126. NS_ENSURE_TRUE(caret, NS_ERROR_UNEXPECTED);
  4127. caret->SetIgnoreUserModify(false);
  4128. caret->SetSelection(selection);
  4129. selectionController->SetCaretReadOnly(IsReadonly());
  4130. selectionController->SetCaretEnabled(true);
  4131. // Init selection
  4132. selectionController->SetDisplaySelection(
  4133. nsISelectionController::SELECTION_ON);
  4134. selectionController->SetSelectionFlags(
  4135. nsISelectionDisplay::DISPLAY_ALL);
  4136. selectionController->RepaintSelection(
  4137. nsISelectionController::SELECTION_NORMAL);
  4138. // If the computed selection root isn't root content, we should set it
  4139. // as selection ancestor limit. However, if that is root element, it means
  4140. // there is not limitation of the selection, then, we must set nullptr.
  4141. // NOTE: If we set a root element to the ancestor limit, some selection
  4142. // methods don't work fine.
  4143. if (selectionRootContent->GetParent()) {
  4144. selection->SetAncestorLimiter(selectionRootContent);
  4145. } else {
  4146. selection->SetAncestorLimiter(nullptr);
  4147. }
  4148. // XXX What case needs this?
  4149. if (isTargetDoc) {
  4150. int32_t rangeCount;
  4151. selection->GetRangeCount(&rangeCount);
  4152. if (!rangeCount) {
  4153. BeginningOfDocument();
  4154. }
  4155. }
  4156. // If there is composition when this is called, we may need to restore IME
  4157. // selection because if the editor is reframed, this already forgot IME
  4158. // selection and the transaction.
  4159. if (mComposition && !mIMETextNode && mIMETextLength) {
  4160. // We need to look for the new mIMETextNode from current selection.
  4161. // XXX If selection is changed during reframe, this doesn't work well!
  4162. nsRange* firstRange = selection->GetRangeAt(0);
  4163. NS_ENSURE_TRUE(firstRange, NS_ERROR_FAILURE);
  4164. nsCOMPtr<nsINode> startNode = firstRange->GetStartParent();
  4165. int32_t startOffset = firstRange->StartOffset();
  4166. FindBetterInsertionPoint(startNode, startOffset);
  4167. Text* textNode = startNode->GetAsText();
  4168. MOZ_ASSERT(textNode,
  4169. "There must be text node if mIMETextLength is larger than 0");
  4170. if (textNode) {
  4171. MOZ_ASSERT(textNode->Length() >= mIMETextOffset + mIMETextLength,
  4172. "The text node must be different from the old mIMETextNode");
  4173. CompositionTransaction::SetIMESelection(*this, textNode, mIMETextOffset,
  4174. mIMETextLength,
  4175. mComposition->GetRanges());
  4176. }
  4177. }
  4178. return NS_OK;
  4179. }
  4180. class RepaintSelectionRunner final : public Runnable {
  4181. public:
  4182. explicit RepaintSelectionRunner(nsISelectionController* aSelectionController)
  4183. : mSelectionController(aSelectionController)
  4184. {
  4185. }
  4186. NS_IMETHOD Run() override
  4187. {
  4188. mSelectionController->RepaintSelection(
  4189. nsISelectionController::SELECTION_NORMAL);
  4190. return NS_OK;
  4191. }
  4192. private:
  4193. nsCOMPtr<nsISelectionController> mSelectionController;
  4194. };
  4195. NS_IMETHODIMP
  4196. EditorBase::FinalizeSelection()
  4197. {
  4198. nsCOMPtr<nsISelectionController> selectionController =
  4199. GetSelectionController();
  4200. if (NS_WARN_IF(!selectionController)) {
  4201. return NS_ERROR_FAILURE;
  4202. }
  4203. RefPtr<Selection> selection = GetSelection();
  4204. NS_ENSURE_STATE(selection);
  4205. selection->SetAncestorLimiter(nullptr);
  4206. nsCOMPtr<nsIPresShell> presShell = GetPresShell();
  4207. NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_INITIALIZED);
  4208. selectionController->SetCaretEnabled(false);
  4209. nsFocusManager* fm = nsFocusManager::GetFocusManager();
  4210. NS_ENSURE_TRUE(fm, NS_ERROR_NOT_INITIALIZED);
  4211. fm->UpdateCaretForCaretBrowsingMode();
  4212. if (!HasIndependentSelection()) {
  4213. // If this editor doesn't have an independent selection, i.e., it must
  4214. // mean that it is an HTML editor, the selection controller is shared with
  4215. // presShell. So, even this editor loses focus, other part of the document
  4216. // may still have focus.
  4217. nsCOMPtr<nsIDocument> doc = GetDocument();
  4218. ErrorResult ret;
  4219. if (!doc || !doc->HasFocus(ret)) {
  4220. // If the document already lost focus, mark the selection as disabled.
  4221. selectionController->SetDisplaySelection(
  4222. nsISelectionController::SELECTION_DISABLED);
  4223. } else {
  4224. // Otherwise, mark selection as normal because outside of a
  4225. // contenteditable element should be selected with normal selection
  4226. // color after here.
  4227. selectionController->SetDisplaySelection(
  4228. nsISelectionController::SELECTION_ON);
  4229. }
  4230. } else if (IsFormWidget() || IsPasswordEditor() ||
  4231. IsReadonly() || IsDisabled() || IsInputFiltered()) {
  4232. // In <input> or <textarea>, the independent selection should be hidden
  4233. // while this editor doesn't have focus.
  4234. selectionController->SetDisplaySelection(
  4235. nsISelectionController::SELECTION_HIDDEN);
  4236. } else {
  4237. // Otherwise, although we're not sure how this case happens, the
  4238. // independent selection should be marked as disabled.
  4239. selectionController->SetDisplaySelection(
  4240. nsISelectionController::SELECTION_DISABLED);
  4241. }
  4242. // FinalizeSelection might be called from ContentRemoved even if selection
  4243. // isn't updated. So we need to call RepaintSelection after updated it.
  4244. nsContentUtils::AddScriptRunner(
  4245. new RepaintSelectionRunner(selectionController));
  4246. return NS_OK;
  4247. }
  4248. Element*
  4249. EditorBase::GetRoot()
  4250. {
  4251. if (!mRootElement) {
  4252. // Let GetRootElement() do the work
  4253. nsCOMPtr<nsIDOMElement> root;
  4254. GetRootElement(getter_AddRefs(root));
  4255. }
  4256. return mRootElement;
  4257. }
  4258. Element*
  4259. EditorBase::GetEditorRoot()
  4260. {
  4261. return GetRoot();
  4262. }
  4263. Element*
  4264. EditorBase::GetExposedRoot()
  4265. {
  4266. Element* rootElement = GetRoot();
  4267. // For plaintext editors, we need to ask the input/textarea element directly.
  4268. if (rootElement && rootElement->IsRootOfNativeAnonymousSubtree()) {
  4269. rootElement = rootElement->GetParent()->AsElement();
  4270. }
  4271. return rootElement;
  4272. }
  4273. nsresult
  4274. EditorBase::DetermineCurrentDirection()
  4275. {
  4276. // Get the current root direction from its frame
  4277. nsIContent* rootElement = GetExposedRoot();
  4278. NS_ENSURE_TRUE(rootElement, NS_ERROR_FAILURE);
  4279. // If we don't have an explicit direction, determine our direction
  4280. // from the content's direction
  4281. if (!(mFlags & (nsIPlaintextEditor::eEditorLeftToRight |
  4282. nsIPlaintextEditor::eEditorRightToLeft))) {
  4283. nsIFrame* frame = rootElement->GetPrimaryFrame();
  4284. NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
  4285. // Set the flag here, to enable us to use the same code path below.
  4286. // It will be flipped before returning from the function.
  4287. if (frame->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
  4288. mFlags |= nsIPlaintextEditor::eEditorRightToLeft;
  4289. } else {
  4290. mFlags |= nsIPlaintextEditor::eEditorLeftToRight;
  4291. }
  4292. }
  4293. return NS_OK;
  4294. }
  4295. NS_IMETHODIMP
  4296. EditorBase::SwitchTextDirection()
  4297. {
  4298. // Get the current root direction from its frame
  4299. nsIContent* rootElement = GetExposedRoot();
  4300. nsresult rv = DetermineCurrentDirection();
  4301. NS_ENSURE_SUCCESS(rv, rv);
  4302. // Apply the opposite direction
  4303. if (mFlags & nsIPlaintextEditor::eEditorRightToLeft) {
  4304. NS_ASSERTION(!(mFlags & nsIPlaintextEditor::eEditorLeftToRight),
  4305. "Unexpected mutually exclusive flag");
  4306. mFlags &= ~nsIPlaintextEditor::eEditorRightToLeft;
  4307. mFlags |= nsIPlaintextEditor::eEditorLeftToRight;
  4308. rv = rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::dir, NS_LITERAL_STRING("ltr"), true);
  4309. } else if (mFlags & nsIPlaintextEditor::eEditorLeftToRight) {
  4310. NS_ASSERTION(!(mFlags & nsIPlaintextEditor::eEditorRightToLeft),
  4311. "Unexpected mutually exclusive flag");
  4312. mFlags |= nsIPlaintextEditor::eEditorRightToLeft;
  4313. mFlags &= ~nsIPlaintextEditor::eEditorLeftToRight;
  4314. rv = rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::dir, NS_LITERAL_STRING("rtl"), true);
  4315. }
  4316. if (NS_SUCCEEDED(rv)) {
  4317. FireInputEvent();
  4318. }
  4319. return rv;
  4320. }
  4321. void
  4322. EditorBase::SwitchTextDirectionTo(uint32_t aDirection)
  4323. {
  4324. // Get the current root direction from its frame
  4325. nsIContent* rootElement = GetExposedRoot();
  4326. nsresult rv = DetermineCurrentDirection();
  4327. NS_ENSURE_SUCCESS_VOID(rv);
  4328. // Apply the requested direction
  4329. if (aDirection == nsIPlaintextEditor::eEditorLeftToRight &&
  4330. (mFlags & nsIPlaintextEditor::eEditorRightToLeft)) {
  4331. NS_ASSERTION(!(mFlags & nsIPlaintextEditor::eEditorLeftToRight),
  4332. "Unexpected mutually exclusive flag");
  4333. mFlags &= ~nsIPlaintextEditor::eEditorRightToLeft;
  4334. mFlags |= nsIPlaintextEditor::eEditorLeftToRight;
  4335. rv = rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::dir, NS_LITERAL_STRING("ltr"), true);
  4336. } else if (aDirection == nsIPlaintextEditor::eEditorRightToLeft &&
  4337. (mFlags & nsIPlaintextEditor::eEditorLeftToRight)) {
  4338. NS_ASSERTION(!(mFlags & nsIPlaintextEditor::eEditorRightToLeft),
  4339. "Unexpected mutually exclusive flag");
  4340. mFlags |= nsIPlaintextEditor::eEditorRightToLeft;
  4341. mFlags &= ~nsIPlaintextEditor::eEditorLeftToRight;
  4342. rv = rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::dir, NS_LITERAL_STRING("rtl"), true);
  4343. }
  4344. if (NS_SUCCEEDED(rv)) {
  4345. FireInputEvent();
  4346. }
  4347. }
  4348. #if DEBUG_JOE
  4349. void
  4350. EditorBase::DumpNode(nsIDOMNode* aNode,
  4351. int32_t indent)
  4352. {
  4353. for (int32_t i = 0; i < indent; i++) {
  4354. printf(" ");
  4355. }
  4356. nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
  4357. nsCOMPtr<nsIDOMDocumentFragment> docfrag = do_QueryInterface(aNode);
  4358. if (element || docfrag) {
  4359. if (element) {
  4360. nsAutoString tag;
  4361. element->GetTagName(tag);
  4362. printf("<%s>\n", NS_LossyConvertUTF16toASCII(tag).get());
  4363. } else {
  4364. printf("<document fragment>\n");
  4365. }
  4366. nsCOMPtr<nsIDOMNodeList> childList;
  4367. aNode->GetChildNodes(getter_AddRefs(childList));
  4368. NS_ENSURE_TRUE(childList, NS_ERROR_NULL_POINTER);
  4369. uint32_t numChildren;
  4370. childList->GetLength(&numChildren);
  4371. nsCOMPtr<nsIDOMNode> child, tmp;
  4372. aNode->GetFirstChild(getter_AddRefs(child));
  4373. for (uint32_t i = 0; i < numChildren; i++) {
  4374. DumpNode(child, indent + 1);
  4375. child->GetNextSibling(getter_AddRefs(tmp));
  4376. child = tmp;
  4377. }
  4378. } else if (IsTextNode(aNode)) {
  4379. nsCOMPtr<nsIDOMCharacterData> textNode = do_QueryInterface(aNode);
  4380. nsAutoString str;
  4381. textNode->GetData(str);
  4382. nsAutoCString cstr;
  4383. LossyCopyUTF16toASCII(str, cstr);
  4384. cstr.ReplaceChar('\n', ' ');
  4385. printf("<textnode> %s\n", cstr.get());
  4386. }
  4387. }
  4388. #endif
  4389. bool
  4390. EditorBase::IsModifiableNode(nsIDOMNode* aNode)
  4391. {
  4392. return true;
  4393. }
  4394. bool
  4395. EditorBase::IsModifiableNode(nsINode* aNode)
  4396. {
  4397. return true;
  4398. }
  4399. already_AddRefed<nsIContent>
  4400. EditorBase::GetFocusedContent()
  4401. {
  4402. nsCOMPtr<nsIDOMEventTarget> piTarget = GetDOMEventTarget();
  4403. if (!piTarget) {
  4404. return nullptr;
  4405. }
  4406. nsFocusManager* fm = nsFocusManager::GetFocusManager();
  4407. NS_ENSURE_TRUE(fm, nullptr);
  4408. nsCOMPtr<nsIContent> content = fm->GetFocusedContent();
  4409. return SameCOMIdentity(content, piTarget) ? content.forget() : nullptr;
  4410. }
  4411. already_AddRefed<nsIContent>
  4412. EditorBase::GetFocusedContentForIME()
  4413. {
  4414. return GetFocusedContent();
  4415. }
  4416. bool
  4417. EditorBase::IsActiveInDOMWindow()
  4418. {
  4419. nsCOMPtr<nsIDOMEventTarget> piTarget = GetDOMEventTarget();
  4420. if (!piTarget) {
  4421. return false;
  4422. }
  4423. nsFocusManager* fm = nsFocusManager::GetFocusManager();
  4424. NS_ENSURE_TRUE(fm, false);
  4425. nsCOMPtr<nsIDocument> document = GetDocument();
  4426. if (NS_WARN_IF(!document)) {
  4427. return false;
  4428. }
  4429. nsPIDOMWindowOuter* ourWindow = document->GetWindow();
  4430. nsCOMPtr<nsPIDOMWindowOuter> win;
  4431. nsIContent* content =
  4432. nsFocusManager::GetFocusedDescendant(ourWindow, false,
  4433. getter_AddRefs(win));
  4434. return SameCOMIdentity(content, piTarget);
  4435. }
  4436. bool
  4437. EditorBase::IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent)
  4438. {
  4439. // If the event is trusted, the event should always cause input.
  4440. if (NS_WARN_IF(!aGUIEvent)) {
  4441. return false;
  4442. }
  4443. // If this is dispatched by using cordinates but this editor doesn't have
  4444. // focus, we shouldn't handle it.
  4445. if (aGUIEvent->IsUsingCoordinates()) {
  4446. nsCOMPtr<nsIContent> focusedContent = GetFocusedContent();
  4447. if (!focusedContent) {
  4448. return false;
  4449. }
  4450. }
  4451. // If a composition event isn't dispatched via widget, we need to ignore them
  4452. // since they cannot be managed by TextComposition. E.g., the event was
  4453. // created by chrome JS.
  4454. // Note that if we allow to handle such events, editor may be confused by
  4455. // strange event order.
  4456. bool needsWidget = false;
  4457. switch (aGUIEvent->mMessage) {
  4458. case eUnidentifiedEvent:
  4459. // If events are not created with proper event interface, their message
  4460. // are initialized with eUnidentifiedEvent. Let's ignore such event.
  4461. return false;
  4462. case eCompositionStart:
  4463. case eCompositionEnd:
  4464. case eCompositionUpdate:
  4465. case eCompositionChange:
  4466. case eCompositionCommitAsIs:
  4467. // Don't allow composition events whose internal event are not
  4468. // WidgetCompositionEvent.
  4469. if (!aGUIEvent->AsCompositionEvent()) {
  4470. return false;
  4471. }
  4472. needsWidget = true;
  4473. break;
  4474. default:
  4475. break;
  4476. }
  4477. if (needsWidget && !aGUIEvent->mWidget) {
  4478. return false;
  4479. }
  4480. // Accept all trusted events.
  4481. if (aGUIEvent->IsTrusted()) {
  4482. return true;
  4483. }
  4484. // Ignore untrusted mouse event.
  4485. // XXX Why are we handling other untrusted input events?
  4486. if (aGUIEvent->AsMouseEventBase()) {
  4487. return false;
  4488. }
  4489. // Otherwise, we shouldn't handle any input events when we're not an active
  4490. // element of the DOM window.
  4491. return IsActiveInDOMWindow();
  4492. }
  4493. void
  4494. EditorBase::OnFocus(nsIDOMEventTarget* aFocusEventTarget)
  4495. {
  4496. InitializeSelection(aFocusEventTarget);
  4497. if (mInlineSpellChecker) {
  4498. mInlineSpellChecker->UpdateCurrentDictionary();
  4499. }
  4500. }
  4501. NS_IMETHODIMP
  4502. EditorBase::GetSuppressDispatchingInputEvent(bool* aSuppressed)
  4503. {
  4504. NS_ENSURE_ARG_POINTER(aSuppressed);
  4505. *aSuppressed = !mDispatchInputEvent;
  4506. return NS_OK;
  4507. }
  4508. NS_IMETHODIMP
  4509. EditorBase::SetSuppressDispatchingInputEvent(bool aSuppress)
  4510. {
  4511. mDispatchInputEvent = !aSuppress;
  4512. return NS_OK;
  4513. }
  4514. NS_IMETHODIMP
  4515. EditorBase::GetIsInEditAction(bool* aIsInEditAction)
  4516. {
  4517. MOZ_ASSERT(aIsInEditAction, "aIsInEditAction must not be null");
  4518. *aIsInEditAction = mIsInEditAction;
  4519. return NS_OK;
  4520. }
  4521. int32_t
  4522. EditorBase::GetIMESelectionStartOffsetIn(nsINode* aTextNode)
  4523. {
  4524. MOZ_ASSERT(aTextNode, "aTextNode must not be nullptr");
  4525. nsCOMPtr<nsISelectionController> selectionController =
  4526. GetSelectionController();
  4527. if (NS_WARN_IF(!selectionController)) {
  4528. return -1;
  4529. }
  4530. uint32_t minOffset = UINT32_MAX;
  4531. static const SelectionType kIMESelectionTypes[] = {
  4532. SelectionType::eIMERawClause,
  4533. SelectionType::eIMESelectedRawClause,
  4534. SelectionType::eIMEConvertedClause,
  4535. SelectionType::eIMESelectedClause
  4536. };
  4537. for (auto selectionType : kIMESelectionTypes) {
  4538. RefPtr<Selection> selection = GetSelection(selectionType);
  4539. if (!selection) {
  4540. continue;
  4541. }
  4542. for (uint32_t i = 0; i < selection->RangeCount(); i++) {
  4543. RefPtr<nsRange> range = selection->GetRangeAt(i);
  4544. if (NS_WARN_IF(!range)) {
  4545. continue;
  4546. }
  4547. if (NS_WARN_IF(range->GetStartParent() != aTextNode)) {
  4548. // ignore the start offset...
  4549. } else {
  4550. minOffset = std::min(minOffset, range->StartOffset());
  4551. }
  4552. if (NS_WARN_IF(range->GetEndParent() != aTextNode)) {
  4553. // ignore the end offset...
  4554. } else {
  4555. minOffset = std::min(minOffset, range->EndOffset());
  4556. }
  4557. }
  4558. }
  4559. return minOffset < INT32_MAX ? minOffset : -1;
  4560. }
  4561. void
  4562. EditorBase::HideCaret(bool aHide)
  4563. {
  4564. if (mHidingCaret == aHide) {
  4565. return;
  4566. }
  4567. nsCOMPtr<nsIPresShell> presShell = GetPresShell();
  4568. NS_ENSURE_TRUE_VOID(presShell);
  4569. RefPtr<nsCaret> caret = presShell->GetCaret();
  4570. NS_ENSURE_TRUE_VOID(caret);
  4571. mHidingCaret = aHide;
  4572. if (aHide) {
  4573. caret->AddForceHide();
  4574. } else {
  4575. caret->RemoveForceHide();
  4576. }
  4577. }
  4578. } // namespace mozilla