+2004-09-22 Darin Adler <darin@apple.com>
+
+ - renamed these files:
+
+ misc/khtml_text_operations.h -> editing/visible_text.h
+ misc/khtml_text_operations.cpp -> editing/visible_text.cpp
+ xml/dom_caretposition.cpp -> editing/visible_position.cpp
+ xml/dom_caretposition.h -> editing/visible_position.h
+ xml/dom_selection.cpp -> editing/selection.cpp
+ xml/dom_selection.h -> editing/selection.h
+
+ - broke out the word/line/paragraph part of visible_position.h into visible_units.h
+ - removed some unnecessary includes from some header files to reduce the number of
+ files that trigger "building the world"
+
+ * WebCore.pbproj/project.pbxproj: Added the files under new names, removed the old ones.
+
+ * ForwardingHeaders/editing/jsediting.h: Added.
+ * ForwardingHeaders/editing/visible_text.h: Added.
+ * ForwardingHeaders/misc/khtml_text_operations.h: Removed.
+ * ForwardingHeaders/xml/dom_caretposition.h: Removed.
+ * ForwardingHeaders/xml/dom_selection.h: Removed.
+
+ * khtml/ecma/kjs_window.cpp: Updated or removed #include lines.
+ * khtml/editing/htmlediting.cpp: Ditto.
+ * khtml/editing/htmlediting.h: Ditto.
+ * khtml/editing/htmlediting_impl.cpp: Ditto.
+ * khtml/editing/htmlediting_impl.h: Ditto.
+ * khtml/editing/jsediting.cpp: Ditto.
+ * khtml/editing/selection.cpp: Ditto.
+ * khtml/editing/selection.h: Ditto.
+ * khtml/editing/visible_position.cpp: Ditto.
+ * khtml/editing/visible_position.h: Ditto.
+ * khtml/editing/visible_text.cpp: Ditto.
+ * khtml/editing/visible_text.h: Ditto.
+ * khtml/editing/visible_units.cpp: Added.
+ * khtml/editing/visible_units.h: Added.
+ * khtml/html/html_elementimpl.cpp: Updated or removed #include lines.
+ * khtml/khtml_part.cpp: Ditto.
+ * khtml/khtml_part.h: Ditto.
+ * khtml/khtmlpart_p.h: Ditto.
+ * khtml/khtmlview.cpp: Ditto.
+ * khtml/misc/khtml_text_operations.cpp: Removed.
+ * khtml/misc/khtml_text_operations.h: Removed.
+ * khtml/rendering/render_block.cpp: Updated or removed #include lines.
+ * khtml/xml/dom2_rangeimpl.cpp: Ditto.
+ * khtml/xml/dom_caretposition.cpp: Removed.
+ * khtml/xml/dom_caretposition.h: Removed.
+ * khtml/xml/dom_docimpl.cpp: Updated or removed #include lines.
+ * khtml/xml/dom_docimpl.h: Ditto.
+ * khtml/xml/dom_elementimpl.cpp: Ditto.
+ * khtml/xml/dom_nodeimpl.cpp: Ditto.
+ * khtml/xml/dom_position.cpp: Ditto.
+ * khtml/xml/dom_selection.cpp: Removed.
+ * khtml/xml/dom_selection.h: Removed.
+ * kwq/KWQKHTMLPart.mm: Updated or removed #include lines.
+ * kwq/KWQKHTMLPart.h: Ditto.
+ * kwq/KWQRenderTreeDebug.cpp: Ditto.
+ * kwq/WebCoreBridge.mm: Ditto.
+
2004-09-22 Richard Williamson <rjw@apple.com>
Pass dashboard regions up to WebKit.
--- /dev/null
+#include <jsediting.h>
--- /dev/null
+#include <visible_text.h>
+++ /dev/null
-#include <khtml_text_operations.h>
+++ /dev/null
-#include <dom_caretposition.h>
+++ /dev/null
-#include <dom_selection.h>
832556E5061DF155007B8054,
BC86FB8F061F5C23006BB822,
BE8BD8F506359F6000D3F20B,
- BE8BD90B0635CC2F00D3F20B,
- 9342E3EB0646C8FF00004B05,
931D712C065FB91800C966E1,
931D7225065FC25900C966E1,
93859E33065FCAD300CF54EE,
BC06F25006D18A7E004A6FA3,
93ABCE6006E1A42E0085925B,
93B641F406E28C5C0055F610,
- BEF3442706F1123C000A65D3,
BE855F800701E83500239769,
5150C2A20702629000AF642C,
+ 93ABE06F070285F600BD91F9,
+ 93ABE071070285F600BD91F9,
+ 93ABE073070285F600BD91F9,
+ 93ABE075070285F600BD91F9,
);
isa = PBXHeadersBuildPhase;
runOnlyForDeploymentPostprocessing = 0;
832556E7061DF161007B8054,
BC86FB90061F5C23006BB822,
BE8BD8F406359F6000D3F20B,
- BE8BD90A0635CC2F00D3F20B,
842F72DD06405FDF00CC271B,
- 9342E3EA0646C8FF00004B05,
931D722B065FC40800C966E1,
51F6A3D70663BF04004D2919,
51F6A3DF0663C2EC004D2919,
BC06F24F06D18A7E004A6FA3,
93ABCE5F06E1A42E0085925B,
93B641F306E28C5C0055F610,
- BEF3442606F1123C000A65D3,
BE8560520701F91100239769,
5150C2A60702629800AF642C,
+ 93ABE06E070285F600BD91F9,
+ 93ABE070070285F600BD91F9,
+ 93ABE072070285F600BD91F9,
+ 93ABE074070285F600BD91F9,
);
isa = PBXSourcesBuildPhase;
runOnlyForDeploymentPostprocessing = 0;
settings = {
};
};
- 9342E3E80646C8FF00004B05 = {
- fileEncoding = 4;
- isa = PBXFileReference;
- lastKnownFileType = sourcecode.cpp.cpp;
- path = khtml_text_operations.cpp;
- refType = 4;
- sourceTree = "<group>";
- };
- 9342E3E90646C8FF00004B05 = {
- fileEncoding = 4;
- isa = PBXFileReference;
- lastKnownFileType = sourcecode.c.h;
- path = khtml_text_operations.h;
- refType = 4;
- sourceTree = "<group>";
- };
- 9342E3EA0646C8FF00004B05 = {
- fileRef = 9342E3E80646C8FF00004B05;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 9342E3EB0646C8FF00004B05 = {
- fileRef = 9342E3E90646C8FF00004B05;
- isa = PBXBuildFile;
- settings = {
- };
- };
9348900506C00363007E7ACE = {
fileEncoding = 30;
isa = PBXFileReference;
settings = {
};
};
+ 93ABE066070285F600BD91F9 = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.cpp.cpp;
+ name = selection.cpp;
+ path = editing/selection.cpp;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 93ABE067070285F600BD91F9 = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = selection.h;
+ path = editing/selection.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 93ABE068070285F600BD91F9 = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.cpp.cpp;
+ name = visible_position.cpp;
+ path = editing/visible_position.cpp;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 93ABE069070285F600BD91F9 = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = visible_position.h;
+ path = editing/visible_position.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 93ABE06A070285F600BD91F9 = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.cpp.cpp;
+ name = visible_text.cpp;
+ path = editing/visible_text.cpp;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 93ABE06B070285F600BD91F9 = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = visible_text.h;
+ path = editing/visible_text.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 93ABE06C070285F600BD91F9 = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.cpp.cpp;
+ name = visible_units.cpp;
+ path = editing/visible_units.cpp;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 93ABE06D070285F600BD91F9 = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = visible_units.h;
+ path = editing/visible_units.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 93ABE06E070285F600BD91F9 = {
+ fileRef = 93ABE066070285F600BD91F9;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 93ABE06F070285F600BD91F9 = {
+ fileRef = 93ABE067070285F600BD91F9;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 93ABE070070285F600BD91F9 = {
+ fileRef = 93ABE068070285F600BD91F9;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 93ABE071070285F600BD91F9 = {
+ fileRef = 93ABE069070285F600BD91F9;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 93ABE072070285F600BD91F9 = {
+ fileRef = 93ABE06A070285F600BD91F9;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 93ABE073070285F600BD91F9 = {
+ fileRef = 93ABE06B070285F600BD91F9;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 93ABE074070285F600BD91F9 = {
+ fileRef = 93ABE06C070285F600BD91F9;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 93ABE075070285F600BD91F9 = {
+ fileRef = 93ABE06D070285F600BD91F9;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
93B641F106E28C5C0055F610 = {
fileEncoding = 30;
isa = PBXFileReference;
settings = {
};
};
- BE8BD9080635CC2F00D3F20B = {
- fileEncoding = 30;
- isa = PBXFileReference;
- lastKnownFileType = sourcecode.cpp.cpp;
- path = dom_selection.cpp;
- refType = 4;
- sourceTree = "<group>";
- };
- BE8BD9090635CC2F00D3F20B = {
- fileEncoding = 30;
- isa = PBXFileReference;
- lastKnownFileType = sourcecode.c.h;
- path = dom_selection.h;
- refType = 4;
- sourceTree = "<group>";
- };
- BE8BD90A0635CC2F00D3F20B = {
- fileRef = BE8BD9080635CC2F00D3F20B;
- isa = PBXBuildFile;
- settings = {
- };
- };
- BE8BD90B0635CC2F00D3F20B = {
- fileRef = BE8BD9090635CC2F00D3F20B;
- isa = PBXBuildFile;
- settings = {
- };
- };
BE9185DD05EE59B80081354D = {
fileEncoding = 30;
isa = PBXFileReference;
BE9185DF05EE59B80081354D,
BE02D4E6066F908A0076809F,
BE02D4E7066F908A0076809F,
+ 93ABE067070285F600BD91F9,
+ 93ABE066070285F600BD91F9,
+ 93ABE069070285F600BD91F9,
+ 93ABE068070285F600BD91F9,
+ 93ABE06B070285F600BD91F9,
+ 93ABE06A070285F600BD91F9,
+ 93ABE06D070285F600BD91F9,
+ 93ABE06C070285F600BD91F9,
);
isa = PBXGroup;
name = editing;
refType = 4;
sourceTree = "<group>";
};
- BEF3442406F1123C000A65D3 = {
- fileEncoding = 30;
- isa = PBXFileReference;
- lastKnownFileType = sourcecode.cpp.cpp;
- path = dom_caretposition.cpp;
- refType = 4;
- sourceTree = "<group>";
- };
- BEF3442506F1123C000A65D3 = {
- fileEncoding = 30;
- isa = PBXFileReference;
- lastKnownFileType = sourcecode.c.h;
- path = dom_caretposition.h;
- refType = 4;
- sourceTree = "<group>";
- };
- BEF3442606F1123C000A65D3 = {
- fileRef = BEF3442406F1123C000A65D3;
- isa = PBXBuildFile;
- settings = {
- };
- };
- BEF3442706F1123C000A65D3 = {
- fileRef = BEF3442506F1123C000A65D3;
- isa = PBXBuildFile;
- settings = {
- };
- };
BEF7EEA005FF8F0D009717EE = {
fileEncoding = 30;
isa = PBXFileReference;
F523D28102DE43D7018635CA,
F523D28202DE43D7018635CA,
F523D28302DE43D7018635CA,
- 9342E3E80646C8FF00004B05,
- 9342E3E90646C8FF00004B05,
F523D28402DE43D7018635CA,
F523D28502DE43D7018635CA,
F523D28602DE43D7018635CA,
BC3B364505C9D5E200E42902,
BC3B364605C9D5E200E42902,
BC3B364705C9D5E200E42902,
- BEF3442406F1123C000A65D3,
- BEF3442506F1123C000A65D3,
F523D2F402DE4476018635CA,
F523D2F502DE4476018635CA,
F523D2F702DE4476018635CA,
BE91FC8C06133666005E3790,
BE02F482066E1C550013A9F6,
BE02F483066E1C550013A9F6,
- BE8BD9080635CC2F00D3F20B,
- BE8BD9090635CC2F00D3F20B,
F523D2FB02DE4476018635CA,
F523D2FC02DE4476018635CA,
F523D2FD02DE4476018635CA,
#include "xml/dom2_eventsimpl.h"
#include "xml/dom_docimpl.h"
#include "xml/dom_position.h"
-#include "xml/dom_selection.h"
#include "html/html_documentimpl.h"
using DOM::DocumentImpl;
#include <kdebug.h>
#include <kio/job.h>
#include <qobject.h>
+#include <qregexp.h>
#ifdef APPLE_CHANGES
#include "KWQLoader.h"
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "dom_selection.h"
-
-#include "dom_caretposition.h"
-#include "dom_docimpl.h"
-#include "dom_elementimpl.h"
-#include "dom_node.h"
-#include "dom_nodeimpl.h"
-#include "dom_positioniterator.h"
-#include "dom_string.h"
-#include "dom_textimpl.h"
-#include "dom2_rangeimpl.h"
-#include "htmltags.h"
+#include "selection.h"
+
+#include <qevent.h>
+#include <qpainter.h>
+#include <qrect.h>
+
+#include "dom/dom_node.h"
+#include "dom/dom_string.h"
#include "khtml_part.h"
#include "khtmlview.h"
-#include "qevent.h"
-#include "qpainter.h"
-#include "qrect.h"
-#include "render_object.h"
-#include "render_style.h"
-#include "render_text.h"
+#include "misc/htmltags.h"
+#include "rendering/render_object.h"
+#include "rendering/render_style.h"
+#include "rendering/render_text.h"
+#include "visible_position.h"
+#include "visible_units.h"
+#include "xml/dom_docimpl.h"
+#include "xml/dom_elementimpl.h"
+#include "xml/dom_nodeimpl.h"
+#include "xml/dom_positioniterator.h"
+#include "xml/dom_textimpl.h"
+#include "xml/dom2_rangeimpl.h"
#if APPLE_CHANGES
#include "KWQAssertions.h"
caret = pos - (textLength - show.length());
}
- show = show.replace("\n", " ");
- show = show.replace("\r", " ");
+ show.replace('\n', ' ');
+ show.replace('\r', ' ');
fprintf(stderr, "==> #text : \"%s\" at offset %d\n", show.latin1(), pos);
fprintf(stderr, " ");
for (int i = 0; i < caret; i++)
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __dom_selection_h__
-#define __dom_selection_h__
+#ifndef KHTML_EDITING_SELECTION_H
+#define KHTML_EDITING_SELECTION_H
#include <qrect.h>
-#include "dom_caretposition.h"
+#include "xml/dom_position.h"
class KHTMLPart;
class QPainter;
namespace DOM {
-class NodeImpl;
-class Position;
-class Range;
+class CaretPosition;
class Selection
{
} // namespace DOM
-#endif // __dom_selection_h__
+#endif // KHTML_EDITING_SELECTION_H
#include "xml/dom_docimpl.h"
#include "xml/dom_nodeimpl.h"
#include "xml/dom_position.h"
-#include "xml/dom_selection.h"
#include "xml/dom_textimpl.h"
#if APPLE_CHANGES
#ifndef __htmlediting_h__
#define __htmlediting_h__
-#include "dom_position.h"
-#include "dom_selection.h"
-#include "dom_string.h"
-#include "shared.h"
#include "xml/dom_nodeimpl.h"
namespace DOM {
- class CSSStyleDeclarationImpl;
class DocumentFragmentImpl;
- class DocumentImpl;
- class DOMString;
- class ElementImpl;
- class NodeImpl;
- class Position;
class Selection;
class TextImpl;
-};
+}
namespace khtml {
#include "htmlediting_impl.h"
+#include <qptrlist.h>
+
+#include "visible_position.h"
+#include "visible_units.h"
+
#include "cssproperties.h"
#include "css/css_computedstyle.h"
#include "css/css_valueimpl.h"
#include "htmltags.h"
#include "khtml_part.h"
#include "khtmlview.h"
-#include "qptrlist.h"
#include "rendering/render_object.h"
#include "rendering/render_style.h"
#include "rendering/render_text.h"
-#include "xml/dom_caretposition.h"
#include "xml/dom_docimpl.h"
#include "xml/dom_elementimpl.h"
#include "xml/dom_positioniterator.h"
#include "xml/dom_nodeimpl.h"
#include "xml/dom_position.h"
-#include "xml/dom_selection.h"
#include "xml/dom_stringimpl.h"
#include "xml/dom_textimpl.h"
#include "xml/dom2_rangeimpl.h"
#include "htmlediting.h"
-#include "dom_position.h"
-#include "dom_selection.h"
-#include "dom_string.h"
-#include "dom2_range.h"
-#include "qvaluelist.h"
-#include "shared.h"
+#include <qvaluelist.h>
+#include "selection.h"
namespace DOM {
- class AtomicString;
class CSSProperty;
- class CSSStyleDeclarationImpl;
- class DocumentImpl;
- class DOMString;
- class ElementImpl;
class HTMLElementImpl;
- class NodeImpl;
- class NodeListImpl;
- class Position;
- class Range;
- class Selection;
- class TextImpl;
- class TreeWalkerImpl;
-};
+}
namespace khtml {
#include "jsediting.h"
-#include "cssproperties.h"
-#include "dom_selection.h"
+#include <qstring.h>
+
#include "htmlediting.h"
+
#include "khtml_part.h"
+#include "css/cssproperties.h"
+
+#if APPLE_CHANGES
#include "KWQKHTMLPart.h"
-#include "qstring.h"
+#endif
using khtml::TypingCommand;
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "dom_selection.h"
-
-#include "dom_caretposition.h"
-#include "dom_docimpl.h"
-#include "dom_elementimpl.h"
-#include "dom_node.h"
-#include "dom_nodeimpl.h"
-#include "dom_positioniterator.h"
-#include "dom_string.h"
-#include "dom_textimpl.h"
-#include "dom2_rangeimpl.h"
-#include "htmltags.h"
+#include "selection.h"
+
+#include <qevent.h>
+#include <qpainter.h>
+#include <qrect.h>
+
+#include "dom/dom_node.h"
+#include "dom/dom_string.h"
#include "khtml_part.h"
#include "khtmlview.h"
-#include "qevent.h"
-#include "qpainter.h"
-#include "qrect.h"
-#include "render_object.h"
-#include "render_style.h"
-#include "render_text.h"
+#include "misc/htmltags.h"
+#include "rendering/render_object.h"
+#include "rendering/render_style.h"
+#include "rendering/render_text.h"
+#include "visible_position.h"
+#include "visible_units.h"
+#include "xml/dom_docimpl.h"
+#include "xml/dom_elementimpl.h"
+#include "xml/dom_nodeimpl.h"
+#include "xml/dom_positioniterator.h"
+#include "xml/dom_textimpl.h"
+#include "xml/dom2_rangeimpl.h"
#if APPLE_CHANGES
#include "KWQAssertions.h"
caret = pos - (textLength - show.length());
}
- show = show.replace("\n", " ");
- show = show.replace("\r", " ");
+ show.replace('\n', ' ');
+ show.replace('\r', ' ');
fprintf(stderr, "==> #text : \"%s\" at offset %d\n", show.latin1(), pos);
fprintf(stderr, " ");
for (int i = 0; i < caret; i++)
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __dom_selection_h__
-#define __dom_selection_h__
+#ifndef KHTML_EDITING_SELECTION_H
+#define KHTML_EDITING_SELECTION_H
#include <qrect.h>
-#include "dom_caretposition.h"
+#include "xml/dom_position.h"
class KHTMLPart;
class QPainter;
namespace DOM {
-class NodeImpl;
-class Position;
-class Range;
+class CaretPosition;
class Selection
{
} // namespace DOM
-#endif // __dom_selection_h__
+#endif // KHTML_EDITING_SELECTION_H
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "dom_caretposition.h"
+#include "visible_position.h"
-#include "dom2_rangeimpl.h"
-#include "dom_elementimpl.h"
-#include "dom_nodeimpl.h"
-#include "dom_string.h"
-#include "htmltags.h"
-#include "khtml_text_operations.h"
-#include "render_object.h"
-#include "render_text.h"
+#include "misc/htmltags.h"
+#include "rendering/render_text.h"
+#include "xml/dom2_rangeimpl.h"
#if APPLE_CHANGES
#include "KWQAssertions.h"
#define LOG(channel, formatAndArgs...) ((void)0)
#endif
-using khtml::CharacterIterator;
-using khtml::findWordBoundary;
using khtml::InlineTextBox;
-using khtml::nextWordFromIndex;
-using khtml::PRE;
using khtml::RenderObject;
-using khtml::RenderStyle;
using khtml::RenderText;
-using khtml::SimplifiedBackwardsTextIterator;
-using khtml::TextIterator;
using khtml::VISIBLE;
namespace DOM {
return code == 0;
}
-static CaretPosition previousWordBoundary(const CaretPosition &c, unsigned (*searchFunction)(const QChar *, unsigned))
-{
- Position pos = c.deepEquivalent();
- NodeImpl *n = pos.node();
- if (!n)
- return CaretPosition();
- DocumentImpl *d = n->getDocument();
- if (!d)
- return CaretPosition();
- NodeImpl *de = d->documentElement();
- if (!de)
- return CaretPosition();
-
- Range searchRange(d);
- searchRange.setStartBefore(de);
- Position end(pos.equivalentRangeCompliantPosition());
- searchRange.setEnd(end.node(), end.offset());
- SimplifiedBackwardsTextIterator it(searchRange);
- QString string;
- unsigned next = 0;
- while (!it.atEnd() && it.length() > 0) {
- // Keep asking the iterator for chunks until the nextWordFromIndex() function
- // returns a non-zero value.
- string.prepend(it.characters(), it.length());
- next = searchFunction(string.unicode(), string.length());
- if (next != 0)
- break;
- it.advance();
- }
-
- if (it.atEnd() && next == 0) {
- Range range(it.range());
- pos = Position(range.startContainer().handle(), range.startOffset());
- }
- else if (!it.atEnd() && it.length() == 0) {
- // Got a zero-length chunk.
- // This means we have hit a replaced element.
- // Make a check to see if the position should be before or after the replaced element
- // by performing an additional check with a modified string which uses an "X"
- // character to stand in for the replaced element.
- QChar chars[2];
- chars[0] = 'X';
- chars[1] = ' ';
- string.prepend(chars, 2);
- unsigned pastImage = searchFunction(string.unicode(), string.length());
- Range range(it.range());
- if (pastImage == 0)
- pos = Position(range.startContainer().handle(), range.startOffset());
- else
- pos = Position(range.endContainer().handle(), range.endOffset());
- }
- else if (next != 0) {
- // The simpler iterator used in this function, as compared to the one used in
- // nextWordPosition(), gives us results we can use directly without having to
- // iterate again to translate the next value into a DOM position.
- NodeImpl *node = it.range().startContainer().handle();
- if (node->isTextNode()) {
- // The next variable contains a usable index into a text node
- pos = Position(node, next);
- }
- else {
- // If we are not in a text node, we ended on a node boundary, so the
- // range start offset should be used.
- pos = Position(node, it.range().startOffset());
- }
- }
- // Use DOWNSTREAM here so that we don't jump past words at the start of lines.
- // <rdar://problem/3765519> REGRESSION (Mail): word movement goes too far upstream at start of line
- return pos.equivalentDeepPosition().closestRenderedPosition(DOWNSTREAM);
-}
-
-static CaretPosition nextWordBoundary(const CaretPosition &c, unsigned (*searchFunction)(const QChar *, unsigned))
-{
- Position pos = c.deepEquivalent();
- NodeImpl *n = pos.node();
- if (!n)
- return CaretPosition();
- DocumentImpl *d = n->getDocument();
- if (!d)
- return CaretPosition();
- NodeImpl *de = d->documentElement();
- if (!de)
- return CaretPosition();
-
- Range searchRange(d);
- Position start(pos.equivalentRangeCompliantPosition());
- searchRange.setStart(start.node(), start.offset());
- searchRange.setEndAfter(de);
- TextIterator it(searchRange);
- QString string;
- unsigned next = 0;
- while (!it.atEnd() && it.length() > 0) {
- // Keep asking the iterator for chunks until the findWordBoundary() function
- // returns an end value not equal to the length of the string passed to it.
- string.append(it.characters(), it.length());
- next = searchFunction(string.unicode(), string.length());
- if (next != string.length())
- break;
- it.advance();
- }
-
- if (it.atEnd() && next == string.length()) {
- Range range(it.range());
- pos = Position(range.startContainer().handle(), range.startOffset());
- }
- else if (!it.atEnd() && it.length() == 0) {
- // Got a zero-length chunk.
- // This means we have hit a replaced element.
- // Make a check to see if the position should be before or after the replaced element
- // by performing an additional check with a modified string which uses an "X"
- // character to stand in for the replaced element.
- QChar chars[2];
- chars[0] = ' ';
- chars[1] = 'X';
- string.append(chars, 2);
- unsigned pastImage = searchFunction(string.unicode(), string.length());
- Range range(it.range());
- if (next != pastImage)
- pos = Position(range.endContainer().handle(), range.endOffset());
- else
- pos = Position(range.startContainer().handle(), range.startOffset());
- }
- else if (next != 0) {
- // Use the character iterator to translate the next value into a DOM position.
- CharacterIterator charIt(searchRange);
- charIt.advance(next - 1);
- pos = Position(charIt.range().endContainer().handle(), charIt.range().endOffset());
- }
- return pos.equivalentDeepPosition().closestRenderedPosition(UPSTREAM);
-}
-
-static unsigned startWordBoundary(const QChar *characters, unsigned length)
-{
- int start, end;
- findWordBoundary(characters, length, length, &start, &end);
- return start;
-}
-
-CaretPosition startOfWord(const CaretPosition &c, EWordSide side)
-{
- CaretPosition p = c;
- if (side == RightWordIfOnBoundary) {
- p = c.next();
- if (p.isNull())
- return c;
- }
- return previousWordBoundary(p, startWordBoundary);
-}
-
-static unsigned endWordBoundary(const QChar *characters, unsigned length)
-{
- int start, end;
- findWordBoundary(characters, length, 0, &start, &end);
- return end;
-}
-
-CaretPosition endOfWord(const CaretPosition &c, EWordSide side)
-{
- CaretPosition p = c;
- if (side == LeftWordIfOnBoundary) {
- p = c.previous();
- if (p.isNull())
- return c;
- }
- return nextWordBoundary(p, endWordBoundary);
-}
-
-static unsigned previousWordPositionBoundary(const QChar *characters, unsigned length)
-{
- return nextWordFromIndex(characters, length, length, false);
-}
-
-CaretPosition previousWordPosition(const CaretPosition &c)
-{
- return previousWordBoundary(c, previousWordPositionBoundary);
-}
-
-static unsigned nextWordPositionBoundary(const QChar *characters, unsigned length)
-{
- return nextWordFromIndex(characters, length, 0, true);
-}
-
-CaretPosition nextWordPosition(const CaretPosition &c)
-{
- return nextWordBoundary(c, nextWordPositionBoundary);
-}
-
-CaretPosition previousLinePosition(const CaretPosition &c, int x)
-{
- return c.deepEquivalent().previousLinePosition(x);
-}
-
-CaretPosition nextLinePosition(const CaretPosition &c, int x)
-{
- return c.deepEquivalent().nextLinePosition(x);
-}
-
-CaretPosition startOfParagraph(const CaretPosition &c)
-{
- Position p = c.deepEquivalent();
- NodeImpl *startNode = p.node();
- if (!startNode)
- return CaretPosition();
-
- NodeImpl *startBlock = startNode->enclosingBlockFlowElement();
-
- NodeImpl *node = startNode;
- long offset = p.offset();
-
- for (NodeImpl *n = startNode; n; n = n->traversePreviousNodePostOrder(startBlock)) {
- RenderObject *r = n->renderer();
- if (!r)
- continue;
- RenderStyle *style = r->style();
- if (style->visibility() != VISIBLE)
- continue;
- if (r->isBR() || r->isBlockFlow())
- break;
- if (r->isText()) {
- if (style->whiteSpace() == PRE) {
- QChar *text = static_cast<RenderText *>(r)->text();
- long i = static_cast<RenderText *>(r)->length();
- long o = offset;
- if (n == startNode && o < i)
- i = kMax(0L, o);
- while (--i >= 0)
- if (text[i] == '\n')
- return CaretPosition(n, i + 1);
- }
- node = n;
- offset = 0;
- } else if (r->isReplaced()) {
- node = n;
- offset = 0;
- }
- }
-
- return CaretPosition(node, offset);
-}
-
-CaretPosition endOfParagraph(const CaretPosition &c, EIncludeLineBreak includeLineBreak)
-{
- Position p = c.deepEquivalent();
-
- NodeImpl *startNode = p.node();
- if (!startNode)
- return CaretPosition();
-
- NodeImpl *startBlock = startNode->enclosingBlockFlowElement();
-
- NodeImpl *node = startNode;
- long offset = p.offset();
-
- for (NodeImpl *n = startNode; n; n = n->traverseNextNode(startBlock)) {
- RenderObject *r = n->renderer();
- if (!r)
- continue;
- RenderStyle *style = r->style();
- if (style->visibility() != VISIBLE)
- continue;
- if (r->isBR()) {
- if (includeLineBreak)
- return CaretPosition(n, 1);
- break;
- }
- if (r->isBlockFlow()) {
- if (includeLineBreak)
- return CaretPosition(n, 0);
- break;
- }
- if (r->isText()) {
- long length = static_cast<RenderText *>(r)->length();
- if (style->whiteSpace() == PRE) {
- QChar *text = static_cast<RenderText *>(r)->text();
- long o = 0;
- if (n == startNode && offset < length)
- o = offset;
- for (long i = o; i < length; ++i)
- if (text[i] == '\n')
- return CaretPosition(n, i + includeLineBreak);
- }
- node = n;
- offset = length;
- } else if (r->isReplaced()) {
- node = n;
- offset = 1;
- }
- }
-
- return CaretPosition(node, offset);
-}
-
-bool inSameParagraph(const CaretPosition &a, const CaretPosition &b)
-{
- return a == b || startOfParagraph(a) == startOfParagraph(b);
-}
-
-CaretPosition previousParagraphPosition(const CaretPosition &p, int x)
-{
- CaretPosition pos = p;
- do {
- CaretPosition n = previousLinePosition(pos, x);
- if (n.isNull() || n == pos)
- return p;
- pos = n;
- } while (inSameParagraph(p, pos));
- return pos;
-}
-
-CaretPosition nextParagraphPosition(const CaretPosition &p, int x)
-{
- CaretPosition pos = p;
- do {
- CaretPosition n = nextLinePosition(pos, x);
- if (n.isNull() || n == pos)
- return p;
- pos = n;
- } while (inSameParagraph(p, pos));
- return pos;
-}
-
} // namespace DOM
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __dom_caretposition_h__
-#define __dom_caretposition_h__
+#ifndef KHTML_EDITING_VISIBLE_POSITION_H
+#define KHTML_EDITING_VISIBLE_POSITION_H
-#include "dom_position.h"
-#include "dom/dom2_range.h"
+#include "xml/dom_position.h"
namespace DOM {
-class NodeImpl;
+class Range;
+class RangeImpl;
class CaretPosition
{
return !(a == b);
}
-// --- DOM range and caret position interoperability; to be moved to a separate header ---
-
Range makeRange(const CaretPosition &start, const CaretPosition &end);
bool setStart(Range &, const CaretPosition &start);
bool setStart(RangeImpl *, const CaretPosition &start);
CaretPosition end(const Range &);
CaretPosition end(const RangeImpl *);
-// --- word, line, and paragraph operations; to be moved to a separate header ---
-
-enum EWordSide { RightWordIfOnBoundary = false, LeftWordIfOnBoundary = true };
-enum EIncludeLineBreak { DoNotIncludeLineBreak = false, IncludeLineBreak = true };
-
-// words
-CaretPosition startOfWord(const CaretPosition &, EWordSide = RightWordIfOnBoundary);
-CaretPosition endOfWord(const CaretPosition &, EWordSide = RightWordIfOnBoundary);
-CaretPosition previousWordPosition(const CaretPosition &);
-CaretPosition nextWordPosition(const CaretPosition &);
-
-// lines
-CaretPosition startOfLine(const CaretPosition &);
-CaretPosition endOfLine(const CaretPosition &, EIncludeLineBreak = DoNotIncludeLineBreak);
-CaretPosition previousLinePosition(const CaretPosition &, int x);
-CaretPosition nextLinePosition(const CaretPosition &, int x);
-
-// paragraphs
-CaretPosition startOfParagraph(const CaretPosition &);
-CaretPosition endOfParagraph(const CaretPosition &, EIncludeLineBreak = DoNotIncludeLineBreak);
-CaretPosition previousParagraphPosition(const CaretPosition &, int x);
-CaretPosition nextParagraphPosition(const CaretPosition &, int x);
-bool inSameParagraph(const CaretPosition &, const CaretPosition &);
-
} // namespace DOM
-#endif // __dom_caretposition_h__
+#endif // KHTML_EDITING_VISIBLE_POSITION_H
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "khtml_text_operations.h"
+#include "visible_text.h"
-#include <dom/dom2_range.h>
-#include <misc/htmltags.h>
-#include <rendering/render_text.h>
-#include <xml/dom_nodeimpl.h>
-#include <xml/dom_position.h>
-#include <xml/dom2_rangeimpl.h>
+#include "misc/htmltags.h"
+#include "rendering/render_text.h"
+#include "xml/dom_nodeimpl.h"
+#include "xml/dom_position.h"
+#include "xml/dom2_rangeimpl.h"
using DOM::DOMString;
using DOM::Node;
using DOM::Range;
using DOM::RangeImpl;
+// FIXME: These classes should probably use the render tree and not the DOM tree, since elements could
+// be hidden using CSS, or additional generated content could be added. For now, we just make sure
+// text objects walk their renderers' InlineTextBox objects, so that we at least get the whitespace
+// stripped out properly and obey CSS visibility for text runs.
+
namespace khtml {
const unsigned short nonBreakingSpace = 0xA0;
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __khtml_text_operations_h__
-#define __khtml_text_operations_h__
+#ifndef KHTML_EDITING_VISIBLE_TEXT_H
+#define KHTML_EDITING_VISIBLE_TEXT_H
-#include <qstring.h>
#include "dom/dom2_range.h"
-namespace DOM {
-class NodeImpl;
-}
-
-// FIXME: This class should probably use the render tree and not the DOM tree, since elements could
-// be hidden using CSS, or additional generated content could be added. For now, we just make sure
-// text objects walk their renderers' InlineTextBox objects, so that we at least get the whitespace
-// stripped out properly and obey CSS visibility for text runs.
-
namespace khtml {
class InlineTextBox;
-// General utillity functions
+// General utility functions
QString plainText(const DOM::Range &);
DOM::Range findPlainText(const DOM::Range &, const QString &, bool forward, bool caseSensitive);
-
// Iterates through the DOM range, returning all the text, and 0-length boundaries
// at points where replaced elements break up the text flow. The text comes back in
// chunks so as to optimize for performance of the iteration.
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "dom_caretposition.h"
-
-#include "dom2_rangeimpl.h"
-#include "dom_elementimpl.h"
-#include "dom_nodeimpl.h"
-#include "dom_string.h"
-#include "htmltags.h"
-#include "khtml_text_operations.h"
-#include "render_object.h"
-#include "render_text.h"
-
-#if APPLE_CHANGES
-#include "KWQAssertions.h"
-#include "KWQLogging.h"
-#else
-#define ASSERT(assertion) assert(assertion)
-#define LOG(channel, formatAndArgs...) ((void)0)
-#endif
+#include "visible_units.h"
+
+#include <qstring.h>
+
+#include "misc/helper.h"
+#include "rendering/render_text.h"
+#include "visible_position.h"
+#include "visible_text.h"
+#include "xml/dom_docimpl.h"
using khtml::CharacterIterator;
using khtml::findWordBoundary;
-using khtml::InlineTextBox;
using khtml::nextWordFromIndex;
using khtml::PRE;
using khtml::RenderObject;
namespace DOM {
-CaretPosition::CaretPosition(NodeImpl *node, long offset)
-{
- init(Position(node, offset));
-}
-
-CaretPosition::CaretPosition(const Position &pos)
-{
- init(pos);
-}
-
-void CaretPosition::init(const Position &pos)
-{
- Position deepPos = deepEquivalent(pos);
-
- if (isCandidate(deepPos)) {
- m_deepPosition = deepPos;
- Position previous = previousCaretPosition(deepPos);
- if (previous.isNotNull()) {
- Position next = nextCaretPosition(previous);
- if (next.isNotNull())
- m_deepPosition = next;
- }
- }
- else {
- Position next = nextCaretPosition(deepPos);
- if (next.isNotNull()) {
- m_deepPosition = next;
- }
- else {
- Position previous = previousCaretPosition(deepPos);
- if (previous.isNotNull())
- m_deepPosition = previous;
- }
- }
-}
-
-bool CaretPosition::isLastInBlock() const
-{
- if (isNull())
- return false;
-
- CaretPosition n = next();
- return n.isNull() || (n.deepEquivalent().node()->enclosingBlockFlowElement() != m_deepPosition.node()->enclosingBlockFlowElement());
-}
-
-CaretPosition CaretPosition::next() const
-{
- CaretPosition result;
- result.m_deepPosition = nextCaretPosition(m_deepPosition);
- return result;
-}
-
-CaretPosition CaretPosition::previous() const
-{
- CaretPosition result;
- result.m_deepPosition = previousCaretPosition(m_deepPosition);
- return result;
-}
-
-Position CaretPosition::previousCaretPosition(const Position &pos)
-{
- if (pos.isNull() || atStart(pos))
- return Position();
-
- Position test = deepEquivalent(pos);
- bool acceptAnyCaretPosition = !isCandidate(test) || pos.isFirstRenderedPositionOnLine();
-
- Position current = test;
- while (!atStart(current)) {
- current = previousPosition(current);
- if (isCandidate(current) && (acceptAnyCaretPosition || current.rendersInDifferentPosition(test))) {
- return current;
- }
- }
-
- return Position();
-}
-
-Position CaretPosition::nextCaretPosition(const Position &pos)
-{
- if (pos.isNull() || atEnd(pos))
- return Position();
-
- Position test = deepEquivalent(pos);
- bool acceptAnyCaretPosition = !isCandidate(test) || pos.isLastRenderedPositionOnLine();
-
- Position current = test;
- while (!atEnd(current)) {
- current = nextPosition(current);
- if (isCandidate(current) && (acceptAnyCaretPosition || current.rendersInDifferentPosition(test))) {
- return current;
- }
- }
-
- return Position();
-}
-
-Position CaretPosition::previousPosition(const Position &pos)
-{
- if (pos.isNull())
- return pos;
-
- Position result;
-
- if (pos.offset() <= 0) {
- NodeImpl *prevNode = pos.node()->previousLeafNode();
- if (prevNode)
- result = Position(prevNode, prevNode->maxOffset());
- }
- else {
- result = Position(pos.node(), pos.offset() - 1);
- }
-
- return result;
-}
-
-Position CaretPosition::nextPosition(const Position &pos)
-{
- if (pos.isNull())
- return pos;
-
- Position result;
-
- if (pos.offset() >= pos.node()->maxOffset()) {
- NodeImpl *nextNode = pos.node()->nextLeafNode();
- if (nextNode)
- result = Position(nextNode, 0);
- }
- else {
- result = Position(pos.node(), pos.offset() + 1);
- }
-
- return result;
-}
-
-bool CaretPosition::atStart(const Position &pos)
-{
- if (pos.isNull())
- return true;
-
- return pos.offset() <= 0 && pos.node()->previousLeafNode() == 0;
-}
-
-bool CaretPosition::atEnd(const Position &pos)
-{
- if (pos.isNull())
- return true;
-
- return pos.offset() >= pos.node()->maxOffset() && pos.node()->nextLeafNode() == 0;
-}
-
-bool CaretPosition::isCandidate(const Position &pos)
-{
- if (pos.isNull())
- return false;
-
- RenderObject *renderer = pos.node()->renderer();
- if (!renderer)
- return false;
-
- if (renderer->style()->visibility() != VISIBLE)
- return false;
-
- if (renderer->isReplaced())
- // return true for replaced elements
- return pos.offset() == 0 || pos.offset() == 1;
-
- if (renderer->isBR() && static_cast<RenderText *>(renderer)->firstTextBox())
- // return true for offset 0 into BR element on a line by itself
- return pos.offset() == 0;
-
- if (renderer->isText()) {
- RenderText *textRenderer = static_cast<RenderText *>(renderer);
- for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
- if (pos.offset() >= box->m_start && pos.offset() <= box->m_start + box->m_len) {
- // return true if in a text node
- return true;
- }
- else if (pos.offset() < box->m_start) {
- // The offset we're looking for is before this node
- // this means the offset must be in content that is
- // not rendered. Return false.
- return false;
- }
- }
- }
-
- if (renderer->isBlockFlow() && !renderer->firstChild() && renderer->height())
- // return true for offset 0 into rendered blocks that are empty of rendered kids, but have a height
- return pos.offset() == 0;
-
- return false;
-}
-
-Position CaretPosition::deepEquivalent(const Position &pos)
-{
- NodeImpl *node = pos.node();
- long offset = pos.offset();
-
- if (!node)
- return Position();
-
- if (isAtomicNode(node)) {
- // This is part of the strategy to wean the code off Positions with BRs and replaced elements
- // as the nodes and offsets > 0.
- if (offset > 0 && (node->id() == ID_BR || node->renderer() && node->renderer()->isReplaced())) {
- NodeImpl *next = node->traverseNextNode();
- if (next && node->enclosingBlockFlowElement() == next->enclosingBlockFlowElement())
- return deepEquivalent(Position(next, 0));
- }
- return pos;
- }
-
- if (offset >= (long)node->childNodeCount()) {
- do {
- NodeImpl *child = node->lastChild();
- if (!child)
- break;
- node = child;
- } while (!isAtomicNode(node));
- return Position(node, node->caretMaxOffset());
- }
-
- node = node->childNode(offset);
- ASSERT(node);
- while (!isAtomicNode(node)) {
- NodeImpl *child = node->firstChild();
- if (!child)
- break;
- node = child;
- }
- return Position(node, 0);
-}
-
-Position CaretPosition::rangeCompliantEquivalent(const Position &pos)
-{
- NodeImpl *node = pos.node();
- if (!node)
- return Position();
-
- // FIXME: This clamps out-of-range values.
- // Instead we should probably assert, and not use such values.
-
- long offset = pos.offset();
- if (!offsetInCharacters(node->nodeType()) && isAtomicNode(node) && offset > 0)
- return Position(node->parentNode(), node->nodeIndex() + 1);
-
- return Position(node, kMax(0L, kMin(offset, maxOffset(node))));
-}
-
-long CaretPosition::maxOffset(const NodeImpl *node)
-{
- return offsetInCharacters(node->nodeType()) ? (long)static_cast<const CharacterDataImpl *>(node)->length() : (long)node->childNodeCount();
-}
-
-bool CaretPosition::isAtomicNode(const NodeImpl *node)
-{
- return node && (!node->hasChildNodes() || (node->id() == ID_OBJECT && node->renderer() && node->renderer()->isReplaced()));
-}
-
-void CaretPosition::debugPosition(const char *msg) const
-{
- if (isNull())
- fprintf(stderr, "Position [%s]: null\n", msg);
- else
- fprintf(stderr, "Position [%s]: %s [%p] at %d\n", msg, getTagName(m_deepPosition.node()->id()).string().latin1(), m_deepPosition.node(), m_deepPosition.offset());
-}
-
-#ifndef NDEBUG
-void CaretPosition::formatForDebugger(char *buffer, unsigned length) const
-{
- m_deepPosition.formatForDebugger(buffer, length);
-}
-#endif
-
-Range makeRange(const CaretPosition &start, const CaretPosition &end)
-{
- Position s = start.position();
- Position e = end.position();
- return Range(s.node(), s.offset(), e.node(), e.offset());
-}
-
-CaretPosition start(const Range &r)
-{
- return CaretPosition(r.startContainer().handle(), r.startOffset());
-}
-
-CaretPosition end(const Range &r)
-{
- return CaretPosition(r.endContainer().handle(), r.endOffset());
-}
-
-bool setStart(Range &r, const CaretPosition &c)
-{
- RangeImpl *ri = r.handle();
- if (!ri)
- return false;
- Position p = c.position();
- int code = 0;
- ri->setStart(p.node(), p.offset(), code);
- return code == 0;
-}
-
-bool setEnd(Range &r, const CaretPosition &c)
-{
- RangeImpl *ri = r.handle();
- if (!ri)
- return false;
- Position p = c.position();
- int code = 0;
- ri->setEnd(p.node(), p.offset(), code);
- return code == 0;
-}
-
static CaretPosition previousWordBoundary(const CaretPosition &c, unsigned (*searchFunction)(const QChar *, unsigned))
{
Position pos = c.deepEquivalent();
return pos;
}
-} // namespace DOM
+} // namespace DOM
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __dom_caretposition_h__
-#define __dom_caretposition_h__
-
-#include "dom_position.h"
-#include "dom/dom2_range.h"
+#ifndef KHTML_EDITING_VISIBLE_UNITS_H
+#define KHTML_EDITING_VISIBLE_UNITS_H
namespace DOM {
-class NodeImpl;
-
-class CaretPosition
-{
-public:
- CaretPosition() { }
- CaretPosition(NodeImpl *, long offset);
- CaretPosition(const Position &);
-
- void clear() { m_deepPosition.clear(); }
-
- bool isNull() const { return m_deepPosition.isNull(); }
- bool isNotNull() const { return m_deepPosition.isNotNull(); }
-
- Position position() const { return rangeCompliantEquivalent(m_deepPosition); }
- Position deepEquivalent() const { return m_deepPosition; }
-
- friend inline bool operator==(const CaretPosition &a, const CaretPosition &b);
-
- CaretPosition next() const;
- CaretPosition previous() const;
-
- bool isLastInBlock() const;
-
- void debugPosition(const char *msg = "") const;
-
-#ifndef NDEBUG
- void formatForDebugger(char *buffer, unsigned length) const;
-#endif
-
-private:
- void init(const Position &);
-
- static Position deepEquivalent(const Position &);
- static Position rangeCompliantEquivalent(const Position &);
-
- static long maxOffset(const NodeImpl *);
- static bool isAtomicNode(const NodeImpl *);
-
- static Position previousCaretPosition(const Position &);
- static Position nextCaretPosition(const Position &);
-
- static Position previousPosition(const Position &);
- static Position nextPosition(const Position &);
-
- static bool atStart(const Position &);
- static bool atEnd(const Position &);
-
- static bool isCandidate(const Position &);
-
- Position m_deepPosition;
-};
-
-inline bool operator==(const CaretPosition &a, const CaretPosition &b)
-{
- return a.m_deepPosition == b.m_deepPosition;
-}
-
-inline bool operator!=(const CaretPosition &a, const CaretPosition &b)
-{
- return !(a == b);
-}
-
-// --- DOM range and caret position interoperability; to be moved to a separate header ---
-
-Range makeRange(const CaretPosition &start, const CaretPosition &end);
-bool setStart(Range &, const CaretPosition &start);
-bool setStart(RangeImpl *, const CaretPosition &start);
-bool setEnd(Range &, const CaretPosition &start);
-bool setEnd(RangeImpl *, const CaretPosition &start);
-CaretPosition start(const Range &);
-CaretPosition start(const RangeImpl *);
-CaretPosition end(const Range &);
-CaretPosition end(const RangeImpl *);
-
-// --- word, line, and paragraph operations; to be moved to a separate header ---
+class CaretPosition;
enum EWordSide { RightWordIfOnBoundary = false, LeftWordIfOnBoundary = true };
enum EIncludeLineBreak { DoNotIncludeLineBreak = false, IncludeLineBreak = true };
} // namespace DOM
-#endif // __dom_caretposition_h__
+#endif // KHTML_EDITING_VISIBLE_POSITION_H
#include "html/htmltokenizer.h"
#include "misc/htmlhashes.h"
-#include "misc/khtml_text_operations.h"
+#include "editing/visible_text.h"
#include "khtmlview.h"
#include "khtml_part.h"
#include "css/cssproperties.h"
#include "css/cssvalues.h"
#include "css/css_ruleimpl.h"
-#include "xml/dom_selection.h"
#include "xml/dom_textimpl.h"
#include "xml/dom2_eventsimpl.h"
#include "dom/dom_string.h"
#include "dom/dom_element.h"
+#include "dom/html_document.h"
#include "editing/htmlediting.h"
#include "html/html_documentimpl.h"
#include "html/html_baseimpl.h"
#include "rendering/render_frames.h"
#include "misc/htmlhashes.h"
#include "misc/loader.h"
-#include "xml/dom_caretposition.h"
-#include "xml/dom_selection.h"
+#include "editing/visible_position.h"
#include "xml/dom2_eventsimpl.h"
#include "xml/xml_tokenizer.h"
#include "css/css_computedstyle.h"
#include "css/cssstyleselector.h"
#include "css/csshelper.h"
-#include "misc/khtml_text_operations.h"
+#include "editing/visible_text.h"
#include "css/css_computedstyle.h"
using namespace DOM;
#ifndef __khtml_part_h__
#define __khtml_part_h__
-#include "dom/html_document.h"
-#include "dom/dom2_range.h"
-#include "dom/dom_misc.h"
-#include "editing/htmlediting.h"
+#include "editing/selection.h" // only for text granularity -- should fix this to reduce dependencies
#include <kparts/part.h>
#include <kparts/browserextension.h>
-#include <qregexp.h>
-
class KHTMLPartPrivate;
class KHTMLPartBrowserExtension;
class KJSProxy;
{
class CSSComputedStyleDeclarationImpl;
class CSSStyleDeclarationImpl;
+ class DOMString;
+ class Document;
class DocumentImpl;
class EventListener;
class HTMLAnchorElementImpl;
class RenderPartObject;
class RenderWidget;
class XMLTokenizer;
-};
+}
namespace KJS {
+ class DOMDocument;
+ class JSEventListener;
class Selection;
class SelectionFunc;
class Window;
class WindowFunc;
- class JSEventListener;
- class DOMDocument;
-};
+}
namespace KParts
{
-#ifndef khtmlpart_p_h
-#define khtmlpart_p_h
-
/* This file is part of the KDE project
*
* Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+
+#ifndef khtmlpart_p_h
+#define khtmlpart_p_h
+
#include <kcursor.h>
#include <klibloader.h>
#include <kxmlguifactory.h>
#include "ecma/kjs_proxy.h"
#include "css/css_valueimpl.h"
#include "dom/dom_misc.h"
-#include "xml/dom_selection.h"
+#include "editing/htmlediting.h"
+#include "editing/selection.h"
namespace KIO
{
QStringList m_paramValues;
bool m_bNotify;
};
-
- class EditCommand;
-};
+}
class FrameList : public QValueList<khtml::ChildFrame>
{
#include "rendering/render_line.h"
#include "rendering/render_text.h"
#include "xml/dom_nodeimpl.h"
-#include "xml/dom_selection.h"
#include "xml/dom2_eventsimpl.h"
#include "css/cssstyleselector.h"
#include "misc/htmlhashes.h"
+++ /dev/null
-/*
- * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "khtml_text_operations.h"
-
-#include <dom/dom2_range.h>
-#include <misc/htmltags.h>
-#include <rendering/render_text.h>
-#include <xml/dom_nodeimpl.h>
-#include <xml/dom_position.h>
-#include <xml/dom2_rangeimpl.h>
-
-using DOM::DOMString;
-using DOM::Node;
-using DOM::NodeImpl;
-using DOM::offsetInCharacters;
-using DOM::Range;
-using DOM::RangeImpl;
-
-namespace khtml {
-
-const unsigned short nonBreakingSpace = 0xA0;
-
-// Buffer that knows how to compare with a search target.
-// Keeps enough of the previous text to be able to search in the future,
-// but no more.
-class CircularSearchBuffer {
-public:
- CircularSearchBuffer(const QString &target, bool isCaseSensitive);
- ~CircularSearchBuffer() { free(m_buffer); }
-
- void clear() { m_cursor = m_buffer; m_bufferFull = false; }
- void append(long length, const QChar *characters);
- void append(const QChar &);
-
- long neededCharacters() const;
- bool isMatch() const;
- long length() const { return m_target.length(); }
-
-private:
- QString m_target;
- bool m_isCaseSensitive;
-
- QChar *m_buffer;
- QChar *m_cursor;
- bool m_bufferFull;
-
- CircularSearchBuffer(const CircularSearchBuffer&);
- CircularSearchBuffer &operator=(const CircularSearchBuffer&);
-};
-
-TextIterator::TextIterator() : m_endContainer(0), m_endOffset(0), m_positionNode(0)
-{
-}
-
-TextIterator::TextIterator(const Range &r) : m_endContainer(0), m_endOffset(0), m_positionNode(0)
-{
- const RangeImpl *ri = r.handle();
- if (!ri)
- return;
-
- int exceptionCode = 0;
-
- NodeImpl *startContainer = ri->startContainer(exceptionCode);
- long startOffset = ri->startOffset(exceptionCode);
- NodeImpl *endContainer = ri->endContainer(exceptionCode);
- long endOffset = ri->endOffset(exceptionCode);
-
- if (exceptionCode != 0)
- return;
-
- m_endContainer = endContainer;
- m_endOffset = endOffset;
-
- m_node = ri->startNode();
- if (m_node == 0)
- return;
-
- m_offset = m_node == startContainer ? startOffset : 0;
- m_handledNode = false;
- m_handledChildren = false;
-
- m_pastEndNode = ri->pastEndNode();
-
- m_needAnotherNewline = false;
- m_textBox = 0;
-
- m_lastTextNode = 0;
- m_lastTextNodeEndedWithCollapsedSpace = false;
- m_lastCharacter = '\n';
-
-#ifndef NDEBUG
- // Need this just because of the assert.
- m_positionNode = m_node;
-#endif
-
- advance();
-}
-
-void TextIterator::advance()
-{
- assert(m_positionNode);
-
- m_positionNode = 0;
- m_textLength = 0;
-
- if (m_needAnotherNewline) {
- // Emit the newline, with position a collapsed range at the end of current node.
- long offset = m_node->nodeIndex();
- emitCharacter('\n', m_node->parentNode(), offset + 1, offset + 1);
- m_needAnotherNewline = false;
- return;
- }
-
- if (m_textBox) {
- handleTextBox();
- if (m_positionNode) {
- return;
- }
- }
-
- while (m_node && m_node != m_pastEndNode) {
- if (!m_handledNode) {
- RenderObject *renderer = m_node->renderer();
- if (renderer && renderer->isText() && m_node->nodeType() == Node::TEXT_NODE) {
- // FIXME: What about CDATA_SECTION_NODE?
- if (renderer->style()->visibility() == VISIBLE) {
- m_handledNode = handleTextNode();
- }
- } else if (renderer && (renderer->isImage() || renderer->isWidget())) {
- if (renderer->style()->visibility() == VISIBLE) {
- m_handledNode = handleReplacedElement();
- }
- } else {
- m_handledNode = handleNonTextNode();
- }
- if (m_positionNode) {
- return;
- }
- }
-
- NodeImpl *next = m_handledChildren ? 0 : m_node->firstChild();
- m_offset = 0;
- if (!next) {
- next = m_node->nextSibling();
- while (!next && m_node->parentNode()) {
- m_node = m_node->parentNode();
- exitNode();
- if (m_positionNode) {
- m_handledNode = true;
- m_handledChildren = true;
- return;
- }
- next = m_node->nextSibling();
- }
- }
-
- m_node = next;
- m_handledNode = false;
- m_handledChildren = false;
-
- if (m_positionNode) {
- return;
- }
- }
-}
-
-bool TextIterator::handleTextNode()
-{
- m_lastTextNode = m_node;
-
- RenderText *renderer = static_cast<RenderText *>(m_node->renderer());
- DOMString str = m_node->nodeValue();
-
- if (renderer->style()->whiteSpace() == khtml::PRE) {
- long runStart = m_offset;
- if (m_lastTextNodeEndedWithCollapsedSpace) {
- emitCharacter(' ', m_node, runStart, runStart);
- return false;
- }
- long strLength = str.length();
- long end = (m_node == m_endContainer) ? m_endOffset : LONG_MAX;
- long runEnd = kMin(strLength, end);
-
- m_positionNode = m_node;
- m_positionStartOffset = runStart;
- m_positionEndOffset = runEnd;
- m_textCharacters = str.unicode() + runStart;
- m_textLength = runEnd - runStart;
-
- m_lastCharacter = str[runEnd - 1];
-
- return true;
- }
-
- if (!renderer->firstTextBox() && str.length() > 0) {
- m_lastTextNodeEndedWithCollapsedSpace = true; // entire block is collapsed space
- return true;
- }
-
- m_textBox = renderer->firstTextBox();
- handleTextBox();
- return true;
-}
-
-void TextIterator::handleTextBox()
-{
- RenderText *renderer = static_cast<RenderText *>(m_node->renderer());
- DOMString str = m_node->nodeValue();
- long start = m_offset;
- long end = (m_node == m_endContainer) ? m_endOffset : LONG_MAX;
- for (; m_textBox; m_textBox = m_textBox->nextTextBox()) {
- long textBoxStart = m_textBox->m_start;
- long runStart = kMax(textBoxStart, start);
-
- // Check for collapsed space at the start of this run.
- bool needSpace = m_lastTextNodeEndedWithCollapsedSpace
- || (m_textBox == renderer->firstTextBox() && textBoxStart == runStart && runStart > 0);
- if (needSpace && !m_lastCharacter.isSpace()) {
- emitCharacter(' ', m_node, runStart, runStart);
- return;
- }
-
- long textBoxEnd = textBoxStart + m_textBox->m_len;
- long runEnd = kMin(textBoxEnd, end);
-
- if (runStart < runEnd) {
- // Handle either a single newline character (which becomes a space),
- // or a run of characters that does not include a newline.
- // This effectively translates newlines to spaces without copying the text.
- if (str[runStart] == '\n') {
- emitCharacter(' ', m_node, runStart, runStart + 1);
- m_offset = runStart + 1;
- } else {
- long subrunEnd = str.find('\n', runStart);
- if (subrunEnd == -1 || subrunEnd > runEnd) {
- subrunEnd = runEnd;
- }
-
- m_offset = subrunEnd;
-
- m_positionNode = m_node;
- m_positionStartOffset = runStart;
- m_positionEndOffset = subrunEnd;
- m_textCharacters = str.unicode() + runStart;
- m_textLength = subrunEnd - runStart;
-
- m_lastTextNodeEndedWithCollapsedSpace = false;
- m_lastCharacter = str[subrunEnd - 1];
- }
-
- // If we are doing a subrun that doesn't go to the end of the text box,
- // come back again to finish handling this text box; don't advance to the next one.
- if (m_positionEndOffset < textBoxEnd) {
- return;
- }
-
- // Advance to the next text box.
- InlineTextBox *nextTextBox = m_textBox->nextTextBox();
- long nextRunStart = nextTextBox ? nextTextBox->m_start : str.length();
- if (nextRunStart > runEnd) {
- m_lastTextNodeEndedWithCollapsedSpace = true; // collapsed space between runs or at the end
- }
- m_textBox = nextTextBox;
- return;
- }
- }
-}
-
-bool TextIterator::handleReplacedElement()
-{
- if (m_lastTextNodeEndedWithCollapsedSpace) {
- long offset = m_lastTextNode->nodeIndex();
- emitCharacter(' ', m_lastTextNode->parentNode(), offset + 1, offset + 1);
- return false;
- }
-
- long offset = m_node->nodeIndex();
-
- m_positionNode = m_node->parentNode();
- m_positionStartOffset = offset;
- m_positionEndOffset = offset + 1;
-
- m_textCharacters = 0;
- m_textLength = 0;
-
- m_lastCharacter = 0;
-
- return true;
-}
-
-bool TextIterator::handleNonTextNode()
-{
- switch (m_node->id()) {
- case ID_BR: {
- long offset = m_node->nodeIndex();
- emitCharacter('\n', m_node->parentNode(), offset, offset + 1);
- break;
- }
-
- case ID_TD:
- case ID_TH:
- if (m_lastCharacter != '\n' && m_lastTextNode) {
- long offset = m_lastTextNode->nodeIndex();
- emitCharacter('\t', m_lastTextNode->parentNode(), offset, offset + 1);
- }
- break;
-
- case ID_BLOCKQUOTE:
- case ID_DD:
- case ID_DIV:
- case ID_DL:
- case ID_DT:
- case ID_H1:
- case ID_H2:
- case ID_H3:
- case ID_H4:
- case ID_H5:
- case ID_H6:
- case ID_HR:
- case ID_LI:
- case ID_OL:
- case ID_P:
- case ID_PRE:
- case ID_TR:
- case ID_UL:
- if (m_lastCharacter != '\n' && m_lastTextNode) {
- long offset = m_lastTextNode->nodeIndex();
- emitCharacter('\n', m_lastTextNode->parentNode(), offset, offset + 1);
- }
- break;
- }
-
- return true;
-}
-
-void TextIterator::exitNode()
-{
- bool endLine = false;
- bool addNewline = false;
-
- switch (m_node->id()) {
- case ID_BLOCKQUOTE:
- case ID_DD:
- case ID_DIV:
- case ID_DL:
- case ID_DT:
- case ID_HR:
- case ID_LI:
- case ID_OL:
- case ID_PRE:
- case ID_TR:
- case ID_UL:
- endLine = true;
- break;
-
- case ID_H1:
- case ID_H2:
- case ID_H3:
- case ID_H4:
- case ID_H5:
- case ID_H6:
- case ID_P:
- endLine = true;
- addNewline = true;
- break;
- }
-
- if (endLine && m_lastCharacter != '\n' && m_lastTextNode) {
- long offset = m_lastTextNode->nodeIndex();
- emitCharacter('\n', m_lastTextNode->parentNode(), offset, offset + 1);
- m_needAnotherNewline = addNewline;
- } else if (addNewline && m_lastTextNode) {
- long offset = m_node->childNodeCount();
- emitCharacter('\n', m_node, offset, offset);
- }
-}
-
-void TextIterator::emitCharacter(QChar c, NodeImpl *textNode, long textStartOffset, long textEndOffset)
-{
- m_singleCharacterBuffer = c;
- m_positionNode = textNode;
- m_positionStartOffset = textStartOffset;
- m_positionEndOffset = textEndOffset;
- m_textCharacters = &m_singleCharacterBuffer;
- m_textLength = 1;
-
- m_lastTextNodeEndedWithCollapsedSpace = false;
- m_lastCharacter = c;
-}
-
-Range TextIterator::range() const
-{
- if (m_positionNode)
- return Range(m_positionNode, m_positionStartOffset, m_positionNode, m_positionEndOffset);
- if (m_endContainer)
- return Range(m_endContainer, m_endOffset, m_endContainer, m_endOffset);
- return Range();
-}
-
-SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator() : m_positionNode(0)
-{
-}
-
-SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range &r)
-{
- if (r.isNull()) {
- m_positionNode = 0;
- return;
- }
-
- NodeImpl *startNode = r.startContainer().handle();
- NodeImpl *endNode = r.endContainer().handle();
- long startOffset = r.startOffset();
- long endOffset = r.endOffset();
-
- if (!offsetInCharacters(startNode->nodeType())) {
- if (startOffset >= 0 && startOffset < static_cast<long>(startNode->childNodeCount())) {
- startNode = startNode->childNode(startOffset);
- startOffset = 0;
- }
- }
- if (!offsetInCharacters(endNode->nodeType())) {
- if (endOffset > 0 && endOffset <= static_cast<long>(endNode->childNodeCount())) {
- endNode = endNode->childNode(endOffset - 1);
- endOffset = endNode->hasChildNodes() ? endNode->childNodeCount() : endNode->maxOffset();
- }
- }
-
- m_node = endNode;
- m_offset = endOffset;
- m_handledNode = false;
- m_handledChildren = endOffset == 0;
-
- m_startNode = startNode;
- m_startOffset = startOffset;
-
-#ifndef NDEBUG
- // Need this just because of the assert.
- m_positionNode = endNode;
-#endif
-
- advance();
-}
-
-void SimplifiedBackwardsTextIterator::advance()
-{
- assert(m_positionNode);
-
- m_positionNode = 0;
- m_textLength = 0;
-
- while (m_node) {
- if (!m_handledNode) {
- RenderObject *renderer = m_node->renderer();
- if (renderer && renderer->isText() && m_node->nodeType() == Node::TEXT_NODE) {
- // FIXME: What about CDATA_SECTION_NODE?
- if (renderer->style()->visibility() == VISIBLE && m_offset > 0) {
- m_handledNode = handleTextNode();
- }
- } else if (renderer && (renderer->isImage() || renderer->isWidget())) {
- if (renderer->style()->visibility() == VISIBLE && m_offset > 0) {
- m_handledNode = handleReplacedElement();
- }
- } else {
- m_handledNode = handleNonTextNode();
- }
- if (m_positionNode) {
- return;
- }
- }
-
- if (m_node == m_startNode)
- return;
-
- NodeImpl *next = 0;
- if (!m_handledChildren) {
- next = m_node->lastChild();
- while (next && next->lastChild())
- next = next->lastChild();
- m_handledChildren = true;
- }
- if (!next && m_node != m_startNode) {
- next = m_node->previousSibling();
- if (next) {
- exitNode();
- while (next->lastChild())
- next = next->lastChild();
- }
- else if (m_node->parentNode()) {
- next = m_node->parentNode();
- exitNode();
- }
- }
-
- m_node = next;
- if (m_node)
- m_offset = m_node->caretMaxOffset();
- else
- m_offset = 0;
- m_handledNode = false;
-
- if (m_positionNode) {
- return;
- }
- }
-}
-
-bool SimplifiedBackwardsTextIterator::handleTextNode()
-{
- RenderText *renderer = static_cast<RenderText *>(m_node->renderer());
- DOMString str = m_node->nodeValue();
-
- if (!renderer->firstTextBox() && str.length() > 0) {
- return true;
- }
-
- m_positionEndOffset = m_offset;
-
- m_offset = (m_node == m_startNode) ? m_startOffset : 0;
- m_positionNode = m_node;
- m_positionStartOffset = m_offset;
- m_textLength = m_positionEndOffset - m_positionStartOffset;
- m_textCharacters = str.unicode() + m_positionStartOffset;
-
- return true;
-}
-
-bool SimplifiedBackwardsTextIterator::handleReplacedElement()
-{
- long offset = m_node->nodeIndex();
-
- m_positionNode = m_node->parentNode();
- m_positionStartOffset = offset;
- m_positionEndOffset = offset + 1;
-
- m_textCharacters = 0;
- m_textLength = 0;
-
- return true;
-}
-
-bool SimplifiedBackwardsTextIterator::handleNonTextNode()
-{
- switch (m_node->id()) {
- case ID_BR:
- case ID_TD:
- case ID_TH:
- case ID_BLOCKQUOTE:
- case ID_DD:
- case ID_DIV:
- case ID_DL:
- case ID_DT:
- case ID_H1:
- case ID_H2:
- case ID_H3:
- case ID_H4:
- case ID_H5:
- case ID_H6:
- case ID_HR:
- case ID_LI:
- case ID_OL:
- case ID_P:
- case ID_PRE:
- case ID_TR:
- case ID_UL:
- // Emit a space to "break up" content. Any word break
- // character will do.
- emitCharacter(' ', m_node, 0, 0);
- break;
- }
-
- return true;
-}
-
-void SimplifiedBackwardsTextIterator::exitNode()
-{
- // Left this function in so that the name and usage patters remain similar to
- // TextIterator. However, the needs of this iterator are much simpler, and
- // the handleNonTextNode() function does just what we want (i.e. insert a
- // space for certain node types to "break up" text so that it does not seem
- // like content is next to other text when it really isn't).
- handleNonTextNode();
-}
-
-void SimplifiedBackwardsTextIterator::emitCharacter(QChar c, NodeImpl *node, long startOffset, long endOffset)
-{
- m_singleCharacterBuffer = c;
- m_positionNode = node;
- m_positionStartOffset = startOffset;
- m_positionEndOffset = endOffset;
- m_textCharacters = &m_singleCharacterBuffer;
- m_textLength = 1;
-}
-
-Range SimplifiedBackwardsTextIterator::range() const
-{
- if (m_positionNode) {
- return Range(m_positionNode, m_positionStartOffset, m_positionNode, m_positionEndOffset);
- } else {
- return Range(m_startNode, m_startOffset, m_startNode, m_startOffset);
- }
-}
-
-CharacterIterator::CharacterIterator()
- : m_offset(0), m_runOffset(0), m_atBreak(true)
-{
-}
-
-CharacterIterator::CharacterIterator(const Range &r)
- : m_offset(0), m_runOffset(0), m_atBreak(true), m_textIterator(r)
-{
- while (!atEnd() && m_textIterator.length() == 0) {
- m_textIterator.advance();
- }
-}
-
-Range CharacterIterator::range() const
-{
- Range r = m_textIterator.range();
- if (!m_textIterator.atEnd()) {
- if (m_textIterator.length() <= 1) {
- assert(m_runOffset == 0);
- } else {
- Node n = r.startContainer();
- assert(n == r.endContainer());
- long offset = r.startOffset() + m_runOffset;
- r.setStart(n, offset);
- r.setEnd(n, offset + 1);
- }
- }
- return r;
-}
-
-void CharacterIterator::advance(long count)
-{
- assert(!atEnd());
-
- m_atBreak = false;
-
- long remaining = m_textIterator.length() - m_runOffset;
- if (count < remaining) {
- m_runOffset += count;
- m_offset += count;
- return;
- }
-
- count -= remaining;
- m_offset += remaining;
- for (m_textIterator.advance(); !atEnd(); m_textIterator.advance()) {
- long runLength = m_textIterator.length();
- if (runLength == 0) {
- m_atBreak = true;
- } else {
- if (count < runLength) {
- m_runOffset = count;
- m_offset += count;
- return;
- }
- count -= runLength;
- m_offset += runLength;
- }
- }
-
- m_atBreak = true;
- m_runOffset = 0;
-}
-
-QString CharacterIterator::string(long numChars)
-{
- QString result;
- result.reserve(numChars);
- while (numChars > 0 && !atEnd()) {
- long runSize = kMin(numChars, length());
- result.append(characters(), runSize);
- numChars -= runSize;
- advance(runSize);
- }
- return result;
-}
-
-WordAwareIterator::WordAwareIterator()
-: m_previousText(0), m_didLookAhead(false)
-{
-}
-
-WordAwareIterator::WordAwareIterator(const Range &r)
-: m_previousText(0), m_didLookAhead(false), m_textIterator(r)
-{
- m_didLookAhead = true; // so we consider the first chunk from the text iterator
- advance(); // get in position over the first chunk of text
-}
-
-// We're always in one of these modes:
-// - The current chunk in the text iterator is our current chunk
-// (typically its a piece of whitespace, or text that ended with whitespace)
-// - The previous chunk in the text iterator is our current chunk
-// (we looked ahead to the next chunk and found a word boundary)
-// - We built up our own chunk of text from many chunks from the text iterator
-
-//FIXME: Perf could be bad for huge spans next to each other that don't fall on word boundaries
-
-void WordAwareIterator::advance()
-{
- m_previousText = 0;
- m_buffer = ""; // toss any old buffer we built up
-
- // If last time we did a look-ahead, start with that looked-ahead chunk now
- if (!m_didLookAhead) {
- assert(!m_textIterator.atEnd());
- m_textIterator.advance();
- }
- m_didLookAhead = false;
-
- // Go to next non-empty chunk
- while (!m_textIterator.atEnd() && m_textIterator.length() == 0) {
- m_textIterator.advance();
- }
- m_range = m_textIterator.range();
-
- if (m_textIterator.atEnd()) {
- return;
- }
-
- while (1) {
- // If this chunk ends in whitespace we can just use it as our chunk.
- if (m_textIterator.characters()[m_textIterator.length()-1].isSpace()) {
- return;
- }
-
- // If this is the first chunk that failed, save it in previousText before look ahead
- if (m_buffer.isEmpty()) {
- m_previousText = m_textIterator.characters();
- m_previousLength = m_textIterator.length();
- }
-
- // Look ahead to next chunk. If it is whitespace or a break, we can use the previous stuff
- m_textIterator.advance();
- if (m_textIterator.atEnd() || m_textIterator.length() == 0 || m_textIterator.characters()[0].isSpace()) {
- m_didLookAhead = true;
- return;
- }
-
- if (m_buffer.isEmpty()) {
- // Start gobbling chunks until we get to a suitable stopping point
- m_buffer.append(m_previousText, m_previousLength);
- m_previousText = 0;
- }
- m_buffer.append(m_textIterator.characters(), m_textIterator.length());
- m_range.setEnd(m_textIterator.range().endContainer(), m_textIterator.range().endOffset());
- }
-}
-
-long WordAwareIterator::length() const
-{
- if (!m_buffer.isEmpty()) {
- return m_buffer.length();
- } else if (m_previousText) {
- return m_previousLength;
- } else {
- return m_textIterator.length();
- }
-}
-
-const QChar *WordAwareIterator::characters() const
-{
- if (!m_buffer.isEmpty()) {
- return m_buffer.unicode();
- } else if (m_previousText) {
- return m_previousText;
- } else {
- return m_textIterator.characters();
- }
-}
-
-CircularSearchBuffer::CircularSearchBuffer(const QString &s, bool isCaseSensitive)
- : m_target(s)
-{
- assert(!s.isEmpty());
-
- if (!isCaseSensitive) {
- m_target = s.lower();
- }
- m_target.replace(nonBreakingSpace, ' ');
- m_isCaseSensitive = isCaseSensitive;
-
- m_buffer = static_cast<QChar *>(malloc(s.length() * sizeof(QChar)));
- m_cursor = m_buffer;
- m_bufferFull = false;
-}
-
-void CircularSearchBuffer::append(const QChar &c)
-{
- if (m_isCaseSensitive) {
- *m_cursor++ = c.unicode() == nonBreakingSpace ? ' ' : c.unicode();
- } else {
- *m_cursor++ = c.unicode() == nonBreakingSpace ? ' ' : c.lower().unicode();
- }
- if (m_cursor == m_buffer + length()) {
- m_cursor = m_buffer;
- m_bufferFull = true;
- }
-}
-
-// This function can only be used when the buffer is not yet full,
-// and when then count is small enough to fit in the buffer.
-// No need for a more general version for the search algorithm.
-void CircularSearchBuffer::append(long count, const QChar *characters)
-{
- long tailSpace = m_buffer + length() - m_cursor;
-
- assert(!m_bufferFull);
- assert(count <= tailSpace);
-
- if (m_isCaseSensitive) {
- for (long i = 0; i != count; ++i) {
- QChar c = characters[i];
- m_cursor[i] = c.unicode() == nonBreakingSpace ? ' ' : c.unicode();
- }
- } else {
- for (long i = 0; i != count; ++i) {
- QChar c = characters[i];
- m_cursor[i] = c.unicode() == nonBreakingSpace ? ' ' : c.lower().unicode();
- }
- }
- if (count < tailSpace) {
- m_cursor += count;
- } else {
- m_bufferFull = true;
- m_cursor = m_buffer;
- }
-}
-
-long CircularSearchBuffer::neededCharacters() const
-{
- return m_bufferFull ? 0 : m_buffer + length() - m_cursor;
-}
-
-bool CircularSearchBuffer::isMatch() const
-{
- assert(m_bufferFull);
-
- long headSpace = m_cursor - m_buffer;
- long tailSpace = length() - headSpace;
- return memcmp(m_cursor, m_target.unicode(), tailSpace * sizeof(QChar)) == 0
- && memcmp(m_buffer, m_target.unicode() + tailSpace, headSpace * sizeof(QChar)) == 0;
-}
-
-QString plainText(const Range &r)
-{
- // Allocate string at the right size, rather than building it up by successive append calls.
- long length = 0;
- for (TextIterator it(r); !it.atEnd(); it.advance()) {
- length += it.length();
- }
- QString result("");
- result.reserve(length);
- for (TextIterator it(r); !it.atEnd(); it.advance()) {
- result.append(it.characters(), it.length());
- }
- return result;
-}
-
-Range findPlainText(const Range &r, const QString &s, bool forward, bool caseSensitive)
-{
- // FIXME: Can we do Boyer-Moore or equivalent instead for speed?
-
- // FIXME: This code does not allow \n at the moment because of issues with <br>.
- // Once we fix those, we can remove this check.
- if (s.isEmpty() || s.find('\n') != -1) {
- Range result = r;
- result.collapse(forward);
- return result;
- }
-
- CircularSearchBuffer buffer(s, caseSensitive);
-
- bool found = false;
- CharacterIterator rangeEnd;
-
- {
- CharacterIterator it(r);
- while (1) {
- // Fill the buffer.
- while (long needed = buffer.neededCharacters()) {
- if (it.atBreak()) {
- if (it.atEnd()) {
- goto done;
- }
- buffer.clear();
- }
- long available = it.length();
- long runLength = kMin(needed, available);
- buffer.append(runLength, it.characters());
- it.advance(runLength);
- }
-
- // Do the search.
- do {
- if (buffer.isMatch()) {
- // Compute the range for the result.
- found = true;
- rangeEnd = it;
- // If searching forward, stop on the first match.
- // If searching backward, don't stop, so we end up with the last match.
- if (forward) {
- goto done;
- }
- }
- buffer.append(it.characters()[0]);
- it.advance(1);
- } while (!it.atBreak());
- buffer.clear();
- }
- }
-
-done:
- Range result = r;
- if (!found) {
- result.collapse(!forward);
- } else {
- CharacterIterator it(r);
- it.advance(rangeEnd.characterOffset() - buffer.length());
- result.setStart(it.range().startContainer(), it.range().startOffset());
- it.advance(buffer.length() - 1);
- result.setEnd(it.range().endContainer(), it.range().endOffset());
- }
- return result;
-}
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __khtml_text_operations_h__
-#define __khtml_text_operations_h__
-
-#include <qstring.h>
-#include "dom/dom2_range.h"
-
-namespace DOM {
-class NodeImpl;
-}
-
-// FIXME: This class should probably use the render tree and not the DOM tree, since elements could
-// be hidden using CSS, or additional generated content could be added. For now, we just make sure
-// text objects walk their renderers' InlineTextBox objects, so that we at least get the whitespace
-// stripped out properly and obey CSS visibility for text runs.
-
-namespace khtml {
-
-class InlineTextBox;
-
-// General utillity functions
-
-QString plainText(const DOM::Range &);
-DOM::Range findPlainText(const DOM::Range &, const QString &, bool forward, bool caseSensitive);
-
-
-// Iterates through the DOM range, returning all the text, and 0-length boundaries
-// at points where replaced elements break up the text flow. The text comes back in
-// chunks so as to optimize for performance of the iteration.
-class TextIterator
-{
-public:
- TextIterator();
- explicit TextIterator(const DOM::Range &);
-
- bool atEnd() const { return !m_positionNode; }
- void advance();
-
- long length() const { return m_textLength; }
- const QChar *characters() const { return m_textCharacters; }
-
- DOM::Range range() const;
-
-private:
- void exitNode();
- bool handleTextNode();
- bool handleReplacedElement();
- bool handleNonTextNode();
- void handleTextBox();
- void emitCharacter(QChar, DOM::NodeImpl *textNode, long textStartOffset, long textEndOffset);
-
- // Current position, not necessarily of the text being returned, but position
- // as we walk through the DOM tree.
- DOM::NodeImpl *m_node;
- long m_offset;
- bool m_handledNode;
- bool m_handledChildren;
-
- // End of the range.
- DOM::NodeImpl *m_endContainer;
- long m_endOffset;
- DOM::NodeImpl *m_pastEndNode;
-
- // The current text and its position, in the form to be returned from the iterator.
- DOM::NodeImpl *m_positionNode;
- long m_positionStartOffset;
- long m_positionEndOffset;
- const QChar *m_textCharacters;
- long m_textLength;
-
- // Used when there is still some pending text from the current node; when these
- // are false and 0, we go back to normal iterating.
- bool m_needAnotherNewline;
- InlineTextBox *m_textBox;
-
- // Used to do the whitespace collapsing logic.
- DOM::NodeImpl *m_lastTextNode;
- bool m_lastTextNodeEndedWithCollapsedSpace;
- QChar m_lastCharacter;
-
- // Used for whitespace characters that aren't in the DOM, so we can point at them.
- QChar m_singleCharacterBuffer;
-};
-
-// Iterates through the DOM range, returning all the text, and 0-length boundaries
-// at points where replaced elements break up the text flow. The text comes back in
-// chunks so as to optimize for performance of the iteration.
-class SimplifiedBackwardsTextIterator
-{
-public:
- SimplifiedBackwardsTextIterator();
- explicit SimplifiedBackwardsTextIterator(const DOM::Range &);
-
- bool atEnd() const { return !m_positionNode; }
- void advance();
-
- long length() const { return m_textLength; }
- const QChar *characters() const { return m_textCharacters; }
-
- DOM::Range range() const;
-
-private:
- void exitNode();
- bool handleTextNode();
- bool handleReplacedElement();
- bool handleNonTextNode();
- void emitCharacter(QChar, DOM::NodeImpl *Node, long startOffset, long endOffset);
-
- // Current position, not necessarily of the text being returned, but position
- // as we walk through the DOM tree.
- DOM::NodeImpl *m_node;
- long m_offset;
- bool m_handledNode;
- bool m_handledChildren;
-
- // End of the range.
- DOM::NodeImpl *m_startNode;
- long m_startOffset;
-
- // The current text and its position, in the form to be returned from the iterator.
- DOM::NodeImpl *m_positionNode;
- long m_positionStartOffset;
- long m_positionEndOffset;
- const QChar *m_textCharacters;
- long m_textLength;
-
- // Used for whitespace characters that aren't in the DOM, so we can point at them.
- QChar m_singleCharacterBuffer;
-};
-
-// Builds on the text iterator, adding a character position so we can walk one
-// character at a time, or faster, as needed. Useful for searching.
-class CharacterIterator {
-public:
- CharacterIterator();
- explicit CharacterIterator(const DOM::Range &r);
-
- void advance(long numCharacters);
-
- bool atBreak() const { return m_atBreak; }
- bool atEnd() const { return m_textIterator.atEnd(); }
-
- long length() const { return m_textIterator.length() - m_runOffset; }
- const QChar *characters() const { return m_textIterator.characters() + m_runOffset; }
- QString string(long numChars);
-
- long characterOffset() const { return m_offset; }
- DOM::Range range() const;
-
-private:
- long m_offset;
- long m_runOffset;
- bool m_atBreak;
-
- TextIterator m_textIterator;
-};
-
-
-// Very similar to the TextIterator, except that the chunks of text returned are "well behaved",
-// meaning they never end split up a word. This is useful for spellcheck or (perhaps one day) searching.
-class WordAwareIterator {
-public:
- WordAwareIterator();
- explicit WordAwareIterator(const DOM::Range &r);
-
- bool atEnd() const { return !m_didLookAhead && m_textIterator.atEnd(); }
- void advance();
-
- long length() const;
- const QChar *characters() const;
-
- // Range of the text we're currently returning
- DOM::Range range() const { return m_range; }
-
-private:
- // text from the previous chunk from the textIterator
- const QChar *m_previousText;
- long m_previousLength;
-
- // many chunks from textIterator concatenated
- QString m_buffer;
-
- // Did we have to look ahead in the textIterator to confirm the current chunk?
- bool m_didLookAhead;
-
- DOM::Range m_range;
-
- TextIterator m_textIterator;
-};
-
-}
-
-#endif
#include "xml/dom_nodeimpl.h"
#include "xml/dom_docimpl.h"
#include "xml/dom_position.h"
-#include "xml/dom_selection.h"
#include "html/html_formimpl.h"
#include "render_block.h"
#include "dom_xmlimpl.h"
#include "html/html_elementimpl.h"
#include "misc/htmltags.h"
-#include "misc/khtml_text_operations.h"
+#include "editing/visible_text.h"
#include "render_block.h"
// FIXME: As with innerText, we'd like this to work even if there are no render objects.
m_startContainer->getDocument()->updateLayout();
- // FIXME: Maybe DOMRange constructor take const DOMRangeImpl*; if it did we would not need this const_cast.
+ // FIXME: Maybe DOMRange constructor should take const DOMRangeImpl*; if it did we would not need this const_cast.
return plainText(const_cast<RangeImpl *>(this));
}
#include "xml/dom_textimpl.h"
#include "xml/dom_xmlimpl.h"
#include "xml/dom2_rangeimpl.h"
-#include "xml/dom_selection.h"
#include "xml/dom2_eventsimpl.h"
#include "xml/xml_tokenizer.h"
#include <qptrstack.h>
#include <qpaintdevicemetrics.h>
+#include <qregexp.h>
#include <kdebug.h>
#include <kstaticdeleter.h>
#include "khtmlview.h"
#include "khtml_part.h"
-#include "khtml_text_operations.h"
#include <kglobalsettings.h>
#include <kstringhandler.h>
#include "cssvalues.h"
-#include "jsediting.h"
+#include "editing/jsediting.h"
+#include "editing/visible_text.h"
#include <kio/job.h>
#include "decoder.h"
#endif
-#include "htmlediting.h"
-
class QPaintDevice;
class QPaintDeviceMetrics;
class KHTMLView;
namespace khtml {
class CSSStyleSelector;
class DocLoader;
- class EditCommand;
class RenderImage;
class Tokenizer;
class XMLHandler;
#include "css/css_valueimpl.h"
#include "css/css_stylesheetimpl.h"
#include "css/cssstyleselector.h"
-#include "xml/dom_selection.h"
#include "xml/dom_xmlimpl.h"
#include <qtextstream.h>
#include "xml/dom2_eventsimpl.h"
#include "xml/dom_docimpl.h"
#include "xml/dom_position.h"
-#include "xml/dom_selection.h"
#include "xml/dom2_rangeimpl.h"
#include "css/csshelper.h"
#include "css/cssstyleselector.h"
#include "css_computedstyle.h"
#include "css_valueimpl.h"
+#include "dom_elementimpl.h"
+#include "dom_nodeimpl.h"
+#include "dom_positioniterator.h"
+#include "dom2_range.h"
#include "dom2_viewsimpl.h"
#include "helper.h"
#include "htmltags.h"
#include "rendering/render_line.h"
#include "rendering/render_style.h"
#include "rendering/render_text.h"
-#include "xml/dom_positioniterator.h"
-#include "xml/dom_elementimpl.h"
-#include "xml/dom_nodeimpl.h"
#if APPLE_CHANGES
#include "KWQAssertions.h"
+++ /dev/null
-/*
- * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "dom_selection.h"
-
-#include "dom_caretposition.h"
-#include "dom_docimpl.h"
-#include "dom_elementimpl.h"
-#include "dom_node.h"
-#include "dom_nodeimpl.h"
-#include "dom_positioniterator.h"
-#include "dom_string.h"
-#include "dom_textimpl.h"
-#include "dom2_rangeimpl.h"
-#include "htmltags.h"
-#include "khtml_part.h"
-#include "khtmlview.h"
-#include "qevent.h"
-#include "qpainter.h"
-#include "qrect.h"
-#include "render_object.h"
-#include "render_style.h"
-#include "render_text.h"
-
-#if APPLE_CHANGES
-#include "KWQAssertions.h"
-#else
-#define ASSERT(assertion) assert(assertion)
-#endif
-
-#define EDIT_DEBUG 0
-
-using khtml::findWordBoundary;
-using khtml::InlineTextBox;
-using khtml::RenderObject;
-using khtml::RenderText;
-
-namespace DOM {
-
-static Selection selectionForLine(const Position &position);
-
-Selection::Selection()
-{
- init();
-}
-
-Selection::Selection(const Position &pos)
- : m_base(pos), m_extent(pos)
-{
- init();
- validate();
-}
-
-Selection::Selection(const Range &r)
- : m_base(startPosition(r)), m_extent(endPosition(r))
-{
- init();
- validate();
-}
-
-Selection::Selection(const Position &base, const Position &extent)
- : m_base(base), m_extent(extent)
-{
- init();
- validate();
-}
-
-Selection::Selection(const CaretPosition &base, const CaretPosition &extent)
- : m_base(base.position()), m_extent(extent.position())
-{
- init();
- validate();
-}
-
-Selection::Selection(const Selection &o)
- : m_base(o.m_base), m_extent(o.m_extent)
- , m_start(o.m_start), m_end(o.m_end)
- , m_state(o.m_state), m_affinity(o.m_affinity)
- , m_baseIsStart(o.m_baseIsStart)
- , m_needsCaretLayout(o.m_needsCaretLayout)
- , m_modifyBiasSet(o.m_modifyBiasSet)
-{
- // Only copy the coordinates over if the other object
- // has had a layout, otherwise keep the current
- // coordinates. This prevents drawing artifacts from
- // remaining when the caret is painted and then moves,
- // and the old rectangle needs to be repainted.
- if (!m_needsCaretLayout) {
- m_caretRect = o.m_caretRect;
- }
-}
-
-void Selection::init()
-{
- m_state = NONE;
- m_affinity = DOWNSTREAM;
- m_baseIsStart = true;
- m_needsCaretLayout = true;
- m_modifyBiasSet = false;
-}
-
-Selection &Selection::operator=(const Selection &o)
-{
- m_base = o.m_base;
- m_extent = o.m_extent;
- m_start = o.m_start;
- m_end = o.m_end;
-
- m_state = o.m_state;
- m_affinity = o.m_affinity;
-
- m_baseIsStart = o.m_baseIsStart;
- m_needsCaretLayout = o.m_needsCaretLayout;
- m_modifyBiasSet = o.m_modifyBiasSet;
-
- // Only copy the coordinates over if the other object
- // has had a layout, otherwise keep the current
- // coordinates. This prevents drawing artifacts from
- // remaining when the caret is painted and then moves,
- // and the old rectangle needs to be repainted.
- if (!m_needsCaretLayout) {
- m_caretRect = o.m_caretRect;
- }
-
- return *this;
-}
-
-void Selection::setAffinity(EAffinity affinity)
-{
- if (affinity == m_affinity)
- return;
-
- m_affinity = affinity;
- setNeedsLayout();
-}
-
-void Selection::moveTo(const Range &r)
-{
- m_base = startPosition(r);
- m_extent = endPosition(r);
- validate();
-}
-
-void Selection::moveTo(const Selection &o)
-{
- m_base = o.m_start;
- m_extent = o.m_end;
- validate();
-}
-
-void Selection::moveTo(const Position &pos)
-{
- m_base = pos;
- m_extent = pos;
- validate();
-}
-
-void Selection::moveTo(const Position &base, const Position &extent)
-{
- m_base = base;
- m_extent = extent;
- validate();
-}
-
-void Selection::setModifyBias(EAlter alter, EDirection direction)
-{
- switch (alter) {
- case MOVE:
- m_modifyBiasSet = false;
- break;
- case EXTEND:
- if (!m_modifyBiasSet) {
- m_modifyBiasSet = true;
- switch (direction) {
- // FIXME: right for bidi?
- case RIGHT:
- case FORWARD:
- m_base = m_start;
- m_extent = m_end;
- break;
- case LEFT:
- case BACKWARD:
- m_base = m_end;
- m_extent = m_start;
- break;
- }
- }
- break;
- }
-}
-
-CaretPosition Selection::modifyExtendingRightForward(ETextGranularity granularity)
-{
- CaretPosition pos = m_extent;
- switch (granularity) {
- case CHARACTER:
- pos = pos.next();
- break;
- case WORD:
- pos = nextWordPosition(pos);
- break;
- case PARAGRAPH:
- pos = nextParagraphPosition(pos, xPosForVerticalArrowNavigation(EXTENT));
- break;
- case LINE:
- pos = nextLinePosition(pos, xPosForVerticalArrowNavigation(EXTENT));
- break;
- case LINE_BOUNDARY:
- pos = selectionForLine(m_end).end();
- break;
- case PARAGRAPH_BOUNDARY:
- pos = endOfParagraph(m_end);
- break;
- case DOCUMENT_BOUNDARY: {
- NodeImpl *de = m_start.node()->getDocument()->documentElement();
- pos = Position(de, de ? de->childNodeCount() : 0);
- break;
- }
- }
- return pos;
-}
-
-CaretPosition Selection::modifyMovingRightForward(ETextGranularity granularity)
-{
- CaretPosition pos;
- switch (granularity) {
- case CHARACTER:
- if (isRange())
- pos = m_end;
- else
- pos = CaretPosition(m_extent).next();
- break;
- case WORD:
- pos = nextWordPosition(m_extent);
- break;
- case PARAGRAPH:
- pos = nextParagraphPosition(m_end, xPosForVerticalArrowNavigation(END, isRange()));
- break;
- case LINE:
- pos = nextLinePosition(m_end, xPosForVerticalArrowNavigation(END, isRange()));
- break;
- case LINE_BOUNDARY:
- pos = selectionForLine(m_end).end();
- break;
- case PARAGRAPH_BOUNDARY:
- pos = endOfParagraph(m_end);
- break;
- case DOCUMENT_BOUNDARY: {
- NodeImpl *de = m_start.node()->getDocument()->documentElement();
- pos = Position(de, de ? de->childNodeCount() : 0);
- break;
- }
- }
- return pos;
-}
-
-CaretPosition Selection::modifyExtendingLeftBackward(ETextGranularity granularity)
-{
- CaretPosition pos = m_extent;
- switch (granularity) {
- case CHARACTER:
- pos = pos.previous();
- break;
- case WORD:
- pos = previousWordPosition(pos);
- break;
- case PARAGRAPH:
- pos = previousParagraphPosition(pos, xPosForVerticalArrowNavigation(EXTENT));
- break;
- case LINE:
- pos = previousLinePosition(pos, xPosForVerticalArrowNavigation(EXTENT));
- break;
- case LINE_BOUNDARY:
- pos = selectionForLine(m_start).start();
- break;
- case PARAGRAPH_BOUNDARY:
- pos = startOfParagraph(m_start);
- break;
- case DOCUMENT_BOUNDARY:
- pos = CaretPosition(m_start.node()->getDocument()->documentElement(), 0);
- break;
- }
- return pos;
-}
-
-CaretPosition Selection::modifyMovingLeftBackward(ETextGranularity granularity)
-{
- CaretPosition pos;
- switch (granularity) {
- case CHARACTER:
- if (isRange())
- pos = m_start;
- else
- pos = CaretPosition(m_extent).previous();
- break;
- case WORD:
- pos = previousWordPosition(m_extent);
- break;
- case PARAGRAPH:
- pos = previousParagraphPosition(m_start, xPosForVerticalArrowNavigation(START, isRange()));
- break;
- case LINE:
- pos = previousLinePosition(m_start, xPosForVerticalArrowNavigation(START, isRange()));
- break;
- case LINE_BOUNDARY:
- pos = selectionForLine(m_start).start();
- break;
- case PARAGRAPH_BOUNDARY:
- pos = startOfParagraph(m_start).deepEquivalent();
- break;
- case DOCUMENT_BOUNDARY:
- pos = CaretPosition(m_start.node()->getDocument()->documentElement(), 0);
- break;
- }
- return pos;
-}
-
-bool Selection::modify(EAlter alter, EDirection dir, ETextGranularity granularity)
-{
- setModifyBias(alter, dir);
-
- CaretPosition pos;
-
- switch (dir) {
- // EDIT FIXME: These need to handle bidi
- case RIGHT:
- case FORWARD:
- if (alter == EXTEND)
- pos = modifyExtendingRightForward(granularity);
- else
- pos = modifyMovingRightForward(granularity);
- break;
- case LEFT:
- case BACKWARD:
- if (alter == EXTEND)
- pos = modifyExtendingLeftBackward(granularity);
- else
- pos = modifyMovingLeftBackward(granularity);
- break;
- }
-
- if (pos.isNull())
- return false;
-
- switch (alter) {
- case MOVE:
- moveTo(pos.deepEquivalent());
- break;
- case EXTEND:
- setExtent(pos.deepEquivalent());
- break;
- }
-
- return true;
-}
-
-// FIXME: Maybe baseline would be better?
-static bool caretY(const CaretPosition &c, int &y)
-{
- Position p = c.deepEquivalent();
- NodeImpl *n = p.node();
- if (!n)
- return false;
- RenderObject *r = p.node()->renderer();
- if (!r)
- return false;
- QRect rect = r->caretRect(p.offset(), false);
- if (rect.isEmpty())
- return false;
- y = rect.y() + rect.height() / 2;
- return true;
-}
-
-bool Selection::modify(EAlter alter, int verticalDistance)
-{
- if (verticalDistance == 0) {
- return false;
- }
-
- setModifyBias(alter, verticalDistance > 0 ? FORWARD : BACKWARD);
-
- CaretPosition pos;
-
- int xPos = 0; /* initialized only to make compiler happy */
- switch (alter) {
- case MOVE:
- pos = verticalDistance > 0 ? m_end : m_start;
- xPos = xPosForVerticalArrowNavigation(verticalDistance > 0 ? END : START, isRange());
- break;
- case EXTEND:
- pos = m_extent;
- xPos = xPosForVerticalArrowNavigation(EXTENT);
- break;
- }
-
- int startY;
- if (!caretY(pos, startY))
- return false;
- if (verticalDistance < 0)
- startY = -startY;
- int lastY = startY;
-
- CaretPosition result;
-
- CaretPosition next;
- for (CaretPosition p = pos; ; p = next) {
- next = verticalDistance > 0
- ? nextLinePosition(p, xPos)
- : previousLinePosition(p, xPos);
- if (next.isNull() || next == p)
- break;
- int nextY;
- if (!caretY(next, nextY))
- break;
- if (verticalDistance < 0)
- nextY = -nextY;
- if (nextY - startY > verticalDistance)
- break;
- if (nextY >= lastY) {
- lastY = nextY;
- result = next;
- }
- }
-
- if (result.isNull())
- return false;
-
- switch (alter) {
- case MOVE:
- moveTo(result.deepEquivalent());
- break;
- case EXTEND:
- setExtent(result.deepEquivalent());
- break;
- }
-
- return true;
-}
-
-bool Selection::expandUsingGranularity(ETextGranularity granularity)
-{
- if (isNone())
- return false;
- validate(granularity);
- return true;
-}
-
-int Selection::xPosForVerticalArrowNavigation(EPositionType type, bool recalc) const
-{
- int x = 0;
-
- if (isNone())
- return x;
-
- Position pos;
- switch (type) {
- case START:
- pos = m_start;
- break;
- case END:
- pos = m_end;
- break;
- case BASE:
- pos = m_base;
- break;
- case EXTENT:
- pos = m_extent;
- break;
- }
-
- KHTMLPart *part = pos.node()->getDocument()->part();
- if (!part)
- return x;
-
- if (recalc || part->xPosForVerticalArrowNavigation() == KHTMLPart::NoXPosForVerticalArrowNavigation) {
- x = pos.node()->renderer()->caretRect(pos.offset(), false).x();
- part->setXPosForVerticalArrowNavigation(x);
- }
- else {
- x = part->xPosForVerticalArrowNavigation();
- }
-
- return x;
-}
-
-void Selection::clear()
-{
- m_base.clear();
- m_extent.clear();
- validate();
-}
-
-void Selection::setBase(const Position &pos)
-{
- m_base = pos;
- validate();
-}
-
-void Selection::setExtent(const Position &pos)
-{
- m_extent = pos;
- validate();
-}
-
-void Selection::setBaseAndExtent(const Position &base, const Position &extent)
-{
- m_base = base;
- m_extent = extent;
- validate();
-}
-
-void Selection::setNeedsLayout(bool flag)
-{
- m_needsCaretLayout = flag;
-}
-
-Range Selection::toRange() const
-{
- if (isNone())
- return Range();
-
- // Make sure we have an updated layout since this function is called
- // in the course of running edit commands which modify the DOM.
- // Failing to call this can result in equivalentXXXPosition calls returning
- // incorrect results.
- m_start.node()->getDocument()->updateLayout();
-
- Position s, e;
- if (isCaret()) {
- // If the selection is a caret, move the range start upstream. This helps us match
- // the conventions of text editors tested, which make style determinations based
- // on the character before the caret, if any.
- s = m_start.upstream(StayInBlock).equivalentRangeCompliantPosition();
- e = s;
- }
- else {
- // If the selection is a range, select the minimum range that encompasses the selection.
- // Again, this is to match the conventions of text editors tested, which make style
- // determinations based on the first character of the selection.
- // For instance, this operation helps to make sure that the "X" selected below is the
- // only thing selected. The range should not be allowed to "leak" out to the end of the
- // previous text node, or to the beginning of the next text node, each of which has a
- // different style.
- //
- // On a treasure map, <b>X</b> marks the spot.
- // ^ selected
- //
- ASSERT(isRange());
- s = m_start.downstream();
- e = m_end.upstream();
- if (RangeImpl::compareBoundaryPoints(s.node(), s.offset(), e.node(), e.offset()) > 0) {
- // Make sure the start is before the end.
- // The end can wind up before the start if collapsed whitespace is the only thing selected.
- Position tmp = s;
- s = e;
- e = tmp;
- }
- s = s.equivalentRangeCompliantPosition();
- e = e.equivalentRangeCompliantPosition();
- }
-
- return Range(s.node(), s.offset(), e.node(), e.offset());
-}
-
-void Selection::layoutCaret()
-{
- if (!isCaret() || !m_start.node()->inDocument()) {
- m_caretRect = QRect();
- return;
- }
-
- // EDIT FIXME: Enhance call to pass along selection
- // upstream/downstream affinity to get the right position.
- m_caretRect = m_start.node()->renderer()->caretRect(m_start.offset(), false);
-
- m_needsCaretLayout = false;
-}
-
-QRect Selection::caretRect() const
-{
- if (m_needsCaretLayout) {
- const_cast<Selection *>(this)->layoutCaret();
- }
-
- return m_caretRect;
-}
-
-QRect Selection::caretRepaintRect() const
-{
- // FIXME: Add one pixel of slop on each side to make sure we don't leave behind artifacts.
- QRect r = caretRect();
- if (r.isEmpty())
- return QRect();
- return QRect(r.left() - 1, r.top() - 1, r.width() + 2, r.height() + 2);
-}
-
-void Selection::needsCaretRepaint()
-{
- if (!isCaret())
- return;
-
- if (!m_start.node()->getDocument())
- return;
-
- KHTMLView *v = m_start.node()->getDocument()->view();
- if (!v)
- return;
-
- if (m_needsCaretLayout) {
- // repaint old position and calculate new position
- v->updateContents(caretRepaintRect(), false);
- layoutCaret();
-
- // EDIT FIXME: This is an unfortunate hack.
- // Basically, we can't trust this layout position since we
- // can't guarantee that the check to see if we are in unrendered
- // content will work at this point. We may have to wait for
- // a layout and re-render of the document to happen. So, resetting this
- // flag will cause another caret layout to happen the first time
- // that we try to paint the caret after this call. That one will work since
- // it happens after the document has accounted for any editing
- // changes which may have been done.
- // And, we need to leave this layout here so the caret moves right
- // away after clicking.
- m_needsCaretLayout = true;
- }
- v->updateContents(caretRepaintRect(), false);
-}
-
-void Selection::paintCaret(QPainter *p, const QRect &rect)
-{
- if (m_state != CARET)
- return;
-
- if (m_needsCaretLayout)
- layoutCaret();
-
- if (m_caretRect.isValid())
- p->fillRect(m_caretRect & rect, QBrush());
-}
-
-void Selection::validate(ETextGranularity granularity)
-{
- // Move the selection to rendered positions, if possible.
- Position originalBase(m_base);
- bool baseAndExtentEqual = m_base == m_extent;
- bool updatedLayout = false;
- if (m_base.isNotNull()) {
- m_base.node()->getDocument()->updateLayout();
- updatedLayout = true;
- m_base = m_base.equivalentDeepPosition().closestRenderedPosition(affinity());
- if (baseAndExtentEqual)
- m_extent = m_base;
- }
- if (m_extent.isNotNull() && !baseAndExtentEqual) {
- if (!updatedLayout)
- m_extent.node()->getDocument()->updateLayout();
- m_extent = m_extent.equivalentDeepPosition().closestRenderedPosition(affinity());
- }
-
- // Make sure we do not have a dangling start or end
- if (m_base.isNull() && m_extent.isNull()) {
- // Move the position to the enclosingBlockFlowElement of the original base, if possible.
- // This has the effect of flashing the caret somewhere when a rendered position for
- // the base and extent cannot be found.
- if (originalBase.isNotNull()) {
- Position pos(originalBase.node()->enclosingBlockFlowElement(), 0);
- m_base = pos;
- m_extent = pos;
- }
- else {
- // We have no position to work with. See if the BODY element of the page
- // is contentEditable. If it is, put the caret there.
- //NodeImpl *node = document()
- m_start.clear();
- m_end.clear();
- }
- m_baseIsStart = true;
- }
- else if (m_base.isNull()) {
- m_base = m_extent;
- m_baseIsStart = true;
- }
- else if (m_extent.isNull()) {
- m_extent = m_base;
- m_baseIsStart = true;
- }
- else {
- m_baseIsStart = RangeImpl::compareBoundaryPoints(m_base.node(), m_base.offset(), m_extent.node(), m_extent.offset()) <= 0;
- }
-
- m_start.clear();
- m_end.clear();
-
- // calculate the correct start and end positions
- switch (granularity) {
- case CHARACTER:
- if (m_baseIsStart) {
- m_start = m_base;
- m_end = m_extent;
- } else {
- m_start = m_extent;
- m_end = m_base;
- }
- break;
- case WORD:
- if (m_baseIsStart) {
- m_end = endOfWord(m_extent).deepEquivalent();
- // If at the end of the document, expand to the left.
- EWordSide side = (m_end == m_extent) ? LeftWordIfOnBoundary : RightWordIfOnBoundary;
- m_start = startOfWord(m_base, side).deepEquivalent();
- } else {
- m_start = startOfWord(m_extent).deepEquivalent();
- m_end = endOfWord(m_base).deepEquivalent();
- }
- break;
- case LINE:
- case LINE_BOUNDARY: {
- Selection baseSelection = *this;
- Selection extentSelection = *this;
- Selection baseLine = selectionForLine(m_base);
- if (baseLine.isCaretOrRange()) {
- baseSelection = baseLine;
- }
- Selection extentLine = selectionForLine(m_extent);
- if (extentLine.isCaretOrRange()) {
- extentSelection = extentLine;
- }
- if (m_baseIsStart) {
- m_start = baseSelection.m_start;
- m_end = extentSelection.m_end;
- } else {
- m_start = extentSelection.m_start;
- m_end = baseSelection.m_end;
- }
- break;
- }
- case PARAGRAPH:
- if (m_baseIsStart) {
- m_start = startOfParagraph(m_base).deepEquivalent();
- m_end = endOfParagraph(m_extent, IncludeLineBreak).deepEquivalent();
- } else {
- m_start = startOfParagraph(m_extent).deepEquivalent();
- m_end = endOfParagraph(m_base, IncludeLineBreak).deepEquivalent();
- }
- break;
- case DOCUMENT_BOUNDARY: {
- NodeImpl *de = m_start.node()->getDocument()->documentElement();
- m_start = CaretPosition(de, 0).deepEquivalent();
- m_end = CaretPosition(de, de ? de->childNodeCount() : 0).deepEquivalent();
- break;
- }
- case PARAGRAPH_BOUNDARY:
- if (m_baseIsStart) {
- m_start = startOfParagraph(m_base).deepEquivalent();
- m_end = endOfParagraph(m_extent).deepEquivalent();
- } else {
- m_start = startOfParagraph(m_extent).deepEquivalent();
- m_end = endOfParagraph(m_base).deepEquivalent();
- }
- break;
- }
-
- // adjust the state
- if (m_start.isNull()) {
- ASSERT(m_end.isNull());
- m_state = NONE;
- }
- else if (m_start == m_end || m_start.upstream(StayInBlock) == m_end.upstream(StayInBlock)) {
- m_state = CARET;
- }
- else {
- m_state = RANGE;
- // "Constrain" the selection to be the smallest equivalent range of nodes.
- // This is a somewhat arbitrary choice, but experience shows that it is
- // useful to make to make the selection "canonical" (if only for
- // purposes of comparing selections). This is an ideal point of the code
- // to do this operation, since all selection changes that result in a RANGE
- // come through here before anyone uses it.
- m_start = m_start.downstream(StayInBlock);
- m_end = m_end.upstream(StayInBlock);
- }
-
- m_needsCaretLayout = true;
-
-#if EDIT_DEBUG
- debugPosition();
-#endif
-}
-
-static Position startOfFirstRunAt(RenderObject *renderNode, int y)
-{
- for (RenderObject *n = renderNode; n; n = n->nextSibling()) {
- if (n->isText()) {
- RenderText *textRenderer = static_cast<RenderText *>(n);
- for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox())
- if (box->m_y == y)
- return Position(textRenderer->element(), box->m_start);
- }
-
- Position position = startOfFirstRunAt(n->firstChild(), y);
- if (position.isNotNull())
- return position;
- }
-
- return Position();
-}
-
-static Position endOfLastRunAt(RenderObject *renderNode, int y)
-{
- RenderObject *n = renderNode;
- if (!n)
- return Position();
- if (RenderObject *parent = n->parent())
- n = parent->lastChild();
-
- while (1) {
- Position position = endOfLastRunAt(n->firstChild(), y);
- if (position.isNotNull())
- return position;
-
- if (n->isText()) {
- RenderText *textRenderer = static_cast<RenderText *>(n);
- for (InlineTextBox* box = textRenderer->lastTextBox(); box; box = box->prevTextBox())
- if (box->m_y == y)
- return Position(textRenderer->element(), box->m_start + box->m_len);
- }
-
- if (n == renderNode)
- return Position();
-
- n = n->previousSibling();
- }
-}
-
-static Selection selectionForLine(const Position &position)
-{
- NodeImpl *node = position.node();
-
- if (!node)
- return Selection();
-
- switch (node->nodeType()) {
- case Node::TEXT_NODE:
- case Node::CDATA_SECTION_NODE:
- break;
- default:
- return Selection();
- }
-
- RenderText *renderer = static_cast<RenderText *>(node->renderer());
-
- int pos;
- InlineTextBox *run = renderer->findNextInlineTextBox(position.offset(), pos);
- if (!run)
- return Selection();
-
- int selectionPointY = run->m_y;
-
- // Go up to first non-inline element.
- RenderObject *renderNode = renderer;
- while (renderNode && renderNode->isInline())
- renderNode = renderNode->parent();
- renderNode = renderNode->firstChild();
-
- // Look for all the first child in the block that is on the same line
- // as the selection point.
- Position start = startOfFirstRunAt(renderNode, selectionPointY);
- if (start.isNull())
- return Selection();
-
- // Look for all the last child in the block that is on the same line
- // as the selection point.
- Position end = endOfLastRunAt(renderNode, selectionPointY);
- if (end.isNull())
- return Selection();
-
- return Selection(start, end);
-}
-
-void Selection::debugRenderer(RenderObject *r, bool selected) const
-{
- if (r->node()->isElementNode()) {
- ElementImpl *element = static_cast<ElementImpl *>(r->node());
- fprintf(stderr, "%s%s\n", selected ? "==> " : " ", element->tagName().string().latin1());
- }
- else if (r->isText()) {
- RenderText *textRenderer = static_cast<RenderText *>(r);
- if (textRenderer->stringLength() == 0 || !textRenderer->firstTextBox()) {
- fprintf(stderr, "%s#text (empty)\n", selected ? "==> " : " ");
- return;
- }
-
- static const int max = 36;
- QString text = DOMString(textRenderer->string()).string();
- int textLength = text.length();
- if (selected) {
- int offset = 0;
- if (r->node() == m_start.node())
- offset = m_start.offset();
- else if (r->node() == m_end.node())
- offset = m_end.offset();
-
- int pos;
- InlineTextBox *box = textRenderer->findNextInlineTextBox(offset, pos);
- text = text.mid(box->m_start, box->m_len);
-
- QString show;
- int mid = max / 2;
- int caret = 0;
-
- // text is shorter than max
- if (textLength < max) {
- show = text;
- caret = pos;
- }
-
- // too few characters to left
- else if (pos - mid < 0) {
- show = text.left(max - 3) + "...";
- caret = pos;
- }
-
- // enough characters on each side
- else if (pos - mid >= 0 && pos + mid <= textLength) {
- show = "..." + text.mid(pos - mid + 3, max - 6) + "...";
- caret = mid;
- }
-
- // too few characters on right
- else {
- show = "..." + text.right(max - 3);
- caret = pos - (textLength - show.length());
- }
-
- show = show.replace("\n", " ");
- show = show.replace("\r", " ");
- fprintf(stderr, "==> #text : \"%s\" at offset %d\n", show.latin1(), pos);
- fprintf(stderr, " ");
- for (int i = 0; i < caret; i++)
- fprintf(stderr, " ");
- fprintf(stderr, "^\n");
- }
- else {
- if ((int)text.length() > max)
- text = text.left(max - 3) + "...";
- else
- text = text.left(max);
- fprintf(stderr, " #text : \"%s\"\n", text.latin1());
- }
- }
-}
-
-void Selection::debugPosition() const
-{
- if (!m_start.node())
- return;
-
- //static int context = 5;
-
- //RenderObject *r = 0;
-
- fprintf(stderr, "Selection =================\n");
-
- if (m_start == m_end) {
- Position pos = m_start;
- Position upstream = pos.upstream();
- Position downstream = pos.downstream();
- fprintf(stderr, "upstream: %s %p:%d\n", getTagName(upstream.node()->id()).string().latin1(), upstream.node(), upstream.offset());
- fprintf(stderr, "pos: %s %p:%d\n", getTagName(pos.node()->id()).string().latin1(), pos.node(), pos.offset());
- fprintf(stderr, "downstream: %s %p:%d\n", getTagName(downstream.node()->id()).string().latin1(), downstream.node(), downstream.offset());
- }
- else {
- Position pos = m_start;
- Position upstream = pos.upstream();
- Position downstream = pos.downstream();
- fprintf(stderr, "upstream: %s %p:%d\n", getTagName(upstream.node()->id()).string().latin1(), upstream.node(), upstream.offset());
- fprintf(stderr, "start: %s %p:%d\n", getTagName(pos.node()->id()).string().latin1(), pos.node(), pos.offset());
- fprintf(stderr, "downstream: %s %p:%d\n", getTagName(downstream.node()->id()).string().latin1(), downstream.node(), downstream.offset());
- fprintf(stderr, "-----------------------------------\n");
- pos = m_end;
- upstream = pos.upstream();
- downstream = pos.downstream();
- fprintf(stderr, "upstream: %s %p:%d\n", getTagName(upstream.node()->id()).string().latin1(), upstream.node(), upstream.offset());
- fprintf(stderr, "end: %s %p:%d\n", getTagName(pos.node()->id()).string().latin1(), pos.node(), pos.offset());
- fprintf(stderr, "downstream: %s %p:%d\n", getTagName(downstream.node()->id()).string().latin1(), downstream.node(), downstream.offset());
- fprintf(stderr, "-----------------------------------\n");
- }
-
-#if 0
- int back = 0;
- r = m_start.node()->renderer();
- for (int i = 0; i < context; i++, back++) {
- if (r->previousRenderer())
- r = r->previousRenderer();
- else
- break;
- }
- for (int i = 0; i < back; i++) {
- debugRenderer(r, false);
- r = r->nextRenderer();
- }
-
-
- fprintf(stderr, "\n");
-
- if (m_start.node() == m_end.node())
- debugRenderer(m_start.node()->renderer(), true);
- else
- for (r = m_start.node()->renderer(); r && r != m_end.node()->renderer(); r = r->nextRenderer())
- debugRenderer(r, true);
-
- fprintf(stderr, "\n");
-
- r = m_end.node()->renderer();
- for (int i = 0; i < context; i++) {
- if (r->nextRenderer()) {
- r = r->nextRenderer();
- debugRenderer(r, false);
- }
- else
- break;
- }
-#endif
-
- fprintf(stderr, "================================\n");
-}
-
-#ifndef NDEBUG
-#define FormatBufferSize 1024
-void Selection::formatForDebugger(char *buffer, unsigned length) const
-{
- DOMString result;
- DOMString s;
-
- if (isNone()) {
- result = "<none>";
- }
- else {
- char s[FormatBufferSize];
- result += "from ";
- m_start.formatForDebugger(s, FormatBufferSize);
- result += s;
- result += " to ";
- m_end.formatForDebugger(s, FormatBufferSize);
- result += s;
- }
-
- strncpy(buffer, result.string().latin1(), length - 1);
-}
-#undef FormatBufferSize
-#endif
-
-} // namespace DOM
+++ /dev/null
-/*
- * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __dom_selection_h__
-#define __dom_selection_h__
-
-#include <qrect.h>
-#include "dom_caretposition.h"
-
-class KHTMLPart;
-class QPainter;
-
-namespace khtml {
- class RenderObject;
-}
-
-namespace DOM {
-
-class NodeImpl;
-class Position;
-class Range;
-
-class Selection
-{
-public:
- enum EState { NONE, CARET, RANGE };
- enum EAlter { MOVE, EXTEND };
- enum EDirection { FORWARD, BACKWARD, RIGHT, LEFT };
- enum ETextGranularity { CHARACTER, WORD, LINE, PARAGRAPH, LINE_BOUNDARY, PARAGRAPH_BOUNDARY, DOCUMENT_BOUNDARY };
-
- Selection();
- Selection(const Range &);
- Selection(const CaretPosition &);
- Selection(const CaretPosition &, const CaretPosition &);
- Selection(const Position &);
- Selection(const Position &, const Position &);
- Selection(const Selection &);
-
- Selection &operator=(const Selection &o);
- Selection &operator=(const Range &r) { moveTo(r); return *this; }
- Selection &operator=(const CaretPosition &r) { moveTo(r); return *this; }
- Selection &operator=(const Position &r) { moveTo(r); return *this; }
-
- void moveTo(const Range &);
- void moveTo(const CaretPosition &);
- void moveTo(const CaretPosition &, const CaretPosition &);
- void moveTo(const Position &);
- void moveTo(const Position &, const Position &);
- void moveTo(const Selection &);
-
- EState state() const { return m_state; }
- EAffinity affinity() const { return m_affinity; }
- void setAffinity(EAffinity);
-
- bool modify(EAlter, EDirection, ETextGranularity);
- bool modify(EAlter, int verticalDistance);
- bool expandUsingGranularity(ETextGranularity);
- void clear();
-
- void setBase(const CaretPosition &);
- void setExtent(const CaretPosition &);
- void setBaseAndExtent(const CaretPosition &base, const CaretPosition &extent);
-
- void setBase(const Position &pos);
- void setExtent(const Position &pos);
- void setBaseAndExtent(const Position &base, const Position &extent);
-
- Position base() const { return m_base; }
- Position extent() const { return m_extent; }
- Position start() const { return m_start; }
- Position end() const { return m_end; }
-
- QRect caretRect() const;
- void setNeedsLayout(bool flag = true);
-
- void clearModifyBias() { m_modifyBiasSet = false; }
- void setModifyBias(EAlter, EDirection);
-
- bool isNone() const { return state() == NONE; }
- bool isCaret() const { return state() == CARET; }
- bool isRange() const { return state() == RANGE; }
- bool isCaretOrRange() const { return state() != NONE; }
-
- Range toRange() const;
-
- void debugPosition() const;
- void debugRenderer(khtml::RenderObject *r, bool selected) const;
-
- friend class KHTMLPart;
-
-#ifndef NDEBUG
- void formatForDebugger(char *buffer, unsigned length) const;
-#endif
-
-private:
- enum EPositionType { START, END, BASE, EXTENT };
-
- void init();
- void validate(ETextGranularity granularity = CHARACTER);
-
- CaretPosition modifyExtendingRightForward(ETextGranularity);
- CaretPosition modifyMovingRightForward(ETextGranularity);
- CaretPosition modifyExtendingLeftBackward(ETextGranularity);
- CaretPosition modifyMovingLeftBackward(ETextGranularity);
-
- void layoutCaret();
- void needsCaretRepaint();
- void paintCaret(QPainter *p, const QRect &rect);
- QRect caretRepaintRect() const;
-
- int xPosForVerticalArrowNavigation(EPositionType, bool recalc = false) const;
-
- Position m_base; // base position for the selection
- Position m_extent; // extent position for the selection
- Position m_start; // start position for the selection
- Position m_end; // end position for the selection
-
- EState m_state; // the state of the selection
- EAffinity m_affinity; // the upstream/downstream affinity of the selection
-
- QRect m_caretRect; // caret coordinates, size, and position
-
- bool m_baseIsStart : 1; // true if base node is before the extent node
- bool m_needsCaretLayout : 1; // true if the caret position needs to be calculated
- bool m_modifyBiasSet : 1; // true if the selection has been horizontally
- // modified with EAlter::EXTEND
-};
-
-inline bool operator==(const Selection &a, const Selection &b)
-{
- return a.start() == b.start() && a.end() == b.end();
-}
-
-inline bool operator!=(const Selection &a, const Selection &b)
-{
- return !(a == b);
-}
-
-} // namespace DOM
-
-#endif // __dom_selection_h__
#include "xml/dom_textimpl.h"
#include "xml/dom_xmlimpl.h"
#include "html/html_headimpl.h"
+#include "html/html_tableimpl.h"
#include "misc/htmltags.h"
#include "misc/htmlattrs.h"
#include "misc/loader.h"
#ifndef KWQKHTMLPart_H
#define KWQKHTMLPart_H
-#include "khtml_part.h"
+#import "khtml_part.h"
-#include "dom_nodeimpl.h"
-#include "html_formimpl.h"
-#include "html_tableimpl.h"
+#import "dom_nodeimpl.h"
+#import "dom2_range.h"
#import "WebCoreKeyboardAccess.h"
-#include <CoreFoundation/CoreFoundation.h>
+#import <CoreFoundation/CoreFoundation.h>
-#include <JavaVM/jni.h>
-#include <JavaScriptCore/jni_jsobject.h>
-#include <JavaScriptCore/npruntime.h>
-#include <JavaScriptCore/NP_jsobject.h>
-#include <JavaScriptCore/runtime.h>
+#import <JavaVM/jni.h>
+#import <JavaScriptCore/jni_jsobject.h>
+#import <JavaScriptCore/npruntime.h>
+#import <JavaScriptCore/NP_jsobject.h>
+#import <JavaScriptCore/runtime.h>
-#include "KWQDict.h"
-#include "KWQClipboard.h"
+#import "KWQDict.h"
+#import "KWQClipboard.h"
class KHTMLPartPrivate;
-class KWQClipboard;
class KWQWindowWidget;
+namespace DOM {
+ class DocumentFragmentImpl;
+ class HTMLTableCellElementImpl;
+}
+
namespace khtml {
class RenderObject;
struct DashboardRegionValue;
#import "KWQLogging.h"
#import "KWQPageState.h"
#import "KWQPrinter.h"
+#import "KWQRegExp.h"
#import "KWQScrollBar.h"
#import "KWQWindowWidget.h"
#import "WebCoreBridge.h"
#import "dom2_eventsimpl.h"
#import "dom2_rangeimpl.h"
#import "dom_position.h"
-#import "dom_selection.h"
#import "dom_textimpl.h"
+#import "html_document.h"
#import "html_documentimpl.h"
+#import "html_formimpl.h"
#import "html_misc.h"
+#import "html_tableimpl.h"
#import "htmlattrs.h"
#import "htmltokenizer.h"
-#import "khtml_text_operations.h"
#import "khtmlpart_p.h"
#import "khtmlview.h"
#import "kjs_binding.h"
#import "render_style.h"
#import "render_table.h"
#import "render_text.h"
+#import "selection.h"
+#import "visible_position.h"
+#import "visible_text.h"
+#import "visible_units.h"
+
#import <JavaScriptCore/identifier.h>
#import <JavaScriptCore/property_map.h>
#import <JavaScriptCore/runtime.h>
#include "xml/dom_docimpl.h"
#include "xml/dom_nodeimpl.h"
#include "xml/dom_position.h"
-#include "xml/dom_selection.h"
#include "KWQKHTMLPart.h"
#include "KWQTextStream.h"
#import "dom2_eventsimpl.h"
#import "dom2_rangeimpl.h"
#import "dom2_viewsimpl.h"
-#import "dom_caretposition.h"
#import "dom_docimpl.h"
#import "dom_node.h"
#import "dom_nodeimpl.h"
#import "dom_position.h"
-#import "dom_selection.h"
#import "html_documentimpl.h"
#import "html_formimpl.h"
#import "html_imageimpl.h"
#import "render_object.h"
#import "render_replaced.h"
#import "render_style.h"
+#import "selection.h"
+#import "visible_position.h"
#import <JavaScriptCore/npruntime.h>
#import <JavaScriptCore/jni_jsobject.h>