• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KHTML

jsediting.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  * 1. Redistributions of source code must retain the above copyright
00008  *    notice, this list of conditions and the following disclaimer.
00009  * 2. Redistributions in binary form must reproduce the above copyright
00010  *    notice, this list of conditions and the following disclaimer in the
00011  *    documentation and/or other materials provided with the distribution.
00012  *
00013  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
00014  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00015  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00016  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
00017  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00018  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00019  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00020  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00021  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00022  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00023  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00024  */
00025 
00026 #include "jsediting.h"
00027 #include "htmlediting.h"
00028 #include "editor.h"
00029 
00030 #include "css/cssproperties.h"
00031 #include "css/css_valueimpl.h"
00032 #include "xml/dom_selection.h"
00033 #include "xml/dom_docimpl.h"
00034 #include "dom/dom_string.h"
00035 
00036 #include "misc/khtml_partaccessor.h"
00037 
00038 #include <QHash>
00039 #include <QString>
00040 
00041 using khtml::TypingCommand;
00042 // 
00043 #define KPAC khtml::KHTMLPartAccessor
00044 
00045 namespace DOM {
00046 
00047 class DocumentImpl;
00048 
00049 struct CommandImp {
00050     bool (*execFn)(KHTMLPart *part, bool userInterface, const DOMString &value);
00051     bool (*enabledFn)(KHTMLPart *part);
00052     Editor::TriState (*stateFn)(KHTMLPart *part);
00053     DOMString (*valueFn)(KHTMLPart *part);
00054 };
00055 
00056 typedef QHash<QString,const CommandImp*> CommandDict;
00057 static CommandDict createCommandDictionary();
00058 
00059 bool JSEditor::execCommand(const CommandImp *cmd, bool userInterface, const DOMString &value)
00060 {
00061     if (!cmd || !cmd->enabledFn)
00062         return false;
00063     KHTMLPart *part = m_doc->part();
00064     if (!part)
00065         return false;
00066     m_doc->updateLayout();
00067     return cmd->enabledFn(part) && cmd->execFn(part, userInterface, value);
00068 }
00069 
00070 bool JSEditor::queryCommandEnabled(const CommandImp *cmd)
00071 {
00072     if (!cmd || !cmd->enabledFn)
00073         return false;
00074     KHTMLPart *part = m_doc->part();
00075     if (!part)
00076         return false;
00077     m_doc->updateLayout();
00078     return cmd->enabledFn(part);
00079 }
00080 
00081 bool JSEditor::queryCommandIndeterm(const CommandImp *cmd)
00082 {
00083     if (!cmd || !cmd->enabledFn)
00084         return false;
00085     KHTMLPart *part = m_doc->part();
00086     if (!part)
00087         return false;
00088     m_doc->updateLayout();
00089     return cmd->stateFn(part) == Editor::MixedTriState;
00090 }
00091 
00092 bool JSEditor::queryCommandState(const CommandImp *cmd)
00093 {
00094     if (!cmd || !cmd->enabledFn)
00095         return false;
00096     KHTMLPart *part = m_doc->part();
00097     if (!part)
00098         return false;
00099     m_doc->updateLayout();
00100     return cmd->stateFn(part) != Editor::FalseTriState;
00101 }
00102 
00103 bool JSEditor::queryCommandSupported(const CommandImp *cmd)
00104 {
00105     return cmd != 0;
00106 }
00107 
00108 DOMString JSEditor::queryCommandValue(const CommandImp *cmd)
00109 {
00110     if (!cmd || !cmd->enabledFn)
00111         return DOMString();
00112     KHTMLPart *part = m_doc->part();
00113     if (!part)
00114         return DOMString();
00115     m_doc->updateLayout();
00116     return cmd->valueFn(part);
00117 }
00118 
00119 // =============================================================================================
00120 
00121 // Private stuff
00122 
00123 static bool execStyleChange(KHTMLPart *part, int propertyID, const DOMString &propertyValue)
00124 {
00125     CSSStyleDeclarationImpl *style = new CSSStyleDeclarationImpl(0);
00126     style->setProperty(propertyID, propertyValue);
00127     style->ref();
00128     part->editor()->applyStyle(style);
00129     style->deref();
00130     return true;
00131 }
00132 
00133 static bool execStyleChange(KHTMLPart *part, int propertyID, const char *propertyValue)
00134 {
00135     return execStyleChange(part, propertyID, DOMString(propertyValue));
00136 }
00137 
00138 static Editor::TriState stateStyle(KHTMLPart *part, int propertyID, const char *desiredValue)
00139 {
00140     CSSStyleDeclarationImpl *style = new CSSStyleDeclarationImpl(0);
00141     style->setProperty(propertyID, desiredValue);
00142     style->ref();
00143     Editor::TriState state = part->editor()->selectionHasStyle(style);
00144     style->deref();
00145     return state;
00146 }
00147 
00148 static bool selectionStartHasStyle(KHTMLPart *part, int propertyID, const char *desiredValue)
00149 {
00150     CSSStyleDeclarationImpl *style = new CSSStyleDeclarationImpl(0);
00151     style->setProperty(propertyID, desiredValue);
00152     style->ref();
00153     bool hasStyle = part->editor()->selectionStartHasStyle(style);
00154     style->deref();
00155     return hasStyle;
00156 }
00157 
00158 static DOMString valueStyle(KHTMLPart *part, int propertyID)
00159 {
00160     return part->editor()->selectionStartStylePropertyValue(propertyID);
00161 }
00162 
00163 // =============================================================================================
00164 //
00165 // execCommand implementations
00166 //
00167 
00168 static bool execBackColor(KHTMLPart *part, bool /*userInterface*/, const DOMString &value)
00169 {
00170     return execStyleChange(part, CSS_PROP_BACKGROUND_COLOR, value);
00171 }
00172 
00173 static bool execBold(KHTMLPart *part, bool /*userInterface*/, const DOMString &/*value*/)
00174 {
00175     bool isBold = selectionStartHasStyle(part, CSS_PROP_FONT_WEIGHT, "bold");
00176     return execStyleChange(part, CSS_PROP_FONT_WEIGHT, isBold ? "normal" : "bold");
00177 }
00178 
00179 static bool execCopy(KHTMLPart *part, bool /*userInterface*/, const DOMString &/*value*/)
00180 {
00181     part->editor()->copy();
00182     return true;
00183 }
00184 
00185 static bool execCut(KHTMLPart *part, bool /*userInterface*/, const DOMString &/*value*/)
00186 {
00187     part->editor()->cut();
00188     return true;
00189 }
00190 
00191 static bool execDelete(KHTMLPart *part, bool /*userInterface*/, const DOMString &/*value*/)
00192 {
00193     TypingCommand::deleteKeyPressed(KPAC::xmlDocImpl(part));
00194     return true;
00195 }
00196 
00197 static bool execFontName(KHTMLPart *part, bool /*userInterface*/, const DOMString &value)
00198 {
00199     return execStyleChange(part, CSS_PROP_FONT_FAMILY, value);
00200 }
00201 
00202 static bool execFontSize(KHTMLPart *part, bool /*userInterface*/, const DOMString &value)
00203 {
00204     return execStyleChange(part, CSS_PROP_FONT_SIZE, value);
00205 }
00206 
00207 static bool execForeColor(KHTMLPart *part, bool /*userInterface*/, const DOMString &value)
00208 {
00209     return execStyleChange(part, CSS_PROP_COLOR, value);
00210 }
00211 
00212 static bool execIndent(KHTMLPart * /*part*/, bool /*userInterface*/, const DOMString &/*value*/)
00213 {
00214     // FIXME: Implement.
00215     return false;
00216 }
00217 
00218 static bool execInsertNewline(KHTMLPart *part, bool /*userInterface*/, const DOMString &/*value*/)
00219 {
00220     TypingCommand::insertNewline(KPAC::xmlDocImpl(part));
00221     return true;
00222 }
00223 
00224 static bool execInsertParagraph(KHTMLPart * /*part*/, bool /*userInterface*/, const DOMString &/*value*/)
00225 {
00226     // FIXME: Implement.
00227     return false;
00228 }
00229 
00230 static bool execInsertText(KHTMLPart *part, bool /*userInterface*/, const DOMString &value)
00231 {
00232     TypingCommand::insertText(KPAC::xmlDocImpl(part), value);
00233     return true;
00234 }
00235 
00236 static bool execItalic(KHTMLPart *part, bool /*userInterface*/, const DOMString &/*value*/)
00237 {
00238     bool isItalic = selectionStartHasStyle(part, CSS_PROP_FONT_STYLE, "italic");
00239     return execStyleChange(part, CSS_PROP_FONT_STYLE, isItalic ? "normal" : "italic");
00240 }
00241 
00242 static bool execJustifyCenter(KHTMLPart *part, bool /*userInterface*/, const DOMString &/*value*/)
00243 {
00244     return execStyleChange(part, CSS_PROP_TEXT_ALIGN, "center");
00245 }
00246 
00247 static bool execJustifyFull(KHTMLPart *part, bool /*userInterface*/, const DOMString &/*value*/)
00248 {
00249     return execStyleChange(part, CSS_PROP_TEXT_ALIGN, "justify");
00250 }
00251 
00252 static bool execJustifyLeft(KHTMLPart *part, bool /*userInterface*/, const DOMString &/*value*/)
00253 {
00254     return execStyleChange(part, CSS_PROP_TEXT_ALIGN, "left");
00255 }
00256 
00257 static bool execJustifyRight(KHTMLPart *part, bool /*userInterface*/, const DOMString &/*value*/)
00258 {
00259     return execStyleChange(part, CSS_PROP_TEXT_ALIGN, "right");
00260 }
00261 
00262 static bool execOutdent(KHTMLPart * /*part*/, bool /*userInterface*/, const DOMString &/*value*/)
00263 {
00264     // FIXME: Implement.
00265     return false;
00266 }
00267 
00268 #ifndef NO_SUPPORT_PASTE
00269 
00270 static bool execPaste(KHTMLPart *part, bool /*userInterface*/, const DOMString &/*value*/)
00271 {
00272     part->editor()->paste();
00273     return true;
00274 }
00275 
00276 #endif
00277 
00278 static bool execPrint(KHTMLPart *part, bool /*userInterface*/, const DOMString &/*value*/)
00279 {
00280     part->editor()->print();
00281     return true;
00282 }
00283 
00284 static bool execRedo(KHTMLPart *part, bool /*userInterface*/, const DOMString &/*value*/)
00285 {
00286     part->editor()->redo();
00287     return true;
00288 }
00289 
00290 static bool execSelectAll(KHTMLPart *part, bool /*userInterface*/, const DOMString &/*value*/)
00291 {
00292     part->selectAll();
00293     return true;
00294 }
00295 
00296 static bool execSubscript(KHTMLPart *part, bool /*userInterface*/, const DOMString &/*value*/)
00297 {
00298     return execStyleChange(part, CSS_PROP_VERTICAL_ALIGN, "sub");
00299 }
00300 
00301 static bool execSuperscript(KHTMLPart *part, bool /*userInterface*/, const DOMString &/*value*/)
00302 {
00303     return execStyleChange(part, CSS_PROP_VERTICAL_ALIGN, "super");
00304 }
00305 
00306 static bool execUndo(KHTMLPart *part, bool /*userInterface*/, const DOMString &/*value*/)
00307 {
00308     part->editor()->undo();
00309     return true;
00310 }
00311 
00312 static bool execUnselect(KHTMLPart *part, bool /*userInterface*/, const DOMString &/*value*/)
00313 {
00314     KPAC::clearSelection(part);
00315     return true;
00316 }
00317 
00318 // =============================================================================================
00319 //
00320 // queryCommandEnabled implementations
00321 //
00322 // It's a bit difficult to get a clear notion of the difference between
00323 // "supported" and "enabled" from reading the Microsoft documentation, but
00324 // what little I could glean from that seems to make some sense.
00325 //     Supported = The command is supported by this object.
00326 //     Enabled =   The command is available and enabled.
00327 
00328 static bool enabled(KHTMLPart * /*part*/)
00329 {
00330     return true;
00331 }
00332 
00333 static bool enabledAnySelection(KHTMLPart *part)
00334 {
00335     return KPAC::caret(part).notEmpty();
00336 }
00337 
00338 #ifndef NO_SUPPORT_PASTE
00339 
00340 static bool enabledPaste(KHTMLPart *part)
00341 {
00342     return part->editor()->canPaste();
00343 }
00344 
00345 #endif
00346 
00347 static bool enabledRangeSelection(KHTMLPart *part)
00348 {
00349     return KPAC::caret(part).state() == Selection::RANGE;
00350 }
00351 
00352 static bool enabledRedo(KHTMLPart *part)
00353 {
00354     return part->editor()->canRedo();
00355 }
00356 
00357 static bool enabledUndo(KHTMLPart *part)
00358 {
00359     return part->editor()->canUndo();
00360 }
00361 
00362 // =============================================================================================
00363 //
00364 // queryCommandIndeterm/State implementations
00365 //
00366 // It's a bit difficult to get a clear notion of what these methods are supposed
00367 // to do from reading the Microsoft documentation, but my current guess is this:
00368 //
00369 //     queryCommandState and queryCommandIndeterm work in concert to return
00370 //     the two bits of information that are needed to tell, for instance,
00371 //     if the text of a selection is bold. The answer can be "yes", "no", or
00372 //     "partially".
00373 //
00374 // If this is so, then queryCommandState should return "yes" in the case where
00375 // all the text is bold and "no" for non-bold or partially-bold text.
00376 // Then, queryCommandIndeterm should return "no" in the case where
00377 // all the text is either all bold or not-bold and and "yes" for partially-bold text.
00378 
00379 static Editor::TriState stateNone(KHTMLPart * /*part*/)
00380 {
00381     return Editor::FalseTriState;
00382 }
00383 
00384 static Editor::TriState stateBold(KHTMLPart *part)
00385 {
00386     return stateStyle(part, CSS_PROP_FONT_WEIGHT, "bold");
00387 }
00388 
00389 static Editor::TriState stateItalic(KHTMLPart *part)
00390 {
00391     return stateStyle(part, CSS_PROP_FONT_STYLE, "italic");
00392 }
00393 
00394 static Editor::TriState stateSubscript(KHTMLPart *part)
00395 {
00396     return stateStyle(part, CSS_PROP_VERTICAL_ALIGN, "sub");
00397 }
00398 
00399 static Editor::TriState stateSuperscript(KHTMLPart *part)
00400 {
00401     return stateStyle(part, CSS_PROP_VERTICAL_ALIGN, "super");
00402 }
00403 
00404 // =============================================================================================
00405 //
00406 // queryCommandValue implementations
00407 //
00408 
00409 static DOMString valueNull(KHTMLPart * /*part*/)
00410 {
00411     return DOMString();
00412 }
00413 
00414 static DOMString valueBackColor(KHTMLPart *part)
00415 {
00416     return valueStyle(part, CSS_PROP_BACKGROUND_COLOR);
00417 }
00418 
00419 static DOMString valueFontName(KHTMLPart *part)
00420 {
00421     return valueStyle(part, CSS_PROP_FONT_FAMILY);
00422 }
00423 
00424 static DOMString valueFontSize(KHTMLPart *part)
00425 {
00426     return valueStyle(part, CSS_PROP_FONT_SIZE);
00427 }
00428 
00429 static DOMString valueForeColor(KHTMLPart *part)
00430 {
00431     return valueStyle(part, CSS_PROP_COLOR);
00432 }
00433 
00434 // =============================================================================================
00435 
00436 struct EditorCommandInfo { const char *name; CommandImp imp; };
00437 
00438 // NOTE: strictly keep in sync with EditorCommand in editor_command.h
00439 static const EditorCommandInfo commands[] = {
00440 
00441     { "backColor", { execBackColor, enabled, stateNone, valueBackColor } },
00442     { "bold", { execBold, enabledAnySelection, stateBold, valueNull } },
00443     { "copy", { execCopy, enabledRangeSelection, stateNone, valueNull } },
00444     { "cut", { execCut, enabledRangeSelection, stateNone, valueNull } },
00445     { "delete", { execDelete, enabledAnySelection, stateNone, valueNull } },
00446     { "fontName", { execFontName, enabledAnySelection, stateNone, valueFontName } },
00447     { "fontSize", { execFontSize, enabledAnySelection, stateNone, valueFontSize } },
00448     { "foreColor", { execForeColor, enabledAnySelection, stateNone, valueForeColor } },
00449     { "indent", { execIndent, enabledAnySelection, stateNone, valueNull } },
00450     { "insertNewline", { execInsertNewline, enabledAnySelection, stateNone, valueNull } },
00451     { "insertParagraph", { execInsertParagraph, enabledAnySelection, stateNone, valueNull } },
00452     { "insertText", { execInsertText, enabledAnySelection, stateNone, valueNull } },
00453     { "italic", { execItalic, enabledAnySelection, stateItalic, valueNull } },
00454     { "justifyCenter", { execJustifyCenter, enabledAnySelection, stateNone, valueNull } },
00455     { "justifyFull", { execJustifyFull, enabledAnySelection, stateNone, valueNull } },
00456     { "justifyLeft", { execJustifyLeft, enabledAnySelection, stateNone, valueNull } },
00457     { "justifyNone", { execJustifyLeft, enabledAnySelection, stateNone, valueNull } },
00458     { "justifyRight", { execJustifyRight, enabledAnySelection, stateNone, valueNull } },
00459     { "outdent", { execOutdent, enabledAnySelection, stateNone, valueNull } },
00460 #ifndef NO_SUPPORT_PASTE
00461     { "paste", { execPaste, enabledPaste, stateNone, valueNull } },
00462 #else
00463     { 0, { 0, 0, 0, 0 } },
00464 #endif
00465     { "print", { execPrint, enabled, stateNone, valueNull } },
00466     { "redo", { execRedo, enabledRedo, stateNone, valueNull } },
00467     { "selectAll", { execSelectAll, enabled, stateNone, valueNull } },
00468     { "subscript", { execSubscript, enabledAnySelection, stateSubscript, valueNull } },
00469     { "superscript", { execSuperscript, enabledAnySelection, stateSuperscript, valueNull } },
00470     { "undo", { execUndo, enabledUndo, stateNone, valueNull } },
00471     { "unselect", { execUnselect, enabledAnySelection, stateNone, valueNull } }
00472 
00473     //
00474     // The "unsupported" commands are listed here since they appear in the Microsoft
00475     // documentation used as the basis for the list.
00476     //
00477 
00478     // 2d-position (not supported)
00479     // absolutePosition (not supported)
00480     // blockDirLTR (not supported)
00481     // blockDirRTL (not supported)
00482     // browseMode (not supported)
00483     // clearAuthenticationCache (not supported)
00484     // createBookmark (not supported)
00485     // createLink (not supported)
00486     // dirLTR (not supported)
00487     // dirRTL (not supported)
00488     // editMode (not supported)
00489     // formatBlock (not supported)
00490     // inlineDirLTR (not supported)
00491     // inlineDirRTL (not supported)
00492     // insertButton (not supported)
00493     // insertFieldSet (not supported)
00494     // insertHorizontalRule (not supported)
00495     // insertIFrame (not supported)
00496     // insertImage (not supported)
00497     // insertInputButton (not supported)
00498     // insertInputCheckbox (not supported)
00499     // insertInputFileUpload (not supported)
00500     // insertInputHidden (not supported)
00501     // insertInputImage (not supported)
00502     // insertInputPassword (not supported)
00503     // insertInputRadio (not supported)
00504     // insertInputReset (not supported)
00505     // insertInputSubmit (not supported)
00506     // insertInputText (not supported)
00507     // insertMarquee (not supported)
00508     // insertOrderedList (not supported)
00509     // insertSelectDropDown (not supported)
00510     // insertSelectListBox (not supported)
00511     // insertTextArea (not supported)
00512     // insertUnorderedList (not supported)
00513     // liveResize (not supported)
00514     // multipleSelection (not supported)
00515     // open (not supported)
00516     // overwrite (not supported)
00517     // playImage (not supported)
00518     // refresh (not supported)
00519     // removeFormat (not supported)
00520     // removeParaFormat (not supported)
00521     // saveAs (not supported)
00522     // sizeToControl (not supported)
00523     // sizeToControlHeight (not supported)
00524     // sizeToControlWidth (not supported)
00525     // stop (not supported)
00526     // stopimage (not supported)
00527     // strikethrough (not supported)
00528     // unbookmark (not supported)
00529     // underline (not supported)
00530     // unlink (not supported)
00531 };
00532 
00533 static CommandDict createCommandDictionary()
00534 {
00535     const int numCommands = sizeof(commands) / sizeof(commands[0]);
00536     CommandDict commandDictionary; // case-insensitive dictionary
00537     for (int i = 0; i < numCommands; ++i) {
00538         if (commands[i].name)
00539             commandDictionary.insert(QString(commands[i].name).toLower(), &commands[i].imp);
00540     }
00541     return commandDictionary;
00542 }
00543 
00544 const CommandImp *JSEditor::commandImp(const DOMString &command)
00545 {
00546     static CommandDict commandDictionary = createCommandDictionary();
00547     CommandDict::const_iterator it = commandDictionary.find(command.string().toLower());
00548     return commandDictionary.value( command.string().toLower() );
00549 }
00550 
00551 const CommandImp *JSEditor::commandImp(int command)
00552 {
00553     if (command < 0 || command > int(sizeof commands / sizeof commands[0]))
00554         return 0;
00555     return &commands[command].imp;
00556 }
00557 
00558 
00559 
00560 } // namespace DOM
00561 
00562 #undef KPAC

KHTML

Skip menu "KHTML"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal