1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 
7 #include <stdio.h>                      // for printf
8 
9 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
10 #include "nsAString.h"
11 #include "nsCOMPtr.h"                   // for nsCOMPtr, do_QueryInterface, etc
12 #include "nsComponentManagerUtils.h"    // for do_CreateInstance
13 #include "nsComposerCommands.h"
14 #include "nsDebug.h"                    // for NS_ENSURE_TRUE, etc
15 #include "nsError.h"                    // for NS_OK, NS_ERROR_FAILURE, etc
16 #include "nsGkAtoms.h"                  // for nsGkAtoms, nsGkAtoms::font, etc
17 #include "nsIAtom.h"                    // for nsIAtom, etc
18 #include "nsIClipboard.h"               // for nsIClipboard, etc
19 #include "nsICommandParams.h"           // for nsICommandParams, etc
20 #include "nsID.h"
21 #include "nsIDOMElement.h"              // for nsIDOMElement
22 #include "nsIEditor.h"                  // for nsIEditor
23 #include "nsIHTMLAbsPosEditor.h"        // for nsIHTMLAbsPosEditor
24 #include "nsIHTMLEditor.h"              // for nsIHTMLEditor, etc
25 #include "nsLiteralString.h"            // for NS_LITERAL_STRING
26 #include "nsReadableUtils.h"            // for EmptyString
27 #include "nsString.h"                   // for nsAutoString, nsString, etc
28 #include "nsStringFwd.h"                // for nsAFlatString
29 
30 class nsISupports;
31 
32 //prototype
33 nsresult GetListState(nsIHTMLEditor* aEditor, bool* aMixed,
34                       nsAString& aLocalName);
35 nsresult RemoveOneProperty(nsIHTMLEditor* aEditor, const nsAString& aProp);
36 nsresult RemoveTextProperty(nsIHTMLEditor* aEditor, const nsAString& aProp);
37 nsresult SetTextProperty(nsIHTMLEditor *aEditor, const nsAString& aProp);
38 
39 
40 //defines
41 #define STATE_ENABLED  "state_enabled"
42 #define STATE_ALL "state_all"
43 #define STATE_ANY "state_any"
44 #define STATE_MIXED "state_mixed"
45 #define STATE_BEGIN "state_begin"
46 #define STATE_END "state_end"
47 #define STATE_ATTRIBUTE "state_attribute"
48 #define STATE_DATA "state_data"
49 
50 
nsBaseComposerCommand()51 nsBaseComposerCommand::nsBaseComposerCommand()
52 {
53 }
54 
NS_IMPL_ISUPPORTS(nsBaseComposerCommand,nsIControllerCommand)55 NS_IMPL_ISUPPORTS(nsBaseComposerCommand, nsIControllerCommand)
56 
57 
58 nsBaseStateUpdatingCommand::nsBaseStateUpdatingCommand(nsIAtom* aTagName)
59 : nsBaseComposerCommand()
60 , mTagName(aTagName)
61 {
62   MOZ_ASSERT(mTagName);
63 }
64 
~nsBaseStateUpdatingCommand()65 nsBaseStateUpdatingCommand::~nsBaseStateUpdatingCommand()
66 {
67 }
68 
NS_IMPL_ISUPPORTS_INHERITED0(nsBaseStateUpdatingCommand,nsBaseComposerCommand)69 NS_IMPL_ISUPPORTS_INHERITED0(nsBaseStateUpdatingCommand, nsBaseComposerCommand)
70 
71 NS_IMETHODIMP
72 nsBaseStateUpdatingCommand::IsCommandEnabled(const char *aCommandName,
73                                              nsISupports *refCon,
74                                              bool *outCmdEnabled)
75 {
76   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
77   if (editor)
78     return editor->GetIsSelectionEditable(outCmdEnabled);
79 
80   *outCmdEnabled = false;
81   return NS_OK;
82 }
83 
84 
85 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * refCon)86 nsBaseStateUpdatingCommand::DoCommand(const char *aCommandName,
87                                       nsISupports *refCon)
88 {
89   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
90   NS_ENSURE_TRUE(editor, NS_ERROR_NOT_INITIALIZED);
91 
92   return ToggleState(editor);
93 }
94 
95 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)96 nsBaseStateUpdatingCommand::DoCommandParams(const char *aCommandName,
97                                             nsICommandParams *aParams,
98                                             nsISupports *refCon)
99 {
100   return DoCommand(aCommandName, refCon);
101 }
102 
103 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)104 nsBaseStateUpdatingCommand::GetCommandStateParams(const char *aCommandName,
105                                                   nsICommandParams *aParams,
106                                                   nsISupports *refCon)
107 {
108   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
109   if (editor)
110     return GetCurrentState(editor, aParams);
111 
112   return NS_OK;
113 }
114 
115 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * refCon,bool * outCmdEnabled)116 nsPasteNoFormattingCommand::IsCommandEnabled(const char * aCommandName,
117                                              nsISupports *refCon,
118                                              bool *outCmdEnabled)
119 {
120   NS_ENSURE_ARG_POINTER(outCmdEnabled);
121   *outCmdEnabled = false;
122 
123   // This command is only implemented by nsIHTMLEditor, since
124   //  pasting in a plaintext editor automatically only supplies
125   //  "unformatted" text
126   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(refCon);
127   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NOT_IMPLEMENTED);
128 
129   nsCOMPtr<nsIEditor> editor = do_QueryInterface(htmlEditor);
130   NS_ENSURE_TRUE(editor, NS_ERROR_INVALID_ARG);
131 
132   return editor->CanPaste(nsIClipboard::kGlobalClipboard, outCmdEnabled);
133 }
134 
135 
136 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * refCon)137 nsPasteNoFormattingCommand::DoCommand(const char *aCommandName,
138                                       nsISupports *refCon)
139 {
140   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(refCon);
141   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NOT_IMPLEMENTED);
142 
143   return htmlEditor->PasteNoFormatting(nsIClipboard::kGlobalClipboard);
144 }
145 
146 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)147 nsPasteNoFormattingCommand::DoCommandParams(const char *aCommandName,
148                                             nsICommandParams *aParams,
149                                             nsISupports *refCon)
150 {
151   return DoCommand(aCommandName, refCon);
152 }
153 
154 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)155 nsPasteNoFormattingCommand::GetCommandStateParams(const char *aCommandName,
156                                                   nsICommandParams *aParams,
157                                                   nsISupports *refCon)
158 {
159   NS_ENSURE_ARG_POINTER(aParams);
160 
161   bool enabled = false;
162   nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled);
163   NS_ENSURE_SUCCESS(rv, rv);
164 
165   return aParams->SetBooleanValue(STATE_ENABLED, enabled);
166 }
167 
nsStyleUpdatingCommand(nsIAtom * aTagName)168 nsStyleUpdatingCommand::nsStyleUpdatingCommand(nsIAtom* aTagName)
169 : nsBaseStateUpdatingCommand(aTagName)
170 {
171 }
172 
173 nsresult
GetCurrentState(nsIEditor * aEditor,nsICommandParams * aParams)174 nsStyleUpdatingCommand::GetCurrentState(nsIEditor *aEditor,
175                                         nsICommandParams *aParams)
176 {
177   NS_ASSERTION(aEditor, "Need editor here");
178   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
179   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NOT_INITIALIZED);
180 
181   bool firstOfSelectionHasProp = false;
182   bool anyOfSelectionHasProp = false;
183   bool allOfSelectionHasProp = false;
184 
185   nsresult rv = htmlEditor->GetInlineProperty(mTagName, EmptyString(),
186                                               EmptyString(),
187                                               &firstOfSelectionHasProp,
188                                               &anyOfSelectionHasProp,
189                                               &allOfSelectionHasProp);
190 
191   aParams->SetBooleanValue(STATE_ENABLED, NS_SUCCEEDED(rv));
192   aParams->SetBooleanValue(STATE_ALL, allOfSelectionHasProp);
193   aParams->SetBooleanValue(STATE_ANY, anyOfSelectionHasProp);
194   aParams->SetBooleanValue(STATE_MIXED, anyOfSelectionHasProp
195            && !allOfSelectionHasProp);
196   aParams->SetBooleanValue(STATE_BEGIN, firstOfSelectionHasProp);
197   aParams->SetBooleanValue(STATE_END, allOfSelectionHasProp);//not completely accurate
198   return NS_OK;
199 }
200 
201 nsresult
ToggleState(nsIEditor * aEditor)202 nsStyleUpdatingCommand::ToggleState(nsIEditor *aEditor)
203 {
204   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
205   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NO_INTERFACE);
206 
207   //create some params now...
208   nsresult rv;
209   nsCOMPtr<nsICommandParams> params =
210       do_CreateInstance(NS_COMMAND_PARAMS_CONTRACTID,&rv);
211   if (NS_FAILED(rv) || !params)
212     return rv;
213 
214   // tags "href" and "name" are special cases in the core editor
215   // they are used to remove named anchor/link and shouldn't be used for insertion
216   bool doTagRemoval;
217   if (mTagName == nsGkAtoms::href || mTagName == nsGkAtoms::name) {
218     doTagRemoval = true;
219   } else {
220     // check current selection; set doTagRemoval if formatting should be removed
221     rv = GetCurrentState(aEditor, params);
222     NS_ENSURE_SUCCESS(rv, rv);
223     rv = params->GetBooleanValue(STATE_ALL, &doTagRemoval);
224     NS_ENSURE_SUCCESS(rv, rv);
225   }
226 
227   if (doTagRemoval) {
228     // Also remove equivalent properties (bug 317093)
229     if (mTagName == nsGkAtoms::b) {
230       rv = RemoveTextProperty(htmlEditor, NS_LITERAL_STRING("strong"));
231       NS_ENSURE_SUCCESS(rv, rv);
232     } else if (mTagName == nsGkAtoms::i) {
233       rv = RemoveTextProperty(htmlEditor, NS_LITERAL_STRING("em"));
234       NS_ENSURE_SUCCESS(rv, rv);
235     } else if (mTagName == nsGkAtoms::strike) {
236       rv = RemoveTextProperty(htmlEditor, NS_LITERAL_STRING("s"));
237       NS_ENSURE_SUCCESS(rv, rv);
238     }
239 
240     rv = RemoveTextProperty(htmlEditor, nsDependentAtomString(mTagName));
241   } else {
242     // Superscript and Subscript styles are mutually exclusive
243     aEditor->BeginTransaction();
244 
245     nsDependentAtomString tagName(mTagName);
246     if (mTagName == nsGkAtoms::sub || mTagName == nsGkAtoms::sup) {
247       rv = RemoveTextProperty(htmlEditor, tagName);
248     }
249     if (NS_SUCCEEDED(rv))
250       rv = SetTextProperty(htmlEditor, tagName);
251 
252     aEditor->EndTransaction();
253   }
254 
255   return rv;
256 }
257 
nsListCommand(nsIAtom * aTagName)258 nsListCommand::nsListCommand(nsIAtom* aTagName)
259 : nsBaseStateUpdatingCommand(aTagName)
260 {
261 }
262 
263 nsresult
GetCurrentState(nsIEditor * aEditor,nsICommandParams * aParams)264 nsListCommand::GetCurrentState(nsIEditor* aEditor, nsICommandParams* aParams)
265 {
266   NS_ASSERTION(aEditor, "Need editor here");
267   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
268   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NO_INTERFACE);
269 
270   bool bMixed;
271   nsAutoString localName;
272   nsresult rv = GetListState(htmlEditor, &bMixed, localName);
273   NS_ENSURE_SUCCESS(rv, rv);
274 
275   bool inList = mTagName->Equals(localName);
276   aParams->SetBooleanValue(STATE_ALL, !bMixed && inList);
277   aParams->SetBooleanValue(STATE_MIXED, bMixed);
278   aParams->SetBooleanValue(STATE_ENABLED, true);
279   return NS_OK;
280 }
281 
282 nsresult
ToggleState(nsIEditor * aEditor)283 nsListCommand::ToggleState(nsIEditor *aEditor)
284 {
285   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(aEditor);
286   NS_ENSURE_TRUE(editor, NS_NOINTERFACE);
287 
288   nsresult rv;
289   nsCOMPtr<nsICommandParams> params =
290       do_CreateInstance(NS_COMMAND_PARAMS_CONTRACTID,&rv);
291   if (NS_FAILED(rv) || !params)
292     return rv;
293 
294   rv = GetCurrentState(aEditor, params);
295   NS_ENSURE_SUCCESS(rv, rv);
296 
297   bool inList;
298   rv = params->GetBooleanValue(STATE_ALL,&inList);
299   NS_ENSURE_SUCCESS(rv, rv);
300 
301   nsDependentAtomString listType(mTagName);
302   if (inList) {
303     rv = editor->RemoveList(listType);
304   } else {
305     rv = editor->MakeOrChangeList(listType, false, EmptyString());
306   }
307 
308   return rv;
309 }
310 
nsListItemCommand(nsIAtom * aTagName)311 nsListItemCommand::nsListItemCommand(nsIAtom* aTagName)
312 : nsBaseStateUpdatingCommand(aTagName)
313 {
314 }
315 
316 nsresult
GetCurrentState(nsIEditor * aEditor,nsICommandParams * aParams)317 nsListItemCommand::GetCurrentState(nsIEditor* aEditor,
318                                    nsICommandParams *aParams)
319 {
320   NS_ASSERTION(aEditor, "Need editor here");
321   // 39584
322   nsCOMPtr<nsIHTMLEditor>  htmlEditor = do_QueryInterface(aEditor);
323   NS_ENSURE_TRUE(htmlEditor, NS_NOINTERFACE);
324 
325   bool bMixed, bLI, bDT, bDD;
326   nsresult rv = htmlEditor->GetListItemState(&bMixed, &bLI, &bDT, &bDD);
327   NS_ENSURE_SUCCESS(rv, rv);
328 
329   bool inList = false;
330   if (!bMixed) {
331     if (bLI) {
332       inList = mTagName == nsGkAtoms::li;
333     } else if (bDT) {
334       inList = mTagName == nsGkAtoms::dt;
335     } else if (bDD) {
336       inList = mTagName == nsGkAtoms::dd;
337     }
338   }
339 
340   aParams->SetBooleanValue(STATE_ALL, !bMixed && inList);
341   aParams->SetBooleanValue(STATE_MIXED, bMixed);
342 
343   return NS_OK;
344 }
345 
346 nsresult
ToggleState(nsIEditor * aEditor)347 nsListItemCommand::ToggleState(nsIEditor *aEditor)
348 {
349   NS_ASSERTION(aEditor, "Need editor here");
350   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
351   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NOT_INITIALIZED);
352 
353   bool inList;
354   // Need to use mTagName????
355   nsresult rv;
356   nsCOMPtr<nsICommandParams> params =
357       do_CreateInstance(NS_COMMAND_PARAMS_CONTRACTID,&rv);
358   if (NS_FAILED(rv) || !params)
359     return rv;
360   rv = GetCurrentState(aEditor, params);
361   rv = params->GetBooleanValue(STATE_ALL,&inList);
362   NS_ENSURE_SUCCESS(rv, rv);
363   NS_ENSURE_SUCCESS(rv, rv);
364 
365   if (inList) {
366     // To remove a list, first get what kind of list we're in
367     bool bMixed;
368     nsAutoString localName;
369     rv = GetListState(htmlEditor, &bMixed, localName);
370     NS_ENSURE_SUCCESS(rv, rv);
371     if (localName.IsEmpty() || bMixed) {
372       return rv;
373     }
374     return htmlEditor->RemoveList(localName);
375   }
376 
377   // Set to the requested paragraph type
378   //XXX Note: This actually doesn't work for "LI",
379   //    but we currently don't use this for non DL lists anyway.
380   // Problem: won't this replace any current block paragraph style?
381   return htmlEditor->SetParagraphFormat(nsDependentAtomString(mTagName));
382 }
383 
384 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * refCon,bool * outCmdEnabled)385 nsRemoveListCommand::IsCommandEnabled(const char * aCommandName,
386                                       nsISupports *refCon,
387                                       bool *outCmdEnabled)
388 {
389   *outCmdEnabled = false;
390   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
391   NS_ENSURE_TRUE(editor, NS_OK);
392 
393   bool isEditable = false;
394   nsresult rv = editor->GetIsSelectionEditable(&isEditable);
395   NS_ENSURE_SUCCESS(rv, rv);
396   if (!isEditable) {
397     return NS_OK;
398   }
399 
400   // It is enabled if we are in any list type
401   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(refCon);
402   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NO_INTERFACE);
403 
404   bool bMixed;
405   nsAutoString localName;
406   rv = GetListState(htmlEditor, &bMixed, localName);
407   NS_ENSURE_SUCCESS(rv, rv);
408 
409   *outCmdEnabled = bMixed || !localName.IsEmpty();
410   return NS_OK;
411 }
412 
413 
414 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * refCon)415 nsRemoveListCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
416 {
417   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
418 
419   nsresult rv = NS_OK;
420   if (editor) {
421     // This removes any list type
422     rv = editor->RemoveList(EmptyString());
423   }
424 
425   return rv;
426 }
427 
428 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)429 nsRemoveListCommand::DoCommandParams(const char *aCommandName,
430                                      nsICommandParams *aParams,
431                                      nsISupports *refCon)
432 {
433   return DoCommand(aCommandName, refCon);
434 }
435 
436 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)437 nsRemoveListCommand::GetCommandStateParams(const char *aCommandName,
438                                            nsICommandParams *aParams,
439                                            nsISupports *refCon)
440 {
441   bool outCmdEnabled = false;
442   IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
443   return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled);
444 }
445 
446 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * refCon,bool * outCmdEnabled)447 nsIndentCommand::IsCommandEnabled(const char * aCommandName,
448                                   nsISupports *refCon, bool *outCmdEnabled)
449 {
450   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
451   if (editor)
452     return editor->GetIsSelectionEditable(outCmdEnabled);
453 
454   *outCmdEnabled = false;
455   return NS_OK;
456 }
457 
458 
459 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * refCon)460 nsIndentCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
461 {
462   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
463 
464   nsresult rv = NS_OK;
465   if (editor) {
466     rv = editor->Indent(NS_LITERAL_STRING("indent"));
467   }
468 
469   return rv;
470 }
471 
472 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)473 nsIndentCommand::DoCommandParams(const char *aCommandName,
474                                  nsICommandParams *aParams,
475                                  nsISupports *refCon)
476 {
477   return DoCommand(aCommandName, refCon);
478 }
479 
480 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)481 nsIndentCommand::GetCommandStateParams(const char *aCommandName,
482                                        nsICommandParams *aParams,
483                                        nsISupports *refCon)
484 {
485   bool outCmdEnabled = false;
486   IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
487   return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled);
488 }
489 
490 
491 //OUTDENT
492 
493 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * refCon,bool * outCmdEnabled)494 nsOutdentCommand::IsCommandEnabled(const char * aCommandName,
495                                    nsISupports *refCon,
496                                    bool *outCmdEnabled)
497 {
498   *outCmdEnabled = false;
499 
500   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
501   if (editor) {
502     nsresult rv = editor->GetIsSelectionEditable(outCmdEnabled);
503     NS_ENSURE_SUCCESS(rv, rv);
504   }
505 
506   return NS_OK;
507 }
508 
509 
510 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * refCon)511 nsOutdentCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
512 {
513   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(refCon);
514   if (htmlEditor)
515     return htmlEditor->Indent(NS_LITERAL_STRING("outdent"));
516 
517   return NS_OK;
518 }
519 
520 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)521 nsOutdentCommand::DoCommandParams(const char *aCommandName,
522                                   nsICommandParams *aParams,
523                                   nsISupports *refCon)
524 {
525   return DoCommand(aCommandName, refCon);
526 }
527 
528 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)529 nsOutdentCommand::GetCommandStateParams(const char *aCommandName,
530                                         nsICommandParams *aParams,
531                                         nsISupports *refCon)
532 {
533   bool outCmdEnabled = false;
534   IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
535   return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled);
536 }
537 
nsMultiStateCommand()538 nsMultiStateCommand::nsMultiStateCommand()
539 : nsBaseComposerCommand()
540 {
541 }
542 
~nsMultiStateCommand()543 nsMultiStateCommand::~nsMultiStateCommand()
544 {
545 }
546 
NS_IMPL_ISUPPORTS_INHERITED0(nsMultiStateCommand,nsBaseComposerCommand)547 NS_IMPL_ISUPPORTS_INHERITED0(nsMultiStateCommand, nsBaseComposerCommand)
548 
549 NS_IMETHODIMP
550 nsMultiStateCommand::IsCommandEnabled(const char * aCommandName,
551                                       nsISupports *refCon,
552                                       bool *outCmdEnabled)
553 {
554   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
555   // should be disabled sometimes, like if the current selection is an image
556   if (editor)
557     return editor->GetIsSelectionEditable(outCmdEnabled);
558 
559   *outCmdEnabled = false;
560   return NS_OK;
561 }
562 
563 
564 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * refCon)565 nsMultiStateCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
566 {
567 #ifdef DEBUG
568   printf("who is calling nsMultiStateCommand::DoCommand \
569           (no implementation)? %s\n", aCommandName);
570 #endif
571 
572   return NS_OK;
573 }
574 
575 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)576 nsMultiStateCommand::DoCommandParams(const char *aCommandName,
577                                      nsICommandParams *aParams,
578                                      nsISupports *refCon)
579 {
580   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
581 
582   nsresult rv = NS_OK;
583   if (editor) {
584       nsAutoString tString;
585 
586       if (aParams) {
587         nsXPIDLCString s;
588         rv = aParams->GetCStringValue(STATE_ATTRIBUTE, getter_Copies(s));
589         if (NS_SUCCEEDED(rv))
590           tString.AssignWithConversion(s);
591         else
592           rv = aParams->GetStringValue(STATE_ATTRIBUTE, tString);
593       }
594 
595       rv = SetState(editor, tString);
596   }
597 
598   return rv;
599 }
600 
601 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)602 nsMultiStateCommand::GetCommandStateParams(const char *aCommandName,
603                                            nsICommandParams *aParams,
604                                            nsISupports *refCon)
605 {
606   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
607   nsresult rv = NS_OK;
608   if (editor) {
609       rv = GetCurrentState(editor, aParams);
610   }
611   return rv;
612 }
613 
nsParagraphStateCommand()614 nsParagraphStateCommand::nsParagraphStateCommand()
615 : nsMultiStateCommand()
616 {
617 }
618 
619 nsresult
GetCurrentState(nsIEditor * aEditor,nsICommandParams * aParams)620 nsParagraphStateCommand::GetCurrentState(nsIEditor *aEditor,
621                                          nsICommandParams *aParams)
622 {
623   NS_ASSERTION(aEditor, "Need an editor here");
624 
625   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
626   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
627 
628   bool outMixed;
629   nsAutoString outStateString;
630   nsresult rv = htmlEditor->GetParagraphState(&outMixed, outStateString);
631   if (NS_SUCCEEDED(rv)) {
632     nsAutoCString tOutStateString;
633     tOutStateString.AssignWithConversion(outStateString);
634     aParams->SetBooleanValue(STATE_MIXED,outMixed);
635     aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
636   }
637   return rv;
638 }
639 
640 
641 nsresult
SetState(nsIEditor * aEditor,nsString & newState)642 nsParagraphStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
643 {
644   NS_ASSERTION(aEditor, "Need an editor here");
645   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
646   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
647 
648   return htmlEditor->SetParagraphFormat(newState);
649 }
650 
nsFontFaceStateCommand()651 nsFontFaceStateCommand::nsFontFaceStateCommand()
652 : nsMultiStateCommand()
653 {
654 }
655 
656 nsresult
GetCurrentState(nsIEditor * aEditor,nsICommandParams * aParams)657 nsFontFaceStateCommand::GetCurrentState(nsIEditor *aEditor,
658                                         nsICommandParams *aParams)
659 {
660   NS_ASSERTION(aEditor, "Need an editor here");
661   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
662   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
663 
664   nsAutoString outStateString;
665   bool outMixed;
666   nsresult rv = htmlEditor->GetFontFaceState(&outMixed, outStateString);
667   if (NS_SUCCEEDED(rv)) {
668     aParams->SetBooleanValue(STATE_MIXED,outMixed);
669     aParams->SetCStringValue(STATE_ATTRIBUTE, NS_ConvertUTF16toUTF8(outStateString).get());
670   }
671   return rv;
672 }
673 
674 
675 nsresult
SetState(nsIEditor * aEditor,nsString & newState)676 nsFontFaceStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
677 {
678   NS_ASSERTION(aEditor, "Need an editor here");
679   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
680   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
681 
682   if (newState.EqualsLiteral("tt")) {
683     // The old "teletype" attribute
684     nsresult rv = htmlEditor->SetInlineProperty(nsGkAtoms::tt, EmptyString(),
685                                                 EmptyString());
686     NS_ENSURE_SUCCESS(rv, rv);
687     // Clear existing font face
688     return htmlEditor->RemoveInlineProperty(nsGkAtoms::font,
689                                             NS_LITERAL_STRING("face"));
690   }
691 
692   // Remove any existing TT nodes
693   nsresult rv = htmlEditor->RemoveInlineProperty(nsGkAtoms::tt, EmptyString());
694   NS_ENSURE_SUCCESS(rv, rv);
695 
696   if (newState.IsEmpty() || newState.EqualsLiteral("normal")) {
697     return htmlEditor->RemoveInlineProperty(nsGkAtoms::font,
698                                             NS_LITERAL_STRING("face"));
699   }
700 
701   return htmlEditor->SetInlineProperty(nsGkAtoms::font,
702                                        NS_LITERAL_STRING("face"), newState);
703 }
704 
nsFontSizeStateCommand()705 nsFontSizeStateCommand::nsFontSizeStateCommand()
706   : nsMultiStateCommand()
707 {
708 }
709 
710 //  nsAutoCString tOutStateString;
711 //  tOutStateString.AssignWithConversion(outStateString);
712 nsresult
GetCurrentState(nsIEditor * aEditor,nsICommandParams * aParams)713 nsFontSizeStateCommand::GetCurrentState(nsIEditor *aEditor,
714                                         nsICommandParams *aParams)
715 {
716   NS_ASSERTION(aEditor, "Need an editor here");
717   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
718   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_INVALID_ARG);
719 
720   nsAutoString outStateString;
721   nsCOMPtr<nsIAtom> fontAtom = NS_Atomize("font");
722   bool firstHas, anyHas, allHas;
723   nsresult rv = htmlEditor->GetInlinePropertyWithAttrValue(fontAtom,
724                                          NS_LITERAL_STRING("size"),
725                                          EmptyString(),
726                                          &firstHas, &anyHas, &allHas,
727                                          outStateString);
728   NS_ENSURE_SUCCESS(rv, rv);
729 
730   nsAutoCString tOutStateString;
731   tOutStateString.AssignWithConversion(outStateString);
732   aParams->SetBooleanValue(STATE_MIXED, anyHas && !allHas);
733   aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
734   aParams->SetBooleanValue(STATE_ENABLED, true);
735 
736   return rv;
737 }
738 
739 
740 // acceptable values for "newState" are:
741 //   -2
742 //   -1
743 //    0
744 //   +1
745 //   +2
746 //   +3
747 //   medium
748 //   normal
749 nsresult
SetState(nsIEditor * aEditor,nsString & newState)750 nsFontSizeStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
751 {
752   NS_ASSERTION(aEditor, "Need an editor here");
753   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
754   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_INVALID_ARG);
755 
756   if (!newState.IsEmpty() &&
757       !newState.EqualsLiteral("normal") &&
758       !newState.EqualsLiteral("medium")) {
759     return htmlEditor->SetInlineProperty(nsGkAtoms::font,
760                                          NS_LITERAL_STRING("size"), newState);
761   }
762 
763   // remove any existing font size, big or small
764   nsresult rv = htmlEditor->RemoveInlineProperty(nsGkAtoms::font,
765                                                  NS_LITERAL_STRING("size"));
766   NS_ENSURE_SUCCESS(rv, rv);
767 
768   rv = htmlEditor->RemoveInlineProperty(nsGkAtoms::big, EmptyString());
769   NS_ENSURE_SUCCESS(rv, rv);
770 
771   return htmlEditor->RemoveInlineProperty(nsGkAtoms::small, EmptyString());
772 }
773 
nsFontColorStateCommand()774 nsFontColorStateCommand::nsFontColorStateCommand()
775 : nsMultiStateCommand()
776 {
777 }
778 
779 nsresult
GetCurrentState(nsIEditor * aEditor,nsICommandParams * aParams)780 nsFontColorStateCommand::GetCurrentState(nsIEditor *aEditor,
781                                          nsICommandParams *aParams)
782 {
783   NS_ASSERTION(aEditor, "Need an editor here");
784 
785   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
786   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
787 
788   bool outMixed;
789   nsAutoString outStateString;
790   nsresult rv = htmlEditor->GetFontColorState(&outMixed, outStateString);
791   NS_ENSURE_SUCCESS(rv, rv);
792 
793   nsAutoCString tOutStateString;
794   tOutStateString.AssignWithConversion(outStateString);
795   aParams->SetBooleanValue(STATE_MIXED, outMixed);
796   aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
797   return NS_OK;
798 }
799 
800 nsresult
SetState(nsIEditor * aEditor,nsString & newState)801 nsFontColorStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
802 {
803   NS_ASSERTION(aEditor, "Need an editor here");
804   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
805   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
806 
807   if (newState.IsEmpty() || newState.EqualsLiteral("normal")) {
808     return htmlEditor->RemoveInlineProperty(nsGkAtoms::font,
809                                             NS_LITERAL_STRING("color"));
810   }
811 
812   return htmlEditor->SetInlineProperty(nsGkAtoms::font,
813                                        NS_LITERAL_STRING("color"), newState);
814 }
815 
nsHighlightColorStateCommand()816 nsHighlightColorStateCommand::nsHighlightColorStateCommand()
817 : nsMultiStateCommand()
818 {
819 }
820 
821 nsresult
GetCurrentState(nsIEditor * aEditor,nsICommandParams * aParams)822 nsHighlightColorStateCommand::GetCurrentState(nsIEditor *aEditor,
823                                               nsICommandParams *aParams)
824 {
825   NS_ASSERTION(aEditor, "Need an editor here");
826   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
827   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
828 
829   bool outMixed;
830   nsAutoString outStateString;
831   nsresult rv = htmlEditor->GetHighlightColorState(&outMixed, outStateString);
832   NS_ENSURE_SUCCESS(rv, rv);
833 
834   nsAutoCString tOutStateString;
835   tOutStateString.AssignWithConversion(outStateString);
836   aParams->SetBooleanValue(STATE_MIXED, outMixed);
837   aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
838   return NS_OK;
839 }
840 
841 nsresult
SetState(nsIEditor * aEditor,nsString & newState)842 nsHighlightColorStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
843 {
844   NS_ASSERTION(aEditor, "Need an editor here");
845   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
846   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
847 
848   if (newState.IsEmpty() || newState.EqualsLiteral("normal")) {
849     return htmlEditor->RemoveInlineProperty(nsGkAtoms::font,
850                                             NS_LITERAL_STRING("bgcolor"));
851   }
852 
853   return htmlEditor->SetInlineProperty(nsGkAtoms::font,
854                                        NS_LITERAL_STRING("bgcolor"),
855                                        newState);
856 }
857 
858 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * refCon,bool * outCmdEnabled)859 nsHighlightColorStateCommand::IsCommandEnabled(const char * aCommandName,
860                                                nsISupports *refCon,
861                                                bool *outCmdEnabled)
862 {
863   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
864   if (editor)
865     return editor->GetIsSelectionEditable(outCmdEnabled);
866 
867   *outCmdEnabled = false;
868   return NS_OK;
869 }
870 
871 
nsBackgroundColorStateCommand()872 nsBackgroundColorStateCommand::nsBackgroundColorStateCommand()
873 : nsMultiStateCommand()
874 {
875 }
876 
877 nsresult
GetCurrentState(nsIEditor * aEditor,nsICommandParams * aParams)878 nsBackgroundColorStateCommand::GetCurrentState(nsIEditor *aEditor,
879                                                nsICommandParams *aParams)
880 {
881   NS_ASSERTION(aEditor, "Need an editor here");
882 
883   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
884   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
885 
886   bool outMixed;
887   nsAutoString outStateString;
888   nsresult rv =  htmlEditor->GetBackgroundColorState(&outMixed, outStateString);
889   NS_ENSURE_SUCCESS(rv, rv);
890 
891   nsAutoCString tOutStateString;
892   tOutStateString.AssignWithConversion(outStateString);
893   aParams->SetBooleanValue(STATE_MIXED, outMixed);
894   aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
895   return NS_OK;
896 }
897 
898 nsresult
SetState(nsIEditor * aEditor,nsString & newState)899 nsBackgroundColorStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
900 {
901   NS_ASSERTION(aEditor, "Need an editor here");
902 
903   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
904   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
905 
906   return htmlEditor->SetBackgroundColor(newState);
907 }
908 
nsAlignCommand()909 nsAlignCommand::nsAlignCommand()
910 : nsMultiStateCommand()
911 {
912 }
913 
914 nsresult
GetCurrentState(nsIEditor * aEditor,nsICommandParams * aParams)915 nsAlignCommand::GetCurrentState(nsIEditor *aEditor, nsICommandParams *aParams)
916 {
917   NS_ASSERTION(aEditor, "Need an editor here");
918 
919   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
920   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
921 
922   nsIHTMLEditor::EAlignment firstAlign;
923   bool outMixed;
924   nsresult rv = htmlEditor->GetAlignment(&outMixed, &firstAlign);
925 
926   NS_ENSURE_SUCCESS(rv, rv);
927 
928   nsAutoString outStateString;
929   switch (firstAlign) {
930     default:
931     case nsIHTMLEditor::eLeft:
932       outStateString.AssignLiteral("left");
933       break;
934 
935     case nsIHTMLEditor::eCenter:
936       outStateString.AssignLiteral("center");
937       break;
938 
939     case nsIHTMLEditor::eRight:
940       outStateString.AssignLiteral("right");
941       break;
942 
943     case nsIHTMLEditor::eJustify:
944       outStateString.AssignLiteral("justify");
945       break;
946   }
947   nsAutoCString tOutStateString;
948   tOutStateString.AssignWithConversion(outStateString);
949   aParams->SetBooleanValue(STATE_MIXED,outMixed);
950   aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
951   return NS_OK;
952 }
953 
954 nsresult
SetState(nsIEditor * aEditor,nsString & newState)955 nsAlignCommand::SetState(nsIEditor *aEditor, nsString& newState)
956 {
957   NS_ASSERTION(aEditor, "Need an editor here");
958 
959   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
960   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
961 
962   return htmlEditor->Align(newState);
963 }
964 
nsAbsolutePositioningCommand()965 nsAbsolutePositioningCommand::nsAbsolutePositioningCommand()
966 : nsBaseStateUpdatingCommand(nsGkAtoms::_empty)
967 {
968 }
969 
970 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * aCommandRefCon,bool * outCmdEnabled)971 nsAbsolutePositioningCommand::IsCommandEnabled(const char * aCommandName,
972                                                nsISupports *aCommandRefCon,
973                                                bool *outCmdEnabled)
974 {
975   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
976   nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(aCommandRefCon);
977   if (htmlEditor) {
978     bool isEditable = false;
979     nsresult rv = editor->GetIsSelectionEditable(&isEditable);
980     NS_ENSURE_SUCCESS(rv, rv);
981     if (isEditable)
982       return htmlEditor->GetAbsolutePositioningEnabled(outCmdEnabled);
983   }
984 
985   *outCmdEnabled = false;
986   return NS_OK;
987 }
988 
989 nsresult
GetCurrentState(nsIEditor * aEditor,nsICommandParams * aParams)990 nsAbsolutePositioningCommand::GetCurrentState(nsIEditor *aEditor, nsICommandParams *aParams)
991 {
992   NS_ASSERTION(aEditor, "Need an editor here");
993 
994   nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(aEditor);
995   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
996 
997   bool isEnabled;
998   htmlEditor->GetAbsolutePositioningEnabled(&isEnabled);
999   if (!isEnabled) {
1000     aParams->SetBooleanValue(STATE_MIXED,false);
1001     aParams->SetCStringValue(STATE_ATTRIBUTE, "");
1002     return NS_OK;
1003   }
1004 
1005   nsCOMPtr<nsIDOMElement>  elt;
1006   nsresult rv = htmlEditor->GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(elt));
1007   NS_ENSURE_SUCCESS(rv, rv);
1008 
1009   nsAutoString outStateString;
1010   if (elt)
1011     outStateString.AssignLiteral("absolute");
1012 
1013   aParams->SetBooleanValue(STATE_MIXED,false);
1014   aParams->SetCStringValue(STATE_ATTRIBUTE, NS_ConvertUTF16toUTF8(outStateString).get());
1015   return NS_OK;
1016 }
1017 
1018 nsresult
ToggleState(nsIEditor * aEditor)1019 nsAbsolutePositioningCommand::ToggleState(nsIEditor *aEditor)
1020 {
1021   NS_ASSERTION(aEditor, "Need an editor here");
1022 
1023   nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(aEditor);
1024   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
1025 
1026   nsCOMPtr<nsIDOMElement> elt;
1027   nsresult rv = htmlEditor->GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(elt));
1028   NS_ENSURE_SUCCESS(rv, rv);
1029 
1030   return htmlEditor->AbsolutePositionSelection(!elt);
1031 }
1032 
1033 
1034 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * refCon,bool * outCmdEnabled)1035 nsDecreaseZIndexCommand::IsCommandEnabled(const char * aCommandName,
1036                                           nsISupports *refCon,
1037                                           bool *outCmdEnabled)
1038 {
1039   nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon);
1040   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
1041 
1042   htmlEditor->GetAbsolutePositioningEnabled(outCmdEnabled);
1043   if (!(*outCmdEnabled))
1044     return NS_OK;
1045 
1046   nsCOMPtr<nsIDOMElement> positionedElement;
1047   htmlEditor->GetPositionedElement(getter_AddRefs(positionedElement));
1048   *outCmdEnabled = false;
1049   if (positionedElement) {
1050     int32_t z;
1051     nsresult rv = htmlEditor->GetElementZIndex(positionedElement, &z);
1052     NS_ENSURE_SUCCESS(rv, rv);
1053     *outCmdEnabled = (z > 0);
1054   }
1055 
1056   return NS_OK;
1057 }
1058 
1059 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * refCon)1060 nsDecreaseZIndexCommand::DoCommand(const char *aCommandName,
1061                                    nsISupports *refCon)
1062 {
1063   nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon);
1064   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NOT_IMPLEMENTED);
1065 
1066   return htmlEditor->RelativeChangeZIndex(-1);
1067 }
1068 
1069 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)1070 nsDecreaseZIndexCommand::DoCommandParams(const char *aCommandName,
1071                                          nsICommandParams *aParams,
1072                                          nsISupports *refCon)
1073 {
1074   return DoCommand(aCommandName, refCon);
1075 }
1076 
1077 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)1078 nsDecreaseZIndexCommand::GetCommandStateParams(const char *aCommandName,
1079                                                nsICommandParams *aParams,
1080                                                nsISupports *refCon)
1081 {
1082   NS_ENSURE_ARG_POINTER(aParams);
1083 
1084   bool enabled = false;
1085   nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled);
1086   NS_ENSURE_SUCCESS(rv, rv);
1087 
1088   return aParams->SetBooleanValue(STATE_ENABLED, enabled);
1089 }
1090 
1091 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * refCon,bool * outCmdEnabled)1092 nsIncreaseZIndexCommand::IsCommandEnabled(const char * aCommandName,
1093                                           nsISupports *refCon,
1094                                           bool *outCmdEnabled)
1095 {
1096   nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon);
1097   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
1098 
1099   htmlEditor->GetAbsolutePositioningEnabled(outCmdEnabled);
1100   if (!(*outCmdEnabled))
1101     return NS_OK;
1102 
1103   nsCOMPtr<nsIDOMElement> positionedElement;
1104   htmlEditor->GetPositionedElement(getter_AddRefs(positionedElement));
1105   *outCmdEnabled = (nullptr != positionedElement);
1106   return NS_OK;
1107 }
1108 
1109 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * refCon)1110 nsIncreaseZIndexCommand::DoCommand(const char *aCommandName,
1111                                    nsISupports *refCon)
1112 {
1113   nsCOMPtr<nsIHTMLAbsPosEditor> htmlEditor = do_QueryInterface(refCon);
1114   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_NOT_IMPLEMENTED);
1115 
1116   return htmlEditor->RelativeChangeZIndex(1);
1117 }
1118 
1119 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)1120 nsIncreaseZIndexCommand::DoCommandParams(const char *aCommandName,
1121                                          nsICommandParams *aParams,
1122                                          nsISupports *refCon)
1123 {
1124   return DoCommand(aCommandName, refCon);
1125 }
1126 
1127 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)1128 nsIncreaseZIndexCommand::GetCommandStateParams(const char *aCommandName,
1129                                                nsICommandParams *aParams,
1130                                                nsISupports *refCon)
1131 {
1132   NS_ENSURE_ARG_POINTER(aParams);
1133 
1134   bool enabled = false;
1135   nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled);
1136   NS_ENSURE_SUCCESS(rv, rv);
1137 
1138   return aParams->SetBooleanValue(STATE_ENABLED, enabled);
1139 }
1140 
1141 
1142 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * refCon,bool * outCmdEnabled)1143 nsRemoveStylesCommand::IsCommandEnabled(const char * aCommandName,
1144                                         nsISupports *refCon,
1145                                         bool *outCmdEnabled)
1146 {
1147   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
1148   // test if we have any styles?
1149   if (editor)
1150     return editor->GetIsSelectionEditable(outCmdEnabled);
1151 
1152   *outCmdEnabled = false;
1153   return NS_OK;
1154 }
1155 
1156 
1157 
1158 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * refCon)1159 nsRemoveStylesCommand::DoCommand(const char *aCommandName,
1160                                  nsISupports *refCon)
1161 {
1162   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
1163 
1164   nsresult rv = NS_OK;
1165   if (editor) {
1166     rv = editor->RemoveAllInlineProperties();
1167   }
1168 
1169   return rv;
1170 }
1171 
1172 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)1173 nsRemoveStylesCommand::DoCommandParams(const char *aCommandName,
1174                                        nsICommandParams *aParams,
1175                                        nsISupports *refCon)
1176 {
1177   return DoCommand(aCommandName, refCon);
1178 }
1179 
1180 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)1181 nsRemoveStylesCommand::GetCommandStateParams(const char *aCommandName,
1182                                              nsICommandParams *aParams,
1183                                              nsISupports *refCon)
1184 {
1185   bool outCmdEnabled = false;
1186   IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
1187   return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled);
1188 }
1189 
1190 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * refCon,bool * outCmdEnabled)1191 nsIncreaseFontSizeCommand::IsCommandEnabled(const char * aCommandName,
1192                                             nsISupports *refCon,
1193                                             bool *outCmdEnabled)
1194 {
1195   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
1196   // test if we are at max size?
1197   if (editor)
1198     return editor->GetIsSelectionEditable(outCmdEnabled);
1199 
1200   *outCmdEnabled = false;
1201   return NS_OK;
1202 }
1203 
1204 
1205 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * refCon)1206 nsIncreaseFontSizeCommand::DoCommand(const char *aCommandName,
1207                                      nsISupports *refCon)
1208 {
1209   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
1210 
1211   nsresult rv = NS_OK;
1212   if (editor) {
1213     rv = editor->IncreaseFontSize();
1214   }
1215 
1216   return rv;
1217 }
1218 
1219 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)1220 nsIncreaseFontSizeCommand::DoCommandParams(const char *aCommandName,
1221                                            nsICommandParams *aParams,
1222                                            nsISupports *refCon)
1223 {
1224   return DoCommand(aCommandName, refCon);
1225 }
1226 
1227 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)1228 nsIncreaseFontSizeCommand::GetCommandStateParams(const char *aCommandName,
1229                                                  nsICommandParams *aParams,
1230                                                  nsISupports *refCon)
1231 {
1232   bool outCmdEnabled = false;
1233   IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
1234   return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled);
1235 }
1236 
1237 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * refCon,bool * outCmdEnabled)1238 nsDecreaseFontSizeCommand::IsCommandEnabled(const char * aCommandName,
1239                                             nsISupports *refCon,
1240                                             bool *outCmdEnabled)
1241 {
1242   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
1243   // test if we are at min size?
1244   if (editor)
1245     return editor->GetIsSelectionEditable(outCmdEnabled);
1246 
1247   *outCmdEnabled = false;
1248   return NS_OK;
1249 }
1250 
1251 
1252 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * refCon)1253 nsDecreaseFontSizeCommand::DoCommand(const char *aCommandName,
1254                                      nsISupports *refCon)
1255 {
1256   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
1257 
1258   nsresult rv = NS_OK;
1259   if (editor) {
1260     rv = editor->DecreaseFontSize();
1261   }
1262 
1263   return rv;
1264 }
1265 
1266 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)1267 nsDecreaseFontSizeCommand::DoCommandParams(const char *aCommandName,
1268                                            nsICommandParams *aParams,
1269                                            nsISupports *refCon)
1270 {
1271   return DoCommand(aCommandName, refCon);
1272 }
1273 
1274 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)1275 nsDecreaseFontSizeCommand::GetCommandStateParams(const char *aCommandName,
1276                                                  nsICommandParams *aParams,
1277                                                  nsISupports *refCon)
1278 {
1279   bool outCmdEnabled = false;
1280   IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
1281   return aParams->SetBooleanValue(STATE_ENABLED,outCmdEnabled);
1282 }
1283 
1284 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * refCon,bool * outCmdEnabled)1285 nsInsertHTMLCommand::IsCommandEnabled(const char * aCommandName,
1286                                       nsISupports *refCon,
1287                                       bool *outCmdEnabled)
1288 {
1289   NS_ENSURE_ARG_POINTER(outCmdEnabled);
1290   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
1291   if (editor)
1292     return editor->GetIsSelectionEditable(outCmdEnabled);
1293 
1294   *outCmdEnabled = false;
1295   return NS_OK;
1296 }
1297 
1298 
1299 NS_IMETHODIMP
DoCommand(const char * aCommandName,nsISupports * refCon)1300 nsInsertHTMLCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
1301 {
1302   // If nsInsertHTMLCommand is called with no parameters, it was probably called with
1303   // an empty string parameter ''. In this case, it should act the same as the delete command
1304   NS_ENSURE_ARG_POINTER(refCon);
1305 
1306   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
1307   NS_ENSURE_TRUE(editor, NS_ERROR_NOT_IMPLEMENTED);
1308 
1309   nsString html = EmptyString();
1310   return editor->InsertHTML(html);
1311 }
1312 
1313 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)1314 nsInsertHTMLCommand::DoCommandParams(const char *aCommandName,
1315                                      nsICommandParams *aParams,
1316                                      nsISupports *refCon)
1317 {
1318   NS_ENSURE_ARG_POINTER(aParams);
1319   NS_ENSURE_ARG_POINTER(refCon);
1320 
1321   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
1322   NS_ENSURE_TRUE(editor, NS_ERROR_NOT_IMPLEMENTED);
1323 
1324   // Get HTML source string to insert from command params
1325   nsAutoString html;
1326   nsresult rv = aParams->GetStringValue(STATE_DATA, html);
1327   NS_ENSURE_SUCCESS(rv, rv);
1328 
1329   return editor->InsertHTML(html);
1330 }
1331 
1332 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)1333 nsInsertHTMLCommand::GetCommandStateParams(const char *aCommandName,
1334                                            nsICommandParams *aParams,
1335                                            nsISupports *refCon)
1336 {
1337   NS_ENSURE_ARG_POINTER(aParams);
1338   NS_ENSURE_ARG_POINTER(refCon);
1339 
1340   bool outCmdEnabled = false;
1341   IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
1342   return aParams->SetBooleanValue(STATE_ENABLED, outCmdEnabled);
1343 }
1344 
NS_IMPL_ISUPPORTS_INHERITED0(nsInsertTagCommand,nsBaseComposerCommand)1345 NS_IMPL_ISUPPORTS_INHERITED0(nsInsertTagCommand, nsBaseComposerCommand)
1346 
1347 nsInsertTagCommand::nsInsertTagCommand(nsIAtom* aTagName)
1348 : nsBaseComposerCommand()
1349 , mTagName(aTagName)
1350 {
1351   MOZ_ASSERT(mTagName);
1352 }
1353 
~nsInsertTagCommand()1354 nsInsertTagCommand::~nsInsertTagCommand()
1355 {
1356 }
1357 
1358 NS_IMETHODIMP
IsCommandEnabled(const char * aCommandName,nsISupports * refCon,bool * outCmdEnabled)1359 nsInsertTagCommand::IsCommandEnabled(const char * aCommandName,
1360                                      nsISupports *refCon,
1361                                      bool *outCmdEnabled)
1362 {
1363   NS_ENSURE_ARG_POINTER(outCmdEnabled);
1364   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
1365   if (editor)
1366     return editor->GetIsSelectionEditable(outCmdEnabled);
1367 
1368   *outCmdEnabled = false;
1369   return NS_OK;
1370 }
1371 
1372 
1373 // corresponding STATE_ATTRIBUTE is: src (img) and href (a)
1374 NS_IMETHODIMP
DoCommand(const char * aCmdName,nsISupports * refCon)1375 nsInsertTagCommand::DoCommand(const char *aCmdName, nsISupports *refCon)
1376 {
1377   NS_ENSURE_TRUE(mTagName == nsGkAtoms::hr, NS_ERROR_NOT_IMPLEMENTED);
1378 
1379   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
1380   NS_ENSURE_TRUE(editor, NS_ERROR_NOT_IMPLEMENTED);
1381 
1382   nsCOMPtr<nsIDOMElement> domElem;
1383   nsresult rv = editor->CreateElementWithDefaults(
1384     nsDependentAtomString(mTagName), getter_AddRefs(domElem));
1385   NS_ENSURE_SUCCESS(rv, rv);
1386 
1387   return editor->InsertElementAtSelection(domElem, true);
1388 }
1389 
1390 NS_IMETHODIMP
DoCommandParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)1391 nsInsertTagCommand::DoCommandParams(const char *aCommandName,
1392                                     nsICommandParams *aParams,
1393                                     nsISupports *refCon)
1394 {
1395   NS_ENSURE_ARG_POINTER(refCon);
1396 
1397   // inserting an hr shouldn't have an parameters, just call DoCommand for that
1398   if (mTagName == nsGkAtoms::hr) {
1399     return DoCommand(aCommandName, refCon);
1400   }
1401 
1402   NS_ENSURE_ARG_POINTER(aParams);
1403 
1404   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
1405   NS_ENSURE_TRUE(editor, NS_ERROR_NOT_IMPLEMENTED);
1406 
1407   // do we have an href to use for creating link?
1408   nsXPIDLCString s;
1409   nsresult rv = aParams->GetCStringValue(STATE_ATTRIBUTE, getter_Copies(s));
1410   NS_ENSURE_SUCCESS(rv, rv);
1411   nsAutoString attrib; attrib.AssignWithConversion(s);
1412 
1413   if (attrib.IsEmpty())
1414     return NS_ERROR_INVALID_ARG;
1415 
1416   // filter out tags we don't know how to insert
1417   nsAutoString attributeType;
1418   if (mTagName == nsGkAtoms::a) {
1419     attributeType.AssignLiteral("href");
1420   } else if (mTagName == nsGkAtoms::img) {
1421     attributeType.AssignLiteral("src");
1422   } else {
1423     return NS_ERROR_NOT_IMPLEMENTED;
1424   }
1425 
1426   nsCOMPtr<nsIDOMElement> domElem;
1427   rv = editor->CreateElementWithDefaults(nsDependentAtomString(mTagName),
1428                                          getter_AddRefs(domElem));
1429   NS_ENSURE_SUCCESS(rv, rv);
1430 
1431   rv = domElem->SetAttribute(attributeType, attrib);
1432   NS_ENSURE_SUCCESS(rv, rv);
1433 
1434   // do actual insertion
1435   if (mTagName == nsGkAtoms::a)
1436     return editor->InsertLinkAroundSelection(domElem);
1437 
1438   return editor->InsertElementAtSelection(domElem, true);
1439 }
1440 
1441 NS_IMETHODIMP
GetCommandStateParams(const char * aCommandName,nsICommandParams * aParams,nsISupports * refCon)1442 nsInsertTagCommand::GetCommandStateParams(const char *aCommandName,
1443                                           nsICommandParams *aParams,
1444                                           nsISupports *refCon)
1445 {
1446   NS_ENSURE_ARG_POINTER(aParams);
1447   NS_ENSURE_ARG_POINTER(refCon);
1448 
1449   bool outCmdEnabled = false;
1450   IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
1451   return aParams->SetBooleanValue(STATE_ENABLED, outCmdEnabled);
1452 }
1453 
1454 
1455 /****************************/
1456 //HELPER METHODS
1457 /****************************/
1458 
1459 nsresult
GetListState(nsIHTMLEditor * aEditor,bool * aMixed,nsAString & aLocalName)1460 GetListState(nsIHTMLEditor* aEditor, bool* aMixed, nsAString& aLocalName)
1461 {
1462   MOZ_ASSERT(aEditor);
1463   MOZ_ASSERT(aMixed);
1464 
1465   *aMixed = false;
1466   aLocalName.Truncate();
1467 
1468   bool bOL, bUL, bDL;
1469   nsresult rv = aEditor->GetListState(aMixed, &bOL, &bUL, &bDL);
1470   NS_ENSURE_SUCCESS(rv, rv);
1471 
1472   if (*aMixed) {
1473     return NS_OK;
1474   }
1475 
1476   if (bOL) {
1477     aLocalName.AssignLiteral("ol");
1478   } else if (bUL) {
1479     aLocalName.AssignLiteral("ul");
1480   } else if (bDL) {
1481     aLocalName.AssignLiteral("dl");
1482   }
1483   return NS_OK;
1484 }
1485 
1486 nsresult
RemoveOneProperty(nsIHTMLEditor * aEditor,const nsAString & aProp)1487 RemoveOneProperty(nsIHTMLEditor* aEditor, const nsAString& aProp)
1488 {
1489   MOZ_ASSERT(aEditor);
1490 
1491   /// XXX Hack alert! Look in nsIEditProperty.h for this
1492   nsCOMPtr<nsIAtom> styleAtom = NS_Atomize(aProp);
1493   NS_ENSURE_TRUE(styleAtom, NS_ERROR_OUT_OF_MEMORY);
1494 
1495   return aEditor->RemoveInlineProperty(styleAtom, EmptyString());
1496 }
1497 
1498 
1499 // the name of the attribute here should be the contents of the appropriate
1500 // tag, e.g. 'b' for bold, 'i' for italics.
1501 nsresult
RemoveTextProperty(nsIHTMLEditor * aEditor,const nsAString & aProp)1502 RemoveTextProperty(nsIHTMLEditor* aEditor, const nsAString& aProp)
1503 {
1504   MOZ_ASSERT(aEditor);
1505 
1506   if (aProp.LowerCaseEqualsLiteral("all")) {
1507     return aEditor->RemoveAllInlineProperties();
1508   }
1509 
1510   return RemoveOneProperty(aEditor, aProp);
1511 }
1512 
1513 // the name of the attribute here should be the contents of the appropriate
1514 // tag, e.g. 'b' for bold, 'i' for italics.
1515 nsresult
SetTextProperty(nsIHTMLEditor * aEditor,const nsAString & aProp)1516 SetTextProperty(nsIHTMLEditor* aEditor, const nsAString& aProp)
1517 {
1518   MOZ_ASSERT(aEditor);
1519 
1520   /// XXX Hack alert! Look in nsIEditProperty.h for this
1521   nsCOMPtr<nsIAtom> styleAtom = NS_Atomize(aProp);
1522   NS_ENSURE_TRUE(styleAtom, NS_ERROR_OUT_OF_MEMORY);
1523 
1524   return aEditor->SetInlineProperty(styleAtom, EmptyString(), EmptyString());
1525 }
1526