зеркало из https://github.com/mozilla/gecko-dev.git
fix for #59638. cross folder navigation in the stand alone msg window
doesn't load the next unread message. thanks to ssu for the initial patch, and neil for the suggestions. r/sr=bienvenu fix for #49305. in "view all headers" mode, we only see the last header for headers where multiple headers are legal. thanks to richard.li@sun.com for the initial patch. r/sr=bienvenu fix for #179803. when we added mail views, we added "Sender is[n't] in addressbook" support to filter / search / views, but it left us with two "Sender" menuitems. this code unifies them into one. on disk (for filters and views) both the old way ("from in ab") and the new way ("from") work, so there isn't a migration issue. r/sr=bienvenu
This commit is contained in:
Родитель
8a962ca347
Коммит
cbb05359cf
|
@ -461,6 +461,25 @@
|
|||
</getter>
|
||||
</property>
|
||||
|
||||
<property name="optargets" readonly="true">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
var forAttrs = this.getAttribute("opfor");
|
||||
if (!forAttrs) return null;
|
||||
var optargetIds = forAttrs.split(",");
|
||||
if (optargetIds.length == 0) return null;
|
||||
|
||||
var optargets = new Array;
|
||||
var j=0;
|
||||
for (var i=0; i<optargetIds.length;i++) {
|
||||
var optarget = document.getElementById(optargetIds[i]);
|
||||
if (optarget) optargets[j++] = optarget;
|
||||
}
|
||||
return optargets;
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<!-- value forwards to the internal menulist's "value" attribute -->
|
||||
<property name="value" onget="return document.getAnonymousNodes(this)[0].selectedItem.getAttribute('value');">
|
||||
<setter>
|
||||
|
@ -473,12 +492,19 @@
|
|||
// now notify targets of new parent's value
|
||||
var targets = this.targets;
|
||||
if (targets) {
|
||||
for (var i=0; i< targets.length; i++) {
|
||||
for (var i=0; i < targets.length; i++) {
|
||||
targets[i].parentValue = val;
|
||||
}
|
||||
} else {
|
||||
//dump("Doh! No targets!\n");
|
||||
}
|
||||
|
||||
// now notify optargets of new op parent's value
|
||||
var optargets = this.optargets;
|
||||
if (optargets) {
|
||||
for (i=0; i < optargets.length; i++) {
|
||||
optargets[i].opParentValue = val;
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
]]>
|
||||
</setter>
|
||||
|
@ -543,10 +569,17 @@
|
|||
// notify targets
|
||||
var targets = this.targets;
|
||||
if (targets) {
|
||||
for (var i=0; i< targets.length; i++) {
|
||||
for (var i=0; i < targets.length; i++) {
|
||||
targets[i].parentValue = menulist.value;
|
||||
}
|
||||
}
|
||||
|
||||
var optargets = this.optargets;
|
||||
if (optargets) {
|
||||
for (i=0; i < optargets.length; i++) {
|
||||
optargets[i].opParentValue = menulist.value;
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
@ -621,8 +654,8 @@
|
|||
|
||||
<!-- searchvalue - a widget which dynamically changes it's user interface
|
||||
depending on what type of data it's supposed to be showing
|
||||
currently handles arbitrary text entry, and menulists for priority and
|
||||
status
|
||||
currently handles arbitrary text entry, and menulists for
|
||||
priority, status, junk status and addressbook
|
||||
-->
|
||||
<binding id="searchvalue" name="searchValue">
|
||||
<content>
|
||||
|
@ -675,9 +708,56 @@
|
|||
</xul:menulist>
|
||||
</content>
|
||||
<implementation>
|
||||
|
||||
<field name="internalOperator">null</field>
|
||||
<field name="internalAttribute">null</field>
|
||||
<field name="internalValue">null</field>
|
||||
|
||||
<property name="opParentValue" onget="return this.internalOperator;">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
// noop if we're not changing it
|
||||
if (this.internalOperator == val) return val;
|
||||
|
||||
// if it's not sender, we don't care
|
||||
if (this.searchAttribute != Components.interfaces.nsMsgSearchAttrib.Sender) {
|
||||
this.internalOperator = val;
|
||||
return val;
|
||||
}
|
||||
|
||||
var children = document.getAnonymousNodes(this);
|
||||
if (val == Components.interfaces.nsMsgSearchOp.IsntInAB ||
|
||||
val == Components.interfaces.nsMsgSearchOp.IsInAB) {
|
||||
// if the old internalOperator was
|
||||
// IsntInAB or IsInAB, and the new internalOperator is
|
||||
// IsntInAB or IsInAB, noop because the search value
|
||||
// was an ab type, and it still is.
|
||||
// otherwise, switch to the ab picker and select the PAB
|
||||
if (this.internalOperator != Components.interfaces.nsMsgSearchOp.IsntInAB &&
|
||||
this.internalOperator != Components.interfaces.nsMsgSearchOp.IsInAB) {
|
||||
var abs = children[4].getElementsByAttribute("value", "moz-abmdbdirectory://abook.mab");
|
||||
if (abs.length > 0)
|
||||
children[4].selectedItem = abs[0];
|
||||
this.setAttribute("selectedIndex", "4");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// if the old internalOperator wasn't
|
||||
// IsntInAB or IsInAB, and the new internalOperator isn't
|
||||
// IsntInAB or IsInAB, noop because the search value
|
||||
// wasn't an ab type, and it still isn't.
|
||||
// otherwise, switch to the textbox and clear it
|
||||
if (this.internalOperator == Components.interfaces.nsMsgSearchOp.IsntInAB ||
|
||||
this.internalOperator == Components.interfaces.nsMsgSearchOp.IsInAB) {
|
||||
children[0].value = "";
|
||||
this.setAttribute("selectedIndex", "0");
|
||||
}
|
||||
}
|
||||
|
||||
this.internalOperator = val;
|
||||
return val;
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
<!-- parentValue forwards to the attribute -->
|
||||
<property name="parentValue" onset="return this.searchAttribute=val;"
|
||||
onget="return this.searchAttribute;"/>
|
||||
|
@ -687,6 +767,10 @@
|
|||
// noop if we're not changing it
|
||||
if (this.internalAttribute == val) return val;
|
||||
this.internalAttribute = val;
|
||||
|
||||
// if the searchAttribute changing, null out the internalOperator
|
||||
this.internalOperator = null;
|
||||
|
||||
// we inherit from a deck, so just use it's index attribute
|
||||
// to hide/show widgets
|
||||
if (val == Components.interfaces.nsMsgSearchAttrib.Priority)
|
||||
|
@ -695,13 +779,12 @@
|
|||
this.setAttribute("selectedIndex", "2");
|
||||
else if (val == Components.interfaces.nsMsgSearchAttrib.Date)
|
||||
this.setAttribute("selectedIndex", "3");
|
||||
else if (val == Components.interfaces.nsMsgSearchAttrib.SenderInAddressBook)
|
||||
{
|
||||
var children = document.getAnonymousNodes(this);
|
||||
var abs = children[4].getElementsByAttribute("value", "moz-abmdbdirectory://abook.mab");
|
||||
if (abs.length > 0)
|
||||
children[4].selectedItem = abs[0];
|
||||
this.setAttribute("selectedIndex", "4");
|
||||
else if (val == Components.interfaces.nsMsgSearchAttrib.Sender) {
|
||||
// since the internalOperator is null
|
||||
// this is the same as the initial state
|
||||
// the initial state for Sender isn't an ab type search
|
||||
// it's a text search, so show the textbox
|
||||
this.setAttribute("selectedIndex", "0");
|
||||
}
|
||||
else if (val == Components.interfaces.nsMsgSearchAttrib.Label)
|
||||
{
|
||||
|
@ -747,11 +830,16 @@
|
|||
children[0].value = val.age;
|
||||
else if (attrib == nsMsgSearchAttrib.Date)
|
||||
children[3].value = convertPRTimeToString(val.date);
|
||||
else if (attrib == nsMsgSearchAttrib.SenderInAddressBook)
|
||||
{
|
||||
var abs = children[4].getElementsByAttribute("value", val.str);
|
||||
if (abs.length > 0)
|
||||
children[4].selectedItem = abs[0];
|
||||
else if (attrib == nsMsgSearchAttrib.Sender)
|
||||
{
|
||||
if (this.internalOperator == Components.interfaces.nsMsgSearchOp.IsntInAB ||
|
||||
this.internalOperator == Components.interfaces.nsMsgSearchOp.IsInAB) {
|
||||
var abs = children[4].getElementsByAttribute("value", val.str);
|
||||
if (abs.length > 0)
|
||||
children[4].selectedItem = abs[0];
|
||||
}
|
||||
else
|
||||
children[0].value = val.str;
|
||||
}
|
||||
else if (attrib == nsMsgSearchAttrib.Label)
|
||||
{
|
||||
|
@ -789,8 +877,13 @@
|
|||
searchValue.age = children[0].value;
|
||||
else if (searchAttribute == nsMsgSearchAttrib.Date)
|
||||
searchValue.date = convertStringToPRTime(children[3].value);
|
||||
else if (searchAttribute == nsMsgSearchAttrib.SenderInAddressBook)
|
||||
searchValue.str = children[4].selectedItem.value;
|
||||
else if (searchAttribute == nsMsgSearchAttrib.Sender) {
|
||||
if (this.internalOperator == Components.interfaces.nsMsgSearchOp.IsntInAB ||
|
||||
this.internalOperator == Components.interfaces.nsMsgSearchOp.IsInAB)
|
||||
searchValue.str = children[4].selectedItem.value;
|
||||
else
|
||||
searchValue.str = children[0].value;
|
||||
}
|
||||
else if (searchAttribute == nsMsgSearchAttrib.Label)
|
||||
searchValue.label = children[5].selectedItem.value;
|
||||
else if (searchAttribute == nsMsgSearchAttrib.JunkStatus)
|
||||
|
|
|
@ -393,18 +393,12 @@ function InitViewBodyMenu()
|
|||
|
||||
function IsNewsMessage(messageUri)
|
||||
{
|
||||
if (!messageUri)
|
||||
return false;
|
||||
else
|
||||
return (messageUri.substring(0,14) == "news-message:/");
|
||||
return (/^news-message:/.test(messageUri));
|
||||
}
|
||||
|
||||
function IsImapMessage(messageUri)
|
||||
{
|
||||
if (!messageUri)
|
||||
return false;
|
||||
else
|
||||
return (messageUri.substring(0,14) == "imap-message:/");
|
||||
return (/^imap-message:/.test(messageUri));
|
||||
}
|
||||
|
||||
function SetMenuItemLabel(menuItemId, customLabel)
|
||||
|
@ -1893,6 +1887,7 @@ function OnMsgLoaded(folder, msgURI)
|
|||
var currentMsgFolder = folder.QueryInterface(Components.interfaces.nsIMsgFolder);
|
||||
if (!IsImapMessage(msgURI))
|
||||
return;
|
||||
|
||||
var imapServer = currentMsgFolder.server.QueryInterface(Components.interfaces.nsIImapIncomingServer);
|
||||
var storeReadMailInPFC = imapServer.storeReadMailInPFC;
|
||||
if (storeReadMailInPFC)
|
||||
|
@ -1904,16 +1899,7 @@ function OnMsgLoaded(folder, msgURI)
|
|||
// look in read mail PFC for msg with same msg id - if we find one,
|
||||
// don't put this message in the read mail pfc.
|
||||
var outputPFC = imapServer.GetReadMailPFC(true);
|
||||
var messageURI = GetLoadedMessage();
|
||||
if (messageURI != msgURI)
|
||||
{
|
||||
// XXX TODO
|
||||
// bienvenu tells me:
|
||||
// if you have two message windows open, you can get multiple attempts
|
||||
// to copy into the pfc. the second will fail and assert.
|
||||
dump("not loading msg into this window - loaded message = " + messageURI + "loading " + msgURI + "\n");
|
||||
// return;
|
||||
}
|
||||
|
||||
var msgHdr = messenger.messageServiceFromURI(messageURI).messageURIToMsgHdr(messageURI);
|
||||
if (msgHdr)
|
||||
{
|
||||
|
|
|
@ -82,15 +82,12 @@ var folderListener = {
|
|||
else if (event.GetUnicode() == "DeleteOrMoveMsgFailed") {
|
||||
HandleDeleteOrMoveMsgFailed(folder);
|
||||
}
|
||||
else if (event.GetUnicode() == "msgLoaded") {
|
||||
OnMsgLoaded(folder, gCurrentMessageUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var messagepaneObserver = {
|
||||
|
||||
canHandleMultipleItems: false,
|
||||
canHandleMultipleItems: false,
|
||||
|
||||
onDrop: function (aEvent, aData, aDragSession)
|
||||
{
|
||||
|
@ -99,8 +96,7 @@ canHandleMultipleItems: false,
|
|||
{
|
||||
var msgHdr = GetMsgHdrFromUri(sourceUri);
|
||||
var folderUri = msgHdr.folder.URI;
|
||||
if (folderUri != gCurrentFolderUri)
|
||||
UpdateDBView(folderUri);
|
||||
SelectFolder(folderUri);
|
||||
SelectMessage(sourceUri);
|
||||
}
|
||||
},
|
||||
|
@ -132,19 +128,6 @@ canHandleMultipleItems: false,
|
|||
}
|
||||
};
|
||||
|
||||
function UpdateDBView(folderUri)
|
||||
{
|
||||
var dbview = GetDBView(); //close old folder view
|
||||
if (dbview) {
|
||||
dbview.close();
|
||||
}
|
||||
|
||||
SelectFolder(folderUri);
|
||||
|
||||
CreateView(null); //create new folder view
|
||||
}
|
||||
|
||||
|
||||
function nsMsgDBViewCommandUpdater()
|
||||
{}
|
||||
|
||||
|
@ -521,8 +504,18 @@ function SetNextMessageAfterDelete()
|
|||
|
||||
function SelectFolder(folderUri)
|
||||
{
|
||||
gCurrentFolderUri = folderUri;
|
||||
}
|
||||
if (folderUri == gCurrentFolderUri)
|
||||
return;
|
||||
|
||||
var dbview = GetDBView(); // close old folder view
|
||||
if (dbview) {
|
||||
dbview.close();
|
||||
}
|
||||
|
||||
gCurrentFolderUri = folderUri;
|
||||
|
||||
CreateView(null); //create new folder view
|
||||
}
|
||||
|
||||
function GetMsgHdrFromUri(messageUri)
|
||||
{
|
||||
|
@ -905,14 +898,14 @@ var MessageWindowController =
|
|||
}
|
||||
};
|
||||
|
||||
function performNavigation(type)
|
||||
function LoadMessageByNavigationType(type)
|
||||
{
|
||||
var resultId = new Object;
|
||||
var resultIndex = new Object;
|
||||
var threadIndex = new Object;
|
||||
|
||||
gDBView.viewNavigate(type, resultId, resultIndex, threadIndex, true /* wrap */);
|
||||
|
||||
|
||||
// if we found something....display it.
|
||||
if ((resultId.value != nsMsgKey_None) && (resultIndex.value != nsMsgKey_None))
|
||||
{
|
||||
|
@ -920,11 +913,33 @@ function performNavigation(type)
|
|||
gDBView.loadMessageByMsgKey(resultId.value);
|
||||
// if we changed folders, the message counts changed.
|
||||
UpdateStandAloneMessageCounts();
|
||||
return;
|
||||
|
||||
// new message has been loaded
|
||||
return true;
|
||||
}
|
||||
|
||||
// no message found to load
|
||||
return false;
|
||||
}
|
||||
|
||||
function performNavigation(type)
|
||||
{
|
||||
// Try to load a message by navigation type if we can find
|
||||
// the message in the same folder.
|
||||
if (LoadMessageByNavigationType(type))
|
||||
return;
|
||||
|
||||
// we need to span another folder
|
||||
CrossFolderNavigation(type, false);
|
||||
var folder = CrossFolderNavigation(type);
|
||||
if (!folder)
|
||||
return;
|
||||
|
||||
// Try again to load a message by nagivation by type if
|
||||
// the folder has been changed. If the folder was not changed,
|
||||
// then the first call to LoadMessageByNavigationType() would
|
||||
// have loaded the message.
|
||||
if (folder.Value == gCurrentFolderUri)
|
||||
LoadMessageByNavigationType(type);
|
||||
}
|
||||
|
||||
function SetupCommandUpdateHandlers()
|
||||
|
|
|
@ -34,10 +34,6 @@
|
|||
var msgHeaderParserContractID = "@mozilla.org/messenger/headerparser;1";
|
||||
var abAddressCollectorContractID = "@mozilla.org/addressbook/services/addressCollecter;1";
|
||||
|
||||
// get the "msgLoad" atom
|
||||
var atomService = Components.classes["@mozilla.org/atom-service;1"].getService().QueryInterface(Components.interfaces.nsIAtomService);
|
||||
var gMsgLoadedAtom = atomService.getAtom("msgLoaded").QueryInterface(Components.interfaces.nsISupports);
|
||||
|
||||
var gViewAllHeaders = false;
|
||||
var gNumAddressesToShow = 3;
|
||||
var gShowUserAgent = false;
|
||||
|
@ -297,7 +293,7 @@ var messageHeaderSink = {
|
|||
{
|
||||
this.onStartHeaders();
|
||||
|
||||
var index = 0;
|
||||
var index = 0;
|
||||
// process each header
|
||||
while (index < numHeaders)
|
||||
{
|
||||
|
@ -309,11 +305,19 @@ var messageHeaderSink = {
|
|||
foo.headerValue = headerValues[index];
|
||||
foo.headerName = headerNames[index];
|
||||
|
||||
// some times, you can have multiple To or cc lines....in this case, we want to APPEND
|
||||
// these headers into one.
|
||||
if ( (lowerCaseHeaderName == 'to' || lowerCaseHeaderName == 'cc') && ( lowerCaseHeaderName in currentHeaderData))
|
||||
// according to RFC 2822, certain headers
|
||||
// can occur "unlimited" times
|
||||
if (lowerCaseHeaderName in currentHeaderData)
|
||||
{
|
||||
currentHeaderData[lowerCaseHeaderName].headerValue = currentHeaderData[lowerCaseHeaderName].headerValue + ',' + foo.headerValue;
|
||||
// sometimes, you can have multiple To or Cc lines....
|
||||
// in this case, we want to append these headers into one.
|
||||
if (lowerCaseHeaderName == 'to' || lowerCaseHeaderName == 'cc')
|
||||
currentHeaderData[lowerCaseHeaderName].headerValue = currentHeaderData[lowerCaseHeaderName].headerValue + ',' + foo.headerValue;
|
||||
else {
|
||||
// use the index to create a unique header name like:
|
||||
// received5, received6, etc
|
||||
currentHeaderData[lowerCaseHeaderName + index] = foo;
|
||||
}
|
||||
}
|
||||
else
|
||||
currentHeaderData[lowerCaseHeaderName] = foo;
|
||||
|
@ -374,12 +378,12 @@ var messageHeaderSink = {
|
|||
|
||||
onEndMsgDownload: function(url)
|
||||
{
|
||||
var msgFolder;
|
||||
if (url)
|
||||
{
|
||||
msgFolder = url.folder;
|
||||
if (msgFolder)
|
||||
msgFolder.NotifyFolderEvent(gMsgLoadedAtom);
|
||||
var msgFolder = url.folder;
|
||||
var msgURI = GetLoadedMessage();
|
||||
if (msgFolder && msgURI)
|
||||
OnMsgLoaded(msgFolder, msgURI);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -255,9 +255,6 @@ var folderListener = {
|
|||
else if(eventType == "RenameCompleted") {
|
||||
SelectFolder(folder.URI);
|
||||
}
|
||||
else if (eventType == "msgLoaded") {
|
||||
OnMsgLoaded(folder, gDBView.URIForFirstSelectedMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -193,7 +193,7 @@ function GetRootFoldersInFolderPaneOrder()
|
|||
return serversMsgFolders;
|
||||
}
|
||||
|
||||
function CrossFolderNavigation(type, supportsFolderPane )
|
||||
function CrossFolderNavigation(type)
|
||||
{
|
||||
if (type != nsMsgNavigationType.nextUnreadMessage) {
|
||||
// only do cross folder navigation for "next unread message"
|
||||
|
@ -214,16 +214,14 @@ function CrossFolderNavigation(type, supportsFolderPane )
|
|||
case 0:
|
||||
// do this unconditionally
|
||||
gNextMessageAfterLoad = type;
|
||||
if (supportsFolderPane)
|
||||
SelectFolder(folder.URI);
|
||||
SelectFolder(folder.URI);
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
var promptText = gMessengerBundle.getFormattedString("advanceNextPrompt", [ folder.name ], 1);
|
||||
if (promptService.confirm(window, promptText, promptText)) {
|
||||
gNextMessageAfterLoad = type;
|
||||
if (supportsFolderPane)
|
||||
SelectFolder(folder.URI);
|
||||
SelectFolder(folder.URI);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -268,7 +266,7 @@ function GoNextMessage(type, startFromBeginning)
|
|||
try {
|
||||
var succeeded = ScrollToMessage(type, startFromBeginning, true);
|
||||
if (!succeeded) {
|
||||
CrossFolderNavigation(type, true);
|
||||
CrossFolderNavigation(type);
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
|
|
|
@ -102,10 +102,9 @@ interface nsMsgSearchAttrib {
|
|||
const nsMsgSearchAttribValue Department = 30;
|
||||
const nsMsgSearchAttribValue AdditionalEmail = 31;
|
||||
|
||||
// 32 - 45, reserved for ab / LDAP;
|
||||
// 32 - 46, reserved for ab / LDAP;
|
||||
|
||||
const nsMsgSearchAttribValue JunkStatus = 46;
|
||||
const nsMsgSearchAttribValue SenderInAddressBook = 47;
|
||||
const nsMsgSearchAttribValue JunkStatus = 47;
|
||||
const nsMsgSearchAttribValue Label = 48; /* mail only...can search by label */
|
||||
//49 is for showing customize... in ui headers start from 50 onwards up until 99.
|
||||
const nsMsgSearchAttribValue OtherHeader = 49; /* for mail and news. MUST ALWAYS BE LAST attribute since we can have an arbitrary # of these... */
|
||||
|
|
|
@ -181,7 +181,6 @@ var gFolderListener = {
|
|||
else if (eventType == "DeleteOrMoveMsgFailed") {
|
||||
HandleDeleteOrMoveMessageFailed(folder);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -306,6 +306,7 @@ function createSearchRow(index, scope, searchTerm)
|
|||
enclosingBox.appendChild(boolOp);
|
||||
|
||||
searchAttr.setAttribute("for", searchOp.id + "," + searchVal.id);
|
||||
searchOp.setAttribute("opfor", searchVal.id);
|
||||
|
||||
var rowdata = new Array(enclosingBox, searchAttr,
|
||||
null, searchOp,
|
||||
|
|
|
@ -54,15 +54,15 @@
|
|||
<listitem id="searchListItem">
|
||||
<listcell id="preSearchAttr"/>
|
||||
<listcell allowevents="true">
|
||||
<searchattribute id="searchAttr" for="searchOp,searchValue" flex="1"/>
|
||||
<searchattribute id="searchAttr1" for="searchOp1,searchValue1" flex="1"/>
|
||||
</listcell>
|
||||
<listcell id="preSearchOp"/>
|
||||
<listcell allowevents="true">
|
||||
<searchoperator id="searchOp" flex="1"/>
|
||||
<searchoperator id="searchOp1" opfor="searchValue1" flex="1"/>
|
||||
</listcell>
|
||||
<listcell id="preSearchValue"/>
|
||||
<listcell allowevents="true" >
|
||||
<searchvalue id="searchValue" flex="1"/>
|
||||
<searchvalue id="searchValue1" flex="1"/>
|
||||
</listcell>
|
||||
<listcell id="postSearchValue"/>
|
||||
</listitem>
|
||||
|
|
|
@ -47,8 +47,8 @@
|
|||
43=reserved for AB
|
||||
44=reserved for AB
|
||||
45=reserved for AB
|
||||
46=Junk Status
|
||||
47=Sender
|
||||
46=reserved for AB
|
||||
47=Junk Status
|
||||
48=Label
|
||||
# don't use above 49
|
||||
49=Customize...
|
||||
|
|
|
@ -193,10 +193,10 @@ nsresult nsMsgSearchValidityManager::InitOfflineMailTable ()
|
|||
m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::Sender, nsMsgSearchOp::EndsWith, 1);
|
||||
m_offlineMailTable->SetEnabled (nsMsgSearchAttrib::Sender, nsMsgSearchOp::EndsWith, 1);
|
||||
|
||||
m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsInAB, 1);
|
||||
m_offlineMailTable->SetEnabled (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsInAB, 1);
|
||||
m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsntInAB, 1);
|
||||
m_offlineMailTable->SetEnabled (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsntInAB, 1);
|
||||
m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::Sender, nsMsgSearchOp::IsInAB, 1);
|
||||
m_offlineMailTable->SetEnabled (nsMsgSearchAttrib::Sender, nsMsgSearchOp::IsInAB, 1);
|
||||
m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::Sender, nsMsgSearchOp::IsntInAB, 1);
|
||||
m_offlineMailTable->SetEnabled (nsMsgSearchAttrib::Sender, nsMsgSearchOp::IsntInAB, 1);
|
||||
|
||||
m_offlineMailTable->SetAvailable (nsMsgSearchAttrib::Label, nsMsgSearchOp::Is, 1);
|
||||
m_offlineMailTable->SetEnabled (nsMsgSearchAttrib::Label, nsMsgSearchOp::Is, 1);
|
||||
|
@ -414,10 +414,10 @@ nsresult nsMsgSearchValidityManager::InitOnlineMailFilterTable()
|
|||
m_onlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::Sender, nsMsgSearchOp::EndsWith, 1);
|
||||
m_onlineMailFilterTable->SetEnabled (nsMsgSearchAttrib::Sender, nsMsgSearchOp::EndsWith, 1);
|
||||
|
||||
m_onlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsInAB, 1);
|
||||
m_onlineMailFilterTable->SetEnabled (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsInAB, 1);
|
||||
m_onlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsntInAB, 1);
|
||||
m_onlineMailFilterTable->SetEnabled (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsntInAB, 1);
|
||||
m_onlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::Sender, nsMsgSearchOp::IsInAB, 1);
|
||||
m_onlineMailFilterTable->SetEnabled (nsMsgSearchAttrib::Sender, nsMsgSearchOp::IsInAB, 1);
|
||||
m_onlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::Sender, nsMsgSearchOp::IsntInAB, 1);
|
||||
m_onlineMailFilterTable->SetEnabled (nsMsgSearchAttrib::Sender, nsMsgSearchOp::IsntInAB, 1);
|
||||
|
||||
m_onlineMailFilterTable->SetAvailable (nsMsgSearchAttrib::To, nsMsgSearchOp::Contains, 1);
|
||||
m_onlineMailFilterTable->SetEnabled (nsMsgSearchAttrib::To, nsMsgSearchOp::Contains, 1);
|
||||
|
|
|
@ -492,7 +492,6 @@ nsresult nsMsgSearchOfflineMail::ProcessSearchTerm(nsIMsgDBHdr *msgToMatch,
|
|||
|
||||
switch (attrib)
|
||||
{
|
||||
case nsMsgSearchAttrib::SenderInAddressBook:
|
||||
case nsMsgSearchAttrib::Sender:
|
||||
msgToMatch->GetAuthor(getter_Copies(matchString));
|
||||
err = aTerm->MatchRfc822String (matchString, charset, charsetOverride, &result);
|
||||
|
|
|
@ -740,10 +740,10 @@ nsresult nsMsgSearchValidityManager::InitNewsFilterTable()
|
|||
m_newsFilterTable->SetAvailable (nsMsgSearchAttrib::Sender, nsMsgSearchOp::EndsWith, 1);
|
||||
m_newsFilterTable->SetEnabled (nsMsgSearchAttrib::Sender, nsMsgSearchOp::EndsWith, 1);
|
||||
|
||||
m_newsFilterTable->SetAvailable (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsInAB, 1);
|
||||
m_newsFilterTable->SetEnabled (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsInAB, 1);
|
||||
m_newsFilterTable->SetAvailable (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsntInAB, 1);
|
||||
m_newsFilterTable->SetEnabled (nsMsgSearchAttrib::SenderInAddressBook, nsMsgSearchOp::IsntInAB, 1);
|
||||
m_newsFilterTable->SetAvailable (nsMsgSearchAttrib::Sender, nsMsgSearchOp::IsInAB, 1);
|
||||
m_newsFilterTable->SetEnabled (nsMsgSearchAttrib::Sender, nsMsgSearchOp::IsInAB, 1);
|
||||
m_newsFilterTable->SetAvailable (nsMsgSearchAttrib::Sender, nsMsgSearchOp::IsntInAB, 1);
|
||||
m_newsFilterTable->SetEnabled (nsMsgSearchAttrib::Sender, nsMsgSearchOp::IsntInAB, 1);
|
||||
|
||||
m_newsFilterTable->SetAvailable (nsMsgSearchAttrib::Subject, nsMsgSearchOp::Contains, 1);
|
||||
m_newsFilterTable->SetEnabled (nsMsgSearchAttrib::Subject, nsMsgSearchOp::Contains, 1);
|
||||
|
|
|
@ -82,19 +82,23 @@ typedef struct
|
|||
|
||||
nsMsgSearchAttribEntry SearchAttribEntryTable[] =
|
||||
{
|
||||
{nsMsgSearchAttrib::Subject, "subject"},
|
||||
{nsMsgSearchAttrib::Sender, "from"},
|
||||
{nsMsgSearchAttrib::Body, "body"},
|
||||
{nsMsgSearchAttrib::Date, "date"},
|
||||
{nsMsgSearchAttrib::Priority, "priority"},
|
||||
{nsMsgSearchAttrib::MsgStatus, "status"},
|
||||
{nsMsgSearchAttrib::To, "to"},
|
||||
{nsMsgSearchAttrib::CC, "cc"},
|
||||
{nsMsgSearchAttrib::ToOrCC, "to or cc"},
|
||||
{nsMsgSearchAttrib::AgeInDays, "age in days"},
|
||||
{nsMsgSearchAttrib::Label, "label"},
|
||||
{nsMsgSearchAttrib::SenderInAddressBook, "from in ab"},
|
||||
{nsMsgSearchAttrib::JunkStatus, "junk status"},
|
||||
{nsMsgSearchAttrib::Subject, "subject"},
|
||||
{nsMsgSearchAttrib::Sender, "from"},
|
||||
{nsMsgSearchAttrib::Body, "body"},
|
||||
{nsMsgSearchAttrib::Date, "date"},
|
||||
{nsMsgSearchAttrib::Priority, "priority"},
|
||||
{nsMsgSearchAttrib::MsgStatus, "status"},
|
||||
{nsMsgSearchAttrib::To, "to"},
|
||||
{nsMsgSearchAttrib::CC, "cc"},
|
||||
{nsMsgSearchAttrib::ToOrCC, "to or cc"},
|
||||
{nsMsgSearchAttrib::AgeInDays, "age in days"},
|
||||
{nsMsgSearchAttrib::Label, "label"},
|
||||
// this used to be nsMsgSearchAttrib::SenderInAddressBook
|
||||
// we used to have two Sender menuitems
|
||||
// for backward compatability, we can still parse
|
||||
// the old style. see bug #179803
|
||||
{nsMsgSearchAttrib::Sender, "from in ab"},
|
||||
{nsMsgSearchAttrib::JunkStatus, "junk status"},
|
||||
};
|
||||
|
||||
// Take a string which starts off with an attribute
|
||||
|
@ -570,40 +574,34 @@ nsMsgSearchTerm::ParseOperator(char *inStream, nsMsgSearchOpValue *value)
|
|||
// find the attribute code for this comma-delimited attribute.
|
||||
nsresult
|
||||
nsMsgSearchTerm::ParseAttribute(char *inStream, nsMsgSearchAttribValue *attrib)
|
||||
{
|
||||
nsCAutoString attributeStr;
|
||||
PRInt16 attributeVal;
|
||||
nsresult err;
|
||||
{
|
||||
while (nsString::IsSpace(*inStream))
|
||||
inStream++;
|
||||
|
||||
// if we are dealing with an arbitrary header, it may be quoted....
|
||||
PRBool quoteVal = PR_FALSE;
|
||||
if (*inStream == '"')
|
||||
{
|
||||
quoteVal = PR_TRUE;
|
||||
inStream++;
|
||||
}
|
||||
|
||||
// arbitrary headers are quoted
|
||||
char *separator = strchr(inStream, quoteVal ? '"' : ',');
|
||||
|
||||
while (nsString::IsSpace(*inStream))
|
||||
inStream++;
|
||||
|
||||
// if we are dealing with an arbitrary header, it may be quoted....
|
||||
PRBool quoteVal = PR_FALSE;
|
||||
if (*inStream == '"')
|
||||
{
|
||||
quoteVal = PR_TRUE;
|
||||
inStream++;
|
||||
}
|
||||
|
||||
char *separator;
|
||||
if (quoteVal) // arbitrary headers are quoted...
|
||||
separator = PL_strchr(inStream, '"');
|
||||
else
|
||||
separator = PL_strchr(inStream, ',');
|
||||
|
||||
if (separator)
|
||||
*separator = '\0';
|
||||
|
||||
err = NS_MsgGetAttributeFromString(inStream, &attributeVal);
|
||||
NS_ENSURE_SUCCESS(err, err);
|
||||
|
||||
*attrib = (nsMsgSearchAttribValue) attributeVal;
|
||||
|
||||
if (*attrib > nsMsgSearchAttrib::OtherHeader && *attrib < nsMsgSearchAttrib::kNumMsgSearchAttributes) // if we are dealing with an arbitrary header....
|
||||
m_arbitraryHeader = inStream;
|
||||
|
||||
return err;
|
||||
if (separator)
|
||||
*separator = '\0';
|
||||
|
||||
PRInt16 attributeVal;
|
||||
nsresult rv = NS_MsgGetAttributeFromString(inStream, &attributeVal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*attrib = (nsMsgSearchAttribValue) attributeVal;
|
||||
|
||||
if (*attrib > nsMsgSearchAttrib::OtherHeader && *attrib < nsMsgSearchAttrib::kNumMsgSearchAttributes) // if we are dealing with an arbitrary header....
|
||||
m_arbitraryHeader = inStream;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// De stream one search term. If the condition looks like
|
||||
|
@ -854,7 +852,7 @@ nsresult nsMsgSearchTerm::InitializeAddressBook()
|
|||
nsXPIDLCString dirURI;
|
||||
mDirectory->GetDirUri(getter_Copies(dirURI));
|
||||
if (strcmp(dirURI.get(), m_value.string))
|
||||
mDirectory = NULL; // clear out the directory....we are no longer pointing to the right one
|
||||
mDirectory = nsnull; // clear out the directory....we are no longer pointing to the right one
|
||||
}
|
||||
if (!mDirectory)
|
||||
{
|
||||
|
@ -904,7 +902,9 @@ nsresult nsMsgSearchTerm::MatchRfc2047String (const char *rfc2047string,
|
|||
charset, charsetOverride,
|
||||
PR_FALSE);
|
||||
|
||||
if (nsMsgSearchAttrib::SenderInAddressBook == m_attribute)
|
||||
if (m_attribute == nsMsgSearchAttrib::Sender &&
|
||||
(m_operator == nsMsgSearchOp::IsInAB ||
|
||||
m_operator == nsMsgSearchOp::IsntInAB))
|
||||
{
|
||||
res = MatchInAddressBook(stringToMatch ? stringToMatch : rfc2047string, pResult);
|
||||
}
|
||||
|
@ -1067,7 +1067,9 @@ nsresult nsMsgSearchTerm::MatchRfc822String (const char *string, const char *cha
|
|||
{
|
||||
walkNames = names + namePos;
|
||||
walkAddresses = addresses + addressPos;
|
||||
if (nsMsgSearchAttrib::SenderInAddressBook == m_attribute)
|
||||
if (m_attribute == nsMsgSearchAttrib::Sender &&
|
||||
(m_operator == nsMsgSearchOp::IsInAB ||
|
||||
m_operator == nsMsgSearchOp::IsntInAB))
|
||||
{
|
||||
err = MatchRfc2047String (walkAddresses.get(), charset, charsetOverride, &result);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ logging="no"
|
|||
name="People I Know"
|
||||
enabled="yes"
|
||||
type="1"
|
||||
condition="AND (from in ab,is in ab,moz-abmdbdirectory://abook.mab)"
|
||||
condition="AND (from,is in ab,moz-abmdbdirectory://abook.mab)"
|
||||
name="Recent Mail"
|
||||
enabled="yes"
|
||||
type="1"
|
||||
|
|
Загрузка…
Ссылка в новой задаче