PTI Engine API: Using PtiEngine API

The most basic parameter of PtiEngine operation is the currently set language and input mode. Only a few utility methods function without setting language and input mode; others will fail with KErrNoActiveLanguage.

PtiEngine is designed to be flexible and extensible, as it must accommodate various combinations of languages and input modes. However, not all combinations of languages and input modes are meaningful; also, availability of languages and input modes depends on the actual configuration and installed plug-ins. Unsupported or unavailable operations are typically indicated by returning NULL objects or KErrNotSupported error code. When using PtiEngine API, one must always properly check error conditions and never assume availability of certain functionality.

Initializing PtiEngine

Creating an instance of PtiEngine is an expensive operation. For this reason, having it as a member should be preferred over temporary variable use. In the examples below, however, temporary variable is used to keep sample code compact.

Creating an engine instance initializes the default multitapping and QWERTY input modes, and the numeric language. Then all core plug-ins are loaded an initialized.

// Create an engine instance
MPtiEngine* eng = CPtiEngine::NewL( ETrue );
CleanupStack::PushL( eng );

Activating language

After a language is activated, the engine is ready to use.

TInt err;
// Activate a language in default input mode
err = eng->ActivateLanguageL( ELangEnglish );
// Activate a language, in specified input mode
err = eng->ActivateLanguage( ELangEnglish, EPtiEngineMultitapping );

Closing current language

After the current language is closed, there is no active language and most PtiEngine API methods return an error until ActivateLanguageL is called again. Core objects for active language are asked to release related resources.

eng-> CloseCurrentLanguageL();

Setting input mode

Availability of input modes depends on the actual configuration and installed plug-ins. Return value KErrNotSupported indicates that the current language does not support the given input mode.

if ( KErrNone == eng->SetInputMode( EPtiEnginePredictive ) )
    {
    //...
    }

Checking language and input mode

The following code snippet checks whether predictive Norwegian is supported.

MPtiLanguage* lang = eng->GetLanguage( ELangNorwegian );
if ( lang && lang->HasInputMode( EPtiEnginePredictive )
    {
    //...
    }

Getting current language

MPtiLanguage* lang = eng->CurrentLanguage();

Inputting text

Inputting text is achieved by appending key presses. Depending on the input mode, PtiEngine provides the resulting text, or result candidate list.

This chapter describes input modes and their basic functionality. Availability of these input modes depends on the actual configuration and installed plug-ins.

Multitapping

The multitapping input mode (EPtiEngineMultitapping) implements the basic multitapping input for ITU-T keyboard. This is the traditional text input mode, where the user may need to press one key several times to input the requested character. The basic use case for inputting one character is presented in Figure 2.

Figure 2: Basic multitapping

eng->ActivateLanguageL( ELangEnglish, EPtiEngineMultitapping );
eng->AppendKeyPress( EPtiKey3 );
eng->AppendKeyPress( EPtiKey6 );
eng->AppendKeyPress( EPtiKey6 );
eng->AppendKeyPress( EPtiKey6 );
eng->AppendKeyPress( EPtiKey4 );
TBuf<100> temp;
temp.Copy( eng->CurrentWord() );  // At this point temp would contain 
                                  // word "dog".

Numeric

The numeric input mode (EPtiEngineNumeric) is a basic input mode for numeric data. It works exactly like the multitapping mode, except that key mappings are not loaded from the resource file, but are always available in memory. This input mode is always available for each language. In addition there is a special language object called numeric language. See Numeric language for more information.

Predictive

The predictive input mode (EPtiEngineMultitapping) implements the predictive text. In this input, instead of cycling through characters bound to keys, the user presses each key only once and PtiEngine tries to guess which word the user is inputting. Usually PtiEngine returns several candidates for each input sequence. The basic use case for entering one key and returning the topmost candidate for it is presented in Figure 3.

Figure 3: Basic predictive input

eng->ActivateLanguageL( ELangEnglish, EPtiEnginePredicitve );
eng->AppendKeyPress( EPtiKey8 );
eng->AppendKeyPress( EPtiKey4 );
eng->AppendKeyPress( EPtiKey4 );
eng->AppendKeyPress( EPtiKey7 );
TBuf<100> temp;
temp.Copy( eng->CurrentWord() );   // At this point temp would contain 
                                   // (depending on the underlying
                                   // core) word "this".
if ( eng->NumberOfCandidates() > 1 )
    {
    temp.Copy( eng->NextCandidate() ); // Move on to next candidate.
    }

Word completion

The word completion input mode (EPtiEngineWordCompletion) works exactly like the predictive input mode, except that output words can contain more characters than the number of key presses in the current input sequence.

Pinyin

The Pinyin input mode (EPtiEnginePinyin) is a Chinese input method where the user inputs phonetic spellings for Chinese characters using Latin characters. Key presses produce a candidate list consisting of Pinyin spellings. The user selects one of the Pinyin spellings, which is then fed again to the prediction engine. The result is a set of Chinese candidate words. Basic Pinyin input functionality is presented in Figure 4.

Figure 4: Pinyin input

Stroke

The stroke input mode (EPtiEngineStroke) is a Chinese input method where the user builds Chinese characters from a set of strokes. Key presses produce a string of stroke characters, which is passed to prediction engine. The list of Chinese candidate characters is produced as a result. S60 supports the 6-stroke version.

Zhuyin

The Zhuyin input mode (EPtiEngineZhuyin) is a Chinese input method, where the user enters a string of Zhuyin symbols. That string is passed to prediction engine and a list of Chinese candidate characters is produced as a result. Since there are more Zhuyin symbols than keys in a normal ITU-T keypad, Zhuyin symbols are entered by using the multitapping method. Illegal Zhuyin characters are rejected and the user is allowed to enter only valid combinations.

Pinyin phrase

The Pinyin phrase input (EPtiEnginePinyinByPhrase) is essentially the same as the regular Pinyin input, except that the user may enter several Pinyin words. Candidates can be fetched either by using the GetcandidatePage() method (as with regular Pinyin) or by using GetChinesePhraseCandidates(). The latter method returns all candidates in a single table.

Zhuyin phrase

The Zhuyin phrase input (EPtiEngineZhuyinByPhrase) is essentially the same as the regular Zhuyin input, except that Zhuyin symbols are entered by using QWERTY keyboard.

CangJie

The CangJie input is separated into three different input modes:

QWERTY

The QWERTY input mode (EPtiEngineQwerty) implements the basic QWERTY input mode for Latin-like languages. Basic functionality of Latin QWERTY input is very simple. The client calls the CPtiEngine::AppendKeyPress method and PtiEngine appends a new character to the input buffer according to the current key mappings. In addition to normal upper and lower test cases, there are two extra case definitions: EPtiCaseChrLower and EPtiCaseChrUpper. They are needed for the Chr-key functionality and when either of them is activated (by calling CPtiEngine::SetCase) consecutive key presses cycle through accented characters associated to that key.

Another QWERTY related special case is the dead key functionality. A dead key does not produce any character initially when pressed, but when a suitable key is pressed next, the character associated to the second key is appended to the buffer in accented form. If the second key is not able to produce any accented form associated to the first key, then both the dead key root character and the character for second key are appended to the buffer. PtiEngine client should prepare to handle a situation in which a single key press produces two characters.

Dead key functionality variation is implemented for Vietnamese QWERTY. Vietnamese input specification specifies certain vowel sequences, where two consecutive key presses are combined into one character. The vowel sequences are not defined in key mapping data, but handled as hardcoded special case in QWERTY key mapping handler.

Chinese QWERTY

The following input modes are defined for Chinese QWERTY:

Japanese input modes

The following input modes are defined for Japanese input:

Committing the current word

Committing means that the current word is accepted to be part of the edited text and can be marked as ‘used’ in case the predictive core maintains the frequency information (the reordering feature). The current input sequence is cleared and PtiEngine is ready for a new word.

eng->CommitCurrentWord();          // Tell engine that current word was
                                   // accepted, so that the underlying
                                   // core keeps frequency information
                                   // up-to-date.

Listing available languages

The following code snippet lists available languages.

if ( eng->NumberOfLanguages() )
    {
    RArray<TInt> languages;
    CleanupClosePushL( languages );
    eng->GetAvailableLanguagesL( languages );
    //...
    CleanupStack::PopAndDestroy( &languages; );
    }

Listing available input modes

The following code snippet lists available input modes of the current language.

MPtiLanguage* lang = eng->CurrentLanguage();
if ( lang )
    {
    RArray<TInt> inputModes;
    CleanupClosePushL( inputModes );
    eng->GetAvailableInputModesL( inputModes );
    //...
    CleanupStack::PopAndDestroy( &inputModes; );
    }

Clearing the current word

Clearing the current word means that current word is rejected and will not be part of edited text. The current input sequence is cleared and PtiEngine is ready for a new word.

eng->ClearCurrentWord();          // Tell engine that current word was
                                  // rejected.

The current word has to be either committed (CommitCurrentWord) or cleared (ClearCurrentWord) before starting a new word.

Adding / removing entries to user dictionary

PtiEngine has to be in predictive mode to add or remove entries to the user dictionary.

TPtiUserDictionaryEntry newEntry( _L("customword") );
TPtiEngineInputMode curInputMode = eng->InputMode();
User::LeaveIfError( eng->SetInputMode( EPtiEnginePredictive ) );
// Add entry
User::LeaveIfError( eng->AddUserDictionaryEntry( newEntry ) );
// Remove entry
User::LeaveIfError( eng->RemoveEntryFromUserDictionary( newEntry ) );
User::LeaveIfError( eng->SetInputMode( curInputMode ) );

Implementing plug-ins

Core objects are implemented as ECom plug-ins. At startup PtiEngine queries the available ECom plug-ins with the interface ID 0x101F87FC.

The base class CPtiCore contains code for loading the core as ECom plug-in. Concrete implementations need to provide the ECom resource file.

MMP file fragment:

target      MyCore.dll
targettype  PLUGIN
capability  ALL -TCB
uid         0x10009d8d 0xE0000ABCD

source MyCore.cpp

START RESOURCE ..\src\E000ABCD.rss
TARGET MyCore.rsc
END

Resource file fragment:

RESOURCE REGISTRY_INFO theInfo
  {
  dll_uid = 0xE000ABCD;
  interfaces = 
    {		
    INTERFACE_INFO
      {
      interface_uid = 0x101F87FC;
      implementations =
        {
        IMPLEMENTATION_INFO 
          {
          implementation_uid = 0xE0001234;
          version_no = 1;
          display_name = "Custom Core for PtiEngine";
          }
        };
      }
    };
  }

Core object must derive from CPtiCore and override the methods it wishes to implement. The core object has to fill a structure called TPtiCoreInfo, this is used by PtiEngine to query core object capabilities. It also must update the language list.

The sample core object supports predictive input and word completion for Norwegian language:

class CMyCore : public CPtiCore
    {
    public: // new methods
        void ConstructL();
        //...

    public: // from MPtiCore
        void InitializeL(
            CPtiEngine* aOwner,
            TDes* aTextBuffer,
            CArrayPtrFlat<CPtiCoreLanguage>* aLanguageList,
            TBool aUseDefautUserDictionary );
        MPtiCoreInfo* GetCoreInfo();
        //...

    private: // data
        CPtiEngine*  iOwner; // Not owned.
        TDes*        iTextBuffer; // Not owned.        
        TPtiCoreInfo iCoreInfo;
        //...
    };

void CMyCore::ConstructL()
    {
    // Fill core info.
    iCoreInfo.SetMaxWordLength( 32 );
    iCoreInfo.SetUid( 0xE0001234 );
    iCoreInfo.SetVendorString( _L("My Core") );
    iCoreInfo.SetMaxNumberOfCandidates( 8 );
    iCoreInfo.SetCapsBits( EWordCompletion );
    }

void CMyCore::InitializeL(
    CPtiEngine* aOwner, TDes* aTextBuffer,
    CArrayPtrFlat<CPtiCoreLanguage>* aLanguageList,
    TBool /*aUseDefautUserDictionary*/ )
    {
    CPtiCoreLanguage* lang = NULL;
    iOwner = aOwner;
    iTextBuffer = aTextBuffer;

    // Check if Norwegian is already on the list
    for ( TInt i = 0; i < aLanguageList->Count(); i++ )
        {
        if ( (*aLanguageList)[i]->LanguageCode() == ELangNorwegian )
            {
            lang = (*aLanguageList)[i];
            break;
            }
        }
    if ( !lang )
        {
        // Not on the list, add now.
        lang = CPtiCoreLanguage::NewL();
        CleanupStack::PushL( lang );
        lang->SetLanguageCode( ELangNorwegian ); 
        aLanguageList->AppendL( lang );
        CleanupStack::Pop( lang );
        }
    // Set predictive Norwegian core to this.
    lang->SetCore( this, EPtiEnginePredictive );
    }

MPtiCoreInfo* CMyCore::GetCoreInfo()
    {
    return &iCoreInfo;
    }


Error handling

PtiEngine API uses standard Symbian OS error reporting mechanism. In addition to Symbian OS error codes, a PtiEngine specific error range is also defined in file PtiDefs.h. Leaves and system wide error codes as function return values are used if the error is recoverable. A client application can handle these errors similarly as a normal Symbian platform application.

Memory overhead

Memory consumption of PtiEngine API is proportional to the number of cores loaded and the actual implementation of the cores. Memory requirement of concrete core implementations varies.

It should be noted, however, that predictive input modes, user dictionaries, reordering feature data, etc. are usually kept in memory for efficiency reasons.

Limitations of the API

None.


Copyright © Nokia Corporation 2001-2008
Back to top