Coverage Report

Created: 2018-09-25 14:53

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