Revision: 7204
http://svn.sourceforge.net/mahogany/?rev=7204&view=rev
Author: vadz
Date: 2007-01-08 13:23:41 -0800 (Mon, 08 Jan 2007)
Log Message:
-----------
Refactoring, fixes and improvements to addresses expansion:
- extract the non-GUI login into functions in AdbManager.h/.cpp
- extract GUI logic for addresses in wxTextCtrl (and wxComboBox in the future)
in separate AddressExpander class
- better/more consistent handling of to:/cc:/... prefixes
- expand all addresses and not just the 1st one when Enter is pressed (bug 921)
Modified Paths:
--------------
trunk/M/M.vcproj
trunk/M/include/Composer.h
trunk/M/include/adb/AdbManager.h
trunk/M/include/gui/wxComposeView.h
trunk/M/src/adb/AdbManager.cpp
trunk/M/src/classes/MApplication.cpp
trunk/M/src/gui/wxComposeView.cpp
trunk/M/src/mail/MailFolder.cpp
Added Paths:
-----------
trunk/M/include/gui/AddressExpander.h
trunk/M/src/gui/AddressExpander.cpp
Modified: trunk/M/M.vcproj
===================================================================
--- trunk/M/M.vcproj 2007-01-08 00:09:32 UTC (rev 7203)
+++ trunk/M/M.vcproj 2007-01-08 21:23:41 UTC (rev 7204)
@@ -373,6 +373,9 @@
Name="gui"
Filter="">
<File
+ RelativePath=".\src\gui\AddressExpander.cpp">
+ </File>
+ <File
RelativePath=".\src\gui\ClickAtt.cpp">
</File>
<File
@@ -859,7 +862,8 @@
<Tool
Name="VCCustomBuildTool"
Description="Creating MInterface.h and .cpp"
- CommandLine="extra\scripts\m4.bat $(InputDir) $(InputDir)"
+ CommandLine="extra\scripts\m4.bat $(InputDir) $(InputDir)
+"
AdditionalDependencies="$(InputDir)/MInterface.mid;$(InputDir)/MInterface.cpp.m4;$(InputDir)/MInterface.h.m4;$(InputDir)/mid2cpp.m4;$(InputDir)/mid2h.m4"
Outputs="$(InputDir)/MInterface.cpp;$(InputDir)/MInterface.h"/>
</FileConfiguration>
@@ -868,7 +872,8 @@
<Tool
Name="VCCustomBuildTool"
Description="Creating MInterface.h and .cpp"
- CommandLine="extra\scripts\m4.bat $(InputDir) $(InputDir)"
+ CommandLine="extra\scripts\m4.bat $(InputDir) $(InputDir)
+"
AdditionalDependencies="$(InputDir)/MInterface.mid;$(InputDir)/MInterface.cpp.m4;$(InputDir)/MInterface.h.m4;$(InputDir)/mid2cpp.m4;$(InputDir)/mid2h.m4"
Outputs="$(InputDir)/MInterface.cpp;$(InputDir)/MInterface.h"/>
</FileConfiguration>
@@ -877,7 +882,8 @@
<Tool
Name="VCCustomBuildTool"
Description="Creating MInterface.h and .cpp"
- CommandLine="extra\scripts\m4.bat $(InputDir) $(InputDir)"
+ CommandLine="extra\scripts\m4.bat $(InputDir) $(InputDir)
+"
AdditionalDependencies="$(InputDir)/MInterface.mid;$(InputDir)/MInterface.cpp.m4;$(InputDir)/MInterface.h.m4;$(InputDir)/mid2cpp.m4;$(InputDir)/mid2h.m4"
Outputs="$(InputDir)/MInterface.cpp;$(InputDir)/MInterface.h"/>
</FileConfiguration>
@@ -886,7 +892,8 @@
<Tool
Name="VCCustomBuildTool"
Description="Creating MInterface.h and .cpp"
- CommandLine="extra\scripts\m4.bat $(InputDir) $(InputDir)"
+ CommandLine="extra\scripts\m4.bat $(InputDir) $(InputDir)
+"
AdditionalDependencies="$(InputDir)/MInterface.mid;$(InputDir)/MInterface.cpp.m4;$(InputDir)/MInterface.h.m4;$(InputDir)/mid2cpp.m4;$(InputDir)/mid2h.m4"
Outputs="$(InputDir)/MInterface.cpp;$(InputDir)/MInterface.h"/>
</FileConfiguration>
@@ -1880,6 +1887,9 @@
RelativePath=".\include\AddressCC.h">
</File>
<File
+ RelativePath=".\include\gui\AddressExpander.h">
+ </File>
+ <File
RelativePath=".\include\ASMailFolder.h">
</File>
<File
Modified: trunk/M/include/Composer.h
===================================================================
--- trunk/M/include/Composer.h 2007-01-08 00:09:32 UTC (rev 7203)
+++ trunk/M/include/Composer.h 2007-01-08 21:23:41 UTC (rev 7204)
@@ -56,6 +56,13 @@
class Composer
{
public:
+ /// Flags for AddRecipients()
+ enum
+ {
+ /// Expand the address before adding it
+ AddRcpt_Expand = 1
+ };
+
/**
@name Different ways to create a new composer window
@@ -186,7 +193,7 @@
/// adds recipients from addr (Recipient_Max means to reuse the last)
virtual void AddRecipients(const String& addr,
RecipientType rcptType = Recipient_Max,
- bool doLayout = true) = 0;
+ int flags = AddRcpt_Expand) = 0;
/// adds a "To" recipient
void AddTo(const String& addr) { AddRecipients(addr, Recipient_To); }
@@ -223,15 +230,6 @@
*/
virtual void AddHeaderEntry(const String& entry, const String& value) = 0;
- /**
- Expand the given string: this method handles address book completion and
- mailto: URLs parsing. It modifies the string passed to it in place.
-
- @param text the text to expand, modified by the method
- @return the inferred recipient type or Recipient_None if invalid address
- */
- virtual RecipientType ExpandRecipient(String *text) = 0;
-
//@}
/** @name Add/insert stuff into composer */
Modified: trunk/M/include/adb/AdbManager.h
===================================================================
--- trunk/M/include/adb/AdbManager.h 2007-01-08 00:09:32 UTC (rev 7203)
+++ trunk/M/include/adb/AdbManager.h 2007-01-08 21:23:41 UTC (rev 7204)
@@ -17,6 +17,8 @@
#include "adb/AdbEntry.h" // for AdbLookup_xxx constants
+#include "RecipientType.h"
+
#ifndef USE_PCH
# include <wx/dynarray.h>
#endif // USE_PCH
@@ -25,6 +27,8 @@
class AdbBook;
class AdbDataProvider;
+class WXDLLEXPORT wxFrame;
+
// arrays
WX_DEFINE_ARRAY(AdbBook *, ArrayAdbBooks);
WX_DEFINE_ARRAY(AdbEntryGroup *, ArrayAdbGroups);
@@ -186,10 +190,70 @@
@return FALSE if no matches, TRUE if at least one item matched
*/
-class wxFrame;
extern bool AdbExpand(wxArrayString& results,
const String& what,
int how,
wxFrame *frame);
+/**
+ Expand a single address coming from the user input.
+
+ The user input can be a full address, a mailto: URL or a string to be
+ expanded using AdbExpand().
+
+ This function doesn't support multiple comma-separated addresses, use
+ AdbExpandRecipients() for this. Nor does it support "cc:"-like
+ prefixes selecting the recipient type, as AdbExpandSingleRecipient() does.
+
+ @param address the address string, modified in place by this function
+ @param subject filled with the subject on output if it's specified as
+ part of the address (currently only happens with mailto)
+ and is left empty otherwise
+ @param profile to use for expansion options
+ @param parent window to use as parent for the dialogs
+ @return true if the address was expanded, false if the expansion was
+ cancelled (address is unchanged then)
+ */
+bool AdbExpandSingleAddress(String *address,
+ String *subject,
+ Profile *profile,
+ wxFrame *win);
+
+/**
+ Expand a single address coming from the user input, possibly with a
+ recipient type string.
+
+ This function does the same thing as AdbExpandSingleAddress() except that
+ accepts "to:", "cc:" &c prefixes.
+
+ Returns the recipient type (which can be Recipient_None if none was
+ explicitly specified) or Recipient_Max is expansion was cancelled and the
+ address is unchanged.
+ */
+RecipientType AdbExpandSingleRecipient(String *address,
+ String *subject,
+ Profile *profile,
+ wxFrame *win);
+
+/**
+ Expand all addresses in the specified string.
+
+ Returns the number of addresses which can be 0 if the control was empty
+ or -1 if the expansion was cancelled.
+
+ @param text contains the addresses to expand
+ @param addresses filled in with the addresses on return
+ @param rcptTypes filled in with RecipientType enum elements
+ @param subject filled with the subject on output
+ @param profile to use for expansion options
+ @param parent window to use as parent for the dialogs
+ @return number of addresses expanded or -1 if cancelled
+ */
+int AdbExpandAllRecipients(const String& text,
+ wxArrayString& addresses,
+ wxArrayInt& rcptTypes,
+ String *subject,
+ Profile *profile,
+ wxFrame *win);
+
#endif //_ADBMANAGER_H
Added: trunk/M/include/gui/AddressExpander.h
===================================================================
--- trunk/M/include/gui/AddressExpander.h (rev 0)
+++ trunk/M/include/gui/AddressExpander.h 2007-01-08 21:23:41 UTC (rev 7204)
@@ -0,0 +1,73 @@
+///////////////////////////////////////////////////////////////////////////////
+// Project: M - cross platform e-mail GUI client
+// File name: gui/AddressExpander.h
+// Purpose: declaration of AddressExpander class
+// Author: Vadim Zeitlin
+// Created: 2007-01-08
+// CVS-ID: $Id$
+// Copyright: (c) 1998-2007 Mahogany team
+// Licence: M license
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ @file gui/AddressExpander.h
+ @brief Declaration of AddressExpander helper.
+
+ AddressExpander can be used with any control which needs to expand email
+ addresses entered into it by user by looking them up in the address books.
+ */
+
+#ifndef _M_GUI_ADDRESSEXPANDER_H_
+#define _M_GUI_ADDRESSEXPANDER_H_
+
+#include "RecipientType.h"
+
+class WXDLLEXPORT wxFrame;
+class WXDLLEXPORT wxTextCtrl;
+
+/**
+ AddressExpander is not a control but can be associated with an existing
+ control to add support for expanding addresses in it.
+ */
+class AddressExpander
+{
+public:
+ /**
+ Create an AddressExpander associated with the given text entry zone.
+
+ @param text the associated text control
+ @param profile for expansion options
+ */
+ AddressExpander(wxTextCtrl *text, Profile *profile);
+
+ /**
+ Calls AdbExpandAllRecipients() for the control contents.
+
+ Doesn't modify the control contents.
+ */
+ int ExpandAll(wxArrayString& addresses,
+ wxArrayInt& rcptTypes,
+ String *subject) const;
+
+ /**
+ Replaces the last address entered into the control with its expansion.
+
+ @param subject filled in with the subject if the recipient contains it
+ @return type of the recipient if explicitly specified, Recipient_None if
+ none and Recipient_Max if nothing was expanded
+ */
+ RecipientType ExpandLast(String *subject);
+
+private:
+ // return the parent window for ADB functions
+ wxFrame *GetParentFrame() const;
+
+
+ wxTextCtrl *m_text;
+ Profile_obj m_profile;
+
+ DECLARE_NO_COPY_CLASS(AddressExpander)
+};
+
+#endif // _M_GUI_ADDRESSEXPANDER_H_
+
Modified: trunk/M/include/gui/wxComposeView.h
===================================================================
--- trunk/M/include/gui/wxComposeView.h 2007-01-08 00:09:32 UTC (rev 7203)
+++ trunk/M/include/gui/wxComposeView.h 2007-01-08 21:23:41 UTC (rev 7204)
@@ -169,14 +169,11 @@
/// sets Subject field
void SetSubject(const String &subj);
- /// adds recepients from addr (Recepient_Max means to reuse the last)
+ /// adds recipients from addr (Recipient_Max means to reuse the last)
virtual void AddRecipients(const String& addr,
RecipientType rcptType = Recipient_Max,
- bool doLayout = true);
+ int flags = AddRcpt_Expand);
- /// expands an address
- virtual RecipientType ExpandRecipient(String *text);
-
/// get from value (empty means default)
String GetFrom() const;
Modified: trunk/M/src/adb/AdbManager.cpp
===================================================================
--- trunk/M/src/adb/AdbManager.cpp 2007-01-08 00:09:32 UTC (rev 7203)
+++ trunk/M/src/adb/AdbManager.cpp 2007-01-08 21:23:41 UTC (rev 7204)
@@ -39,6 +39,12 @@
#include "adb/AdbDialogs.h"
// ----------------------------------------------------------------------------
+// options we use here
+// ----------------------------------------------------------------------------
+
+extern const MOption MP_ADB_SUBSTRINGEXPANSION;
+
+// ----------------------------------------------------------------------------
// types
// ----------------------------------------------------------------------------
@@ -339,6 +345,204 @@
return !results.IsEmpty();
}
+bool
+AdbExpandSingleAddress(String *address,
+ String *subject,
+ Profile *profile,
+ wxFrame *win)
+{
+ CHECK( address && subject, false, "NULL input address" );
+
+ subject->clear();
+
+ String textOrig = *address;
+
+ // remove "mailto:" prefix if it's there - this is convenient when you paste
+ // in an URL from the web browser
+ //
+ // TODO: add support for the mailto URL parameters, i.e. should support
+ // things like "mailto:[email protected]?subject=Please%20help"
+ String newText;
+ if ( !textOrig.StartsWith(_T("mailto:"), &newText) )
+ {
+ // if the text already has a '@' inside it and looks like a full email
+ // address assume that it doesn't need to be expanded (this saves a lot
+ // of time as expanding a non existing address looks through all address
+ // books...)
+ size_t pos = textOrig.find('@');
+ if ( pos != String::npos && pos > 0 && pos < textOrig.length() )
+ {
+ // also check that the host part of the address is expanded - it
+ // should contain at least one dot normally
+ if ( wxStrchr(textOrig.c_str() + pos + 1, '.') )
+ {
+ // looks like a valid address - nothing to do
+ newText = textOrig;
+ }
+ }
+
+ if ( newText.empty() )
+ {
+ wxArrayString expansions;
+
+ if ( !AdbExpand(expansions,
+ textOrig,
+ READ_CONFIG(profile, MP_ADB_SUBSTRINGEXPANSION)
+ ? AdbLookup_Substring
+ : AdbLookup_StartsWith,
+ win) )
+ {
+ // cancelled, indicate it by returning invalid recipient type
+ return false;
+ }
+
+ // construct the replacement string(s)
+ size_t nExpCount = expansions.GetCount();
+ for ( size_t nExp = 0; nExp < nExpCount; nExp++ )
+ {
+ if ( nExp > 0 )
+ newText += ", ";
+
+ newText += expansions[nExp];
+ }
+ }
+ }
+ //else: address following mailto: doesn't need to be expanded
+
+ *address = newText;
+
+ return true;
+}
+
+RecipientType
+AdbExpandSingleRecipient(String *address,
+ String *subject,
+ Profile *profile,
+ wxFrame *win)
+{
+ CHECK( address, Recipient_Max, "NULL input address" );
+
+ String text = *address;
+ RecipientType rcptType = Recipient_None;
+ if ( text.length() > 3 )
+ {
+ // check for to:, cc: or bcc: prefix
+ if ( text[2u] == ':' )
+ {
+ if ( toupper(text[0u]) == 'T' && toupper(text[1u]) == 'O' )
+ rcptType = Recipient_To;
+ else if ( toupper(text[0u]) == 'C' && toupper(text[1u]) == 'C' )
+ rcptType = Recipient_Cc;
+ }
+ else if ( text[3u] == ':' && text(0, 3).Upper() == _T("BCC") )
+ {
+ rcptType = Recipient_Bcc;
+ }
+
+ if ( rcptType != Recipient_None )
+ {
+ // erase the prefix (length 2 or 3) with the colon
+ text.erase(0, rcptType == Recipient_Bcc ? 4 : 3);
+ }
+ }
+
+ if ( !AdbExpandSingleAddress(&text, subject, profile, win) )
+ return Recipient_Max;
+
+ *address = text;
+
+ return rcptType;
+}
+
+int
+AdbExpandAllRecipients(const String& text,
+ wxArrayString& addresses,
+ wxArrayInt& rcptTypes,
+ String *subject,
+ Profile *profile,
+ wxFrame *win)
+{
+ addresses.clear();
+ rcptTypes.clear();
+
+ int count = 0;
+ bool expandedSomething = false; // will be set to true if expand any address
+
+ // expand all addresses, one by one
+ const size_t len = text.length();
+ String address;
+ address.reserve(len);
+ bool quoted = false;
+ for ( size_t n = 0; n <= len; n++ )
+ {
+ switch ( const wxChar ch = n == len ? '\0' : text[n] )
+ {
+ case '"':
+ quoted = !quoted;
+ break;
+
+ case '\\':
+ // backslash escapes the next character (if there is one), so
+ // append it without special handling, even if it's a quote or
+ // address separator
+ if ( n < len - 1 )
+ address += text[++n];
+ else
+ wxLogWarning(_("Trailing backslash ignored."));
+ break;
+
+ case ' ':
+ // skip leading spaces unless they're quoted (note that we don't
+ // ignore trailing spaces because we want "Dan " to expand into
+ // "Dan Black" but not into "Danish guy")
+ if ( quoted || !address.empty() )
+ address += ch;
+ break;
+
+ case '\0':
+ if ( quoted )
+ {
+ wxLogWarning(_("Closing open quote implicitly."));
+ quoted = false;
+ }
+ // fall through
+
+ case ',':
+ case ';':
+ if ( !quoted )
+ {
+ // end of this address component, expand and remember it
+ RecipientType rcptType =
+ AdbExpandSingleRecipient(&address, subject, profile, win);
+ if ( rcptType != Recipient_Max )
+ {
+ expandedSomething = true;
+ }
+ else // expansion of this address failed
+ {
+ // still continue with the other ones but don't set
+ // expandedSomething so that our caller will know if we
+ // didn't do anything at all
+ rcptType = Recipient_None;
+ }
+
+ addresses.push_back(address);
+ rcptTypes.push_back(rcptType);
+ count++;
+ address.clear();
+ break;
+ }
+ //else: quoted address separators are not special, fall through
+
+ default:
+ // just accumulate in the current address
+ address += ch;
+ }
+ }
+
+ return expandedSomething ? count : -1;
+}
+
// ----------------------------------------------------------------------------
// AdbManager static functions and variables
// ----------------------------------------------------------------------------
Modified: trunk/M/src/classes/MApplication.cpp
===================================================================
--- trunk/M/src/classes/MApplication.cpp 2007-01-08 00:09:32 UTC (rev 7203)
+++ trunk/M/src/classes/MApplication.cpp 2007-01-08 21:23:41 UTC (rev 7204)
@@ -231,20 +231,17 @@
if ( composer )
{
+ composer->AddRecipients(cmdLineOpts.composer.to, Recipient_To);
composer->AddRecipients(cmdLineOpts.composer.bcc, Recipient_Bcc);
composer->AddRecipients(cmdLineOpts.composer.cc, Recipient_Cc);
composer->AddRecipients(cmdLineOpts.composer.newsgroups,
Recipient_Newsgroup);
- // the "to" parameter may be a mailto: URL, pass it through our expansion
- // function first
- String to = cmdLineOpts.composer.to;
- composer->ExpandRecipient(&to);
+ if ( !cmdLineOpts.composer.subject.empty() )
+ composer->SetSubject(cmdLineOpts.composer.subject);
+ //else: don't override the subject which could have been specified as
+ // part of "To:" recipient (common for mailto: URLs)
- composer->AddRecipients(to, Recipient_To);
-
- composer->SetSubject(cmdLineOpts.composer.subject);
-
composer->InsertText(cmdLineOpts.composer.body);
composer->ResetDirty();
Added: trunk/M/src/gui/AddressExpander.cpp
===================================================================
--- trunk/M/src/gui/AddressExpander.cpp (rev 0)
+++ trunk/M/src/gui/AddressExpander.cpp 2007-01-08 21:23:41 UTC (rev 7204)
@@ -0,0 +1,125 @@
+///////////////////////////////////////////////////////////////////////////////
+// Project: M - cross platform e-mail GUI client
+// File name: gui/AddressExpander.cpp
+// Purpose: AddressExpander implementation
+// Author: Vadim Zeitlin
+// Created: 2007-01-08
+// CVS-ID: $Id: wxComposeView.cpp 7203 2007-01-08 00:09:32Z vadz $
+// Copyright: (c) 1998-2007 Mahogany team
+// Licence: M license
+///////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+#include "Mpch.h"
+
+#ifndef USE_PCH
+# include "Mcommon.h"
+#endif
+
+#include "adb/AdbManager.h"
+
+#include "gui/AddressExpander.h"
+
+// ============================================================================
+// AddressExpander implementation
+// ============================================================================
+
+AddressExpander::AddressExpander(wxTextCtrl *text, Profile *profile)
+ : m_profile(profile)
+{
+ SafeIncRef(profile);
+
+ m_text = text;
+
+ // TODO: connect to TAB and Enter events to handle them automatically?
+}
+
+wxFrame *AddressExpander::GetParentFrame() const
+{
+ return (wxFrame *)wxGetTopLevelParent(m_text);
+}
+
+int
+AddressExpander::ExpandAll(wxArrayString& addresses,
+ wxArrayInt& rcptTypes,
+ String *subject) const
+{
+ return AdbExpandAllRecipients
+ (
+ m_text->GetValue(),
+ addresses,
+ rcptTypes,
+ subject,
+ m_profile,
+ GetParentFrame()
+ );
+}
+
+RecipientType AddressExpander::ExpandLast(String *subject)
+{
+ // find the last address
+ String text = m_text->GetValue();
+ const size_t len = text.length();
+ size_t start = 0;
+ bool quoted = false;
+ for ( size_t n = 0; n < len; n++ )
+ {
+ switch ( text[n] )
+ {
+ case '\\':
+ // skip the next character, even if it's a quote or separator
+ n++;
+ break;
+
+ case '"':
+ quoted = !quoted;
+ break;
+
+ case ',':
+ case ';':
+ if ( !quoted )
+ {
+ // keep the space if there is one following the separator
+ if ( n < len - 1 && text[n + 1] == ' ' )
+ n++;
+
+ start = n;
+ }
+ break;
+ }
+ }
+
+ // if we didn't find the final quote, skip over the initial one too
+ if ( quoted )
+ start++;
+
+ if ( start == len )
+ return Recipient_Max; // nothing to expand
+
+ // preserve the part before the address start
+ String textBefore;
+ start++;
+ textBefore.assign(text, 0, start);
+ text.erase(0, start);
+ text.Trim(false /* from left */);
+
+ // expand the address
+ RecipientType rcptType =
+ AdbExpandSingleRecipient(&text, subject, m_profile, GetParentFrame());
+
+ if ( rcptType != Recipient_Max )
+ {
+ m_text->SetValue(textBefore + text);
+ m_text->SetInsertionPointEnd();
+ }
+
+ return rcptType;
+}
+
Modified: trunk/M/src/gui/wxComposeView.cpp
===================================================================
--- trunk/M/src/gui/wxComposeView.cpp 2007-01-08 00:09:32 UTC (rev 7203)
+++ trunk/M/src/gui/wxComposeView.cpp 2007-01-08 21:23:41 UTC (rev 7204)
@@ -86,6 +86,7 @@
#include "HeadersDialogs.h"
+#include "gui/AddressExpander.h"
#include "gui/wxIdentityCombo.h"
#include "gui/wxOptionsDlg.h"
#include "gui/wxDialogLayout.h"
@@ -581,7 +582,8 @@
// different roles rather than because it is really needed.
// ----------------------------------------------------------------------------
-class wxAddressTextCtrl : public wxTextCtrlProcessingEnter
+class wxAddressTextCtrl : public wxTextCtrlProcessingEnter,
+ public AddressExpander
{
public:
// ctor
@@ -1217,16 +1219,34 @@
void wxRcptMainControl::OnAdd()
{
// expand before adding (make this optional?)
- RecipientType addrType = GetText()->DoExpand();
- if ( addrType == Recipient_None )
+ wxArrayString addresses;
+ wxArrayInt rcptTypes;
+ String subject;
+ const int count = GetText()->ExpandAll(addresses, rcptTypes, &subject);
+ if ( count == -1 )
{
- // cancelled or address is invalid
+ // cancelled by user
return;
}
- // add new recipient(s)
- m_composeView->AddRecipients(GetText()->GetValue(), addrType);
+ if ( !subject.empty() )
+ m_composeView->SetSubject(subject);
+ for ( unsigned n = 0; n < (unsigned)count; n++ )
+ {
+ // add new recipient(s)
+ RecipientType rcptType = (RecipientType)rcptTypes[n];
+ if ( rcptType == Recipient_None )
+ {
+ // use the default one
+ rcptType = GetType();
+ }
+
+ // don't [try to] expand the address again here
+ m_composeView->AddRecipients(addresses[n], rcptType,
+ !Composer::AddRcpt_Expand);
+ }
+
// clear the entry zone as recipient(s) were moved elsewhere
GetText()->SetValue(wxEmptyString);
}
@@ -1320,7 +1340,9 @@
wxAddressTextCtrl::wxAddressTextCtrl(wxWindow *parent,
wxRcptControl *rcptControl)
- : wxTextCtrlProcessingEnter(parent, wxTE_PROCESS_TAB)
+ : wxTextCtrlProcessingEnter(parent, wxTE_PROCESS_TAB),
+ AddressExpander(this,
+ rcptControl->GetComposer()->GetProfile())
{
m_rcptControl = rcptControl;
}
@@ -1377,15 +1399,11 @@
case Recipient_Cc:
case Recipient_Bcc:
{
- String text = GetValue();
+ String subject;
+ rcptType = ExpandLast(&subject);
- rcptType = GetComposer()->ExpandRecipient(&text);
-
- if ( rcptType != Recipient_None )
- {
- SetValue(text);
- SetInsertionPointEnd();
- }
+ if ( !subject.empty() )
+ m_rcptControl->GetComposer()->SetSubject(subject);
}
break;
@@ -2301,198 +2319,6 @@
// wxComposeView address headers stuff
// ----------------------------------------------------------------------------
-RecipientType
-wxComposeView::ExpandRecipient(String *textAddress)
-{
- // don't do anything for the newsgroups
- //
- // TODO-NEWS: expand using .newsrc?
- if ( m_mode == wxComposeView::Mode_News )
- {
- return Recipient_Newsgroup;
- }
-
- // try to expand the last component
- String& text = *textAddress;
-
- // trim spaces from left, but not (all) from right -- this allows "Dan " to
- // be expanded into "Dan Black" but not in "Danish Guy"
- text.Trim(FALSE);
- bool hasSpaceAtEnd = !text.empty() && text.Last() == ' ';
- text.Trim(TRUE);
- if ( !text.empty() && hasSpaceAtEnd )
- text += ' ';
-
- // check for the lone '"' simplifies the code for finding the starting
- // position below: it should be done here, otherwise the following loop
- // will crash!
- if ( text.empty() || text == '"' )
- {
- // don't do anything
- wxLogStatus(GetFrame(),
- _("Nothing to expand - please enter something."));
-
- return Recipient_None;
- }
-
- // find the starting position of the last address in the address list
- size_t nLastAddr;
- bool quoted = text.Last() == '"';
- if ( quoted )
- {
- // just find the matching quote (not escaped)
- const wxChar *pStart = text.c_str();
- const wxChar *p;
- for ( p = pStart + text.length() - 2; p >= pStart; p-- )
- {
- if ( *p == '"' )
- {
- // check that it's not escaped
- if ( (p == pStart) || (*(p - 1) != '\\') )
- {
- // ok, found it!
- break;
- }
- }
- }
-
- nLastAddr = p - pStart;
- }
- else // unquoted
- {
- // search back until the last address separator
- for ( nLastAddr = text.length() - 1; nLastAddr > 0; nLastAddr-- )
- {
- wxChar c = text[nLastAddr];
- if ( (c == ',') || (c == ';') )
- break;
- }
-
- if ( nLastAddr > 0 )
- {
- // move beyond the ',' or ';' which stopped the scan
- nLastAddr++;
- }
-
- // the address will probably never start with spaces but if it does, it
- // will be enough to just take it into quotes
- while ( wxIsspace(text[nLastAddr]) )
- {
- nLastAddr++;
- }
- }
-
- // so now we've got the text we'll be trying to expand
- String textOrig = text.c_str() + nLastAddr;
-
- // do we have an explicit address type specifier
- RecipientType addrType = Recipient_Max;
- if ( textOrig.length() > 3 )
- {
- // check for to:, cc: or bcc: prefix
- if ( textOrig[2u] == ':' )
- {
- if ( toupper(textOrig[0u]) == 'T' && toupper(textOrig[1u]) == 'O' )
- addrType = Recipient_To;
- else if ( toupper(textOrig[0u]) == 'C' && toupper(textOrig[1u]) == 'C' )
- addrType = Recipient_Cc;
- }
- else if ( textOrig[3u] == ':' && textOrig(0, 3).Upper() == _T("BCC") )
- {
- addrType = Recipient_Bcc;
- }
-
- if ( addrType != Recipient_Max )
- {
- // erase the colon as well
- textOrig.erase(0, addrType == Recipient_Bcc ? 4 : 3);
- }
- }
-
- // remove "mailto:" prefix if it's there - this is convenient when you paste
- // in an URL from the web browser
- //
- // TODO: add support for the mailto URL parameters, i.e. should support
- // things like "mailto:[email protected]?subject=Please%20help"
- String newText;
- if ( !textOrig.StartsWith(_T("mailto:"), &newText) )
- {
- // if the text already has a '@' inside it and looks like a full email
- // address assume that it doesn't need to be expanded (this saves a lot
- // of time as expanding a non existing address looks through all address
- // books...)
- size_t pos = textOrig.find('@');
- if ( pos != String::npos && pos > 0 && pos < textOrig.length() )
- {
- // also check that the host part of the address is expanded - it
- // should contain at least one dot normally
- if ( wxStrchr(textOrig.c_str() + pos + 1, '.') )
- {
- // looks like a valid address - nothing to do
- newText = textOrig;
- }
- }
-
- if ( newText.empty() )
- {
- wxArrayString expansions;
-
- if ( !AdbExpand(expansions,
- textOrig,
- READ_CONFIG(GetProfile(), MP_ADB_SUBSTRINGEXPANSION)
- ? AdbLookup_Substring
- : AdbLookup_StartsWith,
- this) )
- {
- // cancelled, don't do anything
- return Recipient_None;
- }
-
- // construct the replacement string(s)
- size_t nExpCount = expansions.GetCount();
- for ( size_t nExp = 0; nExp < nExpCount; nExp++ )
- {
- if ( nExp > 0 )
- newText += CANONIC_ADDRESS_SEPARATOR;
-
- newText += expansions[nExp];
- }
- }
- }
-
- // find the end of the previous address
- size_t nPrevAddrEnd;
- if ( nLastAddr > 0 )
- {
- // undo "++" above
- nLastAddr--;
- }
-
- for ( nPrevAddrEnd = nLastAddr; nPrevAddrEnd > 0; nPrevAddrEnd-- )
- {
- wxChar c = text[nPrevAddrEnd];
- if ( !wxIsspace(c) && (c != ',') && (c != ';') )
- {
- // this character is a part of previous string, leave it there
- nPrevAddrEnd++;
-
- break;
- }
- }
-
- // keep the text up to the address we expanded/processed
- wxString oldText(text, nPrevAddrEnd); // first nPrevAddrEnd chars
- if ( !oldText.empty() )
- {
- // there was something before, add separator
- oldText += CANONIC_ADDRESS_SEPARATOR;
- }
-
- text = oldText + newText;
-
- return addrType;
-}
-
void
wxComposeView::AddRecipientControls(const String& value, RecipientType rt)
{
@@ -2569,12 +2395,16 @@
}
void
-wxComposeView::AddRecipients(const String& address, RecipientType addrType, bool doLayout)
+wxComposeView::AddRecipients(const String& addressOrig,
+ RecipientType addrType,
+ int flags)
{
// if there is no address, nothing to do
- if ( address.empty() )
+ if ( addressOrig.empty() )
return;
+ String address = addressOrig;
+
// invalid rcpt type means to reuse the last one
if ( addrType == Recipient_Max )
{
@@ -2605,6 +2435,15 @@
case Recipient_To:
case Recipient_Cc:
case Recipient_Bcc:
+ if ( flags & AddRcpt_Expand )
+ {
+ String subject;
+ AdbExpandSingleAddress(&address, &subject, GetProfile(), this);
+
+ if ( !subject.empty() )
+ SetSubject(subject);
+ }
+
// an email address
{
// split the string in addreses and add all of them
Modified: trunk/M/src/mail/MailFolder.cpp
===================================================================
--- trunk/M/src/mail/MailFolder.cpp 2007-01-08 00:09:32 UTC (rev 7203)
+++ trunk/M/src/mail/MailFolder.cpp 2007-01-08 21:23:41 UTC (rev 7204)
@@ -680,7 +680,7 @@
while ( n-- )
{
- cv->AddRecipients(rcptAddresses[n], (RecipientType)rcptTypes[n], (n > 0 ? false : true));
+ cv->AddRecipients(rcptAddresses[n], (RecipientType)rcptTypes[n]);
}
return;
@@ -869,7 +869,7 @@
while ( n-- )
{
- cv->AddRecipients(rcptAddresses[n], (RecipientType)rcptTypes[n], !n);
+ cv->AddRecipients(rcptAddresses[n], (RecipientType)rcptTypes[n]);
}
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.