Bug 92135: shows source of autocomplete items in the mail compose window using icons in the dropdown (default match, local addressbook, remote addressbook). Allows (via hidden pref; off by default) for more sophisticated info about each address -- specific addrbook name, or random ldap attribute, like department). Also fixes minor LDAP autocomplete i18n regression introduced post 0.9.3 and found while testing. r=sspitzer; sr=hewitt; a=asa

This commit is contained in:
dmose%netscape.com 2001-09-04 05:25:08 +00:00
Родитель cbc7b5ba25
Коммит df7ab3a7c0
11 изменённых файлов: 273 добавлений и 50 удалений

Просмотреть файл

@ -42,11 +42,12 @@ interface nsIAbLDAPAutoCompFormatter: nsILDAPAutoCompFormatter {
* If any of these are unset, components implementing this interface
* are free to choose reasonable defaults. As an example, the
*"@mozilla.org/ldap-autocomplete-formatter;1?type=addrbook"
* implementation currently happens to use the followingn defaults:
* implementation currently happens to use the following default
* strings:
*
* nameFormat: [cn]
* addressFormat: {mail}
* commentFormat: [o]
* nameFormat: "[cn]"
* addressFormat: "{mail}"
* commentFormat: ""
*
* and generates autocomplete items like this:
*

Просмотреть файл

@ -103,9 +103,16 @@ PRBool nsAbAutoCompleteSession::ItsADuplicate(PRUnichar* fullAddrStr, nsIAutoCom
return PR_FALSE;
}
void nsAbAutoCompleteSession::AddToResult(const PRUnichar* pNickNameStr, const PRUnichar* pDisplayNameStr, const PRUnichar* pFirstNameStr,
const PRUnichar* pLastNameStr, const PRUnichar* pEmailStr, const PRUnichar* pNotesStr, PRBool bIsMailList, MatchType type,
nsIAutoCompleteResults* results)
void
nsAbAutoCompleteSession::AddToResult(const PRUnichar* pNickNameStr,
const PRUnichar* pDisplayNameStr,
const PRUnichar* pFirstNameStr,
const PRUnichar* pLastNameStr,
const PRUnichar* pEmailStr,
const PRUnichar* pNotesStr,
const PRUnichar* pDirName,
PRBool bIsMailList, MatchType type,
nsIAutoCompleteResults* results)
{
nsresult rv;
PRUnichar* fullAddrStr = nsnull;
@ -180,11 +187,37 @@ void nsAbAutoCompleteSession::AddToResult(const PRUnichar* pNickNameStr, const P
rv = nsComponentManager::CreateInstance(kAutoCompleteItemCID, nsnull, NS_GET_IID(nsIAutoCompleteItem), getter_AddRefs(newItem));
if (NS_SUCCEEDED(rv))
{
nsAbAutoCompleteParam *param = new nsAbAutoCompleteParam(pNickNameStr, pDisplayNameStr, pFirstNameStr, pLastNameStr, pEmailStr, pNotesStr, bIsMailList, type);
nsAbAutoCompleteParam *param = new nsAbAutoCompleteParam(pNickNameStr, pDisplayNameStr, pFirstNameStr, pLastNameStr, pEmailStr, pNotesStr, pDirName, bIsMailList, type);
NS_IF_ADDREF(param);
newItem->SetParam(param);
NS_IF_RELEASE(param);
// how to process the comment column, if at all. this value
// comes from "mail.autoComplete.commentColumn", or, if that
// doesn't exist, defaults to 0
//
// 0 = none
// 1 = name of addressbook this card came from
// 2 = other per-addressbook format (currrently unused here)
//
if (mAutoCompleteCommentColumn == 1) {
rv = newItem->SetComment(pDirName);
if (NS_FAILED(rv)) {
NS_WARNING("nsAbAutoCompleteSession::AddToResult():"
" newItem->SetComment() failed\n");
}
}
// if this isn't a default match, set the class name so we can style
// this cell with the local addressbook icon (or whatever)
//
rv = newItem->SetClassName(type == DEFAULT_MATCH ? "default-match" :
"local-abook");
if (NS_FAILED(rv)) {
NS_WARNING("nsAbAutoCompleteSession::AddToResult():"
" newItem->SetClassName() failed\n");
}
newItem->SetValue(nsDependentString(fullAddrStr));
nsCOMPtr<nsISupportsArray> array;
rv = results->GetItems(getter_AddRefs(array));
@ -374,11 +407,26 @@ nsresult nsAbAutoCompleteSession::SearchCards(nsIAbDirectory* directory, nsAbAut
continue;
MatchType matchType;
if (CheckEntry(searchStr, (const PRUnichar*)pNickNameStr, (const PRUnichar*)pDisplayNameStr,
(const PRUnichar*)pFirstNameStr, (const PRUnichar*)pLastNameStr, (const PRUnichar*)pEmailStr, &matchType))
AddToResult((const PRUnichar*)pNickNameStr, (const PRUnichar*)pDisplayNameStr, (const PRUnichar*)pFirstNameStr,
(const PRUnichar*)pLastNameStr, (const PRUnichar*)pEmailStr, (const PRUnichar*)pNotesStr, bIsMailList,
matchType, results);
if ( CheckEntry(searchStr, pNickNameStr.get(),
pDisplayNameStr.get(),
pFirstNameStr.get(),
pLastNameStr.get(), pEmailStr.get(),
&matchType)) {
nsXPIDLString pDirName;
if ( mAutoCompleteCommentColumn == 1 ) {
rv = directory->GetDirName(getter_Copies(pDirName));
if (NS_FAILED(rv)) {
continue;
}
}
AddToResult(pNickNameStr.get(), pDisplayNameStr.get(),
pFirstNameStr.get(), pLastNameStr.get(),
pEmailStr.get(), pNotesStr.get(),
pDirName.get(), bIsMailList, matchType,
results);
}
}
}
}
@ -489,9 +537,11 @@ nsresult nsAbAutoCompleteSession::SearchPreviousResults(nsAbAutoCompleteSearchSt
MatchType matchType;
if (CheckEntry(searchStr, param->mNickName, param->mDisplayName, param->mFirstName, param->mLastName, param->mEmailAddress, &matchType))
AddToResult(param->mNickName, param->mDisplayName, param->mFirstName, param->mLastName, param->mEmailAddress,
param->mNotes, param->mIsMailList, matchType, results);
AddToResult(param->mNickName, param->mDisplayName,
param->mFirstName, param->mLastName,
param->mEmailAddress, param->mNotes,
param->mDirName, param->mIsMailList, matchType,
results);
}
return NS_OK;
}
@ -518,7 +568,16 @@ NS_IMETHODIMP nsAbAutoCompleteSession::OnStartLookup(const PRUnichar *uSearchStr
listener->OnAutoComplete(nsnull, nsIAutoCompleteStatus::ignored);
return NS_OK;
}
// figure out what we're supposed to do about the comment column, and
// remember it for when the results start coming back
//
rv = pPref->GetIntPref("mail.autoComplete.commentColumn",
&mAutoCompleteCommentColumn);
if (NS_FAILED(rv)) {
mAutoCompleteCommentColumn = 0;
}
PRInt32 i;
for (i = nsCRT::strlen(uSearchString) - 1; i >= 0; i --)
if (uSearchString[i] == '@')
@ -549,7 +608,9 @@ NS_IMETHODIMP nsAbAutoCompleteSession::OnStartLookup(const PRUnichar *uSearchStr
if (mDefaultDomain[0] != 0)
{
PRUnichar emptyStr = 0;
AddToResult(&emptyStr, uSearchString, &emptyStr, &emptyStr, &emptyStr, &emptyStr, PR_FALSE, DEFAULT_MATCH, results);
AddToResult(&emptyStr, uSearchString, &emptyStr, &emptyStr,
&emptyStr, &emptyStr, &emptyStr, PR_FALSE,
DEFAULT_MATCH, results);
addedDefaultItem = PR_TRUE;
}

Просмотреть файл

@ -82,9 +82,14 @@ public:
protected:
void ResetMatchTypeConters();
PRBool ItsADuplicate(PRUnichar* fullAddrStr, nsIAutoCompleteResults* results);
void AddToResult(const PRUnichar* pNickNameStr, const PRUnichar* pDisplayNameStr, const PRUnichar* pFirstNameStr, const PRUnichar* pLastNameStr,
const PRUnichar* pEmailStr, const PRUnichar* pNotes, PRBool bIsMailList, MatchType type, nsIAutoCompleteResults* results);
PRBool CheckEntry(nsAbAutoCompleteSearchString* searchStr, const PRUnichar* nickName,const PRUnichar* displayName,
void AddToResult(const PRUnichar* pNickNameStr,
const PRUnichar* pDisplayNameStr,
const PRUnichar* pFirstNameStr,
const PRUnichar* pLastNameStr,
const PRUnichar* pEmailStr, const PRUnichar* pNotes,
const PRUnichar* pDirName, PRBool bIsMailList,
MatchType type, nsIAutoCompleteResults* results);
PRBool CheckEntry(nsAbAutoCompleteSearchString* searchStr, const PRUnichar* nickName,const PRUnichar* displayName,
const PRUnichar* firstName, const PRUnichar* lastName, const PRUnichar* emailAddress, MatchType* matchType);
nsresult SearchCards(nsIAbDirectory* directory, nsAbAutoCompleteSearchString* searchStr, nsIAutoCompleteResults* results);
nsresult SearchDirectory(nsString& fileName, nsAbAutoCompleteSearchString* searchStr, nsIAutoCompleteResults* results, PRBool searchSubDirectory = PR_FALSE);
@ -93,6 +98,16 @@ protected:
nsCOMPtr<nsIMsgHeaderParser> mParser;
nsString mDefaultDomain;
PRUint32 mMatchTypeConters[LAST_MATCH_TYPE];
// how to process the comment column, if at all. this value
// comes from "mail.autoComplete.commentColumn", or, if that
// doesn't exist, defaults to 0
//
// 0 = none
// 1 = name of addressbook this card came from
// 2 = other per-addressbook format (currrently unused here)
//
PRInt32 mAutoCompleteCommentColumn;
};
@ -113,6 +128,7 @@ public:
const PRUnichar* lastName,
const PRUnichar* emailAddress,
const PRUnichar* notes,
const PRUnichar* dirName,
PRBool isMailList,
nsAbAutoCompleteSession::MatchType type)
{
@ -123,6 +139,7 @@ public:
mLastName = nsCRT::strdup(lastName ? lastName : NS_STATIC_CAST(const PRUnichar*, NS_LITERAL_STRING("").get()));
mEmailAddress = nsCRT::strdup(emailAddress ? emailAddress : NS_STATIC_CAST(const PRUnichar*, NS_LITERAL_STRING("").get()));
mNotes = nsCRT::strdup(notes ? notes : NS_STATIC_CAST(const PRUnichar*, NS_LITERAL_STRING("").get()));
mDirName = nsCRT::strdup(dirName ? dirName : NS_STATIC_CAST(const PRUnichar *, NS_LITERAL_STRING("").get()));
mIsMailList = isMailList;
mType = type;
}
@ -135,6 +152,7 @@ public:
CRTFREEIF(mLastName);
CRTFREEIF(mEmailAddress);
CRTFREEIF(mNotes);
CRTFREEIF(mDirName);
};
protected:
@ -144,6 +162,7 @@ protected:
PRUnichar* mLastName;
PRUnichar* mEmailAddress;
PRUnichar* mNotes;
PRUnichar* mDirName;
PRBool mIsMailList;
nsAbAutoCompleteSession::MatchType mType;

Просмотреть файл

@ -43,8 +43,7 @@ NS_IMPL_ISUPPORTS2(nsAbLDAPAutoCompFormatter,
nsAbLDAPAutoCompFormatter::nsAbLDAPAutoCompFormatter() :
mNameFormat(NS_LITERAL_STRING("[cn]")),
mAddressFormat(NS_LITERAL_STRING("{mail}")),
mCommentFormat(NS_LITERAL_STRING("[o]"))
mAddressFormat(NS_LITERAL_STRING("{mail}"))
{
NS_INIT_ISUPPORTS();
}
@ -126,19 +125,18 @@ nsAbLDAPAutoCompFormatter::Format(nsILDAPMessage *aMsg,
//
nsCAutoString comment;
rv = ProcessFormat(mCommentFormat, aMsg, &comment, 0);
if (NS_FAILED(rv)) {
// Something went wrong lower down the stack; a messagne should have
// already been logged there. Return an error rather than
// trying to generate a bogus nsIAutoCompleteItem.
//
return rv;
if (NS_SUCCEEDED(rv)) {
rv = item->SetComment(NS_ConvertUTF8toUCS2(comment).get());
if (NS_FAILED(rv)) {
NS_WARNING("nsAbLDAPAutoCompFormatter::Format():"
" item->SetComment() failed");
}
}
rv = item->SetComment(NS_ConvertUTF8toUCS2(comment).get());
rv = item->SetClassName("remote-abook");
if (NS_FAILED(rv)) {
NS_ERROR("nsAbLDAPAutoCompFormatter::Format():"
" item->SetComment failed");
return rv;
NS_WARNING("nsAbLDAPAutoCompleteFormatter::Format():"
" item->SetClassName() failed");
}
// all done; return the item
@ -347,7 +345,7 @@ nsAbLDAPAutoCompFormatter::ProcessFormat(const nsAReadableString & aFormat,
// this character gets treated as a literal
//
(*aValue).Append(NS_STATIC_CAST(char, *iter));
(*aValue).Append(NS_ConvertUCS2toUTF8(*iter));
}
}

Просмотреть файл

@ -712,17 +712,50 @@ function setupLdapAutocompleteSession()
// nsAbLDAPAutoCompFormatter use its default.
}
// override autocomplete entry comment format?
//
try {
ldapFormatter.commentFormat =
prefs.CopyUnicharPref(autocompleteDirectory +
".autoComplete.commentFormat");
// figure out what goes in the comment column, if anything
//
// 0 = none
// 1 = name of addressbook this card came from
// 2 = other per-addressbook format
//
var showComments = 0;
showComments = prefs.GetIntPref(
"mail.autoComplete.commentColumn");
switch (showComments) {
case 1:
// use the name of this directory
//
ldapFormatter.commentFormat = prefs.CopyUnicharPref(
autocompleteDirectory + ".description");
break;
case 2:
// override ldap-specific autocomplete entry?
//
try {
ldapFormatter.commentFormat =
prefs.CopyUnicharPref(autocompleteDirectory +
".autoComplete.commentFormat");
} catch (innerException) {
// if nothing has been specified, use the ldap
// organization field
ldapFormatter.commentFormat = "[o]";
}
break;
case 0:
default:
// do nothing
}
} catch (ex) {
// if this pref isn't there, no big deal. just let
// nsAbLDAPAutoCompFormatter use its default.
// if something went wrong while setting up comments, try and
// proceed anyway
}
// set the session's formatter, which also happens to
// force a call to the formatter's getAttributes() method
// -- which is why this needs to happen after we've set the
@ -2074,8 +2107,22 @@ function setupAutocomplete()
var emailAddr = gCurrentIdentity.email;
var start = emailAddr.lastIndexOf("@");
gAutocompleteSession.defaultDomain = emailAddr.slice(start + 1, emailAddr.length);
}
else {
// if the pref is set to turn on the comment column, honor it here.
// this element then gets cloned for subsequent rows, so they should
// honor it as well
//
try {
if (prefs.GetIntPref("mail.autoComplete.commentColumn")) {
document.getElementById('msgRecipient#1').showCommentColumn =
true;
}
} catch (ex) {
// if we can't get this pref, then don't show the columns (which is
// what the XUL defaults to)
}
} else {
gAutocompleteSession = 1;
}
}

Просмотреть файл

@ -432,6 +432,11 @@ function awAppendNewRow(setFocus)
//this copies the autocomplete sessions list from recipient#1
input[0].syncSessions(document.getElementById('msgRecipient#1'));
// also clone the showCommentColumn setting
//
input[0].showCommentColumn =
document.getElementById("msgRecipient#1").showCommentColumn;
// We always clone the first row. The problem is that the first row
// could be focused. When we clone that row, we end up with a cloned
// XUL textbox that has a focused attribute set. Therefore we think

Просмотреть файл

@ -481,6 +481,7 @@ classic.jar:
skin/classic/messenger/addressbook/person-hover.gif (messenger/addressbook/person-hover.gif)
skin/classic/messenger/addressbook/person.gif (messenger/addressbook/person.gif)
skin/classic/messenger/addressbook/property.gif (messenger/addressbook/property.gif)
skin/classic/messenger/addressbook/remote-abook.gif (messenger/addressbook/remote-abook.gif)
skin/classic/messenger/addressbook/searchold-disabled.gif (messenger/addressbook/searchold-disabled.gif)
skin/classic/messenger/addressbook/searchold-hover-active.gif (messenger/addressbook/searchold-hover-active.gif)
skin/classic/messenger/addressbook/searchold-hover.gif (messenger/addressbook/searchold-hover.gif)

Просмотреть файл

Просмотреть файл

@ -257,7 +257,27 @@
list-style-image : url("chrome://messenger/skin/abcard.gif");
margin : 0px 3px 0px 3px;
}
outlinerbody:-moz-outliner-cell-text(default-match)
{
margin: 2px -3px 2px 15px;
border: none;
}
outlinerbody:-moz-outliner-image(local-abook)
{
margin: 2px -1px 2px 4px;
border: none;
list-style-image: url("chrome://messenger/skin/addressbook/myaddrbk.gif");
}
outlinerbody:-moz-outliner-image(remote-abook)
{
margin: 2px -3px 2px 2px;
border: none;
list-style-image: url("chrome://messenger/skin/addressbook/remote-abook.gif");
}
#msgheaderstoolbar-box
{
margin-top : 2px;

Просмотреть файл

@ -19,6 +19,7 @@
*
* Contributor(s):
* Joe Hewitt (hewitt@netscape.com)
* Dan Mosedale <dmose@netscape.com>
*/
/* ===== messengercompose.css ===========================================
@ -226,6 +227,23 @@
list-style-image: url("chrome://messenger/skin/addressbook/icons/person.gif");
}
outlinerbody:-moz-outliner-cell-text(default-match) {
margin: 2px -3px 2px 15px;
border: none;
}
outlinerbody:-moz-outliner-image(local-abook) {
margin: 2px -3px 2px 4px;
border: none;
list-style-image: url("chrome://messenger/skin/addressbook/icons/myaddrbk.gif");
}
outlinerbody:-moz-outliner-image(remote-abook) {
margin: 2px -4px 2px 3px;
border: none;
list-style-image: url("chrome://messenger/skin/addressbook/icons/directory.gif");
}
/* ::::: status bar border tweaks ::::: */
statusbarpanel,

Просмотреть файл

@ -58,7 +58,7 @@
this.ifSetAttribute("disableAutocomplete", false);
this.ifSetAttribute("forceComplete", false);
this.ifSetAttribute("tabScrolling", false);
this.ifSetAttribute("showCommentColumn", false);
// initialize the search sessions
this.searchSessions = this.getAttribute("searchSessions");
@ -154,11 +154,40 @@
onset="return this.setAttribute('autoFillAfterMatch', val);"
onget="return this.getAttribute('autoFillAfterMatch') == 'true';"/>
<!-- adds a second column to the results list which contains the string
in the comment field of each autocomplete result -->
<!-- toggles a second column in the results list which contains
the string in the comment field of each autocomplete result -->
<property name="showCommentColumn"
onset="return this.setAttribute('showCommentColumn', val);"
onget="return this.getAttribute('showCommentColumn') == 'true';"/>
onget=
"return this.getAttribute('showCommentColumn') == 'true';">
<setter><![CDATA[
var currentState = this.getAttribute('showCommentColumn');
// if comment column has been switched from off to on
//
if (val && (currentState == 'false')) {
// reset the flex on the value column and add the comment column
//
document.getElementById("value").setAttribute("flex", 2);
this.resultsPopup.addColumn({id: "comment", flex: 1});
// if comment column has been switched from on to off
//
} else if (!val && (currentState == 'true')) {
// reset the flex on the value column and add the comment column
//
document.getElementById("value").setAttribute("flex", 1);
this.resultsPopup.removeColumn('comment');
}
// save and return the current state
//
return this.setAttribute('showCommentColumn', val);
]]></setter>
</property>
<!-- option for completing to the default result whenever the user hits
enter or the textbox loses focus -->
@ -1057,6 +1086,21 @@
getCellProperties: function(aIndex, aColId, aProperties)
{
this.getRowProperties(aIndex, aProperties);
// for the value column, append nsIAutoCompleteItem::className
// to the property list so that we can style this column
// using that property
try {
if (aColId == "value") {
var className = this.mTextbox.getResultAt(aIndex).className;
if ( className != "" ) {
aProperties.AppendElement(this.createAtom(className));
}
}
} catch (ex) {
// the ability to style here is a frill, so don't abort
// if there's a problem
}
},
getColumnProperties: function(aColId, aColElt, aProperties)
@ -1182,6 +1226,15 @@
]]></body>
</method>
<!-- remove a single column from the outliner, specified by
element id -->
<method name="removeColumn">
<parameter name="aColId"/>
<body><![CDATA[
return this.outliner.removeChild(document.getElementById(aColId));
]]></body>
</method>
<method name="adjustHeight">
<body><![CDATA[
// detect the desired height of the outliner