26 #include "css/css_renderstyledeclarationimpl.h"
27 #include "css/css_valueimpl.h"
28 #include "xml/dom_selection.h"
29 #include "xml/dom_docimpl.h"
30 #include "xml/dom_elementimpl.h"
31 #include "xml/dom_textimpl.h"
32 #include "xml/dom2_rangeimpl.h"
43 # define assert(x) Q_ASSERT(x)
46 #define PREPARE_JSEDITOR_CALL(command, retval) \
47 JSEditor *js = m_part->xmlDocImpl() ? m_part->xmlDocImpl()->jsEditor() : 0; \
48 if (!js) return retval; \
49 const CommandImp *imp = js->commandImp(command)
51 #define DEBUG_COMMANDS
57 using khtml::RenderStyleDeclarationImpl;
84 RefPtr<EditCommandImpl> m_lastEditCommand;
94 :
d(new EditorPrivate), m_typingStyle(0), m_part(part) {
99 m_typingStyle->deref();
106 return js->execCommand(imp, userInterface, value);
112 return js->queryCommandEnabled(imp);
118 return js->queryCommandIndeterm(imp);
124 return js->queryCommandState(imp);
130 return js->queryCommandSupported(imp);
136 return js->queryCommandValue(imp);
142 return js->execCommand(imp, userInterface, value);
148 return js->queryCommandEnabled(imp);
154 return js->queryCommandIndeterm(imp);
160 return js->queryCommandState(imp);
166 return js->queryCommandSupported(imp);
172 return js->queryCommandValue(imp);
206 if (d->m_redo.isEmpty())
208 RefPtr<EditCommandImpl> e = d->m_redo.pop();
214 if (d->m_undo.isEmpty())
216 RefPtr<EditCommandImpl> e = d->m_undo.pop();
222 return !d->m_redo.isEmpty();
227 return !d->m_undo.isEmpty();
232 switch (m_part->caret().state()) {
233 case Selection::NONE:
236 case Selection::CARET:
240 case Selection::RANGE:
241 if (m_part->xmlDocImpl() && style) {
242 #ifdef DEBUG_COMMANDS
243 kDebug() <<
"[create ApplyStyleCommand]" << endl;
254 QListIterator<CSSProperty*> it(*desiredStyle->values());
255 while (it.hasNext()) {
256 int propertyID = it.next()->id();
257 DOMString desiredProperty = desiredStyle->getPropertyValue(propertyID);
258 DOMString computedProperty = computedStyle->getPropertyValue(propertyID);
262 state = propertyState;
264 }
else if (state != propertyState) {
277 if (ctx->
m_selection.state() != Selection::RANGE) {
278 NodeImpl *nodeToRemove;
282 selectionStyle->ref();
283 updateState(style, selectionStyle, atStart, state);
284 selectionStyle->deref();
286 int exceptionCode = 0;
287 nodeToRemove->remove(exceptionCode);
288 assert(exceptionCode == 0);
291 for (NodeImpl *node = ctx->
m_selection.start().node(); node; node = node->traverseNextNode()) {
292 if (node->isHTMLElement()) {
293 CSSStyleDeclarationImpl *computedStyle =
new RenderStyleDeclarationImpl(node);
294 computedStyle->ref();
296 computedStyle->deref();
310 NodeImpl *nodeToRemove;
315 selectionStyle->ref();
319 QListIterator<CSSProperty*> it(*style->values());
320 while (it.hasNext()) {
321 int propertyID = it.next()->id();
322 DOMString desiredProperty = style->getPropertyValue(propertyID);
323 DOMString selectionProperty = selectionStyle->getPropertyValue(propertyID);
324 if (
strcasecmp(selectionProperty, desiredProperty) != 0) {
330 selectionStyle->deref();
333 int exceptionCode = 0;
334 nodeToRemove->
remove(exceptionCode);
335 assert(exceptionCode == 0);
343 NodeImpl *nodeToRemove;
348 selectionStyle->ref();
349 DOMString value = selectionStyle->getPropertyValue(stylePropertyID);
350 selectionStyle->deref();
353 int exceptionCode = 0;
354 nodeToRemove->
remove(exceptionCode);
355 assert(exceptionCode == 0);
365 if (!m_part->xmlDocImpl())
375 ElementImpl *elem = pos.element();
376 ElementImpl *styleElement = elem;
377 int exceptionCode = 0;
380 styleElement = m_part->xmlDocImpl()->createHTMLElement(
"SPAN");
383 styleElement->setAttribute(ATTR_STYLE, m_typingStyle->cssText().implementation());
386 TextImpl *text = m_part->xmlDocImpl()->createEditingTextNode(
"");
387 styleElement->appendChild(text, exceptionCode);
388 assert(exceptionCode == 0);
390 elem->appendChild(styleElement, exceptionCode);
391 assert(exceptionCode == 0);
393 nodeToRemove = styleElement;
396 return new RenderStyleDeclarationImpl(styleElement);
401 return d->m_lastEditCommand;
406 #ifdef DEBUG_COMMANDS
407 kDebug() <<
"[Applied editing]" << endl;
411 m_part->xmlDocImpl()->updateLayout();
415 if (d->m_lastEditCommand == cmd) {
420 d->registerUndo(cmd);
421 d->m_lastEditCommand = cmd;
423 m_part->editorContext()->
m_selection.setNeedsLayout(
true);
424 m_part->selectionLayoutChanged();
432 m_part->xmlDocImpl()->updateLayout();
435 d->registerRedo(cmd);
437 KWQ(
this)->respondToChangedContents();
439 m_part->editorContext()->
m_selection.setNeedsLayout(
true);
440 m_part->selectionLayoutChanged();
444 d->m_lastEditCommand = 0;
450 m_part->xmlDocImpl()->updateLayout();
453 d->registerUndo(cmd,
false );
455 KWQ(
this)->respondToChangedContents();
457 m_part->selectionLayoutChanged();
461 d->m_lastEditCommand = 0;
466 return m_typingStyle;
471 CSSStyleDeclarationImpl *old = m_typingStyle;
472 m_typingStyle = style;
474 m_typingStyle->ref();
494 IndentOutdentCommandImpl::Indent);
501 IndentOutdentCommandImpl::Outdent);
505 bool Editor::handleKeyEvent(QKeyEvent *_ke)
507 bool handled =
false;
509 bool ctrl = _ke->modifiers() & Qt::ControlModifier;
510 bool alt = _ke->modifiers() & Qt::AltModifier;
512 bool meta = _ke->modifiers() & Qt::MetaModifier;
514 if (ctrl || alt || meta) {
520 case Qt::Key_Delete: {
521 Selection selectionToDelete = m_part->caret();
522 #ifdef DEBUG_COMMANDS
523 kDebug(6200) <<
"========== KEY_DELETE ==========" << endl;
525 if (selectionToDelete.state() == Selection::CARET) {
526 Position pos(selectionToDelete.start());
527 #ifdef DEBUG_COMMANDS
528 kDebug(6200) <<
"pos.inLastEditableInRootEditableElement " << pos.inLastEditableInRootEditableElement() <<
" pos.offset " << pos.offset() <<
" pos.max " << pos.node()->caretMaxRenderedOffset() << endl;
530 if (pos.nextCharacterPosition() == pos) {
532 #ifdef DEBUG_COMMANDS
533 kDebug(6200) <<
"no delete!!!!!!!!!!" << endl;
538 = Selection(pos, pos.nextCharacterPosition());
542 case Qt::Key_Backspace:
543 TypingCommandImpl::deleteKeyPressed0(m_part->xmlDocImpl());
550 TypingCommandImpl::insertNewline0(m_part->xmlDocImpl());
564 if (m_part->caret().state() != Selection::CARET) {
568 kDebug(6200) <<
"Editable node w/o caret!";
569 DOM::NodeImpl* focus = m_part->xmlDocImpl()->focusNode();
570 if (m_part->caret().state() == Selection::NONE) {
572 m_part->setCaret(Position(focus, focus->caretMinOffset()));
578 if (!_ke->text().isEmpty()) {
579 TypingCommandImpl::insertText0(m_part->xmlDocImpl(), _ke->text());
595 #include "editor.moc"
This class implements the basic string we use in the DOM.
void remove(unsigned int pos, int len=1)
DOMString queryCommandValue(const DOMString &command)
Returns the given command's value.
void applyStyle(DOM::CSSStyleDeclarationImpl *)
applies the given style to the current selection
TriState
Tri-state boolean.
bool canRedo() const
returns whether any actions can be redone
void print()
prints the current document
void copy()
copy selection to clipboard
void unappliedEditing(khtml::EditCommandImpl *)
Called when editing has been unapplied.
bool queryCommandEnabled(const DOMString &command)
Checks whether the given command is enabled.
WTF::PassRefPtr< khtml::EditCommandImpl > lastEditCommand() const
Returns the most recent edit command applied.
TriState selectionHasStyle(DOM::CSSStyleDeclarationImpl *) const
returns whether the selection has got applied the given style
DOM::CSSStyleDeclarationImpl * selectionComputedStyle(DOM::NodeImpl *&nodeToRemove) const
computed style of current selection
bool execCommand(const DOMString &command, bool userInterface, const DOMString &value)
Executes the given editor command.
bool selectionStartHasStyle(DOM::CSSStyleDeclarationImpl *) const
returns whether the selection has got applied the given style
void clearTypingStyle()
Clears the typing style for the document.
void paste()
paste into current selection from clipboard
bool queryCommandIndeterm(const DOMString &command)
Checks whether the given command's style is indeterminate.
void indent()
indent/outdent current selection
bool canUndo() const
returns whether any actions can be undone
DOM::CSSStyleDeclarationImpl * typingStyle() const
Returns the typing style for the document.
DOM::DOMString selectionStartStylePropertyValue(int stylePropertyID) const
?
void appliedEditing(khtml::EditCommandImpl *)
Called when editing has been applied.
void setTypingStyle(DOM::CSSStyleDeclarationImpl *)
Sets the typing style for the document.
bool queryCommandState(const DOMString &command)
Checks whether the given command's style is state.
void undo()
undo last action
bool queryCommandSupported(const DOMString &command)
Checks whether the given command is supported in the current context.
void reappliedEditing(khtml::EditCommandImpl *)
Called when editing has been reapplied.
bool canPaste() const
returns whether clipboard contains data to be pasted
void cut()
cut selection and insert into clipboard
void redo()
redo last undone action
NodeImpl * handle() const
Node startContainer() const
Node within which the range begins.
long startOffset() const
Offset within the starting node of the range.
This is the BrowserExtension for a KHTMLPart document.
khtml::EditorContext editor_context
This class is khtml's main class.
KParts::BrowserExtension * browserExtension() const
Returns a pointer to the KParts::BrowserExtension.
virtual bool isTypingCommand() const
DOM::Selection endingSelection() const
DOM::Selection startingSelection() const
#define PREPARE_JSEDITOR_CALL(command, retval)
static void updateState(CSSStyleDeclarationImpl *desiredStyle, CSSStyleDeclarationImpl *computedStyle, bool &atStart, Editor::TriState &state)
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
This library provides a full-featured HTML parser and widget.
EditorCommand
List of all supported built-in editor commands.
static const int sMaxUndoSteps
bool strcasecmp(const DOMString &a, const DOMString &b)
Contextual information about the caret and the built-in editor.
DOM::Selection m_selection