desktop/source/app/app.cxx      |   24 +++++++-----
 include/sfx2/app.hxx            |    1 
 include/vcl/svapp.hxx           |   40 ++++++++++++++++----
 sfx2/source/appl/appdde.cxx     |   78 ++++++++++++++++++++++++++--------------
 vcl/aqua/source/app/salinst.cxx |    3 -
 vcl/aqua/source/app/vclnsapp.mm |   30 +++++++--------
 6 files changed, 113 insertions(+), 63 deletions(-)

New commits:
commit d5266a9e3f367752e2b2099e542518078271edcc
Author: Stephan Bergmann <sberg...@redhat.com>
Date:   Sat Jul 27 19:47:01 2013 +0200

    fdo#54264: Fix multi-argument ApplicationEvent::TYPE_OPEN/PRINT
    
    ...that had been broken when 5c22a03320f20ae9ac2c3c16025e7c5e3a7915d5> 
"Cleaned
    up CommandLineArgs" changed the representation of those multi-arguments 
from a
    single string with \n delimiters to vector<string> in
    desktop/soruce/app/cmdlineargs.hxx, but missed updating other producers of
    such ApplicationEvents.
    
    (cherry picked from commit 787940e0ac285aa1101ca8964d252faaab3ea8c1, plus
    04f4d4bfb708ef477618fa47d5f17779f4e4cf3c "Add TODO comment expressing doubts
    about existing code")
    Conflicts:
        sfx2/source/appl/appdde.cxx
    
    Change-Id: I527d620c60a87f3a01d970927c521163fb6df192
    Reviewed-on: https://gerrit.libreoffice.org/5192
    Reviewed-by: Fridrich Strba <fridr...@documentfoundation.org>
    Tested-by: Fridrich Strba <fridr...@documentfoundation.org>

diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx
index 195776f..5bda373 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -2645,7 +2645,7 @@ void Desktop::HandleAppEvent( const ApplicationEvent& 
rAppEvent )
     case ApplicationEvent::TYPE_ACCEPT:
         // every time an accept parameter is used we create an acceptor
         // with the corresponding accept-string
-        createAcceptor(rAppEvent.GetData());
+        createAcceptor(rAppEvent.GetStringData());
         break;
     case ApplicationEvent::TYPE_APPEAR:
         if ( !GetCommandLineArgs().IsInvisible() )
@@ -2694,7 +2694,7 @@ void Desktop::HandleAppEvent( const ApplicationEvent& 
rAppEvent )
         }
         break;
     case ApplicationEvent::TYPE_HELP:
-        displayCmdlineHelp(rAppEvent.GetData());
+        displayCmdlineHelp(rAppEvent.GetStringData());
         break;
     case ApplicationEvent::TYPE_VERSION:
         displayVersion();
@@ -2706,7 +2706,9 @@ void Desktop::HandleAppEvent( const ApplicationEvent& 
rAppEvent )
             {
                 ProcessDocumentsRequest* pDocsRequest = new 
ProcessDocumentsRequest(
                     rCmdLine.getCwdUrl());
-                pDocsRequest->aOpenList.push_back(rAppEvent.GetData());
+                std::vector<OUString> const & data(rAppEvent.GetStringsData());
+                pDocsRequest->aOpenList.insert(
+                    pDocsRequest->aOpenList.end(), data.begin(), data.end());
                 pDocsRequest->pcProcessed = NULL;
 
                 OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest );
@@ -2716,7 +2718,7 @@ void Desktop::HandleAppEvent( const ApplicationEvent& 
rAppEvent )
         break;
     case ApplicationEvent::TYPE_OPENHELPURL:
         // start help for a specific URL
-        Application::GetHelp()->Start(rAppEvent.GetData(), NULL);
+        Application::GetHelp()->Start(rAppEvent.GetStringData(), NULL);
         break;
     case ApplicationEvent::TYPE_PRINT:
         {
@@ -2725,7 +2727,9 @@ void Desktop::HandleAppEvent( const ApplicationEvent& 
rAppEvent )
             {
                 ProcessDocumentsRequest* pDocsRequest = new 
ProcessDocumentsRequest(
                     rCmdLine.getCwdUrl());
-                pDocsRequest->aPrintList.push_back(rAppEvent.GetData());
+                std::vector<OUString> const & data(rAppEvent.GetStringsData());
+                pDocsRequest->aPrintList.insert(
+                    pDocsRequest->aPrintList.end(), data.begin(), data.end());
                 pDocsRequest->pcProcessed = NULL;
 
                 OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest );
@@ -2771,10 +2775,10 @@ void Desktop::HandleAppEvent( const ApplicationEvent& 
rAppEvent )
 
             Reference< css::util::XURLTransformer > xParser = 
css::util::URLTransformer::create(xContext);
             css::util::URL aCommand;
-            if( rAppEvent.GetData() == OUString("PREFERENCES") )
-                aCommand.Complete = OUString( ".uno:OptionsTreeDialog"  );
-            else if( rAppEvent.GetData() == OUString("ABOUT") )
-                aCommand.Complete = OUString( ".uno:About"  );
+            if( rAppEvent.GetStringData() == "PREFERENCES" )
+                aCommand.Complete = ".uno:OptionsTreeDialog";
+            else if( rAppEvent.GetStringData() == "ABOUT" )
+                aCommand.Complete = ".uno:About";
             if( !aCommand.Complete.isEmpty() )
             {
                 xParser->parseStrict(aCommand);
@@ -2789,7 +2793,7 @@ void Desktop::HandleAppEvent( const ApplicationEvent& 
rAppEvent )
         break;
     case ApplicationEvent::TYPE_UNACCEPT:
         // try to remove corresponding acceptor
-        destroyAcceptor(rAppEvent.GetData());
+        destroyAcceptor(rAppEvent.GetStringData());
         break;
     default:
         OSL_FAIL("this cannot happen");
diff --git a/include/sfx2/app.hxx b/include/sfx2/app.hxx
index 858140d..9ab77df 100644
--- a/include/sfx2/app.hxx
+++ b/include/sfx2/app.hxx
@@ -40,7 +40,6 @@
 #include <vector>
 
 class Timer;
-class ApplicationEvent;
 class WorkWindow;
 class ISfxTemplateCommon;
 class BasicManager;
diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx
index 101de7a..ff5f79e 100644
--- a/include/vcl/svapp.hxx
+++ b/include/vcl/svapp.hxx
@@ -24,7 +24,9 @@
 
 #include <sal/config.h>
 
+#include <cassert>
 #include <stdexcept>
+#include <vector>
 
 #include <comphelper/solarmutex.hxx>
 #include <osl/thread.hxx>
@@ -100,20 +102,42 @@ public:
         TYPE_SHOWDIALOG, TYPE_UNACCEPT
     };
 
-    ApplicationEvent() {}
+    explicit ApplicationEvent(Type type): aEvent(type) {
+        assert(
+            type == TYPE_APPEAR || type == TYPE_VERSION
+            || type == TYPE_PRIVATE_DOSHUTDOWN || type == TYPE_QUICKSTART);
+    }
+
+    ApplicationEvent(Type type, OUString const & data): aEvent(type) {
+        assert(
+            type == TYPE_ACCEPT || type == TYPE_HELP || type == 
TYPE_OPENHELPURL
+            || type == TYPE_SHOWDIALOG || type == TYPE_UNACCEPT);
+        aData.push_back(data);
+    }
 
-    explicit ApplicationEvent(
-        Type rEvent, const OUString& rData = OUString()):
-        aEvent(rEvent),
-        aData(rData)
-    {}
+    ApplicationEvent(Type type, std::vector<OUString> const & data):
+        aEvent(type), aData(data)
+    { assert(type == TYPE_OPEN || type == TYPE_PRINT); }
 
     Type GetEvent() const { return aEvent; }
-    const OUString& GetData() const { return aData; }
+
+    OUString GetStringData() const {
+        assert(
+            aEvent == TYPE_ACCEPT || aEvent == TYPE_HELP
+            || aEvent == TYPE_OPENHELPURL || aEvent == TYPE_SHOWDIALOG
+            || aEvent == TYPE_UNACCEPT);
+        assert(aData.size() == 1);
+        return aData[0];
+    }
+
+    std::vector<OUString> const & GetStringsData() const {
+        assert(aEvent == TYPE_OPEN || aEvent == TYPE_PRINT);
+        return aData;
+    }
 
 private:
     Type aEvent;
-    OUString aData;
+    std::vector<OUString> aData;
 };
 
 
diff --git a/sfx2/source/appl/appdde.cxx b/sfx2/source/appl/appdde.cxx
index 371f523..7fd2346 100644
--- a/sfx2/source/appl/appdde.cxx
+++ b/sfx2/source/appl/appdde.cxx
@@ -230,16 +230,19 @@ public:
 
 class SfxDdeDocTopics_Impl : public std::vector<SfxDdeDocTopic_Impl*> {};
 
+#if defined( WNT )
+
+namespace {
+
 //========================================================================
 
-sal_Bool SfxAppEvent_Impl( ApplicationEvent &rAppEvent,
-                           const OUString& rCmd, const OUString& rEvent,
+sal_Bool SfxAppEvent_Impl( const OUString& rCmd, const OUString& rEvent,
                            ApplicationEvent::Type eType )
 
 /*  [Description]
 
     Checks if 'rCmd' of the event 'rEvent' is (without '(') and then assemble
-    this data into a <ApplicationEvent>, which can be excecuted through
+    this data into a <ApplicationEvent>, which is then excecuted through
     <Application::AppEvent()>. If 'rCmd' is the given event 'rEvent', then
     TRUE is returned, otherwise FALSE.
 
@@ -250,37 +253,59 @@ sal_Bool SfxAppEvent_Impl( ApplicationEvent &rAppEvent,
 */
 
 {
-    OUString sEvent(rEvent);
-    sEvent += "(";
+    OUString sEvent(rEvent + "(");
     if (rCmd.startsWithIgnoreAsciiCase(sEvent))
     {
-        OUStringBuffer aData( rCmd );
-        aData.remove(0, sEvent.getLength());
-        if ( aData.getLength() > 2 )
+        sal_Int32 start = sEvent.getLength();
+        if ( rCmd.getLength() - start >= 2 )
         {
             // Transform into the ApplicationEvent Format
-            aData.remove( aData.getLength() - 1, 1 );
-            for ( sal_Int32 n = 0; n < aData.getLength(); )
+            //TODO: I /assume/ that rCmd should match the syntax of
+            // <http://msdn.microsoft.com/en-us/library/ms648995.aspx>
+            // "WM_DDE_EXECUTE message" but does not (handle commands enclosed
+            // in [...]; handle commas separating multiple arguments; handle
+            // double "", ((, )), [[, ]] in quoted arguments); see also the 
mail
+            // thread starting at <http://lists.freedesktop.org/archives/
+            // libreoffice/2013-July/054779.html> "DDE on Windows."
+            std::vector<OUString> aData;
+            for ( sal_Int32 n = start; n < rCmd.getLength() - 1; )
             {
-                switch ( aData[n] )
+                // Resiliently read arguments either starting with " and
+                // spanning to the next " (if any; TODO: do we need to undo any
+                // escaping within the string?) or with neither " nor SPC and
+                // spanning to the next SPC (if any; TODO: is this from not
+                // wrapped in "..." relevant? it would have been parsed by the
+                // original code even if that was only by accident, so I left 
it
+                // in), with runs of SPCs treated like single ones:
+                switch ( rCmd[n] )
                 {
                 case '"':
-                    aData.remove( n, 1 );
-                    while ( n < aData.getLength() && aData[n] != '"' )
-                        ++n;
-                    if ( n < aData.getLength() )
-                        aData.remove( n, 1 );
-                    break;
+                    {
+                        sal_Int32 i = rCmd.indexOf('"', ++n);
+                        if (i < 0 || i > rCmd.getLength() - 1) {
+                            i = rCmd.getLength() - 1;
+                        }
+                        aData.push_back(rCmd.copy(n, i - n));
+                        n = i + 1;
+                        break;
+                    }
                 case ' ':
-                    aData[n++] = '\n';
-                    break;
-                default:
                     ++n;
                     break;
+                default:
+                    {
+                        sal_Int32 i = rCmd.indexOf(' ', n);
+                        if (i < 0 || i > rCmd.getLength() - 1) {
+                            i = rCmd.getLength() - 1;
+                        }
+                        aData.push_back(rCmd.copy(n, i - n));
+                        n = i + 1;
+                        break;
+                    }
                 }
             }
 
-            rAppEvent = ApplicationEvent(eType, aData.makeStringAndClear());
+            GetpApp()->AppEvent( ApplicationEvent(eType, aData) );
             return sal_True;
         }
     }
@@ -288,7 +313,8 @@ sal_Bool SfxAppEvent_Impl( ApplicationEvent &rAppEvent,
     return sal_False;
 }
 
-#if defined( WNT )
+}
+
 long SfxApplication::DdeExecute
 (
     const String&   rCmd  // Expressed in our BASIC-Syntax
@@ -306,11 +332,8 @@ long SfxApplication::DdeExecute
 
 {
     // Print or Open-Event?
-    ApplicationEvent aAppEvent;
-    if ( SfxAppEvent_Impl( aAppEvent, rCmd, "Print", 
ApplicationEvent::TYPE_PRINT ) ||
-         SfxAppEvent_Impl( aAppEvent, rCmd, "Open", 
ApplicationEvent::TYPE_OPEN ) )
-        GetpApp()->AppEvent( aAppEvent );
-    else
+    if ( !( SfxAppEvent_Impl( rCmd, "Print", ApplicationEvent::TYPE_PRINT ) ||
+            SfxAppEvent_Impl( rCmd, "Open", ApplicationEvent::TYPE_OPEN ) ) )
     {
         // all others are BASIC
         StarBASIC* pBasic = GetBasic();
@@ -324,6 +347,7 @@ long SfxApplication::DdeExecute
     }
     return 1;
 }
+
 #endif
 
 long SfxObjectShell::DdeExecute
diff --git a/vcl/aqua/source/app/salinst.cxx b/vcl/aqua/source/app/salinst.cxx
index 167dca5..5f033f2 100644
--- a/vcl/aqua/source/app/salinst.cxx
+++ b/vcl/aqua/source/app/salinst.cxx
@@ -110,8 +110,7 @@ void AquaSalInstance::delayedSettingsChanged( bool 
bInvalidate )
 
 
 // the AppEventList must be available before any SalData/SalInst/etc. objects 
are ready
-typedef std::list<const ApplicationEvent*> AppEventList;
-AppEventList AquaSalInstance::aAppEventList;
+AquaSalInstance::AppEventList AquaSalInstance::aAppEventList;
 
 NSMenu* AquaSalInstance::GetDynamicDockMenu()
 {
diff --git a/vcl/aqua/source/app/vclnsapp.mm b/vcl/aqua/source/app/vclnsapp.mm
index 5a8ed35..9b68b55 100644
--- a/vcl/aqua/source/app/vclnsapp.mm
+++ b/vcl/aqua/source/app/vclnsapp.mm
@@ -17,7 +17,9 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
-#include "rtl/ustrbuf.hxx"
+#include "sal/config.h"
+
+#include <vector>
 
 #include "vcl/window.hxx"
 #include "vcl/svapp.hxx"
@@ -300,8 +302,9 @@
 -(BOOL)application: (NSApplication*)app openFile: (NSString*)pFile
 {
     (void)app;
-    const rtl::OUString aFile( GetOUString( pFile ) );
-    if( ! AquaSalInstance::isOnCommandLine( aFile ) )
+    std::vector<OUString> aFile;
+    aFile.push_back( GetOUString( pFile ) );
+    if( ! AquaSalInstance::isOnCommandLine( aFile[0] ) )
     {
         const ApplicationEvent* pAppEvent = new 
ApplicationEvent(ApplicationEvent::TYPE_OPEN, aFile);
         AquaSalInstance::aAppEventList.push_back( pAppEvent );
@@ -312,7 +315,7 @@
 -(void)application: (NSApplication*) app openFiles: (NSArray*)files
 {
     (void)app;
-    rtl::OUStringBuffer aFileList( 256 );
+    std::vector<OUString> aFileList;
 
     NSEnumerator* it = [files objectEnumerator];
     NSString* pFile = nil;
@@ -322,18 +325,16 @@
         const rtl::OUString aFile( GetOUString( pFile ) );
         if( ! AquaSalInstance::isOnCommandLine( aFile ) )
         {
-            if( aFileList.getLength() > 0 )
-                aFileList.append('\n');
-            aFileList.append( aFile );
+            aFileList.push_back( aFile );
         }
     }
 
-    if( aFileList.getLength() )
+    if( !aFileList.empty() )
     {
         // we have no back channel here, we have to assume success, in which 
case
         // replyToOpenOrPrint does not need to be called according to 
documentation
         // [app replyToOpenOrPrint: NSApplicationDelegateReplySuccess];
-        const ApplicationEvent* pAppEvent = new 
ApplicationEvent(ApplicationEvent::TYPE_OPEN, aFileList.makeStringAndClear());
+        const ApplicationEvent* pAppEvent = new 
ApplicationEvent(ApplicationEvent::TYPE_OPEN, aFileList);
         AquaSalInstance::aAppEventList.push_back( pAppEvent );
     }
 }
@@ -341,7 +342,8 @@
 -(BOOL)application: (NSApplication*)app printFile: (NSString*)pFile
 {
     (void)app;
-    const rtl::OUString aFile( GetOUString( pFile ) );
+    std::vector<OUString> aFile;
+    aFile.push_back( GetOUString( pFile ) );
        const ApplicationEvent* pAppEvent = new 
ApplicationEvent(ApplicationEvent::TYPE_PRINT, aFile);
        AquaSalInstance::aAppEventList.push_back( pAppEvent );
     return YES;
@@ -352,18 +354,16 @@
     (void)printSettings;
     (void)bShowPrintPanels;
     // currently ignores print settings an bShowPrintPanels
-    rtl::OUStringBuffer aFileList( 256 );
+    std::vector<OUString> aFileList;
 
     NSEnumerator* it = [files objectEnumerator];
     NSString* pFile = nil;
 
     while( (pFile = [it nextObject]) != nil )
     {
-        if( aFileList.getLength() > 0 )
-            aFileList.append('\n');
-        aFileList.append( GetOUString( pFile ) );
+        aFileList.push_back( GetOUString( pFile ) );
     }
-       const ApplicationEvent* pAppEvent = new 
ApplicationEvent(ApplicationEvent::TYPE_PRINT, aFileList.makeStringAndClear());
+       const ApplicationEvent* pAppEvent = new 
ApplicationEvent(ApplicationEvent::TYPE_PRINT, aFileList);
        AquaSalInstance::aAppEventList.push_back( pAppEvent );
     // we have no back channel here, we have to assume success
     // correct handling would be NSPrintingReplyLater and then send [app 
replyToOpenOrPrint]
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to