Index: public/nsIMsgCompose.idl
===================================================================
RCS file: /cvsroot/mozilla/mailnews/compose/public/nsIMsgCompose.idl,v
retrieving revision 1.30
diff -u -r1.30 nsIMsgCompose.idl
--- nsIMsgCompose.idl 2000/08/08 04:44:04 1.30
+++ nsIMsgCompose.idl 2000/08/20 16:57:06
@@ -84,12 +84,29 @@
[scriptable, uuid(f38ea280-e090-11d3-a449-e3153319347c)]
interface nsIMsgCompSendFormat {
- const long AskUser = 0;
+ const long AskUser = 4; /* Hack: Bug 44512. If this is 0 and passed
+ as results.action to the askSendFormat
+ dialog, the args object gets destroyed.*/
const long PlainText = 1;
const long HTML = 2;
const long Both = 3;
};
+[scriptable, uuid(9638af92-1dd1-11b2-bef1-ca5fee0abc62)]
+interface nsIMsgCompConvertible/*ToTXT*/ {
+ const long Plain = 1; // Like 4.x: Only ,
,
, ...
+ const long Yes = 2; // *Minor* alterations of the look:
, - , ...
+ const long Altering = 3; /* Look altered: , ,
, ...
+ Can be expressed in plaintext, but not in
+ the way it looked in the HTML composer. */
+ const long No = 4; /* Will lose data: , ...
+ Really *requires* visual formatting or
+ is not supported by our HTML->TXT converter. */
+ /* The values here have meaning, they are "levels":
+ convertible({a; b}) == max(convertible({a}), convertible({b}))
+ must be true, i.e. the higher value counts. */
+};
+
[scriptable, uuid(e72c6981-992a-11d3-a449-eb15bb19bc7c)]
interface nsIMsgComposeStateListener : nsISupports
{
@@ -146,9 +163,10 @@
*/
wstring GetNoHtmlNewsgroups(in wstring newsgroups);
- /* BodyContainsHTMLTag: will return true if the node passed contains any HTML tag that really affect the formating
+ /* bodyConvertible: The level of "convertibility" to plaintext
+ * @return a value from nsIMsgCompConvertible
*/
- boolean BodyContainsHTMLTag(in nsIDOMNode node);
+ long bodyConvertible(in nsIDOMNode node);
/* SetSignature: will replace the curr.
*/
Index: resources/content/MsgComposeCommands.js
===================================================================
RCS file: /cvsroot/mozilla/mailnews/compose/resources/content/MsgComposeCommands.js,v
retrieving revision 1.113
diff -u -r1.113 MsgComposeCommands.js
--- MsgComposeCommands.js 2000/08/18 00:08:59 1.113
+++ MsgComposeCommands.js 2000/08/20 16:57:08
@@ -20,6 +20,7 @@
var msgCompDeliverMode = Components.interfaces.nsIMsgCompDeliverMode;
var msgCompSendFormat = Components.interfaces.nsIMsgCompSendFormat;
+var msgCompConvertible = Components.interfaces.nsIMsgCompConvertible;
var msgCompType = Components.interfaces.nsIMsgCompType;
var accountManagerProgID = "component://netscape/messenger/account-manager";
@@ -937,18 +938,24 @@
return;
}
}
-
+
// Before sending the message, check what to do with HTML message, eventually abort.
- action = DetermineHTMLAction();
+ var convert = DetermineConvertibility();
+ action = DetermineHTMLAction(convert);
if (action == msgCompSendFormat.AskUser)
{
- var result = {action:msgCompSendFormat.PlainText, abort:false};
- window.openDialog("chrome://messenger/content/messengercompose/askSendFormat.xul",
- "askSendFormatDialog", "chrome,modal",
- result);
+ recommAction = convert == msgCompConvertible.No
+ ? msgCompSendFormat.AskUser
+ : msgCompSendFormat.PlainText;
+ var result = {action:recommAction,
+ convertible:convert,
+ abort:false};
+ window.openDialog("chrome://messenger/content/messengercompose/askSendFormat.xul",
+ "askSendFormatDialog", "chrome,modal",
+ result);
if (result.abort)
return;
- action = result.action;
+ action = result.action;
}
switch (action)
{
@@ -1433,7 +1440,7 @@
dump("AttachVCard()\n");
}
-function DetermineHTMLAction()
+function DetermineHTMLAction(convertible)
{
if (! msgCompose.composeHTML)
{
@@ -1470,11 +1477,8 @@
if (noHtmlRecipients != "" || noHtmlnewsgroups != "")
{
- try {
- var bodyContainsHTML = msgCompose.BodyContainsHTMLTag(window.editorShell.contentWindow.document.childNodes[1]);
- if (! bodyContainsHTML)
- return msgCompSendFormat.PlainText;
- } catch(ex) {}
+ if (convertible == msgCompConvertible.Plain)
+ return msgCompSendFormat.PlainText;
if (noHtmlnewsgroups == "")
{
@@ -1502,6 +1506,17 @@
}
return sendFormat;
+}
+
+function DetermineConvertibility()
+{
+ if (!msgCompose.composeHTML)
+ return msgCompConvertible.Plain;
+
+ try {
+ return msgCompose.bodyConvertible(
+ window.editorShell.contentWindow.document.childNodes[1]);
+ } catch(ex) {}
}
function LoadIdentity(startup)
Index: resources/content/askSendFormat.js
===================================================================
RCS file: /cvsroot/mozilla/mailnews/compose/resources/content/askSendFormat.js,v
retrieving revision 1.5
diff -u -r1.5 askSendFormat.js
--- askSendFormat.js 2000/05/09 02:09:11 1.5
+++ askSendFormat.js 2000/08/20 16:57:08
@@ -1,38 +1,116 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
var msgCompSendFormat = Components.interfaces.nsIMsgCompSendFormat;
+var msgCompConvertible = Components.interfaces.nsIMsgCompConvertible;
+var changeDefault = false; /* Set default selection following
+ the recommendation. Some people think, the
+ default should *always* be the same. */
var param = null;
function Startup()
{
- if (window.arguments && window.arguments[0] && window.arguments[0])
+ if (window.arguments && window.arguments[0])
{
+ var defaultElement = document.getElementById("SendPlainTextOnly");
+ // used only if changeDefault == false
+
param = window.arguments[0];
- param.abort = true; //if the user hit the close box, we will abort.
+ param.abort = true; //if the user hit the close box, we will abort.
if (param.action)
{
- //Set the default radio array value
- var group = document.getElementById("mailDefaultHTMLAction");
- var element = document.getElementById("SendPlainTextAndHtml");
- group.selectedItem= element;
- group.data = element.data;
+ // Set the question label
+ var labeldeck = document.getElementById("mailSendFormatExplanation");
+ var icon = document.getElementById("convertDefault");
+ switch (param.convertible)
+ {
+ case msgCompConvertible.Plain:
+ // We shouldn't be here at all
+ labeldeck.setAttribute("index", 1);
+ // No icon
+ break;
+ case msgCompConvertible.Yes:
+ labeldeck.setAttribute("index", 1);
+ icon.setAttribute("id", "convertYes");
+ break;
+ case msgCompConvertible.Altering:
+ labeldeck.setAttribute("index", 2);
+ icon.setAttribute("id", "convertAltering");
+ break;
+ case msgCompConvertible.No:
+ labeldeck.setAttribute("index", 3);
+ icon.setAttribute("id", "convertNo");
+ break;
+ }
+
+ // Set the default radio array value and recommendation
+ var group = document.getElementById("mailDefaultHTMLAction");
+ var element;
+ var recommlabels = document.getElementById("hiddenLabels");
+ var label;
+ var setrecomm = false;
+ switch (param.action)
+ {
+ case msgCompSendFormat.AskUser:
+ //setrecomm = false;
+ break;
+ case msgCompSendFormat.PlainText:
+ element = document.getElementById("SendPlainTextOnly");
+ //label = recommlabels.getAttribute("plainTextOnlyRecommendedLabel");
+ label = document.getElementById("plainTextOnlyRecommended");
+ // elements for "recommended" are a workaround for what seems to be an XUL bug
+ setrecomm = true;
+ break;
+ case msgCompSendFormat.Both:
+ element = document.getElementById("SendPlainTextAndHtml");
+ //label = recommlabels.getAttribute("plainTextAndHtmlRecommendedLabel");
+ label = document.getElementById("plainTextAndHtmlRecommended");
+ setrecomm = true;
+ break;
+ case msgCompSendFormat.HTML:
+ element = document.getElementById("SendHtmlOnly");
+ //label = recommlabels.getAttribute("htmlOnlyRecommendedLabel");
+ label = document.getElementById("htmlOnlyRecommended");
+ setrecomm = true;
+ break;
+ }
+ if (setrecomm)
+ {
+ /*
+ dump(element.getAttribute("value"));
+ element.setAttribute("value", label);
+ element.setAttribute("value", "foo");
+ dump(element.getAttribute("value"));
+ */
+ label.removeAttribute("hidden");
+ if (changeDefault)
+ {
+ group.selectedItem = element;
+ group.data = element.data;
+ }
+ }
+ if (!changeDefault)
+ {
+ group.selectedItem = defaultElement;
+ group.data = defaultElement.data;
+ }
//change the button label
- labels = document.getElementById("okCancelButtons");
+ var buttonlabels = document.getElementById("okCancelButtons");
element = document.getElementById("ok");
- element.setAttribute("value", labels.getAttribute("button1Label"));
+ element.setAttribute("value", buttonlabels.getAttribute("button1Label"));
element = document.getElementById("cancel");
- element.setAttribute("value", labels.getAttribute("button2Label"));
+ element.setAttribute("value", buttonlabels.getAttribute("button2Label"));
/*
element = document.getElementById("Button2");
- element.setAttribute("value", labels.getAttribute("button3Label"));
+ element.setAttribute("value", buttonlabels.getAttribute("button3Label"));
element.removeAttribute("hidden");
element.setAttribute("disabled", "true");
element = document.getElementById("Button3");
- element.setAttribute("value", labels.getAttribute("button4Label"));
+ element.setAttribute("value", buttonlabels.getAttribute("button4Label"));
element.removeAttribute("hidden");
element.setAttribute("disabled", "true");
*/
//set buttons action
- doSetOKCancel(Send, DontSend, Recipients, Help);
+ doSetOKCancel(Send, Cancel, Recipients, Help);
moveToAlertPosition();
}
@@ -41,7 +119,6 @@
{
dump("error, no return object registered\n");
}
-
}
function Send()
@@ -59,7 +136,7 @@
return true;
}
-function DontSend()
+function Cancel()
{
if (param)
param.abort = true;
Index: resources/content/askSendFormat.xul
===================================================================
RCS file: /cvsroot/mozilla/mailnews/compose/resources/content/askSendFormat.xul,v
retrieving revision 1.6
diff -u -r1.6 askSendFormat.xul
--- askSendFormat.xul 2000/05/16 03:25:51 1.6
+++ askSendFormat.xul 2000/08/20 16:57:08
@@ -1,35 +1,58 @@
-
+
-
+
-
+
-
+ >
-
+
-
-
-
+
+
+
+
+
+ &recipient.label;
+
+ &convertibleDefault.label;
+ &convertibleYes.label;
+ &convertibleAltering.label;
+ &convertibleNo.label;
+
+ &question.label;
-
+
+
+ &recommended.label;
+
+
+
+ &recommended.label;
+
+
+ &recommended.label;
+
+
@@ -37,9 +60,14 @@
+
-
+
Index: resources/locale/en-US/askSendFormat.dtd
===================================================================
RCS file: /cvsroot/mozilla/mailnews/compose/resources/locale/en-US/askSendFormat.dtd,v
retrieving revision 1.1
diff -u -r1.1 askSendFormat.dtd
--- askSendFormat.dtd 2000/02/12 03:58:01 1.1
+++ askSendFormat.dtd 2000/08/20 16:57:08
@@ -1,13 +1,25 @@
-
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
Index: src/nsMsgCompose.cpp
===================================================================
RCS file: /cvsroot/mozilla/mailnews/compose/src/nsMsgCompose.cpp,v
retrieving revision 1.191
diff -u -r1.191 nsMsgCompose.cpp
--- nsMsgCompose.cpp 2000/08/10 22:56:21 1.191
+++ nsMsgCompose.cpp 2000/08/20 16:57:11
@@ -1410,6 +1410,7 @@
// text before we try to insert it into the editor. If we don't, we
// just get lots of HTML text in the message...not good.
//
+ // XXX not m_composeHTML? /BenB
PRBool composeHTML = PR_TRUE;
mComposeObj->GetComposeHTML(&composeHTML);
if (!composeHTML)
@@ -1420,20 +1421,13 @@
ConvertToPlainText(formatflowed);
Recycle(target_charset);
}
-
- //
- // Ok, now we have finished quoting so we should load this into the editor
- // window.
- //
- PRBool compHTML = PR_FALSE;
- mComposeObj->GetComposeHTML(&compHTML);
-
+
mComposeObj->ProcessSignature(mIdentity, &mSignature);
nsIEditorShell *editor = nsnull;
if (NS_SUCCEEDED(mComposeObj->GetEditor(&editor)) && editor)
{
- mComposeObj->ConvertAndLoadComposeWindow(editor, mCitePrefix, mMsgBody, mSignature, PR_TRUE, compHTML);
+ mComposeObj->ConvertAndLoadComposeWindow(editor, mCitePrefix, mMsgBody, mSignature, PR_TRUE, composeHTML);
}
}
@@ -2711,40 +2706,38 @@
return rv;
}
-nsresult nsMsgCompose::BodyContainsHTMLTag(nsIDOMNode *node, PRBool *_retval)
+// Internal helper function. Parameters are not checked.
+static inline nsresult TagConvertible(nsIDOMNode *node, PRInt32 *_retval)
{
nsresult rv;
nsAutoString aStr;
- PRUint32 i;
- PRUint32 nbrOfElements;
nsCOMPtr pItem;
PRBool hasChild;
- if (nsnull == node || nsnull == _retval)
- return NS_ERROR_NULL_POINTER;
-
- *_retval = PR_TRUE;
-
+ *_retval = nsIMsgCompConvertible::No;
+
rv = node->GetNodeName(aStr);
if (NS_FAILED(rv))
return rv;
-
- if (aStr.EqualsWithConversion("a", PR_TRUE))
+ nsCAutoString aCStr; aCStr.AssignWithConversion(aStr);
+
+ if (aCStr.EqualsIgnoreCase("a"))
{
- //We can ignore an anchore tag if the link is the same than the text
+ /* Ignore anchor tag, if the URI is the same as the text
+ (as inserted by recognizers) */
nsAutoString href;
nsCOMPtr pAttributes;
rv = node->GetAttributes(getter_AddRefs(pAttributes));
if (NS_SUCCEEDED(rv) && pAttributes)
{
- nsString attributeName; attributeName.AssignWithConversion("href");
+ nsAutoString attributeName; attributeName.AssignWithConversion("href");
pAttributes->GetNamedItem(attributeName, getter_AddRefs(pItem));
if (NS_SUCCEEDED(rv) && pItem)
{
rv = pItem->GetNodeValue(href);
if (NS_SUCCEEDED(rv))
- {
+ {
rv = node->HasChildNodes(&hasChild);
if (NS_SUCCEEDED(rv) && hasChild)
{
@@ -2759,7 +2752,7 @@
if (NS_SUCCEEDED(rv))
{
if (aStr.Compare(href) == 0)
- *_retval = PR_FALSE;
+ *_retval = nsIMsgCompConvertible::Plain;
}
}
}
@@ -2767,56 +2760,129 @@
}
}
}
+
+ // It isn't, so don't ignore
+ *_retval = nsIMsgCompConvertible::Altering;
}
- else if (aStr.EqualsWithConversion("blockquote", PR_TRUE))
+ else if (aCStr.EqualsIgnoreCase("blockquote"))
{
- //skip only if the type is "cite"
+ // Skip
nsCOMPtr pAttributes;
rv = node->GetAttributes(getter_AddRefs(pAttributes));
if (NS_SUCCEEDED(rv) && pAttributes)
{
- nsString attributeName; attributeName.AssignWithConversion("type");
+ nsAutoString attributeName; attributeName.AssignWithConversion("type");
pAttributes->GetNamedItem(attributeName, getter_AddRefs(pItem));
if (NS_SUCCEEDED(rv) && pItem)
{
rv = pItem->GetNodeValue(aStr);
- if (NS_SUCCEEDED(rv) && aStr.EqualsWithConversion("cite", PR_TRUE))
- *_retval = PR_FALSE;
+ if (NS_SUCCEEDED(rv))
+ {
+ aCStr.StripChars("\"");
+ if (aCStr.EqualsIgnoreCase("cite"))
+ *_retval = nsIMsgCompConvertible::Plain;
+ }
}
}
- }
- else if (aStr.EqualsWithConversion("html", PR_TRUE))
- {
- *_retval = PR_FALSE;
- }
- else if (aStr.EqualsWithConversion("head", PR_TRUE))
- {
- *_retval = PR_FALSE;
- }
- else if (aStr.EqualsWithConversion("body", PR_TRUE))
- {
- *_retval = PR_FALSE;
- }
- else if (aStr.EqualsWithConversion("p", PR_TRUE))
- {
- *_retval = PR_FALSE;
- }
- else if (aStr.EqualsWithConversion("br", PR_TRUE))
- {
- *_retval = PR_FALSE;
+
+ // It isn't, so don't ignore
+ *_retval = nsIMsgCompConvertible::Yes;
}
- else if (aStr.EqualsWithConversion("pre", PR_TRUE))
+
+#if 0
+ /* This is for an edge case: A Mozilla user replies to plaintext per HTML
+ and the recipient of that HTML msg, also a Mozilla user, replies to
+ that again. Then we'll have to recognize the stuff inserted by our
+ TXT->HTML converter. Let's see, if this is actually a problem and
+ worth the processing time.
+ Bug 44552. */
+ else if (aCStr.EqualsIgnoreCase("div") ||
+ aCStr.EqualsIgnoreCase("span") ||
+ aCStr.EqualsIgnoreCase("em") ||
+ aCStr.EqualsIgnoreCase("strong") ||
+ aCStr.EqualsIgnoreCase("a"))
{
- *_retval = PR_FALSE;
+ /* skip only if inserted by our [TXT|HTML]->HTML converter
+ (might be in a quote) */
+ nsCOMPtr pAttributes;
+ rv = node->GetAttributes(getter_AddRefs(pAttributes));
+ if (NS_SUCCEEDED(rv) && pAttributes)
+ {
+ nsAutoString attributeName; attributeName.AssignWithConversion("class");
+ pAttributes->GetNamedItem(attributeName, getter_AddRefs(pItem));
+ if (NS_SUCCEEDED(rv) && pItem)
+ {
+ rv = pItem->GetNodeValue(aStr);
+ if (NS_SUCCEEDED(rv)
+ && (aCStr.EqualsIgnoreCase("txt", 3) ||
+ aCStr.EqualsIgnoreCase("\"txt", 4)))
+ *_retval = nsIMsgCompConvertible::Plain;
+ }
+ }
}
- else if (aStr.EqualsWithConversion("#text", PR_TRUE))
+#endif
+ else if (
+ aCStr.EqualsIgnoreCase("html") ||
+ aCStr.EqualsIgnoreCase("head") ||
+ aCStr.EqualsIgnoreCase("body") ||
+ aCStr.EqualsIgnoreCase("p") ||
+ aCStr.EqualsIgnoreCase("br") ||
+ aCStr.EqualsIgnoreCase("pre") ||
+ aCStr.EqualsIgnoreCase("tt") ||
+ aCStr.EqualsIgnoreCase("#text")
+ )
+ {
+ *_retval = nsIMsgCompConvertible::Plain;
+ }
+ else if (
+ //aCStr.EqualsIgnoreCase("blockquote") || // see above
+ aCStr.EqualsIgnoreCase("ul") ||
+ aCStr.EqualsIgnoreCase("ol") ||
+ aCStr.EqualsIgnoreCase("li") ||
+ aCStr.EqualsIgnoreCase("dl") ||
+ aCStr.EqualsIgnoreCase("dt") ||
+ aCStr.EqualsIgnoreCase("dd") ||
+ aCStr.EqualsIgnoreCase("hr")
+ )
+ {
+ *_retval = nsIMsgCompConvertible::Yes;
+ }
+ else if (
+ aCStr.EqualsIgnoreCase("h1") ||
+ aCStr.EqualsIgnoreCase("h2") ||
+ aCStr.EqualsIgnoreCase("h3") ||
+ aCStr.EqualsIgnoreCase("h4") ||
+ aCStr.EqualsIgnoreCase("h5") ||
+ aCStr.EqualsIgnoreCase("h6") ||
+ //aCStr.EqualsIgnoreCase("a") || // see above
+ aCStr.EqualsIgnoreCase("em") ||
+ aCStr.EqualsIgnoreCase("strong") ||
+ aCStr.EqualsIgnoreCase("code") ||
+ aCStr.EqualsIgnoreCase("b") ||
+ aCStr.EqualsIgnoreCase("i") ||
+ aCStr.EqualsIgnoreCase("u")
+ )
{
- *_retval = PR_FALSE;
+ *_retval = nsIMsgCompConvertible::Altering;
}
-
- if (NS_FAILED(rv) || *_retval)
- return rv;
+ return rv;
+}
+
+nsresult nsMsgCompose::BodyConvertible(nsIDOMNode *node, PRInt32 *_retval)
+{
+ NS_ENSURE_TRUE(node && _retval, NS_ERROR_NULL_POINTER);
+
+ nsresult rv;
+ PRInt32 result;
+
+ // Check this node
+ rv = TagConvertible(node, &result);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Walk tree recursively to check the children
+ PRBool hasChild;
rv = node->HasChildNodes(&hasChild);
if (NS_SUCCEEDED(rv) && hasChild)
{
@@ -2824,19 +2890,24 @@
rv = node->GetChildNodes(getter_AddRefs(children));
if (NS_SUCCEEDED(rv) && children)
{
+ PRUint32 nbrOfElements;
rv = children->GetLength(&nbrOfElements);
- if (NS_FAILED(rv))
- return rv;
-
- for (i = 0; i < nbrOfElements && *_retval == PR_FALSE && NS_SUCCEEDED(rv); i ++)
+ for (PRUint32 i = 0; NS_SUCCEEDED(rv) && i < nbrOfElements; i++)
{
+ nsCOMPtr pItem;
rv = children->Item(i, getter_AddRefs(pItem));
if (NS_SUCCEEDED(rv) && pItem)
- rv = BodyContainsHTMLTag(pItem, _retval);
+ {
+ PRInt32 curresult;
+ rv = BodyConvertible(pItem, &curresult);
+ if (NS_SUCCEEDED(rv) && curresult > result)
+ result = curresult;
+ }
}
}
}
-
+
+ *_retval = result;
return rv;
}
@@ -2856,9 +2927,8 @@
rv = editor->GetRootElement(getter_AddRefs(rootElement));
if (NS_FAILED(rv) || nsnull == rootElement)
return rv;
-
- //First look for the actual signature, if we have one
+ //First look for the current signature, if we have one
nsCOMPtr node;
nsCOMPtr tempNode;
nsAutoString tagLocalName;