Back to index

lightning-sunbird  0.9+nobinonly
nsComposerCommands.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Ryan Cassin <rcassin@supernova.org>
00024  *   Daniel Glazman <glazman@netscape.com>
00025  *   Charles Manske <cmanske@netscape.com>
00026  *   Kathleen Brade <brade@netscape.com>
00027  *
00028  * Alternatively, the contents of this file may be used under the terms of
00029  * either of the GNU General Public License Version 2 or later (the "GPL"),
00030  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00031  * in which case the provisions of the GPL or the LGPL are applicable instead
00032  * of those above. If you wish to allow use of your version of this file only
00033  * under the terms of either the GPL or the LGPL, and not to allow others to
00034  * use your version of this file under the terms of the MPL, indicate your
00035  * decision by deleting the provisions above and replace them with the notice
00036  * and other provisions required by the GPL or the LGPL. If you do not delete
00037  * the provisions above, a recipient may use your version of this file under
00038  * the terms of any one of the MPL, the GPL or the LGPL.
00039  *
00040  * ***** END LICENSE BLOCK ***** */
00041 
00042 
00043 #include "nsIEditor.h"
00044 #include "nsIHTMLEditor.h"
00045 #include "nsIHTMLAbsPosEditor.h"
00046 
00047 #include "nsIDOMElement.h"
00048 #include "nsIAtom.h"
00049 
00050 #include "nsIClipboard.h"
00051 
00052 #include "nsCOMPtr.h"
00053 
00054 #include "nsComposerCommands.h"
00055 #include "nsReadableUtils.h"
00056 #include "nsUnicharUtils.h"
00057 #include "nsICommandParams.h"
00058 #include "nsComponentManagerUtils.h"
00059 #include "nsCRT.h"
00060 
00061 //prototype
00062 nsresult GetListState(nsIEditor *aEditor, PRBool *aMixed, PRUnichar **tagStr);
00063 nsresult RemoveOneProperty(nsIHTMLEditor *aEditor,const nsString& aProp,
00064                            const nsString &aAttr);
00065 nsresult RemoveTextProperty(nsIEditor *aEditor, const PRUnichar *prop,
00066                             const PRUnichar *attr);
00067 nsresult SetTextProperty(nsIEditor *aEditor, const PRUnichar *prop,
00068                          const PRUnichar *attr, const PRUnichar *value);
00069 
00070 
00071 //defines
00072 #define STATE_ENABLED  "state_enabled"
00073 #define STATE_ALL "state_all"
00074 #define STATE_ANY "state_any"
00075 #define STATE_MIXED "state_mixed"
00076 #define STATE_BEGIN "state_begin"
00077 #define STATE_END "state_end"
00078 #define STATE_ATTRIBUTE "state_attribute"
00079 #define STATE_DATA "state_data"
00080 
00081 
00082 nsBaseComposerCommand::nsBaseComposerCommand()
00083 {
00084 }
00085 
00086 NS_IMPL_ISUPPORTS1(nsBaseComposerCommand, nsIControllerCommand)
00087 
00088 
00089 #ifdef XP_MAC
00090 #pragma mark -
00091 #endif
00092 
00093 
00094 nsBaseStateUpdatingCommand::nsBaseStateUpdatingCommand(const char* aTagName)
00095 : nsBaseComposerCommand()
00096 , mTagName(aTagName)
00097 {
00098 }
00099 
00100 nsBaseStateUpdatingCommand::~nsBaseStateUpdatingCommand()
00101 {
00102 }
00103 
00104 NS_IMPL_ISUPPORTS_INHERITED0(nsBaseStateUpdatingCommand, nsBaseComposerCommand)
00105 
00106 NS_IMETHODIMP
00107 nsBaseStateUpdatingCommand::IsCommandEnabled(const char *aCommandName,
00108                                              nsISupports *refCon,
00109                                              PRBool *outCmdEnabled)
00110 {
00111   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
00112   *outCmdEnabled = editor ? PR_TRUE : PR_FALSE;
00113   return NS_OK;
00114 }
00115 
00116 
00117 NS_IMETHODIMP
00118 nsBaseStateUpdatingCommand::DoCommand(const char *aCommandName,
00119                                       nsISupports *refCon)
00120 {
00121   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
00122   if (!editor) return NS_ERROR_NOT_INITIALIZED;
00123 
00124   return ToggleState(editor, mTagName);
00125 }
00126 
00127 NS_IMETHODIMP
00128 nsBaseStateUpdatingCommand::DoCommandParams(const char *aCommandName,
00129                                             nsICommandParams *aParams,
00130                                             nsISupports *refCon)
00131 {
00132   return DoCommand(aCommandName, refCon);
00133 }
00134 
00135 NS_IMETHODIMP
00136 nsBaseStateUpdatingCommand::GetCommandStateParams(const char *aCommandName, 
00137                                                   nsICommandParams *aParams,
00138                                                   nsISupports *refCon)
00139 {
00140   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
00141   if (editor)
00142     return GetCurrentState(editor, mTagName, aParams);
00143 
00144   return NS_OK;
00145 }
00146 
00147 NS_IMETHODIMP
00148 nsPasteNoFormattingCommand::IsCommandEnabled(const char * aCommandName, 
00149                                              nsISupports *refCon, 
00150                                              PRBool *outCmdEnabled)
00151 {
00152   NS_ENSURE_ARG_POINTER(outCmdEnabled);
00153   *outCmdEnabled = PR_FALSE;
00154 
00155   // This command is only implemented by nsIHTMLEditor, since
00156   //  pasting in a plaintext editor automatically only supplies 
00157   //  "unformatted" text
00158   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(refCon);
00159   if (!htmlEditor)
00160     return NS_ERROR_NOT_IMPLEMENTED;
00161 
00162   nsCOMPtr<nsIEditor> editor = do_QueryInterface(htmlEditor);
00163   if (!editor)
00164     return NS_ERROR_INVALID_ARG;
00165 
00166   return editor->CanPaste(nsIClipboard::kGlobalClipboard, outCmdEnabled);
00167 }
00168 
00169 
00170 NS_IMETHODIMP
00171 nsPasteNoFormattingCommand::DoCommand(const char *aCommandName,
00172                                       nsISupports *refCon)
00173 {
00174   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(refCon);
00175   if (!htmlEditor)
00176     return NS_ERROR_NOT_IMPLEMENTED;
00177 
00178   return htmlEditor->PasteNoFormatting(nsIClipboard::kGlobalClipboard);
00179 }
00180 
00181 NS_IMETHODIMP
00182 nsPasteNoFormattingCommand::DoCommandParams(const char *aCommandName,
00183                                             nsICommandParams *aParams, 
00184                                             nsISupports *refCon)
00185 {
00186   return DoCommand(aCommandName, refCon);
00187 }
00188 
00189 NS_IMETHODIMP
00190 nsPasteNoFormattingCommand::GetCommandStateParams(const char *aCommandName,
00191                                                   nsICommandParams *aParams,
00192                                                   nsISupports *refCon)
00193 {
00194   NS_ENSURE_ARG_POINTER(aParams);
00195 
00196   PRBool enabled = PR_FALSE;
00197   nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled);
00198   NS_ENSURE_SUCCESS(rv, rv);
00199 
00200   return aParams->SetBooleanValue(STATE_ENABLED, enabled);
00201 }
00202 
00203 #ifdef XP_MAC
00204 #pragma mark -
00205 #endif
00206 
00207 nsStyleUpdatingCommand::nsStyleUpdatingCommand(const char* aTagName)
00208 : nsBaseStateUpdatingCommand(aTagName)
00209 {
00210 }
00211 
00212 nsresult
00213 nsStyleUpdatingCommand::GetCurrentState(nsIEditor *aEditor, 
00214                                         const char* aTagName,
00215                                         nsICommandParams *aParams)
00216 {
00217   NS_ASSERTION(aEditor, "Need editor here");
00218   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
00219   if (!htmlEditor) return NS_ERROR_NOT_INITIALIZED;
00220   
00221   nsresult rv = NS_OK;
00222 
00223   PRBool firstOfSelectionHasProp = PR_FALSE;
00224   PRBool anyOfSelectionHasProp = PR_FALSE;
00225   PRBool allOfSelectionHasProp = PR_FALSE;
00226 
00227   nsCOMPtr<nsIAtom> styleAtom = do_GetAtom(aTagName);
00228   rv = htmlEditor->GetInlineProperty(styleAtom, EmptyString(), 
00229                                      EmptyString(), 
00230                                      &firstOfSelectionHasProp, 
00231                                      &anyOfSelectionHasProp, 
00232                                      &allOfSelectionHasProp);
00233 
00234   aParams->SetBooleanValue(STATE_ENABLED, NS_SUCCEEDED(rv));
00235   aParams->SetBooleanValue(STATE_ALL, allOfSelectionHasProp);
00236   aParams->SetBooleanValue(STATE_ANY, anyOfSelectionHasProp);
00237   aParams->SetBooleanValue(STATE_MIXED, anyOfSelectionHasProp
00238            && !allOfSelectionHasProp);
00239   aParams->SetBooleanValue(STATE_BEGIN, firstOfSelectionHasProp);
00240   aParams->SetBooleanValue(STATE_END, allOfSelectionHasProp);//not completely accurate
00241   return NS_OK;
00242 }
00243 
00244 nsresult
00245 nsStyleUpdatingCommand::ToggleState(nsIEditor *aEditor, const char* aTagName)
00246 {
00247   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
00248   if (!htmlEditor)
00249     return NS_ERROR_NO_INTERFACE;
00250 
00251   //create some params now...
00252   nsresult rv;
00253   nsCOMPtr<nsICommandParams> params =
00254       do_CreateInstance(NS_COMMAND_PARAMS_CONTRACTID,&rv);
00255   if (NS_FAILED(rv) || !params)
00256     return rv;
00257 
00258   // tags "href" and "name" are special cases in the core editor 
00259   // they are used to remove named anchor/link and shouldn't be used for insertion
00260   nsAutoString tagName; tagName.AssignWithConversion(aTagName);
00261   PRBool doTagRemoval;
00262   if (tagName.EqualsLiteral("href") ||
00263       tagName.EqualsLiteral("name"))
00264     doTagRemoval = PR_TRUE;
00265   else
00266   {
00267     // check current selection; set doTagRemoval if formatting should be removed
00268     rv = GetCurrentState(aEditor, aTagName, params);
00269     if (NS_FAILED(rv)) 
00270       return rv;
00271     rv = params->GetBooleanValue(STATE_ALL, &doTagRemoval);
00272     if (NS_FAILED(rv)) 
00273       return rv;
00274   }
00275 
00276   if (doTagRemoval)
00277     rv = RemoveTextProperty(aEditor, tagName.get(), nsnull);
00278   else
00279   {
00280     // Superscript and Subscript styles are mutually exclusive
00281     nsAutoString removeName; 
00282     aEditor->BeginTransaction();
00283 
00284     if (tagName.EqualsLiteral("sub"))
00285     {
00286       removeName.AssignLiteral("sup");
00287       rv = RemoveTextProperty(aEditor,tagName.get(), nsnull);
00288     } 
00289     else if (tagName.EqualsLiteral("sup"))
00290     {
00291       removeName.AssignLiteral("sub");
00292       rv = RemoveTextProperty(aEditor, tagName.get(), nsnull);
00293     }
00294     if (NS_SUCCEEDED(rv))
00295       rv = SetTextProperty(aEditor,tagName.get(), nsnull, nsnull);
00296 
00297     aEditor->EndTransaction();
00298   }
00299 
00300   return rv;
00301 }
00302 #ifdef XP_MAC
00303 #pragma mark -
00304 #endif
00305 
00306 nsListCommand::nsListCommand(const char* aTagName)
00307 : nsBaseStateUpdatingCommand(aTagName)
00308 {
00309 }
00310 
00311 nsresult
00312 nsListCommand::GetCurrentState(nsIEditor *aEditor, const char* aTagName,
00313                                nsICommandParams *aParams)
00314 {
00315   NS_ASSERTION(aEditor, "Need editor here");
00316 
00317   PRBool bMixed;
00318   PRUnichar *tagStr;
00319   nsresult rv = GetListState(aEditor,&bMixed, &tagStr);
00320   if (NS_FAILED(rv)) return rv;
00321 
00322   // Need to use mTagName????
00323   PRBool inList = (0 == nsCRT::strcmp(tagStr,
00324                    NS_ConvertASCIItoUCS2(mTagName).get()));
00325   aParams->SetBooleanValue(STATE_ALL, !bMixed && inList);
00326   aParams->SetBooleanValue(STATE_MIXED, bMixed);
00327   aParams->SetBooleanValue(STATE_ENABLED, PR_TRUE);
00328   if (tagStr) NS_Free(tagStr);
00329   return NS_OK;
00330 }
00331 
00332 nsresult
00333 nsListCommand::ToggleState(nsIEditor *aEditor, const char* aTagName)
00334 {
00335   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(aEditor);
00336   if (!editor)
00337     return NS_NOINTERFACE;
00338   PRBool inList;
00339   // Need to use mTagName????
00340   nsresult rv;
00341   nsCOMPtr<nsICommandParams> params =
00342       do_CreateInstance(NS_COMMAND_PARAMS_CONTRACTID,&rv);
00343   if (NS_FAILED(rv) || !params)
00344     return rv;
00345 
00346   rv = GetCurrentState(aEditor, mTagName, params);
00347   rv = params->GetBooleanValue(STATE_ALL,&inList);
00348   if (NS_FAILED(rv)) 
00349     return rv;
00350 
00351   nsAutoString listType; listType.AssignWithConversion(mTagName);
00352   if (inList)
00353     rv = editor->RemoveList(listType);    
00354   else
00355   {
00356     rv = editor->MakeOrChangeList(listType, PR_FALSE, EmptyString());
00357   }
00358   
00359   return rv;
00360 }
00361 
00362 #ifdef XP_MAC
00363 #pragma mark -
00364 #endif
00365 
00366 nsListItemCommand::nsListItemCommand(const char* aTagName)
00367 : nsBaseStateUpdatingCommand(aTagName)
00368 {
00369 }
00370 
00371 nsresult
00372 nsListItemCommand::GetCurrentState(nsIEditor *aEditor, const char* aTagName,
00373                                    nsICommandParams *aParams)
00374 {
00375   NS_ASSERTION(aEditor, "Need editor here");
00376   // 39584
00377   nsCOMPtr<nsIHTMLEditor>  htmlEditor = do_QueryInterface(aEditor);
00378   if (!htmlEditor)
00379     return NS_NOINTERFACE;
00380 
00381   PRBool bMixed, bLI, bDT, bDD;
00382   nsresult rv = htmlEditor->GetListItemState(&bMixed, &bLI, &bDT, &bDD);
00383   if (NS_FAILED(rv)) return rv;
00384 
00385   PRBool inList = PR_FALSE;
00386   if (!bMixed)
00387   {
00388     if (bLI) inList = (0 == nsCRT::strcmp(mTagName, "li"));
00389     else if (bDT) inList = (0 == nsCRT::strcmp(mTagName, "dt"));
00390     else if (bDD) inList = (0 == nsCRT::strcmp(mTagName, "dd"));
00391   }
00392 
00393   aParams->SetBooleanValue(STATE_ALL, !bMixed && inList);
00394   aParams->SetBooleanValue(STATE_MIXED, bMixed);
00395 
00396   return NS_OK;
00397 }
00398 
00399 nsresult
00400 nsListItemCommand::ToggleState(nsIEditor *aEditor, const char* aTagName)
00401 {
00402   NS_ASSERTION(aEditor, "Need editor here");
00403   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
00404   if (!htmlEditor) return NS_ERROR_NOT_INITIALIZED;
00405 
00406   PRBool inList;
00407   // Need to use mTagName????
00408   nsresult rv;
00409   nsCOMPtr<nsICommandParams> params =
00410       do_CreateInstance(NS_COMMAND_PARAMS_CONTRACTID,&rv);
00411   if (NS_FAILED(rv) || !params)
00412     return rv;
00413   rv = GetCurrentState(aEditor, mTagName, params);
00414   rv = params->GetBooleanValue(STATE_ALL,&inList);
00415   if (NS_FAILED(rv)) 
00416     return rv;
00417   if (NS_FAILED(rv)) return rv;
00418   
00419   if (inList)
00420   {
00421     // To remove a list, first get what kind of list we're in
00422     PRBool bMixed;
00423     PRUnichar *tagStr;
00424     rv = GetListState(aEditor,&bMixed, &tagStr);
00425     if (NS_FAILED(rv)) return rv; 
00426     if (tagStr)
00427     {
00428       if (!bMixed)
00429       {
00430         rv = htmlEditor->RemoveList(nsDependentString(tagStr));    
00431       }
00432       NS_Free(tagStr);
00433     }
00434   }
00435   else
00436   {
00437     nsAutoString itemType; itemType.AssignWithConversion(mTagName);
00438     // Set to the requested paragraph type
00439     //XXX Note: This actually doesn't work for "LI",
00440     //    but we currently don't use this for non DL lists anyway.
00441     // Problem: won't this replace any current block paragraph style?
00442     rv = htmlEditor->SetParagraphFormat(itemType);
00443   }
00444     
00445   return rv;
00446 }
00447 
00448 #ifdef XP_MAC
00449 #pragma mark -
00450 #endif
00451 
00452 NS_IMETHODIMP
00453 nsRemoveListCommand::IsCommandEnabled(const char * aCommandName,
00454                                       nsISupports *refCon,
00455                                       PRBool *outCmdEnabled)
00456 {
00457   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
00458   if (editor)
00459   {
00460     // It is enabled if we are in any list type
00461     PRBool bMixed;
00462     PRUnichar *tagStr;
00463     nsresult rv = GetListState(editor, &bMixed, &tagStr);
00464     if (NS_FAILED(rv)) return rv;
00465 
00466     *outCmdEnabled = bMixed ? PR_TRUE : (tagStr && *tagStr);
00467     
00468     if (tagStr) NS_Free(tagStr);
00469   }
00470   else
00471     *outCmdEnabled = PR_FALSE;
00472 
00473   return NS_OK;
00474 }
00475 
00476 
00477 NS_IMETHODIMP
00478 nsRemoveListCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
00479 {
00480   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
00481 
00482   nsresult rv = NS_OK;
00483   if (editor)
00484   {
00485     // This removes any list type
00486     rv = editor->RemoveList(EmptyString());
00487   }
00488 
00489   return rv;  
00490 }
00491 
00492 NS_IMETHODIMP
00493 nsRemoveListCommand::DoCommandParams(const char *aCommandName, 
00494                                      nsICommandParams *aParams,
00495                                      nsISupports *refCon)
00496 {
00497   return DoCommand(aCommandName, refCon);
00498 }
00499 
00500 NS_IMETHODIMP
00501 nsRemoveListCommand::GetCommandStateParams(const char *aCommandName,
00502                                            nsICommandParams *aParams, 
00503                                            nsISupports *refCon)
00504 {
00505   PRBool outCmdEnabled = PR_FALSE;
00506   IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
00507   return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled);
00508 }
00509 
00510 #ifdef XP_MAC
00511 #pragma mark -
00512 #endif
00513 
00514 NS_IMETHODIMP
00515 nsIndentCommand::IsCommandEnabled(const char * aCommandName,
00516                                   nsISupports *refCon, PRBool *outCmdEnabled)
00517 {
00518   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
00519   *outCmdEnabled = editor ? PR_TRUE : PR_FALSE;
00520   return NS_OK;
00521 }
00522 
00523 
00524 NS_IMETHODIMP
00525 nsIndentCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
00526 {
00527   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
00528 
00529   nsresult rv = NS_OK;
00530   if (editor)
00531   {
00532     rv = editor->Indent(NS_LITERAL_STRING("indent"));
00533   }
00534   
00535   return rv;  
00536 }
00537 
00538 NS_IMETHODIMP
00539 nsIndentCommand::DoCommandParams(const char *aCommandName,
00540                                  nsICommandParams *aParams,
00541                                  nsISupports *refCon)
00542 {
00543   return DoCommand(aCommandName, refCon);  
00544 }
00545 
00546 NS_IMETHODIMP
00547 nsIndentCommand::GetCommandStateParams(const char *aCommandName,
00548                                        nsICommandParams *aParams,
00549                                        nsISupports *refCon)
00550 {
00551   PRBool outCmdEnabled = PR_FALSE;
00552   IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
00553   return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled);
00554 }
00555 
00556 
00557 //OUTDENT
00558 
00559 NS_IMETHODIMP
00560 nsOutdentCommand::IsCommandEnabled(const char * aCommandName,
00561                                    nsISupports *refCon,
00562                                    PRBool *outCmdEnabled)
00563 {
00564   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(refCon);
00565   if (htmlEditor)
00566   {
00567     PRBool canIndent, canOutdent;
00568     htmlEditor->GetIndentState(&canIndent, &canOutdent);
00569     *outCmdEnabled = canOutdent;
00570   }
00571   else
00572     *outCmdEnabled = PR_FALSE;
00573 
00574   return NS_OK;
00575 }
00576 
00577 
00578 NS_IMETHODIMP
00579 nsOutdentCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
00580 {
00581   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(refCon);
00582   if (htmlEditor)
00583     return htmlEditor->Indent(NS_LITERAL_STRING("outdent"));
00584   
00585   return NS_OK;  
00586 }
00587 
00588 NS_IMETHODIMP
00589 nsOutdentCommand::DoCommandParams(const char *aCommandName,
00590                                   nsICommandParams *aParams, 
00591                                   nsISupports *refCon)
00592 {
00593   return DoCommand(aCommandName, refCon);  
00594 }
00595 
00596 NS_IMETHODIMP
00597 nsOutdentCommand::GetCommandStateParams(const char *aCommandName,
00598                                         nsICommandParams *aParams,
00599                                         nsISupports *refCon)
00600 {
00601   PRBool outCmdEnabled = PR_FALSE;
00602   IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
00603   return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled);
00604 }
00605 
00606 #ifdef XP_MAC
00607 #pragma mark -
00608 #endif
00609 
00610 
00611 nsMultiStateCommand::nsMultiStateCommand()
00612 : nsBaseComposerCommand()
00613 {
00614 }
00615 
00616 nsMultiStateCommand::~nsMultiStateCommand()
00617 {
00618 }
00619 
00620 NS_IMPL_ISUPPORTS_INHERITED0(nsMultiStateCommand, nsBaseComposerCommand)
00621 
00622 NS_IMETHODIMP
00623 nsMultiStateCommand::IsCommandEnabled(const char * aCommandName,
00624                                       nsISupports *refCon,
00625                                       PRBool *outCmdEnabled)
00626 {
00627   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
00628   // should be disabled sometimes, like if the current selection is an image
00629   *outCmdEnabled = editor ? PR_TRUE : PR_FALSE;
00630   return NS_OK; 
00631 }
00632 
00633 
00634 NS_IMETHODIMP
00635 nsMultiStateCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
00636 {
00637 #ifdef DEBUG
00638   printf("who is calling nsMultiStateCommand::DoCommand \
00639           (no implementation)? %s\n", aCommandName);
00640 #endif
00641   
00642   return NS_OK;  
00643 }
00644 
00645 NS_IMETHODIMP
00646 nsMultiStateCommand::DoCommandParams(const char *aCommandName,
00647                                      nsICommandParams *aParams,
00648                                      nsISupports *refCon)
00649 {
00650   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
00651 
00652   nsresult rv = NS_OK;
00653   if (editor)
00654   {
00655       nsAutoString tString;
00656 
00657       if (aParams) {
00658         nsXPIDLCString s;
00659         rv = aParams->GetCStringValue(STATE_ATTRIBUTE, getter_Copies(s));
00660         if (NS_SUCCEEDED(rv))
00661           tString.AssignWithConversion(s);
00662         else
00663           rv = aParams->GetStringValue(STATE_ATTRIBUTE, tString);
00664       }
00665 
00666       rv = SetState(editor, tString);
00667   }
00668   
00669   return rv;  
00670 }
00671 
00672 NS_IMETHODIMP
00673 nsMultiStateCommand::GetCommandStateParams(const char *aCommandName,
00674                                            nsICommandParams *aParams,
00675                                            nsISupports *refCon)
00676 {
00677   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
00678   nsresult rv = NS_OK;
00679   if (editor)
00680   {
00681       rv = GetCurrentState(editor, aParams);
00682   }
00683   return rv;
00684 }
00685 
00686 #ifdef XP_MAC
00687 #pragma mark -
00688 #endif
00689 
00690 nsParagraphStateCommand::nsParagraphStateCommand()
00691 : nsMultiStateCommand()
00692 {
00693 }
00694 
00695 nsresult
00696 nsParagraphStateCommand::GetCurrentState(nsIEditor *aEditor,
00697                                          nsICommandParams *aParams)
00698 {
00699   NS_ASSERTION(aEditor, "Need an editor here");
00700   
00701   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
00702   if (!htmlEditor) return NS_ERROR_FAILURE;
00703 
00704   PRBool outMixed;
00705   nsAutoString outStateString;
00706   nsresult rv = htmlEditor->GetParagraphState(&outMixed, outStateString);
00707   if (NS_SUCCEEDED(rv))
00708   {
00709     nsCAutoString tOutStateString;
00710     tOutStateString.AssignWithConversion(outStateString);
00711     aParams->SetBooleanValue(STATE_MIXED,outMixed);
00712     aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
00713   }
00714   return rv;
00715 }
00716 
00717 
00718 nsresult
00719 nsParagraphStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
00720 {
00721   NS_ASSERTION(aEditor, "Need an editor here");
00722   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
00723   if (!htmlEditor) return NS_ERROR_FAILURE;
00724 
00725   return htmlEditor->SetParagraphFormat(newState);
00726 }
00727 
00728 #ifdef XP_MAC
00729 #pragma mark -
00730 #endif
00731 
00732 nsFontFaceStateCommand::nsFontFaceStateCommand()
00733 : nsMultiStateCommand()
00734 {
00735 }
00736 
00737 nsresult
00738 nsFontFaceStateCommand::GetCurrentState(nsIEditor *aEditor,
00739                                         nsICommandParams *aParams)
00740 {
00741   NS_ASSERTION(aEditor, "Need an editor here");
00742   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
00743   if (!htmlEditor) return NS_ERROR_FAILURE;
00744 
00745   nsAutoString outStateString;
00746   PRBool outMixed;
00747   nsresult rv = htmlEditor->GetFontFaceState(&outMixed, outStateString);
00748   if (NS_SUCCEEDED(rv))
00749   {
00750     aParams->SetBooleanValue(STATE_MIXED,outMixed);
00751     aParams->SetCStringValue(STATE_ATTRIBUTE, NS_ConvertUTF16toUTF8(outStateString).get());
00752   }
00753   return rv;
00754 }
00755 
00756 
00757 nsresult
00758 nsFontFaceStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
00759 {
00760   NS_ASSERTION(aEditor, "Need an editor here");
00761   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
00762   if (!htmlEditor) return NS_ERROR_FAILURE;
00763   
00764   nsresult rv;
00765   nsCOMPtr<nsIAtom> ttAtom = do_GetAtom("tt");
00766   nsCOMPtr<nsIAtom> fontAtom = do_GetAtom("font");
00767 
00768   if (newState.EqualsLiteral("tt"))
00769   {
00770     // The old "teletype" attribute  
00771     rv = htmlEditor->SetInlineProperty(ttAtom, EmptyString(), 
00772                                        EmptyString());  
00773     // Clear existing font face
00774     rv = htmlEditor->RemoveInlineProperty(fontAtom, NS_LITERAL_STRING("face"));
00775   }
00776   else
00777   {
00778     // Remove any existing TT nodes
00779     rv = htmlEditor->RemoveInlineProperty(ttAtom, EmptyString());  
00780 
00781     if (newState.IsEmpty() || newState.EqualsLiteral("normal")) {
00782       rv = htmlEditor->RemoveInlineProperty(fontAtom, NS_LITERAL_STRING("face"));
00783     } else {
00784       rv = htmlEditor->SetInlineProperty(fontAtom, NS_LITERAL_STRING("face"),
00785                                          newState);
00786     }
00787   }
00788   
00789   return rv;
00790 }
00791 
00792 #ifdef XP_MAC
00793 #pragma mark -
00794 #endif
00795 
00796 nsFontSizeStateCommand::nsFontSizeStateCommand()
00797   : nsMultiStateCommand()
00798 {
00799 }
00800 
00801 //  nsCAutoString tOutStateString;
00802 //  tOutStateString.AssignWithConversion(outStateString);
00803 nsresult
00804 nsFontSizeStateCommand::GetCurrentState(nsIEditor *aEditor,
00805                                         nsICommandParams *aParams)
00806 {
00807   NS_ASSERTION(aEditor, "Need an editor here");
00808   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
00809   if (!htmlEditor) return NS_ERROR_INVALID_ARG;
00810 
00811   nsAutoString outStateString;
00812   nsCOMPtr<nsIAtom> fontAtom = do_GetAtom("font");
00813   PRBool firstHas, anyHas, allHas;
00814   nsresult rv = htmlEditor->GetInlinePropertyWithAttrValue(fontAtom,
00815                                          NS_LITERAL_STRING("size"),
00816                                          EmptyString(),
00817                                          &firstHas, &anyHas, &allHas,
00818                                          outStateString);
00819   if (NS_FAILED(rv)) return rv;
00820 
00821   nsCAutoString tOutStateString;
00822   tOutStateString.AssignWithConversion(outStateString);
00823   aParams->SetBooleanValue(STATE_MIXED, anyHas && !allHas);
00824   aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
00825   aParams->SetBooleanValue(STATE_ENABLED, PR_TRUE);
00826 
00827   return rv;
00828 }
00829 
00830 
00831 // acceptable values for "newState" are:
00832 //   -2
00833 //   -1
00834 //    0
00835 //   +1
00836 //   +2
00837 //   +3
00838 //   medium
00839 //   normal
00840 nsresult
00841 nsFontSizeStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
00842 {
00843   NS_ASSERTION(aEditor, "Need an editor here");
00844   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
00845   if (!htmlEditor) return NS_ERROR_INVALID_ARG;
00846 
00847   nsresult rv;
00848   nsCOMPtr<nsIAtom> fontAtom = do_GetAtom("font");
00849   if (newState.IsEmpty() || 
00850       newState.EqualsLiteral("normal") ||
00851       newState.EqualsLiteral("medium")) {
00852     // remove any existing font size, big or small
00853     rv = htmlEditor->RemoveInlineProperty(fontAtom, NS_LITERAL_STRING("size"));  
00854     if (NS_FAILED(rv)) return rv;
00855 
00856     nsCOMPtr<nsIAtom> bigAtom = do_GetAtom("big");
00857     rv = htmlEditor->RemoveInlineProperty(bigAtom, EmptyString());  
00858     if (NS_FAILED(rv)) return rv;
00859 
00860     nsCOMPtr<nsIAtom> smallAtom = do_GetAtom("small");
00861     rv = htmlEditor->RemoveInlineProperty(smallAtom, EmptyString());  
00862     if (NS_FAILED(rv)) return rv;
00863   } else {
00864     // set the size
00865     rv = htmlEditor->SetInlineProperty(fontAtom, NS_LITERAL_STRING("size"),
00866                                        newState);
00867   }
00868 
00869   return rv;
00870 }
00871 
00872 #ifdef XP_MAC
00873 #pragma mark -
00874 #endif
00875 nsFontColorStateCommand::nsFontColorStateCommand()
00876 : nsMultiStateCommand()
00877 {
00878 }
00879 
00880 nsresult
00881 nsFontColorStateCommand::GetCurrentState(nsIEditor *aEditor,
00882                                          nsICommandParams *aParams)
00883 {
00884   NS_ASSERTION(aEditor, "Need an editor here");
00885   
00886   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
00887   if (!htmlEditor) return NS_ERROR_FAILURE;
00888 
00889   PRBool outMixed;
00890   nsAutoString outStateString;
00891   nsresult rv = htmlEditor->GetFontColorState(&outMixed, outStateString);
00892   if (NS_SUCCEEDED(rv))
00893   {
00894     nsCAutoString tOutStateString;
00895     tOutStateString.AssignWithConversion(outStateString);
00896     aParams->SetBooleanValue(STATE_MIXED,outMixed);
00897     aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
00898   }
00899   return rv;
00900 }
00901 
00902 nsresult
00903 nsFontColorStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
00904 {
00905   NS_ASSERTION(aEditor, "Need an editor here");
00906   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
00907   if (!htmlEditor) return NS_ERROR_FAILURE;
00908   
00909   nsresult rv;
00910   nsCOMPtr<nsIAtom> fontAtom = do_GetAtom("font");
00911 
00912   if (newState.IsEmpty() || newState.EqualsLiteral("normal")) {
00913     rv = htmlEditor->RemoveInlineProperty(fontAtom, NS_LITERAL_STRING("color"));
00914   } else {
00915     rv = htmlEditor->SetInlineProperty(fontAtom, NS_LITERAL_STRING("color"), 
00916                                        newState);
00917   }
00918   
00919   return rv;
00920 }
00921 
00922 #ifdef XP_MAC
00923 #pragma mark -
00924 #endif
00925 
00926 nsHighlightColorStateCommand::nsHighlightColorStateCommand()
00927 : nsMultiStateCommand()
00928 {
00929 }
00930 
00931 nsresult
00932 nsHighlightColorStateCommand::GetCurrentState(nsIEditor *aEditor,
00933                                               nsICommandParams *aParams)
00934 {
00935   NS_ASSERTION(aEditor, "Need an editor here");
00936   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
00937   if (!htmlEditor) return NS_ERROR_FAILURE;
00938 
00939   PRBool outMixed;
00940   nsAutoString outStateString;
00941   nsresult rv = htmlEditor->GetHighlightColorState(&outMixed, outStateString);
00942   if (NS_SUCCEEDED(rv))
00943   {
00944     nsCAutoString tOutStateString;
00945     tOutStateString.AssignWithConversion(outStateString);
00946     aParams->SetBooleanValue(STATE_MIXED,outMixed);
00947     aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
00948   }
00949   return rv;
00950 }
00951 
00952 nsresult
00953 nsHighlightColorStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
00954 {
00955   NS_ASSERTION(aEditor, "Need an editor here");
00956   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
00957   if (!htmlEditor) return NS_ERROR_FAILURE;
00958 
00959   nsresult rv;
00960   nsCOMPtr<nsIAtom> fontAtom = do_GetAtom("font");
00961 
00962   if (newState.IsEmpty() || newState.EqualsLiteral("normal")) {
00963 //    rv = RemoveOneProperty(htmlEditor, NS_LITERAL_STRING("font"), NS_LITERAL_STRING("bgcolor"));
00964     rv = htmlEditor->RemoveInlineProperty(fontAtom, NS_LITERAL_STRING("bgcolor"));
00965   } else {
00966     rv = htmlEditor->SetCSSInlineProperty(fontAtom, NS_LITERAL_STRING("bgcolor"),
00967                                           newState);
00968   }
00969 
00970   return rv;
00971 }
00972 
00973 NS_IMETHODIMP
00974 nsHighlightColorStateCommand::IsCommandEnabled(const char * aCommandName,
00975                                                nsISupports *refCon,
00976                                                PRBool *outCmdEnabled)
00977 {
00978   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(refCon);
00979   *outCmdEnabled = htmlEditor ? PR_TRUE : PR_FALSE;
00980   return NS_OK;
00981 }
00982 
00983 
00984 #ifdef XP_MAC
00985 #pragma mark -
00986 #endif
00987 
00988 nsBackgroundColorStateCommand::nsBackgroundColorStateCommand()
00989 : nsMultiStateCommand()
00990 {
00991 }
00992 
00993 nsresult
00994 nsBackgroundColorStateCommand::GetCurrentState(nsIEditor *aEditor,
00995                                                nsICommandParams *aParams)
00996 {
00997   NS_ASSERTION(aEditor, "Need an editor here");
00998   
00999   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
01000   if (!htmlEditor) return NS_ERROR_FAILURE;
01001 
01002   PRBool outMixed;
01003   nsAutoString outStateString;
01004   nsresult rv =  htmlEditor->GetBackgroundColorState(&outMixed, outStateString);
01005   if (NS_SUCCEEDED(rv))
01006   {
01007     nsCAutoString tOutStateString;
01008     tOutStateString.AssignWithConversion(outStateString);
01009     aParams->SetBooleanValue(STATE_MIXED,outMixed);
01010     aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
01011   }
01012   return rv;
01013 }
01014 
01015 nsresult
01016 nsBackgroundColorStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
01017 {
01018   NS_ASSERTION(aEditor, "Need an editor here");
01019   
01020   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
01021   if (!htmlEditor) return NS_ERROR_FAILURE;
01022 
01023   return htmlEditor->SetBackgroundColor(newState);
01024 }
01025 
01026 #ifdef XP_MAC
01027 #pragma mark -
01028 #endif
01029 
01030 nsAlignCommand::nsAlignCommand()
01031 : nsMultiStateCommand()
01032 {
01033 }
01034 
01035 nsresult
01036 nsAlignCommand::GetCurrentState(nsIEditor *aEditor, nsICommandParams *aParams)
01037 {
01038   NS_ASSERTION(aEditor, "Need an editor here");
01039   
01040   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
01041   if (!htmlEditor) return NS_ERROR_FAILURE;
01042  
01043   nsIHTMLEditor::EAlignment firstAlign;
01044   PRBool outMixed;
01045   nsresult rv = htmlEditor->GetAlignment(&outMixed, &firstAlign);
01046   
01047   if (NS_FAILED(rv)) 
01048     return rv;
01049   
01050   nsAutoString outStateString;
01051   switch (firstAlign)
01052   {
01053     default:
01054     case nsIHTMLEditor::eLeft:
01055       outStateString.AssignLiteral("left");
01056       break;
01057       
01058     case nsIHTMLEditor::eCenter:
01059       outStateString.AssignLiteral("center");
01060       break;
01061       
01062     case nsIHTMLEditor::eRight:
01063       outStateString.AssignLiteral("right");
01064       break;
01065 
01066     case nsIHTMLEditor::eJustify:
01067       outStateString.AssignLiteral("justify");
01068       break;
01069   }
01070   nsCAutoString tOutStateString;
01071   tOutStateString.AssignWithConversion(outStateString);
01072   aParams->SetBooleanValue(STATE_MIXED,outMixed);
01073   aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
01074   return NS_OK;
01075 }
01076 
01077 nsresult
01078 nsAlignCommand::SetState(nsIEditor *aEditor, nsString& newState)
01079 {
01080   NS_ASSERTION(aEditor, "Need an editor here");
01081   
01082   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
01083   if (!htmlEditor) return NS_ERROR_FAILURE;
01084 
01085   return htmlEditor->Align(newState);
01086 }
01087 
01088 
01089 #ifdef XP_MAC
01090 #pragma mark -
01091 #endif
01092 
01093 
01094 nsAbsolutePositioningCommand::nsAbsolutePositioningCommand()
01095 : nsBaseStateUpdatingCommand("")
01096 {
01097 }
01098 
01099 NS_IMETHODIMP
01100 nsAbsolutePositioningCommand::IsCommandEnabled(const char * aCommandName,
01101                                                nsISupports *aCommandRefCon,
01102                                                PRBool *_retval)
01103 {
01104   NS_ASSERTION(aCommandRefCon, "Need an editor here");
01105   
01106   nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(aCommandRefCon);
01107   if (!htmlEditor) return NS_ERROR_FAILURE;
01108 
01109   htmlEditor->GetAbsolutePositioningEnabled(_retval);
01110   return NS_OK;
01111 }
01112 
01113 nsresult
01114 nsAbsolutePositioningCommand::GetCurrentState(nsIEditor *aEditor, const char* aTagName, nsICommandParams *aParams)
01115 {
01116   NS_ASSERTION(aEditor, "Need an editor here");
01117   
01118   nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(aEditor);
01119   if (!htmlEditor) return NS_ERROR_FAILURE;
01120 
01121   PRBool isEnabled;
01122   htmlEditor->GetAbsolutePositioningEnabled(&isEnabled);
01123   if (!isEnabled) {
01124     aParams->SetBooleanValue(STATE_MIXED,PR_FALSE);
01125     aParams->SetCStringValue(STATE_ATTRIBUTE, "");
01126     return NS_OK;
01127   }
01128 
01129   nsCOMPtr<nsIDOMElement>  elt;
01130   nsresult rv = htmlEditor->GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(elt));
01131   if (NS_FAILED(rv)) 
01132     return rv;
01133 
01134   nsAutoString outStateString;
01135   if (elt)
01136     outStateString.AssignLiteral("absolute");
01137 
01138   aParams->SetBooleanValue(STATE_MIXED,PR_FALSE);
01139   aParams->SetCStringValue(STATE_ATTRIBUTE, NS_ConvertUCS2toUTF8(outStateString).get());
01140   return NS_OK;
01141 }
01142 
01143 nsresult
01144 nsAbsolutePositioningCommand::ToggleState(nsIEditor *aEditor, const char* aTagName)
01145 {
01146   NS_ASSERTION(aEditor, "Need an editor here");
01147   
01148   nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(aEditor);
01149   if (!htmlEditor) return NS_ERROR_FAILURE;
01150 
01151   nsCOMPtr<nsIDOMElement>  elt;
01152   nsresult rv = htmlEditor->GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(elt));
01153   if (NS_FAILED(rv)) return rv;
01154 
01155   if (elt) {
01156     // we have to remove positioning on an element
01157     rv = htmlEditor->AbsolutePositionSelection(PR_FALSE);
01158   }
01159   else {
01160     rv = htmlEditor->AbsolutePositionSelection(PR_TRUE);
01161   }
01162   return rv;
01163 }
01164 
01165 
01166 #ifdef XP_MAC
01167 #pragma mark -
01168 #endif
01169 
01170 NS_IMETHODIMP
01171 nsDecreaseZIndexCommand::IsCommandEnabled(const char * aCommandName,
01172                                           nsISupports *refCon,
01173                                           PRBool *outCmdEnabled)
01174 {
01175   nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon);
01176   if (!htmlEditor) return NS_ERROR_FAILURE;
01177 
01178   htmlEditor->GetAbsolutePositioningEnabled(outCmdEnabled);
01179   if (!(*outCmdEnabled))
01180     return NS_OK;
01181 
01182   nsCOMPtr<nsIDOMElement> positionedElement;
01183   htmlEditor->GetPositionedElement(getter_AddRefs(positionedElement));
01184   *outCmdEnabled = PR_FALSE;
01185   if (positionedElement) {
01186     PRInt32 z;
01187     nsresult res = htmlEditor->GetElementZIndex(positionedElement, &z);
01188     if (NS_FAILED(res)) return res;
01189     *outCmdEnabled = (z > 0);
01190   }
01191 
01192   return NS_OK;
01193 }
01194 
01195 NS_IMETHODIMP
01196 nsDecreaseZIndexCommand::DoCommand(const char *aCommandName,
01197                                    nsISupports *refCon)
01198 {
01199   nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon);
01200   if (!htmlEditor)
01201     return NS_ERROR_NOT_IMPLEMENTED;
01202 
01203   return htmlEditor->RelativeChangeZIndex(-1);
01204 }
01205 
01206 NS_IMETHODIMP
01207 nsDecreaseZIndexCommand::DoCommandParams(const char *aCommandName,
01208                                          nsICommandParams *aParams, 
01209                                          nsISupports *refCon)
01210 {
01211   return DoCommand(aCommandName, refCon);
01212 }
01213 
01214 NS_IMETHODIMP
01215 nsDecreaseZIndexCommand::GetCommandStateParams(const char *aCommandName,
01216                                                nsICommandParams *aParams,
01217                                                nsISupports *refCon)
01218 {
01219   NS_ENSURE_ARG_POINTER(aParams);
01220 
01221   PRBool enabled = PR_FALSE;
01222   nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled);
01223   NS_ENSURE_SUCCESS(rv, rv);
01224 
01225   return aParams->SetBooleanValue(STATE_ENABLED, enabled);
01226 }
01227 
01228 #ifdef XP_MAC
01229 #pragma mark -
01230 #endif
01231 
01232 NS_IMETHODIMP
01233 nsIncreaseZIndexCommand::IsCommandEnabled(const char * aCommandName,
01234                                           nsISupports *refCon,
01235                                           PRBool *outCmdEnabled)
01236 {
01237   nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon);
01238   if (!htmlEditor) return NS_ERROR_FAILURE;
01239 
01240   htmlEditor->GetAbsolutePositioningEnabled(outCmdEnabled);
01241   if (!(*outCmdEnabled))
01242     return NS_OK;
01243 
01244   nsCOMPtr<nsIDOMElement> positionedElement;
01245   htmlEditor->GetPositionedElement(getter_AddRefs(positionedElement));
01246   *outCmdEnabled = (nsnull != positionedElement);
01247   return NS_OK;
01248 }
01249 
01250 NS_IMETHODIMP
01251 nsIncreaseZIndexCommand::DoCommand(const char *aCommandName,
01252                                    nsISupports *refCon)
01253 {
01254   nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon);
01255   if (!htmlEditor)
01256     return NS_ERROR_NOT_IMPLEMENTED;
01257 
01258   return htmlEditor->RelativeChangeZIndex(1);
01259 }
01260 
01261 NS_IMETHODIMP
01262 nsIncreaseZIndexCommand::DoCommandParams(const char *aCommandName,
01263                                          nsICommandParams *aParams, 
01264                                          nsISupports *refCon)
01265 {
01266   return DoCommand(aCommandName, refCon);
01267 }
01268 
01269 NS_IMETHODIMP
01270 nsIncreaseZIndexCommand::GetCommandStateParams(const char *aCommandName,
01271                                                nsICommandParams *aParams,
01272                                                nsISupports *refCon)
01273 {
01274   NS_ENSURE_ARG_POINTER(aParams);
01275 
01276   PRBool enabled = PR_FALSE;
01277   nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled);
01278   NS_ENSURE_SUCCESS(rv, rv);
01279 
01280   return aParams->SetBooleanValue(STATE_ENABLED, enabled);
01281 }
01282 
01283 #ifdef XP_MAC
01284 #pragma mark -
01285 #endif
01286 
01287 
01288 NS_IMETHODIMP
01289 nsRemoveStylesCommand::IsCommandEnabled(const char * aCommandName,
01290                                         nsISupports *refCon,
01291                                         PRBool *outCmdEnabled)
01292 {
01293   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
01294   // test if we have any styles?
01295   *outCmdEnabled = editor ? PR_TRUE : PR_FALSE;
01296   return NS_OK;
01297 }
01298 
01299 
01300 
01301 NS_IMETHODIMP
01302 nsRemoveStylesCommand::DoCommand(const char *aCommandName,
01303                                  nsISupports *refCon)
01304 {
01305   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
01306 
01307   nsresult rv = NS_OK;
01308   if (editor)
01309   {
01310     rv = editor->RemoveAllInlineProperties();
01311   }
01312   
01313   return rv;  
01314 }
01315 
01316 NS_IMETHODIMP
01317 nsRemoveStylesCommand::DoCommandParams(const char *aCommandName,
01318                                        nsICommandParams *aParams,
01319                                        nsISupports *refCon)
01320 {
01321   return DoCommand(aCommandName, refCon);
01322 }
01323 
01324 NS_IMETHODIMP
01325 nsRemoveStylesCommand::GetCommandStateParams(const char *aCommandName,
01326                                              nsICommandParams *aParams,
01327                                              nsISupports *refCon)
01328 {
01329   PRBool outCmdEnabled = PR_FALSE;
01330   IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
01331   return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled);
01332 }
01333 
01334 #ifdef XP_MAC
01335 #pragma mark -
01336 #endif
01337 
01338 NS_IMETHODIMP
01339 nsIncreaseFontSizeCommand::IsCommandEnabled(const char * aCommandName,
01340                                             nsISupports *refCon,
01341                                             PRBool *outCmdEnabled)
01342 {
01343   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
01344   // test if we have any styles?
01345   *outCmdEnabled = editor ? PR_TRUE : PR_FALSE;
01346   return NS_OK;
01347 }
01348 
01349 
01350 NS_IMETHODIMP
01351 nsIncreaseFontSizeCommand::DoCommand(const char *aCommandName,
01352                                      nsISupports *refCon)
01353 {
01354   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
01355 
01356   nsresult rv = NS_OK;
01357   if (editor)
01358   {
01359     rv = editor->IncreaseFontSize();
01360   }
01361   
01362   return rv;  
01363 }
01364 
01365 NS_IMETHODIMP
01366 nsIncreaseFontSizeCommand::DoCommandParams(const char *aCommandName,
01367                                            nsICommandParams *aParams,
01368                                            nsISupports *refCon)
01369 {
01370   return DoCommand(aCommandName, refCon);
01371 }
01372 
01373 NS_IMETHODIMP
01374 nsIncreaseFontSizeCommand::GetCommandStateParams(const char *aCommandName,
01375                                                  nsICommandParams *aParams,
01376                                                  nsISupports *refCon)
01377 {
01378   PRBool outCmdEnabled = PR_FALSE;
01379   IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
01380   return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled);
01381 }
01382 
01383 #ifdef XP_MAC
01384 #pragma mark -
01385 #endif
01386 
01387 NS_IMETHODIMP
01388 nsDecreaseFontSizeCommand::IsCommandEnabled(const char * aCommandName,
01389                                             nsISupports *refCon,
01390                                             PRBool *outCmdEnabled)
01391 {
01392   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
01393   // test if we are at min size?
01394   *outCmdEnabled = editor ? PR_TRUE : PR_FALSE;
01395   return NS_OK;
01396 }
01397 
01398 
01399 NS_IMETHODIMP
01400 nsDecreaseFontSizeCommand::DoCommand(const char *aCommandName,
01401                                      nsISupports *refCon)
01402 {
01403   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
01404 
01405   nsresult rv = NS_OK;
01406   if (editor)
01407   {
01408     rv = editor->DecreaseFontSize();
01409   }
01410   
01411   return rv;  
01412 }
01413 
01414 NS_IMETHODIMP
01415 nsDecreaseFontSizeCommand::DoCommandParams(const char *aCommandName,
01416                                            nsICommandParams *aParams,
01417                                            nsISupports *refCon)
01418 {
01419   return DoCommand(aCommandName, refCon);
01420 }
01421 
01422 NS_IMETHODIMP
01423 nsDecreaseFontSizeCommand::GetCommandStateParams(const char *aCommandName,
01424                                                  nsICommandParams *aParams,
01425                                                  nsISupports *refCon)
01426 {
01427   PRBool outCmdEnabled = PR_FALSE;
01428   IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
01429   return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled);
01430 }
01431 
01432 #ifdef XP_MAC
01433 #pragma mark -
01434 #endif
01435 
01436 NS_IMETHODIMP
01437 nsInsertHTMLCommand::IsCommandEnabled(const char * aCommandName,
01438                                       nsISupports *refCon,
01439                                       PRBool *outCmdEnabled)
01440 {
01441   NS_ENSURE_ARG_POINTER(outCmdEnabled);
01442   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
01443   *outCmdEnabled = editor ? PR_TRUE : PR_FALSE;
01444   return NS_OK;
01445 }
01446 
01447 
01448 NS_IMETHODIMP
01449 nsInsertHTMLCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
01450 {
01451   return NS_ERROR_NOT_IMPLEMENTED;
01452 }
01453 
01454 NS_IMETHODIMP
01455 nsInsertHTMLCommand::DoCommandParams(const char *aCommandName,
01456                                      nsICommandParams *aParams,
01457                                      nsISupports *refCon)
01458 {
01459   NS_ENSURE_ARG_POINTER(aParams);
01460   NS_ENSURE_ARG_POINTER(refCon);
01461 
01462   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
01463   if (!editor)
01464     return NS_ERROR_NOT_IMPLEMENTED;
01465 
01466   // Get HTML source string to insert from command params
01467   nsAutoString html;
01468   nsresult rv = aParams->GetStringValue(STATE_DATA, html);
01469   NS_ENSURE_SUCCESS(rv, rv);
01470 
01471   if (!html.IsEmpty())
01472     return editor->InsertHTML(html);
01473 
01474   return NS_OK;
01475 }
01476 
01477 NS_IMETHODIMP
01478 nsInsertHTMLCommand::GetCommandStateParams(const char *aCommandName,
01479                                            nsICommandParams *aParams,
01480                                            nsISupports *refCon)
01481 {
01482   NS_ENSURE_ARG_POINTER(aParams);
01483   NS_ENSURE_ARG_POINTER(refCon);
01484 
01485   PRBool outCmdEnabled = PR_FALSE;
01486   IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
01487   return aParams->SetBooleanValue(STATE_ENABLED, outCmdEnabled);
01488 }
01489 
01490 #ifdef XP_MAC
01491 #pragma mark -
01492 #endif
01493 
01494 NS_IMPL_ISUPPORTS_INHERITED0(nsInsertTagCommand, nsBaseComposerCommand)
01495 
01496 nsInsertTagCommand::nsInsertTagCommand(const char* aTagName)
01497 : nsBaseComposerCommand()
01498 , mTagName(aTagName)
01499 {
01500 }
01501 
01502 nsInsertTagCommand::~nsInsertTagCommand()
01503 {
01504 }
01505 
01506 NS_IMETHODIMP
01507 nsInsertTagCommand::IsCommandEnabled(const char * aCommandName,
01508                                      nsISupports *refCon,
01509                                      PRBool *outCmdEnabled)
01510 {
01511   NS_ENSURE_ARG_POINTER(outCmdEnabled);
01512   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
01513   *outCmdEnabled = editor ? PR_TRUE : PR_FALSE;
01514   return NS_OK;
01515 }
01516 
01517 
01518 // corresponding STATE_ATTRIBUTE is: src (img) and href (a) 
01519 NS_IMETHODIMP
01520 nsInsertTagCommand::DoCommand(const char *aCmdName, nsISupports *refCon)
01521 {
01522   if (0 == nsCRT::strcmp(mTagName, "hr"))
01523   {
01524     nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
01525     if (!editor)
01526       return NS_ERROR_NOT_IMPLEMENTED;
01527 
01528     nsCOMPtr<nsIDOMElement> domElem;
01529     nsresult rv;
01530     rv = editor->CreateElementWithDefaults(NS_ConvertASCIItoUCS2(mTagName),
01531                                            getter_AddRefs(domElem));
01532     if (NS_FAILED(rv))
01533       return rv;
01534 
01535     return editor->InsertElementAtSelection(domElem, PR_TRUE);
01536   }
01537 
01538   return NS_ERROR_NOT_IMPLEMENTED;
01539 }
01540 
01541 NS_IMETHODIMP
01542 nsInsertTagCommand::DoCommandParams(const char *aCommandName,
01543                                     nsICommandParams *aParams,
01544                                     nsISupports *refCon)
01545 {
01546   NS_ENSURE_ARG_POINTER(refCon);
01547 
01548   // inserting an hr shouldn't have an parameters, just call DoCommand for that
01549   if (0 == nsCRT::strcmp(mTagName, "hr"))
01550     return DoCommand(aCommandName, refCon);
01551 
01552   NS_ENSURE_ARG_POINTER(aParams);
01553 
01554   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
01555   if (!editor)
01556     return NS_ERROR_NOT_IMPLEMENTED;
01557 
01558   // do we have an href to use for creating link?
01559   nsXPIDLCString s;
01560   nsresult rv = aParams->GetCStringValue(STATE_ATTRIBUTE, getter_Copies(s));
01561   NS_ENSURE_SUCCESS(rv, rv);
01562   nsAutoString attrib; attrib.AssignWithConversion(s);
01563 
01564   if (attrib.IsEmpty())
01565     return NS_ERROR_INVALID_ARG;
01566 
01567   // filter out tags we don't know how to insert
01568   nsAutoString attributeType;
01569   if (0 == nsCRT::strcmp(mTagName, "a")) {
01570     attributeType.AssignLiteral("href");
01571   } else if (0 == nsCRT::strcmp(mTagName, "img")) {
01572     attributeType.AssignLiteral("src");
01573   } else {
01574     return NS_ERROR_NOT_IMPLEMENTED;
01575   }
01576 
01577   nsCOMPtr<nsIDOMElement> domElem;
01578   rv = editor->CreateElementWithDefaults(NS_ConvertASCIItoUCS2(mTagName),
01579                                          getter_AddRefs(domElem));
01580   if (NS_FAILED(rv))
01581     return rv;
01582 
01583   rv = domElem->SetAttribute(attributeType, attrib);
01584   if (NS_FAILED(rv))
01585     return rv;
01586 
01587   // do actual insertion
01588   if (0 == nsCRT::strcmp(mTagName, "a"))
01589     return editor->InsertLinkAroundSelection(domElem);
01590 
01591   return editor->InsertElementAtSelection(domElem, PR_TRUE);
01592 }
01593 
01594 NS_IMETHODIMP
01595 nsInsertTagCommand::GetCommandStateParams(const char *aCommandName,
01596                                           nsICommandParams *aParams,
01597                                           nsISupports *refCon)
01598 {
01599   NS_ENSURE_ARG_POINTER(aParams);
01600   NS_ENSURE_ARG_POINTER(refCon);
01601 
01602   PRBool outCmdEnabled = PR_FALSE;
01603   IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
01604   return aParams->SetBooleanValue(STATE_ENABLED, outCmdEnabled);
01605 }
01606 
01607 #ifdef XP_MAC
01608 #pragma mark -
01609 #endif
01610 
01611 /****************************/
01612 //HELPER METHODS
01613 /****************************/
01614 
01615 nsresult
01616 GetListState(nsIEditor *aEditor, PRBool *aMixed, PRUnichar **_retval)
01617 {
01618   if (!aMixed || !_retval || !aEditor) 
01619     return NS_ERROR_NULL_POINTER;
01620   *_retval = nsnull;
01621   *aMixed = PR_FALSE;
01622 
01623   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
01624   nsresult err = NS_ERROR_NO_INTERFACE;
01625   if (htmlEditor)
01626   {
01627     PRBool bOL, bUL, bDL;
01628     err = htmlEditor->GetListState(aMixed, &bOL, &bUL, &bDL);
01629     if (NS_SUCCEEDED(err))
01630     {
01631       if (!*aMixed)
01632       {
01633         nsAutoString tagStr;
01634         if (bOL) 
01635           tagStr.AssignLiteral("ol");
01636         else if (bUL) 
01637           tagStr.AssignLiteral("ul");
01638         else if (bDL) 
01639           tagStr.AssignLiteral("dl");
01640         *_retval = ToNewUnicode(tagStr);
01641       }
01642     }  
01643   }
01644   return err;
01645 }
01646 
01647 nsresult
01648 RemoveOneProperty(nsIHTMLEditor *aEditor,const nsString& aProp, 
01649                   const nsString &aAttr)
01650 {
01651   if (!aEditor) 
01652     return NS_ERROR_NOT_INITIALIZED;
01653 
01655   nsCOMPtr<nsIAtom> styleAtom = do_GetAtom(aProp);
01656   if (! styleAtom) 
01657     return NS_ERROR_OUT_OF_MEMORY;
01658 
01659   return aEditor->RemoveInlineProperty(styleAtom, aAttr);
01660 }
01661 
01662 
01663 // the name of the attribute here should be the contents of the appropriate
01664 // tag, e.g. 'b' for bold, 'i' for italics.
01665 nsresult
01666 RemoveTextProperty(nsIEditor *aEditor, const PRUnichar *prop, 
01667                    const PRUnichar *attr)
01668 {
01669   if (!aEditor) 
01670     return NS_ERROR_NOT_INITIALIZED;
01671   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(aEditor);
01672   if (!editor) 
01673     return NS_ERROR_INVALID_ARG;
01674   // OK, I'm really hacking now. This is just so that 
01675   //     we can accept 'all' as input.  
01676   nsAutoString  allStr(prop);
01677   
01678   ToLowerCase(allStr);
01679   PRBool    doingAll = (allStr.EqualsLiteral("all"));
01680   nsresult  err = NS_OK;
01681 
01682   if (doingAll)
01683   {
01684     err = editor->RemoveAllInlineProperties();
01685   }
01686   else
01687   {
01688     nsAutoString  aProp(prop);
01689     nsAutoString  aAttr(attr);
01690     err = RemoveOneProperty(editor,aProp, aAttr);
01691   }
01692   
01693   return err;
01694 }
01695 
01696 // the name of the attribute here should be the contents of the appropriate
01697 // tag, e.g. 'b' for bold, 'i' for italics.
01698 nsresult
01699 SetTextProperty(nsIEditor *aEditor, const PRUnichar *prop, 
01700                 const PRUnichar *attr, const PRUnichar *value)
01701 {
01702   //static initialization 
01703   static const PRUnichar sEmptyStr = PRUnichar('\0');
01704   
01705   if (!aEditor) 
01706     return NS_ERROR_NOT_INITIALIZED;
01707 
01709   nsCOMPtr<nsIAtom> styleAtom = do_GetAtom(prop);
01710   if (! styleAtom) 
01711     return NS_ERROR_OUT_OF_MEMORY;
01712 
01713   nsresult  err = NS_NOINTERFACE;
01714 
01715   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor,&err);
01716   if (htmlEditor)
01717     err = htmlEditor->SetInlineProperty(styleAtom,
01718                                 nsDependentString(attr?attr:&sEmptyStr),
01719                                 nsDependentString(value?value:&sEmptyStr));
01720 
01721   return err;
01722 }