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.
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 );
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 );
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();
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 ) ) { //... }
The following code snippet checks whether predictive Norwegian is supported.
MPtiLanguage* lang = eng->GetLanguage( ELangNorwegian ); if ( lang && lang->HasInputMode( EPtiEnginePredictive ) { //... }
MPtiLanguage* lang = eng->CurrentLanguage();
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.
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".
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.
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. }
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.
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
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.
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.
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.
The Zhuyin phrase input (EPtiEngineZhuyinByPhrase
) is
essentially the same as the regular Zhuyin input, except that Zhuyin symbols
are entered by using QWERTY keyboard.
The CangJie input is separated into three different input modes:
EPtiEngineNormalCangjieQwerty
implements normal CangJie
input.
EPtiEngineEasyCangjieQwerty
implements easy CangJie input.
EPtiEngineAdvCangjieQwerty
implements advanced CangJie
input.
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.
The following input modes are defined for Chinese QWERTY:
EPtiEngineZhuyinQwerty
for the Zhuyin QWERTY mode.
EPtiEngineZhuyinPhraseQwerty
for the Zhuyin QWERTY phrase
mode.
EPtiEnginePinyinQwerty
for the Pinyin QWERTY mode.
EPtiEnginePinyinPhraseQwerty
for the Pinyin QWERTY phrase
mode.
EPtiEngineStrokeQwerty
for the Stroke QWERTY mode.
The following input modes are defined for Japanese input:
EPtiEngineHiraganaKanji
for the Hiragana/Kanji mode.
EPtiEngineHiraganaKanjiPredictive
for the predictive
Hiragana/Kanji mode.
EPtiEngineKatakana
for the half-width Katakana mode.
EPtiEngineFullWidthKatakana
for the full-width Katakana
mode.
EPtiEngineFullWidthNumeric
for the full-width numeric.
EPtiEngineFullWidthAlphabet
for the full-width alphabet
mode.
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.
The following code snippet lists available languages.
if ( eng->NumberOfLanguages() ) { RArray<TInt> languages; CleanupClosePushL( languages ); eng->GetAvailableLanguagesL( languages ); //... CleanupStack::PopAndDestroy( &languages; ); }
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 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.
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 ) );
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; }
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 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.
None.