Symbian/beginnings of Series 80 support
[p5sagit/p5-mst-13.2.git] / symbian / PerlApp.cpp
1 /* Copyright (c) 2004-2005 Nokia. All rights reserved. */
2
3 /* The PerlApp application is licensed under the same terms as Perl itself.
4  * Note that this PerlApp is for Symbian/Series 60/80 smartphones and it has
5  * nothing whatsoever to do with the ActiveState PerlApp. */
6
7 #include "PerlApp.h"
8
9 #ifdef __SERIES60__
10 # include <avkon.hrh>
11 # include <aknnotewrappers.h> 
12 # include <AknCommonDialogs.h>
13 # ifndef __SERIES60_1X__
14 #  include <CAknFileSelectionDialog.h>
15 # endif
16 #endif /* #ifdef __SERIES60__ */
17
18 #ifdef __SERIES80__
19 # include <eikon.hrh>
20 # include <cknflash.h>
21 # include <ckndgopn.h>
22 #endif /* #ifdef __SERIES80__ */
23
24 #include <apparc.h>
25 #include <e32base.h>
26 #include <e32cons.h>
27 #include <eikenv.h>
28 #include <bautils.h>
29 #include <eikappui.h>
30 #include <utf.h>
31 #include <f32file.h>
32
33 #include <coemain.h>
34
35 #ifndef PerlMin
36
37 #include "PerlApp.hrh"
38
39 #include "PerlApp.rsg"
40
41 #endif //#ifndef PerlMin
42
43 #include "EXTERN.h"
44 #include "perl.h"
45 #include "PerlBase.h"
46
47 const TUid KPerlAppUid = {
48 #ifdef PerlMinUid
49   PerlMinUid
50 #else
51   0x102015F6
52 #endif
53 };
54
55 _LIT(KDefaultScript, "default.pl");
56
57 // This is like the Symbian _LIT() but without the embedded L prefix,
58 // which enables using #defined constants (which need to carry their
59 // own L prefix).
60 #ifndef _LIT_NO_L
61 # define _LIT_NO_L(n, s) static const TLitC<sizeof(s)/2> n={sizeof(s)/2-1,s}
62 #endif // #ifndef _LIT_NO_L
63
64 #ifdef PerlMinName
65 _LIT_NO_L(KAppName, PerlMinName);
66 #else
67 _LIT(KAppName, "PerlApp");
68 #endif
69
70 #ifndef PerlMin
71
72 _LIT_NO_L(KFlavor, PERL_SYMBIANSDK_FLAVOR);
73 _LIT(KAboutFormat,
74      "Perl %d.%d.%d, Symbian port %d.%d.%d, built for %S SDK %d.%d");
75 _LIT(KCopyrightFormat,
76      "Copyright 1987-2005 Larry Wall and others, Symbian port Copyright Nokia 2004-2005");
77 _LIT(KInboxPrefix, "\\System\\Mail\\");
78 _LIT(KScriptPrefix, "\\Perl\\");
79
80 _LIT8(KModulePrefix, SITELIB); // SITELIB from Perl config.h
81
82 typedef TBuf<256>  TMessageBuffer;
83 typedef TBuf8<256> TPeekBuffer;
84 typedef TBuf8<256> TFileName8;
85
86 #endif // #ifndef PerlMin
87
88 // Usage: DEBUG_PRINTF((_L("%S"), &aStr))
89 #if 1
90 #define DEBUG_PRINTF(s) {TMessageBuffer message; message.Format s; YesNoDialogL(message);}
91 #endif
92
93 static void DoRunScriptL(TFileName aScriptName);
94
95 TUid CPerlAppApplication::AppDllUid() const
96 {
97     return KPerlAppUid;
98 }
99
100 enum TPerlAppPanic 
101 {
102     EPerlAppCommandUnknown = 1
103 };
104
105 void Panic(TPerlAppPanic aReason)
106 {
107     User::Panic(KAppName, aReason);
108 }
109
110 void CPerlAppUi::ConstructL()
111 {
112     BaseConstructL();
113     iAppView = CPerlAppView::NewL(ClientRect());
114     AddToStackL(iAppView);
115     iFs = NULL;
116     CEikonEnv::Static()->DisableExitChecks(ETrue); // Symbian FAQ-0577.
117 }
118
119 CPerlAppUi::~CPerlAppUi()
120 {
121     if (iAppView) {
122         iEikonEnv->RemoveFromStack(iAppView);
123         delete iAppView;
124         iAppView = NULL;
125     }
126     if (iFs) {
127         delete iFs;
128         iFs = NULL;
129     }
130     if (iDoorObserver) // Otherwise the embedding application waits forever.
131         iDoorObserver->NotifyExit(MApaEmbeddedDocObserver::EEmpty);
132 }
133
134 #ifndef PerlMin
135
136 #ifdef __SERIES60__
137
138 static TBool DlgOk(CAknNoteDialog* dlg)
139 {
140     return dlg && dlg->RunDlgLD() == EAknSoftkeyOk;
141 }
142
143 #endif /* #ifdef __SERIES60__ */
144
145 static TBool OkCancelDialogL(TDesC& aMessage)
146 {
147 #ifdef __SERIES60__
148     CAknNoteDialog* dlg =
149         new (ELeave) CAknNoteDialog(CAknNoteDialog::EConfirmationTone);
150     dlg->PrepareLC(R_OK_CANCEL_DIALOG);
151     dlg->SetTextL(aMessage);
152     return DlgOk(dlg);
153 #endif /* #ifdef __SERIES60__ */
154 #ifdef __SERIES80__
155     return CCknFlashingDialog::RunDlgLD(_L("OK/Cancel"), aMessage, NULL,
156                                         CCknFlashingDialog::EShort,
157                                         NULL);
158 #endif /* #ifdef __SERIES80__ */
159 }
160
161 static TBool YesNoDialogL(TDesC& aMessage)
162 {
163 #ifdef __SERIES60__
164     CAknNoteDialog* dlg =
165         new (ELeave) CAknNoteDialog(CAknNoteDialog::EConfirmationTone);
166     dlg->PrepareLC(R_YES_NO_DIALOG);
167     dlg->SetTextL(aMessage);
168     return DlgOk(dlg);
169 #endif /* #ifdef __SERIES60__ */
170 #ifdef __SERIES80__
171     return CCknFlashingDialog::RunDlgLD(_L("Yes/No"), aMessage, NULL,
172                                         CCknFlashingDialog::EShort,
173                                         NULL);
174 #endif /* #ifdef __SERIES80__ */
175 }
176
177 static TInt InformationNoteL(TDesC& aMessage)
178 {
179 #ifdef __SERIES60__
180     CAknInformationNote* note = new (ELeave) CAknInformationNote;
181     return note->ExecuteLD(aMessage);
182 #endif /* #ifdef __SERIES60__ */
183 #ifdef __SERIES80__
184     return CCknFlashingDialog::RunDlgLD(_L("Info"), aMessage, NULL,
185                                         CCknFlashingDialog::ENormal,
186                                         NULL);
187 #endif /* #ifdef __SERIES80__ */
188 }
189
190 static TInt ConfirmationNoteL(TDesC& aMessage)
191 {
192 #ifdef __SERIES60__
193     CAknConfirmationNote* note = new (ELeave) CAknConfirmationNote;
194     return note->ExecuteLD(aMessage);
195 #endif /* #ifdef __SERIES60__ */
196 #ifdef __SERIES80__
197     return CCknFlashingDialog::RunDlgLD(_L("Confirmation"), aMessage, NULL,
198                                         CCknFlashingDialog::ENormal,
199                                         NULL);
200 #endif /* #ifdef __SERIES80__ */
201 }
202
203 static TInt WarningNoteL(TDesC& aMessage)
204 {
205 #ifdef __SERIES60__
206     CAknWarningNote* note = new (ELeave) CAknWarningNote;
207     return note->ExecuteLD(aMessage);
208 #endif /* #ifdef __SERIES60__ */
209 #ifdef __SERIES80__
210     CEikonEnv::Static()->AlertWin(aMessage);
211     return ETrue;
212 #endif /* #ifdef __SERIES80__ */
213 }
214
215 static TInt TextQueryDialogL(const TDesC& aPrompt, TDes& aData, const TInt aMaxLength)
216 {
217 #ifdef __SERIES60__
218     CAknTextQueryDialog* dlg =
219         new (ELeave) CAknTextQueryDialog(aData);
220     dlg->SetPromptL(aPrompt);
221     dlg->SetMaxLength(aMaxLength);
222     return dlg->ExecuteLD(R_TEXT_QUERY_DIALOG);
223 #endif /* #ifdef __SERIES60__ */
224 #ifdef __SERIES80__
225     /* TODO */
226     return ETrue;
227 #endif
228 }
229
230 // The isXXX() come from the Perl headers.
231 #define FILENAME_IS_ABSOLUTE(n) \
232         (isALPHA(((n)[0])) && ((n)[1]) == ':' && ((n)[2]) == '\\')
233
234 static TBool IsInPerl(TFileName aFileName)
235 {
236     TInt offset = aFileName.FindF(KScriptPrefix);
237     return ((offset == 0 && // \foo
238              aFileName[0] == '\\')
239             ||
240             (offset == 2 && // x:\foo
241              FILENAME_IS_ABSOLUTE(aFileName)));
242 }
243
244 static TBool IsInInbox(TFileName aFileName)
245 {
246     TInt offset = aFileName.FindF(KInboxPrefix);
247     return ((offset == 0 && // \foo
248              aFileName[0] == '\\')
249             ||
250             (offset == 2 && // x:\foo
251              FILENAME_IS_ABSOLUTE(aFileName)));
252 }
253
254 static TBool IsPerlModule(TParsePtrC aParsed)
255 {
256     return aParsed.Ext().CompareF(_L(".pm")) == 0; 
257 }
258
259 static TBool IsPerlScript(TParsePtrC aParsed)
260 {
261     return aParsed.Ext().CompareF(_L(".pl")) == 0; 
262 }
263
264 static void CopyFromInboxL(RFs aFs, const TFileName& aSrc, const TFileName& aDst)
265 {
266     TBool proceed = ETrue;
267     TMessageBuffer message;
268
269     message.Format(_L("%S is untrusted. Install only if you trust provider."), &aDst);
270     if (OkCancelDialogL(message)) {
271         message.Format(_L("Install as %S?"), &aDst);
272         if (OkCancelDialogL(message)) {
273             if (BaflUtils::FileExists(aFs, aDst)) {
274                 message.Format(_L("Replace old %S?"), &aDst);
275                 if (!OkCancelDialogL(message))
276                     proceed = EFalse;
277             }
278             if (proceed) {
279                 // Create directory?
280                 TInt err = BaflUtils::CopyFile(aFs, aSrc, aDst);
281                 if (err == KErrNone) {
282                     message.Format(_L("Installed %S"), &aDst);
283                     ConfirmationNoteL(message);
284                 }
285                 else {
286                     message.Format(_L("Failure %d installing %S"), err, &aDst);
287                     WarningNoteL(message);
288                 }
289             }
290         }
291     }
292 }
293
294 static TBool FindPerlPackageName(TPeekBuffer aPeekBuffer, TInt aOff, TFileName& aFn)
295 {
296     aFn.SetMax();
297     TInt m = aFn.MaxLength();
298     TInt n = aPeekBuffer.Length();
299     TInt i = 0;
300     TInt j = aOff;
301
302     aFn.SetMax();
303     // The following is a little regular expression
304     // engine that matches Perl package names.
305     if (j < n && isSPACE(aPeekBuffer[j])) {
306         while (j < n && isSPACE(aPeekBuffer[j])) j++;
307         if (j < n && isALPHA(aPeekBuffer[j])) {
308             while (j < n && isALNUM(aPeekBuffer[j])) {
309                 while (j < n &&
310                        isALNUM(aPeekBuffer[j]) &&
311                        i < m)
312                     aFn[i++] = aPeekBuffer[j++];
313                 if (j + 1 < n &&
314                     aPeekBuffer[j    ] == ':' &&
315                     aPeekBuffer[j + 1] == ':' &&
316                     i < m) {
317                     aFn[i++] = '\\';
318                     j += 2;
319                     if (j < n &&
320                         isALPHA(aPeekBuffer[j])) {
321                         while (j < n &&
322                                isALNUM(aPeekBuffer[j]) &&
323                                i < m) 
324                             aFn[i++] = aPeekBuffer[j++];
325                     }
326                 }
327             }
328             while (j < n && isSPACE(aPeekBuffer[j])) j++;
329             if (j < n && aPeekBuffer[j] == ';' && i + 3 < m) {
330                 aFn.SetLength(i);
331                 aFn.Append(_L(".pm"));
332                 return ETrue;
333             }
334         }
335     }
336     return EFalse;
337 }
338
339 static void GuessPerlModule(TFileName& aGuess, TPeekBuffer aPeekBuffer, TParse aDrive)
340 {
341    TInt offset = aPeekBuffer.Find(_L8("package"));
342    if (offset != KErrNotFound) {
343        const TInt KPackageLen = 7;
344        TFileName q;
345
346        if (!FindPerlPackageName(aPeekBuffer, offset + KPackageLen, q))
347            return;
348
349        TFileName8 p;
350        p.Copy(aDrive.Drive());
351        p.Append(KModulePrefix);
352
353        aGuess.SetMax();
354        if (p.Length() + 1 + q.Length() < aGuess.MaxLength()) {
355            TInt i = 0, j;
356
357            for (j = 0; j < p.Length(); j++)
358                aGuess[i++] = p[j];
359            aGuess[i++] = '\\';
360            for (j = 0; j < q.Length(); j++)
361                aGuess[i++] = q[j];
362            aGuess.SetLength(i);
363        }
364        else
365            aGuess.SetLength(0);
366    }
367 }
368
369 static TBool LooksLikePerlL(TPeekBuffer aPeekBuffer)
370 {
371     return aPeekBuffer.Left(2).Compare(_L8("#!")) == 0 &&
372            aPeekBuffer.Find(_L8("perl")) != KErrNotFound;
373 }
374
375 static TBool InstallStuffL(const TFileName &aSrc, TParse aDrive, TParse aFile, TPeekBuffer aPeekBuffer, RFs aFs)
376 {
377     TFileName aDst;
378     TPtrC drive  = aDrive.Drive();
379     TPtrC namext = aFile.NameAndExt(); 
380
381     aDst.Format(_L("%S%S%S"), &drive, &KScriptPrefix, &namext);
382     if (!IsPerlScript(aDst) && !LooksLikePerlL(aPeekBuffer)) {
383         aDst.SetLength(0);
384         if (IsPerlModule(aDst))
385             GuessPerlModule(aDst, aPeekBuffer, aDrive);
386     }
387     if (aDst.Length() > 0) {
388         CopyFromInboxL(aFs, aSrc, aDst);
389         return ETrue;
390     }
391
392     return EFalse;
393 }
394
395 static TBool RunStuffL(const TFileName& aScriptName, TPeekBuffer aPeekBuffer)
396 {
397     TBool isModule = EFalse;
398
399     if (IsInPerl(aScriptName) &&
400         (IsPerlScript(aScriptName) ||
401          (isModule = IsPerlModule(aScriptName)) ||
402          LooksLikePerlL(aPeekBuffer))) {
403         TMessageBuffer message;
404
405         if (isModule)
406             message.Format(_L("Really run module %S?"), &aScriptName);
407         else 
408             message.Format(_L("Run %S?"), &aScriptName);
409         if (YesNoDialogL(message))
410             DoRunScriptL(aScriptName);
411
412         return ETrue;
413     }
414
415     return EFalse;
416 }
417
418 void CPerlAppUi::InstallOrRunL(const TFileName& aFileName)
419 {
420     TParse aFile;
421     TParse aDrive;
422     TMessageBuffer message;
423
424     aFile.Set(aFileName, NULL, NULL);
425     if (FILENAME_IS_ABSOLUTE(aFileName)) {
426         aDrive.Set(aFileName, NULL, NULL);
427     } else {
428         TFileName appName =
429           CEikonEnv::Static()->EikAppUi()->Application()->AppFullName();
430         aDrive.Set(appName, NULL, NULL);
431     }
432     if (!iFs)
433         iFs = &CEikonEnv::Static()->FsSession();
434     RFile f;
435     TInt err = f.Open(*iFs, aFileName, EFileRead);
436     if (err == KErrNone) {
437         TPeekBuffer aPeekBuffer;
438         err = f.Read(aPeekBuffer);
439         f.Close();  // Release quickly.
440         if (err == KErrNone) {
441             if (!(IsInInbox(aFileName) ?
442                   InstallStuffL(aFileName, aDrive, aFile, aPeekBuffer, *iFs) :
443                   RunStuffL(aFileName, aPeekBuffer))) {
444                 message.Format(_L("Failed for file %S"), &aFileName);
445                 WarningNoteL(message);
446             }
447         } else {
448             message.Format(_L("Error %d reading %S"), err, &aFileName);
449             WarningNoteL(message);
450         }
451     } else {
452         message.Format(_L("Error %d opening %S"), err, &aFileName);
453         WarningNoteL(message);
454     }
455     if (iDoorObserver)
456         delete CEikonEnv::Static()->EikAppUi();
457     else
458         Exit();
459 }
460
461 #endif // #ifndef PerlMin
462
463 static void DoRunScriptL(TFileName aScriptName)
464 {
465     CPerlBase* perl = CPerlBase::NewInterpreterLC();
466     TRAPD(error, perl->RunScriptL(aScriptName));
467 #ifndef PerlMin
468     if (error != KErrNone) {
469         TMessageBuffer message;
470         message.Format(_L("Error %d"), error);
471         YesNoDialogL(message);
472     }
473 #endif // #ifndef PerlMin
474     CleanupStack::PopAndDestroy(perl);
475 }
476
477 #ifndef PerlMin
478
479 void CPerlAppUi::OpenFileL(const TDesC& aFileName)
480 {
481     InstallOrRunL(aFileName);
482     return;
483 }
484
485 #endif // #ifndef PerlMin
486
487 TBool CPerlAppUi::ProcessCommandParametersL(TApaCommand aCommand, TFileName& /* aDocumentName */, const TDesC8& /* aTail */)
488 {
489     if (aCommand == EApaCommandRun) {
490         TFileName appName = Application()->AppFullName();
491         TParse p;
492         p.Set(KDefaultScript, &appName, NULL);
493         TEntry aEntry;
494         RFs aFs;
495         aFs.Connect();
496         if (aFs.Entry(p.FullName(), aEntry) == KErrNone) {
497             DoRunScriptL(p.FullName());
498             Exit();
499         }
500     }
501     return aCommand == EApaCommandOpen ? ETrue : EFalse;
502 }
503
504 #ifndef PerlMin
505
506 void CPerlAppUi::SetFs(const RFs& aFs)
507 {
508     iFs = (RFs*) &aFs;
509 }
510
511 #endif // #ifndef PerlMin
512
513 static void DoHandleCommandL(TInt aCommand) {
514 #ifndef PerlMin
515     TMessageBuffer message;
516 #endif // #ifndef PerlMin
517
518     switch(aCommand)
519     {
520 #ifndef PerlMin
521     case EPerlAppCommandAbout:
522         {
523             message.Format(KAboutFormat,
524                            PERL_REVISION,
525                            PERL_VERSION,
526                            PERL_SUBVERSION,
527                            PERL_SYMBIANPORT_MAJOR,
528                            PERL_SYMBIANPORT_MINOR,
529                            PERL_SYMBIANPORT_PATCH,
530                            &KFlavor,
531                            PERL_SYMBIANSDK_MAJOR,
532                            PERL_SYMBIANSDK_MINOR
533                            );
534             InformationNoteL(message);
535         }
536         break;
537     case EPerlAppCommandTime:
538         {
539             CPerlBase* perl = CPerlBase::NewInterpreterLC();
540             const char *const argv[] =
541               { "perl", "-le",
542                 "print 'Running in ', $^O, \"\\n\", scalar localtime" };
543             perl->ParseAndRun(sizeof(argv)/sizeof(char*), (char **)argv, 0);
544             CleanupStack::PopAndDestroy(perl);
545         }
546         break;
547      case EPerlAppCommandRunFile:
548         {
549             TFileName aScriptUtf16;
550 #ifdef __SERIES60__
551             if (AknCommonDialogs::RunSelectDlgLD(aScriptUtf16,
552                                                  R_MEMORY_SELECTION_DIALOG))
553                 DoRunScriptL(aScriptUtf16);
554 #endif /* #ifdef __SERIES60__ */
555 #ifdef __SERIES80__
556             aScriptUtf16.Copy(_L("C:\\"));
557             if (CCknOpenFileDialog::RunDlgLD(aScriptUtf16,
558                 CCknOpenFileDialog::EShowSystemFilesAndFolders |
559                 CCknOpenFileDialog::EShowHiddenFilesAndFolders |
560                 CCknOpenFileDialog::EShowAllDrives             |
561                 CCknOpenFileDialog::EShowExtendedView          |
562                 CCknOpenFileDialog::EShowNoFilesText) {
563               /* TODO: despite all the above flags still does not seem
564                * to allow navigating outside the default directory. */
565               TEntry aEntry;
566               RFs aFs;
567               aFs.Connect();
568               if (aFs.Entry(aScriptUtf16, aEntry) == KErrNone)
569                 DoRunScriptL(aScriptUtf16);
570               /* else show error message? */
571             }
572 #endif /* #ifdef __SERIES80__ */
573         }
574         break;
575      case EPerlAppCommandOneLiner:
576         {
577             _LIT(prompt, "Oneliner:");
578             CPerlAppUi* cAppUi =
579               STATIC_CAST(CPerlAppUi*, CEikonEnv::Static()->EikAppUi());
580             if (TextQueryDialogL(prompt,
581                                  cAppUi->iOneLiner,
582                                  KPerlAppOneLinerSize)) {
583                const TUint KPerlAppUtf8Multi = 3;
584                 TBuf8<KPerlAppUtf8Multi * KPerlAppOneLinerSize> utf8;
585
586                 CnvUtfConverter::ConvertFromUnicodeToUtf8(utf8, cAppUi->iOneLiner);
587                 CPerlBase* perl = CPerlBase::NewInterpreterLC();
588                 int argc = 3;
589                 char **argv = (char**) malloc(argc * sizeof(char *));
590                 User::LeaveIfNull(argv);
591
592                 TCleanupItem argvCleanupItem = TCleanupItem(free, argv);
593                 CleanupStack::PushL(argvCleanupItem);
594                 argv[0] = (char *) "perl";
595                 argv[1] = (char *) "-le";
596                 argv[2] = (char *) utf8.PtrZ();
597                 perl->ParseAndRun(argc, argv);
598                 CleanupStack::PopAndDestroy(2, perl);
599             }
600         }
601         break;
602      case EPerlAppCommandCopyright:
603         {
604             message.Format(KCopyrightFormat);
605             InformationNoteL(message);
606         }
607         break;
608      case EPerlAppCommandAboutCopyright:
609         {
610             TMessageBuffer m1;
611             TMessageBuffer m2;
612             m1.Format(KAboutFormat,
613                       PERL_REVISION,
614                       PERL_VERSION,
615                       PERL_SUBVERSION,
616                       PERL_SYMBIANPORT_MAJOR,
617                       PERL_SYMBIANPORT_MINOR,
618                       PERL_SYMBIANPORT_PATCH,
619                       &KFlavor,
620                       PERL_SYMBIANSDK_MAJOR,
621                       PERL_SYMBIANSDK_MINOR
622                       );
623             InformationNoteL(message);
624             m2.Format(KCopyrightFormat);
625             message.Format(_L("%S %S"), &m1, &m2);
626             InformationNoteL(message);
627         }
628         break;
629 #endif // #ifndef PerlMin
630     default:
631         Panic(EPerlAppCommandUnknown);
632     }
633 }
634
635 #ifdef __SERIES60__
636
637 void CPerlAppUi::HandleCommandL(TInt aCommand)
638 {
639     switch(aCommand)
640     {
641     case EEikCmdExit:
642     case EAknSoftkeyExit:
643         Exit();
644         break;
645     default:
646         DoHandleCommandL(aCommand);
647         break;
648     }
649 }
650
651 #endif /* #ifdef __SERIES60__ */
652
653 #ifdef __SERIES80__
654
655 void CPerlAppView::HandleCommandL(TInt aCommand) {
656     DoHandleCommandL(aCommand);
657 }
658
659 void CPerlAppUi::HandleCommandL(TInt aCommand) {
660     switch(aCommand)
661     {
662     case EEikCmdExit:
663         Exit();
664         break;
665     default:
666         iAppView->HandleCommandL(aCommand);
667         break;
668     }
669 }
670
671 #endif /* #ifdef __SERIES80__ */
672
673 CPerlAppView* CPerlAppView::NewL(const TRect& aRect)
674 {
675     CPerlAppView* self = CPerlAppView::NewLC(aRect);
676     CleanupStack::Pop(self);
677     return self;
678 }
679
680 CPerlAppView* CPerlAppView::NewLC(const TRect& aRect)
681 {
682     CPerlAppView* self = new (ELeave) CPerlAppView;
683     CleanupStack::PushL(self);
684     self->ConstructL(aRect);
685     return self;
686 }
687
688 void CPerlAppView::ConstructL(const TRect& aRect)
689 {
690     CreateWindowL();
691     SetRect(aRect);
692     ActivateL();
693 }
694
695 CPerlAppView::~CPerlAppView()
696 {
697 }
698
699 void CPerlAppView::Draw(const TRect& /*aRect*/) const
700 {
701     CWindowGc& gc = SystemGc();
702     TRect rect = Rect();
703     gc.Clear(rect);
704 }
705
706 CApaDocument* CPerlAppApplication::CreateDocumentL() 
707 {
708     CPerlAppDocument* document = new (ELeave) CPerlAppDocument(*this);
709     return document;
710 }
711
712 CEikAppUi* CPerlAppDocument::CreateAppUiL()
713 {
714     CPerlAppUi* appui = new (ELeave) CPerlAppUi();
715     return appui;
716 }
717
718
719 #ifndef PerlMin
720
721 CFileStore* CPerlAppDocument::OpenFileL(TBool aDoOpen, const TDesC& aFileName, RFs& aFs)
722 {
723     CPerlAppUi* appui =
724       STATIC_CAST(CPerlAppUi*, CEikonEnv::Static()->EikAppUi());
725     appui->SetFs(aFs);
726     if (aDoOpen)
727         appui->OpenFileL(aFileName);
728     return NULL;
729 }
730
731 #endif // #ifndef PerlMin
732
733 EXPORT_C CApaApplication* NewApplication() 
734 {
735     return new CPerlAppApplication;
736 }
737
738 GLDEF_C TInt E32Dll(TDllReason /*aReason*/)
739 {
740     return KErrNone;
741 }
742