This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
fix dist/Time-HiRes/t/*.t that assumed '.' in @INC
[perl5.git] / symbian / PerlApp.cpp
index 8be786b..ffca7af 100644 (file)
@@ -1,35 +1,12 @@
 /* Copyright (c) 2004-2005 Nokia. All rights reserved. */
 
 /* The PerlApp application is licensed under the same terms as Perl itself.
- * Note that this PerlApp is for Symbian/Series 60 smartphones and has nothing
- * whatsoever to do with the ActiveState PerlApp. */
-
-/* This source code can be compiled into "PerlApp" which is the simple
- * launchpad application/demonstrator, or into "PerlMin", which is the
- * minimal Perl-on-Series-60 application.  Define the cpp symbols
- * PerlMin (a boolean), PerlMinUid (the Symbian application uid in
- * the 0x... format), and PerlMinName (a C wide string, with the L prefix)
- * to compile as "PerlMin". */
+ *
+ * Note that this PerlApp is for Symbian/Series 60/80/UIQ smartphones
+ * and it has nothing whatsoever to do with the ActiveState PerlApp. */
 
 #include "PerlApp.h"
 
-#ifdef PerlMinSample
-# define PerlMin
-# define PerlMinUid 0x0beefadd
-# define PerlMinName L"PerlMin"
-#endif
-
-#ifdef PerlMin
-# ifndef PerlMinUid
-#   error PerlMin defined but PerlMinUid undefined
-# endif
-# ifndef PerlMinName
-#  error PerlMin defined but PerlMinName undefined
-# endif
-#endif
-
-#include <avkon.hrh>
-#include <aknnotewrappers.h> 
 #include <apparc.h>
 #include <e32base.h>
 #include <e32cons.h>
 #include <utf.h>
 #include <f32file.h>
 
-#include <AknCommonDialogs.h>
-
-#ifndef __SERIES60_1X__
-#include <CAknFileSelectionDialog.h>
-#endif
-
 #include <coemain.h>
 
-#ifndef PerlMin
+#ifndef PerlAppMinimal
 
 #include "PerlApp.hrh"
-#include "PerlApp.rsg"
 
-#endif // #ifndef PerlMin
+#endif //#ifndef PerlAppMinimal
+
+#define PERL_GLOBAL_STRUCT
+#define PERL_GLOBAL_STRUCT_PRIVATE
 
 #include "EXTERN.h"
 #include "perl.h"
+#include "XSUB.h"
+
 #include "PerlBase.h"
+#include "PerlUtil.h"
+
+#define symbian_get_vars() Dll::Tls() // Not visible from perlXYZ.lib?
 
 const TUid KPerlAppUid = {
-#ifdef PerlMinUid
-  PerlMinUid
+#ifdef PerlAppMinimalUid
+  PerlAppMinimalUid
 #else
   0x102015F6
 #endif
@@ -68,20 +46,14 @@ const TUid KPerlAppUid = {
 
 _LIT(KDefaultScript, "default.pl");
 
-// This is like the Symbian _LIT() but without the embedded L prefix,
-// which enables using #defined constants (which need to carry their
-// own L prefix).
-#ifndef _LIT_NO_L
-# define _LIT_NO_L(n, s) static const TLitC<sizeof(s)/2> n={sizeof(s)/2-1,s}
-#endif // #ifndef _LIT_NO_L
-
-#ifdef PerlMinName
-_LIT_NO_L(KAppName, PerlMinName);
+#ifdef PerlAppMinimalName
+_LIT_NO_L(KAppName, PerlAppMinimalName);
 #else
 _LIT(KAppName, "PerlApp");
 #endif
 
-#ifndef PerlMin
+#ifndef PerlAppMinimal
+
 _LIT_NO_L(KFlavor, PERL_SYMBIANSDK_FLAVOR);
 _LIT(KAboutFormat,
      "Perl %d.%d.%d, Symbian port %d.%d.%d, built for %S SDK %d.%d");
@@ -91,23 +63,21 @@ _LIT(KInboxPrefix, "\\System\\Mail\\");
 _LIT(KScriptPrefix, "\\Perl\\");
 
 _LIT8(KModulePrefix, SITELIB); // SITELIB from Perl config.h
-#endif // #ifndef PerlMin
 
 typedef TBuf<256>  TMessageBuffer;
 typedef TBuf8<256> TPeekBuffer;
 typedef TBuf8<256> TFileName8;
 
-// Usage: DEBUG_PRINTF((_L("%S"), &aStr))
-#if 1
-#define DEBUG_PRINTF(s) {TMessageBuffer message; message.Format s; YesNoDialogL(message);}
-#endif
+#endif // #ifndef PerlAppMinimal
+
+static void DoRunScriptL(TFileName aScriptName);
 
 TUid CPerlAppApplication::AppDllUid() const
 {
     return KPerlAppUid;
 }
 
-enum TPerlAppPanic 
+enum TPerlAppPanic
 {
     EPerlAppCommandUnknown = 1
 };
@@ -117,83 +87,7 @@ void Panic(TPerlAppPanic aReason)
     User::Panic(KAppName, aReason);
 }
 
-void CPerlAppUi::ConstructL()
-{
-    BaseConstructL();
-    iAppView = CPerlAppView::NewL(ClientRect());
-    AddToStackL(iAppView);
-    iFs = NULL;
-    CEikonEnv::Static()->DisableExitChecks(ETrue); // Symbian FAQ-0577.
-}
-
-CPerlAppUi::~CPerlAppUi()
-{
-    if (iAppView) {
-        iEikonEnv->RemoveFromStack(iAppView);
-        delete iAppView;
-        iAppView = NULL;
-    }
-    if (iFs) {
-        delete iFs;
-        iFs = NULL;
-    }
-    if (iDoorObserver) // Otherwise the embedding application waits forever.
-        iDoorObserver->NotifyExit(MApaEmbeddedDocObserver::EEmpty);
-}
-
-static void DoRunScriptL(TFileName aScriptName);
-
-#ifndef PerlMin
-
-static TBool DlgOk(CAknNoteDialog* dlg)
-{
-    return dlg && dlg->RunDlgLD() == EAknSoftkeyOk;
-}
-
-static TBool OkCancelDialogL(TDesC& aMessage)
-{
-    CAknNoteDialog* dlg =
-        new (ELeave) CAknNoteDialog(CAknNoteDialog::EConfirmationTone);
-    dlg->PrepareLC(R_OK_CANCEL_DIALOG);
-    dlg->SetTextL(aMessage);
-    return DlgOk(dlg);
-}
-
-static TBool YesNoDialogL(TDesC& aMessage)
-{
-    CAknNoteDialog* dlg =
-        new (ELeave) CAknNoteDialog(CAknNoteDialog::EConfirmationTone);
-    dlg->PrepareLC(R_YES_NO_DIALOG);
-    dlg->SetTextL(aMessage);
-    return DlgOk(dlg);
-}
-
-static TInt InformationNoteL(TDesC& aMessage)
-{
-    CAknInformationNote* note = new (ELeave) CAknInformationNote;
-    return note->ExecuteLD(aMessage);
-}
-
-static TInt ConfirmationNoteL(TDesC& aMessage)
-{
-    CAknConfirmationNote* note = new (ELeave) CAknConfirmationNote;
-    return note->ExecuteLD(aMessage);
-}
-
-static TInt WarningNoteL(TDesC& aMessage)
-{
-    CAknWarningNote* note = new (ELeave) CAknWarningNote;
-    return note->ExecuteLD(aMessage);
-}
-
-static TInt TextQueryDialogL(const TDesC& aPrompt, TDes& aData, const TInt aMaxLength)
-{
-    CAknTextQueryDialog* dlg =
-        new (ELeave) CAknTextQueryDialog(aData);
-    dlg->SetPromptL(aPrompt);
-    dlg->SetMaxLength(aMaxLength);
-    return dlg->ExecuteLD(R_TEXT_QUERY_DIALOG);
-}
+#ifndef PerlAppMinimal
 
 // The isXXX() come from the Perl headers.
 #define FILENAME_IS_ABSOLUTE(n) \
@@ -221,12 +115,12 @@ static TBool IsInInbox(TFileName aFileName)
 
 static TBool IsPerlModule(TParsePtrC aParsed)
 {
-    return aParsed.Ext().CompareF(_L(".pm")) == 0; 
+    return aParsed.Ext().CompareF(_L(".pm")) == 0;
 }
 
 static TBool IsPerlScript(TParsePtrC aParsed)
 {
-    return aParsed.Ext().CompareF(_L(".pl")) == 0; 
+    return aParsed.Ext().CompareF(_L(".pl")) == 0;
 }
 
 static void CopyFromInboxL(RFs aFs, const TFileName& aSrc, const TFileName& aDst)
@@ -235,12 +129,12 @@ static void CopyFromInboxL(RFs aFs, const TFileName& aSrc, const TFileName& aDst
     TMessageBuffer message;
 
     message.Format(_L("%S is untrusted. Install only if you trust provider."), &aDst);
-    if (OkCancelDialogL(message)) {
+    if (CPerlUi::OkCancelDialogL(message)) {
         message.Format(_L("Install as %S?"), &aDst);
-        if (OkCancelDialogL(message)) {
+        if (CPerlUi::OkCancelDialogL(message)) {
             if (BaflUtils::FileExists(aFs, aDst)) {
                 message.Format(_L("Replace old %S?"), &aDst);
-                if (!OkCancelDialogL(message))
+                if (!CPerlUi::OkCancelDialogL(message))
                     proceed = EFalse;
             }
             if (proceed) {
@@ -248,11 +142,11 @@ static void CopyFromInboxL(RFs aFs, const TFileName& aSrc, const TFileName& aDst
                 TInt err = BaflUtils::CopyFile(aFs, aSrc, aDst);
                 if (err == KErrNone) {
                     message.Format(_L("Installed %S"), &aDst);
-                    ConfirmationNoteL(message);
+                    CPerlUi::InformationNoteL(message);
                 }
                 else {
                     message.Format(_L("Failure %d installing %S"), err, &aDst);
-                    WarningNoteL(message);
+                    CPerlUi::WarningNoteL(message);
                 }
             }
         }
@@ -288,7 +182,7 @@ static TBool FindPerlPackageName(TPeekBuffer aPeekBuffer, TInt aOff, TFileName&
                         isALPHA(aPeekBuffer[j])) {
                         while (j < n &&
                                isALNUM(aPeekBuffer[j]) &&
-                               i < m) 
+                               i < m)
                             aFn[i++] = aPeekBuffer[j++];
                     }
                 }
@@ -344,7 +238,7 @@ static TBool InstallStuffL(const TFileName &aSrc, TParse aDrive, TParse aFile, T
 {
     TFileName aDst;
     TPtrC drive  = aDrive.Drive();
-    TPtrC namext = aFile.NameAndExt(); 
+    TPtrC namext = aFile.NameAndExt();
 
     aDst.Format(_L("%S%S%S"), &drive, &KScriptPrefix, &namext);
     if (!IsPerlScript(aDst) && !LooksLikePerlL(aPeekBuffer)) {
@@ -372,18 +266,17 @@ static TBool RunStuffL(const TFileName& aScriptName, TPeekBuffer aPeekBuffer)
 
         if (isModule)
             message.Format(_L("Really run module %S?"), &aScriptName);
-        else 
+        else
             message.Format(_L("Run %S?"), &aScriptName);
-        if (YesNoDialogL(message))
+        if (CPerlUi::YesNoDialogL(message))
             DoRunScriptL(aScriptName);
-
         return ETrue;
     }
 
     return EFalse;
 }
 
-void CPerlAppUi::InstallOrRunL(const TFileName& aFileName)
+void CPerlAppAppUi::InstallOrRunL(const TFileName& aFileName)
 {
     TParse aFile;
     TParse aDrive;
@@ -410,15 +303,15 @@ void CPerlAppUi::InstallOrRunL(const TFileName& aFileName)
                   InstallStuffL(aFileName, aDrive, aFile, aPeekBuffer, *iFs) :
                   RunStuffL(aFileName, aPeekBuffer))) {
                 message.Format(_L("Failed for file %S"), &aFileName);
-                WarningNoteL(message);
+                CPerlUi::WarningNoteL(message);
             }
         } else {
             message.Format(_L("Error %d reading %S"), err, &aFileName);
-            WarningNoteL(message);
+            CPerlUi::WarningNoteL(message);
         }
     } else {
         message.Format(_L("Error %d opening %S"), err, &aFileName);
-        WarningNoteL(message);
+        CPerlUi::WarningNoteL(message);
     }
     if (iDoorObserver)
         delete CEikonEnv::Static()->EikAppUi();
@@ -426,62 +319,81 @@ void CPerlAppUi::InstallOrRunL(const TFileName& aFileName)
         Exit();
 }
 
-#endif // #ifndef PerlMin
+#endif /* #ifndef PerlAppMinimal */
+
+CPerlAppAppUi::~CPerlAppAppUi()
+{
+    if (iAppView) {
+        iEikonEnv->RemoveFromStack(iAppView);
+        delete iAppView;
+        iAppView = NULL;
+    }
+    if (iFs) {
+        delete iFs;
+        iFs = NULL;
+    }
+    if (iDoorObserver) // Otherwise the embedding application waits forever.
+        iDoorObserver->NotifyExit(MApaEmbeddedDocObserver::EEmpty);
+}
 
 static void DoRunScriptL(TFileName aScriptName)
 {
     CPerlBase* perl = CPerlBase::NewInterpreterLC();
     TRAPD(error, perl->RunScriptL(aScriptName));
-#ifndef PerlMin
+#ifndef PerlAppMinimal
     if (error != KErrNone) {
         TMessageBuffer message;
         message.Format(_L("Error %d"), error);
-        YesNoDialogL(message);
+        CPerlUi::YesNoDialogL(message);
     }
-#endif
+#endif // #ifndef PerlAppMinimal
     CleanupStack::PopAndDestroy(perl);
 }
 
-void CPerlAppUi::OpenFileL(const TDesC& aFileName)
+#ifndef PerlAppMinimal
+
+void CPerlAppAppUi::OpenFileL(const TDesC& aFileName)
 {
-#ifndef PerlMin
     InstallOrRunL(aFileName);
-#else
-    DoRunScriptL(aFileName);
-#endif
     return;
 }
 
-TBool CPerlAppUi::ProcessCommandParametersL(TApaCommand aCommand, TFileName& /* aDocumentName */, const TDesC8& /* aTail */)
+#endif // #ifndef PerlAppMinimal
+
+TBool CPerlAppAppUi::ProcessCommandParametersL(TApaCommand aCommand, TFileName& /* aDocumentName */, const TDesC8& /* aTail */)
 {
     if (aCommand == EApaCommandRun) {
         TFileName appName = Application()->AppFullName();
-       TParse p;
-       p.Set(KDefaultScript, &appName, NULL);
-       DoRunScriptL(p.FullName());
-       return EFalse;
+        TParse p;
+        p.Set(KDefaultScript, &appName, NULL);
+        TEntry aEntry;
+        RFs aFs;
+        aFs.Connect();
+        if (aFs.Entry(p.FullName(), aEntry) == KErrNone) {
+            DoRunScriptL(p.FullName());
+            Exit();
+        }
     }
     return aCommand == EApaCommandOpen ? ETrue : EFalse;
 }
 
-void CPerlAppUi::SetFs(const RFs& aFs)
+#ifndef PerlAppMinimal
+
+void CPerlAppAppUi::SetFs(const RFs& aFs)
 {
     iFs = (RFs*) &aFs;
 }
 
-void CPerlAppUi::HandleCommandL(TInt aCommand)
-{
-#ifndef PerlMin
+#endif // #ifndef PerlAppMinimal
+
+void CPerlAppAppUi::DoHandleCommandL(TInt aCommand) {
+#ifndef PerlAppMinimal
     TMessageBuffer message;
-#endif // #ifndef PerlMin
+#endif // #ifndef PerlAppMinimal
 
     switch(aCommand)
     {
-    case EEikCmdExit:
-    case EAknSoftkeyExit:
-        Exit();
-        break;
-#ifndef PerlMin
+#ifndef PerlAppMinimal
     case EPerlAppCommandAbout:
         {
             message.Format(KAboutFormat,
@@ -495,7 +407,7 @@ void CPerlAppUi::HandleCommandL(TInt aCommand)
                            PERL_SYMBIANSDK_MAJOR,
                            PERL_SYMBIANSDK_MINOR
                            );
-            InformationNoteL(message);
+            CPerlUi::InformationNoteL(message);
         }
         break;
     case EPerlAppCommandTime:
@@ -508,34 +420,56 @@ void CPerlAppUi::HandleCommandL(TInt aCommand)
             CleanupStack::PopAndDestroy(perl);
         }
         break;
+#ifndef __UIQ__
      case EPerlAppCommandRunFile:
         {
-            InformationNoteL(message);
             TFileName aScriptUtf16;
-            if (AknCommonDialogs::RunSelectDlgLD(aScriptUtf16,
-                                                 R_MEMORY_SELECTION_DIALOG))
-                DoRunScriptL(aScriptUtf16);
+            aScriptUtf16.Copy(_L("C:\\"));
+            if (CPerlUi::FileQueryDialogL(aScriptUtf16))
+              DoRunScriptL(aScriptUtf16);
         }
         break;
+#endif
      case EPerlAppCommandOneLiner:
         {
+#ifdef __SERIES60__
             _LIT(prompt, "Oneliner:");
-            if (TextQueryDialogL(prompt, iOneLiner, KPerlAppOneLinerSize)) {
-                const TUint KPerlAppUtf8Multi = 3;
-                TBuf8<KPerlAppUtf8Multi * KPerlAppOneLinerSize> utf8;
-
-                CnvUtfConverter::ConvertFromUnicodeToUtf8(utf8, iOneLiner);
+#endif /* #ifdef __SERIES60__ */
+#if defined(__SERIES80__) || defined(__SERIES90__) || defined(__UIQ__)
+            _LIT(prompt, "Code:"); // The title has "Oneliner" already.
+#endif /* #if defined(__SERIES80__) || defined(__SERIES90__) || defined(__UIQ__) */
+            CPerlAppAppUi* cAppUi =
+              static_cast<CPerlAppAppUi*>(CEikonEnv::Static()->EikAppUi());
+            if (CPerlUi::TextQueryDialogL(_L("Oneliner"),
+                                          prompt,
+                                          cAppUi->iOneLiner,
+                                          KPerlUiOneLinerSize)) {
+                const TUint KPerlUiUtf8Multi = 3; // Expansion multiplier.
+                TBuf8<KPerlUiUtf8Multi * KPerlUiOneLinerSize> utf8;
+
+                CnvUtfConverter::ConvertFromUnicodeToUtf8(utf8,
+                                                          cAppUi->iOneLiner);
                 CPerlBase* perl = CPerlBase::NewInterpreterLC();
-                int argc = 3;
-                char **argv = (char**) malloc(argc * sizeof(char *));
+#ifdef __SERIES90__
+               int argc = 5;
+#else
+               int argc = 3;
+#endif
+               char **argv = (char**) malloc(argc * sizeof(char *));
                 User::LeaveIfNull(argv);
 
                 TCleanupItem argvCleanupItem = TCleanupItem(free, argv);
                 CleanupStack::PushL(argvCleanupItem);
                 argv[0] = (char *) "perl";
                 argv[1] = (char *) "-le";
+#ifdef __SERIES90__
+                argv[2] = (char *) "unshift @INC, 'C:/Mydocs';";
+                argv[3] = (char *) "-e";
+                argv[4] = (char *) utf8.PtrZ();
+#else
                 argv[2] = (char *) utf8.PtrZ();
-                perl->ParseAndRun(argc, argv);
+#endif
+               perl->ParseAndRun(argc, argv);
                 CleanupStack::PopAndDestroy(2, perl);
             }
         }
@@ -543,67 +477,64 @@ void CPerlAppUi::HandleCommandL(TInt aCommand)
      case EPerlAppCommandCopyright:
         {
             message.Format(KCopyrightFormat);
-            InformationNoteL(message);
+            CPerlUi::InformationNoteL(message);
+        }
+        break;
+     case EPerlAppCommandAboutCopyright:
+        {
+            TMessageBuffer m1;
+            TMessageBuffer m2;
+            m1.Format(KAboutFormat,
+                      PERL_REVISION,
+                      PERL_VERSION,
+                      PERL_SUBVERSION,
+                      PERL_SYMBIANPORT_MAJOR,
+                      PERL_SYMBIANPORT_MINOR,
+                      PERL_SYMBIANPORT_PATCH,
+                      &KFlavor,
+                      PERL_SYMBIANSDK_MAJOR,
+                      PERL_SYMBIANSDK_MINOR
+                      );
+            CPerlUi::InformationNoteL(m1);
+            User::After((TTimeIntervalMicroSeconds32) (1000*1000)); // 1 sec.
+            m2.Format(KCopyrightFormat);
+            CPerlUi::InformationNoteL(m2);
         }
         break;
-#endif // #ifndef PerlMin
+#endif // #ifndef PerlAppMinimal
     default:
         Panic(EPerlAppCommandUnknown);
-        break;
     }
 }
 
-CPerlAppView* CPerlAppView::NewL(const TRect& aRect)
+CApaDocument* CPerlAppApplication::CreateDocumentL()
 {
-    CPerlAppView* self = CPerlAppView::NewLC(aRect);
-    CleanupStack::Pop(self);
-    return self;
+    CPerlAppDocument* cDoc = new (ELeave) CPerlAppDocument(*this);
+    return cDoc;
 }
 
-CPerlAppView* CPerlAppView::NewLC(const TRect& aRect)
+CEikAppUi* CPerlAppDocument::CreateAppUiL()
 {
-    CPerlAppView* self = new (ELeave) CPerlAppView;
-    CleanupStack::PushL(self);
-    self->ConstructL(aRect);
-    return self;
+    CPerlAppAppUi* cAppUi = new (ELeave) CPerlAppAppUi();
+    return cAppUi;
 }
 
-void CPerlAppView::ConstructL(const TRect& aRect)
-{
-    CreateWindowL();
-    SetRect(aRect);
-    ActivateL();
-}
 
-void CPerlAppView::Draw(const TRect& /*aRect*/) const
-{
-    CWindowGc& gc = SystemGc();
-    TRect rect = Rect();
-    gc.Clear(rect);
-}
+#ifndef PerlAppMinimal
 
-CApaDocument* CPerlAppApplication::CreateDocumentL() 
+CFileStore* CPerlAppDocument::OpenFileL(TBool aDoOpen, const TDesC& aFileName, RFs& aFs)
 {
-    CPerlAppDocument* document = new (ELeave) CPerlAppDocument(*this);
-    return document;
-}
-
-CEikAppUi* CPerlAppDocument::CreateAppUiL()
-{
-    CPerlAppUi* appui = new (ELeave) CPerlAppUi();
-    return appui;
-}
-
-CFileStore* CPerlAppDocument::OpenFileL(TBool /* aDoOpen */, const TDesC& aFileName, RFs& aFs)
-{
-    CPerlAppUi* appui =
-      STATIC_CAST(CPerlAppUi*, CEikonEnv::Static()->EikAppUi());
-    appui->SetFs(aFs);
-    appui->OpenFileL(aFileName);
+    CPerlAppAppUi* cAppUi =
+      static_cast<CPerlAppAppUi*>(CEikonEnv::Static()->EikAppUi());
+    cAppUi->SetFs(aFs);
+    if (aDoOpen)
+        cAppUi->OpenFileL(aFileName);
     return NULL;
 }
 
-EXPORT_C CApaApplication* NewApplication() 
+#endif // #ifndef PerlAppMinimal
+
+EXPORT_C CApaApplication* NewApplication()
 {
     return new CPerlAppApplication;
 }