javauis/lcdui_akn/lcdui/src/CMIDTextBoxQueryDialog.cpp
branchRCL_3
changeset 66 2455ef1f5bbc
child 71 d5e927d5853b
equal deleted inserted replaced
65:ae942d28ec0e 66:2455ef1f5bbc
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Popu-up TextBox dialog implementation for S60
       
    15 *
       
    16 */
       
    17 
       
    18 #include <eikenv.h>
       
    19 #include "CMIDTextBoxQueryDialog.h"
       
    20 
       
    21 #include "lcdui.hrh"
       
    22 #include <lcdui.rsg>
       
    23 #include <EIKCOCTL.rsg>
       
    24 
       
    25 #include "CMIDEdwinUtils.h"
       
    26 
       
    27 #include <eikcapc.h>
       
    28 #include <avkon.rsg>
       
    29 #include <avkon.hrh>
       
    30 
       
    31 #include <aknenv.h>
       
    32 #include <AknSettingCache.h>
       
    33 
       
    34 // FEP CR
       
    35 // constants for FEP
       
    36 #include <AknFepInternalCRKeys.h>
       
    37 #include <centralrepository.h>
       
    38 
       
    39 // CAknExtendedInputCapabilities for extended input capabilities
       
    40 #include <aknextendedinputcapabilities.h>
       
    41 
       
    42 // sound files
       
    43 #include <aknappui.h>
       
    44 #include <aknsoundsystem.h>
       
    45 
       
    46 // aiw used to invoke phonebook
       
    47 #include <AiwContactSelectionDataTypes.h>
       
    48 // phone client API classes for starting phone call
       
    49 #include <AiwCommon.h>
       
    50 #include <aiwdialdata.h>
       
    51 #include <aiwdialdataext.h>
       
    52 
       
    53 
       
    54 #include <j2me/jdebug.h>
       
    55 
       
    56 CMIDTextBoxQueryDialog* CMIDTextBoxQueryDialog::NewLC(TInt aConstraints,
       
    57         TDes& aResult,
       
    58         TInt aMaxSize,
       
    59         CMIDDisplayable* aDisplayable,
       
    60         const TDesC& aText)
       
    61 {
       
    62     CMIDTextBoxQueryDialog* self = new(ELeave) CMIDTextBoxQueryDialog(aResult);
       
    63     CleanupStack::PushL(self);
       
    64     self->ConstructL(aConstraints, aMaxSize, aDisplayable, aText);
       
    65     return self;
       
    66 }
       
    67 
       
    68 CMIDTextBoxQueryDialog::~CMIDTextBoxQueryDialog()
       
    69 {
       
    70     delete iAiwPbkClient;
       
    71     delete iEdwinUtils;
       
    72     RemoveNonMidletCommands();
       
    73 }
       
    74 
       
    75 void CMIDTextBoxQueryDialog::ConstructL(TInt aConstraints,
       
    76                                         TInt aMaxSize,
       
    77                                         CMIDDisplayable* aDisplayable,
       
    78                                         const TDesC& aText)
       
    79 {
       
    80     TLocale loc;
       
    81     iDecimalSeparator = loc.DecimalSeparator();
       
    82     if (iDecimalSeparator != ',')
       
    83     {
       
    84         iDecimalSeparator = '.';
       
    85     }
       
    86 
       
    87     iEdwinUtils = CMIDEdwinUtils::NewL(this, iDecimalSeparator);
       
    88 
       
    89     iConstraints = aConstraints;
       
    90     iStrict = ETrue;
       
    91 
       
    92     // if text is invalid according to constraints, throw IllegalArgumentException,
       
    93     // except for a PHONENUMBER which only has the invalid characters removed
       
    94     if ((iConstraints & MMIDTextField::EConstraintMask) != MMIDTextField::EPhoneNumber
       
    95             && !iEdwinUtils->ConstraintsValidForText(aText,iConstraints,ETrue))
       
    96     {
       
    97         User::Leave(KErrArgument);
       
    98     }
       
    99 
       
   100     iMaxSize = aMaxSize;
       
   101     iDisplayable = aDisplayable;
       
   102 
       
   103     // This is aprotected method call must be inside the class itself.
       
   104     // ConstructSleepingDialogL is replacing the call of ReadResourceLC
       
   105     // in CMIDTextBoxDialogControl::CreateTextBoxQueryDialogL
       
   106     ConstructSleepingDialogL(R_MIDP_POPUP_TEXTBOX);
       
   107 }
       
   108 
       
   109 CMIDTextBoxQueryDialog::CMIDTextBoxQueryDialog(TDes& aResult)
       
   110         : CAknTextQueryDialog(aResult, CAknQueryDialog::ENoTone)
       
   111 {
       
   112 }
       
   113 
       
   114 TInt CMIDTextBoxQueryDialog::RouseSleepingDialog()
       
   115 {
       
   116     return CAknTextQueryDialog::RouseSleepingDialog();
       
   117 }
       
   118 
       
   119 void CMIDTextBoxQueryDialog::ExitSleepingDialog()
       
   120 {
       
   121     CAknTextQueryDialog::ExitSleepingDialog();
       
   122 }
       
   123 
       
   124 void CMIDTextBoxQueryDialog::TryExitL(TInt aButtonId)
       
   125 {
       
   126     iDisplayable->MenuHandler()->ProcessCommandL(aButtonId);
       
   127 }
       
   128 
       
   129 TBool CMIDTextBoxQueryDialog::ProcessCommandL(CMIDCommand* aCommand)
       
   130 {
       
   131     ASSERT(aCommand);
       
   132     TBool ret = EFalse;
       
   133 
       
   134     switch (aCommand->Id())
       
   135     {
       
   136     case CMIDEdwinUtils::EMenuCommandFetchPhoneNumber:
       
   137         // for fetching data from phonebook
       
   138         if (!iAiwPbkClient)
       
   139         {
       
   140             iAiwPbkClient = CMIDAiwPbk2Client::NewL(*this);
       
   141         }
       
   142         iAiwPbkClient->FetchFromPhoneBookL(EAiwPhoneNumberSelect);
       
   143         ret = ETrue;
       
   144         break;
       
   145     case CMIDEdwinUtils::EMenuCommandFetchEmailAddress:
       
   146         // for fetching data from phonebook
       
   147         if (!iAiwPbkClient)
       
   148         {
       
   149             iAiwPbkClient = CMIDAiwPbk2Client::NewL(*this);
       
   150         }
       
   151         iAiwPbkClient->FetchFromPhoneBookL(EAiwEMailSelect);
       
   152         ret = ETrue;
       
   153         break;
       
   154     case CMIDEdwinUtils::EMenuCommandCreatePhoneCall:
       
   155         CreatePhoneCallL();
       
   156         ret = ETrue;
       
   157         break;
       
   158     default:
       
   159         break;
       
   160     }
       
   161 
       
   162     return ret;
       
   163 }
       
   164 
       
   165 void CMIDTextBoxQueryDialog::DeleteTextL(TInt aOffset,TInt aLength)
       
   166 {
       
   167     // get all initial values before deletion
       
   168     TInt oldSize = Size();
       
   169     HBufC* oldText = iEditor->GetTextInHBufL();
       
   170     CleanupStack::PushL(oldText);
       
   171 
       
   172     TInt cursorPos = GetCaretPosition();
       
   173 
       
   174     TCursorSelection selection = TCursorSelection(aOffset, aOffset + aLength);
       
   175     _LIT(KEmptyText, "");
       
   176     iEditor->InsertDeleteCharsL(aOffset, KEmptyText, selection);
       
   177 
       
   178     // Check that new content is valid.
       
   179     // If not, return old content and throw exception.
       
   180     TBool valid = iEdwinUtils->ConstraintsValidForText(Read(), iConstraints, ETrue);
       
   181     if (!valid)
       
   182     {
       
   183         iEditor->SetTextL(oldText);
       
   184     }
       
   185     CleanupStack::PopAndDestroy(oldText);
       
   186 
       
   187     iEditor->HandleTextChangedL();
       
   188 
       
   189     if (!valid)
       
   190     {
       
   191         User::Leave(KErrArgument);
       
   192     }
       
   193 
       
   194     // Handle cursor moving
       
   195 
       
   196     // Cursor is in the middle of delete area
       
   197     if ((cursorPos > aOffset) && (cursorPos < (aOffset + aLength)))
       
   198     {
       
   199         SetCursorPositionL(aOffset);
       
   200     }
       
   201     // cursor is on the right side of delete area
       
   202     else if (cursorPos > (aOffset + aLength))
       
   203     {
       
   204         TInt newPosition = cursorPos - aLength;
       
   205         if (newPosition < 0)
       
   206         {
       
   207             newPosition = 0;
       
   208         }
       
   209         SetCursorPositionL(newPosition);
       
   210     }
       
   211     // cursor is on the left side of delete area
       
   212     else
       
   213     {
       
   214         SetCursorPositionL(cursorPos);
       
   215     }
       
   216 }
       
   217 
       
   218 void CMIDTextBoxQueryDialog::SetTextL(const TDesC& aText)
       
   219 {
       
   220     // if text is invalid according to constraints, throw IllegalArgumentException,
       
   221     //  except for a PHONENUMBER which only has the invalid characters removed
       
   222     if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber)
       
   223     {
       
   224     }
       
   225     else if (!iEdwinUtils->ConstraintsValidForText(aText, iConstraints, (iStrict ? ETrue : EFalse)))
       
   226     {
       
   227         User::Leave(KErrArgument);
       
   228     }
       
   229     iStrict = ETrue;
       
   230 
       
   231     HBufC* buf = iEdwinUtils->ConvertToLocalizedLC(aText, iConstraints);
       
   232 
       
   233     if (IsNumberConversionNeeded())
       
   234     {
       
   235         TPtr ptr = buf->Des();
       
   236         AknTextUtils::LanguageSpecificNumberConversion(ptr);
       
   237     }
       
   238 
       
   239     if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber)
       
   240     {
       
   241         iEdwinUtils->RemoveNonPhoneNumberChars(buf);
       
   242     }
       
   243     iEditor->SetTextL(buf);
       
   244     iEditor->HandleTextChangedL();
       
   245     CleanupStack::PopAndDestroy(buf);
       
   246 
       
   247     // move cursor to end of the new text
       
   248     SetCursorPositionL(Size());
       
   249 }
       
   250 
       
   251 void CMIDTextBoxQueryDialog::InsertTextL(const TDesC& aText,TInt aPosition)
       
   252 {
       
   253     //VALIDATE EXISTING TEXT
       
   254     HBufC* temp = NULL;
       
   255     if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EDecimal)
       
   256     {
       
   257         // Convert decimal content to unlocalized form before testing validity
       
   258         // of insertion.
       
   259         temp = GetTextL();
       
   260         if (temp)
       
   261         {
       
   262             CleanupStack::PushL(temp);
       
   263             iEdwinUtils->ConvertFromLocalizedDecimal(temp);
       
   264         }
       
   265     }
       
   266 
       
   267     if (aPosition < 0)
       
   268         aPosition = 0;
       
   269     //
       
   270     TInt size = Size();
       
   271     if (aPosition > size)
       
   272         aPosition = size;
       
   273     //
       
   274     if (!iEdwinUtils->ConstraintsValidForInsertedTextL((temp ? temp->Des() : Read()),
       
   275             aText,
       
   276             aPosition,
       
   277             iConstraints,
       
   278             ETrue))
       
   279         User::Leave(KErrArgument);
       
   280     if (temp)
       
   281     {
       
   282         CleanupStack::PopAndDestroy(temp);
       
   283         temp = NULL;
       
   284     }
       
   285     //
       
   286     //TEXT INSERTION STARTS HERE
       
   287     if (IsReadyToDraw())
       
   288     {
       
   289         iEditor->ClearSelectionL();
       
   290     }
       
   291 
       
   292     temp = iEdwinUtils->ConvertToLocalizedLC(aText, iConstraints);
       
   293 
       
   294     if (IsNumberConversionNeeded())
       
   295     {
       
   296         TPtr ptr = temp->Des();
       
   297         AknTextUtils::LanguageSpecificNumberConversion(ptr);
       
   298     }
       
   299     iEditor->Text()->InsertL(aPosition, temp->Des());
       
   300 
       
   301     iEditor->HandleTextChangedL();
       
   302 
       
   303     // Get the cursor position and move it forward along with inserter characters, if
       
   304     // characters were inserted on the left side of the cursor.
       
   305     TInt cursorPos = GetCaretPosition();
       
   306     TInt numberOfAddedCharacters = Size() - size;
       
   307 
       
   308     if (cursorPos >= aPosition)
       
   309     {
       
   310         if ((cursorPos + numberOfAddedCharacters) < iMaxSize)
       
   311         {
       
   312             SetCursorPositionL(cursorPos + numberOfAddedCharacters);
       
   313         }
       
   314     }
       
   315 
       
   316     CleanupStack::PopAndDestroy(temp);
       
   317 }
       
   318 
       
   319 void CMIDTextBoxQueryDialog::SetConstraintsL(TUint /*aConstraints*/)
       
   320 {
       
   321 }
       
   322 
       
   323 void CMIDTextBoxQueryDialog::SetFEPModeAndCharFormat()
       
   324 {
       
   325     iEdwinUtils->SetFEPModeAndCharFormat(iConstraints, iEditor);
       
   326 }
       
   327 
       
   328 TInt CMIDTextBoxQueryDialog::SetMaxSizeL(TInt aSize)
       
   329 {
       
   330     TInt oldSize = Size();
       
   331     if (aSize < oldSize)
       
   332     {
       
   333         DeleteTextL(aSize, oldSize - aSize);
       
   334     }
       
   335     iMaxSize = aSize;
       
   336     iEditor->SetTextLimit(iMaxSize);
       
   337     iMaxSize = GetMaxSize();
       
   338     return iMaxSize;
       
   339 }
       
   340 
       
   341 TInt CMIDTextBoxQueryDialog::GetMaxSize()
       
   342 {
       
   343     return iEditor->MaxLength();
       
   344 }
       
   345 
       
   346 TInt CMIDTextBoxQueryDialog::Size()
       
   347 {
       
   348     return iEditor->TextLength();
       
   349 }
       
   350 
       
   351 TInt CMIDTextBoxQueryDialog::GetCaretPosition()
       
   352 {
       
   353     return iEditor->CursorPos();
       
   354 }
       
   355 
       
   356 HBufC* CMIDTextBoxQueryDialog::GetTextL()
       
   357 {
       
   358     // getting of native text
       
   359     HBufC* buf = iEditor->GetTextInHBufL();
       
   360 
       
   361     // If there is no text in iEditor, this set empty buf.
       
   362     if (!buf)
       
   363     {
       
   364         buf = HBufC::NewL(0);
       
   365     }
       
   366 
       
   367     // convert decimal from localized to MIDlet-visible representation
       
   368     if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EDecimal)
       
   369     {
       
   370         iEdwinUtils->ConvertFromLocalizedDecimal(buf);
       
   371     }
       
   372 
       
   373     // convert digits, if needed
       
   374     if (IsNumberConversionNeeded())
       
   375     {
       
   376         TPtr ptr = buf->Des();
       
   377         AknTextUtils::ConvertDigitsTo(ptr, EDigitTypeWestern);
       
   378     }
       
   379 
       
   380     // Return a copy of the contents where newlines etc. are
       
   381     // mapped to their Java representations.
       
   382     CMIDUtils::MapETextToJavaChars(buf);
       
   383 
       
   384 
       
   385     return buf;
       
   386 }
       
   387 
       
   388 void CMIDTextBoxQueryDialog::SetInitialInputModeL(const TDesC& aCharacterSubset)
       
   389 {
       
   390     iEdwinUtils->SetInitialInputModeL(aCharacterSubset,
       
   391                                       iConstraints,
       
   392                                       iInitialCurrentCase,
       
   393                                       iInitialCurrentInputMode,
       
   394                                       iInitialCurrentLanguage);
       
   395 
       
   396     TUint constraint = iConstraints & MMIDTextField::EConstraintMask;
       
   397 
       
   398     // Set permitted case modes for TextBox in lowercase or uppercase mode.
       
   399     if (aCharacterSubset.Compare(KMidpUppercaseLatin) == 0 ||
       
   400             aCharacterSubset.Compare(KMidpLowercaseLatin) == 0)
       
   401     {
       
   402         // MIDP_UPPERCASE_LATIN or MIDP_LOWERCASE_LATIN are ignored if
       
   403         // INITIAL_CAPS_SENTENCE or INITIAL_CAPS_WORD modifier in ANY.
       
   404         if (!(iConstraints & MMIDTextField::EInitialCapsWordSentence ||
       
   405                 iConstraints & MMIDTextField::EInitialCapsWord) ||
       
   406                 constraint != MMIDTextField::EAny)
       
   407         {
       
   408             // If initial input mode is uppercase or lowercase then permit
       
   409             // only explicit case mode changes, automatic changes are not
       
   410             // allowed.
       
   411             iEditor->SetAknEditorPermittedCaseModes(EAknEditorUpperCase |
       
   412                                                     EAknEditorLowerCase);
       
   413         }
       
   414     }
       
   415     else
       
   416     {
       
   417         iEditor->SetAknEditorPermittedCaseModes(EAknEditorAllCaseModes);
       
   418     }
       
   419 }
       
   420 
       
   421 void CMIDTextBoxQueryDialog::SetTitleL(const TDesC* aString)
       
   422 {
       
   423     if (aString)
       
   424     {
       
   425         SetPromptL(*aString);
       
   426     }
       
   427     else
       
   428     {
       
   429         SetPromptL(KNullDesC);
       
   430     }
       
   431 }
       
   432 
       
   433 void CMIDTextBoxQueryDialog::SetCursorPositionL(TInt aPosition)
       
   434 {
       
   435     TInt textLength = iEditor->TextLength();
       
   436     if (textLength < aPosition)
       
   437     {
       
   438         aPosition = textLength;
       
   439     }
       
   440     if (textLength >0)
       
   441     {
       
   442         iEditor->SetCursorPosL(aPosition, EFalse);
       
   443     }
       
   444     else
       
   445     {
       
   446         iEditor->SetCursorPosL(0, EFalse);
       
   447     }
       
   448 }
       
   449 
       
   450 TSize CMIDTextBoxQueryDialog::ContentSize() const
       
   451 {
       
   452     return CCoeControl::Size();
       
   453 }
       
   454 
       
   455 void CMIDTextBoxQueryDialog::FocusChanged(TDrawNow aDrawNow)
       
   456 {
       
   457     CAknTextQueryDialog::FocusChanged(aDrawNow);
       
   458 }
       
   459 //
       
   460 // We do not want to become visible if we are not showing
       
   461 //
       
   462 void CMIDTextBoxQueryDialog::MakeVisible(TBool aVisible)
       
   463 {
       
   464     if (!aVisible)
       
   465     {
       
   466         CAknTextQueryDialog::MakeVisible(aVisible);
       
   467     }
       
   468     else if (iShowing)
       
   469     {
       
   470         if (aVisible)
       
   471         {
       
   472             //re-layouting done just before dialog is shown
       
   473             //to be sure layout is correct in CAknPopupForm
       
   474             CAknTextQueryDialog::SizeChanged();
       
   475         }
       
   476         CAknTextQueryDialog::MakeVisible(aVisible);
       
   477     }
       
   478 }
       
   479 
       
   480 void CMIDTextBoxQueryDialog::SizeChanged()
       
   481 {
       
   482     if (iShowing)
       
   483     {
       
   484         CAknTextQueryDialog::SizeChanged();
       
   485     }
       
   486     TRAP_IGNORE(UpdateScrollBarPositionL());
       
   487 }
       
   488 
       
   489 TKeyResponse CMIDTextBoxQueryDialog::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
       
   490 {
       
   491     // If midlet is closed from applications menu or by pressing end key, then
       
   492     // 'esc' key event is generated. That event is not handled here.
       
   493     // See OfferKeyEventL function of CMIDTextBoxDialogControl.
       
   494     if (aKeyEvent.iCode == EKeyEscape)
       
   495     {
       
   496         return EKeyWasNotConsumed;
       
   497     }
       
   498     //
       
   499     //  Enter Key:
       
   500     //
       
   501     //
       
   502     if (aType == EEventKey)
       
   503     {
       
   504         iusedKeyEvent = &aKeyEvent;
       
   505     }
       
   506 
       
   507     // If TextBox have constraints below params
       
   508     // Any and Password
       
   509     // Numeric or Numeric and Password or
       
   510     // Decimal or Decimal and Password  or
       
   511     // PhoneNumber or PhoneNumber and Password or
       
   512     // MailAddr or MailAddr and Password or
       
   513     // PhoneNumber Uneditable or MailAddr Uneditable or
       
   514     // Url or Url and Password
       
   515     // then show menu or activate one command.
       
   516     if (((aType == EEventKey && aKeyEvent.iCode == EKeyEnter) ||
       
   517             (aType == EEventKeyUp && aKeyEvent.iScanCode ==   EStdKeyEnter &&
       
   518              aKeyEvent.iCode == EKeyEnter && iusedKeyEvent!=&aKeyEvent)))
       
   519     {
       
   520 
       
   521         if ((iConstraints == MMIDTextField::EAny + MMIDTextField::EPassword) ||
       
   522 
       
   523                 (iConstraints == MMIDTextField::ENumeric ||
       
   524                  (iConstraints == MMIDTextField::ENumeric  + MMIDTextField::EPassword) ||
       
   525                  iConstraints == MMIDTextField::EDecimal ||
       
   526                  (iConstraints == MMIDTextField::EDecimal + MMIDTextField::EPassword)) ||
       
   527 
       
   528                 (iConstraints == MMIDTextField::EPhoneNumber ||
       
   529                  (iConstraints == MMIDTextField::EPhoneNumber + MMIDTextField::EPassword) ||
       
   530                  iConstraints == MMIDTextField::EMailAddr ||
       
   531                  (iConstraints == MMIDTextField::EMailAddr  + MMIDTextField::EPassword))  ||
       
   532 
       
   533                 ((iConstraints == MMIDTextField::EPhoneNumber + MMIDTextField::EUneditable) ||
       
   534                  (iConstraints == MMIDTextField::EMailAddr  + MMIDTextField::EUneditable)) ||
       
   535 
       
   536                 (iConstraints == MMIDTextField::EUrl ||
       
   537                  (iConstraints == MMIDTextField::EUrl + MMIDTextField::EPassword)))
       
   538         {
       
   539 
       
   540             // counter OK and Item elements from options menu
       
   541             TInt numOpt = iDisplayable->NumCommandsForOkOptionsMenu();
       
   542 
       
   543             //open menu
       
   544             if (numOpt > 1)
       
   545             {
       
   546                 iDisplayable->MenuHandler()->ShowMenuL(CMIDMenuHandler::EOkMenu);
       
   547             }
       
   548             else
       
   549             {
       
   550                 CMIDCommand* cmdTmp = NULL;
       
   551 
       
   552                 // counter of all elements from options menu
       
   553                 TInt numItemCommands = iDisplayable->MainCommandList()->Count();
       
   554 
       
   555                 for (TInt i = 0; i < numItemCommands; i++)
       
   556                 {
       
   557                     // for each command from menu
       
   558                     // count offset index only for commands
       
   559                     // without FetchPhoneNumber, EmailAddress, PhoneCall
       
   560                     cmdTmp = iDisplayable->MainCommandList()->At(i).iCommand;
       
   561 
       
   562                     if (cmdTmp)
       
   563                     {
       
   564                         if ((cmdTmp->Id() != CMIDEdwinUtils::EMenuCommandFetchPhoneNumber) &&
       
   565                                 (cmdTmp->Id() != CMIDEdwinUtils::EMenuCommandFetchEmailAddress) &&
       
   566                                 (cmdTmp->Id() != CMIDEdwinUtils::EMenuCommandCreatePhoneCall))
       
   567                         {
       
   568                             break;
       
   569                         }
       
   570                     }
       
   571                 }
       
   572 
       
   573                 // execute command
       
   574                 if (cmdTmp)
       
   575                 {
       
   576                     if ((cmdTmp->CommandType() == MMIDCommand::EOk ||
       
   577                             cmdTmp->CommandType() == MMIDCommand::EItem ||
       
   578                             cmdTmp->CommandType() == MMIDCommand::EScreen))
       
   579                     {
       
   580                         // get command index from option menu
       
   581                         TInt offsetIdx = iDisplayable->MainCommandList()->FindCommandIndex(cmdTmp);
       
   582 
       
   583                         if (offsetIdx != KErrNotFound &&
       
   584                                 iDisplayable->MainCommandList()->At(offsetIdx).iCommand == cmdTmp)
       
   585                         {
       
   586                             iDisplayable->ProcessCommandL(iDisplayable->MainCommandList()->CommandOffset() + offsetIdx);
       
   587                         }
       
   588 
       
   589                     }
       
   590                 }
       
   591             }
       
   592             return EKeyWasConsumed;
       
   593         }
       
   594     }
       
   595 
       
   596     //
       
   597     //  End Enter Key
       
   598     //
       
   599 
       
   600     // msk: this is needed if MSK is not enabled on the device
       
   601     if ((aType == EEventKey) && (aKeyEvent.iScanCode == EStdKeyDevice3))
       
   602     {
       
   603         if (iDisplayable && iDisplayable->ShowOkOptionsMenuL())
       
   604         {
       
   605             SetFocus(EFalse);
       
   606         }
       
   607         return EKeyWasConsumed;
       
   608     }
       
   609 
       
   610     // store the key pressed last time, used for warning beeps while reaching size limit
       
   611     if (aType == EEventKeyDown)
       
   612     {
       
   613         iLastMultitapKey = iThisMultitapKey;
       
   614         iThisMultitapKey = aKeyEvent.iScanCode;
       
   615     }
       
   616 
       
   617     if (aType == EEventKeyDown)
       
   618     {
       
   619         iKeyEventsPending = ETrue;
       
   620     }
       
   621     else if (aType == EEventKeyUp)
       
   622     {
       
   623         iKeyEventsPending = EFalse;
       
   624     }
       
   625     //
       
   626     // Post ItemStateChangedEvent before a command is delivered to the Form's CommandListener
       
   627     //
       
   628     TUint scanCode = aKeyEvent.iScanCode;
       
   629 
       
   630     //
       
   631     // ignore up and down arrows on PASSWORD TextField to avoid funny behaviour
       
   632     // with line breaks
       
   633     if (iDisplayable && (iConstraints & MMIDTextField::EPassword)
       
   634             && (aKeyEvent.iCode == EKeyDownArrow || aKeyEvent.iCode == EKeyUpArrow))
       
   635     {
       
   636         return EKeyWasConsumed;
       
   637     }
       
   638 
       
   639     // when pressing the send key on a phonenumber-type box, call the number
       
   640 #ifdef RD_SCALABLE_UI_V2
       
   641     if ((aType == EEventKey) && (scanCode == EStdKeyYes))
       
   642 #else
       
   643     if ((aType == EEventKeyUp) && (scanCode == EStdKeyYes))
       
   644 #endif // RD_SCALABLE_UI_V2
       
   645     {
       
   646         if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber)
       
   647         {
       
   648             CreatePhoneCallL();
       
   649             return EKeyWasConsumed;
       
   650         }
       
   651     }
       
   652 
       
   653 #ifdef RD_SCALABLE_UI_V2
       
   654     if (IsConstraintSet(MMIDTextField::ENumeric) && (aType == EEventKey || aType == EEventKeyUp) && !iEditor->IsReadOnly() &&
       
   655 #else
       
   656     if (IsConstraintSet(MMIDTextField::ENumeric) && (aType == EEventKeyUp) && !iEditor->IsReadOnly() &&
       
   657 #endif // RD_SCALABLE_UI_V2
       
   658             ((scanCode==EStdKeyNkpAsterisk) || (scanCode == EStdKeyMinus) || (scanCode==EStdKeyNkpMinus) || (scanCode == 0x2A) || (scanCode == 0x2D) ||
       
   659              (TChar(aKeyEvent.iCode) == TChar('-') && scanCode != EStdKeyMinus)))
       
   660     {
       
   661         HandleMinusCharEventL(MEikEdwinObserver::EEventTextUpdate);
       
   662         return EKeyWasConsumed;
       
   663     }
       
   664 
       
   665     //handling of qwerty keypad "-" or "." pressing in Decimal mode
       
   666 #ifdef RD_SCALABLE_UI_V2
       
   667     if (IsConstraintSet(MMIDTextField::EDecimal) && (aType == EEventKey) && !iEditor->IsReadOnly() &&
       
   668 #else
       
   669     if (IsConstraintSet(MMIDTextField::EDecimal) && (aType == EEventKeyUp) && !iEditor->IsReadOnly() &&
       
   670 #endif // RD_SCALABLE_UI_V2
       
   671             ((scanCode==EStdKeyMinus) || (scanCode==EStdKeyFullStop)))
       
   672     {
       
   673         CPlainText* res = iEditor->Text();
       
   674         TInt textLength = Size();
       
   675         if (scanCode == EStdKeyMinus && textLength < iMaxSize)
       
   676         {
       
   677             res->InsertL(GetCaretPosition(), KMinusChar);
       
   678         }
       
   679         else if (scanCode == EStdKeyFullStop && textLength < iMaxSize)
       
   680         {
       
   681             res->InsertL(GetCaretPosition(), KFullStopChar);
       
   682         }
       
   683 
       
   684         iEditor->HandleTextChangedL(); // notify editor about the text changes
       
   685         TInt cursorPos = GetCaretPosition();
       
   686 
       
   687         if (Size() < iMaxSize)
       
   688         {
       
   689             SetCursorPositionL(cursorPos + 1);
       
   690         }
       
   691         else if (cursorPos == (iMaxSize - 1) && cursorPos == textLength &&
       
   692                  (scanCode == EStdKeyFullStop || scanCode == EStdKeyMinus))
       
   693         {
       
   694             SetCursorPositionL(iMaxSize);
       
   695         }
       
   696 
       
   697         HandleTextUpdateL(MEikEdwinObserver::EEventTextUpdate);
       
   698     }
       
   699     //Error tone playing case1:
       
   700     //Play error tone if TextBox/TextField is read-only or maximum length has been reached.
       
   701     //Here is handling of keys 0...9 for full keyboard and itu-t, but NOT virtual keyboard.
       
   702     if (aType == EEventKeyDown
       
   703             && ((scanCode >= KKeyQwerty0 && scanCode <= KKeyQwerty9)
       
   704                 || scanCode == EStdKeyHash
       
   705                 || scanCode == EStdKeyNkpAsterisk
       
   706                 || scanCode == KMidpKeyNkpAsteriskHW))
       
   707     {
       
   708         if ((scanCode == EStdKeyNkpAsterisk || scanCode == KMidpKeyNkpAsteriskHW)
       
   709                 && !iEditor->IsReadOnly() && IsConstraintSet(MMIDTextField::ENumeric))
       
   710         {
       
   711             //Do nothing here in case of minus char toggle
       
   712         }
       
   713         else if (iEditor->IsReadOnly())
       
   714         {
       
   715             iAvkonAppUi->KeySounds()->PlaySound(EAvkonSIDErrorTone);
       
   716             return EKeyWasConsumed;
       
   717         }
       
   718 
       
   719         // All possible sources of warning beep are separated to be easy to read
       
   720         else if (Size() >= iMaxSize)
       
   721         {
       
   722             TInt ret = KErrNone;
       
   723             TInt inputModeValue = iEditor->AknEditorCurrentInputMode();
       
   724             if (inputModeValue != EAknEditorTextInputMode)
       
   725             {
       
   726                 iAvkonAppUi->KeySounds()->PlaySound(EAvkonSIDErrorTone);
       
   727                 return EKeyWasConsumed;
       
   728             }
       
   729 
       
   730             TInt aknRepositoryValue = 0;
       
   731             CRepository* aknFepRepository = NULL;
       
   732             TRAP(ret, aknFepRepository = CRepository::NewL(KCRUidAknFep));
       
   733             if ((ret != KErrNone) || (!aknFepRepository))
       
   734             {
       
   735                 // if we cannot get the repository (something is wrong), play nothing
       
   736                 return EKeyWasConsumed;
       
   737             }
       
   738             aknFepRepository->Get(KAknFepPredTxtFlag, aknRepositoryValue);
       
   739 
       
   740             delete aknFepRepository;
       
   741             aknFepRepository = NULL;
       
   742 
       
   743             if (aknRepositoryValue == 1)    // 1 means the predictive input is on
       
   744             {
       
   745                 iAvkonAppUi->KeySounds()->PlaySound(EAvkonSIDErrorTone);
       
   746                 return EKeyWasConsumed;
       
   747             }
       
   748             // now only nonpredictive textinput is left
       
   749             if (iThisMultitapKey != iLastMultitapKey) // different key tapped -> no multitap
       
   750             {
       
   751                 iAvkonAppUi->KeySounds()->PlaySound(EAvkonSIDErrorTone);
       
   752                 iThisMultitapKey = 0;
       
   753                 iLastMultitapKey = 0;
       
   754                 return EKeyWasConsumed;
       
   755             }
       
   756         }
       
   757     }
       
   758 
       
   759     if (aType != EEventKey)
       
   760     {
       
   761         return EKeyWasConsumed;
       
   762     }
       
   763 
       
   764 
       
   765     TKeyResponse response = EKeyWasNotConsumed;
       
   766     TBool isFocused = IsFocused();
       
   767 
       
   768     // If there is no focus textbox should not consume keys
       
   769     if (isFocused)
       
   770     {
       
   771         // Error tone playing case2:
       
   772         // Play error tone if TextBox/TextField is read-only or maximum length has been reached.
       
   773         // Here is handling of full keyboard keys(NOT 0...9) and all virtual keyboard keys
       
   774         // (camera and menu key not included).
       
   775         // (Note: Virtual keyboard sends only EEventKey type events, not up or down events)
       
   776         // (Note: Error tone is played when there is no text to be replaced i.e. no text has been painted)
       
   777         if (!iEdwinUtils->IsNavigationKey(aKeyEvent) && !iEdwinUtils->IsHotKeyL(aKeyEvent, iCoeEnv) && aKeyEvent.iCode != EKeyYes &&
       
   778                 (!iKeyEventsPending || (scanCode < KKeyQwerty0  || scanCode > KKeyQwerty9)) &&
       
   779                 (aKeyEvent.iCode != EKeyApplication0 && scanCode != EStdKeyApplication0 &&
       
   780                  aKeyEvent.iCode != EKeyApplication19 && scanCode != EStdKeyApplication19))
       
   781         {
       
   782             if (iEditor->IsReadOnly() || (Size() >= iMaxSize && aKeyEvent.iCode != EKeyBackspace))
       
   783             {
       
   784                 //SelectionLength() > 0 if text has been selected/painted
       
   785                 if (iEditor->SelectionLength() == 0)
       
   786                 {
       
   787                     iAvkonAppUi->KeySounds()->PlaySound(EAvkonSIDErrorTone);
       
   788                 }
       
   789                 response = iEditor->OfferKeyEventL(aKeyEvent,aType);
       
   790                 return response;
       
   791             }
       
   792         }
       
   793 
       
   794         TBool valid = EFalse;
       
   795 
       
   796         if (iEdwinUtils->IsNavigationKey(aKeyEvent) || iEdwinUtils->IsHotKeyL(aKeyEvent, iCoeEnv))
       
   797         {
       
   798             HBufC* oldText = GetTextL();
       
   799             CleanupStack::PushL(oldText);
       
   800             TCursorSelection sel = iEditor->Selection();
       
   801 
       
   802             response = CAknTextQueryDialog::OfferKeyEventL(aKeyEvent,aType);
       
   803             valid = iEdwinUtils->ConstraintsValidForText(iEditor->Text()?Read():TPtrC(),iConstraints,EFalse);
       
   804 
       
   805             if (!valid)
       
   806             {
       
   807                 SetTextL(*oldText);
       
   808                 iEditor->HandleTextChangedL();
       
   809                 iEditor->SetSelectionL(sel.iCursorPos,sel.iAnchorPos);
       
   810                 response = EKeyWasConsumed;
       
   811             }
       
   812             CleanupStack::PopAndDestroy(oldText);
       
   813 
       
   814             return response;
       
   815         }
       
   816         else
       
   817         {
       
   818             TBuf<1> key;
       
   819             key.Append(TChar(aKeyEvent.iCode));
       
   820             valid = iEdwinUtils->ConstraintsValidForInsertedTextL(iEditor->Text()?Read():TPtrC(),
       
   821                     key,
       
   822                     GetCaretPosition(),
       
   823                     iConstraints,
       
   824                     EFalse);
       
   825             if (valid)
       
   826             {
       
   827                 response = iEditor->OfferKeyEventL(aKeyEvent,aType);
       
   828             }
       
   829             else
       
   830             {
       
   831                 // If minus char was entered in full querty editor mode
       
   832                 if (IsConstraintSet(MMIDTextField::EDecimal) &&
       
   833                         (aType == EEventKey) && iEditor && !iEditor->IsReadOnly() &&
       
   834                         (TChar(aKeyEvent.iCode) == TChar('-') && scanCode != EStdKeyMinus))
       
   835                 {
       
   836                     CPlainText* res = iEditor->Text();
       
   837 
       
   838                     if (res && TChar(aKeyEvent.iCode) == TChar('-') &&
       
   839                             Size() < iMaxSize)
       
   840                     {
       
   841                         TInt textLength = Size();
       
   842                         res->InsertL(GetCaretPosition(), KMinusChar);
       
   843                         // notify editor about the text changes
       
   844                         iEditor->HandleTextChangedL();
       
   845                         TInt cursorPos = GetCaretPosition();
       
   846 
       
   847                         if (Size() < iMaxSize)
       
   848                         {
       
   849                             SetCursorPositionL(GetCaretPosition() + 1);
       
   850                         }
       
   851                         else if (cursorPos == (iMaxSize - 1) && cursorPos == textLength)
       
   852 
       
   853                         {
       
   854                             SetCursorPositionL(iMaxSize);
       
   855                         }
       
   856                         //Prevent changes that would result in an illegal string
       
   857                         HandleTextUpdateL(MEikEdwinObserver::EEventTextUpdate);
       
   858                     }
       
   859                 }
       
   860 
       
   861             }
       
   862             return response;
       
   863         }
       
   864     }
       
   865     return response;
       
   866 }
       
   867 
       
   868 #ifdef RD_SCALABLE_UI_V2
       
   869 void CMIDTextBoxQueryDialog::HandlePointerEventL(const TPointerEvent &aPointerEvent)
       
   870 {
       
   871     if (AknLayoutUtils::PenEnabled() && Rect().Contains(aPointerEvent.iPosition))
       
   872     {
       
   873         TBool consumed = STATIC_CAST(CMIDDisplayable*, iDisplayable)->TryDetectLongTapL(aPointerEvent);
       
   874         if (!consumed)
       
   875         {
       
   876             CAknTextQueryDialog::HandlePointerEventL(aPointerEvent);
       
   877         }
       
   878     }
       
   879 }
       
   880 #endif // RD_SCALABLE_UI_V2
       
   881 
       
   882 TCoeInputCapabilities CMIDTextBoxQueryDialog::InputCapabilities() const
       
   883 {
       
   884     TCoeInputCapabilities inputCapabilities(TCoeInputCapabilities::ENone, NULL,
       
   885                                             const_cast<CMIDTextBoxQueryDialog*>(this));
       
   886     inputCapabilities.MergeWith(iEditor->InputCapabilities());
       
   887     return inputCapabilities;
       
   888 }
       
   889 
       
   890 void CMIDTextBoxQueryDialog::HandleEdwinEventL(CEikEdwin* aEdwin, TEdwinEvent aEventType)
       
   891 {
       
   892     if (aEdwin != iEditor)
       
   893     {
       
   894         return;
       
   895     }
       
   896 
       
   897     if (aEventType == MEikEdwinObserver::EEventTextUpdate)
       
   898     {
       
   899         // handles clearing multitap counter
       
   900         if ((iLastMultitapKey != 0) && (iLastMultitapKey != iThisMultitapKey))
       
   901         {
       
   902             iLastMultitapKey = 0;
       
   903         }
       
   904         else
       
   905         {
       
   906             iThisMultitapKey = 0;
       
   907             iLastMultitapKey = 0;
       
   908         }
       
   909 
       
   910         HandleTextUpdateL(MEikEdwinObserver::EEventTextUpdate);
       
   911 
       
   912     }
       
   913 }
       
   914 
       
   915 void CMIDTextBoxQueryDialog::HandleTextUpdateL(TEdwinEvent aEventType)
       
   916 {
       
   917     if (aEventType == MEikEdwinObserver::EEventTextUpdate)
       
   918     {
       
   919         TBool textChanged = EFalse;
       
   920         HBufC* res = NULL;
       
   921         TRAPD(err, { res = GetTextL();});
       
   922         if (err != KErrNone || !res)
       
   923         {
       
   924             return;
       
   925         }
       
   926         CleanupStack::PushL(res);
       
   927 
       
   928         // in DECIMAL mode, don't allow changes that would result
       
   929         // in an illegal string;
       
   930         //  1) if there is a minus, it must be the first character
       
   931         //  2) there can be at most one decimal separator
       
   932         if ((aEventType == EEventTextUpdate) && ((iConstraints
       
   933                 & MMIDTextField::EConstraintMask) == MMIDTextField::EDecimal))
       
   934         {
       
   935             TInt illegalCharPos = -1;
       
   936             TPtr16 ptr = res->Des();
       
   937             TInt minusPos = ptr.LocateReverse(TChar('-'));
       
   938             TInt pointPosL = ptr.Locate(iDecimalSeparator);
       
   939             TInt pointPosR = ptr.LocateReverse(iDecimalSeparator);
       
   940             TInt cursorPos = GetCaretPosition();
       
   941             TInt endCursorPos = cursorPos;
       
   942 
       
   943             // check if minus sign is inserted on incorrect place
       
   944             // (not at the beginning)
       
   945             if ((minusPos != KErrNotFound) && (minusPos != 0))
       
   946             {
       
   947                 // check if minus sign isn't inserted twice
       
   948                 if (minusPos != ptr.Locate(TChar('-')))
       
   949                 {
       
   950                     illegalCharPos = minusPos;
       
   951                 }
       
   952                 // insert minus char at the beginning of decimal field
       
   953                 else
       
   954                 {
       
   955                     ptr.Delete(minusPos, 1);
       
   956                     ptr.Insert(0, KMinusChar);
       
   957                     minusPos = 0;
       
   958                     iStrict = EFalse;
       
   959 
       
   960                     // Decimal separator was inserted twice and minus
       
   961                     // was next character in text. Minus was just set as first
       
   962                     // character - so in fact we have two decimal separators
       
   963                     // after minus character - this is not allowed,
       
   964                     // delete extra character
       
   965                     if (pointPosL != pointPosR && pointPosL == 0 &&
       
   966                             minusPos == pointPosL)
       
   967                     {
       
   968                         // Delete both decimal separator characters
       
   969                         // and place new decimal separator in correct position
       
   970                         ptr.Delete(pointPosR, 1);
       
   971                         ptr.Delete((pointPosL + 1), 1);
       
   972                         ptr.Insert(1, KFullStopChar);
       
   973                     }
       
   974                     SetTextL(*res);
       
   975                     textChanged = ETrue;
       
   976 
       
   977                     // Set correct cusros possition
       
   978                     if (pointPosL == 0 && minusPos == pointPosL)
       
   979                     {
       
   980                         endCursorPos = (pointPosL + 1);
       
   981                     }
       
   982                 }
       
   983             }
       
   984 
       
   985             // Locate decimal separator again
       
   986             pointPosL = ptr.Locate(iDecimalSeparator);
       
   987             pointPosR = ptr.LocateReverse(iDecimalSeparator);
       
   988 
       
   989             if ((minusPos != KErrNotFound) && (pointPosL == 0))
       
   990             {
       
   991                 illegalCharPos = pointPosL;
       
   992             }
       
   993             else if (pointPosL != pointPosR)
       
   994             {
       
   995                 illegalCharPos = pointPosR;
       
   996             }
       
   997 
       
   998             // if minus or dot/comma char is displayed more than once
       
   999             if (illegalCharPos >= 0)
       
  1000             {
       
  1001                 // deleting second minus or dot/comma char
       
  1002                 // and set cursor position on the right place
       
  1003                 ptr.Delete(illegalCharPos, 1);
       
  1004                 iStrict = EFalse;
       
  1005                 SetTextL(*res);
       
  1006                 textChanged = ETrue;
       
  1007                 if (cursorPos >= 1)
       
  1008                 {
       
  1009                     if (cursorPos == (illegalCharPos + 1))
       
  1010                     {
       
  1011                         cursorPos--;
       
  1012                     }
       
  1013 
       
  1014                     endCursorPos = cursorPos;
       
  1015                 }
       
  1016             }
       
  1017             SetCursorPositionL(endCursorPos);
       
  1018         }
       
  1019         else if (((iConstraints &
       
  1020                    MMIDTextField::EConstraintMask) == MMIDTextField::EMailAddr) ||
       
  1021                  ((iConstraints &
       
  1022                    MMIDTextField::EConstraintMask) == MMIDTextField::EUrl))
       
  1023         {
       
  1024             // In EMAIL and URL mode, don't allow changes that would result
       
  1025             // in an illegal string; if there is '/n' or '/f', and line breaks
       
  1026             // are not supported, chars need to be changed to space
       
  1027             // SetText function before actual text change checks if line
       
  1028             // breaks are not supported
       
  1029             TPtr16 text = res->Des();
       
  1030             TInt tmpPos;
       
  1031 
       
  1032             if ((text.Locate(TChar('\n'))) >=0 ||
       
  1033                     (text.Locate(TChar('\f'))) >=0)
       
  1034             {
       
  1035                 tmpPos = GetCaretPosition();
       
  1036                 SetTextL(*res);
       
  1037                 SetCursorPositionL(tmpPos);
       
  1038             }
       
  1039 
       
  1040             textChanged = ETrue;
       
  1041         }
       
  1042         CleanupStack::Pop(res);
       
  1043         delete res;
       
  1044 
       
  1045         // if there were any modifications the text is updated
       
  1046         if (textChanged)
       
  1047         {
       
  1048             iEditor->HandleTextChangedL();
       
  1049         }
       
  1050     }
       
  1051 }
       
  1052 
       
  1053 void CMIDTextBoxQueryDialog::GetCaptionForFep(TDes& aCaption) const
       
  1054 {
       
  1055     aCaption = Prompt();
       
  1056 }
       
  1057 
       
  1058 void CMIDTextBoxQueryDialog::ProcessModifiers()
       
  1059 {
       
  1060     // set general edwin attributes according to TextBox constraints
       
  1061     iEditor->SetReadOnly(iConstraints & MMIDTextField::EUneditable);
       
  1062 }
       
  1063 
       
  1064 void CMIDTextBoxQueryDialog::ShowL(TBool aShow)
       
  1065 {
       
  1066     if (aShow != iShowing)
       
  1067     {
       
  1068         if (aShow)
       
  1069         {
       
  1070             iShowing = ETrue;
       
  1071 
       
  1072 #ifdef RD_SCALABLE_UI_V2
       
  1073             SetPointerCapture(ETrue);
       
  1074 #endif
       
  1075             RouseSleepingDialog();
       
  1076 
       
  1077             UpdateInitialInputModes();
       
  1078         }
       
  1079         else
       
  1080         {
       
  1081             // avoid po-pup dialog box blinking
       
  1082             MakeVisible(EFalse);
       
  1083 
       
  1084             ExitSleepingDialog();
       
  1085 #ifdef RD_SCALABLE_UI_V2
       
  1086             SetPointerCapture(EFalse);
       
  1087 #endif
       
  1088 
       
  1089             iShowing = EFalse; //attention: iShowing must be true when dismissing
       
  1090             // a dialog or else MakeVisible() won't execute and
       
  1091             // we won't update the fader's stack, @see MakeVisible()
       
  1092 
       
  1093         }
       
  1094 
       
  1095         UpdateCbasL();
       
  1096     }
       
  1097 }
       
  1098 
       
  1099 void CMIDTextBoxQueryDialog::SetTextWithNewConstraintsL(HBufC* aText)
       
  1100 {
       
  1101     // If the current contents of the TextBox do not match the new constraints,the
       
  1102     // contents are set to empty, except for a PHONENUMBER which only has the
       
  1103     // invalid characters removed. Otherwise, set the text as given.
       
  1104     if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber)
       
  1105     {
       
  1106         iEdwinUtils->RemoveNonPhoneNumberChars(aText);
       
  1107         SetTextL(*aText);
       
  1108     }
       
  1109     else if (!iEdwinUtils->ConstraintsValidForText(aText->Des(),
       
  1110              iConstraints & MMIDTextField::EConstraintMask,
       
  1111              ETrue))
       
  1112     {
       
  1113         SetTextL(KNullDesC);
       
  1114     }
       
  1115     else
       
  1116     {
       
  1117         SetTextL(*aText);
       
  1118     }
       
  1119 }
       
  1120 
       
  1121 void  CMIDTextBoxQueryDialog::UpdateLeftSoftKeyL()
       
  1122 {
       
  1123 }
       
  1124 
       
  1125 TBool CMIDTextBoxQueryDialog::OkToExitL(TInt aCommandId)
       
  1126 {
       
  1127     TInt offset = iDisplayable->MainCommandList()->CommandOffset();
       
  1128     if (aCommandId ==EEikBidCancel)
       
  1129     {
       
  1130         return ETrue;
       
  1131     }
       
  1132     if (aCommandId == EAknSoftkeyOptions)   // 3000
       
  1133     {
       
  1134         iDisplayable->MenuHandler()->ProcessCommandL(EAknSoftkeyOptions);
       
  1135         SetFocus(EFalse);
       
  1136     }
       
  1137     else if (aCommandId - offset < 0)   // aCommandId value is over 3000 - used by MSK
       
  1138     {
       
  1139         iDisplayable->ProcessCommandL(aCommandId);
       
  1140     }
       
  1141     else // aCommandId value is 7000 and over - used by LSK, RSK and EnterKey
       
  1142     {
       
  1143         CMIDCommand* tempCmd = NULL;
       
  1144         CMIDCommand* command = NULL;
       
  1145         TBool isMaped = EFalse;
       
  1146         TInt mapedCnt = ENone;
       
  1147         TInt mapedId = ENone;
       
  1148 
       
  1149         // number of all commands
       
  1150         TInt numberOfCommands = iDisplayable->CommandCount();
       
  1151         // number of Ok and Item commands
       
  1152         TInt numberOfOkOptionsCommands = iDisplayable->NumCommandsForOkOptionsMenu();
       
  1153         // command ID which is get from aCommandId
       
  1154         TInt commandId = aCommandId - offset;
       
  1155 
       
  1156         if (numberOfCommands > 0)
       
  1157         {
       
  1158             // Go through every midlet command, and save its ID if maped
       
  1159             // and also count maped commands.
       
  1160             for (TInt i = 0; i < numberOfCommands; i++)
       
  1161             {
       
  1162                 tempCmd = iDisplayable->MainCommandList()->At(i).iCommand;
       
  1163                 if (tempCmd->IsMappedToSoftKey())
       
  1164                 {
       
  1165                     mapedId = i;
       
  1166                     isMaped = ETrue;
       
  1167                     mapedCnt++;
       
  1168                 }
       
  1169             }
       
  1170 
       
  1171             // If there are more than one maped command (LSK & RSK maped)
       
  1172             // or maped command is different than commandId (EnterKey used),
       
  1173             // set CMIDCommand command with this command, which index
       
  1174             // is the same as commandId value.
       
  1175             if (mapedCnt > 1 || mapedId != commandId)
       
  1176             {
       
  1177                 command = iDisplayable->MainCommandList()->At(commandId).iCommand;
       
  1178             }
       
  1179             else // Else if there are one or zero command maped.
       
  1180             {
       
  1181                 if (isMaped)   // One command maped.
       
  1182                 {
       
  1183                     command = iDisplayable->MainCommandList()->At(mapedId).iCommand;
       
  1184                 }
       
  1185                 else // Zero commands maped.
       
  1186                 {
       
  1187                     command = iDisplayable->MainCommandList()->At(0).iCommand;
       
  1188                 }
       
  1189             }
       
  1190 
       
  1191             // type of the command
       
  1192             TInt commandType = command->CommandType();
       
  1193 
       
  1194             // If there aren't any EExit, EBack, ECancel and EStop
       
  1195             // command mapped and there are still some commands
       
  1196             // show menu, else process with maped command.
       
  1197             if (commandType != MMIDCommand::EExit &&
       
  1198                     commandType != MMIDCommand::EBack &&
       
  1199                     commandType != MMIDCommand::ECancel &&
       
  1200                     commandType != MMIDCommand::EStop &&
       
  1201                     numberOfOkOptionsCommands > 1)
       
  1202             {
       
  1203                 iDisplayable->MenuHandler()->ShowMenuL(CMIDMenuHandler::EOkMenu);
       
  1204             }
       
  1205             else
       
  1206             {
       
  1207                 iDisplayable->ProcessCommandL(aCommandId);
       
  1208             }
       
  1209         }
       
  1210     }
       
  1211 
       
  1212     //The dialog can only be dismissed java side or else we'll end
       
  1213     //up with the TextBox displayed and no dialog
       
  1214     return EFalse;
       
  1215 }
       
  1216 
       
  1217 void CMIDTextBoxQueryDialog::SetEditorL()
       
  1218 {
       
  1219     iEditor = (CEikEdwin*)QueryControl()->ControlByLayoutOrNull(EDataLayout);
       
  1220     iEditor->SetAknEditorFlags(CEikEdwin::EZeroEnumValue);
       
  1221 
       
  1222     TBool singleLineEditor = IsConstraintSet(MMIDTextField::EMailAddr)
       
  1223                              || IsConstraintSet(MMIDTextField::EUrl)
       
  1224                              || (iConstraints & MMIDTextField::EPassword);
       
  1225 
       
  1226     if (((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EAny)
       
  1227             && !(iConstraints & MMIDTextField::EPassword))
       
  1228     {
       
  1229         iEditor->SetAknEditorFlags(EAknEditorFlagEnableScrollBars | iEditor->AknEdwinFlags());
       
  1230     }
       
  1231 
       
  1232     AknEditUtils::ConstructEditingL(iEditor,                        // aEdwin
       
  1233                                     iMaxSize,                      // aEditingSpace
       
  1234                                     (singleLineEditor ? 1 : 0),    // aEditingWindow
       
  1235                                     EAknEditorCharactersLowerCase, // aCharacterCase
       
  1236                                     EAknEditorAlignLeft,           // aJustification
       
  1237                                     ETrue,                         // aAllowedToMoveInsertionPoint
       
  1238                                     ETrue,                         // aCursorYesNo
       
  1239                                     EFalse);                       // aOverflowYesNo
       
  1240 
       
  1241 
       
  1242     if (iConstraints & MMIDTextField::EPassword)
       
  1243     {
       
  1244         TUint32 userFlags = iEditor->UserFlags();
       
  1245         iEditor->SetAknEditorFlags(userFlags |= CEikEdwin::EUserSuppliedText);
       
  1246         CreatePasswordTextL();
       
  1247     }
       
  1248 
       
  1249     HBufC* buf = GetTextL();
       
  1250     CleanupStack::PushL(buf);
       
  1251     if (buf)
       
  1252     {
       
  1253         CMIDUtils::MapJavaToETextChars(buf);
       
  1254         if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber)
       
  1255         {
       
  1256             iEdwinUtils->RemoveNonPhoneNumberChars(buf);
       
  1257         }
       
  1258         SetTextL(*buf);
       
  1259     }
       
  1260     CleanupStack::PopAndDestroy(buf);
       
  1261 
       
  1262     iEditor->CreateTextViewL();
       
  1263     ProcessModifiers();
       
  1264     SetFEPModeAndCharFormat();
       
  1265     iEditor->AddEdwinObserverL(this);
       
  1266 
       
  1267     CreateNonMidletCommandsL();
       
  1268 
       
  1269     if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::ENonPredictive)
       
  1270     {
       
  1271         SetPredictiveTextInputPermitted(EFalse);
       
  1272     }
       
  1273     else
       
  1274     {
       
  1275         SetPredictiveTextInputPermitted(ETrue);
       
  1276     }
       
  1277     // Publish MIDP constraints via input capabilities of the CEikEdwin
       
  1278     // The information is needed by chinese VKB/HWR system that adjusts its behavior
       
  1279     // based on MIDP constraints (most notably by checking if the field is a PASSWORD field).
       
  1280     TCoeInputCapabilities inputCapabilities = InputCapabilities();
       
  1281     if (inputCapabilities != TCoeInputCapabilities::ENone)
       
  1282     {
       
  1283         MObjectProvider* mop = inputCapabilities.ObjectProvider();
       
  1284         if (mop)
       
  1285         {
       
  1286             CAknExtendedInputCapabilities* extendedInputCapabilities = NULL;
       
  1287             extendedInputCapabilities = mop->MopGetObject(extendedInputCapabilities);
       
  1288             if (extendedInputCapabilities)
       
  1289             {
       
  1290                 extendedInputCapabilities->SetMIDPConstraints(iConstraints);
       
  1291             }
       
  1292         }
       
  1293     }
       
  1294 
       
  1295     iThisMultitapKey = 0;   // reset key counter
       
  1296     iLastMultitapKey = 0;
       
  1297     
       
  1298     if(iEditor->ScrollBarFrame())
       
  1299     {
       
  1300         iEditor->ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff, CEikScrollBarFrame::EOff);
       
  1301     }
       
  1302 }
       
  1303 
       
  1304 TBool CMIDTextBoxQueryDialog::Showing()
       
  1305 {
       
  1306     return iShowing;
       
  1307 }
       
  1308 
       
  1309 TInt CMIDTextBoxQueryDialog::Constraints()
       
  1310 {
       
  1311     return iConstraints;
       
  1312 }
       
  1313 
       
  1314 void CMIDTextBoxQueryDialog::UpdateCbasL()
       
  1315 {
       
  1316     if (iShowing)
       
  1317     {
       
  1318         iDisplayable->SetCba(&ButtonGroupContainer());
       
  1319         iDisplayable->InitializeCbasL();
       
  1320         CCoeControl* cba = ButtonGroupContainer().ButtonGroup()->AsControl();
       
  1321         cba->DrawableWindow()->SetOrdinalPosition(0);
       
  1322         cba->MakeVisible(ETrue);
       
  1323         cba->DrawNow();
       
  1324     }
       
  1325     else
       
  1326     {
       
  1327         iDisplayable->SetCba(iDisplayable->MenuHandler()->Cba());
       
  1328     }
       
  1329 }
       
  1330 
       
  1331 TBool CMIDTextBoxQueryDialog::IsNumberConversionNeeded()
       
  1332 {
       
  1333     return iEdwinUtils->IsNumberConversionNeeded(GetConstraints());
       
  1334 }
       
  1335 
       
  1336 void CMIDTextBoxQueryDialog::HandleMinusCharEventL(MEikEdwinObserver::TEdwinEvent aEventType)
       
  1337 {
       
  1338     if ((aEventType == MEikEdwinObserver::EEventTextUpdate) && ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::ENumeric))
       
  1339     {
       
  1340         CPlainText* res = iEditor->Text();
       
  1341         TBuf<1> firstChar;
       
  1342         if (Size() != 0)
       
  1343         {
       
  1344             res->Extract(firstChar,  0, 1);
       
  1345         }
       
  1346         TInt cursorPos = GetCaretPosition();
       
  1347         //toggle '-' char in the first position
       
  1348         TInt pos = firstChar.Locate(TChar('-'));
       
  1349         if (pos == KErrNotFound)
       
  1350         {
       
  1351             if (Size() < iMaxSize)
       
  1352             {
       
  1353                 res->InsertL(0, KMinusChar);
       
  1354                 cursorPos++;
       
  1355             }
       
  1356             else
       
  1357             {
       
  1358                 //play error sound if text limit is to be exceeded
       
  1359                 iAvkonAppUi->KeySounds()->PlaySound(EAvkonSIDErrorTone);
       
  1360             }
       
  1361         }
       
  1362         else
       
  1363         {
       
  1364             TBool deletion = res->DeleteL(0,1);
       
  1365             if (cursorPos >= 1)
       
  1366             {
       
  1367                 cursorPos--;
       
  1368             }
       
  1369         }
       
  1370         iEditor->HandleTextChangedL(); // notify editor about the text changes
       
  1371         SetCursorPositionL(cursorPos);
       
  1372     }
       
  1373 }
       
  1374 
       
  1375 TPtrC CMIDTextBoxQueryDialog::Read() const
       
  1376 {
       
  1377     if (iConstraints & MMIDTextField::EPassword)
       
  1378     {
       
  1379         return static_cast<CPasswordBoxGlobalText*>(iEditor->Text())->ClearText();
       
  1380     }
       
  1381     else
       
  1382     {
       
  1383         return iEditor->Text()->Read(0,iEditor->TextLength());
       
  1384     }
       
  1385 }
       
  1386 
       
  1387 /** Create non-midlet commands according to the constraints and add them
       
  1388 to either the displayable or to the item. Commands will be processed in ProcessCommandL(). */
       
  1389 void CMIDTextBoxQueryDialog::CreateNonMidletCommandsL()
       
  1390 {
       
  1391     if (((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber) && !(iConstraints & MMIDTextField::EUneditable))
       
  1392     {
       
  1393         AddCommandToEdwinL(R_MIDP_PB_FETCH_NUMBER_SHORT_COMMAND_TEXT, R_MIDP_PB_FETCH_NUMBER_COMMAND_TEXT, CMIDEdwinUtils::EMenuCommandFetchPhoneNumber);
       
  1394         AddCommandToEdwinL(R_MIDP_CREATE_CALL_SHORT_COMMAND_TEXT, R_MIDP_CREATE_CALL_COMMAND_TEXT, CMIDEdwinUtils::EMenuCommandCreatePhoneCall);
       
  1395     }
       
  1396 
       
  1397     if (((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber) && (iConstraints & MMIDTextField::EUneditable))
       
  1398     {
       
  1399         AddCommandToEdwinL(R_MIDP_CREATE_CALL_SHORT_COMMAND_TEXT, R_MIDP_CREATE_CALL_COMMAND_TEXT, CMIDEdwinUtils::EMenuCommandCreatePhoneCall);
       
  1400     }
       
  1401 
       
  1402     if (((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EMailAddr) && !(iConstraints & MMIDTextField::EUneditable))
       
  1403     {
       
  1404         AddCommandToEdwinL(R_MIDP_PB_FETCH_EMAIL_SHORT_COMMAND_TEXT, R_MIDP_PB_FETCH_EMAIL_COMMAND_TEXT, CMIDEdwinUtils::EMenuCommandFetchEmailAddress);
       
  1405     }
       
  1406 }
       
  1407 
       
  1408 /**
       
  1409 Creates and adds new command to edwin based on shot & long label resource ids
       
  1410 and other parameters.
       
  1411 */
       
  1412 void CMIDTextBoxQueryDialog::AddCommandToEdwinL(TInt aCommandResIdShort,
       
  1413         TInt aCommandResIdLong,
       
  1414         TInt aCommandId)
       
  1415 {
       
  1416     TBuf<64> shortLabel;
       
  1417     iEikonEnv->ReadResourceL(shortLabel, aCommandResIdShort);
       
  1418     TBuf<64> longLabel;
       
  1419     iEikonEnv->ReadResourceL(longLabel, aCommandResIdLong);
       
  1420 
       
  1421     MMIDCommand* cmd = CMIDCommand::NewL(shortLabel, longLabel, MMIDCommand::EItem, 0, aCommandId);
       
  1422     CleanupStack::PushL(cmd);
       
  1423 
       
  1424     STATIC_CAST(CMIDCommand*,cmd)->SetObserver(this);
       
  1425 
       
  1426     AddCommandToEdwinL(*cmd);
       
  1427     CleanupStack::Pop(cmd);
       
  1428 }
       
  1429 
       
  1430 /**
       
  1431 Creates and adds new command to edwin, short label is the same as long label.
       
  1432 */
       
  1433 void CMIDTextBoxQueryDialog::AddCommandToEdwinL(TInt aCommandResId,
       
  1434         TInt aCommandId)
       
  1435 {
       
  1436     AddCommandToEdwinL(aCommandResId, aCommandResId, aCommandId);
       
  1437 }
       
  1438 
       
  1439 /** This method is called from the destructor and removes
       
  1440     the commands added by CreateNonMidletCommandsL(). To do
       
  1441     this we examine cmds on the list (either of the displayable
       
  1442     or the item as applicable) and remove those whose observer is us.
       
  1443     */
       
  1444 void CMIDTextBoxQueryDialog::RemoveNonMidletCommands()
       
  1445 {
       
  1446     CMIDCommandList* list = NULL;
       
  1447     if (iDisplayable)
       
  1448     {
       
  1449         list = STATIC_CAST(CMIDDisplayable*, iDisplayable)->MainCommandList();
       
  1450     }
       
  1451 
       
  1452     if (!list)
       
  1453     {
       
  1454         return;
       
  1455     }
       
  1456 
       
  1457     for (TInt i = 0; i < list->Count(); i++)
       
  1458     {
       
  1459         CMIDCommand* cmd = list->At(i).iCommand;
       
  1460         if (cmd && (cmd->Observer() == this))
       
  1461         {
       
  1462             list->Remove(cmd);
       
  1463             cmd->Dispose();
       
  1464             i--;
       
  1465         }
       
  1466     }
       
  1467 }
       
  1468 
       
  1469 void CMIDTextBoxQueryDialog::AddCommandToEdwinL(MMIDCommand& aCommand)
       
  1470 {
       
  1471     STATIC_CAST(CMIDDisplayable*, iDisplayable)->AddCommandL(&aCommand);
       
  1472 }
       
  1473 
       
  1474 void CMIDTextBoxQueryDialog::CreatePhoneCallL()
       
  1475 {
       
  1476     iEdwinUtils->CreatePhoneCallL(Size(), CCoeEnv::Static()->WsSession(), iEditor);
       
  1477 }
       
  1478 
       
  1479 void CMIDTextBoxQueryDialog::CreatePasswordTextL()
       
  1480 {
       
  1481     CGlobalText* oldGText = STATIC_CAST(CGlobalText*,iEditor->Text());
       
  1482     CPasswordBoxGlobalText* text = new(ELeave) CPasswordBoxGlobalText
       
  1483     (oldGText->GlobalParaFormatLayer(),oldGText->GlobalCharFormatLayer(),*iEditor);
       
  1484     CleanupStack::PushL(text);
       
  1485     text->ConstructL();
       
  1486     CleanupStack::Pop(text);
       
  1487 
       
  1488     CPlainText*  editorText = iEditor->Text();
       
  1489     delete editorText;
       
  1490     editorText = NULL;
       
  1491 
       
  1492     iEditor->SetDocumentContentL(*text,CEikEdwin::EUseText);
       
  1493 }
       
  1494 
       
  1495 void CMIDTextBoxQueryDialog::UpdateInitialInputModes()
       
  1496 {
       
  1497     // when becoming the current Displayable, set editor input mode
       
  1498     // to the one set by SetInitialInputModeL
       
  1499     if (((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EAny ||
       
  1500             (iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EMailAddr ||
       
  1501             (iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EUrl))
       
  1502     {
       
  1503         if (iInitialCurrentLanguage)
       
  1504         {
       
  1505             iEditor->SetAknEditorLocalLanguage(iInitialCurrentLanguage);
       
  1506             if (iInitialCurrentInputMode == 0)
       
  1507             {
       
  1508                 // clears any number mode used previously
       
  1509                 iEditor->SetAknEditorCurrentInputMode(EAknEditorNullInputMode);
       
  1510             }
       
  1511         }
       
  1512 
       
  1513         if (iInitialCurrentInputMode)
       
  1514         {
       
  1515             iEditor->SetAknEditorCurrentInputMode(iInitialCurrentInputMode);
       
  1516         }
       
  1517 
       
  1518         if (iInitialCurrentCase)
       
  1519         {
       
  1520             if ((iConstraints & MMIDTextField::EPassword ||
       
  1521                     iConstraints & MMIDTextField::EMailAddr ||
       
  1522                     iConstraints & MMIDTextField::EUrl) &&
       
  1523                     iInitialCurrentCase == EAknEditorTextCase)
       
  1524             {
       
  1525                 // Text case is not used in passwords, emailaddrs and urls
       
  1526                 iInitialCurrentCase = EAknEditorLowerCase;
       
  1527             }
       
  1528             iEditor->SetAknEditorCurrentCase(iInitialCurrentCase);
       
  1529             iEditor->SetAknEditorCase(iInitialCurrentCase);
       
  1530         }
       
  1531     }
       
  1532 }
       
  1533 
       
  1534 TTypeUid::Ptr CMIDTextBoxQueryDialog::MopSupplyObject(TTypeUid aId)
       
  1535 {
       
  1536     TTypeUid::Ptr ret = TTypeUid::Null();
       
  1537 
       
  1538     if (aId.iUid == CEikMenuBar::ETypeId)
       
  1539     {
       
  1540         if (iDisplayable && iDisplayable->MenuHandler())
       
  1541         {
       
  1542             // number of all commands
       
  1543             TInt numberOfCommands = iDisplayable->CommandCount();
       
  1544 
       
  1545             // If there are no commands we should not call SupplyMopObject
       
  1546             if (numberOfCommands > 0)
       
  1547             {
       
  1548                 ret = SupplyMopObject(aId,
       
  1549                                       iDisplayable->MenuHandler()->Cba(),
       
  1550                                       iDisplayable->MenuHandler()->MenuBar());
       
  1551             }
       
  1552         }
       
  1553     }
       
  1554 
       
  1555     if (!ret.Pointer())
       
  1556     {
       
  1557         ret = CAknTextQueryDialog::MopSupplyObject(aId);
       
  1558     }
       
  1559     return ret;
       
  1560 }
       
  1561 
       
  1562 /* HandleResourceChange
       
  1563  *
       
  1564  * This method is called after a resource change event, for example after
       
  1565  * screen dynamic resolution change.
       
  1566  */
       
  1567 void CMIDTextBoxQueryDialog::HandleResourceChange(TInt aType)
       
  1568 {
       
  1569     CAknTextQueryDialog::HandleResourceChange(aType);
       
  1570     TRAP_IGNORE(UpdateScrollBarPositionL());
       
  1571 }
       
  1572 
       
  1573 /* UpdateScrollBarPositionL
       
  1574  *
       
  1575  * This method is called for placing scrollbar to correct place in edwin
       
  1576  */
       
  1577 void CMIDTextBoxQueryDialog::UpdateScrollBarPositionL()
       
  1578 {
       
  1579     if (iEditor && iEditor->TextLayout())
       
  1580     {
       
  1581         TInt numLines = iEditor->TextLayout()->NumFormattedLines();
       
  1582         if (numLines == iEditor->MaximumHeightInLines())
       
  1583         {
       
  1584             if (iEditor->ScrollBarFrame())
       
  1585             {
       
  1586                 iEditor->ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff, CEikScrollBarFrame::EOff);
       
  1587             }
       
  1588         }
       
  1589         else if (numLines > iEditor->MaximumHeightInLines())
       
  1590         {
       
  1591             if (!iEditor->ScrollBarFrame())
       
  1592             {
       
  1593                 iEditor->CreatePreAllocatedScrollBarFrameL();
       
  1594                 iEditor->ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto);
       
  1595             }
       
  1596             TRect editorRect = iEditor->Rect();
       
  1597             if (iEditor->ScrollBarFrame()->VerticalScrollBar())
       
  1598             {
       
  1599                 editorRect.SetWidth(editorRect.Width() - iEditor->ScrollBarFrame()->VerticalScrollBar()->ScrollBarBreadth());
       
  1600                 iEditor->SetRect(editorRect);
       
  1601             }
       
  1602         }
       
  1603     }
       
  1604 }
       
  1605 
       
  1606 void CMIDTextBoxQueryDialog::PreLayoutDynInitL()
       
  1607 {
       
  1608     CAknQueryDialog::PreLayoutDynInitL();
       
  1609     UpdateLeftSoftKeyL();
       
  1610 }
       
  1611 // End of file