Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/editor/libeditor/HTMLEditorDocumentCommands.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 "mozilla/HTMLEditor.h"         // for HTMLEditor
8
#include "mozilla/HTMLEditorCommands.h" // for SetDocumentOptionsCommand, etc
9
#include "mozilla/TextEditor.h"         // for TextEditor
10
#include "nsCommandParams.h"            // for nsCommandParams
11
#include "nsCOMPtr.h"                   // for nsCOMPtr, do_QueryInterface, etc
12
#include "nsCRT.h"                      // for nsCRT
13
#include "nsDebug.h"                    // for NS_ENSURE_ARG_POINTER, etc
14
#include "nsError.h"                    // for NS_ERROR_INVALID_ARG, etc
15
#include "nsIDocShell.h"                // for nsIDocShell
16
#include "nsIDocument.h"                // for nsIDocument
17
#include "nsIEditingSession.h"          // for nsIEditingSession, etc
18
#include "nsIEditor.h"                  // for nsIEditor
19
#include "nsIPlaintextEditor.h"         // for nsIPlaintextEditor, etc
20
#include "nsIPresShell.h"               // for nsIPresShell
21
#include "nsISelectionController.h"     // for nsISelectionController
22
#include "nsISupportsImpl.h"            // for nsPresContext::Release
23
#include "nsISupportsUtils.h"           // for NS_IF_ADDREF
24
#include "nsIURI.h"                     // for nsIURI
25
#include "nsPresContext.h"              // for nsPresContext
26
#include "nscore.h"                     // for NS_IMETHODIMP, nsresult, etc
27
28
class nsISupports;
29
30
//defines
31
0
#define STATE_ENABLED  "state_enabled"
32
0
#define STATE_ALL "state_all"
33
0
#define STATE_ATTRIBUTE "state_attribute"
34
0
#define STATE_DATA "state_data"
35
36
namespace mozilla {
37
38
NS_IMETHODIMP
39
SetDocumentOptionsCommand::IsCommandEnabled(const char* aCommandName,
40
                                            nsISupports* refCon,
41
                                            bool* outCmdEnabled)
42
0
{
43
0
  if (NS_WARN_IF(!outCmdEnabled)) {
44
0
    return NS_ERROR_INVALID_ARG;
45
0
  }
46
0
47
0
  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
48
0
  if (!editor) {
49
0
    *outCmdEnabled = false;
50
0
    return NS_OK;
51
0
  }
52
0
  TextEditor* textEditor = editor->AsTextEditor();
53
0
  MOZ_ASSERT(textEditor);
54
0
  *outCmdEnabled = textEditor->IsSelectionEditable();
55
0
  return NS_OK;
56
0
}
57
58
NS_IMETHODIMP
59
SetDocumentOptionsCommand::DoCommand(const char* aCommandName,
60
                                     nsISupports* refCon)
61
0
{
62
0
  return NS_ERROR_NOT_IMPLEMENTED;
63
0
}
64
65
NS_IMETHODIMP
66
SetDocumentOptionsCommand::DoCommandParams(const char* aCommandName,
67
                                           nsICommandParams* aParams,
68
                                           nsISupports* refCon)
69
0
{
70
0
  if (NS_WARN_IF(!aParams)) {
71
0
    return NS_ERROR_INVALID_ARG;
72
0
  }
73
0
74
0
  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
75
0
  if (NS_WARN_IF(!editor)) {
76
0
    return NS_ERROR_INVALID_ARG;
77
0
  }
78
0
  TextEditor* textEditor = editor->AsTextEditor();
79
0
  MOZ_ASSERT(textEditor);
80
0
81
0
  RefPtr<nsPresContext> presContext = textEditor->GetPresContext();
82
0
  if (NS_WARN_IF(!presContext)) {
83
0
    return NS_ERROR_FAILURE;
84
0
  }
85
0
86
0
  nsCommandParams* params = aParams->AsCommandParams();
87
0
88
0
  IgnoredErrorResult error;
89
0
  int32_t animationMode = params->GetInt("imageAnimation", error);
90
0
  if (!error.Failed()) {
91
0
    // for possible values of animation mode, see:
92
0
    // http://lxr.mozilla.org/seamonkey/source/image/public/imgIContainer.idl
93
0
    presContext->SetImageAnimationMode(animationMode);
94
0
  } else {
95
0
    error.SuppressException();
96
0
  }
97
0
98
0
  bool allowPlugins = params->GetBool("plugins", error);
99
0
  if (error.Failed()) {
100
0
    return NS_OK;
101
0
  }
102
0
103
0
  nsCOMPtr<nsIDocShell> docShell(presContext->GetDocShell());
104
0
  if (NS_WARN_IF(!docShell)) {
105
0
    return NS_ERROR_FAILURE;
106
0
  }
107
0
108
0
  nsresult rv = docShell->SetAllowPlugins(allowPlugins);
109
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
110
0
    return rv;
111
0
  }
112
0
  return NS_OK;
113
0
}
114
115
NS_IMETHODIMP
116
SetDocumentOptionsCommand::GetCommandStateParams(const char* aCommandName,
117
                                                 nsICommandParams* aParams,
118
                                                 nsISupports* refCon)
119
0
{
120
0
  if (NS_WARN_IF(!aParams) || NS_WARN_IF(!refCon)) {
121
0
    return NS_ERROR_INVALID_ARG;
122
0
  }
123
0
124
0
  // The base editor owns most state info
125
0
  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
126
0
  if (NS_WARN_IF(!editor)) {
127
0
    return NS_ERROR_INVALID_ARG;
128
0
  }
129
0
  TextEditor* textEditor = editor->AsTextEditor();
130
0
  MOZ_ASSERT(textEditor);
131
0
132
0
  nsCommandParams* params = aParams->AsCommandParams();
133
0
134
0
  // Always get the enabled state
135
0
  bool outCmdEnabled = false;
136
0
  IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
137
0
  nsresult rv = params->SetBool(STATE_ENABLED, outCmdEnabled);
138
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
139
0
    return rv;
140
0
  }
141
0
142
0
  // get pres context
143
0
  RefPtr<nsPresContext> presContext = textEditor->GetPresContext();
144
0
  if (NS_WARN_IF(!presContext)) {
145
0
    return NS_ERROR_FAILURE;
146
0
  }
147
0
148
0
  IgnoredErrorResult error;
149
0
  Unused << params->GetInt("imageAnimation", error);
150
0
  if (!error.Failed()) {
151
0
    // for possible values of animation mode, see
152
0
    // http://lxr.mozilla.org/seamonkey/source/image/public/imgIContainer.idl
153
0
    rv = params->SetInt("imageAnimation", presContext->ImageAnimationMode());
154
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
155
0
      return rv;
156
0
    }
157
0
  } else {
158
0
    error.SuppressException();
159
0
  }
160
0
161
0
  bool allowPlugins = params->GetBool("plugins", error);
162
0
  if (error.Failed()) {
163
0
    return NS_OK;
164
0
  }
165
0
166
0
  nsCOMPtr<nsIDocShell> docShell(presContext->GetDocShell());
167
0
  if (NS_WARN_IF(!docShell)) {
168
0
    return NS_ERROR_FAILURE;
169
0
  }
170
0
171
0
  allowPlugins = docShell->PluginsAllowedInCurrentDoc();
172
0
  rv = params->SetBool("plugins", allowPlugins);
173
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
174
0
    return rv;
175
0
  }
176
0
  return NS_OK;
177
0
}
178
179
180
/**
181
 *  Commands for document state that may be changed via doCommandParams
182
 *  As of 11/11/02, this is just "cmd_setDocumentModified"
183
 *  Note that you can use the same command class, nsSetDocumentStateCommand,
184
 *    for more than one of this type of command
185
 *    We check the input command param for different behavior
186
 */
187
188
NS_IMETHODIMP
189
SetDocumentStateCommand::IsCommandEnabled(const char* aCommandName,
190
                                          nsISupports* refCon,
191
                                          bool* outCmdEnabled)
192
0
{
193
0
  if (NS_WARN_IF(!outCmdEnabled)) {
194
0
    return NS_ERROR_INVALID_ARG;
195
0
  }
196
0
197
0
  // These commands are always enabled
198
0
  *outCmdEnabled = true;
199
0
  return NS_OK;
200
0
}
201
202
NS_IMETHODIMP
203
SetDocumentStateCommand::DoCommand(const char* aCommandName,
204
                                   nsISupports* refCon)
205
0
{
206
0
  return NS_ERROR_NOT_IMPLEMENTED;
207
0
}
208
209
NS_IMETHODIMP
210
SetDocumentStateCommand::DoCommandParams(const char* aCommandName,
211
                                         nsICommandParams* aParams,
212
                                         nsISupports* refCon)
213
0
{
214
0
  if (NS_WARN_IF(!aParams)) {
215
0
    return NS_ERROR_INVALID_ARG;
216
0
  }
217
0
218
0
  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
219
0
  if (NS_WARN_IF(!editor)) {
220
0
    return NS_ERROR_INVALID_ARG;
221
0
  }
222
0
  TextEditor* textEditor = editor->AsTextEditor();
223
0
  MOZ_ASSERT(textEditor);
224
0
225
0
  nsCommandParams* params = aParams->AsCommandParams();
226
0
227
0
  if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentModified")) {
228
0
    ErrorResult error;
229
0
    bool modified = params->GetBool(STATE_ATTRIBUTE, error);
230
0
    // Should we fail if this param wasn't set?
231
0
    // I'm not sure we should be that strict
232
0
    if (NS_WARN_IF(error.Failed())) {
233
0
      return error.StealNSResult();
234
0
    }
235
0
    if (modified) {
236
0
      nsresult rv = textEditor->IncrementModificationCount(1);
237
0
      if (NS_WARN_IF(NS_FAILED(rv))) {
238
0
        return rv;
239
0
      }
240
0
      return NS_OK;
241
0
    }
242
0
    nsresult rv = textEditor->ResetModificationCount();
243
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
244
0
      return rv;
245
0
    }
246
0
    return NS_OK;
247
0
  }
248
0
249
0
  if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentReadOnly")) {
250
0
    ErrorResult error;
251
0
    bool isReadOnly = params->GetBool(STATE_ATTRIBUTE, error);
252
0
    if (NS_WARN_IF(error.Failed())) {
253
0
      return error.StealNSResult();
254
0
    }
255
0
    if (isReadOnly) {
256
0
      nsresult rv =
257
0
        textEditor->AddFlags(nsIPlaintextEditor::eEditorReadonlyMask);
258
0
      if (NS_WARN_IF(NS_FAILED(rv))) {
259
0
        return rv;
260
0
      }
261
0
      return NS_OK;
262
0
    }
263
0
    nsresult rv =
264
0
      textEditor->RemoveFlags(nsIPlaintextEditor::eEditorReadonlyMask);
265
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
266
0
      return rv;
267
0
    }
268
0
    return NS_OK;
269
0
  }
270
0
271
0
  if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentUseCSS")) {
272
0
    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
273
0
    if (NS_WARN_IF(!htmlEditor)) {
274
0
      return NS_ERROR_INVALID_ARG;
275
0
    }
276
0
    ErrorResult error;
277
0
    bool desireCSS = params->GetBool(STATE_ATTRIBUTE, error);
278
0
    if (NS_WARN_IF(error.Failed())) {
279
0
      return error.StealNSResult();
280
0
    }
281
0
    nsresult rv = htmlEditor->SetIsCSSEnabled(desireCSS);
282
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
283
0
      return rv;
284
0
    }
285
0
    return NS_OK;
286
0
  }
287
0
288
0
  if (!nsCRT::strcmp(aCommandName, "cmd_insertBrOnReturn")) {
289
0
    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
290
0
    if (NS_WARN_IF(!htmlEditor)) {
291
0
      return NS_ERROR_INVALID_ARG;
292
0
    }
293
0
    ErrorResult error;
294
0
    bool insertBrOnReturn = params->GetBool(STATE_ATTRIBUTE, error);
295
0
    if (NS_WARN_IF(error.Failed())) {
296
0
      return error.StealNSResult();
297
0
    }
298
0
    nsresult rv =
299
0
      htmlEditor->SetReturnInParagraphCreatesNewParagraph(!insertBrOnReturn);
300
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
301
0
      return rv;
302
0
    }
303
0
    return NS_OK;
304
0
  }
305
0
306
0
  if (!nsCRT::strcmp(aCommandName, "cmd_defaultParagraphSeparator")) {
307
0
    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
308
0
    if (NS_WARN_IF(!htmlEditor)) {
309
0
      return NS_ERROR_INVALID_ARG;
310
0
    }
311
0
312
0
    nsAutoCString newValue;
313
0
    nsresult rv = params->GetCString(STATE_ATTRIBUTE, newValue);
314
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
315
0
      return rv;
316
0
    }
317
0
318
0
    if (newValue.LowerCaseEqualsLiteral("div")) {
319
0
      htmlEditor->SetDefaultParagraphSeparator(ParagraphSeparator::div);
320
0
      return NS_OK;
321
0
    }
322
0
    if (newValue.LowerCaseEqualsLiteral("p")) {
323
0
      htmlEditor->SetDefaultParagraphSeparator(ParagraphSeparator::p);
324
0
      return NS_OK;
325
0
    }
326
0
    if (newValue.LowerCaseEqualsLiteral("br")) {
327
0
      // Mozilla extension for backwards compatibility
328
0
      htmlEditor->SetDefaultParagraphSeparator(ParagraphSeparator::br);
329
0
      return NS_OK;
330
0
    }
331
0
332
0
    // This should not be reachable from nsHTMLDocument::ExecCommand
333
0
    NS_WARNING("Invalid default paragraph separator");
334
0
    return NS_ERROR_UNEXPECTED;
335
0
  }
336
0
337
0
  if (!nsCRT::strcmp(aCommandName, "cmd_enableObjectResizing")) {
338
0
    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
339
0
    if (NS_WARN_IF(!htmlEditor)) {
340
0
      return NS_ERROR_INVALID_ARG;
341
0
    }
342
0
    ErrorResult error;
343
0
    bool enabled = params->GetBool(STATE_ATTRIBUTE, error);
344
0
    if (NS_WARN_IF(error.Failed())) {
345
0
      return error.StealNSResult();
346
0
    }
347
0
    htmlEditor->EnableObjectResizer(enabled);
348
0
    return NS_OK;
349
0
  }
350
0
351
0
  if (!nsCRT::strcmp(aCommandName, "cmd_enableInlineTableEditing")) {
352
0
    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
353
0
    if (NS_WARN_IF(!htmlEditor)) {
354
0
      return NS_ERROR_INVALID_ARG;
355
0
    }
356
0
    ErrorResult error;
357
0
    bool enabled = params->GetBool(STATE_ATTRIBUTE, error);
358
0
    if (NS_WARN_IF(error.Failed())) {
359
0
      return error.StealNSResult();
360
0
    }
361
0
    htmlEditor->EnableInlineTableEditor(enabled);
362
0
    return NS_OK;
363
0
  }
364
0
365
0
  if (!nsCRT::strcmp(aCommandName, "cmd_enableAbsolutePositionEditing")) {
366
0
    NS_ENSURE_ARG_POINTER(aParams);
367
0
    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
368
0
    if (NS_WARN_IF(!htmlEditor)) {
369
0
      return NS_ERROR_INVALID_ARG;
370
0
    }
371
0
    ErrorResult error;
372
0
    bool enabled = params->GetBool(STATE_ATTRIBUTE, error);
373
0
    if (NS_WARN_IF(error.Failed())) {
374
0
      return error.StealNSResult();
375
0
    }
376
0
    htmlEditor->EnableAbsolutePositionEditor(enabled);
377
0
    return NS_OK;
378
0
  }
379
0
380
0
  return NS_ERROR_NOT_IMPLEMENTED;
381
0
}
382
383
NS_IMETHODIMP
384
SetDocumentStateCommand::GetCommandStateParams(const char* aCommandName,
385
                                               nsICommandParams* aParams,
386
                                               nsISupports* refCon)
387
0
{
388
0
  if (NS_WARN_IF(!aParams) || NS_WARN_IF(!refCon)) {
389
0
    return NS_ERROR_INVALID_ARG;
390
0
  }
391
0
392
0
  // If the result is set to STATE_ALL as bool value, queryCommandState()
393
0
  // returns the bool value.
394
0
  // If the result is set to STATE_ATTRIBUTE as CString value,
395
0
  // queryCommandValue() returns the string value.
396
0
  // Otherwise, ignored.
397
0
398
0
  // The base editor owns most state info
399
0
  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
400
0
  if (NS_WARN_IF(!editor)) {
401
0
    return NS_ERROR_INVALID_ARG;
402
0
  }
403
0
  TextEditor* textEditor = editor->AsTextEditor();
404
0
  MOZ_ASSERT(textEditor);
405
0
406
0
  nsCommandParams* params = aParams->AsCommandParams();
407
0
408
0
  // Always get the enabled state
409
0
  bool outCmdEnabled = false;
410
0
  IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
411
0
  nsresult rv = params->SetBool(STATE_ENABLED, outCmdEnabled);
412
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
413
0
    return rv;
414
0
  }
415
0
416
0
  // cmd_setDocumentModified is an internal command.
417
0
  if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentModified")) {
418
0
    bool modified;
419
0
    rv = textEditor->GetDocumentModified(&modified);
420
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
421
0
      return rv;
422
0
    }
423
0
    // XXX Nobody refers this result due to wrong type.
424
0
    rv = params->SetBool(STATE_ATTRIBUTE, modified);
425
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
426
0
      return rv;
427
0
    }
428
0
    return NS_OK;
429
0
  }
430
0
431
0
  // cmd_setDocumentReadOnly is a Gecko specific command, "contentReadOnly".
432
0
  if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentReadOnly")) {
433
0
    // XXX Nobody refers this result due to wrong type.
434
0
    rv = params->SetBool(STATE_ATTRIBUTE, textEditor->IsReadonly());
435
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
436
0
      return rv;
437
0
    }
438
0
    return NS_OK;
439
0
  }
440
0
441
0
  // cmd_setDocumentUseCSS is a common command, "styleWithCSS".
442
0
  if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentUseCSS")) {
443
0
    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
444
0
    if (NS_WARN_IF(!htmlEditor)) {
445
0
      return NS_ERROR_INVALID_ARG;
446
0
    }
447
0
    rv = params->SetBool(STATE_ALL, htmlEditor->IsCSSEnabled());
448
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
449
0
      return rv;
450
0
    }
451
0
    return NS_OK;
452
0
  }
453
0
454
0
  // cmd_insertBrOnReturn is a Gecko specific command, "insertBrOrReturn".
455
0
  if (!nsCRT::strcmp(aCommandName, "cmd_insertBrOnReturn")) {
456
0
    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
457
0
    if (NS_WARN_IF(!htmlEditor)) {
458
0
      return NS_ERROR_INVALID_ARG;
459
0
    }
460
0
    bool createPOnReturn;
461
0
    htmlEditor->GetReturnInParagraphCreatesNewParagraph(&createPOnReturn);
462
0
    // XXX Nobody refers this result due to wrong type.
463
0
    rv = params->SetBool(STATE_ATTRIBUTE, !createPOnReturn);
464
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
465
0
      return rv;
466
0
    }
467
0
    return NS_OK;
468
0
  }
469
0
470
0
  // cmd_defaultParagraphSeparator is a common command,
471
0
  // "defaultParagraphSeparator".
472
0
  if (!nsCRT::strcmp(aCommandName, "cmd_defaultParagraphSeparator")) {
473
0
    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
474
0
    if (NS_WARN_IF(!htmlEditor)) {
475
0
      return NS_ERROR_INVALID_ARG;
476
0
    }
477
0
478
0
    switch (htmlEditor->GetDefaultParagraphSeparator()) {
479
0
      case ParagraphSeparator::div: {
480
0
        DebugOnly<nsresult> rv =
481
0
          params->SetCString(STATE_ATTRIBUTE, NS_LITERAL_CSTRING("div"));
482
0
        NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
483
0
          "Failed to set command params to return \"div\"");
484
0
        return NS_OK;
485
0
      }
486
0
      case ParagraphSeparator::p: {
487
0
        DebugOnly<nsresult> rv =
488
0
          params->SetCString(STATE_ATTRIBUTE, NS_LITERAL_CSTRING("p"));
489
0
        NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
490
0
          "Failed to set command params to return \"p\"");
491
0
        return NS_OK;
492
0
      }
493
0
      case ParagraphSeparator::br: {
494
0
        DebugOnly<nsresult> rv =
495
0
          params->SetCString(STATE_ATTRIBUTE, NS_LITERAL_CSTRING("br"));
496
0
        NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
497
0
          "Failed to set command params to return \"br\"");
498
0
        return NS_OK;
499
0
      }
500
0
      default:
501
0
        MOZ_ASSERT_UNREACHABLE("Invalid paragraph separator value");
502
0
        return NS_ERROR_UNEXPECTED;
503
0
    }
504
0
  }
505
0
506
0
  // cmd_enableObjectResizing is a Gecko specific command,
507
0
  // "enableObjectResizing".
508
0
  if (!nsCRT::strcmp(aCommandName, "cmd_enableObjectResizing")) {
509
0
    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
510
0
    if (NS_WARN_IF(!htmlEditor)) {
511
0
      return NS_ERROR_INVALID_ARG;
512
0
    }
513
0
    // We returned the result as STATE_ATTRIBUTE with bool value 60 or earlier.
514
0
    // So, the result was ignored by both nsHTMLDocument::QueryCommandValue()
515
0
    // and nsHTMLDocument::QueryCommandState().
516
0
    rv = params->SetBool(STATE_ALL, htmlEditor->IsObjectResizerEnabled());
517
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
518
0
      return rv;
519
0
    }
520
0
    return NS_OK;
521
0
  }
522
0
523
0
  // cmd_enableInlineTableEditing is a Gecko specific command,
524
0
  // "enableInlineTableEditing".
525
0
  if (!nsCRT::strcmp(aCommandName, "cmd_enableInlineTableEditing")) {
526
0
    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
527
0
    if (NS_WARN_IF(!htmlEditor)) {
528
0
      return NS_ERROR_INVALID_ARG;
529
0
    }
530
0
    // We returned the result as STATE_ATTRIBUTE with bool value 60 or earlier.
531
0
    // So, the result was ignored by both nsHTMLDocument::QueryCommandValue()
532
0
    // and nsHTMLDocument::QueryCommandState().
533
0
    rv = params->SetBool(STATE_ALL, htmlEditor->IsInlineTableEditorEnabled());
534
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
535
0
      return rv;
536
0
    }
537
0
    return NS_OK;
538
0
  }
539
0
540
0
  // cmd_enableAbsolutePositionEditing is a Gecko specific command,
541
0
  // "cenableAbsolutePositionEditing".
542
0
  if (!nsCRT::strcmp(aCommandName, "cmd_enableAbsolutePositionEditing")) {
543
0
    NS_ENSURE_ARG_POINTER(aParams);
544
0
    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
545
0
    if (NS_WARN_IF(!htmlEditor)) {
546
0
      return NS_ERROR_INVALID_ARG;
547
0
    }
548
0
    return params->SetBool(STATE_ALL,
549
0
                           htmlEditor->IsAbsolutePositionEditorEnabled());
550
0
  }
551
0
552
0
  return NS_ERROR_NOT_IMPLEMENTED;
553
0
}
554
555
/**
556
 * Commands just for state notification
557
 *  As of 11/21/02, possible commands are:
558
 *    "obs_documentCreated"
559
 *    "obs_documentWillBeDestroyed"
560
 *    "obs_documentLocationChanged"
561
 *  Note that you can use the same command class, nsDocumentStateCommand
562
 *    for these or future observer commands.
563
 *    We check the input command param for different behavior
564
 *
565
 *  How to use:
566
 *  1. Get the nsICommandManager for the current editor
567
 *  2. Implement an nsIObserve object, e.g:
568
 *
569
 *    void Observe(
570
 *        in nsISupports aSubject, // The nsICommandManager calling this Observer
571
 *        in string      aTopic,   // command name, e.g.:"obs_documentCreated"
572
 *                                 //    or "obs_documentWillBeDestroyed"
573
          in wstring     aData );  // ignored (set to "command_status_changed")
574
 *
575
 *  3. Add the observer by:
576
 *       commandManager.addObserver(observeobject, obs_documentCreated);
577
 *  4. In the appropriate location in editorSession, editor, or commands code,
578
 *     trigger the notification of this observer by something like:
579
 *
580
 *  nsCOMPtr<nsICommandManager> commandManager = mDocShell->GetCommandManager();
581
 *  nsCOMPtr<nsPICommandUpdater> commandUpdater = do_QueryInterface(commandManager);
582
 *  NS_ENSURE_TRUE(commandUpdater, NS_ERROR_FAILURE);
583
 *    commandUpdater->CommandStatusChanged(obs_documentCreated);
584
 *
585
 *  5. Use GetCommandStateParams() to obtain state information
586
 *     e.g., any creation state codes when creating an editor are
587
 *     supplied for "obs_documentCreated" command in the
588
 *     "state_data" param's value
589
 *
590
 */
591
592
NS_IMETHODIMP
593
DocumentStateCommand::IsCommandEnabled(const char* aCommandName,
594
                                       nsISupports* refCon,
595
                                       bool* outCmdEnabled)
596
0
{
597
0
  if (NS_WARN_IF(!outCmdEnabled)) {
598
0
    return NS_ERROR_INVALID_ARG;
599
0
  }
600
0
601
0
  // Always return false to discourage callers from using DoCommand()
602
0
  *outCmdEnabled = false;
603
0
  return NS_OK;
604
0
}
605
606
NS_IMETHODIMP
607
DocumentStateCommand::DoCommand(const char* aCommandName,
608
                                nsISupports* refCon)
609
0
{
610
0
  return NS_ERROR_NOT_IMPLEMENTED;
611
0
}
612
613
NS_IMETHODIMP
614
DocumentStateCommand::DoCommandParams(const char* aCommandName,
615
                                      nsICommandParams* aParams,
616
                                      nsISupports* refCon)
617
0
{
618
0
  return NS_ERROR_NOT_IMPLEMENTED;
619
0
}
620
621
NS_IMETHODIMP
622
DocumentStateCommand::GetCommandStateParams(const char* aCommandName,
623
                                            nsICommandParams* aParams,
624
                                            nsISupports* refCon)
625
0
{
626
0
  if (NS_WARN_IF(!aParams) || NS_WARN_IF(!aCommandName)) {
627
0
    return NS_ERROR_INVALID_ARG;
628
0
  }
629
0
630
0
  nsCommandParams* params = aParams->AsCommandParams();
631
0
632
0
  if (!nsCRT::strcmp(aCommandName, "obs_documentCreated")) {
633
0
    uint32_t editorStatus = nsIEditingSession::eEditorErrorUnknown;
634
0
635
0
    nsCOMPtr<nsIEditingSession> editingSession = do_QueryInterface(refCon);
636
0
    if (editingSession) {
637
0
      // refCon is initially set to nsIEditingSession until editor
638
0
      //  is successfully created and source doc is loaded
639
0
      // Embedder gets error status if this fails
640
0
      // If called before startup is finished,
641
0
      //    status = eEditorCreationInProgress
642
0
      nsresult rv = editingSession->GetEditorStatus(&editorStatus);
643
0
      if (NS_WARN_IF(NS_FAILED(rv))) {
644
0
        return rv;
645
0
      }
646
0
    } else {
647
0
      // If refCon is an editor, then everything started up OK!
648
0
      nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
649
0
      if (editor) {
650
0
        editorStatus = nsIEditingSession::eEditorOK;
651
0
      }
652
0
    }
653
0
654
0
    // Note that if refCon is not-null, but is neither
655
0
    // an nsIEditingSession or nsIEditor, we return "eEditorErrorUnknown"
656
0
    DebugOnly<nsresult> rv = params->SetInt(STATE_DATA, editorStatus);
657
0
    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to set editor status");
658
0
    return NS_OK;
659
0
  }
660
0
661
0
  if (!nsCRT::strcmp(aCommandName, "obs_documentLocationChanged")) {
662
0
    nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
663
0
    if (!editor) {
664
0
      return NS_OK;
665
0
    }
666
0
    TextEditor* textEditor = editor->AsTextEditor();
667
0
    MOZ_ASSERT(textEditor);
668
0
669
0
    nsCOMPtr<nsIDocument> doc = textEditor->GetDocument();
670
0
    if (NS_WARN_IF(!doc)) {
671
0
      return NS_ERROR_FAILURE;
672
0
    }
673
0
    nsIURI* uri = doc->GetDocumentURI();
674
0
    if (NS_WARN_IF(!uri)) {
675
0
      return NS_ERROR_FAILURE;
676
0
    }
677
0
    nsresult rv = params->SetISupports(STATE_DATA, uri);
678
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
679
0
      return rv;
680
0
    }
681
0
    return NS_OK;
682
0
  }
683
0
684
0
  return NS_ERROR_NOT_IMPLEMENTED;
685
0
}
686
687
} // namespace mozilla