Opera 12.15 Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

OpDocumentEdit.h 109KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186
  1. /* -*- Mode: c++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*-
  2. *
  3. * Copyright (C) 1995-2011 Opera Software ASA. All rights reserved.
  4. *
  5. * This file is part of the Opera web browser. It may not be distributed
  6. * under any circumstances.
  7. */
  8. #ifndef OP_DOCUMENTEDIT_H
  9. #define OP_DOCUMENTEDIT_H
  10. #ifdef DOCUMENT_EDIT_SUPPORT
  11. #ifdef _DEBUG
  12. #define _DOCEDIT_DEBUG
  13. #endif
  14. #ifdef INTERNAL_SPELLCHECK_SUPPORT
  15. #include "modules/spellchecker/opspellcheckerapi.h"
  16. #endif //INTERNAL_SPELLCHECK_SUPPORT
  17. #include "modules/documentedit/OpDocumentEditUtils.h"
  18. #include "modules/widgets/OpWidget.h"
  19. #include "modules/documentedit/OpDocumentEditUndoRedo.h"
  20. #include "modules/documentedit/OpDocumentEditLayoutModifier.h"
  21. #include "modules/logdoc/html.h"
  22. #include "modules/logdoc/selectionpoint.h"
  23. #include "modules/layout/box/box.h"
  24. #include "modules/layout/traverse/traverse.h"
  25. #include "modules/hardcore/timer/optimer.h"
  26. #include "modules/doc/caret_manager.h"
  27. #include "modules/doc/caret_painter.h"
  28. #include "modules/logdoc/elementref.h"
  29. class OpDocumentEdit;
  30. #ifdef USE_OP_CLIPBOARD
  31. #include "modules/dragdrop/clipboard_manager.h"
  32. #endif // USE_OP_CLIPBOARD
  33. /** Used when inserting html to create empty textelements and prevent them from being removed by OpDocumentEdit::Tidy.
  34. The dummycharacter will be removed after insertion. */
  35. #ifdef _DOCEDIT_DEBUG
  36. #define DEBUG_CHECKER(check_begin_count) OpDocumentEditDebugChecker __debug_checker__dbg__ = OpDocumentEditDebugChecker(m_edit,this,check_begin_count,FALSE)
  37. #define DEBUG_CHECKER_STATIC() OpDocumentEditDebugChecker __debug_checker__dbg__ = OpDocumentEditDebugChecker(NULL,NULL,FALSE,TRUE)
  38. #define DEBUG_CHECKER_CONSTRUCTOR() DEBUG_CHECKER_STATIC()
  39. #define document_edit_dummy_str UNI_L("*")
  40. #else
  41. #define DEBUG_CHECKER(x)
  42. #define DEBUG_CHECKER_STATIC()
  43. #define DEBUG_CHECKER_CONSTRUCTOR()
  44. #define document_edit_dummy_str UNI_L("\xFEFF") // zero width nonbreaking space
  45. #endif
  46. /** Define to enable <p> for linebreaks instead of <br> as default. (<br> still available for shift+enter) */
  47. #define DOCUMENT_EDIT_USE_PARAGRAPH_BREAK
  48. /** Styling added without a selection is placed in a list of pending styles, to be added when text is inserted if caret hasn't moved. */
  49. struct OP_DOCUMENT_EDIT_PENDING_STYLES : public Link {
  50. HTML_Element* helm;
  51. };
  52. #define ATTR_DOCEDIT_AUTO_INSERTED Markup::DOCEDA_AUTO_INSERTED ///< Inserted automatically and should be removed automatically when not needed.
  53. enum OP_DOCUMENT_EDIT_COMMAND {
  54. OP_DOCUMENT_EDIT_COMMAND_USECSS,
  55. OP_DOCUMENT_EDIT_COMMAND_STYLEWITHCSS,
  56. OP_DOCUMENT_EDIT_COMMAND_READONLY,
  57. OP_DOCUMENT_EDIT_COMMAND_CONTENTREADONLY,
  58. OP_DOCUMENT_EDIT_COMMAND_HILITECOLOR,
  59. OP_DOCUMENT_EDIT_COMMAND_BACKCOLOR,
  60. OP_DOCUMENT_EDIT_COMMAND_BOLD,
  61. OP_DOCUMENT_EDIT_COMMAND_COPY,
  62. OP_DOCUMENT_EDIT_COMMAND_CREATELINK,
  63. OP_DOCUMENT_EDIT_COMMAND_CUT,
  64. OP_DOCUMENT_EDIT_COMMAND_DELETE,
  65. OP_DOCUMENT_EDIT_COMMAND_FONTNAME,
  66. OP_DOCUMENT_EDIT_COMMAND_FONTSIZE,
  67. OP_DOCUMENT_EDIT_COMMAND_FORECOLOR,
  68. OP_DOCUMENT_EDIT_COMMAND_FORMATBLOCK,
  69. // OP_DOCUMENT_EDIT_COMMAND_HEADING,
  70. OP_DOCUMENT_EDIT_COMMAND_INDENT,
  71. OP_DOCUMENT_EDIT_COMMAND_INSERTHORIZONTALRULE,
  72. OP_DOCUMENT_EDIT_COMMAND_INSERTHTML,
  73. OP_DOCUMENT_EDIT_COMMAND_INSERTIMAGE,
  74. OP_DOCUMENT_EDIT_COMMAND_INSERTORDEREDLIST,
  75. OP_DOCUMENT_EDIT_COMMAND_INSERTUNORDEREDLIST,
  76. OP_DOCUMENT_EDIT_COMMAND_INSERTPARAGRAPH,
  77. OP_DOCUMENT_EDIT_COMMAND_ITALIC,
  78. OP_DOCUMENT_EDIT_COMMAND_JUSTIFYCENTER,
  79. OP_DOCUMENT_EDIT_COMMAND_JUSTIFYFULL,
  80. OP_DOCUMENT_EDIT_COMMAND_JUSTIFYLEFT,
  81. OP_DOCUMENT_EDIT_COMMAND_JUSTIFYRIGHT,
  82. OP_DOCUMENT_EDIT_COMMAND_OUTDENT,
  83. OP_DOCUMENT_EDIT_COMMAND_PASTE,
  84. OP_DOCUMENT_EDIT_COMMAND_REDO,
  85. OP_DOCUMENT_EDIT_COMMAND_REMOVEFORMAT,
  86. OP_DOCUMENT_EDIT_COMMAND_SELECTALL,
  87. #ifdef SPELLCHECK_COMMAND_SUPPORT
  88. OP_DOCUMENT_EDIT_COMMAND_SPELLCHECK,
  89. OP_DOCUMENT_EDIT_COMMAND_SPELLCHECK_BLOCKING,
  90. OP_DOCUMENT_EDIT_COMMAND_SPELLCHECK_DEBUG,
  91. OP_DOCUMENT_EDIT_COMMAND_SPELLCHECK_HAS_MISSPELLING,
  92. #endif
  93. OP_DOCUMENT_EDIT_COMMAND_STRIKETHROUGH,
  94. OP_DOCUMENT_EDIT_COMMAND_SUBSCRIPT,
  95. OP_DOCUMENT_EDIT_COMMAND_SUPERSCRIPT,
  96. OP_DOCUMENT_EDIT_COMMAND_DECREASEFONTSIZE,
  97. OP_DOCUMENT_EDIT_COMMAND_INCREASEFONTSIZE,
  98. OP_DOCUMENT_EDIT_COMMAND_UNDERLINE,
  99. OP_DOCUMENT_EDIT_COMMAND_UNDO,
  100. OP_DOCUMENT_EDIT_COMMAND_UNLINK,
  101. OP_DOCUMENT_EDIT_COMMAND_UNSELECT,
  102. OP_DOCUMENT_EDIT_COMMAND_DEFAULT_BLOCK,
  103. OP_DOCUMENT_EDIT_COMMAND_UNKNOWN
  104. };
  105. /**
  106. * This is a class that represents how we did selection points before converting to the
  107. * web official representation.
  108. *
  109. * TEXT + offset means the same thing as in normal boundary points.
  110. * ELEMENT + offset must have offset 0 or 1 and means before or after ELEMENT.
  111. */
  112. class OldStyleTextSelectionPoint
  113. {
  114. private:
  115. HTML_Element* m_element;
  116. int m_offset;
  117. BOOL m_bind_forward;
  118. public:
  119. OldStyleTextSelectionPoint() : m_element(NULL), m_offset(0), m_bind_forward(FALSE) {}
  120. OldStyleTextSelectionPoint(HTML_Element* elm, int offset) : m_element(elm), m_offset(offset), m_bind_forward(FALSE) {}
  121. void SetLogicalPosition(HTML_Element* elm, int offset) { m_element = elm; m_offset = offset; m_bind_forward = FALSE; }
  122. /**
  123. * If a selection point has multiple visual positions (BiDi and line breaks
  124. * make that happen), then this flag says which is preferred in rendering.
  125. *
  126. * For a line break, if the rendering should be on the previous line, the
  127. * direction should be BIND_BACKWARD. If the rendering should be at the start
  128. * of the new line, then the direction should be BIND_FORWARD.
  129. *
  130. * @param[in] direction The new bind direction.
  131. */
  132. void SetBindDirection(SelectionBoundaryPoint::BindDirection direction) { m_bind_forward = (direction == SelectionBoundaryPoint::BIND_FORWARD); }
  133. /**
  134. * If a selection point has multiple visual positions (BiDi and line breaks
  135. * make that happen), then this flag says which is preferred in rendering.
  136. *
  137. * @returns The direction. The default is BIND_BACKWARD.
  138. */
  139. SelectionBoundaryPoint::BindDirection GetBindDirection() const { return m_bind_forward ? SelectionBoundaryPoint::BIND_FORWARD : SelectionBoundaryPoint::BIND_BACKWARD; }
  140. HTML_Element* GetElement() const { return m_element; }
  141. int GetOffset() const { return m_offset; }
  142. int GetElementCharacterOffset() const { return m_offset; }
  143. BOOL Precedes(const OldStyleTextSelectionPoint& other_selection) const
  144. {
  145. return GetElement() == other_selection.GetElement() ?
  146. m_offset < other_selection.m_offset :
  147. GetElement()->Precedes(other_selection.GetElement());
  148. }
  149. static SelectionBoundaryPoint ConvertFromOldStyleSelectionPoint(const OldStyleTextSelectionPoint& point);
  150. };
  151. /** OpDocumentEditSelection
  152. Main tasks:
  153. 1. Wrapper/helper for TextSelection in the document.
  154. 2. Can return the selected text as plain text, or as HTML-code (with nearest shared ancestor of start and stop as root).
  155. 3. Can remove the selected elements (and parts of the textelements).
  156. */
  157. class OpDocumentEditSelection
  158. #ifdef _DOCEDIT_DEBUG
  159. : public OpDocumentEditDebugCheckerObject
  160. #endif
  161. {
  162. public:
  163. OpDocumentEditSelection(OpDocumentEdit *edit);
  164. /**
  165. * Sets the HTML_Document selection for the FramesDocument associated this documentedit according to the selection end points.
  166. * @parm startpoint The start or end point of the new selection, order doesn't matter infact.
  167. * @parm startpoint The start or end point of the new selection, order doesn't matter infact.
  168. */
  169. void Select(OldStyleTextSelectionPoint *startpoint, OldStyleTextSelectionPoint *endpoint, BOOL place_caret_at_endpoint = TRUE);
  170. /**
  171. * Sets the HTML_Document selection to the end-points between the current caret-place and (from_helm, from_ofs).
  172. * This is NOT the dom-type of endpoint-sematics with parent-element + offset==child elements before selection end-point, see below.
  173. * @parm from_helm The other selection end-point (in addition to the caret-place), must be an element with replaced
  174. * content, an HE_BR or an HE_TEXT element.
  175. * @parm from_ofs Offset from the beginning of the element, for HE_TEXT elements is this the number of characters BEFORE the
  176. * selection end-point. For all other elements can the offset be either 0 or 1, 0 means that the end-point is "just before" the
  177. * element and 1 "just after".
  178. */
  179. void SelectToCaret(HTML_Element* from_helm, INT32 from_ofs);
  180. /**
  181. * Selects all content in the HTML_Document, OR if the caret is inside an content-editable element, all content
  182. * in that element.
  183. */
  184. void SelectAll();
  185. /** Clears the selection in the HTML_Document. */
  186. void SelectNothing();
  187. /**
  188. * Returns whether the HTML_Document has a non-empty selection or not.
  189. * @return FALSE if the HTML_Document doesn't have any text-selection or if the selection is empty, that is, if the start
  190. * and end end-points points at the same element and has the same "element character offset" (the same logical position).
  191. */
  192. BOOL HasContent();
  193. /**
  194. * Removes the content selected in the HTML_Document.
  195. * @parm aggressive If aggressive is TRUE, the containingelement may be removed if it gets empty and the caret may snap to nearest word.
  196. * If the selection should be replaced with something new, it's a good idea to use FALSE.
  197. */
  198. void RemoveContent(BOOL aggressive = TRUE);
  199. /**
  200. * Removes the content between the two "end-points" (start_elm, start_ofs) and (stop_elm, stop_ofs).
  201. * End-points are represented in the same manner as for SelectToCaret, but all types of elements could be start_elm or stop_elm.
  202. * @parm aggressive If aggressive is TRUE, the containingelement may be removed if it gets empty and the caret may snap to nearest word.
  203. * If the selection should be replaced with something new, it's a good idea to use FALSE.
  204. * @parm start_elm Start element of the selection that should be removed, MUST precede stop_elm.
  205. * @parm stop_elm Stop element of the selection that should be removed, MUST be preceded by start_elm.
  206. * @parm start_ofs Start "end-point" in start_elm.
  207. * @parm start_ofs Stop "end-point" in stop_elm.
  208. * @param change_caret_pos If FALSE a content removal does not change the caret's position.
  209. */
  210. void RemoveContent(BOOL aggressive, HTML_Element* start_elm, HTML_Element* stop_elm, INT32 start_ofs, INT32 stop_ofs, BOOL change_caret_pos = TRUE);
  211. /**
  212. * Retrieves the HTML_Document's selection in text form. This does only include selected text in selected HE_TEXT elements (no tags and such).
  213. * @return Error-code of the operation.
  214. * @parm text OpString object to output the text to, will be empty after return if selection was empty or non-existing.
  215. */
  216. OP_STATUS GetText(OpString& text);
  217. /**
  218. * Retrieves the HTML_Document's selection in html text form. The nearest shared container will act as root of the result, except
  219. * for special-case when include_style_containers == TRUE.
  220. * @return Error-code of the operation.
  221. * @parm text OpString object to output the text to, will be empty after return if selection was empty or non-existing.
  222. * @parm include_style_containers If include_style_containers == TRUE, the will the root of the result be adjusted upwards in the
  223. * tree so it's NOT an HE_OL, HE_UL or HE_PRE element, this if for keeping the "style" of the selected content.
  224. */
  225. OP_STATUS GetTextHTML(OpString& text, BOOL include_style_containers = TRUE);
  226. /**
  227. * Retrieves the selection between the two "end-points" (start_elm, start_ofs) and (stop_elm, stop_ofs) in html
  228. * text form. The nearest shared container will act as root of the result, except for special-case when include_style_containers == TRUE.
  229. * @return Error-code of the operation.
  230. * @parm text OpString object to output the text to, will be empty after return if selection was empty or non-existing.
  231. * @parm include_style_containers If include_style_containers == TRUE, the will the root of the result be adjusted upwards in the
  232. * tree so it's NOT an HE_OL, HE_UL or HE_PRE element, this if for keeping the "style" of the selected content.
  233. */
  234. OP_STATUS GetTextHTML(OpString& text, HTML_Element* start_elm, HTML_Element* stop_elm, INT32 start_ofs, INT32 stop_ofs, BOOL include_style_containers = TRUE);
  235. /** Returns the start element of the HTML_Document's selection (NOT DOM-style with, parent-element and child-element offset) */
  236. HTML_Element* GetStartElement(BOOL only_actual_element = FALSE);
  237. /** Returns the stop element of the HTML_Document's selection (NOT DOM-style with, parent-element and child-element offset) */
  238. HTML_Element* GetStopElement(BOOL only_actual_element = FALSE);
  239. /** Returns the start offset of the HTML_Document's selection (NOT DOM-style with, parent-element and child-element offset) */
  240. INT32 GetStartOfs();
  241. /** Returns the end offset of the HTML_Document's selection (NOT DOM-style with, parent-element and child-element offset) */
  242. INT32 GetStopOfs();
  243. /** Returns TRUE if the end point is the focus point and FALSE if the start point is the focus point. */
  244. BOOL IsEndPointFocusPoint();
  245. private:
  246. BOOL GetRemoveStopElm(BOOL aggressive, HTML_Element *start_elm, int start_ofs, HTML_Element *stop_elm, int stop_ofs);
  247. public:
  248. OpDocumentEdit* m_edit;
  249. };
  250. /** OpDocumentEditCaret
  251. It make use of the SelectionUpdateObject traversal object to find out the visual position of the caret. Same as selection endpoints.
  252. The caret position is based on a HTML_Element, a offset, and the BOOL m_prefer_first.
  253. For textelements, the offset is the character offset.
  254. For other elements, the offset is either 0 or 1 (left or right to the element).
  255. The offset is a logical position, so we need m_prefer_first to tell if it should stick to the first or second word that has the offset.
  256. FIX: The DOM API always use the element as parent element, and offset as child offset. That means same as our current behaviour for text, but
  257. with other elements we have a different behaviour. This is worked around in the doc/DOM code. But we should change this here at some point.
  258. */
  259. class OpDocumentEditCaret
  260. #ifdef _DOCEDIT_DEBUG
  261. : public OpDocumentEditDebugCheckerObject
  262. #endif
  263. {
  264. public:
  265. OpDocumentEditCaret(OpDocumentEdit *edit);
  266. /**
  267. * Initialization function for the OpDocumentEditCaret.
  268. * @return Error status code...
  269. * @parm create_line_if_empty If TRUE will a new empty text-element be created for the caret if no valid caret-pos exists.
  270. * @parm edit_root An editable root element in the document where the caret is "encouraged" to be placed. If edit_root is
  271. * NULL will body be used if it's editable (designMode=='on' or body is content editable), or a "parent canditate" which
  272. * has previously been found will be used.
  273. * @parm only_create_line_if_body If TRUE and create_line_if_empty is TRUE, then will a new line only be created if there
  274. * is a body element that could be an ancestor for the new line.
  275. */
  276. OP_STATUS Init(BOOL create_line_if_empty, HTML_Element* edit_root = NULL, BOOL only_create_line_if_body = FALSE);
  277. /** Returns FALSE if the current position, which has been updated with UpdatePos is not valid (inside something collapsed) */
  278. BOOL IsValid();
  279. /**
  280. * Tries to "snap" the current caret-position to something valid (if it's not already valid).
  281. * Returns FALSE if we still don't have a valid position.
  282. */
  283. BOOL SetToValidPos() { return GetCaretManager()->SetToValidPos(); }
  284. /** Check if the caret is at the first or last insertionpoint in its element (it might still be collapsed data before/after though). */
  285. BOOL IsAtStartOrEndOfElement(BOOL start);
  286. /** Check if the caret is at the first or last insertionpoint in its container (it might still be collapsed data before/after though).
  287. is_at_edge_to_child_container will be set to TRUE if it's at the start/end before/after a child block within the block. */
  288. BOOL IsAtStartOrEndOfBlock(BOOL start, BOOL *is_at_edge_to_child_container = NULL);
  289. /**
  290. * When the caret is placed somewhere else should the current caret-element, which should be an empty text-element,
  291. * be removed if it's then still an empty text-element and no changes has been made to the logical tree from within
  292. * documentedit. This is for creating temporary caret-positions e.g. to permitt the user to navigate below a HR element
  293. * at the bottom of the document.
  294. */
  295. void SetRemoveWhenMoveIfUntouched();
  296. /**
  297. * If the current caret-element is a temporary element created as described in the description of SetRemoveWhenMoveIfUntouched, then
  298. * will that element be removed if it's not == new_helm and the temporary element is still "untouched".
  299. */
  300. void DeleteRemoveWhenMoveIfUntouched(HTML_Element *new_helm);
  301. /** Returns TRUE if the caret is in an "untouched" temporary caret-element as described in the description of SetRemoveWhenMoveIfUntouched */
  302. BOOL IsAtRemoveWhenMoveIfUntounced();
  303. /** Makes the current possible temporary caret element "permanent", see description of SetRemoveWhenMoveIfUntouched */
  304. void SetNotRemoveWhenMoveIfUntouched() { m_remove_when_move_elm = NULL; }
  305. /**
  306. * Creates an empty text element under parent as a successor of after_me without making the possible temporary caret-element,
  307. * as described in the description of SetRemoveWhenMoveIfUntouched "permanent".
  308. * @parm parent The parent for the text-element, can be NULL if after_me != NULL.
  309. * @parm after_me The element which the text-element should be successor of, if after_me == NULL, the text-element
  310. * will be first child of parent.
  311. * @param text If TRUE a text element will be created instead of <br>.
  312. */
  313. HTML_Element* CreateTemporaryCaretHelm(HTML_Element *parent, HTML_Element *after_me = NULL, BOOL text = FALSE);
  314. /**
  315. * Move the caret forward or back in the document in the logical position
  316. * @parm forward If TRUE, tries to move one step forward, else backwards...
  317. * @parm word If TRUE, we'll move to the next word-boundry.
  318. */
  319. void Move(BOOL forward, BOOL word) { GetCaretManager()->Move(forward, word); }
  320. /**
  321. * Create room for a caret by creating the necessary placeholder elements and then position
  322. * the caret there.
  323. *
  324. * @param new_helm The element that would be the place for the caret if there was room.
  325. * @param new_ofs The offset (old style selection) of the element for the caret.
  326. * @param forward Whether we reached the current position going forwards or backwards.
  327. */
  328. void MakeRoomAndMoveCaret(HTML_Element* new_helm, int new_ofs, BOOL forward);
  329. /**
  330. * Move the caret forward or back in the document in the logical position, but instead of wrapping to next
  331. * or previous line, it will search for the visually closest editable element in the given direction.
  332. * @parm forward If TRUE, tries to move one step forward, else backwards...
  333. */
  334. void MoveSpatial(BOOL forward);
  335. /**
  336. * Works like MoveSpatial but tries to move the caret visually up or down in the document.
  337. * @parm down If TRUE, tries to move one line down, else up...
  338. */
  339. void MoveSpatialVertical(BOOL down);
  340. /**
  341. * Places the caret on the specified end-point.
  342. * @parm point The desired caret-position, if the element in point is not valid for putting the caret on, it tries
  343. * to use the DOM-semantics and use the element as parent and the "element character offset" as child-offset.
  344. */
  345. void Place(const SelectionBoundaryPoint& point);
  346. void Place(INT32 x, INT32 y, BOOL remember_x = TRUE, BOOL enter_all = FALSE, BOOL search_whole_viewport = FALSE);
  347. /**
  348. * Places the caret on the specified place in the document,
  349. * e.g. at the beginning of the line where the caret is currently
  350. * placed.
  351. * @parm place Any of the places specified in the enum
  352. * OpWindowCommander::CaretMovementDirection.
  353. *
  354. * @see OpWindowCommander::CaretMovementDirection
  355. */
  356. void Place(OpWindowCommander::CaretMovementDirection place);
  357. /**
  358. * Tries to place the caret at the logical position defined by helm+ofs.
  359. * @parm helm The element to put the caret on.
  360. * @parm ofs The element-offset to put the caret on.
  361. * @parm prefer_first If (helm, ofs) corresponds to two reasonable visual
  362. * positions (for example, at the end of one line vs. at the start of
  363. * the next line), setting this to TRUE will place the caret at the
  364. * first position relative to the flow of text, and vice versa.
  365. * @parm allow_snap If TRUE, helm+ofs will be "snapped" to a valid, non-collapsed, logical position.
  366. * @parm keep_within_current_context If TRUE and the current caret-position is withing a different contentEditable container
  367. * then helm, then will the operation not do anything.
  368. */
  369. void Place(HTML_Element* helm, int ofs, BOOL prefer_first = TRUE,
  370. BOOL allow_snap = TRUE,
  371. BOOL keep_within_current_context = FALSE) { GetCaretManager()->Place(helm, ofs, prefer_first, allow_snap, keep_within_current_context); }
  372. /**
  373. * Tries to place the caret first en the editable container edit_root if a valid caret position is within that element
  374. * @parm edit_root the editable container to put the caret in at the first available caret position, if NULL will a possible
  375. * "parent candidate" or the body (if it's editable) be used.
  376. * @parm create_line_if_empty If TRUE, will create a new line if none exists
  377. */
  378. void PlaceFirst(HTML_Element* edit_root = NULL, BOOL create_line_if_empty = TRUE);
  379. /**
  380. * @parm helm The element to put the caret on.
  381. * @parm ofs The element-offset to put the caret on.
  382. * @parm allow_snap If TRUE, helm+ofs will be "snapped" to a valid, non-collapsed, logical position.
  383. * @parm keep_within_current_context If TRUE and the current caret-position is withing a different contentEditable container
  384. * then helm, then will the operation not do anything.
  385. * Returns FALSE if the caret movement should be aborted.
  386. */
  387. BOOL FixAndCheckCaretMovement(HTML_Element*& helm, int& ofs, BOOL allow_snap, BOOL keep_within_current_context);
  388. /** Return TRUE if the element is editable or a child of a editable content. */
  389. BOOL IsElementEditable(HTML_Element* helm);
  390. /** You should normally not use this function. Use Place instead since it will take care of many special situations for you. */
  391. void Set(HTML_Element* helm, int ofs, BOOL prefer_first = FALSE, BOOL remember_x = TRUE);
  392. /** Stores a real caret element and offset. */
  393. void StoreRealCaretPlacement(HTML_Element* helm, int ofs);
  394. /** You should normally not use this function. Use Place instead since it will take care of many special situations for you. */
  395. void Set(HTML_Element* helm, int ofs, int x, int y, int height);
  396. /** If the caret has offset zero, is not an empty string and has a "friendly" element before, then will the caret "snap" to that element. */
  397. void StickToPreceding();
  398. /** If the caret is placed at the "end" of an element and there is a "friendly" "dummy" element after, then "snap" to that element */
  399. void StickToDummy();
  400. /** Remember current x-position as the wanted x-position when moving caret from line to line. */
  401. void UpdateWantedX();
  402. /** When set to TRUE, caret will behave like it's not between character, but as it selects the entire character */
  403. void SetOverstrike(BOOL overstrike);
  404. /** Makes the caret "blink" (toggle from visible->not visible or the other way around...) */
  405. void BlinkNow();
  406. /** Restart the caret "blinking" and starts with the caret visible, looks nice when changing the caret position... */
  407. void RestartBlink();
  408. /** Makes the caret invisible, stops blinking and entering the invisible state */
  409. void StopBlink();
  410. /**
  411. * Lock or unlock the possibility for the caret to update its
  412. * drawing position. Can be used to optimize, by avoiding to
  413. * update it several times during a operation.
  414. * @parm lock TRUE to lock and FALSE to unlock (that is, update
  415. * caret-pos if we're not inside "nestled" LockUpdatePos calls).
  416. * @parm process_update_pos If FALSE will the caret NOT be updated
  417. * even though the "nestling-count" reaches zero when lock ==
  418. * FALSE.
  419. */
  420. void LockUpdatePos(BOOL lock, BOOL process_update_pos = TRUE);
  421. /**
  422. * Update the drawing position. Returns TRUE if the update is
  423. * done. Returns FALSE if it is postponed. F.ex if it was locked
  424. * or if the document was dirty. This is done automatically from
  425. * the Place functions.
  426. * @returns TRUE if the caret's position was successfully updated.
  427. * @parm prefer_first
  428. * @parm create_line_if_empty If TRUE, will create a new line if
  429. * none exists
  430. */
  431. BOOL UpdatePos(BOOL prefer_first = FALSE, BOOL create_line_if_empty = TRUE);
  432. /**
  433. * Inform the documentedit that the caret position has been
  434. * effectively updated.
  435. */
  436. void OnUpdatePosDone();
  437. /**
  438. * Get position and size of the caret in document coordinates.
  439. */
  440. OpRect GetCaretRectInDocument() const;
  441. /**
  442. * Returns the document's CaretManager. Never NULL since it must exist for there
  443. * to be a OpDocumentEdit.
  444. */
  445. CaretManager* GetCaretManager();
  446. HTML_Element* GetElement();
  447. int GetOffset();
  448. /**
  449. * Removes the temporary text caret element if possible.
  450. *
  451. * @param new_is_created - TRUE if a new temporary caret text element is being created.
  452. */
  453. void CleanTemporaryCaretTextElement(BOOL new_is_created);
  454. /**
  455. * Converts the temporary text caret element to <br>.
  456. *
  457. * @return A br element being a replacement for the temporary text caret element.
  458. */
  459. HTML_Element* ConvertTemporaryCaretTextElementToBR();
  460. /**
  461. * @return TRUE if the caret is currently on unmodified temporary text element.
  462. */
  463. BOOL IsUnmodifiedTemporaryCaretTextElement();
  464. OpDocumentEdit* m_edit;
  465. HTML_Element* m_parent_candidate; ///< Delayed initialization of the caret. The caret should be placed under this element when initialized.
  466. HTML_Element *m_remove_when_move_elm;
  467. int m_remove_when_move_id;
  468. /** Keeps a reference to a temporary text caret element */
  469. AutoNullOnDeleteElementRef m_temp_caret_text_elm;
  470. /** Keeps a reference to a real caret element (the one the caret was placed at). */
  471. AutoNullOnDeleteElementRef m_real_caret_elm;
  472. /** An offset within a real caret element. */
  473. int m_real_caret_elm_off;
  474. };
  475. /** Listener interface for being notified when the caret changes position or text-content is changed, only ONE listener is supported,
  476. * the litener is added with OpDocumentEdit::SetListener.
  477. */
  478. class OpDocumentEditListener
  479. {
  480. public :
  481. virtual ~OpDocumentEditListener() {}
  482. /** Callback for when the caret changes position or when caret is being updated. */
  483. virtual void OnCaretMoved() {}
  484. /** Callback for when documentedit inserts or removes text in the document. */
  485. virtual void OnTextChanged() {}
  486. #ifdef SUPPORT_TEXT_DIRECTION
  487. /** Callback for when documentedit changes text direction, with the direction it changed to */
  488. virtual void OnTextDirectionChanged(BOOL to_rtl) {}
  489. #endif //SUPPORT_TEXT_DIRECTION
  490. };
  491. enum TIDY_LEVEL {
  492. TIDY_LEVEL_NONE, ///< Do not tidy anything.
  493. TIDY_LEVEL_MINIMAL, ///< Don't remove anything. Just convert the document_edit_dummy_str to empty textnode.
  494. TIDY_LEVEL_NORMAL, ///< Remove elements that doesn't have any children etc. Except if they contain a empty textnode (the user has removed the text and might want to type new text).
  495. TIDY_LEVEL_AGGRESSIVE ///< Same as TIDY_LEVEL_NORMAL without exceptions.
  496. };
  497. /** Enum for describing how list items in a selection are ordered,
  498. according to the outmost nestling-level.
  499. */
  500. enum SELECTION_ORDERING
  501. {
  502. UNKNOWN, /// Not initialized yet
  503. ORDERED, /// All items are ordered
  504. UN_ORDERED, /// All items are un-ordered
  505. SPLIT_ORDER /// Some items are ordered while other are un-ordered
  506. };
  507. /** "Abstraction" over OpDocumentEditSelection that is used internally, mainly for simplifying handling
  508. * of cases when the start of the selection is at the end of an element and/or the end of the selection
  509. * is before the start of an element (OpDocumentEditSelection::GetStopOfs() == 0).
  510. * For this purpose are editable_start_elm, editable_stop_elm, editable_start_ofs and editable_stop_ofs
  511. * used, these fields are also "trimmed" so that they points at end-points which are valid for the caret.
  512. * This struct are obtained by OpDocumentEdit::GetSelectionState and restored using
  513. * OpDocumentEdit::RestoreSelectionState.
  514. */
  515. struct SelectionState
  516. {
  517. SelectionState() : caret_elm(NULL), caret_ofs(0), start_elm(NULL), stop_elm(NULL),
  518. editable_start_elm(NULL), editable_stop_elm(NULL), start_ofs(0), stop_ofs(0),
  519. editable_start_ofs(0), editable_stop_ofs(0), removed_selection(FALSE), removed_caret(FALSE), caret_at_end(FALSE) {}
  520. HTML_Element *caret_elm; ///< Caret element when this SelectionState was retrieved.
  521. int caret_ofs; ///< Caret offset when this SelectionState was retrieved.
  522. HTML_Element *start_elm, *stop_elm; ///< Start and stop elements as retrieved from OpDocumentEditSelection when this SelectionState was retrieved.
  523. HTML_Element *editable_start_elm, *editable_stop_elm; ///< The result when start_elm and stop_elm has been "trimmed" according to the description of SelectionState
  524. INT32 start_ofs, stop_ofs; ///< Start and stop offset as retrieved from OpDocumentEditSelection when this SelectionState was retrieved.
  525. INT32 editable_start_ofs, editable_stop_ofs; ///< The result when start_elm and stop_elm has been "trimmed" according to the description of SelectionState
  526. BOOL removed_selection; ///< Was the HTML_Document selection removed when this SelectionState was retrieved?
  527. BOOL removed_caret; ///< Was the caret removed when this SelectionState was retrieved?
  528. BOOL caret_at_end; ///< Was the caret at the end (as opposed to the start) selection point?
  529. /** Returns TRUE if it existed a selection and/or caret position when this SelectionState was retrieved */
  530. BOOL IsValid() { return start_elm && stop_elm; }
  531. /** Returns TRUE if this SelectionState represents a non-empty selection */
  532. BOOL HasContent() { return start_elm && stop_elm && (start_elm != stop_elm || start_ofs != stop_ofs); }
  533. /** Returns TRUE if this SelectionState represents editable content, that is, if (editable_start_elm, editable_start_ofs) and (editable_stop_elm, editable_stop_ofs) are different caret-positions. */
  534. BOOL HasEditableContent() { return editable_start_elm && (editable_start_elm != editable_stop_elm || editable_start_ofs != editable_stop_ofs); }
  535. };
  536. /** This class is intended for representing a consecutive range of HTML elements with the same parent.
  537. */
  538. class SiblingBlock
  539. {
  540. public:
  541. SiblingBlock() : start(NULL), stop(NULL) {}
  542. SiblingBlock(HTML_Element *start_elm, HTML_Element *stop_elm) : start(start_elm), stop(stop_elm) {}
  543. bool operator==(const SiblingBlock &other) const {return start==other.start && stop==other.stop;}
  544. bool operator!=(const SiblingBlock &other) const {return !(*this == other);}
  545. bool IsEmpty() {return start == NULL;}
  546. public:
  547. HTML_Element *start,*stop;
  548. };
  549. // The following are functions that might be used as arguments to OpDocumentEdit::GetSelectionMatchesFunction...
  550. /** Returns TRUE if helm has an ATTR_ALIGN value that is NOT CSS_VALUE_left */
  551. BOOL IsNonLeftAligned(HTML_Element *helm, void *dont_care_about_me);
  552. /** Returns TRUE if helm has an ATTR_ALIGN value equals to CSS_align_value */
  553. BOOL IsAlignedAs(HTML_Element *helm, void *CSS_align_value);
  554. /** Returns TRUE if helm has any of the types in elm_types, elm_types should be an HTML_ElementType[] array ending with HE_UNKNOWN */
  555. BOOL StaticIsMatchingType(HTML_Element *helm, void *elm_types);
  556. // The following are functions that might be used as arguments to OpDocumentEdit::ApplyFunctionBetween...
  557. /**
  558. * Sets ATTR_HREF on helm if it's an HE_A element according to arguments in arg.
  559. * @return Error status code...
  560. * @parm helm The HE_A element to change ATTR_HREF for.
  561. * @parm arg (OpDocumentEdit*)(((void**)(args))[0]) should be an OpDocumentEdit instance and
  562. * (OpDocumentEdit*)(((void**)(args))[1]) should be the new href string.
  563. * @parm ret Set to TRUE if ATTR_HREF was updated, otherwise FALSE.
  564. */
  565. OP_STATUS SetNewHref(HTML_Element *helm, void *arg, BOOL &ret);
  566. /** Change flags informing UNDO/REDO stack about a type of a change */
  567. enum ChangeFlags
  568. {
  569. /** No flags */
  570. CHANGE_FLAGS_NONE = 0,
  571. /** The change may be appended to the previous one, if it appends it */
  572. CHANGE_FLAGS_ALLOW_APPEND = 1,
  573. /** The must not be seen by the user */
  574. CHANGE_FLAGS_USER_INVISIBLE = 2
  575. };
  576. /** UNDO/REDO stack event type */
  577. enum UndoRedoEventType
  578. {
  579. /** unknown event */
  580. UNDO_REDO_TYPE_UNKNOWN = -16, /* -16 */
  581. /** An event reverting an element change */
  582. UNDO_REDO_ELEMENT_REVERT_CHANGE = -3, /* -3 */
  583. /** An element removal */
  584. UNDO_REDO_ELEMENT_REMOVE, /* -2 */
  585. /** An event storing start caret placement */
  586. UNDO_REDO_CARET_PLACEMENT_BEGIN /* -1 */,
  587. /** An event storing end caret placement */
  588. UNDO_REDO_CARET_PLACEMENT_END, /* 0 => ~(-1) => ~UNDO_REDO_CARET_PLACEMENT_BEGIN */
  589. /** An element insertion */
  590. UNDO_REDO_ELEMENT_INSERT, /* 1 => ~(-2) => ~UNDO_REDO_ELEMENT_REMOVE */
  591. /** An element change - e.g. some of its attribute */
  592. UNDO_REDO_ELEMENT_CHANGE /* 2 => ~(-3) => ~UNDO_REDO_ELEMENT_REVERT_CHANGE */
  593. };
  594. /** OpDocumentEdit handles editing of a document.
  595. Will be created and assigned to a FramesDocument by calling FramesDocument::SetEditable(TRUE).
  596. Userinterface is done elsewhere and should interact with OpDocumentEdit through execCommand and the queryCommand* functions.
  597. All the editing is limited to the <body> element.
  598. */
  599. class OpDocumentEdit : public OpInputContext, public MessageObject
  600. #ifdef _DOCEDIT_DEBUG
  601. , public OpDocumentEditDebugCheckerObject
  602. #endif
  603. #ifdef INTERNAL_SPELLCHECK_SUPPORT
  604. , public SpellUIHandler
  605. #endif
  606. #ifdef USE_OP_CLIPBOARD
  607. , public ClipboardListener
  608. #endif // USE_OP_CLIPBOARD
  609. {
  610. public:
  611. OpDocumentEdit();
  612. virtual ~OpDocumentEdit();
  613. /** Static contstructor... */
  614. static OP_STATUS Construct(OpDocumentEdit** obj, FramesDocument* doc, BOOL designmode);
  615. /** Called upon construction, should not be called explicitly */
  616. OP_STATUS Init(FramesDocument* doc, BOOL designmode);
  617. /** Removes all elements in body, clears undo stack an re-initializes caret */
  618. OP_STATUS Clear();
  619. /** Should remove all collapsed whitspaces in the document, FIXME: It just reflows!? */
  620. OP_STATUS CollapseWhitespace();
  621. /** Paint stuff related to editing. Caret and resize-handles for boxes/tables etc.
  622. Should be done after document is fully painted. */
  623. void Paint(VisualDevice* vis_dev);
  624. /**
  625. * Mouse-event handling, will "unactivate" the current "layout modifier" if such exists and event is ONMOUSEDOWN,
  626. * that is, if the user has previously clicked on an e.g. image so that the dashed border around it has appeared,
  627. * that will be removed, and possibly, if helm is also an "layout modifiable" element then helm will be the new
  628. * active "layout modifier".
  629. * @return TRUE if a new "layout modifier" has been "activated".
  630. * @parm helm The target for the mouse-event.
  631. * @parm event The mouse-event, currently will nothing happen for other events other then ONMOUSEDOWN.
  632. * @parm x X-coordinate in document-coordinates.
  633. * @parm y Y-coordinate in document-coordinates.
  634. * @parm button The mouse-button, currently is the bahaviour for all mouse buttons the same.
  635. */
  636. BOOL HandleMouseEvent(HTML_Element* helm, DOM_EventType event, int x, long y, MouseButton button);
  637. /**
  638. * Checks if a particular element can be the currently active "layout modifier", see description for HandleMouseEvent.
  639. * @return TRUE if helm is layout modifiable.
  640. * @parm helm The html-element...
  641. */
  642. BOOL IsLayoutModifiable(HTML_Element* helm);
  643. /**
  644. * Returns how the mouse-cursor should appear if hovering over element helm.
  645. * @return The cursor-type, if the position (x,y) is over a scroll-bar or if helm is not editable (not within a
  646. * design-mode document or an contenteditable element) will CURSOR_AUTO be returned.
  647. * @parm helm The html-element
  648. * @parm x X-coordinate in document-coordinates.
  649. * @parm y Y-coordinate in document-coordinates.
  650. */
  651. CursorType GetCursorType(HTML_Element* helm, int x, int y);
  652. /**
  653. * Initiates the clipboard copy operation which may end up placing the selected
  654. * part in the clipboard.
  655. *
  656. * @param cut - If TRUE the cut operation is initiated instead.
  657. */
  658. void Copy(BOOL cut = FALSE);
  659. /**
  660. * Initiates the clipboard cut operation which may end up placing the selected
  661. * part in the clipboard and removing it from the document.
  662. *
  663. * @see Copy()
  664. */
  665. void Cut() { Copy(TRUE); }
  666. /**
  667. * Initiatse the clipboard paste operation which may end up inserting the clipboard's content
  668. * at the current caret-position.
  669. */
  670. void Paste();
  671. #ifdef USE_OP_CLIPBOARD
  672. // ClipboardListener API
  673. void OnCopy(OpClipboard* clipboard);
  674. void OnPaste(OpClipboard* clipboard);
  675. void OnCut(OpClipboard* clipboard)
  676. {
  677. if(m_readonly || (!m_layout_modifier.IsActive() && !m_selection.HasContent()))
  678. return;
  679. OnCopy(clipboard);
  680. execCommand(OP_DOCUMENT_EDIT_COMMAND_DELETE);
  681. }
  682. #endif // USE_OP_CLIPBOARD
  683. /**
  684. * Undo the last event or linked chain of events recorded on the undo-stack, only works if these events have been
  685. * created within documentedit and not if e.g. DOM has manually inserted elements.
  686. */
  687. void Undo();
  688. /**
  689. * Redo the last event or linked chain of events recorded on the undo-stack, only works if these events have been
  690. * created within documentedit and not if e.g. DOM has manually inserted elements.
  691. */
  692. void Redo();
  693. /**
  694. * Removes all content inside body and inserts text.
  695. * @return Error status code...
  696. * @parm The text to inserted in the empty body, just plain text, doesn't parse html-tags and such.
  697. */
  698. OP_STATUS SetText(const uni_char* text);
  699. /**
  700. * Removes all content inside body and the content represented as html-code in text.
  701. * @return Error status code...
  702. * @parm The html-content to be inserted in the empty body, transforms the html-code to a logical tree.
  703. */
  704. OP_STATUS SetTextHTML(const uni_char* text);
  705. /**
  706. * Retrieves the text of the document. This does only include text in HE_TEXT elements (no tags and such).
  707. * @return Error-code of the operation.
  708. * @parm text OpString object to output the text to.
  709. * @parm block_quotes_as_text If TRUE, blockquotes will make containing lines start with '>' characters.
  710. */
  711. OP_STATUS GetText(OpString& text, BOOL block_quotes_as_text = FALSE);
  712. /** Outputs the html-code for the document's body element and it's inner content. */
  713. OP_STATUS GetTextHTML(OpString& text);
  714. /** Called when script has modified the selection. */
  715. void OnDOMChangedSelection();
  716. /**
  717. * Sets the active OpDocumentEditListener for this OpDocumentEdit instance, see description of OpDocumentEditListener
  718. * @return Always TRUE.
  719. * @parm listener The OpDocumentEditListener, may be NULL.
  720. */
  721. BOOL SetListener(OpDocumentEditListener* listener) { m_listener = listener; return TRUE; }
  722. /**
  723. * Returns the active OpDocumentEditListener for this OpDocumentEdit instance, see description of OpDocumentEditListener
  724. * @return The OpDocumentEditListener, might be NULL.
  725. */
  726. OpDocumentEditListener* GetListener() { return m_listener; }
  727. /**
  728. * Gives selection end-points for the current selection or caret-position.
  729. * @return TRUE if we succeeded to get a selection.
  730. * @parm anchor The selection end-point where the user STARTED the selection, that is, the end-point where
  731. * the caret is NOT located. This is if we're not having a selection and just the caret, then will both anchor
  732. * and focus be the caret end-point.
  733. * @parm focus The selection end-point where the user is currently selection, that is, the end-point where
  734. * the caret IS located. Unfortunately we currently might have situations where the caret is not located at
  735. * any of the selection end-points, then will anchor be the start of the selection and foucs the end, in logica
  736. * order.
  737. */
  738. BOOL GetSelection(SelectionBoundaryPoint &anchor, SelectionBoundaryPoint &focus);
  739. // == Command API for use by the DOM engine ==================
  740. /** Converts a text-representation of a command to an OP_DOCUMENT_EDIT_COMMAND
  741. enum, e.g. "useCss" will return OP_DOCUMENT_EDIT_COMMAND_USECSS. */
  742. static OP_DOCUMENT_EDIT_COMMAND ConvertCommand(const uni_char* command);
  743. /**
  744. * Executes a command on the current document or current selection, or the given range.
  745. *
  746. * @param command The command type to execute.
  747. * @param document_edit The OpDocumentEdit instance. Can be NULL in which
  748. * case the check is performed based on the origin
  749. * of the provided URL and FramesDocument (for
  750. * a limited set of commands).
  751. * @param showui The value of the 'show UI' argument.
  752. * @param value The value of the 'Value' argument.
  753. * @param origin_url The URL of the originating document.
  754. * @param frm_doc The document in context of which the command is performed
  755. * if OpDocumentEdit is not provided. Must be non-NULL if
  756. * document_edit is NULL.
  757. *
  758. * @return OpStatus::ERR_NOT_SUPPORTED if the command is not supported or
  759. * can't work in current context.
  760. * OpStatus::ERR_NO_ACCESS if the command is not allowed to run.
  761. */
  762. static OP_STATUS execCommand(const uni_char* command, OpDocumentEdit* document_edit, BOOL showui, const uni_char* value, URL& origin_url, FramesDocument* frm_doc);
  763. /**
  764. * Returns a Boolean value that indicates whether a specified command can be
  765. * successfully executed using execCommand, given the current state of the
  766. * document.
  767. *
  768. * @param command To command type to query for.
  769. * @param document_edit The OpDocumentEdit instance. Can be NULL in which
  770. * case the check is performed based on the origin
  771. * of the provided URL and FramesDocument (for
  772. * a limited set of commands).
  773. * @param origin_url The URL of the originating document.
  774. * @param frm_doc The document in context of which the query is performed
  775. * if OpDocumentEdit is not provided. Must be non-NULL if
  776. * document_edit is NULL.
  777. *
  778. * @return a value indicating whether a specified command can be executed.
  779. */
  780. static BOOL queryCommandEnabled(const uni_char* command, OpDocumentEdit* document_edit, URL& origin_url, FramesDocument* frm_doc);
  781. /** Returns a Boolean value that indicates the current state of the command. */
  782. BOOL queryCommandState(const uni_char* command);
  783. /**
  784. * Returns a Boolean value that indicates whether the current command is
  785. * supported on the current range.
  786. *
  787. * @param command The command type to query for.
  788. * @param document_edit The OpDocumentEdit instance. Can be NULL in which
  789. * case the check is performed based on the origin
  790. * of provided URL (for a limited set of commands).
  791. * @param origin_url The URL of the originating document.
  792. * @param frm_doc The document in context of which the query is performed
  793. * if OpDocumentEdit is not provided. Must be non-NULL if
  794. * document_edit is NULL.
  795. *
  796. * @return a value indicating whether the command is supported.
  797. */
  798. static BOOL queryCommandSupported(const uni_char* command, OpDocumentEdit* document_edit, URL& origin_url, FramesDocument* frm_doc);
  799. /** Returns the current value of the document, range, or current selection for the given command. */
  800. OP_STATUS queryCommandValue(const uni_char* command, TempBuffer& value);
  801. // == Internal functions for command API =====================
  802. OP_STATUS execCommand(OP_DOCUMENT_EDIT_COMMAND command, BOOL showui = FALSE, const uni_char* value = NULL);
  803. BOOL queryCommandEnabled(OP_DOCUMENT_EDIT_COMMAND command);
  804. BOOL queryCommandState(OP_DOCUMENT_EDIT_COMMAND command);
  805. OP_STATUS queryCommandSupported(OP_DOCUMENT_EDIT_COMMAND command, URL& origin_url);
  806. OP_STATUS queryCommandValue(OP_DOCUMENT_EDIT_COMMAND command, TempBuffer& value);
  807. // == Internal functions for editing ==========================
  808. /**
  809. * Sets the selected text to the given style. If there is no selection, the style will
  810. * apply to typed text from that point.
  811. * @parm type The type of the style-elements to create (e.g. HE_STRONG, HE_EM).
  812. * @parm exclude_type If not 0, this specifies that style elements should NOT be inserted for elements
  813. * that are already under style-elements of this type.
  814. * @parm allow_nestling If TRUE, this indicates that it's ok with nestled style-elements, useful for
  815. * e.g. nestling of BIG/SMALL elements.
  816. * @parm must_be_below_this_type If not 0, it's ensured that the new style elements are not inserted above
  817. * elements of this type. For example: BIG/SMALL elements should be inserted below FONT elements because
  818. * if ATTR_SIZE is defined for the FONT elements, then will BIG/SMALL have no effect if they are inserted
  819. * above those FONT elements.
  820. */
  821. void InsertStyle(HTML_ElementType type, HTML_ElementType exclude_type = (HTML_ElementType)0, BOOL allow_nestling = FALSE, HTML_ElementType must_be_below_this_type = (HTML_ElementType)0);
  822. /**
  823. * Inserts HE_FONT elements with when necessary with ATTR_COLOR on the selection to make all selected text to have color color. If there is no selection, the style will
  824. * apply to typed text from that point. This function uses InsertStyleElement.
  825. * @parm color The color value.
  826. */
  827. void InsertFontColor(UINT32 color);
  828. /**
  829. * Inserts HE_FONT elements with when necessary with ATTR_FACE on the selection to make all selected text to have the font
  830. * specified by fontface. If there is no selection, the style will apply to typed text from that point.
  831. * This function uses InsertStyleElement.
  832. * @parm fontface The name of the font.
  833. */
  834. void InsertFontFace(const uni_char* fontface);
  835. /**
  836. * Inserts HE_FONT elements with when necessary with ATTR_SIZE on the selection to make all selected text to have fontsize size. If there is no selection, the style will
  837. * apply to typed text from that point. This function uses InsertStyleElement.
  838. * @parm size The font size.
  839. */
  840. void InsertFontSize(UINT32 size);
  841. /**
  842. * Inserts HE_FONT elements with when necessary with attribute attr which should have value val, on the selection. If there is no selection, the style will
  843. * apply to typed text from that point. This function uses InsertStyleElement.
  844. * @parm attr The attribute to set on the inserted HE_FONT elements.
  845. * @parm val The attribute value to use.
  846. */
  847. void InsertFont(short attr, void* val);
  848. /**
  849. * Sets the selected text to be "styled" under element helm, or several copies of helm. If there is no selection, the style will
  850. * apply to typed text from that point.
  851. * @parm helm The "style element" to use, should NOT be deleted or accessed after the call.
  852. * @parm exclude_type If not 0, this specifies that style elements should NOT be inserted for elements
  853. * that are already under style-elements of this type.
  854. * @parm allow_nestling If TRUE, this indicates that it's ok with nestled style-elements, useful for
  855. * e.g. nestling of BIG/SMALL elements.
  856. * @parm must_be_below_this_type If not 0, it's ensured that the new style elements are not inserted above
  857. * elements of this type. For example: BIG/SMALL elements should be inserted below FONT elements because
  858. * if ATTR_SIZE is defined for the FONT elements, then will BIG/SMALL have no effect if they are inserted
  859. * above those FONT elements.
  860. */
  861. OP_STATUS InsertStyleElement(HTML_Element* helm, HTML_ElementType exclude_type = (HTML_ElementType)0, BOOL allow_nestling = FALSE, HTML_ElementType must_be_below_this_type = (HTML_ElementType)0);
  862. /**
  863. * "Extracts" the subtree from start_elm to stop_elm under old_root and moves it under new_parent after after_me.
  864. * @return Error status code.
  865. * @parm start-elm The first element in logical ordering to extract. If start_elm == NULL will it be set to the first element
  866. * in the same block as stop_elm.
  867. * @parm start-elm The last element (except of possible children to stop_elm which will follow in the move)
  868. * in logical ordering to extract. If stop_elm == NULL will it be set to the last element in the same block as start_elm.
  869. * @parm old_root The root_element which should stay in place, the extraction should occur under this element.
  870. * @parm new_root The new parent for the extracted subtree.
  871. * @parm after_me The element under new_parent which should precede the extracted tree, if it's NULL will the extracted
  872. * tree be added before the possible first child of new_root.
  873. */
  874. OP_STATUS ExtractElementsTo(HTML_Element *start_elm, HTML_Element *stop_elm, HTML_Element *old_root, HTML_Element *new_root, HTML_Element *after_me);
  875. #ifdef INTERNAL_SPELLCHECK_SUPPORT
  876. // == SpellUISession =======================
  877. virtual OpSpellCheckerSession *GetSpellCheckerSession() { return m_spell_session; }
  878. virtual BOOL SetSpellCheckLanguage(const uni_char *lang);
  879. virtual void DisableSpellcheck();
  880. virtual OpSpellCheckerWordIterator* GetAllContentIterator();
  881. virtual OP_STATUS ReplaceWord(OpSpellCheckerWordIterator *word_iterator, const uni_char *new_word);
  882. virtual void OnSessionReady(OpSpellCheckerSession *session);
  883. virtual void OnError(OpSpellCheckerSession *session, OP_STATUS error_status, const uni_char *error_string);
  884. virtual void OnMisspellingFound(OpSpellCheckerSession *session, OpSpellCheckerWordIterator *word, const uni_char **replacements);
  885. virtual void OnCorrectSpellingFound(OpSpellCheckerSession *session, OpSpellCheckerWordIterator *word);
  886. virtual void OnCheckingComplete(OpSpellCheckerSession *session);
  887. virtual void OnCheckingTakesABreak(OpSpellCheckerSession *session);
  888. OP_STATUS EnableSpellcheckInternal(BOOL by_user, const uni_char *lang);
  889. void DisableSpellcheckInternal(BOOL by_user, BOOL force);
  890. void OnSpellcheckerStopped();
  891. void RunPendingSpellCheck();
  892. OP_STATUS SpellCheckRange(HTML_Element *first, HTML_Element *last);
  893. void RepaintElement(HTML_Element *helm);
  894. void OnBeforeNewCaretPos(HTML_Element *helm, int ofs);
  895. void DoSpellWordInfoUpdate(SpellWordInfoObject *old_info);
  896. void PossiblyDelayMisspell(BOOL was_delayed_misspell);
  897. OP_STATUS MarkMisspellingInTextElement(BOOL misspelled, HTML_WordIterator *word, HTML_Element *helm, int start_ofs, int stop_ofs);
  898. OP_STATUS MarkNodesMisspelled(BOOL misspelled, HTML_WordIterator *word);
  899. void SpellInvalidateAround(HTML_Element *helm, BOOL must_be_outside_helm = FALSE);
  900. BOOL HandleSpellCheckCommand(BOOL showui, const uni_char *value);
  901. OP_STATUS CreateSpellUISessionInternal(IntersectionObject *intersection, int &spell_id);
  902. OP_STATUS CreateSpellUISession(IntersectionObject *intersection, int &spell_id);
  903. WordInfo *GetDelayedMisspellWordInfo() { return m_delay_misspell_word_info; }
  904. #endif // INTERNAL_SPELLCHECK_SUPPORT
  905. virtual void HandleCallback(OpMessage msg, MH_PARAM_1 par1, MH_PARAM_2 par2);
  906. /**
  907. posts a message to recreate caret, for when an element is
  908. removed and it is not possible to get a new caret position
  909. because of this.
  910. */
  911. OP_STATUS PostRecreateCaretMessage();
  912. // From OpInputContext
  913. void SetFocus(FOCUS_REASON reason)
  914. {
  915. m_is_focusing = TRUE;
  916. OpInputContext::SetFocus(reason);
  917. m_is_focusing = FALSE;
  918. }
  919. void ReleaseFocus(FOCUS_REASON reason = FOCUS_REASON_RELEASE)
  920. {
  921. if (!m_is_focusing)
  922. OpInputContext::ReleaseFocus(reason);
  923. }
  924. private:
  925. /** Retrieves the left-margin of element helm in result_px */
  926. OP_STATUS GetCSSIndent(HTML_Element *helm, int &result_px);
  927. /** Sets the left-margin in helm to px */
  928. OP_STATUS SetCSSIndent(HTML_Element *helm, int px);
  929. /**
  930. * Removes the inline CSS-property prop between start_elm and stop_elm.
  931. * @return Error status code.
  932. * @parm start_elm The first element to apply the change to.
  933. * @parm stop_elm The last element to apply the change to.
  934. * @parm prop The inline CSS-propery to remove.
  935. * @parm only_block_element If TRUE, only remove from block-level elements.
  936. */
  937. OP_STATUS RemoveInlinePropertyBetween(HTML_Element *start_elm, HTML_Element *stop_elm, int prop, BOOL only_block_elements = FALSE);
  938. /**
  939. * Sets the ATTR_ALIGN attribute on an element. Currently this function uses HTML_Element::SetAttribute
  940. * after converting value to a string because it seems HTML_Element::SetAttr is not enough anymore...
  941. * @return Error status code.
  942. * @param helm The html element...
  943. * @param value The alignment value (CSS_VALUE_left etc).
  944. */
  945. OP_STATUS SetAlignAttrFromCSSValue(HTML_Element *helm, CSSValue value);
  946. /**
  947. * Extracts the tree to the left or right of the path between root and helm, the elements
  948. * in the path up to (and including) root is copied if necessary, no elements without
  949. * children are created. Currently will this function OP_ASSERT if root->FirstLeaf()==helm->LastLeaf()
  950. * && extract_left==TRUE || root->LastLeaf()==helm->LastLeaf() && extract_left=FALSE, this means -
  951. * this function should only be used when there is really something to "extract".
  952. *
  953. * Example: ExtractTreeBeside(root,e5,TRUE); on this tree...
  954. *
  955. * ...
  956. * |
  957. * <root>
  958. * / | \
  959. * <e1> <e2> <e3>
  960. * / \
  961. * <e4> <e5>
  962. *
  963. * ...makes the tree look like this...
  964. *
  965. * ...
  966. * |
  967. * <root>
  968. * | \
  969. * <e2> <e3>
  970. * \
  971. * <e5>
  972. *
  973. * ...and returns the copy of root...
  974. * NULL
  975. * |
  976. * <copy of root>
  977. * / |
  978. * <e1> <copy of e2>
  979. * /
  980. * <e4>
  981. *
  982. * @return the root of the extracted tree or NULL in case of an error.
  983. * @parm root The root element for the operation, the returned element will be a copy of
  984. * this element, see the example above.
  985. * @parm helm The element in the tree that will be first/last (extract_left==TRUE/FALSE)
  986. * -leaf of root after the operation after the left/right part of the tree has been extracted.
  987. * Or more precisely: If extract_left==TRUE -> root->FirstLeaf()==helm->LastLeaf() after the
  988. * operation, and: If extract_left==FALSE -> root->LastLeaf()==helm->LastLeaf() after operation.
  989. * @parm extract_left Determines whether the extraction should apply to the left or right of
  990. * the path between helm and root.
  991. */
  992. HTML_Element* ExtractTreeBeside(HTML_Element *root, HTML_Element *helm, BOOL extract_left);
  993. /**
  994. * Copies the inline "style-elements" (STRONG, EM, etc) between src_helm and it's ancestor src_containing_elm
  995. * (which is supposed to be a block-level element). The result will be a hierarchy of style elements where
  996. * each element has one child (except of the lowest...), and if put_empty_string_at_bottom==TRUE - an empty
  997. * text element will be at the bottom.
  998. * @return Error status code.
  999. * @parm src_helm The element somewhere below src_containing_helm where the traversal up until src_containing_elm
  1000. * should start in the search for style-elements to copy, src_helm itself is included in this search.
  1001. * @parm src_containing_elm This is supposed to be the block-level containing element of src_helm which the search
  1002. * (by traversing ->Parent()) should proceed up until. If src_containing_elm==NULL, then GetContainingElement(src_helm)
  1003. * will be used.
  1004. * @parm new_top_helm The root in the "style-tree" created by the function.
  1005. * @parm new_bottom_helm The bottom child in the "style-tree" created by the function. If put_empty_string_at_bottom
  1006. * was TRUE, then this element will be an empty text element.
  1007. * @parm put_empty_string_at_bottom If TRUE, then an empty string will be created as the bottom child in the "style-tree".
  1008. * @parm make_empty_dummy If put_empty_string_at_bottom==TRUE and make_empty_dummy==TRUE, then will the "empty"
  1009. * text element att the bottom of the "style-tree" infact contain the "dummy text string" for marking empty text
  1010. * elements which should not be removed by the Tidy() function.
  1011. */
  1012. OP_STATUS CreateStyleTreeCopyOf(HTML_Element *src_helm, HTML_Element *src_containing_elm, HTML_Element *&new_top_helm, HTML_Element *&new_bottom_helm, BOOL put_empty_string_at_bottom, BOOL make_empty_dummy);
  1013. /** Inserts helm over the currently active layout "modifier", used by InsertStyleElement. */
  1014. OP_STATUS InsertStyleElementLayoutModified(HTML_Element* helm);
  1015. /** Inserts multiple copies of helm over the selected text-content (and deletes helm itself), see description of InsertStyleElement */
  1016. OP_STATUS InsertStyleElementMultiple(HTML_Element* helm, HTML_ElementType exclude_type, BOOL allow_nestling);
  1017. /** Inserts helm over the selected text-content, see description of InsertStyleElement */
  1018. OP_STATUS InsertStyleElementSingle(HTML_Element* helm, HTML_ElementType exclude_type, BOOL allow_nestling);
  1019. /** Removes all "style elements" matching type and attr from the current selection, see description of RemoveStyle */
  1020. void RemoveStyleElementMultiple(HTML_ElementType type, short attr, BOOL just_on_level);
  1021. /** Removes all "style elements" matching type and attr from the current selection, the same as RemoveStyleElementMultiple but
  1022. it's implemented differently and only works(?) when start- and stop-elements in the selection are "friends". See description of RemoveStyle. */
  1023. void RemoveStyleElementSingle(HTML_ElementType type, short attr, BOOL just_one_level);
  1024. /**
  1025. * Returns a consecutive range of html elements with the same parent. It starts from
  1026. * helm and scans in both directions (using Suc() and Pred()). If helm is a block-level
  1027. * element, then will the range only consist of this element. If helm is an inline-level
  1028. * element, then will the range include consecutive inline elments before and after helm.
  1029. * @return Returns the range of siblings.
  1030. * @parm stop_at_br FIXME: remove this argument or change behaviour
  1031. * @parm stop_pred Stop scan when Pred() returns this element, and don't include it.
  1032. * @parm stop_suc Stop scan when Suc() returns this element, and don't include it.
  1033. */
  1034. SiblingBlock GetBlockSiblings(HTML_Element *helm, BOOL stop_at_br = FALSE, HTML_Element *stop_pred = NULL, HTML_Element *stop_suc = NULL);
  1035. /**
  1036. * If the parent of the elements in block is of type HE_LI, HE_OL or HE_UL - then will
  1037. * this function remove "unnecessary" children of that parent that are not contained
  1038. * inside block.
  1039. * @param block The range of elements which should NOT be "cleaned".
  1040. */
  1041. void CleanAroundBlock(SiblingBlock block);
  1042. /**
  1043. * This function is a help-function for GetNextListBlock.
  1044. * @return Returns a range of HTML elements which are "friends" immediately under root or immediately
  1045. * under a OL/UL element. The search is made in Depth-First-Search order and starts from block but
  1046. * does not include this block or any block below this block. An empty block is returned if no suitable
  1047. * blocks are found below the parent of block.
  1048. * @param root If the parent of block == root, then a block immediately under root could be returned
  1049. * even though root is not a OL/UL element.
  1050. * @param block The block to start the search from, trees that are successors of block will be traversed.
  1051. */
  1052. SiblingBlock GetSucListBlock(HTML_Element *root, SiblingBlock block);
  1053. /**
  1054. * This function is used for iterating through "friend blocks" of HTML elements that are either
  1055. * children below root or chilren below OL/UL elements which root is an ancestor for.
  1056. * @return Returns a range of HTML elements which are "friends" immediately under root or immediately
  1057. * under a OL/UL element. The search is made in Depth-First-Search order and starts from block but
  1058. * does not include this block or any block below this block. An empty block is returned if no suitable
  1059. * blocks are found below root and after block in DFS order.
  1060. * @param root The root in the tree so search through.
  1061. * @param block The block to start the search from.
  1062. */
  1063. SiblingBlock GetNextListBlock(HTML_Element *root, SiblingBlock block);
  1064. /**
  1065. * Moves the elements in block and appends them after after_me which is a child of new_parent.
  1066. * The old parent of block might be splitted in two parts and if the parent of the old parent
  1067. * is a LI element, this element might be splitted as well.
  1068. * @return OpStatus::OK if successful, otherwise some error...
  1069. * @param block The block to move away into new_parent.
  1070. * @param new_parent The new parent for block.
  1071. * @param after_me The new successor element of block when it's moved into new_parent. If after_me
  1072. * is NULL, block will be added first under new_parent.
  1073. * @split_parent The element under which the split occured.
  1074. * @split_pred The lowest child under split_parent that belongs to the "upper part" of the split.
  1075. */
  1076. OP_STATUS SplitListAroundAndMoveBlock(SiblingBlock block, HTML_Element *new_parent, HTML_Element *after_me, HTML_Element *&split_parent, HTML_Element *&split_pred);
  1077. /**
  1078. * Moves the elements in block and appends them after after_me which is a child of new_parent.
  1079. * @param block The block to move away into new_parent.
  1080. * @param new_parent The new parent for block.
  1081. * @param after_me The new successor element of block when it's moved into new_parent. If after_me
  1082. * is NULL, block will be added first under new_parent.
  1083. */
  1084. void MoveSiblingBlock(SiblingBlock block, HTML_Element *new_parent, HTML_Element *after_me = NULL);
  1085. /**
  1086. * Deletes HE_TEXT elements in block that is non-empty that contains only chars with values <= 32.
  1087. * @parm block The block to "clean", will be updated before returning if block.start or block.stop
  1088. * is "unnecessary".
  1089. * @save_at_least_one If true and all elements in block are "unnecessary", one element will remain anyway.
  1090. */
  1091. void CleanUnnecessaryElementsInBlock(SiblingBlock *block, BOOL save_at_least_one = FALSE);
  1092. /**
  1093. * Adds all blocks >= start_block and <= stop_block as returned by GetNextListBlock to the same list.
  1094. * If start_block is already contained inside a list of the same type as ordered specifies, this
  1095. * list will be used. Otherwise a new list will be created.
  1096. * @return Error status code.
  1097. * @param shared_elm The shared containing element for start_block and stop_block (may infact just be
  1098. * an ancestor of this element because the most deeply nestled shared containing element might be split
  1099. * by this function).
  1100. * @param start_block First block for performing the operation on.
  1101. * @param stop_block Last block for performing the operation on.
  1102. * @parm ordered Should the list be ordered (OL) or un-ordered (UL)
  1103. */
  1104. OP_STATUS InsertAndOrToggleListOrdering(HTML_Element *shared_elm, SiblingBlock start_block, SiblingBlock stop_block, BOOL ordered);
  1105. /**
  1106. * Increases the nestling level of elements inside OL/UL lists that are selected, elements that are
  1107. * participating in any lists are unaffected.
  1108. * @return Error status code.
  1109. */
  1110. OP_STATUS IncreaseListNestling();
  1111. /**
  1112. * Decreases the nestling level of elements inside OL/UL lists that are selected, elements that are
  1113. * participating in any lists are unaffected. LI elements that are not under a list anymore are
  1114. * "converted" to P elements.
  1115. * @return Error status code.
  1116. */
  1117. OP_STATUS DecreaseListNestling();
  1118. /**
  1119. * Decreases the maximum nestling level by decreasing the list-nestling by one of list elements
  1120. * that have a nestling of max_nestling.
  1121. * @return Error status code.
  1122. * @param shared_elm The shared containing element for start_block and stop_block (may infact just be
  1123. * an ancestor of this element because the most deeply nestled shared containing element might be split
  1124. * by this function).
  1125. * @param start_block First block for performing the operation on.
  1126. * @param stop_block Last block for performing the operation on.
  1127. * @param max_nestling The maximum nestling that any list elements >= start_block and <= stop_block are
  1128. * assumed to have before this operation.
  1129. */
  1130. OP_STATUS DecreaseMaxListNestling(HTML_Element *shared_elm, SiblingBlock start_block, SiblingBlock stop_block, INT32 max_nestling);
  1131. /**
  1132. * "Adjusts" start_elm and stop_elm so that if they're not block-elements will they be adjusted upwards in the tree
  1133. * so their ParentActual() will be a block-level element and PredActual() for start-elm and SucActual() for stop_elm
  1134. * will be either NULL or a block-level element.
  1135. * @parm start_elm The start element.
  1136. * @parm stop_elm The stop element.
  1137. */
  1138. void AdjustStartStopToBlocks(HTML_Element *&start_elm, HTML_Element *&stop_elm);
  1139. /**
  1140. * "Adjusts" start_elm and stop_elm "forward" in the tree for start_elm and "backwards" for stop_elm so that
  1141. * both start_elm and stop_elm will be GetInserted() < HE_INSERTED_FIRST_HIDDEN_BY_ACTUAL.
  1142. * @parm start_elm The start element, might be NULL after return (then, stop_elm will also be NULL):
  1143. * @parm stop_elm The stop element, might be NULL after return (then, start_elm will also be NULL):
  1144. */
  1145. void AdjustStartStopToActual(HTML_Element *&start_elm, HTML_Element *&stop_elm);
  1146. /**
  1147. * "Adjusts" start_elm and stop_elm "forward" in the tree for start_elm and "backwards" for stop_elm so that
  1148. * there are not any ancestors of types to start_elm and stop_elm.
  1149. * @parm start_elm The start element, might be NULL after return (then, stop_elm will also be NULL):
  1150. * @parm stop_elm The stop element, might be NULL after return (then, start_elm will also be NULL):
  1151. */
  1152. void AdjustStartStopNotBreakTypes(HTML_Element *&start_elm, HTML_Element *&stop_elm, HTML_ElementType *types);
  1153. /**
  1154. * "Adjust" start_elm and stop_elm upwards in the tree as long as start_elm->PredActual() == NULL and
  1155. * stop_elm->SucActual() == NULL (sort of...).
  1156. * @return The shared containing element for start_elm and stop_elm, which is the same both before and after the call.
  1157. * @parm start_elm The start element.
  1158. * @parm stop_elm The stop element.
  1159. */
  1160. HTML_Element* AdjustStartStopCloserRoot(HTML_Element *&start_elm, HTML_Element *&stop_elm);
  1161. /**
  1162. * Justifies the current selection by setting the ATTR_ALIGN attribute on "suitable" block-level
  1163. * elements, and, in general (special case for tables), removing it from all of these elements
  1164. * children. DIV elements are created for inline elements that are not under block-level parents.
  1165. * @param align How to justify the selection (CSS_VALUE_left, etc).
  1166. */
  1167. void JustifySelection(CSSValue align);
  1168. /**
  1169. * Indents/Outdents the current selection by setting the inline CSS_PROPERTY_margin_left property on "suitable" block-level
  1170. * elements. DIV elements are created for inline elements that are not under block-level parents.
  1171. * @param px How many px to indent (positive value) or outdent (negative value), added to the previous left-margin.
  1172. */
  1173. OP_STATUS IndentSelection(int px);
  1174. /** Detect the direction now from the current text. */
  1175. void AutodetectDirection();
  1176. public:
  1177. /** Clears the list of "styles elements" that should be inserted when the user starts typing, see description of InsertStyle. */
  1178. void ClearPendingStyles();
  1179. /** If lock == TRUE, ClearPendingStyles will do nothing. Use FALSE to unlock. Calls might be "nestled". */
  1180. void LockPendingStyles(BOOL lock) { m_pending_styles_lock += lock ? 1 : -1; OP_ASSERT(m_pending_styles_lock >= 0); }
  1181. /**
  1182. * This function is intended for doing all the work when the InsertOrderedList/InsertUnOrderedList
  1183. * commands are executed.
  1184. * @parm ordered Should be TRUE when InsertOrderedList is executed and FALSE when InsertUnOrderedList
  1185. * is executed.
  1186. */
  1187. void ToggleInsertList(BOOL ordered);
  1188. /** Returns TRUE is helm has block-level children */
  1189. BOOL HasBlockElementChildren(HTML_Element *helm);
  1190. /**
  1191. * "Adjusts" start_elm, stop_elm, start_ofs and stop_ofs to an "editable subrange", this means that (start_elm, start_ofs) and
  1192. * (stop_elm, stop_ofs) will be valid caret-positions after return. That is, if such positions exists >= (start_elm, start_ofs)
  1193. * and <= (stop_elm, stop_ofs)
  1194. * @return TRUE if an editable subrange where found.
  1195. * @parm start_elm The start element to be adjusted.
  1196. * @parm stop_elm The stop element to be adjusted.
  1197. * @parm start_ofs The start offset to be adjusted.
  1198. * @parm stop_ofs The stop offset to be adjusted.
  1199. */
  1200. BOOL GetEditableSubrange(HTML_Element *&start_elm, HTML_Element *&stop_elm, int &start_ofs, int &stop_ofs);
  1201. /**
  1202. * "Snaps" state.start_elm, state.stop_elm, state.start_ofs and state.stop_ofs so that state.start_elm and state.stop_elm
  1203. * are GetInserted() < HE_INSERTED_FIRST_HIDDEN_BY_ACTUAL, state are supposed no NOT be empty.
  1204. * @return TRUE if state is still valid upon return and not empty.
  1205. * @parm state The SelectionState to adjust.
  1206. */
  1207. BOOL ActualizeSelectionState(SelectionState &state);
  1208. /** Returns the current start_elm+stop_elm+start_ofs+stop_ofs if the current selection and de-selects
  1209. if there where no selection the caret-position will be reflected in the result instead. */
  1210. SelectionState GetSelectionState(BOOL de_select = TRUE, BOOL de_caret = FALSE, BOOL require_editable = TRUE, BOOL actual_only = FALSE);
  1211. /** Restores selection according to the SelectionState argument */
  1212. void RestoreSelectionState(SelectionState state);
  1213. /**
  1214. * "Adjusts" helm and ofs to a later text element in the tree if ofs > helm->GetTextContentLength(). This is usefull
  1215. * when helm has been splitted so that ofs is not within the element anymore and we wants to find the corresponing
  1216. * position in another text element.
  1217. * @return TRUE if a matching helm+ofs where found.
  1218. * @parm helm An HE_TEXT element.
  1219. * @parm ofs The offset.
  1220. */
  1221. BOOL AdjustTextOfs(HTML_Element *&helm, int &ofs);
  1222. /**
  1223. * Removes block-level elements like H3, BLOCKQUOTE, P, etc - from the current selection.
  1224. * @parm types An array of the kind of elements to be removed, terminated by HE_UNKNOWN.
  1225. * @parm attr If attr != ATTR_NULL, then will only elements with this attribute be removed.
  1226. * @parm just_one_level If TRUE -> just remove one nestling-level. For example, if HE_BLOCKQUOTE
  1227. * should be removed and one such element contains another such element, then only the first
  1228. * (ancestor) element will be removed.
  1229. * @parm exclude_at_bottom_type If TRUE, don't remove elements with no block-level children.
  1230. * This is sort of a hack for implementing the FormatBlock command by first inserting new blocks
  1231. * and then removing the old ones, the old blocks will then (if they contained TEXT/BR elements)
  1232. * contain newly created block elements, while the newly created elements will not contain any
  1233. * block-level elements.
  1234. */
  1235. void RemoveBlockTypes(HTML_ElementType *types, short attr = ATTR_NULL, BOOL just_one_level = FALSE, HTML_ElementType exclude_at_bottom_type = (HTML_ElementType)0);
  1236. /**
  1237. * Inserts copies of the block-level element helm over all TEXT/BR elements (and their
  1238. * inline-level ancestors). If only_over_cursor==TRUE however, helm itself will be inserted over the
  1239. * cursor-position, and helm will NOT be deleted - which it otherwise will.
  1240. * @return Error status code.
  1241. * @parm helm A block-level element to possibly create multiple duplicates of for inserting. helm
  1242. * will always be deleted before this function returns.
  1243. * @parm exclude_lists Don't inser elements at any place below OL/UL elements.
  1244. * @parm only_over_cursor If TRUE, helm itself (not a copy) will be inserted over the current cursor-
  1245. * position - and helm will not be deleted;
  1246. * @parm dont_insert_where_already_exists Dont insert elements when there is already an element of that type over
  1247. * the elements inside that block, and that already-existing element isn't ancestor of other elements.
  1248. * @parm will_be_removed_types This block-types are about to be removed. Helps this function to determine whether
  1249. * a block of elements are already "covered" if dont_insert_where_already_exists==TRUE.
  1250. */
  1251. OP_STATUS InsertBlockElementMultiple(HTML_Element *helm, BOOL exclude_lists = FALSE, BOOL only_over_cursor = FALSE, BOOL dont_insert_where_already_exists = FALSE, HTML_ElementType *will_be_removed_types = NULL);
  1252. /**
  1253. * Returns whether if the selection contains an matching block level element or if it contains elements
  1254. * which have such ancestors.
  1255. * @return TRUE if such element exists.
  1256. * @parm type The type to find...
  1257. * @parm attr If attr != ATTR_NULL, then an element must have this attribute to be consider as a match.
  1258. */
  1259. BOOL GetHasBlockType(HTML_ElementType type, short attr = ATTR_NULL);
  1260. /**
  1261. * Checks whether the current selection contains any block-level elements of the types specified
  1262. * by the types arrray.
  1263. * @return TRUE if there are any elements of the types in types in the selection.
  1264. * @parm types An array of the types to check for, terminated by HE_UNKNOWN.
  1265. * @parm attr If attr != ATT_NULL -> defines an attribute that must be present in the elements
  1266. * matching the types in types in order to consider it as a match.
  1267. */
  1268. BOOL GetHasBlockTypes(HTML_ElementType *types, short attr = ATTR_NULL);
  1269. /**
  1270. * Applies a function on all selected elements and returns whether all/some/at least one of the calls
  1271. * returns TRUE.
  1272. * Pseudo-code example:
  1273. *
  1274. * BOOL OpDocumentEdit::IsAllTextBold() { // returns FALSE if no HE_TEXT elements are selected
  1275. * return GetSelectionMatchesFunction(&HasElmType,(void*)HE_BOLD,&HasElmType,(void*)HE_TEXT,TRUE,FALSE);
  1276. * }
  1277. *
  1278. * @return TRUE if all/some/at least one of the calls to func applied on the elements that are selected returns TRUE.
  1279. * @parm func A function to apply on selected elements that returns an boolean.
  1280. * @parm func_arg An argument that will be passed along with the html element to func upon each call.
  1281. * @must_match If all_must_match==TRUE and func returns FALSE for an element, then GetSelectionMatchesFunction
  1282. * might ANYWAY return TRUE. This is a way for "relaxing" all_must_match a bit. May be NULL, and MUST be NULL
  1283. * if all_ancestors_must_match==TRUE.
  1284. * @parm must_match_arg An argument that will be passed along with the html element to must_match upon each call.
  1285. * @parm all_must_match If TRUE, func must return TRUE for all elements (at least one) that matches must_match.
  1286. * @parm all_ancestors_must_match ALL elements (except of body and above) that are selected including elements who's
  1287. * children are selected must be returned TRUE by func.
  1288. */
  1289. BOOL GetSelectionMatchesFunction(BOOL (*func)(HTML_Element*,void*), void *func_arg, BOOL (*must_match)(HTML_Element*,void*), void *must_match_arg, BOOL all_must_match, BOOL all_ancestors_must_match);
  1290. /**
  1291. * Calls function func for all elements between start_elm and stop_elm including all ancestors up to and including the
  1292. * editable root (body for designMode or the contenteditable root).
  1293. * @return Error status code, if any of the calls to func returns an error, this error will be returned (immedietly).
  1294. * @parm start_elm The first element to make the call for.
  1295. * @parm stop_elm The last element to make the call for.
  1296. * @parm func The function to call for each element: func(element, func_arg, return_value).
  1297. * @parm call_count If != NULL, will record how many calls that where made (one for each affected argument).
  1298. * @parm true_count If != NULL, will record how many of the calls that where returning TRUE in it's return-value argument.
  1299. * @parm only_actual If TRUE will only elements with GetInserted() < HE_INSERTED_FIRST_HIDDEN_BY_ACTUAL be processed.
  1300. */
  1301. OP_STATUS ApplyFunctionBetween(HTML_Element *start_elm, HTML_Element *stop_elm, OP_STATUS (*func)(HTML_Element*,void*,BOOL&), void *func_arg, int *call_count = NULL, int *true_count = NULL, BOOL only_actual = TRUE);
  1302. /**
  1303. * "Adjusts" the current selection (or caret-position) "backward" for start and "forward" to stop so that start
  1304. * is the first element on a line (first in block or after BR) and stop is the last on a line.
  1305. * @parm start Where the start element should be returned.
  1306. * @parm stop Where the stop element should be returned.
  1307. */
  1308. void GetBlockStartStop(HTML_Element** start, HTML_Element** stop);
  1309. /** Has the same effect as GetBlockStartStop but start the search from a single element (like when there are no
  1310. selection but just the caret for GetBlockStartStop), see description of GetBlockStartStop */
  1311. void GetBlockStartStopInternal(HTML_Element** start, HTML_Element** stop, HTML_Element* from);
  1312. /** Checks if helm is of type type and has attr attr.
  1313. If type is HE_ANY, any friendly element-type matches.
  1314. If attr is ATTR_NULL there will be no check for any attr. */
  1315. BOOL IsMatchingStyle(HTML_Element* helm, HTML_ElementType type, short attr);
  1316. /** Checks if helm has any of the types in the HE_UNKNOWN-terminated array types, and if attr!=ATTR_NULL - if
  1317. that attribute is present. */
  1318. BOOL IsAnyOfTypes(HTML_Element *helm, HTML_ElementType *types, short attr = ATTR_NULL);
  1319. /** Returns the ancestor of helm closest to the root matching any of the types in the HE_UNKNOWN-terminated array types, and
  1320. if attr != ATTR_NULL, also has attribute attr. */
  1321. HTML_Element* GetRootOfTypes(HTML_Element *helm, HTML_ElementType *types, short attr = ATTR_NULL);
  1322. /** Will make sure the element that matches type&attr is removed from the current selection. It will create new branches when needed, to
  1323. preserve the style on surrounding content. If just_one_level==TRUE, then will only one nestling level of style elements be removed,
  1324. this is useful for e.g. decreasing font-size where just one level of BIG elements should be removed */
  1325. void RemoveStyle(HTML_ElementType type, short attr = ATTR_NULL, BOOL just_one_level = FALSE);
  1326. /* Rreturn TRUE if any pending style elements (in m_pending_styles) is of type type */
  1327. BOOL GetHasPendingStyle(HTML_ElementType type, short attr = 0);
  1328. /** Return TRUE if the current selection or the insertpoint has parents that matches type&attr.
  1329. It will search parents up to nearest containing element. If all_must_have_style==TRUE, then
  1330. must all TEXT and BR elements have the matching style for TRUE to be returned. */
  1331. BOOL GetHasStyle(HTML_ElementType type, short attr = ATTR_NULL, BOOL all_must_have_style = FALSE, BOOL include_pending_styles = TRUE);
  1332. /** Like GetHasStyle but only checks the ancestors of helm instead of all selection. */
  1333. BOOL GetHasStyleInternal(HTML_Element* helm, HTML_ElementType type, short attr);
  1334. /** Returns the ancestor for helm that matches type and attr (or only type if attr == ATTR_NULL) */
  1335. HTML_Element* GetStyleElementInternal(HTML_Element* helm, HTML_ElementType type, short attr);
  1336. /** Checks if any ancestor of helm is matching any of the types defined in the HE_UNKNOWN-terminated array types and
  1337. has attribute attr (if attr != ATTR_NULL, then this doesn't need to be true). */
  1338. BOOL GetHasBlockTypesInternal(HTML_Element *helm, HTML_ElementType *types, short attr);
  1339. /** Get the top-most parent of type type */
  1340. HTML_Element* GetTopMostParentOfType(HTML_Element *helm, HTML_ElementType type);
  1341. /** Get the fontsize at the current location of the caret or 0 if not set. */
  1342. short GetFontSize();
  1343. /** Get the fontface at the current location of the caret or NULL if not set. */
  1344. const uni_char* GetFontFace();
  1345. /** Get the fontface at the current location of the caret or NULL if not set.
  1346. The output may include quotes and multiple font names separated with comma. */
  1347. OP_STATUS GetFontFace(TempBuffer &output);
  1348. /** Inserts linebreak at current caret position. If break_list is TRUE, new listitems may be created or deleted
  1349. depending of where the break is inserted.
  1350. if new_paragraph is TRUE a new paragraph is created if apropriate (not in list etc.), Otherwise a BR will be created. */
  1351. void InsertBreak(BOOL break_list = TRUE, BOOL new_paragraph = FALSE);
  1352. /** Inserts helm at current caret position. */
  1353. void InsertElement(HTML_Element* helm);
  1354. /** Clone the list of pending style elements into head */
  1355. OP_STATUS ClonePendingStyles(Head &head);
  1356. /** Add the style elements in head to the pending list (and remove them from head) */
  1357. void AddPendingStyles(Head &head);
  1358. /** Inserts pending style elements at current caret position.
  1359. *
  1360. * @param outmost_element Set to point to the outmost inserted element. May be NULL.
  1361. */
  1362. OP_STATUS InsertPendingStyles(HTML_Element** outmost_element = NULL);
  1363. /** Insert text at current caret position. If allow_append is TRUE, the text may be appended to the last event in the
  1364. * undo&redo-stack. (But it only will, if it follows the last event precisely.)
  1365. * If delete_selection is FALSE the current selection (if any) won't be deleted.
  1366. */
  1367. OP_STATUS InsertText(const uni_char* text, INT32 len,
  1368. BOOL allow_append = FALSE, BOOL delete_selection = TRUE);
  1369. /** Insert HTML-text at current caret position. It will skip eventual bodytag and only take the content.
  1370. If specified, result_start and result_stop will be set to the first and last child (Not last leaf!) that is inserted.
  1371. The new html can split the current branch up to split_root (or ContainingElement if not specified). */
  1372. OP_STATUS InsertTextHTML(const uni_char* text, INT32 len,
  1373. HTML_Element** result_start = NULL,
  1374. HTML_Element** result_stop = NULL,
  1375. HTML_Element* split_root = NULL,
  1376. TIDY_LEVEL tidy_level = TIDY_LEVEL_NORMAL,
  1377. BOOL delete_selection = TRUE);
  1378. /** Converts newlinecodes in text into <BR> elements. Use InsertText instead, since it will call this function if needed */
  1379. OP_STATUS InsertTextWithLinebreaks(const uni_char* text, INT32 len,
  1380. BOOL allow_append = FALSE);
  1381. /** Delete selected content or element active in layoutmodifier. */
  1382. void DeleteSelectedContent(BOOL aggressive = FALSE);
  1383. /** Returns true if helm is on an empty line, that is, if it only exists one valid caret-position. */
  1384. BOOL LineIsEmpty(HTML_Element *helm);
  1385. /** Returns TRUE if this containing_element needs to contain a BR element to not collapse.
  1386. If ignore_current_auto_inserted_br is TRUE, any existing automatically inserted BR will be ignored. */
  1387. BOOL NeedAutoInsertedBR(HTML_Element *containing_element, BOOL ignore_current_auto_inserted_br = FALSE);
  1388. /** Return TRUE if this containing_element contains a automatically inserted br. */
  1389. BOOL HasAutoInsertedBR(HTML_Element *containing_element);
  1390. /**
  1391. * Returns if buf[0] (buf is supposed to be a pointer somewhere into a string represent helm's text content),
  1392. * would collapse if it's a collapsable space, NOT considering that it might be collapsed anyway due to the
  1393. * previous content.
  1394. * @return TRUE if the char would collapse due to being at the end of a line.
  1395. * @parm buf Supposed to be a pointer somewhere into a string represent helm's text content.
  1396. * @helm Supposed to be an HE_TEXT element.
  1397. */
  1398. BOOL WillEndLineCollapseIfWs(uni_char *buf, HTML_Element *helm);
  1399. /** Reflows the document immediately. */
  1400. void ReflowAndUpdate();
  1401. /** Scroll to ensure caret is visible. */
  1402. void ScrollIfNeeded();
  1403. /** Let's the memory-manager rise an OOM condition. */
  1404. void ReportOOM();
  1405. /** Let's the memory-manager rise an OOM condition if status == ERR_NO_MEMORY. */
  1406. void ReportIfOOM(OP_STATUS status);
  1407. /** Check if the logical tree has changed (F.ex. after DOM has removed or added elements). If this has
  1408. happened we have to update the caret and the undoredostack. */
  1409. void CheckLogTreeChanged(BOOL caused_by_user = FALSE);
  1410. /** Called after reflow so that the caret's visual position could be updated. */
  1411. virtual void OnReflow();
  1412. /** Called when the document get focused or unfocused, starts or stops caret-blinking, and if focus == TRUE, the carets editable container will be focused */
  1413. virtual void OnFocus(BOOL focus, FOCUS_REASON reason);
  1414. /** Should be called when a element is inserted in the editable document. */
  1415. void OnElementInserted(HTML_Element* elm);
  1416. /** Should be called when an element is removed by HTML_Element::OutSafe, when it's STILL in the tree */
  1417. void OnBeforeElementOut(HTML_Element* elm);
  1418. /** Should be called before an element change e.g. its attributes */
  1419. void OnElementChange(HTML_Element* elm);
  1420. /** Should be called after an element has been changed e.g. its attributes */
  1421. void OnElementChanged(HTML_Element* elm);
  1422. /** Returns TRUE if OnBeforeElementOut is currently executing with elm as it's argument (see above). */
  1423. BOOL IsBeforeOutElm(HTML_Element *elm);
  1424. BOOL IsInBeforeElementOut() { return !m_before_out_elements.Empty(); }
  1425. /** Should be called when a element is removed from the editable document. */
  1426. void OnElementRemoved(HTML_Element *elm);
  1427. /** Should be called when a element is deleted. */
  1428. void OnElementDeleted(HTML_Element *elm);
  1429. /**
  1430. * Internal docxs function that must be called when the parser or something else causes
  1431. * an HE_TEXT element to be converted into an HE_TEXTGROUP element.
  1432. *
  1433. * @param elm The element that used to be an HE_TEXT but is now an HE_TEXTGROUP.
  1434. *
  1435. * @see HTML_Element::AppendText().
  1436. */
  1437. void OnTextConvertedToTextGroup(HTML_Element* elm);
  1438. void OnTextChange(HTML_Element *elm);
  1439. void OnTextChanged(HTML_Element *elm);
  1440. void OnTextElmGetsLayoutWords(HTML_Element *elm);
  1441. /** Should be called when scalefactor has been changed, to update caret position. */
  1442. void OnScaleChanged();
  1443. /** Should be called when layout has been moved without reflow (F.ex. when a ScrollableContainer is scrolled) */
  1444. void OnLayoutMoved();
  1445. #ifdef SUPPORT_TEXT_DIRECTION
  1446. /** Set direction of current editable container. Returns TRUE if it was changed, FALSE if it already had the given direction. */
  1447. BOOL SetRTL(bool is_rtl);
  1448. #endif
  1449. BOOL GetRTL() { return m_caret.GetCaretManager()->GetRTL(GetEditableContainer(m_caret.GetElement())); }
  1450. #ifdef DOCUMENTEDIT_AUTODETECT_DIRECTION
  1451. /** Enable or Disable automatic detection of direction change. Direction change is signaled to OpTCListener::TCOnRTLDetected */
  1452. void SetAutodetectDirection(BOOL autodetect) { m_autodetect_direction = autodetect; }
  1453. #endif
  1454. #ifdef DOCUMENTEDIT_SPLIT_BLOCKQUOTE
  1455. /** Enable or Disable split of blockquotes on insert of break */
  1456. void SetSplitBlockquote(BOOL split) { m_blockquote_split = split; }
  1457. #endif
  1458. #ifdef DOCUMENTEDIT_PLAIN_TEXT_MODE
  1459. /** Enable or Disable plain text mode (disables formatting shortcuts and formatted text pasting) */
  1460. void SetPlainTextMode(BOOL enable) { m_plain_text_mode = enable; }
  1461. #endif
  1462. /* Set if the tab-key should have any effect or not while editing. */
  1463. void SetWantsTab(BOOL status) { m_wants_tab = status; }
  1464. /** Prepare root element for editing */
  1465. void InitEditableRoot(HTML_Element* root);
  1466. /** Unactivate editing on this element */
  1467. void UninitEditableRoot(HTML_Element* root);
  1468. /** Set focus to the editable element (element should be contentEditable) */
  1469. void FocusEditableRoot(HTML_Element* helm, FOCUS_REASON reason);
  1470. /** Returns the FramesDocument associated with this OpDocumentEdit instance. */
  1471. FramesDocument* GetDoc() { return m_doc; }
  1472. /* Returns TRUE if designMode is on for the document. */
  1473. BOOL IsUsingDesignMode() { return m_body_is_root; }
  1474. /** Begin something that will change element-tree in some way but shouldn't be recorded by the undostack.
  1475. F.ex. a undo or redo event, or initiating stuff. Note, that all events (execpt undo+redo) that change
  1476. the element-tree must use BeginChange to inform the undostack or clear it. */
  1477. void Begin();
  1478. void End();
  1479. void Abort();
  1480. /** Begin something that will change element-tree in some way.
  1481. containing_elm MUST be a element that contains the entire change. As close in to the change as possible
  1482. to save memory. If allow_append is TRUE, the change will be merged with the previous if they are next to
  1483. each other.
  1484. Tidy will be called with the aggressive_tidy flag. (Read more about it on Tidy)*/
  1485. OP_STATUS BeginChange(HTML_Element* containing_elm, int flags = CHANGE_FLAGS_NONE);
  1486. OP_STATUS EndChange(HTML_Element* containing_elm, TIDY_LEVEL tidy_level = TIDY_LEVEL_NORMAL);
  1487. /** A more "customized" variant of EndChange that also defines the start- and stop-elements which should be used as arguments to Tidy() */
  1488. OP_STATUS EndChange(HTML_Element* containing_elm, HTML_Element *start_elm, HTML_Element *stop_elm, BOOL include_start_stop, TIDY_LEVEL tidy_level = TIDY_LEVEL_NORMAL);
  1489. void AbortChange();
  1490. // == Input =======================
  1491. void EditAction(OpInputAction* action);
  1492. virtual BOOL OnInputAction(OpInputAction* action);
  1493. virtual const char* GetInputContextName() { return "Edit Widget"; }
  1494. virtual void OnKeyboardInputGained(OpInputContext* new_input_context, OpInputContext* old_input_context, FOCUS_REASON reason);
  1495. virtual void OnKeyboardInputLost(OpInputContext* new_input_context, OpInputContext* old_input_context, FOCUS_REASON reason);
  1496. virtual BOOL GetBoundingRect(OpRect &rect);
  1497. #ifdef WIDGETS_IME_SUPPORT
  1498. # ifndef DOCUMENTEDIT_DISABLE_IME_SUPPORT
  1499. virtual IM_WIDGETINFO OnStartComposing(OpInputMethodString* imstring, IM_COMPOSE compose);
  1500. virtual IM_WIDGETINFO OnCompose();
  1501. virtual IM_WIDGETINFO GetWidgetInfo();
  1502. virtual void OnCommitResult();
  1503. virtual void OnStopComposing(BOOL cancel);
  1504. # endif
  1505. # ifdef IME_RECONVERT_SUPPORT
  1506. virtual void OnPrepareReconvert(const uni_char*& str, int& sel_start, int& sel_stop);
  1507. virtual void OnReconvertRange(int sel_start, int sel_stop) ;
  1508. # endif
  1509. #endif
  1510. // == Misc. helpers ========================
  1511. /** Sets the text-content of helm to text... */
  1512. void SetElementText(HTML_Element* helm, const uni_char* text, int len = -1);
  1513. /** Sets if the element is inserted by the documentedit code automatically (automatically inserted elements are removed automatically too in the Tidy function). */
  1514. OP_STATUS SetInsertedAutomatically(HTML_Element* helm, BOOL inserted_automatically);
  1515. BOOL GetInsertedAutomatically(HTML_Element* helm);
  1516. OP_STATUS SetSpecialAttr(HTML_Element* helm, Markup::AttrType attr, BOOL value);
  1517. BOOL GetSpecialAttr(HTML_Element* helm, Markup::AttrType attr);
  1518. /** Is CSS_VALUE_pre or CSS_VALUE_pre_wrap used when layouting helm? */
  1519. BOOL IsInPreFormatted(HTML_Element *helm);
  1520. /** Use when user is inserting or removing text in a textelement. Removes or inserts nbsp or regular spaces.
  1521. (If user types several spaces after each other, we have to make nbsp to not collapse them) */
  1522. BOOL RemoveNBSPIfPossible(HTML_Element* helm);
  1523. /** Returns if helm is first on a line or if the last character before is a collapsable whitespace. */
  1524. BOOL IsBeforeCollapsedOrEdge(HTML_Element* helm);
  1525. /** Returns if helm is last on a line or if the last character after is a collapsable whitespace. */
  1526. BOOL IsAfterCollapsedOrEdge(HTML_Element* helm);
  1527. /* Is helm an ending BR (there are content on the line before the BR)
  1528. *
  1529. * @param helm The BR element to check.
  1530. * @param helm_to_remove Element that is to be removed in a moment, it will not be considered as content.
  1531. */
  1532. BOOL IsEndingBr(HTML_Element* helm, HTML_Element* helm_to_remove = NULL);
  1533. /**
  1534. * Get the nearest valid caret position starting from from_helm.
  1535. * @return If such position was found.
  1536. * @parm from_helm The element to start the scan from.
  1537. * @parm nearest_helm The element that was found, if it was found.
  1538. * @parm nearest_ofs The offset that was found, if it was found.
  1539. * @parm forward TRUE if the logical tree should be scanned forward, else backward.
  1540. * @parm include_current TRUE if we should try with from_helm itself first.
  1541. * @parm helm_to_remove Element that is to be removed in a moment, it is not a valid position for the caret.
  1542. */
  1543. BOOL GetNearestCaretPos(HTML_Element* from_helm, HTML_Element** nearest_helm, int* nearest_ofs, BOOL forward, BOOL include_current, HTML_Element* helm_to_remove = NULL);
  1544. /**
  1545. * Finds the next valid caret-position starting from helm and ofs.
  1546. * @return If such position was found.
  1547. * @parm helm The element to start the scan from.
  1548. * @parm ofs The offset to start the scan from.
  1549. * @parm new_helm The element that was found, if it was found (might be helm itself).
  1550. * @parm new_ofs The offset that was found, if it was found.
  1551. * @parm snap If TRUE, tries to "snap" the result to an HE_TEXT element
  1552. * @parm accept_no_diff If TRUE, it's alright if the new position visually is on the same place as the old one,
  1553. * for example: hej|<b>du</b> -> hej<b>|du</b> where | represents the position.
  1554. */
  1555. BOOL GetOneStepBeside(BOOL forward, HTML_Element *helm, int ofs, HTML_Element *&new_helm, int &new_ofs, BOOL snap = TRUE, BOOL accept_no_diff = FALSE) { return m_caret.GetCaretManager()->GetOneStepBeside(forward, helm, ofs, new_helm, new_ofs, snap, accept_no_diff); }
  1556. /**
  1557. * Tries to find the "best" caret position starting from helm, somewhere close to helm hopefully.
  1558. * @return TRUE if such position was found.
  1559. * @parm helm The element to start the scan from, but excluding helm and it's children.
  1560. * @parm new_helm The element that was found, if it was found (will NOT be helm itself).
  1561. * @parm new_ofs The offset that was found, if it was found.
  1562. * @parm prefer_first If YES, give a hint that we would prefer an element before helm, or if NO that we prefer one after.
  1563. * @parm must_be_friends If TRUE, only valid caret-positions at elements that are "friends" (see IsFriends) is accepted.
  1564. * @parm helm_to_remove Element that is to be removed in a moment, it is not a valid position for the caret.
  1565. */
  1566. BOOL GetBestCaretPosFrom(HTML_Element *helm, HTML_Element *&new_helm, int &new_ofs, BOOL3 prefer_first = MAYBE, BOOL must_be_friends = FALSE, HTML_Element *helm_to_remove = NULL);
  1567. /**
  1568. * Works like GetBestCaretPosFrom but includes helm itself and it's possible child-elements to find a caret-position.
  1569. * If helm has no own caret-position but has children and ofs == 0 then the scan for caret position among it's children
  1570. * will start at helm->FirstChildActual() and go forward, if ofs >= 1 it will start from helm->LastLeafActual() and go
  1571. * backwards. If still no valid position has been found will GetBestCaretPosFrom be used.
  1572. * @returns TRUE if a valid caret-position was found.
  1573. * @parm helm The element to start the scan from, including helm and it's children.
  1574. * @parm new_helm The element that was found, if it was found.
  1575. * @parm new_ofs The offset that was found, if it was found.
  1576. */
  1577. BOOL GetValidCaretPosFrom(HTML_Element *helm, int ofs, HTML_Element *&new_helm, int &new_ofs);
  1578. /**
  1579. * Returns the last valid caret-offset in helm (consider white-space collapsing in text-elements).
  1580. * @return TRUE if such caret-offset was found in helm.
  1581. * @parm helm The element to perform the operation on...
  1582. * @parm ofs The resulting last valid caret-offset.
  1583. */
  1584. BOOL GetLastValidCaretOfs(HTML_Element *helm, int &ofs);
  1585. /**
  1586. * Returns the first valid caret-offset in helm (consider white-space collapsing in text-elements).
  1587. * @return TRUE if such caret-offset was found in helm.
  1588. * @parm helm The element to perform the operation on...
  1589. * @parm ofs The resulting first valid caret-offset.
  1590. */
  1591. BOOL GetFirstValidCaretOfs(HTML_Element *helm, int &ofs);
  1592. /**
  1593. * Finds an editable element starting from from_helm, that is, an elements which includes a valid caret-position.
  1594. * @return The editable element that was found, or NULL if no such element was found.
  1595. * @parm forward If TRUE, searches forward in the logical tree, else backwards.
  1596. * @parm include_current If TRUE, from_helm itself will be the first candidate scanned.
  1597. * @parm require_box Only return elements with a layout box.
  1598. * @parm include_ending_br If TRUE may an ending BR be returned, that is, a BR that ends a line with previous valid caret-positions.
  1599. * @parm helm_to_remove Element that is to be removed in a moment, it is not a valid position for the caret and should be omitted
  1600. * during the search
  1601. */
  1602. HTML_Element* FindEditableElement(HTML_Element* from_helm, BOOL forward, BOOL include_current, BOOL require_box, BOOL include_ending_br = FALSE, HTML_Element* helm_to_remove = NULL);
  1603. /**
  1604. * Finds the first element previous to helm that is of type type.
  1605. * @return Such element, or NULL if not found.
  1606. * @parm type The type to find.
  1607. * @parm require_box If TRUE, only returns an element with a layout box.
  1608. */
  1609. HTML_Element* FindElementBeforeOfType(HTML_Element* helm, HTML_ElementType type, BOOL require_box = FALSE);
  1610. /**
  1611. * Finds the first element next to helm that is of type type.
  1612. * @return Such element, or NULL if not found.
  1613. * @parm type The type to find.
  1614. * @parm require_box If TRUE, only returns an element with a layout box.
  1615. */
  1616. HTML_Element* FindElementAfterOfType(HTML_Element* helm, HTML_ElementType type, BOOL require_box = FALSE);
  1617. /**
  1618. * Makes sure the editable container container (that is, body for designMode or a content editable element) has
  1619. * a valid caret-position at the end or beginning. This means that if e.g. container ends with a HR element, then
  1620. * a new empty text-element will be inserted after the HR in order to permitt the user to put the caret under the
  1621. * HR. If no editing action has been performed when the user puts the caret somewhere else will the text-element
  1622. * be removed.
  1623. * @return If not NULL, a empty-text element that was created at the beginning or end of container.
  1624. * @parm helm If container == NULL and helm != NULL, then will container be GetEditableContainer for helm.
  1625. * @parm container The editable container, may be NULL if helm != NULL.
  1626. * @parm at_end If TRUE, possibly add empty text element at end of container, otherwise at the beginning.
  1627. */
  1628. HTML_Element* MakeSureHasValidEdgeCaretPos(HTML_Element *helm, HTML_Element *container, BOOL at_end);
  1629. /** Creates and returns a new HE_TEXT element with text-content the first len characters of text. */
  1630. HTML_Element* NewTextElement(const uni_char* text, int len);
  1631. /** Creates a new HTML_Element with type type and calls HTML_Element::SetEndTagFound on it. */
  1632. HTML_Element* NewElement(HTML_ElementType type, BOOL set_automatic_flag = FALSE);
  1633. /** Duplicates the element and returns the new duplicate. It does not include children. */
  1634. HTML_Element* NewCopyOfElement(HTML_Element* helm, BOOL remove_id = FALSE);
  1635. /** Returns TRUE if helm->GetTextContent()[ofs] is collapsed for HE_TEXT element helm. */
  1636. BOOL IsCharCollapsed(HTML_Element *helm, int ofs);
  1637. /**
  1638. * Deletes len charachters in the text-content of the HE_TEXT element helm starting from offset start_ofs.
  1639. * @return TRUE if text-content was deleted.
  1640. * @parm start_ofs The offset to start the deleting from.
  1641. * @len How many characters to delete.
  1642. */
  1643. BOOL DeleteTextInElement(HTML_Element* helm, INT32 start_ofs, INT32 len);
  1644. /** Returns TRUE if helm has no layout-box or if helm is a text-element with no valid caret-position. */
  1645. BOOL IsCollapsed(HTML_Element* helm);
  1646. /**
  1647. * Returns the next (if forward) or previous (if !forward) non-empty text-element from (but excluding) helm
  1648. * if that element starts (if forward) or ends (if !forward) with a "collapsable" space that is currently
  1649. * not collapsed, if this is not the situation - NULL is returned.
  1650. */
  1651. HTML_Element *GetEdgeHelmMightWsCollapse(HTML_Element *helm, BOOL forward);
  1652. /** Split a (text)element in 2 if ofs is not 0 or at the last caracter. Returns TRUE if the split was done. */
  1653. BOOL SplitElement(HTML_Element* helm, INT32 ofs);
  1654. /** Is a element that doesn't have endtag. F.ex. text, br, hr.. */
  1655. BOOL IsStandaloneElement(HTML_Element* helm) { return CaretManager::IsStandaloneElement(helm); }
  1656. /** Returns TRUE if the element has replaced content */
  1657. BOOL IsReplacedElement(HTML_Element *helm, BOOL must_have_replaced_content = FALSE) { return CaretManager::IsReplacedElement(helm, must_have_replaced_content); }
  1658. void AddInternalEventListener(OpDocumentEditInternalEventListener *listener) { if(listener){listener->Out();listener->Into(&m_internal_event_listeners);}}
  1659. void RemoveInternalEventListener(OpDocumentEditInternalEventListener *listener) { if(listener)listener->Out(); }
  1660. /**
  1661. * Adds a "whitespace preserving operation", this means that the caret might be put at text-elements involved in the
  1662. * operation even though they currently only have collapsed whitespaces as they will "soon" (when preserver->WsPreserve
  1663. * is called) will have un-collapsed whitespaces.
  1664. * @parm preserver The OpDocumentEditWsPreserver that will later be used to preserve the collapse-state of the
  1665. * possible whitespaces before and after the range that has been marked upon construction of preserver.
  1666. */
  1667. void AddWsPreservingOperation(OpDocumentEditWsPreserver *preserver);
  1668. /** Removes preserver from the list of current "whitespace preserving operations", see AddWsPreservingOperation. */
  1669. void RemoveWsPreservingOperation(OpDocumentEditWsPreserver *preserver);
  1670. /**
  1671. * Returns whether helm is in a "whitespace preserving operation" (see AddWsPreservingOperation).
  1672. * @return TRUE if helm is in such an operation + some more constraints, see was_collapsed below.
  1673. * @parm The element...
  1674. * @was_collapsed If was_collapsed == MAYBE, return if helm is in whitespace preserving operation. If
  1675. * was_collapsed == YES, only return TRUE if the "preserved" whitespace was collapsed. if was_collapsed == NO,
  1676. * only return TRUE if the "preserved" whitespace was un-collapsed. The current collapsing-state might differ
  1677. * from the original, but the original will be resored upon calling OpDocumentEditWsPreserver::WsPreserve.
  1678. */
  1679. BOOL IsInWsPreservingOperation(HTML_Element *helm, BOOL3 was_collapsed = MAYBE);
  1680. /**
  1681. * Is element valid for putting the caret on?
  1682. * @return TRUE if there are at least one valid caret-position inside helm.
  1683. * @parm helm The element to perform the check on...
  1684. * @parm is_in_tree If FALSE, helm is not supposed to be in the document's logical tree which implies that
  1685. * helm doesn't need to have an editable container and that no check for if helm is collapsed occurs.
  1686. * @parm helm_to_remove Element that is to be removed in a moment, it is not a valid position for the caret.
  1687. */
  1688. BOOL IsElementValidForCaret(HTML_Element *helm, BOOL is_in_tree = TRUE, BOOL ending_br_is_ok = FALSE, BOOL valid_if_possible = FALSE, HTML_Element* helm_to_remove = NULL);
  1689. /** Returns TRUE if helm is a block-level element. FIXME: not quite accurate, it currently only checks helm's type. */
  1690. BOOL IsBlockElement(HTML_Element *helm) { return CaretManager::IsBlockElement(m_doc, helm); }
  1691. /** Is a element which childs is treated as if in the same string as other childs in a friendly element.
  1692. Basically all inlineelements, with some exceptions if include_replaced is FALSE.
  1693. Use to determine if the caret should move right into it or require a extra keypress. F.ex. a, b, u */
  1694. BOOL IsFriendlyElement(HTML_Element* helm, BOOL include_replaced = FALSE, BOOL br_is_friendly = FALSE, BOOL non_editable_is_friendly = FALSE);
  1695. /** Checks if helm_a and helm_b is friends. (Has the same "unfriendly" parent) */
  1696. BOOL IsFriends(HTML_Element* helm_a, HTML_Element* helm_b, BOOL include_helm_b = TRUE, BOOL include_replaced = FALSE, BOOL br_is_friendly = FALSE);
  1697. /** Just a wrapper around Box::GetBBox... */
  1698. BOOL GetContentRectOfElement(HTML_Element *helm, AffinePos &ctm, RECT &rect, BoxRectType type = CONTENT_BOX);
  1699. /** If the element should be kept when tidying (all conditions. even if it's fully enclosed by the selection start and stop) */
  1700. BOOL KeepWhenTidy(HTML_Element* helm);
  1701. /** If the element should be kept when tidying (even if no childelements. but remove if fully enclosed by the selection start and stop) */
  1702. BOOL KeepWhenTidyIfEmpty(HTML_Element* helm);
  1703. /** If the element can have text content */
  1704. BOOL IsNoTextContainer(HTML_Element* helm);
  1705. /** If helm and all its children is enclosed by start and stop. */
  1706. BOOL IsEnclosedBy(HTML_Element* helm, HTML_Element* start, HTML_Element* stop);
  1707. /** If there is any textelements between start and stop (not including start and stop) */
  1708. BOOL ContainsTextBetween(HTML_Element* start, HTML_Element* stop);
  1709. /**
  1710. * Returns a TextSelectionPoint representing the (caret-position helm, character_offset), does currently NOT
  1711. * perform any conversion to DOM-style semantics with parent and child-offset.
  1712. * @return the OldStyleTextSelectionPoint...
  1713. * @parm character_offset The "element character offset", might be "snapped" to a valid value.
  1714. * @parm prefer_first FIXME: This is argument is not used anymore, remove it???
  1715. */
  1716. OldStyleTextSelectionPoint GetTextSelectionPoint(HTML_Element* helm, int character_offset, BOOL prefer_first = FALSE);
  1717. /**
  1718. * Stores helm and it's child-tree as text-html representation in text.
  1719. * @return Error status code...
  1720. * @parm text The place to store the result.
  1721. * @parm helm The element!
  1722. * @parm include_helm If FALSE, only the content of helm's child-tree will be "textualized" and NOT helm itself.
  1723. */
  1724. OP_STATUS GetTextHTMLFromElement(OpString& text, HTML_Element* helm, BOOL include_helm);
  1725. /** Delete helm in a safe manner */
  1726. void DeleteElement(HTML_Element* helm, BOOL check_caret = TRUE) { DeleteElement(helm, this, check_caret); }
  1727. static void DeleteElement(HTML_Element* helm, OpDocumentEdit* edit, BOOL check_caret = TRUE);
  1728. /**
  1729. * Stores helm and it's child-tree as text-html representation in text.
  1730. *
  1731. * @param[out] text The place to store the result.
  1732. * @param[in] element_name name of the helm!
  1733. * @param[in] include_helm If FALSE, only the content of helm's child-tree will be "textualized" and NOT helm itself.
  1734. *
  1735. * @return OpStatus::OK if found, OpStatus::ERR if element not found or out of memory
  1736. */
  1737. OP_STATUS GetTextHTMLFromNamedElement(OpString& text, const uni_char* element_name, BOOL include_helm);
  1738. /**
  1739. * Delete a named helm in a safe manner and return TRUE if it succeeded finding and deleting it.
  1740. *
  1741. * NOTE: This method doesn't submit changes to the undo/redo stack, so any existing events in
  1742. * the undo/redo stack will be cleared when this is called!
  1743. */
  1744. BOOL DeleteNamedElement(const uni_char* element_name);
  1745. /** Find top-most parent that is content-editable.
  1746. *
  1747. * Returns NULL if not found.
  1748. */
  1749. HTML_Element* GetTopEditableParent(HTML_Element* element);
  1750. /** Returns the closest containing element that contains both elm1 and elm2 */
  1751. HTML_Element* GetSharedContainingElement(HTML_Element* elm1, HTML_Element* elm2);
  1752. /** Returns the root of the logical document. */
  1753. HTML_Element* GetRoot();
  1754. /** Returns the document's body element, if not present the HE_HTML element will be returned,
  1755. if it doesn't exists either, the logical document's root will be returned. */
  1756. HTML_Element* GetBody();
  1757. /** Returns the editable container for helm, that is, body when designMode is on or the nearest
  1758. enclosing content editable element otherwise.
  1759. The returned container is never outside of the body element, e.g. in case when the html
  1760. element is contentEditable the body element is returned by this function
  1761. (provided that there is one). */
  1762. HTML_Element* GetEditableContainer(HTML_Element* helm);
  1763. /** Returns the editable container for helm, that is, body when designMode is on or the nearest
  1764. enclosing content editable element otherwise. If helm is outside of body, but is still
  1765. within an editing host, body will be returned as the container.
  1766. The returned container is never outside of the body element, e.g. in case when the html
  1767. element is contentEditable the body element is returned by this function
  1768. (provided that there is one). */
  1769. HTML_Element* GetFocusableEditableContainer(HTML_Element* helm);
  1770. /** Returns an ancestor of helm (or helm itself) which is suitable for inserting an HE_HR element below (e.g. usually NOT an HE_P element) */
  1771. HTML_Element* GetHrContainer(HTML_Element *helm);
  1772. /** Remove garbage elements. It won't remove elements returned by KeepWhenTidy.
  1773. If aggressive_tidy is TRUE it will remove empty textelements and their parents if
  1774. they become empty. It will never touch any elements above start_helm and stop_helm. */
  1775. void Tidy(HTML_Element* start_helm, HTML_Element* stop_helm, BOOL include_start_stop, TIDY_LEVEL tidy_level = TIDY_LEVEL_NORMAL, BOOL keep_dummy = FALSE, HTML_Element *shared_containing_elm = NULL);
  1776. public:
  1777. FramesDocument* m_doc;
  1778. OpDocumentEditCaret m_caret;
  1779. OpDocumentEditSelection m_selection;
  1780. Head m_internal_event_listeners;
  1781. OpDocumentEditUndoRedoStack m_undo_stack;
  1782. OpDocumentEditLayoutModifier m_layout_modifier;
  1783. #ifdef INTERNAL_SPELLCHECK_SUPPORT
  1784. OpSpellCheckerSession *m_spell_session;
  1785. BOOL m_has_spellchecked;
  1786. HTML_WordIterator m_word_iterator;
  1787. HTML_WordIterator m_replace_word;
  1788. HTML_WordIterator m_background_updater;
  1789. HTML_Element *m_pending_spell_first, *m_pending_spell_last;
  1790. WordInfo *m_delay_misspell_word_info;
  1791. BOOL m_doc_has_changed;
  1792. HTML_Element *m_last_helm_spelled;
  1793. int m_next_wi_index_to_spell;
  1794. BOOL m_last_helm_spelled_needs_update;
  1795. BOOL m_enable_spellcheck_later;
  1796. BOOL m_blocking_spellcheck;
  1797. BOOL m_by_user;
  1798. #endif // INTERNAL_SPELLCHECK_SUPPORT
  1799. int m_pending_styles_lock;
  1800. Head m_pending_styles;
  1801. Head m_ws_preservers;
  1802. Head m_before_out_elements;
  1803. INT32 m_begin_count;
  1804. BOOL m_logtree_changed;
  1805. BOOL m_usecss;
  1806. BOOL m_readonly;
  1807. BOOL m_wants_tab;
  1808. BOOL m_body_is_root;
  1809. BOOL m_autodetect_direction;
  1810. BOOL m_blockquote_split;
  1811. BOOL m_plain_text_mode;
  1812. #ifdef WIDGETS_IME_SUPPORT
  1813. # ifndef DOCUMENTEDIT_DISABLE_IME_SUPPORT
  1814. IM_WIDGETINFO GetIMInfo();
  1815. HTML_Element* BuildInputMethodStringElement();
  1816. void EmptyInputMethodStringElement(BOOL remove=FALSE);
  1817. BOOL IsImComposing() { return m_ime_string_elm != NULL; }
  1818. const OpInputMethodString* m_imstring;
  1819. HTML_Element* m_ime_string_elm;
  1820. BOOL im_waiting_first_compose;
  1821. # endif
  1822. #endif
  1823. private:
  1824. OP_STATUS InsertPlainText(const uni_char *text, INT32 len);
  1825. // Temporary storage of selection-points and caret element.
  1826. OldStyleTextSelectionPoint m_start_sel_copy;
  1827. OldStyleTextSelectionPoint m_stop_sel_copy;
  1828. HTML_Element *m_caret_elm_copy;
  1829. HTML_Element *m_content_pending_helm; ///< Content is about to be added to this element (Set during a insert operation before it's inserted)
  1830. OpDocumentEditListener*
  1831. m_listener;
  1832. #ifdef _DOCEDIT_DEBUG
  1833. BOOL m_random_seed_initialized;
  1834. OpDocumentEdit *m_edit;
  1835. #endif // _DOCEDIT_DEBUG
  1836. BOOL m_recreate_caret;
  1837. HTML_ElementType m_paragraph_element_type; ///< The element to use for paragraphs (e.g. HE_P or HE_DIV). Should be a block element.
  1838. /** The flag remembering if OpDocumentEdit is being focused atm.
  1839. * It's needed because sometimes if <html contenteditable> is being
  1840. * focused we'll focus <body> anyway to prevent going out of <body>
  1841. * in editable documents/elements. Since <body> is set as the focused
  1842. * element in a document while focusing if <html contenteditable> was
  1843. * set as such before the focus will be tried to be cleared and it has
  1844. * to be prevented.
  1845. */
  1846. BOOL m_is_focusing;
  1847. };
  1848. /** The document edit specific element reference. It protects HTML elements being currently used against Tidy(). */
  1849. class DoceditRef : public ElementRef
  1850. {
  1851. public:
  1852. virtual BOOL IsA(ElementRefType type) { return type == ElementRef::DOCEDITELM; }
  1853. };
  1854. #endif // DOCUMENT_EDIT_SUPPORT
  1855. #endif // OP_DOCUMENTEDIT_H