зеркало из https://github.com/mozilla/pjs.git
125197 - and/or search tables for ab searches - r=cavin, sr=sspitzer
This commit is contained in:
Родитель
b091b7d994
Коммит
d3eaf21903
|
@ -625,6 +625,10 @@
|
|||
<property name="valueIds" readonly="true">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
var attrs_length = new Object;
|
||||
var attrs = this.validityTable.getAvailableAttributes(attrs_length);
|
||||
if (!(this.searchAttribute in attrs))
|
||||
this.searchAttribute = Components.interfaces.nsMsgSearchAttrib.Default;
|
||||
var length = new Object;
|
||||
return this.validityTable.getAvailableOperators(this.searchAttribute,length);
|
||||
]]>
|
||||
|
|
|
@ -214,7 +214,9 @@ protected:
|
|||
#endif
|
||||
nsCOMPtr<nsIMsgSearchValidityTable> m_localNewsTable; // used for local news searching or offline news searching...
|
||||
nsCOMPtr<nsIMsgSearchValidityTable> m_ldapTable;
|
||||
nsCOMPtr<nsIMsgSearchValidityTable> m_ldapAndTable;
|
||||
nsCOMPtr<nsIMsgSearchValidityTable> m_localABTable;
|
||||
nsCOMPtr<nsIMsgSearchValidityTable> m_localABAndTable;
|
||||
nsCOMPtr<nsIMsgSearchValidityTable> m_newsFilterTable;
|
||||
|
||||
nsresult NewTable (nsIMsgSearchValidityTable **);
|
||||
|
@ -234,8 +236,10 @@ protected:
|
|||
nsresult SetOtherHeadersInTable(nsIMsgSearchValidityTable *table, const char *customHeaders);
|
||||
|
||||
nsresult InitLdapTable();
|
||||
nsresult InitLdapAndTable();
|
||||
nsresult InitLocalABTable();
|
||||
nsresult SetUpABTable(nsIMsgSearchValidityTable *aTable, PRBool isLocal);
|
||||
nsresult InitLocalABAndTable();
|
||||
nsresult SetUpABTable(nsIMsgSearchValidityTable *aTable, PRBool isOrTable);
|
||||
nsresult EnableDirectoryAttribute(nsIMsgSearchValidityTable *table, nsMsgSearchAttribValue aSearchAttrib);
|
||||
};
|
||||
|
||||
|
|
|
@ -60,6 +60,8 @@ interface nsMsgSearchScope {
|
|||
const nsMsgSearchScopeValue LocalAB = 8;
|
||||
const nsMsgSearchScopeValue allSearchableGroups = 9;
|
||||
const nsMsgSearchScopeValue newsFilter = 10;
|
||||
const nsMsgSearchScopeValue LocalABAnd = 11;
|
||||
const nsMsgSearchScopeValue LDAPAnd = 12;
|
||||
};
|
||||
|
||||
typedef long nsMsgSearchAttribValue;
|
||||
|
@ -86,25 +88,26 @@ interface nsMsgSearchAttrib {
|
|||
const nsMsgSearchAttribValue AnyText = 14;
|
||||
const nsMsgSearchAttribValue Keywords = 15;
|
||||
|
||||
const nsMsgSearchAttribValue Name = 16;
|
||||
const nsMsgSearchAttribValue Email = 17;
|
||||
const nsMsgSearchAttribValue PhoneNumber = 18;
|
||||
const nsMsgSearchAttribValue City = 19;
|
||||
const nsMsgSearchAttribValue Street = 20;
|
||||
const nsMsgSearchAttribValue Nickname = 21;
|
||||
const nsMsgSearchAttribValue WorkPhone = 22;
|
||||
const nsMsgSearchAttribValue HomePhone = 23;
|
||||
const nsMsgSearchAttribValue Fax = 24;
|
||||
const nsMsgSearchAttribValue Pager = 25;
|
||||
const nsMsgSearchAttribValue Mobile = 26;
|
||||
const nsMsgSearchAttribValue ScreenName = 27;
|
||||
const nsMsgSearchAttribValue Title = 28;
|
||||
const nsMsgSearchAttribValue Organization = 29;
|
||||
const nsMsgSearchAttribValue Department = 30;
|
||||
const nsMsgSearchAttribValue AdditionalEmail = 31;
|
||||
const nsMsgSearchAttribValue Name = 16;
|
||||
const nsMsgSearchAttribValue DisplayName = 17;
|
||||
const nsMsgSearchAttribValue Nickname = 18;
|
||||
const nsMsgSearchAttribValue ScreenName = 19;
|
||||
const nsMsgSearchAttribValue Email = 20;
|
||||
const nsMsgSearchAttribValue AdditionalEmail = 21;
|
||||
const nsMsgSearchAttribValue PhoneNumber = 22;
|
||||
const nsMsgSearchAttribValue WorkPhone = 23;
|
||||
const nsMsgSearchAttribValue HomePhone = 24;
|
||||
const nsMsgSearchAttribValue Fax = 25;
|
||||
const nsMsgSearchAttribValue Pager = 26;
|
||||
const nsMsgSearchAttribValue Mobile = 27;
|
||||
const nsMsgSearchAttribValue City = 28;
|
||||
const nsMsgSearchAttribValue Street = 29;
|
||||
const nsMsgSearchAttribValue Title = 30;
|
||||
const nsMsgSearchAttribValue Organization = 31;
|
||||
const nsMsgSearchAttribValue Department = 32;
|
||||
|
||||
// 32 - 45, reserved for ab / LDAP;
|
||||
const nsMsgSearchAttribValue HasAttachmentStatus = 46;
|
||||
// 33 - 45, reserved for ab / LDAP;
|
||||
const nsMsgSearchAttribValue HasAttachmentStatus = 46;
|
||||
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.
|
||||
|
|
|
@ -149,11 +149,20 @@ function SelectDirectory(aURI)
|
|||
function GetScopeForDirectoryURI(aURI)
|
||||
{
|
||||
var directory = gRDF.GetResource(aURI).QueryInterface(nsIAbDirectory);
|
||||
var booleanAnd = gSearchBooleanRadiogroup.selectedItem.value == "and";
|
||||
|
||||
if (directory.isRemote)
|
||||
return nsMsgSearchScope.LDAP;
|
||||
else
|
||||
return nsMsgSearchScope.LocalAB;
|
||||
if (directory.isRemote) {
|
||||
if (booleanAnd)
|
||||
return nsMsgSearchScope.LDAPAnd;
|
||||
else
|
||||
return nsMsgSearchScope.LDAP;
|
||||
}
|
||||
else {
|
||||
if (booleanAnd)
|
||||
return nsMsgSearchScope.LocalABAnd;
|
||||
else
|
||||
return nsMsgSearchScope.LocalAB;
|
||||
}
|
||||
}
|
||||
|
||||
function onEnterInSearchTerm()
|
||||
|
@ -188,30 +197,31 @@ function onSearch()
|
|||
var count = gSearchSession.searchTerms.Count();
|
||||
|
||||
for (var i=0; i<count; i++) {
|
||||
var searchTerm = gSearchSession.searchTerms.GetElementAt(i).QueryInterface(nsIMsgSearchTerm);
|
||||
var searchTerm = gSearchSession.searchTerms.GetElementAt(i).QueryInterface(nsIMsgSearchTerm);
|
||||
|
||||
// get the "and" / "or" value from the first term
|
||||
if (i == 0) {
|
||||
// get the "and" / "or" value from the first term
|
||||
if (i == 0) {
|
||||
if (searchTerm.booleanAnd)
|
||||
searchUri += "and";
|
||||
else
|
||||
searchUri += "or";
|
||||
}
|
||||
}
|
||||
|
||||
var attrs;
|
||||
var attrs;
|
||||
|
||||
switch (searchTerm.attrib) {
|
||||
switch (searchTerm.attrib) {
|
||||
case nsMsgSearchAttrib.Name:
|
||||
// when doing an "and" search, we'll use the first one
|
||||
if (gSearchPhoneticName == "false")
|
||||
attrs = ["DisplayName","FirstName","LastName"];
|
||||
else
|
||||
attrs = ["DisplayName","FirstName","LastName","PhoneticFirstName","PhoneticLastName"];
|
||||
break;
|
||||
case nsMsgSearchAttrib.DisplayName:
|
||||
attrs = ["DisplayName"];
|
||||
break;
|
||||
case nsMsgSearchAttrib.Email:
|
||||
attrs = ["PrimaryEmail"];
|
||||
break;
|
||||
// when doing an "and" search, we'll use the first one
|
||||
case nsMsgSearchAttrib.PhoneNumber:
|
||||
attrs = ["HomePhone","WorkPhone","FaxNumber","PagerNumber","CellularNumber"];
|
||||
break;
|
||||
|
@ -258,11 +268,11 @@ function onSearch()
|
|||
dump("XXX " + searchTerm.attrib + " not a supported search attr!\n");
|
||||
attrs = ["DisplayName"];
|
||||
break;
|
||||
}
|
||||
|
||||
var opStr;
|
||||
}
|
||||
|
||||
switch (searchTerm.op) {
|
||||
var opStr;
|
||||
|
||||
switch (searchTerm.op) {
|
||||
case nsMsgSearchOp.Contains:
|
||||
opStr = "c";
|
||||
break;
|
||||
|
@ -287,30 +297,16 @@ function onSearch()
|
|||
default:
|
||||
opStr = "c";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// currently, we can't do "and" and "or" searches at the same time
|
||||
// (it's either all "and"s or all "or"s)
|
||||
//
|
||||
// so, if we are doing an "and" search
|
||||
// on "Any name" or "Any number" we don't want this:
|
||||
// (displayname,c,seth) && (firstname,c,seth) && (lastname,c,seth)
|
||||
// instead, just use the first term (displayname,c,seth)
|
||||
// max_attrs = 1;
|
||||
//
|
||||
// But, if we are doing an "any" search, we do want:
|
||||
// (displayname,c,seth) || (firstname,c,seth) || (lastname,c,seth)
|
||||
// max_attrs = attrs.length
|
||||
var max_attrs;
|
||||
if (searchTerm.booleanAnd)
|
||||
max_attrs = 1;
|
||||
else
|
||||
max_attrs = attrs.length;
|
||||
// currently, we can't do "and" and "or" searches at the same time
|
||||
// (it's either all "and"s or all "or"s)
|
||||
var max_attrs = attrs.length;
|
||||
|
||||
for (var j=0;j<max_attrs;j++) {
|
||||
for (var j=0;j<max_attrs;j++) {
|
||||
// append the term(s) to the searchUri
|
||||
searchUri += "(" + attrs[j] + "," + opStr + "," + escape(searchTerm.value.str) + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
searchUri += ")";
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
|
||||
<!--
|
||||
The contents of this file are subject to the Netscape Public
|
||||
License Version 1.1 (the "License"); you may not use this file
|
||||
|
@ -70,60 +68,57 @@ Rights Reserved.
|
|||
|
||||
<vbox flex="1">
|
||||
<vbox>
|
||||
<hbox align="center">
|
||||
<label value="&abSearchHeading.label;" accesskey="&abSearchHeading.accesskey;"/>
|
||||
|
||||
<menulist id="abPopup">
|
||||
<menupopup id="abPopup-menupopup" ref="moz-abdirectory://"
|
||||
datasources="rdf:addressdirectory"
|
||||
sortActive="true"
|
||||
sortDirection="ascending"
|
||||
sortResource="http://home.netscape.com/NC-rdf#DirTreeNameSort">
|
||||
<template>
|
||||
<rule nc:IsMailList="false">
|
||||
<menuitem uri="..."
|
||||
oncommand="onChooseDirectory(event.target)"
|
||||
label="rdf:http://home.netscape.com/NC-rdf#DirName"
|
||||
value="rdf:http://home.netscape.com/NC-rdf#DirUri"/>
|
||||
</rule>
|
||||
</template>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
|
||||
<spacer flex="10"/>
|
||||
<button label="&searchButton.label;" id="search-button" oncommand="onSearchButton(event);" default="true" accesskey="&searchButton.accesskey;"/>
|
||||
|
||||
<hbox align="center">
|
||||
<label value="&abSearchHeading.label;" accesskey="&abSearchHeading.accesskey;"/>
|
||||
<menulist id="abPopup">
|
||||
<menupopup id="abPopup-menupopup" ref="moz-abdirectory://"
|
||||
datasources="rdf:addressdirectory"
|
||||
sortActive="true"
|
||||
sortDirection="ascending"
|
||||
sortResource="http://home.netscape.com/NC-rdf#DirTreeNameSort">
|
||||
<template>
|
||||
<rule nc:IsMailList="false">
|
||||
<menuitem uri="..."
|
||||
oncommand="onChooseDirectory(event.target)"
|
||||
label="rdf:http://home.netscape.com/NC-rdf#DirName"
|
||||
value="rdf:http://home.netscape.com/NC-rdf#DirUri"/>
|
||||
</rule>
|
||||
</template>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
<spacer flex="10"/>
|
||||
<button label="&searchButton.label;" id="search-button" oncommand="onSearchButton(event);" default="true" accesskey="&searchButton.accesskey;"/>
|
||||
</hbox>
|
||||
<hbox align="center">
|
||||
<spacer flex="1"/>
|
||||
<button label="&resetButton.label;" oncommand="onAbSearchReset(event);" accesskey="&resetButton.accesskey;"/>
|
||||
</hbox>
|
||||
|
||||
<hbox align="center">
|
||||
<spacer flex="2"/>
|
||||
<button label="&helpButton.label;" align="end" oncommand="openHelp('mail_advanced_ab_search');" accesskey="&helpButton.accesskey;"/>
|
||||
</hbox>
|
||||
<spacer flex="1"/>
|
||||
<button label="&resetButton.label;" oncommand="onAbSearchReset(event);" accesskey="&resetButton.accesskey;"/>
|
||||
</hbox>
|
||||
<hbox align="center">
|
||||
<spacer flex="2"/>
|
||||
<button label="&helpButton.label;" align="end" oncommand="openHelp('mail_advanced_ab_search');" accesskey="&helpButton.accesskey;"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<hbox flex="1">
|
||||
<vbox id="searchTermListBox" flex="1"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
|
||||
<splitter id="gray_horizontal_splitter" collapse="after" persist="state">
|
||||
<grippy/>
|
||||
</splitter>
|
||||
|
||||
|
||||
<vbox flex="1">
|
||||
<vbox id="searchResultListBox" flex="1" >
|
||||
<tree id="abResultsTree" flex="1" persist="height" context="threadPaneContext"/>
|
||||
</vbox>
|
||||
<hbox align="start">
|
||||
<button label="&propertiesButton.label;" id="propertiesButton" oncommand="onProperties()" accesskey="&propertiesButton.accesskey;" disabled="true"/>
|
||||
<button label="&composeButton.label;" id="composeButton" oncommand="onCompose()" accesskey="&composeButton.accesskey;" disabled="true"/>
|
||||
<spacer flex="1" />
|
||||
</hbox>
|
||||
<vbox id="searchResultListBox" flex="1" >
|
||||
<tree id="abResultsTree" flex="1" persist="height" context="threadPaneContext"/>
|
||||
</vbox>
|
||||
<hbox align="start">
|
||||
<button label="&propertiesButton.label;" id="propertiesButton" oncommand="onProperties()" accesskey="&propertiesButton.accesskey;" disabled="true"/>
|
||||
<button label="&composeButton.label;" id="composeButton" oncommand="onCompose()" accesskey="&composeButton.accesskey;" disabled="true"/>
|
||||
<spacer flex="1" />
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<statusbar class="chromeclass-status" id="status-bar"/>
|
||||
<statusbar class="chromeclass-status" id="status-bar"/>
|
||||
|
||||
</window>
|
||||
|
|
|
@ -244,7 +244,8 @@ function onLess(event)
|
|||
}
|
||||
|
||||
// set scope on all visible searchattribute tags
|
||||
function setSearchScope(scope) {
|
||||
function setSearchScope(scope)
|
||||
{
|
||||
gSearchScope = scope;
|
||||
for (var i=0; i<gSearchTerms.length; i++) {
|
||||
gSearchTerms[i].obj.searchattribute.searchScope = scope;
|
||||
|
@ -260,10 +261,12 @@ function updateSearchAttributes()
|
|||
}
|
||||
|
||||
function booleanChanged(event) {
|
||||
// when boolean changes, we have to update all the attributes on the
|
||||
// search terms
|
||||
|
||||
// when boolean changes, we have to update all the attributes on the search terms
|
||||
var newBoolValue = (event.target.getAttribute("value") == "and") ? true : false;
|
||||
if (document.getElementById("abPopup")) {
|
||||
var selectedAB = document.getElementById("abPopup").selectedItem.id;
|
||||
setSearchScope(GetScopeForDirectoryURI(selectedAB));
|
||||
}
|
||||
for (var i=0; i<gSearchTerms.length; i++) {
|
||||
var searchTerm = gSearchTerms[i].obj;
|
||||
searchTerm.booleanAnd = newBoolValue;
|
||||
|
@ -277,7 +280,6 @@ function booleanChanged(event) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
function createSearchRow(index, scope, searchTerm)
|
||||
{
|
||||
var searchAttr = document.createElement("searchattribute");
|
||||
|
|
|
@ -17,23 +17,23 @@
|
|||
14=AnyText
|
||||
15=Keywords
|
||||
# for AB and LDAP
|
||||
16=Any name
|
||||
17=Email
|
||||
18=Any number
|
||||
19=City
|
||||
20=Street
|
||||
21=Nickname
|
||||
22=Work Phone
|
||||
23=Home Phone
|
||||
24=Fax
|
||||
25=Pager
|
||||
26=Mobile
|
||||
27=Screen Name
|
||||
28=Title
|
||||
29=Organization
|
||||
30=Department
|
||||
31=Additional Email
|
||||
32=reserved for AB
|
||||
16=Any Name
|
||||
17=Display Name
|
||||
18=Nickname
|
||||
19=Screen Name
|
||||
20=Email
|
||||
21=Additional Email
|
||||
22=Any Number
|
||||
23=Work Phone
|
||||
24=Home Phone
|
||||
25=Fax
|
||||
26=Pager
|
||||
27=Mobile
|
||||
28=City
|
||||
29=Street
|
||||
30=Title
|
||||
31=Organization
|
||||
32=Department
|
||||
33=reserved for AB
|
||||
34=reserved for AB
|
||||
35=reserved for AB
|
||||
|
|
|
@ -1089,11 +1089,21 @@ NS_IMETHODIMP nsMsgSearchValidityManager::GetTable (int whichTable, nsIMsgSearch
|
|||
rv = InitLdapTable ();
|
||||
*ppOutTable = m_ldapTable;
|
||||
break;
|
||||
case nsMsgSearchScope::LDAPAnd:
|
||||
if (!m_ldapAndTable)
|
||||
rv = InitLdapAndTable ();
|
||||
*ppOutTable = m_ldapAndTable;
|
||||
break;
|
||||
case nsMsgSearchScope::LocalAB:
|
||||
if (!m_localABTable)
|
||||
rv = InitLocalABTable ();
|
||||
*ppOutTable = m_localABTable;
|
||||
break;
|
||||
case nsMsgSearchScope::LocalABAnd:
|
||||
if (!m_localABAndTable)
|
||||
rv = InitLocalABAndTable ();
|
||||
*ppOutTable = m_localABAndTable;
|
||||
break;
|
||||
default:
|
||||
NS_ASSERTION(PR_FALSE, "invalid table type");
|
||||
rv = NS_MSG_ERROR_INVALID_SEARCH_TERM;
|
||||
|
@ -1164,7 +1174,6 @@ nsMsgSearchValidityManager::SetOtherHeadersInTable (nsIMsgSearchValidityTable *a
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsMsgSearchValidityManager::EnableDirectoryAttribute(nsIMsgSearchValidityTable *table, nsMsgSearchAttribValue aSearchAttrib)
|
||||
{
|
||||
table->SetAvailable (aSearchAttrib, nsMsgSearchOp::Contains, 1);
|
||||
|
@ -1191,7 +1200,19 @@ nsresult nsMsgSearchValidityManager::InitLdapTable()
|
|||
nsresult rv = NewTable(getter_AddRefs(m_ldapTable));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
rv = SetUpABTable(m_ldapTable, PR_FALSE);
|
||||
rv = SetUpABTable(m_ldapTable, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgSearchValidityManager::InitLdapAndTable()
|
||||
{
|
||||
NS_ASSERTION(!m_ldapAndTable,"don't call this twice!");
|
||||
|
||||
nsresult rv = NewTable(getter_AddRefs(m_ldapAndTable));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
rv = SetUpABTable(m_ldapAndTable, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
return rv;
|
||||
}
|
||||
|
@ -1208,14 +1229,33 @@ nsresult nsMsgSearchValidityManager::InitLocalABTable()
|
|||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsMsgSearchValidityManager::SetUpABTable(nsIMsgSearchValidityTable *aTable, PRBool isLocal)
|
||||
nsresult nsMsgSearchValidityManager::InitLocalABAndTable()
|
||||
{
|
||||
nsresult rv = aTable->SetDefaultAttrib(nsMsgSearchAttrib::Name);
|
||||
NS_ASSERTION(!m_localABAndTable,"don't call this twice!");
|
||||
|
||||
nsresult rv = NewTable(getter_AddRefs(m_localABAndTable));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
rv = EnableDirectoryAttribute(aTable, nsMsgSearchAttrib::Name);
|
||||
rv = SetUpABTable(m_localABAndTable, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgSearchValidityManager::SetUpABTable(nsIMsgSearchValidityTable *aTable, PRBool isOrTable)
|
||||
{
|
||||
nsresult rv = aTable->SetDefaultAttrib(isOrTable ? nsMsgSearchAttrib::Name : nsMsgSearchAttrib::DisplayName);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
if (isOrTable) {
|
||||
rv = EnableDirectoryAttribute(aTable, nsMsgSearchAttrib::Name);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
rv = EnableDirectoryAttribute(aTable, nsMsgSearchAttrib::PhoneNumber);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
}
|
||||
|
||||
rv = EnableDirectoryAttribute(aTable, nsMsgSearchAttrib::DisplayName);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
rv = EnableDirectoryAttribute(aTable, nsMsgSearchAttrib::Email);
|
||||
|
@ -1260,9 +1300,5 @@ nsMsgSearchValidityManager::SetUpABTable(nsIMsgSearchValidityTable *aTable, PRBo
|
|||
rv = EnableDirectoryAttribute(aTable, nsMsgSearchAttrib::Mobile);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
rv = EnableDirectoryAttribute(aTable, nsMsgSearchAttrib::PhoneNumber);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче