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())
373 Position pos(range.startContainer().handle(), range.startOffset());
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();
488 static_cast<TypingCommandImpl*>(lastCommand)->closeTyping();
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" Contextual information about the caret and the built-in editor.
DOMString queryCommandValue(const DOMString &command)
Returns the given command's value.
void reappliedEditing(khtml::EditCommandImpl *)
Called when editing has been reapplied.
EditorCommand
List of all supported built-in editor commands.
DOM::Selection m_selection
KParts::BrowserExtension * browserExtension() const
Returns a pointer to the KParts::BrowserExtension.
bool canUndo() const
returns whether any actions can be undone
void redo()
redo last undone action
khtml::EditorContext editor_context
bool execCommand(const DOMString &command, bool userInterface, const DOMString &value)
Executes the given editor command.
bool strcasecmp(const DOMString &a, const DOMString &b)
bool queryCommandEnabled(const DOMString &command)
Checks whether the given command is enabled.
void remove(unsigned int pos, int len=1)
bool selectionStartHasStyle(DOM::CSSStyleDeclarationImpl *) const
returns whether the selection has got applied the given style
This class is khtml's main class.
#define PREPARE_JSEDITOR_CALL(command, retval)
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
static const int sMaxUndoSteps
virtual bool isTypingCommand() const
TriState
Tri-state boolean.
bool queryCommandIndeterm(const DOMString &command)
Checks whether the given command's style is indeterminate.
void copy()
copy selection to clipboard
void unappliedEditing(khtml::EditCommandImpl *)
Called when editing has been unapplied.
WTF::PassRefPtr< khtml::EditCommandImpl > lastEditCommand() const
Returns the most recent edit command applied.
DOM::CSSStyleDeclarationImpl * selectionComputedStyle(DOM::NodeImpl *&nodeToRemove) const
computed style of current selection
bool canPaste() const
returns whether clipboard contains data to be pasted
TriState selectionHasStyle(DOM::CSSStyleDeclarationImpl *) const
returns whether the selection has got applied the given style
bool queryCommandState(const DOMString &command)
Checks whether the given command's style is state.
This class implements the basic string we use in the DOM.
void applyStyle(DOM::CSSStyleDeclarationImpl *)
applies the given style to the current selection
DOM::Selection endingSelection() const
void appliedEditing(khtml::EditCommandImpl *)
Called when editing has been applied.
void cut()
cut selection and insert into clipboard
This library provides a full-featured HTML parser and widget.
void indent()
indent/outdent current selection
void print()
prints the current document
void undo()
undo last action
bool queryCommandSupported(const DOMString &command)
Checks whether the given command is supported in the current context.
static void updateState(CSSStyleDeclarationImpl *desiredStyle, CSSStyleDeclarationImpl *computedStyle, bool &atStart, Editor::TriState &state)
This is the BrowserExtension for a KHTMLPart document.
DOM::CSSStyleDeclarationImpl * typingStyle() const
Returns the typing style for the document.
void paste()
paste into current selection from clipboard
DOM::DOMString selectionStartStylePropertyValue(int stylePropertyID) const
?
void clearTypingStyle()
Clears the typing style for the document.
DOM::Selection startingSelection() const
void setTypingStyle(DOM::CSSStyleDeclarationImpl *)
Sets the typing style for the document.
bool canRedo() const
returns whether any actions can be redone