Fix for bugs 23943, 47640 and 63515. Teach editor to handle plain text, and other text file types (including XUL, XML, JS etc), and, in the process, make the commands be smarter about disabling in text mode, and HTML source mode. r=brade, sr=kin

This commit is contained in:
sfraser%netscape.com 2001-05-18 06:42:37 +00:00
parent 040e3083cc
commit 172a2ac866
13 changed files with 642 additions and 341 deletions

View File

@ -94,6 +94,24 @@ nsBaseComposerCommand::SetCommandNodeState(const nsAReadableString & aCommandNam
return uiNode->SetAttribute(NS_ConvertASCIItoUCS2("state"), inNodeState);
}
//--------------------------------------------------------------------------------------------------------------------
PRBool
nsBaseComposerCommand::EditingHTML(nsIEditorShell* inEditorShell)
//--------------------------------------------------------------------------------------------------------------------
{
nsXPIDLCString mimeType;
inEditorShell->GetContentsMIMEType(getter_Copies(mimeType));
if (nsCRT::strcmp(mimeType, "text/html") != 0)
return PR_FALSE;
PRBool sourceMode = PR_FALSE;
inEditorShell->IsHTMLSourceMode(&sourceMode);
if (sourceMode)
return PR_FALSE;
return PR_TRUE;
}
#ifdef XP_MAC
#pragma mark -
@ -119,23 +137,12 @@ nsBaseStateUpdatingCommand::IsCommandEnabled(const nsAReadableString & aCommandN
{
nsCOMPtr<nsIEditorShell> editorShell = do_QueryInterface(refCon);
*outCmdEnabled = PR_FALSE;
if (!editorShell) return NS_OK;
// check for plain text?
nsCOMPtr<nsIEditor> editor;
editorShell->GetEditor(getter_AddRefs(editor));
if (!editor) return NS_OK;
// Enable commands only if not in HTML source edit mode
PRBool sourceMode = PR_FALSE;
editorShell->IsHTMLSourceMode(&sourceMode);
*outCmdEnabled = !sourceMode;
// also udpate the command state
nsresult rv = UpdateCommandState(aCommandName, refCon);
if (NS_FAILED(rv))
if (editorShell && EditingHTML(editorShell))
{
*outCmdEnabled = PR_FALSE;
return NS_OK;
*outCmdEnabled = PR_TRUE;
// also udpate the command state.
UpdateCommandState(aCommandName, refCon);
}
return NS_OK;
@ -472,7 +479,7 @@ nsRemoveListCommand::IsCommandEnabled(const nsAReadableString & aCommandName, ns
{
nsCOMPtr<nsIEditorShell> editorShell = do_QueryInterface(refCon);
*outCmdEnabled = PR_FALSE;
if (editorShell)
if (editorShell && EditingHTML(editorShell))
{
// It is enabled if we are in any list type
PRBool bMixed;
@ -515,7 +522,7 @@ nsIndentCommand::IsCommandEnabled(const nsAReadableString & aCommandName, nsISup
{
nsCOMPtr<nsIEditorShell> editorShell = do_QueryInterface(refCon);
*outCmdEnabled = PR_FALSE;
if (editorShell)
if (editorShell && EditingHTML(editorShell))
{
nsCOMPtr<nsIEditor> editor;
editorShell->GetEditor(getter_AddRefs(editor));
@ -547,7 +554,7 @@ nsOutdentCommand::IsCommandEnabled(const nsAReadableString & aCommandName, nsISu
{
nsCOMPtr<nsIEditorShell> editorShell = do_QueryInterface(refCon);
*outCmdEnabled = PR_FALSE;
if (editorShell)
if (editorShell && EditingHTML(editorShell))
{
nsCOMPtr<nsIEditor> editor;
editorShell->GetEditor(getter_AddRefs(editor));
@ -571,7 +578,7 @@ nsOutdentCommand::DoCommand(const nsAReadableString & aCommandName, nsISupports
nsCOMPtr<nsIEditorShell> editorShell = do_QueryInterface(refCon);
nsresult rv = NS_OK;
if (editorShell)
if (editorShell && EditingHTML(editorShell))
{
nsAutoString indentStr; indentStr.AssignWithConversion("outdent");
rv = editorShell->Indent(indentStr.GetUnicode());
@ -602,7 +609,7 @@ nsMultiStateCommand::IsCommandEnabled(const nsAReadableString & aCommandName, ns
{
nsCOMPtr<nsIEditorShell> editorShell = do_QueryInterface(refCon);
*outCmdEnabled = PR_FALSE;
if (editorShell)
if (editorShell && EditingHTML(editorShell))
{
nsCOMPtr<nsIEditor> editor;
editorShell->GetEditor(getter_AddRefs(editor));
@ -923,7 +930,7 @@ nsRemoveStylesCommand::IsCommandEnabled(const nsAReadableString & aCommandName,
{
nsCOMPtr<nsIEditorShell> editorShell = do_QueryInterface(refCon);
*outCmdEnabled = PR_FALSE;
if (editorShell)
if (editorShell && EditingHTML(editorShell))
{
nsCOMPtr<nsIEditor> editor;
editorShell->GetEditor(getter_AddRefs(editor));
@ -968,7 +975,7 @@ nsIncreaseFontSizeCommand::IsCommandEnabled(const nsAReadableString & aCommandNa
{
nsCOMPtr<nsIEditorShell> editorShell = do_QueryInterface(refCon);
*outCmdEnabled = PR_FALSE;
if (editorShell)
if (editorShell && EditingHTML(editorShell))
{
nsCOMPtr<nsIEditor> editor;
editorShell->GetEditor(getter_AddRefs(editor));
@ -1006,7 +1013,7 @@ nsDecreaseFontSizeCommand::IsCommandEnabled(const nsAReadableString & aCommandNa
{
nsCOMPtr<nsIEditorShell> editorShell = do_QueryInterface(refCon);
*outCmdEnabled = PR_FALSE;
if (editorShell)
if (editorShell && EditingHTML(editorShell))
{
nsCOMPtr<nsIEditor> editor;
editorShell->GetEditor(getter_AddRefs(editor));

View File

@ -59,6 +59,8 @@ protected:
nsresult GetCommandNodeState(const nsAReadableString & aCommandName, nsIEditorShell* editorShell, nsString& outNodeState);
nsresult SetCommandNodeState(const nsAReadableString & aCommandName, nsIEditorShell* editorShell, const nsString& inNodeState);
// are we in HTML edit mode (not source view or plain text editing)
PRBool EditingHTML(nsIEditorShell* inEditorShell);
};

View File

@ -100,6 +100,8 @@
#include "nsILookAndFeel.h"
#include "nsIChromeRegistry.h"
#include "nsCExternalHandlerService.h"
#include "nsIMIMEService.h"
///////////////////////////////////////
// Editor Includes
@ -207,13 +209,14 @@ GetChromeElement(nsIDocShell *aShell, const char *aID, nsIDOMElement **aElement)
// Utility to set and attribute of a UI element
static nsresult
SetChromeAttribute(nsIDocShell *aShell, const char *aID,
const char *aName, const nsString &aValue)
const nsAString& aName, const nsAString &aValue)
{
nsCOMPtr<nsIDOMElement> elem;
nsresult rv = GetChromeElement(aShell, aID, getter_AddRefs(elem));
// Set the text attribute.
if (NS_SUCCEEDED(rv) && elem)
// Set the text attribute.
rv = elem->SetAttribute( NS_ConvertASCIItoUCS2(aName), aValue);
rv = elem->SetAttribute(aName, aValue);
return rv;
}
@ -254,6 +257,8 @@ nsEditorShell::nsEditorShell()
, mCloseWindowWhenLoaded(PR_FALSE)
, mCantEditReason(eCantEditNoReason)
, mEditorType(eUninitializedEditorType)
, mContentMIMEType("text/html")
, mContentTypeKnown(PR_FALSE)
, mWrapColumn(0)
, mSuggestedWordIndex(0)
, mDictionaryIndex(0)
@ -436,6 +441,37 @@ nsEditorShell::ResetEditingState()
return NS_OK;
}
// is this a MIME type that we support the editing of, in plain text mode?
const char* const gSupportedTextTypes[] = {
"text/plain",
"text/css",
"text/rdf",
"text/xml",
"text/xsl",
"text/javascript", // obsolete type
"application/x-javascript",
"text/xul", // obsolete type
"application/vnd.mozilla.xul+xml",
NULL // IMPORTANT! Null must be at end
};
PRBool
nsEditorShell::IsSupportedTextType(const char* aMIMEType)
{
PRInt32 i = 0;
while (gSupportedTextTypes[i])
{
if (nsCRT::strcmp(gSupportedTextTypes[i], aMIMEType) == 0)
return PR_TRUE;
i ++;
}
return PR_FALSE;
}
nsresult
nsEditorShell::PrepareDocumentForEditing(nsIDOMWindow* aDOMWindow, nsIURI *aUrl)
{
@ -884,6 +920,21 @@ nsEditorShell::GetEditorType(PRUnichar **_retval)
return NS_OK;
}
/* attribute string contentsMIMEType; */
NS_IMETHODIMP
nsEditorShell::GetContentsMIMEType(char * *aContentsMIMEType)
{
NS_ENSURE_ARG_POINTER(aContentsMIMEType);
*aContentsMIMEType = mContentMIMEType.ToNewCString();
return NS_OK;
}
NS_IMETHODIMP
nsEditorShell::SetContentsMIMEType(const char * aContentsMIMEType)
{
mContentMIMEType.Assign(aContentsMIMEType ? aContentsMIMEType : "");
return NS_OK;
}
nsresult
nsEditorShell::InstantiateEditor(nsIDOMDocument *aDoc, nsIPresShell *aPresShell)
@ -895,58 +946,66 @@ nsEditorShell::InstantiateEditor(nsIDOMDocument *aDoc, nsIPresShell *aPresShell)
if (mEditor)
return NS_ERROR_ALREADY_INITIALIZED;
nsresult err = NS_OK;
nsresult rv = NS_OK;
nsCOMPtr<nsIEditor> editor;
err = nsComponentManager::CreateInstance(kHTMLEditorCID, nsnull, NS_GET_IID(nsIEditor), getter_AddRefs(editor));
if(!editor)
err = NS_ERROR_OUT_OF_MEMORY;
rv = nsComponentManager::CreateInstance(kHTMLEditorCID, nsnull, NS_GET_IID(nsIEditor), getter_AddRefs(editor));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsISelectionController> selCon = do_QueryInterface(aPresShell);
if (NS_SUCCEEDED(err))
if (mEditorTypeString.EqualsWithConversion("text"))
{
if (mEditorTypeString.EqualsWithConversion("text"))
PRInt16 flags = nsIPlaintextEditor::eEditorPlaintextMask | nsIPlaintextEditor::eEditorEnableWrapHackMask;
if (mMailCompose) flags |= nsIPlaintextEditor::eEditorMailMask;
rv = editor->Init(aDoc, aPresShell, nsnull, selCon, flags);
mEditorType = ePlainTextEditorType;
}
else if (mEditorTypeString.EqualsWithConversion("html") || mEditorTypeString.IsEmpty()) // empty string default to HTML editor
{
PRUint32 editorFlags = 0;
EEditorType editorType = eHTMLTextEditorType;
// if the MIME type of the docment we are editing is text/plain, make a text editor
if (IsSupportedTextType(mContentMIMEType))
{
PRInt16 flags = nsIPlaintextEditor::eEditorPlaintextMask | nsIPlaintextEditor::eEditorEnableWrapHackMask;
if (mMailCompose) flags |= nsIPlaintextEditor::eEditorMailMask;
err = editor->Init(aDoc, aPresShell, nsnull, selCon, flags);
mEditorType = ePlainTextEditorType;
editorFlags = nsIPlaintextEditor::eEditorPlaintextMask;
editorType = ePlainTextEditorType;
}
else if (mEditorTypeString.EqualsWithConversion("html") || mEditorTypeString.IsEmpty()) // empty string default to HTML editor
{
err = editor->Init(aDoc, aPresShell, nsnull, selCon, 0);
mEditorType = eHTMLTextEditorType;
}
else if (mEditorTypeString.EqualsWithConversion("htmlmail")) // HTML editor with special mail rules
{
err = editor->Init(aDoc, aPresShell, nsnull, selCon, nsIPlaintextEditor::eEditorMailMask);
mEditorType = eHTMLTextEditorType;
}
else
{
err = NS_ERROR_INVALID_ARG; // this is not an editor we know about
rv = editor->Init(aDoc, aPresShell, nsnull, selCon, editorFlags);
mEditorType = editorType;
}
else if (mEditorTypeString.EqualsWithConversion("htmlmail")) // HTML editor with special mail rules
{
rv = editor->Init(aDoc, aPresShell, nsnull, selCon, nsIPlaintextEditor::eEditorMailMask);
mEditorType = eHTMLTextEditorType;
}
else
{
rv = NS_ERROR_INVALID_ARG; // this is not an editor we know about
#if DEBUG
nsAutoString errorMsg; errorMsg.AssignWithConversion("Failed to init editor. Unknown editor type \"");
errorMsg += mEditorTypeString;
errorMsg.AppendWithConversion("\"\n");
char *errorMsgCString = errorMsg.ToNewCString();
NS_WARNING(errorMsgCString);
nsCRT::free(errorMsgCString);
nsAutoString errorMsg; errorMsg.AssignWithConversion("Failed to init editor. Unknown editor type \"");
errorMsg += mEditorTypeString;
errorMsg.AppendWithConversion("\"\n");
char *errorMsgCString = errorMsg.ToNewCString();
NS_WARNING(errorMsgCString);
nsCRT::free(errorMsgCString);
#endif
}
}
// disable the preference style sheet so we can override colors
if (NS_SUCCEEDED(err)) {
err = aPresShell->EnablePrefStyleRules(PR_FALSE,0);
}
if (NS_SUCCEEDED(rv))
{
rv = aPresShell->EnablePrefStyleRules(PR_FALSE,0);
}
if (NS_SUCCEEDED(err) && editor)
{
mEditor = do_QueryInterface(editor); // this does the addref that is the owning reference
}
if (NS_SUCCEEDED(rv) && editor)
{
mEditor = do_QueryInterface(editor); // this does the addref that is the owning reference
}
return err;
return rv;
}
@ -1688,6 +1747,27 @@ nsEditorShell::CheckOpenWindowForURLMatch(const PRUnichar* inFileURL, nsIDOMWind
return NS_OK;
}
// helper function
static nsresult GetExtensionForMIMEType(const char* inMIMEType, nsACString& outExtension)
{
nsresult rv;
nsCOMPtr<nsIMIMEService> mimeService = do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIMIMEInfo> mimeInfo;
rv = mimeService->GetFromMIMEType(inMIMEType, getter_AddRefs(mimeInfo));
if (NS_FAILED(rv)) return rv;
nsXPIDLCString fileExtension;
rv = mimeInfo->FirstExtension(getter_Copies(fileExtension));
if (NS_FAILED(rv)) return rv;
outExtension.Assign(fileExtension);
return NS_OK;
}
NS_IMETHODIMP
nsEditorShell::SaveDocument(PRBool aSaveAs, PRBool aSaveCopy, const PRUnichar* aMimeType, PRBool *_retval)
{
@ -1696,13 +1776,20 @@ nsEditorShell::SaveDocument(PRBool aSaveAs, PRBool aSaveCopy, const PRUnichar* a
NS_ENSURE_ARG_POINTER((aMimeType));
nsAutoString mimeType(aMimeType);
PRBool saveAsText = mimeType.EqualsWithConversion("text/plain");
nsCAutoString mimeTypeCStr; mimeTypeCStr.AssignWithConversion(aMimeType);
PRBool saveAsText = IsSupportedTextType(mimeTypeCStr);
// Currently, we only understand plain text and html
if (!mimeType.EqualsWithConversion("text/html") && !saveAsText)
if (!mimeTypeCStr.Equals("text/html") && !saveAsText)
return NS_ERROR_FAILURE;
nsAutoString mimeType(aMimeType);
// if we're saving as text, force the text/plain MIME type (because we use this
// to get a content serializer on save)
if (saveAsText)
mimeType.Assign(NS_LITERAL_STRING("text/plain").get());
switch (mEditorType)
{
case ePlainTextEditorType:
@ -1858,11 +1945,12 @@ nsEditorShell::SaveDocument(PRBool aSaveAs, PRBool aSaveCopy, const PRUnichar* a
title.ReplaceChar(" .\\/@:", (PRUnichar)'_');
}
// get the correct extension from the MIME type here
fileName = title;
if (saveAsText)
fileName.AppendWithConversion(".txt");
else
fileName.AppendWithConversion(".html");
nsCAutoString fileExt(saveAsText ? "txt" : "html");
GetExtensionForMIMEType(mimeTypeCStr.get(), fileExt);
fileName.Append(PRUnichar('.'));
fileName.AppendWithConversion(fileExt);
}
else // have a file spec
{
@ -1881,9 +1969,12 @@ nsEditorShell::SaveDocument(PRBool aSaveAs, PRBool aSaveCopy, const PRUnichar* a
index = fileName.RFind(".shtml", PR_TRUE);
if (index > 0)
{
nsCAutoString fileExt("txt");
GetExtensionForMIMEType(mimeTypeCStr.get(), fileExt);
// Truncate after "." and append "txt" extension
fileName.SetLength(index+1);
fileName.AppendWithConversion("txt");
fileName.AppendWithConversion(fileExt);
}
}
@ -4934,6 +5025,8 @@ nsEditorShell::OnStateChange(nsIWebProgress *aProgress,
PRInt32 aStateFlags,
nsresult aStatus)
{
nsresult rv = NS_OK;
//
// A Request has started...
//
@ -4942,7 +5035,8 @@ nsEditorShell::OnStateChange(nsIWebProgress *aProgress,
// Page level notification...
if (aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK)
{
StartPageLoad();
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
StartPageLoad(channel);
}
// Document level notification...
if (aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT)
@ -5013,12 +5107,36 @@ nsEditorShell::OnSecurityChange(nsIWebProgress *aWebProgress,
return NS_OK;
}
nsresult nsEditorShell::StartPageLoad()
nsresult nsEditorShell::StartPageLoad(nsIChannel *aChannel)
{
nsXPIDLCString contentType;
aChannel->GetContentType(getter_Copies(contentType));
// save the original MIME type; we'll use it later
mContentMIMEType.Assign(contentType.get() ? contentType : "");
if (nsCRT::strcmp(contentType, "text/html") == 0)
{
// fine, do nothing
mContentTypeKnown = PR_TRUE;
}
else if (IsSupportedTextType(contentType))
{
// set the mime type to text/plain so that it renders as text
aChannel->SetContentType("text/plain");
mContentTypeKnown = PR_TRUE;
}
else
{
// we don't know what this is yet. It might be HTML loaded from
// a directory URL (http://www.foo.com/). We'll know the real
// MIME type later.
mContentTypeKnown = PR_FALSE;
}
// Start the throbber
// TODO: We should also start/stop it for saving and publishing?
SetChromeAttribute( mDocShell, "Editor:Throbber", "busy",
NS_ConvertASCIItoUCS2("true") );
SetChromeAttribute( mDocShell, "Editor:Throbber", NS_LITERAL_STRING("busy"), NS_LITERAL_STRING("true") );
// set up a parser observer
if (!mParserObserver)
@ -5029,6 +5147,7 @@ nsresult nsEditorShell::StartPageLoad()
}
NS_ADDREF(mParserObserver);
mParserObserver->RegisterTagToWatch("FRAMESET");
mParserObserver->RegisterTagToWatch("IFRAME");
mParserObserver->Start();
}
@ -5048,12 +5167,31 @@ nsresult nsEditorShell::EndPageLoad(nsIDOMWindow *aDOMWindow,
NS_RELEASE(mParserObserver);
}
SetChromeAttribute( mDocShell, "Editor:Throbber", "busy",
NS_ConvertASCIItoUCS2("false") );
SetChromeAttribute( mDocShell, "Editor:Throbber", NS_LITERAL_STRING("busy"), NS_LITERAL_STRING("false") );
// Is this a MIME type we can handle?
if (aChannel)
{
// if we didn't get the content-type at the start of the load, get it now
if (!mContentTypeKnown)
{
nsXPIDLCString contentType;
aChannel->GetContentType(getter_Copies(contentType));
if (contentType.get())
mContentMIMEType.Assign(contentType);
}
}
if ( !mContentMIMEType.Equals("text/html") && !IsSupportedTextType(mContentMIMEType) )
{
mCloseWindowWhenLoaded = PR_TRUE;
mCantEditReason = eCantEditMimeType;
}
nsAutoString doneText;
GetBundleString(NS_LITERAL_STRING("LoadingDone"), doneText);
SetChromeAttribute(mDocShell, "statusText", "label", doneText);
SetChromeAttribute(mDocShell, "statusText", NS_LITERAL_STRING("label"), doneText);
// Display an Alert dialog if the page cannot be edited...
if (mCloseWindowWhenLoaded)
@ -5101,6 +5239,7 @@ nsresult nsEditorShell::EndPageLoad(nsIDOMWindow *aDOMWindow,
{
nsCOMPtr<nsIURI> url;
aChannel->GetURI(getter_AddRefs(url));
(void) PrepareDocumentForEditing(aDOMWindow, url);
}
@ -5143,24 +5282,6 @@ nsresult nsEditorShell::EndDocumentLoad(nsIDOMWindow *aDOMWindow,
nsCOMPtr<nsIRefreshURI> refreshURI = do_QueryInterface(mContentAreaDocShell);
if (refreshURI)
refreshURI->CancelRefreshURITimers();
// Is this a MIME type we can handle?
if (aChannel)
{
char *contentType;
aChannel->GetContentType(&contentType);
if (contentType)
{
if ( (nsCRT::strcmp(contentType, "text/html") != 0) &&
(nsCRT::strcmp(contentType, "text/plain") != 0))
{
mCloseWindowWhenLoaded = PR_TRUE;
mCantEditReason = eCantEditMimeType;
}
nsMemory::Free(contentType);
}
}
return NS_OK;
}

View File

@ -158,7 +158,7 @@ class nsEditorShell : public nsIEditorShell,
nsresult UpdateWindowTitleAndRecentMenu(PRBool aSaveToPrefs);
// Helper method which is called at the beginning of a new page load
nsresult StartPageLoad();
nsresult StartPageLoad(nsIChannel *aChannel);
// Helper method which is called when an entire page load finishes
nsresult EndPageLoad(nsIDOMWindow *aDOMWindow,
@ -174,6 +174,8 @@ class nsEditorShell : public nsIEditorShell,
nsIChannel *aChannel,
nsresult aStatus);
PRBool IsSupportedTextType(const char* aMIMEType);
// Check a preference and call NormalizeTable if pref is true
// Use after deleting or inserting table cells to automatically
// fix rowspan, colspan, and missing cells problems
@ -234,8 +236,11 @@ class nsEditorShell : public nsIEditorShell,
PRPackedBool mCloseWindowWhenLoaded; // error on load. Close window when loaded
ECantEditReason mCantEditReason;
EEditorType mEditorType;
EEditorType mEditorType;
nsString mEditorTypeString; // string which describes which editor type will be instantiated (lowercased)
nsCString mContentMIMEType; // MIME type of the doc we are editing.
PRBool mContentTypeKnown;
PRInt32 mWrapColumn; // can't actually set this 'til the editor is created, so we may have to hold on to it for a while
nsStringArray mSuggestedWordList;

View File

@ -94,6 +94,24 @@ nsBaseComposerCommand::SetCommandNodeState(const nsAReadableString & aCommandNam
return uiNode->SetAttribute(NS_ConvertASCIItoUCS2("state"), inNodeState);
}
//--------------------------------------------------------------------------------------------------------------------
PRBool
nsBaseComposerCommand::EditingHTML(nsIEditorShell* inEditorShell)
//--------------------------------------------------------------------------------------------------------------------
{
nsXPIDLCString mimeType;
inEditorShell->GetContentsMIMEType(getter_Copies(mimeType));
if (nsCRT::strcmp(mimeType, "text/html") != 0)
return PR_FALSE;
PRBool sourceMode = PR_FALSE;
inEditorShell->IsHTMLSourceMode(&sourceMode);
if (sourceMode)
return PR_FALSE;
return PR_TRUE;
}
#ifdef XP_MAC
#pragma mark -
@ -119,23 +137,12 @@ nsBaseStateUpdatingCommand::IsCommandEnabled(const nsAReadableString & aCommandN
{
nsCOMPtr<nsIEditorShell> editorShell = do_QueryInterface(refCon);
*outCmdEnabled = PR_FALSE;
if (!editorShell) return NS_OK;
// check for plain text?
nsCOMPtr<nsIEditor> editor;
editorShell->GetEditor(getter_AddRefs(editor));
if (!editor) return NS_OK;
// Enable commands only if not in HTML source edit mode
PRBool sourceMode = PR_FALSE;
editorShell->IsHTMLSourceMode(&sourceMode);
*outCmdEnabled = !sourceMode;
// also udpate the command state
nsresult rv = UpdateCommandState(aCommandName, refCon);
if (NS_FAILED(rv))
if (editorShell && EditingHTML(editorShell))
{
*outCmdEnabled = PR_FALSE;
return NS_OK;
*outCmdEnabled = PR_TRUE;
// also udpate the command state.
UpdateCommandState(aCommandName, refCon);
}
return NS_OK;
@ -472,7 +479,7 @@ nsRemoveListCommand::IsCommandEnabled(const nsAReadableString & aCommandName, ns
{
nsCOMPtr<nsIEditorShell> editorShell = do_QueryInterface(refCon);
*outCmdEnabled = PR_FALSE;
if (editorShell)
if (editorShell && EditingHTML(editorShell))
{
// It is enabled if we are in any list type
PRBool bMixed;
@ -515,7 +522,7 @@ nsIndentCommand::IsCommandEnabled(const nsAReadableString & aCommandName, nsISup
{
nsCOMPtr<nsIEditorShell> editorShell = do_QueryInterface(refCon);
*outCmdEnabled = PR_FALSE;
if (editorShell)
if (editorShell && EditingHTML(editorShell))
{
nsCOMPtr<nsIEditor> editor;
editorShell->GetEditor(getter_AddRefs(editor));
@ -547,7 +554,7 @@ nsOutdentCommand::IsCommandEnabled(const nsAReadableString & aCommandName, nsISu
{
nsCOMPtr<nsIEditorShell> editorShell = do_QueryInterface(refCon);
*outCmdEnabled = PR_FALSE;
if (editorShell)
if (editorShell && EditingHTML(editorShell))
{
nsCOMPtr<nsIEditor> editor;
editorShell->GetEditor(getter_AddRefs(editor));
@ -571,7 +578,7 @@ nsOutdentCommand::DoCommand(const nsAReadableString & aCommandName, nsISupports
nsCOMPtr<nsIEditorShell> editorShell = do_QueryInterface(refCon);
nsresult rv = NS_OK;
if (editorShell)
if (editorShell && EditingHTML(editorShell))
{
nsAutoString indentStr; indentStr.AssignWithConversion("outdent");
rv = editorShell->Indent(indentStr.GetUnicode());
@ -602,7 +609,7 @@ nsMultiStateCommand::IsCommandEnabled(const nsAReadableString & aCommandName, ns
{
nsCOMPtr<nsIEditorShell> editorShell = do_QueryInterface(refCon);
*outCmdEnabled = PR_FALSE;
if (editorShell)
if (editorShell && EditingHTML(editorShell))
{
nsCOMPtr<nsIEditor> editor;
editorShell->GetEditor(getter_AddRefs(editor));
@ -923,7 +930,7 @@ nsRemoveStylesCommand::IsCommandEnabled(const nsAReadableString & aCommandName,
{
nsCOMPtr<nsIEditorShell> editorShell = do_QueryInterface(refCon);
*outCmdEnabled = PR_FALSE;
if (editorShell)
if (editorShell && EditingHTML(editorShell))
{
nsCOMPtr<nsIEditor> editor;
editorShell->GetEditor(getter_AddRefs(editor));
@ -968,7 +975,7 @@ nsIncreaseFontSizeCommand::IsCommandEnabled(const nsAReadableString & aCommandNa
{
nsCOMPtr<nsIEditorShell> editorShell = do_QueryInterface(refCon);
*outCmdEnabled = PR_FALSE;
if (editorShell)
if (editorShell && EditingHTML(editorShell))
{
nsCOMPtr<nsIEditor> editor;
editorShell->GetEditor(getter_AddRefs(editor));
@ -1006,7 +1013,7 @@ nsDecreaseFontSizeCommand::IsCommandEnabled(const nsAReadableString & aCommandNa
{
nsCOMPtr<nsIEditorShell> editorShell = do_QueryInterface(refCon);
*outCmdEnabled = PR_FALSE;
if (editorShell)
if (editorShell && EditingHTML(editorShell))
{
nsCOMPtr<nsIEditor> editor;
editorShell->GetEditor(getter_AddRefs(editor));

View File

@ -59,6 +59,8 @@ protected:
nsresult GetCommandNodeState(const nsAReadableString & aCommandName, nsIEditorShell* editorShell, nsString& outNodeState);
nsresult SetCommandNodeState(const nsAReadableString & aCommandName, nsIEditorShell* editorShell, const nsString& inNodeState);
// are we in HTML edit mode (not source view or plain text editing)
PRBool EditingHTML(nsIEditorShell* inEditorShell);
};

View File

@ -100,6 +100,8 @@
#include "nsILookAndFeel.h"
#include "nsIChromeRegistry.h"
#include "nsCExternalHandlerService.h"
#include "nsIMIMEService.h"
///////////////////////////////////////
// Editor Includes
@ -207,13 +209,14 @@ GetChromeElement(nsIDocShell *aShell, const char *aID, nsIDOMElement **aElement)
// Utility to set and attribute of a UI element
static nsresult
SetChromeAttribute(nsIDocShell *aShell, const char *aID,
const char *aName, const nsString &aValue)
const nsAString& aName, const nsAString &aValue)
{
nsCOMPtr<nsIDOMElement> elem;
nsresult rv = GetChromeElement(aShell, aID, getter_AddRefs(elem));
// Set the text attribute.
if (NS_SUCCEEDED(rv) && elem)
// Set the text attribute.
rv = elem->SetAttribute( NS_ConvertASCIItoUCS2(aName), aValue);
rv = elem->SetAttribute(aName, aValue);
return rv;
}
@ -254,6 +257,8 @@ nsEditorShell::nsEditorShell()
, mCloseWindowWhenLoaded(PR_FALSE)
, mCantEditReason(eCantEditNoReason)
, mEditorType(eUninitializedEditorType)
, mContentMIMEType("text/html")
, mContentTypeKnown(PR_FALSE)
, mWrapColumn(0)
, mSuggestedWordIndex(0)
, mDictionaryIndex(0)
@ -436,6 +441,37 @@ nsEditorShell::ResetEditingState()
return NS_OK;
}
// is this a MIME type that we support the editing of, in plain text mode?
const char* const gSupportedTextTypes[] = {
"text/plain",
"text/css",
"text/rdf",
"text/xml",
"text/xsl",
"text/javascript", // obsolete type
"application/x-javascript",
"text/xul", // obsolete type
"application/vnd.mozilla.xul+xml",
NULL // IMPORTANT! Null must be at end
};
PRBool
nsEditorShell::IsSupportedTextType(const char* aMIMEType)
{
PRInt32 i = 0;
while (gSupportedTextTypes[i])
{
if (nsCRT::strcmp(gSupportedTextTypes[i], aMIMEType) == 0)
return PR_TRUE;
i ++;
}
return PR_FALSE;
}
nsresult
nsEditorShell::PrepareDocumentForEditing(nsIDOMWindow* aDOMWindow, nsIURI *aUrl)
{
@ -884,6 +920,21 @@ nsEditorShell::GetEditorType(PRUnichar **_retval)
return NS_OK;
}
/* attribute string contentsMIMEType; */
NS_IMETHODIMP
nsEditorShell::GetContentsMIMEType(char * *aContentsMIMEType)
{
NS_ENSURE_ARG_POINTER(aContentsMIMEType);
*aContentsMIMEType = mContentMIMEType.ToNewCString();
return NS_OK;
}
NS_IMETHODIMP
nsEditorShell::SetContentsMIMEType(const char * aContentsMIMEType)
{
mContentMIMEType.Assign(aContentsMIMEType ? aContentsMIMEType : "");
return NS_OK;
}
nsresult
nsEditorShell::InstantiateEditor(nsIDOMDocument *aDoc, nsIPresShell *aPresShell)
@ -895,58 +946,66 @@ nsEditorShell::InstantiateEditor(nsIDOMDocument *aDoc, nsIPresShell *aPresShell)
if (mEditor)
return NS_ERROR_ALREADY_INITIALIZED;
nsresult err = NS_OK;
nsresult rv = NS_OK;
nsCOMPtr<nsIEditor> editor;
err = nsComponentManager::CreateInstance(kHTMLEditorCID, nsnull, NS_GET_IID(nsIEditor), getter_AddRefs(editor));
if(!editor)
err = NS_ERROR_OUT_OF_MEMORY;
rv = nsComponentManager::CreateInstance(kHTMLEditorCID, nsnull, NS_GET_IID(nsIEditor), getter_AddRefs(editor));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsISelectionController> selCon = do_QueryInterface(aPresShell);
if (NS_SUCCEEDED(err))
if (mEditorTypeString.EqualsWithConversion("text"))
{
if (mEditorTypeString.EqualsWithConversion("text"))
PRInt16 flags = nsIPlaintextEditor::eEditorPlaintextMask | nsIPlaintextEditor::eEditorEnableWrapHackMask;
if (mMailCompose) flags |= nsIPlaintextEditor::eEditorMailMask;
rv = editor->Init(aDoc, aPresShell, nsnull, selCon, flags);
mEditorType = ePlainTextEditorType;
}
else if (mEditorTypeString.EqualsWithConversion("html") || mEditorTypeString.IsEmpty()) // empty string default to HTML editor
{
PRUint32 editorFlags = 0;
EEditorType editorType = eHTMLTextEditorType;
// if the MIME type of the docment we are editing is text/plain, make a text editor
if (IsSupportedTextType(mContentMIMEType))
{
PRInt16 flags = nsIPlaintextEditor::eEditorPlaintextMask | nsIPlaintextEditor::eEditorEnableWrapHackMask;
if (mMailCompose) flags |= nsIPlaintextEditor::eEditorMailMask;
err = editor->Init(aDoc, aPresShell, nsnull, selCon, flags);
mEditorType = ePlainTextEditorType;
editorFlags = nsIPlaintextEditor::eEditorPlaintextMask;
editorType = ePlainTextEditorType;
}
else if (mEditorTypeString.EqualsWithConversion("html") || mEditorTypeString.IsEmpty()) // empty string default to HTML editor
{
err = editor->Init(aDoc, aPresShell, nsnull, selCon, 0);
mEditorType = eHTMLTextEditorType;
}
else if (mEditorTypeString.EqualsWithConversion("htmlmail")) // HTML editor with special mail rules
{
err = editor->Init(aDoc, aPresShell, nsnull, selCon, nsIPlaintextEditor::eEditorMailMask);
mEditorType = eHTMLTextEditorType;
}
else
{
err = NS_ERROR_INVALID_ARG; // this is not an editor we know about
rv = editor->Init(aDoc, aPresShell, nsnull, selCon, editorFlags);
mEditorType = editorType;
}
else if (mEditorTypeString.EqualsWithConversion("htmlmail")) // HTML editor with special mail rules
{
rv = editor->Init(aDoc, aPresShell, nsnull, selCon, nsIPlaintextEditor::eEditorMailMask);
mEditorType = eHTMLTextEditorType;
}
else
{
rv = NS_ERROR_INVALID_ARG; // this is not an editor we know about
#if DEBUG
nsAutoString errorMsg; errorMsg.AssignWithConversion("Failed to init editor. Unknown editor type \"");
errorMsg += mEditorTypeString;
errorMsg.AppendWithConversion("\"\n");
char *errorMsgCString = errorMsg.ToNewCString();
NS_WARNING(errorMsgCString);
nsCRT::free(errorMsgCString);
nsAutoString errorMsg; errorMsg.AssignWithConversion("Failed to init editor. Unknown editor type \"");
errorMsg += mEditorTypeString;
errorMsg.AppendWithConversion("\"\n");
char *errorMsgCString = errorMsg.ToNewCString();
NS_WARNING(errorMsgCString);
nsCRT::free(errorMsgCString);
#endif
}
}
// disable the preference style sheet so we can override colors
if (NS_SUCCEEDED(err)) {
err = aPresShell->EnablePrefStyleRules(PR_FALSE,0);
}
if (NS_SUCCEEDED(rv))
{
rv = aPresShell->EnablePrefStyleRules(PR_FALSE,0);
}
if (NS_SUCCEEDED(err) && editor)
{
mEditor = do_QueryInterface(editor); // this does the addref that is the owning reference
}
if (NS_SUCCEEDED(rv) && editor)
{
mEditor = do_QueryInterface(editor); // this does the addref that is the owning reference
}
return err;
return rv;
}
@ -1688,6 +1747,27 @@ nsEditorShell::CheckOpenWindowForURLMatch(const PRUnichar* inFileURL, nsIDOMWind
return NS_OK;
}
// helper function
static nsresult GetExtensionForMIMEType(const char* inMIMEType, nsACString& outExtension)
{
nsresult rv;
nsCOMPtr<nsIMIMEService> mimeService = do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIMIMEInfo> mimeInfo;
rv = mimeService->GetFromMIMEType(inMIMEType, getter_AddRefs(mimeInfo));
if (NS_FAILED(rv)) return rv;
nsXPIDLCString fileExtension;
rv = mimeInfo->FirstExtension(getter_Copies(fileExtension));
if (NS_FAILED(rv)) return rv;
outExtension.Assign(fileExtension);
return NS_OK;
}
NS_IMETHODIMP
nsEditorShell::SaveDocument(PRBool aSaveAs, PRBool aSaveCopy, const PRUnichar* aMimeType, PRBool *_retval)
{
@ -1696,13 +1776,20 @@ nsEditorShell::SaveDocument(PRBool aSaveAs, PRBool aSaveCopy, const PRUnichar* a
NS_ENSURE_ARG_POINTER((aMimeType));
nsAutoString mimeType(aMimeType);
PRBool saveAsText = mimeType.EqualsWithConversion("text/plain");
nsCAutoString mimeTypeCStr; mimeTypeCStr.AssignWithConversion(aMimeType);
PRBool saveAsText = IsSupportedTextType(mimeTypeCStr);
// Currently, we only understand plain text and html
if (!mimeType.EqualsWithConversion("text/html") && !saveAsText)
if (!mimeTypeCStr.Equals("text/html") && !saveAsText)
return NS_ERROR_FAILURE;
nsAutoString mimeType(aMimeType);
// if we're saving as text, force the text/plain MIME type (because we use this
// to get a content serializer on save)
if (saveAsText)
mimeType.Assign(NS_LITERAL_STRING("text/plain").get());
switch (mEditorType)
{
case ePlainTextEditorType:
@ -1858,11 +1945,12 @@ nsEditorShell::SaveDocument(PRBool aSaveAs, PRBool aSaveCopy, const PRUnichar* a
title.ReplaceChar(" .\\/@:", (PRUnichar)'_');
}
// get the correct extension from the MIME type here
fileName = title;
if (saveAsText)
fileName.AppendWithConversion(".txt");
else
fileName.AppendWithConversion(".html");
nsCAutoString fileExt(saveAsText ? "txt" : "html");
GetExtensionForMIMEType(mimeTypeCStr.get(), fileExt);
fileName.Append(PRUnichar('.'));
fileName.AppendWithConversion(fileExt);
}
else // have a file spec
{
@ -1881,9 +1969,12 @@ nsEditorShell::SaveDocument(PRBool aSaveAs, PRBool aSaveCopy, const PRUnichar* a
index = fileName.RFind(".shtml", PR_TRUE);
if (index > 0)
{
nsCAutoString fileExt("txt");
GetExtensionForMIMEType(mimeTypeCStr.get(), fileExt);
// Truncate after "." and append "txt" extension
fileName.SetLength(index+1);
fileName.AppendWithConversion("txt");
fileName.AppendWithConversion(fileExt);
}
}
@ -4934,6 +5025,8 @@ nsEditorShell::OnStateChange(nsIWebProgress *aProgress,
PRInt32 aStateFlags,
nsresult aStatus)
{
nsresult rv = NS_OK;
//
// A Request has started...
//
@ -4942,7 +5035,8 @@ nsEditorShell::OnStateChange(nsIWebProgress *aProgress,
// Page level notification...
if (aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK)
{
StartPageLoad();
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
StartPageLoad(channel);
}
// Document level notification...
if (aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT)
@ -5013,12 +5107,36 @@ nsEditorShell::OnSecurityChange(nsIWebProgress *aWebProgress,
return NS_OK;
}
nsresult nsEditorShell::StartPageLoad()
nsresult nsEditorShell::StartPageLoad(nsIChannel *aChannel)
{
nsXPIDLCString contentType;
aChannel->GetContentType(getter_Copies(contentType));
// save the original MIME type; we'll use it later
mContentMIMEType.Assign(contentType.get() ? contentType : "");
if (nsCRT::strcmp(contentType, "text/html") == 0)
{
// fine, do nothing
mContentTypeKnown = PR_TRUE;
}
else if (IsSupportedTextType(contentType))
{
// set the mime type to text/plain so that it renders as text
aChannel->SetContentType("text/plain");
mContentTypeKnown = PR_TRUE;
}
else
{
// we don't know what this is yet. It might be HTML loaded from
// a directory URL (http://www.foo.com/). We'll know the real
// MIME type later.
mContentTypeKnown = PR_FALSE;
}
// Start the throbber
// TODO: We should also start/stop it for saving and publishing?
SetChromeAttribute( mDocShell, "Editor:Throbber", "busy",
NS_ConvertASCIItoUCS2("true") );
SetChromeAttribute( mDocShell, "Editor:Throbber", NS_LITERAL_STRING("busy"), NS_LITERAL_STRING("true") );
// set up a parser observer
if (!mParserObserver)
@ -5029,6 +5147,7 @@ nsresult nsEditorShell::StartPageLoad()
}
NS_ADDREF(mParserObserver);
mParserObserver->RegisterTagToWatch("FRAMESET");
mParserObserver->RegisterTagToWatch("IFRAME");
mParserObserver->Start();
}
@ -5048,12 +5167,31 @@ nsresult nsEditorShell::EndPageLoad(nsIDOMWindow *aDOMWindow,
NS_RELEASE(mParserObserver);
}
SetChromeAttribute( mDocShell, "Editor:Throbber", "busy",
NS_ConvertASCIItoUCS2("false") );
SetChromeAttribute( mDocShell, "Editor:Throbber", NS_LITERAL_STRING("busy"), NS_LITERAL_STRING("false") );
// Is this a MIME type we can handle?
if (aChannel)
{
// if we didn't get the content-type at the start of the load, get it now
if (!mContentTypeKnown)
{
nsXPIDLCString contentType;
aChannel->GetContentType(getter_Copies(contentType));
if (contentType.get())
mContentMIMEType.Assign(contentType);
}
}
if ( !mContentMIMEType.Equals("text/html") && !IsSupportedTextType(mContentMIMEType) )
{
mCloseWindowWhenLoaded = PR_TRUE;
mCantEditReason = eCantEditMimeType;
}
nsAutoString doneText;
GetBundleString(NS_LITERAL_STRING("LoadingDone"), doneText);
SetChromeAttribute(mDocShell, "statusText", "label", doneText);
SetChromeAttribute(mDocShell, "statusText", NS_LITERAL_STRING("label"), doneText);
// Display an Alert dialog if the page cannot be edited...
if (mCloseWindowWhenLoaded)
@ -5101,6 +5239,7 @@ nsresult nsEditorShell::EndPageLoad(nsIDOMWindow *aDOMWindow,
{
nsCOMPtr<nsIURI> url;
aChannel->GetURI(getter_AddRefs(url));
(void) PrepareDocumentForEditing(aDOMWindow, url);
}
@ -5143,24 +5282,6 @@ nsresult nsEditorShell::EndDocumentLoad(nsIDOMWindow *aDOMWindow,
nsCOMPtr<nsIRefreshURI> refreshURI = do_QueryInterface(mContentAreaDocShell);
if (refreshURI)
refreshURI->CancelRefreshURITimers();
// Is this a MIME type we can handle?
if (aChannel)
{
char *contentType;
aChannel->GetContentType(&contentType);
if (contentType)
{
if ( (nsCRT::strcmp(contentType, "text/html") != 0) &&
(nsCRT::strcmp(contentType, "text/plain") != 0))
{
mCloseWindowWhenLoaded = PR_TRUE;
mCantEditReason = eCantEditMimeType;
}
nsMemory::Free(contentType);
}
}
return NS_OK;
}

View File

@ -158,7 +158,7 @@ class nsEditorShell : public nsIEditorShell,
nsresult UpdateWindowTitleAndRecentMenu(PRBool aSaveToPrefs);
// Helper method which is called at the beginning of a new page load
nsresult StartPageLoad();
nsresult StartPageLoad(nsIChannel *aChannel);
// Helper method which is called when an entire page load finishes
nsresult EndPageLoad(nsIDOMWindow *aDOMWindow,
@ -174,6 +174,8 @@ class nsEditorShell : public nsIEditorShell,
nsIChannel *aChannel,
nsresult aStatus);
PRBool IsSupportedTextType(const char* aMIMEType);
// Check a preference and call NormalizeTable if pref is true
// Use after deleting or inserting table cells to automatically
// fix rowspan, colspan, and missing cells problems
@ -234,8 +236,11 @@ class nsEditorShell : public nsIEditorShell,
PRPackedBool mCloseWindowWhenLoaded; // error on load. Close window when loaded
ECantEditReason mCantEditReason;
EEditorType mEditorType;
EEditorType mEditorType;
nsString mEditorTypeString; // string which describes which editor type will be instantiated (lowercased)
nsCString mContentMIMEType; // MIME type of the doc we are editing.
PRBool mContentTypeKnown;
PRInt32 mWrapColumn; // can't actually set this 'til the editor is created, so we may have to hold on to it for a while
nsStringArray mSuggestedWordList;

View File

@ -45,6 +45,7 @@ interface nsIEditorShell : nsISupports
attribute nsIDOMWindowInternal webShellWindow;
attribute nsIDOMWindowInternal contentWindow;
attribute wstring editorType;
attribute string contentsMIMEType;
readonly attribute nsIEditor editor;

View File

@ -25,9 +25,6 @@
/* Implementations of nsIControllerCommand for composer commands */
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService);
//-----------------------------------------------------------------------------------
function SetupHTMLEditorCommands()
{
@ -39,7 +36,9 @@ function SetupHTMLEditorCommands()
// Include everthing a text editor does
SetupTextEditorCommands();
dump("Registering HTML editor commands\n");
//dump("Registering HTML editor commands\n");
controller.registerCommand("cmd_renderedHTMLEnabler", nsDummyHTMLCommand);
controller.registerCommand("cmd_listProperties", nsListPropertiesCommand);
controller.registerCommand("cmd_pageProperties", nsPagePropertiesCommand);
@ -92,7 +91,7 @@ function SetupTextEditorCommands()
if (!controller)
return;
dump("Registering plain text editor commands\n");
//dump("Registering plain text editor commands\n");
controller.registerCommand("cmd_find", nsFindCommand);
controller.registerCommand("cmd_findNext", nsFindNextCommand);
@ -179,7 +178,7 @@ function SetupComposerWindowCommands()
function GetEditorController()
{
var numControllers = window._content.controllers.getControllerCount();
// count down to find a controller that supplies a nsIControllerCommandManager interface
for (var i = numControllers; i >= 0 ; i --)
{
@ -187,11 +186,16 @@ function GetEditorController()
try {
var controller = window._content.controllers.getControllerAt(i);
var interfaceRequestor = controller.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
if (!interfaceRequestor) continue;
commandManager = interfaceRequestor.getInterface(Components.interfaces.nsIControllerCommandManager);
} catch(ex) {}
}
catch(ex)
{
//dump(ex + "\n");
}
if (commandManager)
return commandManager;
@ -240,6 +244,22 @@ function PrintNodeID(id)
PrintObject(document.getElementById(id));
}
//-----------------------------------------------------------------------------------
var nsDummyHTMLCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML());
},
doCommand: function(aCommand)
{
// do nothing
dump("Hey, who's calling the dummy command?\n");
}
};
//-----------------------------------------------------------------------------------
var nsOpenCommand =
{
@ -295,7 +315,7 @@ var nsSaveCommand =
{
FinishHTMLSource(); // In editor.js
var doSaveAs = window.editorShell.editorDocument.location == "about:blank";
var result = window.editorShell.saveDocument(doSaveAs, false, window.gDefaultSaveMimeType);
var result = window.editorShell.saveDocument(doSaveAs, false, editorShell.contentsMIMEType);
window._content.focus();
return result;
}
@ -315,7 +335,7 @@ var nsSaveAsCommand =
if (window.editorShell)
{
FinishHTMLSource();
var result = window.editorShell.saveDocument(true, false, window.gDefaultSaveMimeType);
var result = window.editorShell.saveDocument(true, false, editorShell.contentsMIMEType);
window._content.focus();
return result;
}
@ -363,7 +383,7 @@ var nsSaveAsCharsetCommand =
}
else
{
window.ok = window.editorShell.saveDocument(true, false, window.gDefaultSaveMimeType);
window.ok = window.editorShell.saveDocument(true, false, editorShell.contentsMIMEType);
}
}
window._content.focus();
@ -384,6 +404,9 @@ var nsRevertCommand =
doCommand: function(aCommand)
{
// Confirm with the user to abandon current changes
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService);
if (promptService)
{
var result = {value:0};
@ -477,7 +500,7 @@ var nsPreviewCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (window.editorShell != null && (DocumentHasBeenSaved() || window.editorShell.documentModified));
return (window.editorShell && IsEditorContentHTML() && (DocumentHasBeenSaved() || window.editorShell.documentModified));
},
doCommand: function(aCommand)
@ -612,7 +635,7 @@ var nsImageCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (window.editorShell && window.editorShell.documentEditable);
return (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML());
},
doCommand: function(aCommand)
{
@ -626,7 +649,7 @@ var nsHLineCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (window.editorShell && window.editorShell.documentEditable);
return (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML());
},
doCommand: function(aCommand)
{
@ -695,7 +718,7 @@ var nsLinkCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (window.editorShell && window.editorShell.documentEditable);
return (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML());
},
doCommand: function(aCommand)
{
@ -709,7 +732,7 @@ var nsAnchorCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (window.editorShell && window.editorShell.documentEditable);
return (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML());
},
doCommand: function(aCommand)
{
@ -723,7 +746,7 @@ var nsInsertHTMLCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (window.editorShell && window.editorShell.documentEditable);
return (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML());
},
doCommand: function(aCommand)
{
@ -737,7 +760,7 @@ var nsInsertCharsCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (window.editorShell && window.editorShell.documentEditable);
return (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML());
},
doCommand: function(aCommand)
{
@ -750,7 +773,7 @@ var nsInsertBreakCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (window.editorShell && window.editorShell.documentEditable);
return (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML());
},
doCommand: function(aCommand)
{
@ -763,7 +786,7 @@ var nsInsertBreakAllCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (window.editorShell && window.editorShell.documentEditable);
return (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML());
},
doCommand: function(aCommand)
{
@ -776,7 +799,7 @@ var nsListPropertiesCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (window.editorShell && window.editorShell.documentEditable);
return (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML());
},
doCommand: function(aCommand)
{
@ -791,7 +814,7 @@ var nsPagePropertiesCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (window.editorShell && window.editorShell.documentEditable);
return (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML());
},
doCommand: function(aCommand)
{
@ -806,7 +829,7 @@ var nsObjectPropertiesCommand =
isCommandEnabled: function(aCommand, dummy)
{
var isEnabled = false;
if (window.editorShell && window.editorShell.documentEditable)
if (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML())
{
isEnabled = (GetObjectForProperties() != null ||
window.editorShell.GetSelectedElement("href") != null);
@ -870,7 +893,7 @@ var nsSetSmiley =
{
isCommandEnabled: function(aCommand, dummy)
{
return ( window.editorShell && window.editorShell.documentEditable);
return ( window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML());
},
@ -959,7 +982,7 @@ var nsAdvancedPropertiesCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (window.editorShell && window.editorShell.documentEditable);
return (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML());
},
doCommand: function(aCommand)
{
@ -974,7 +997,7 @@ var nsColorPropertiesCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (window.editorShell && window.editorShell.documentEditable);
return (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML());
},
doCommand: function(aCommand)
{
@ -989,7 +1012,7 @@ var nsRemoveLinksCommand =
isCommandEnabled: function(aCommand, dummy)
{
// We could see if there's any link in selection, but it doesn't seem worth the work!
return (window.editorShell && window.editorShell.documentEditable);
return (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML());
},
doCommand: function(aCommand)
{
@ -1004,7 +1027,7 @@ var nsNormalModeCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return true; //(window.editorShell && window.editorShell.documentEditable);
return IsEditorContentHTML(); //(window.editorShell && window.editorShell.documentEditable);
},
doCommand: function(aCommand)
{
@ -1017,7 +1040,7 @@ var nsAllTagsModeCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (window.editorShell && window.editorShell.documentEditable);
return (window.editorShell && window.editorShell.documentEditable && IsEditorContentHTML());
},
doCommand: function(aCommand)
{
@ -1030,7 +1053,7 @@ var nsHTMLSourceModeCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (window.editorShell && window.editorShell.documentEditable);
return (window.editorShell && window.editorShell.documentEditable && IsEditorContentHTML());
},
doCommand: function(aCommand)
{
@ -1043,7 +1066,7 @@ var nsPreviewModeCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (window.editorShell && window.editorShell.documentEditable);
return (window.editorShell && window.editorShell.documentEditable && IsEditorContentHTML());
},
doCommand: function(aCommand)
{
@ -1058,7 +1081,7 @@ var nsInsertOrEditTableCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (window.editorShell && window.editorShell.documentEditable);
return (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML());
},
doCommand: function(aCommand)
{
@ -1153,7 +1176,7 @@ var nsInsertTableCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (window.editorShell && window.editorShell.documentEditable);
return window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML();
},
doCommand: function(aCommand)
{
@ -1359,7 +1382,7 @@ var nsJoinTableCellsCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
if (window.editorShell && window.editorShell.documentEditable)
if (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML())
{
var tagNameObj = new Object;
var countObj = new Object;
@ -1407,7 +1430,7 @@ var nsSplitTableCellCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
if (window.editorShell && window.editorShell.documentEditable)
if (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML())
{
var tagNameObj = new Object;
var countObj = new Object;
@ -1507,6 +1530,8 @@ var nsConvertToTable =
{
isCommandEnabled: function(aCommand, dummy)
{
if (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML())
{
var selection = window.editorShell.editorSelection;
if (selection && !selection.isCollapsed)
@ -1525,6 +1550,7 @@ var nsConvertToTable =
return false
return true;
}
}
return false;
},
@ -1537,3 +1563,4 @@ var nsConvertToTable =
window._content.focus();
}
};

View File

@ -70,7 +70,6 @@ var gColorObj = new Object();
var gPrefs;
var gDefaultTextColor = "";
var gDefaultBackgroundColor = "";
var gDefaultSaveMimeType = "text/html";
// These must be kept in synch with the XUL <options> lists
var gFontSizeNames = new Array("xx-small","x-small","small","medium","large","x-large","xx-large");
@ -110,6 +109,17 @@ function PageIsEmptyAndUntouched()
return (editorShell != null) && (editorShell.documentIsEmpty == true) && (docWasModified == false);
}
function IsEditorContentHTML()
{
return (editorShell.contentsMIMEType == "text/html");
}
// are we editing HTML (i.e. neither in HTML source mode, nor editing a text file)
function IsEditingRenderedHTML()
{
return IsEditorContentHTML() && (gEditorDisplayMode != DisplayModeSource);
}
// This is called when the real editor document is created,
// before it's loaded.
var DocumentStateListener =
@ -189,7 +199,7 @@ function EditorStartup(editorType, editorElement)
EditorSharedStartup();
// Commands specific to the Composer Application window,
// (i.e., not embeded editors)
// (i.e., not embedded editors)
// such as file-related commands, HTML Source editing, Edit Modes...
SetupComposerWindowCommands();
@ -211,17 +221,17 @@ function EditorSharedStartup()
case "html":
case "htmlmail":
SetupHTMLEditorCommands();
window.gDefaultSaveMimeType = "text/html";
editorShell.contentsMIMEType = "text/html";
break;
case "text":
case "textmail":
SetupTextEditorCommands();
window.gDefaultSaveMimeType = "text/plain";
editorShell.contentsMIMEType = "text/plain";
break;
default:
dump("INVALID EDITOR TYPE: "+editorShell.editorType+"\n");
SetupTextEditorCommands();
window.gDefaultSaveMimeType = "text/plain";
editorShell.contentsMIMEType = "text/plain";
break;
}
@ -395,6 +405,9 @@ function CheckAndSaveDocument(reasonToSave, allowDontSave)
var dialogMsg = window.editorShell.GetString("SaveFilePrompt");
dialogMsg = (dialogMsg.replace(/%title%/,title)).replace(/%reason%/,reasonToSave);
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService);
var result = {value:0};
promptService.confirmEx(window, dialogTitle, dialogMsg,
(promptService.BUTTON_TITLE_SAVE * promptService.BUTTON_POS_0) +
@ -406,7 +419,7 @@ function CheckAndSaveDocument(reasonToSave, allowDontSave)
if (result.value == 0)
{
// Save
var success = window.editorShell.saveDocument(false, false, window.gDefaultSaveMimeType);
var success = window.editorShell.saveDocument(false, false, editorShell.contentsMIMEType);
return success;
}
@ -1230,15 +1243,15 @@ function SetDisplayMode(mode)
// Switch to the sourceWindow (second in the deck)
gContentWindowDeck.setAttribute("index","1");
DisableMenusForHTMLSource(true);
//Hide the formating toolbar if not already hidden
//Hide the formatting toolbar if not already hidden
gFormatToolbarHidden = gFormatToolbar.getAttribute("hidden");
if (gFormatToolbarHidden != "true")
{
gFormatToolbar.setAttribute("hidden", "true");
}
// update commands to disable stuff
window.updateCommands("mode_switch");
gSourceContentWindow.focus();
}
else
@ -1247,13 +1260,14 @@ function SetDisplayMode(mode)
gContentWindowDeck.setAttribute("index","0");
// Restore menus and toolbars
DisableMenusForHTMLSource(false);
if (gFormatToolbarHidden != "true")
{
gFormatToolbar.setAttribute("hidden", gFormatToolbarHidden);
}
// update commands to re-enable stuff
window.updateCommands("mode_switch");
gContentWindow.focus();
}
@ -1287,51 +1301,6 @@ function SetDisplayMode(mode)
return false;
}
// We disable all items in View menu except Edit mode and sidebar items
function DisableMenusForHTMLSource(disable)
{
// Disable toolbar buttons
DisableItem("spellingButton", disable);
DisableItem("imageButton", disable);
DisableItem("hlineButton", disable);
DisableItem("tableButton", disable);
DisableItem("linkButton", disable);
DisableItem("namedAnchorButton", disable);
// Any toolbar can be toggled on/off except the format toolbar
DisableItem("viewFormatToolbar", disable);
// Top-level menus that we completely hide
CollapseItem("insertMenu", disable);
CollapseItem("formatMenu", disable);
CollapseItem("tableMenu", disable);
// Edit menu items
DisableItem("menu_find", disable);
DisableItem("menu_findnext", disable);
DisableItem("menu_replace", disable);
DisableItem("menu_checkspelling", disable);
// Disable all items in the view menu except mode switch items
var viewMenu = document.getElementById("viewMenu");
// menuitems are children of the menupopup child
var children = viewMenu.firstChild.childNodes;
for (var i = 0; i < children.length; i++)
{
var item = children.item(i);
if (item.id != "viewToolbar" &&
item.id != "viewNormalMode" &&
item.id != "viewAllTagsMode" &&
item.id != "viewSourceMode" &&
item.id != "viewPreviewMode" &&
item.id != "sidebar-menu")
{
DisableItem(item.id, disable);
}
}
}
function EditorToggleParagraphMarks()
{
var menuItem = document.getElementById("viewParagraphMarks");
@ -1529,8 +1498,10 @@ function getUnicharPref(aPrefName, aDefVal)
function EditorInitFormatMenu()
{
InitObjectPropertiesMenuitem("objectProperties");
InitRemoveStylesMenuitems("removeStylesMenuitem", "removeLinksMenuitem");
try {
InitObjectPropertiesMenuitem("objectProperties");
InitRemoveStylesMenuitems("removeStylesMenuitem", "removeLinksMenuitem");
} catch(ex) {}
// Set alignment check
}
@ -1542,10 +1513,13 @@ function InitObjectPropertiesMenuitem(id)
var menuItem = document.getElementById(id);
if (!menuItem) return null;
var element = GetObjectForProperties();
var element;
var menuStr = GetString("ObjectProperties");
var name;
if (IsEditingRenderedHTML())
element = GetObjectForProperties();
if (element && element.nodeName)
{
var objStr = "";
@ -1671,6 +1645,18 @@ function InitAlignMenu()
function EditorInitToolbars()
{
// Nothing to do now, but we might want some state updating here
if (!IsEditorContentHTML())
{
//Hide the formating toolbar
gFormatToolbar.setAttribute("hidden", "true");
//Hide the edit mode toolbar
gEditModeBar.setAttribute("hidden", "true");
DisableItem("cmd_viewFormatToolbar", true);
DisableItem("cmd_viewEditModeToolbar", true);
}
}
function EditorSetDefaultPrefsAndDoctype()
@ -2044,7 +2030,7 @@ function IsSpellCheckerInstalled()
var spellcheckerClass = Components.classes["@mozilla.org/spellchecker;1"];
gHaveSpellChecker = (spellcheckerClass != null);
gSoughtSpellChecker = true;
dump("Have SpellChecker = "+gHaveSpellChecker+"\n");
//dump("Have SpellChecker = "+gHaveSpellChecker+"\n");
return gHaveSpellChecker;
}
@ -2059,7 +2045,7 @@ function IsFindInstalled()
var findClass = Components.classes["@mozilla.org/appshell/component/find;1"];
gHaveFind = (findClass != null);
gSoughtFind = true;
dump("Have Find = "+gHaveFind+"\n");
//dump("Have Find = "+gHaveFind+"\n");
return gHaveFind;
}
@ -2139,7 +2125,9 @@ function GetPrefsService()
// with this "oncreate" hander:
function EditorInitTableMenu()
{
InitJoinCellMenuitem("menu_JoinTableCells");
try {
InitJoinCellMenuitem("menu_JoinTableCells");
} catch (ex) {}
// Set enable states for all table commands
goUpdateTableMenuItems(document.getElementById("composerTableMenuItems"));
@ -2159,7 +2147,12 @@ function InitJoinCellMenuitem(id)
// Use "Join selected cells if there's more than 1 cell selected
var tagNameObj = new Object;
var countObj = new Object;
if (window.editorShell.GetSelectedOrParentTableElement(tagNameObj, countObj) && countObj.value > 1)
var foundElement;
if (IsEditingRenderedHTML())
foundElement = window.editorShell.GetSelectedOrParentTableElement(tagNameObj, countObj);
if (foundElement && countObj.value > 1)
menuText = GetString("JoinSelectedCells");
else
menuText = GetString("JoinCellToRight");
@ -2195,9 +2188,9 @@ function InitRemoveStylesMenuitems(removeStylesId, removeLinksId)
function goUpdateTableMenuItems(commandset)
{
var enabled = false;
var enabledIfTable = false;
if (window.editorShell && window.editorShell.documentEditable)
if (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML())
{
var selectedCountObj = new Object();
var tagNameObj = new Object();
@ -2246,13 +2239,13 @@ function goUpdateTableMenuItems(commandset)
function IsInTable()
{
return (window.editorShell && window.editorShell.documentEditable &&
return (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML() &&
null != window.editorShell.GetElementOrParentByTagName("table", null));
}
function IsInTableCell()
{
return (window.editorShell && window.editorShell.documentEditable &&
return (window.editorShell && window.editorShell.documentEditable && IsEditingRenderedHTML() &&
null != window.editorShell.GetElementOrParentByTagName("td", null));
}
@ -2476,3 +2469,4 @@ function SwitchInsertCharToAnotherEditorOrClose()
window.InsertCharWindow.close();
}
}

View File

@ -250,7 +250,7 @@
</box>
</deck>
<box id="EditModeToolbar" hidden="false" autostretch="never" valign="middle" persist="hidden collapsed">
<box id="EditModeToolbar" hidden="false" autostretch="never" valign="middle" persist="collapsed">
<tabs id="EditModeTabs" class="tabs-bottom" flex="1">
<tab id="NormalModeButton"/>
<tab id="TagModeButton"/>

View File

@ -93,7 +93,7 @@
<commandset id="composerMenuItems"
commandupdater="true"
events="create"
events="create, mode_switch"
oncommandupdate="goUpdateComposerMenuItems(this)"
>
<!-- format menu -->
@ -116,6 +116,9 @@
<command id="cmd_AllTagsMode" oncommand="goDoCommand('cmd_AllTagsMode')" label="&AllTagsMode.label;"/>
<command id="cmd_HTMLSourceMode" oncommand="goDoCommand('cmd_HTMLSourceMode')"/>
<command id="cmd_PreviewMode" oncommand="goDoCommand('cmd_PreviewMode')" label="&PreviewMode.label;"/>
<!-- dummy command used just to disable things in non-HTML modes -->
<command id="cmd_renderedHTMLEnabler"/>
</commandset>
<commandset id="composerSaveMenuItems"
@ -129,7 +132,8 @@
<command id="cmd_saveAsCharset" label="&saveAsCharsetCmd.label;" oncommand="goDoCommand('cmd_saveAsCharset')"/>
<command id="cmd_revert" label="&fileRevert.label;" oncommand="goDoCommand('cmd_revert')"/>
<command id="cmd_preview" oncommand="goDoCommand('cmd_preview')"/>
<command id="cmd_editSendPage" label="&sendPageCmd.label;" accesskey="&sendPage.accesskey;" oncommand="goDoCommand('cmd_editSendPage')"/>
<command id="cmd_editSendPage" label="&sendPageCmd.label;"
accesskey="&sendPage.accesskey;" oncommand="goDoCommand('cmd_editSendPage')"/>
</commandset>
@ -160,7 +164,7 @@
<!-- style related commands that update on creation, and on selection change -->
<commandset id="composerStyleMenuItems"
commandupdater="true"
events="create, style"
events="create, style, mode_switch"
oncommandupdate="goUpdateComposerMenuItems(this)"
>
<command id="cmd_bold" state="false" oncommand="goDoCommand('cmd_bold')"/>
@ -209,14 +213,21 @@
</commandset>
<!-- commands updated only when the menu gets created -->
<commandset id="composerListMenuItems" oncommandupdate="goUpdateComposerMenuItems(this)">
<commandset id="composerListMenuItems"
commandupdater="true"
events="create, mode_switch"
oncommandupdate="goUpdateComposerMenuItems(this)">
<!-- List menu -->
<command id="cmd_dt" oncommand="goDoCommand('cmd_dt')"/>
<command id="cmd_dd" oncommand="goDoCommand('cmd_dd')"/>
<command id="cmd_removeList" oncommand="goDoCommand('cmd_removeList')"/>
<!-- cmd_ul and cmd_ol are shared with toolbar and are in composerStyleMenuItems commandset -->
</commandset>
<commandset id="composerTableMenuItems" oncommandupdate="goUpdateTableMenuItems(this)">
<commandset id="composerTableMenuItems"
commandupdater="true"
events="create, mode_switch"
oncommandupdate="goUpdateTableMenuItems(this)">
<!-- Table menu -->
<command id="cmd_SelectTable" oncommand="goDoCommand('cmd_SelectTable')"/>
<command id="cmd_SelectRow" oncommand="goDoCommand('cmd_SelectRow')"/>
@ -254,7 +265,7 @@
<command id="cmd_viewCompToolbar" oncommand="goToggleToolbar('EditToolbar','cmd_viewCompToolbar');" checked="true"/>
<command id="cmd_viewFormatToolbar" oncommand="goToggleToolbar('FormatToolbar','cmd_viewFormatToolbar');" checked="true"/>
<command id="cmd_viewEditModeToolbar" oncommand="goToggleToolbar('EditModeToolbar','cmd_viewEditModeToolbar');" checked="true"/>
<command id="cmd_viewtaskbar" oncommand="goToggleToolbar('status-bar','cmd_viewtaskbar');" checked="true"/>
<command id="cmd_viewtaskbar" oncommand="goToggleToolbar('status-bar','cmd_viewtaskbar');" checked="true"/>
<!-- Obsolete; these will go away -->
<command id="Editor:Font:Size" fontsize=""/>
@ -380,12 +391,12 @@
<menu id="fontFaceMenu" label="&fontfaceMenu.label;" accesskey="&formatfontmenu.accesskey;"
position="1">
<menupopup oncommand="doStatefulCommand('cmd_fontFace', event.target.value)" oncreate="initFontFaceMenu(this)">
<menuitem label="&fontVarWidth.label;" accesskey="&fontvarwidth.accesskey;" value="" type="radio" name="1"/>
<menuitem label="&fontFixedWidth.label;" accesskey="&fontfixedwidth.accesskey;" value="tt" type="radio" name="1" key="fontfixedwidthkb"/>
<menuitem label="&fontVarWidth.label;" accesskey="&fontvarwidth.accesskey;" value="" type="radio" name="1" observes="cmd_renderedHTMLEnabler"/>
<menuitem label="&fontFixedWidth.label;" accesskey="&fontfixedwidth.accesskey;" value="tt" type="radio" name="1" key="fontfixedwidthkb" observes="cmd_renderedHTMLEnabler"/>
<menuseparator/>
<menuitem label="&fontHelveticaFont.label;" accesskey="&fonthelvetica.accesskey;" value="Helvetica, Arial, sans-serif" type="radio" name="2" />
<menuitem label="&fontTimes.label;" accesskey="&fonttimes.accesskey;" value="Times New Roman, Times, serif" type="radio" name="2" />
<menuitem label="&fontCourier.label;" accesskey="&fontcourier.accesskey;" value="Courier New, Courier, monospace" type="radio" name="2" />
<menuitem label="&fontHelveticaFont.label;" accesskey="&fonthelvetica.accesskey;" value="Helvetica, Arial, sans-serif" type="radio" name="2" observes="cmd_renderedHTMLEnabler"/>
<menuitem label="&fontTimes.label;" accesskey="&fonttimes.accesskey;" value="Times New Roman, Times, serif" type="radio" name="2" observes="cmd_renderedHTMLEnabler"/>
<menuitem label="&fontCourier.label;" accesskey="&fontcourier.accesskey;" value="Courier New, Courier, monospace" type="radio" name="2" observes="cmd_renderedHTMLEnabler"/>
</menupopup>
</menu>
@ -400,12 +411,12 @@
<!-- Not supported in current font size implementation
<menuitem label="&size-xx-smallCmd.label;" accesskey="&size-xx-small.accesskey;" oncommand="EditorSetFontSize('xx-small')" type="radio" name="2" />
-->
<menuitem label="&size-x-smallCmd.label;" accesskey="&size-x-small.accesskey;" oncommand="EditorSetFontSize('x-small')" type="radio" name="2" />
<menuitem label="&size-smallCmd.label;" accesskey="&size-small.accesskey;" oncommand="EditorSetFontSize('small')" type="radio" name="2" />
<menuitem label="&size-mediumCmd.label;" accesskey="&size-medium.accesskey;" oncommand="EditorSetFontSize('medium')" type="radio" name="2" />
<menuitem label="&size-largeCmd.label;" accesskey="&size-large.accesskey;" oncommand="EditorSetFontSize('large')" type="radio" name="2" />
<menuitem label="&size-x-largeCmd.label;" accesskey="&size-x-large.accesskey;" oncommand="EditorSetFontSize('x-large')" type="radio" name="2" />
<menuitem label="&size-xx-largeCmd.label;" accesskey="&size-xx-large.accesskey;" oncommand="EditorSetFontSize('xx-large')" type="radio" name="2" />
<menuitem label="&size-x-smallCmd.label;" accesskey="&size-x-small.accesskey;" oncommand="EditorSetFontSize('x-small')" type="radio" name="2" observes="cmd_renderedHTMLEnabler"/>
<menuitem label="&size-smallCmd.label;" accesskey="&size-small.accesskey;" oncommand="EditorSetFontSize('small')" type="radio" name="2" observes="cmd_renderedHTMLEnabler"/>
<menuitem label="&size-mediumCmd.label;" accesskey="&size-medium.accesskey;" oncommand="EditorSetFontSize('medium')" type="radio" name="2" observes="cmd_renderedHTMLEnabler"/>
<menuitem label="&size-largeCmd.label;" accesskey="&size-large.accesskey;" oncommand="EditorSetFontSize('large')" type="radio" name="2" observes="cmd_renderedHTMLEnabler"/>
<menuitem label="&size-x-largeCmd.label;" accesskey="&size-x-large.accesskey;" oncommand="EditorSetFontSize('x-large')" type="radio" name="2" observes="cmd_renderedHTMLEnabler"/>
<menuitem label="&size-xx-largeCmd.label;" accesskey="&size-xx-large.accesskey;" oncommand="EditorSetFontSize('xx-large')" type="radio" name="2" observes="cmd_renderedHTMLEnabler"/>
</menupopup>
</menu>
@ -435,7 +446,8 @@
<menuitem id="fontColor" label="&formatFontColor.label;"
accesskey="&formatfontcolor.accesskey;"
oncommand="EditorSelectColor('Text', null);"
observes="cmd_fontColor"
oncommand="goDoCommand('cmd_fontColor')"
position="4"/>
<menuseparator position="5"/>
@ -457,18 +469,18 @@
accesskey="&formatparagraphmenu.accesskey;"
position="9" oncreate="InitParagraphMenu()">
<menupopup oncommand="doStatefulCommand('cmd_paragraphState', event.target.getAttribute('value'))">
<menuitem id="menu_bodyText" type="radio" name="1" label="&bodyTextCmd.label;" accesskey="&bodytext.accesskey;" value=""/>
<menuitem id="menu_p" type="radio" name="1" label="&paragraphParagraphCmd.label;" accesskey="&paragraphparagraph.accesskey;" value="p"/>
<menuitem id="menu_h1" type="radio" name="1" label="&heading1Cmd.label;" accesskey="&heading1.accesskey;" value="h1"/>
<menuitem id="menu_h2" type="radio" name="1" label="&heading2Cmd.label;" accesskey="&heading2.accesskey;" value="h2"/>
<menuitem id="menu_h3" type="radio" name="1" label="&heading3Cmd.label;" accesskey="&heading3.accesskey;" value="h3"/>
<menuitem id="menu_h4" type="radio" name="1" label="&heading4Cmd.label;" accesskey="&heading4.accesskey;" value="h4"/>
<menuitem id="menu_h5" type="radio" name="1" label="&heading5Cmd.label;" accesskey="&heading5.accesskey;" value="h5"/>
<menuitem id="menu_h6" type="radio" name="1" label="&heading6Cmd.label;" accesskey="&heading6.accesskey;" value="h6"/>
<menuitem id="menu_address" type="radio" name="1" label="&paragraphAddressCmd.label;" accesskey="&paragraphaddress.accesskey;" value="address"/>
<menuitem id="menu_pre" type="radio" name="1" label="&paragraphPreformatCmd.label;" accesskey="&paragraphpreformat.accesskey;" value="pre"/>
<menuitem id="menu_bodyText" type="radio" name="1" label="&bodyTextCmd.label;" accesskey="&bodytext.accesskey;" value="" observes="cmd_renderedHTMLEnabler"/>
<menuitem id="menu_p" type="radio" name="1" label="&paragraphParagraphCmd.label;" accesskey="&paragraphparagraph.accesskey;" value="p" observes="cmd_renderedHTMLEnabler"/>
<menuitem id="menu_h1" type="radio" name="1" label="&heading1Cmd.label;" accesskey="&heading1.accesskey;" value="h1" observes="cmd_renderedHTMLEnabler"/>
<menuitem id="menu_h2" type="radio" name="1" label="&heading2Cmd.label;" accesskey="&heading2.accesskey;" value="h2" observes="cmd_renderedHTMLEnabler"/>
<menuitem id="menu_h3" type="radio" name="1" label="&heading3Cmd.label;" accesskey="&heading3.accesskey;" value="h3" observes="cmd_renderedHTMLEnabler"/>
<menuitem id="menu_h4" type="radio" name="1" label="&heading4Cmd.label;" accesskey="&heading4.accesskey;" value="h4" observes="cmd_renderedHTMLEnabler"/>
<menuitem id="menu_h5" type="radio" name="1" label="&heading5Cmd.label;" accesskey="&heading5.accesskey;" value="h5" observes="cmd_renderedHTMLEnabler"/>
<menuitem id="menu_h6" type="radio" name="1" label="&heading6Cmd.label;" accesskey="&heading6.accesskey;" value="h6" observes="cmd_renderedHTMLEnabler"/>
<menuitem id="menu_address" type="radio" name="1" label="&paragraphAddressCmd.label;" accesskey="&paragraphaddress.accesskey;" value="address" observes="cmd_renderedHTMLEnabler"/>
<menuitem id="menu_pre" type="radio" name="1" label="&paragraphPreformatCmd.label;" accesskey="&paragraphpreformat.accesskey;" value="pre" observes="cmd_renderedHTMLEnabler"/>
<menuseparator/>
<menuitem id="menu_blockquote" type="checkbox" label="&paragraphBlockquoteCmd.label;" accesskey="&paragraphblockquote.accesskey;" value="blockquote"/>
<menuitem id="menu_blockquote" type="checkbox" label="&paragraphBlockquoteCmd.label;" accesskey="&paragraphblockquote.accesskey;" value="blockquote" observes="cmd_renderedHTMLEnabler"/>
</menupopup>
</menu>
@ -498,10 +510,10 @@
position="14">
<!-- Align submenu -->
<menupopup oncommand="doStatefulCommand('cmd_align', event.target.getAttribute('value'))">
<menuitem id="menu_left" label="&alignLeft.label;" accesskey="&alignleft.accesskey;" type="radio" name="1" value="left"/>
<menuitem id="menu_center" label="&alignCenter.label;" accesskey="&aligncenter.accesskey;" type="radio" name="1" value="center"/>
<menuitem id="menu_right" label="&alignRight.label;" accesskey="&alignright.accesskey;" type="radio" name="1" value="right"/>
<menuitem id="menu_justify" label="&alignJustify.label;" accesskey="&alignjustify.accesskey;" type="radio" name="1" value="justify"/>
<menuitem id="menu_left" label="&alignLeft.label;" accesskey="&alignleft.accesskey;" type="radio" name="1" value="left" observes="cmd_renderedHTMLEnabler"/>
<menuitem id="menu_center" label="&alignCenter.label;" accesskey="&aligncenter.accesskey;" type="radio" name="1" value="center" observes="cmd_renderedHTMLEnabler"/>
<menuitem id="menu_right" label="&alignRight.label;" accesskey="&alignright.accesskey;" type="radio" name="1" value="right" observes="cmd_renderedHTMLEnabler"/>
<menuitem id="menu_justify" label="&alignJustify.label;" accesskey="&alignjustify.accesskey;" type="radio" name="1" value="justify" observes="cmd_renderedHTMLEnabler"/>
</menupopup>
</menu>
<menuseparator position="15"/>
@ -511,15 +523,12 @@
<!-- Next 3 are items to append at the bottom of the formatMenuPopup -->
<!-- label and accesskey filled in during menu creation -->
<menuitem id="objectProperties"
oncommand="goDoCommand('cmd_objectProperties')"/>
<menuitem id="objectProperties" oncommand="goDoCommand('cmd_objectProperties')" observes="cmd_renderedHTMLEnabler"/>
<!-- Dont use 'observes', must call command correctly -->
<menuitem id="pageProperties" label="&pageProperties.label;"
accesskey="&pageproperties.accesskey;"
oncommand="goDoCommand('cmd_pageProperties')"/>
<menuitem id="colorsAndBackground" label="&colorsAndBackground.label;"
accesskey="&colorsandbackground.accesskey;"
oncommand="goDoCommand('cmd_colorProperties')"/>
<menuitem id="pageProperties" label="&pageProperties.label;" accesskey="&pageproperties.accesskey;"
oncommand="goDoCommand('cmd_pageProperties')" observes="cmd_renderedHTMLEnabler"/>
<menuitem id="colorsAndBackground" label="&colorsAndBackground.label;" accesskey="&colorsandbackground.accesskey;"
oncommand="goDoCommand('cmd_colorProperties')" observes="cmd_renderedHTMLEnabler"/>
<menu id="tableMenu" label="&tableMenu.label;" accesskey="&tablemenu.accesskey;">
<menupopup oncreate="EditorInitTableMenu()">