2
* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
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".
9
* Initial Contributors:
10
* Nokia Corporation - initial contribution.
14
* Description: Retrieves the character map for each of the numeric keys.
18
#include "ckoreankeymap.h"
22
#include "predictivesearchkeymapdefs.h"
23
// This macro suppresses log writes
24
// #define NO_PRED_SEARCH_LOGS
25
#include "predictivesearchlog.h"
28
const int KMibKorean = 36;
30
// These constants are from Hangul and Jamo unicode specifications
31
// UD7A4..UD7AF are unspecific
32
const int KHangulSyllableLowerLimit = 0xAC00;
33
const int KHangulSyllableUpperLimit = 0xD7A3;
35
const int KJamoLowerLimit = 0x1100;
36
const int KJamoUpperLimit = 0x11FF;
38
const int KChoCount = 19;
39
const int KJungCount = 21;
40
const int KJongCount = 28;
42
const int KChoBase = KJamoLowerLimit;
43
const int KJungBase = 0x1161;
44
const int KJongBase = 0x11A7;
48
// ============================== MEMBER FUNCTIONS ============================
50
// ----------------------------------------------------------------------------
51
// CKoreanKeyMap::NewL
52
// ----------------------------------------------------------------------------
53
CKoreanKeyMap* CKoreanKeyMap::NewL()
55
CKoreanKeyMap* self = new (ELeave) CKoreanKeyMap;
56
CleanupStack::PushL(self);
58
CleanupStack::Pop(self);
62
// ----------------------------------------------------------------------------
63
// CKoreanKeyMap::~CKoreanKeyMap
64
// ----------------------------------------------------------------------------
65
CKoreanKeyMap::~CKoreanKeyMap()
69
// ----------------------------------------------------------------------------
70
// CKoreanKeyMap::IsLanguageSupported
71
// Korean QTextCodec recognizes Hangul and Hangul compatibility Jamo characters,
72
// but not the Hangul Jamo characters (U1100+). Hence the Jamo are handled here
73
// and treated as Korean text.
74
// ----------------------------------------------------------------------------
75
TBool CKoreanKeyMap::IsLanguageSupported(QString aSource) const
77
if (iLatinCodec && iLatinCodec->canEncode(aSource))
82
int len = aSource.length();
83
for (int i = 0; i < len; ++i)
85
int unicode = aSource[i].unicode();
86
if (unicode >= KJamoLowerLimit && unicode <= KJamoUpperLimit)
88
// Replace the character in aSource local to this function, with (any)
89
// Hangul syllable that QTextCodec recognizes are Korean text.
90
// Does not modify the caller's version of aSource.
91
aSource[i] = KHangulSyllableLowerLimit;
95
return iKoreanCodec && iKoreanCodec->canEncode(aSource);
98
// ----------------------------------------------------------------------------
99
// CKoreanKeyMap::GetMappedString
100
// Hangul syllable characters are split into Jamos.
101
// Jamos are mapped to sequence of keypresses.
102
// If aSource has spaces, they are treated as separator characters for the
104
// ----------------------------------------------------------------------------
105
QString CKoreanKeyMap::GetMappedString(QString aSource) const
108
TInt length = aSource.length();
110
for (int i = 0; i < length; ++i)
112
QChar ch = aSource[i];
115
QString jamos = ExtractJamos(ch);
116
destination.append(GetMappedString(jamos));
117
destination.append(KSeparatorChar); // Syllable is one token
121
if (ch == KSpaceChar)
123
destination.append(KSeparatorChar);
127
QString keySequence = MapJamoToKeySequence(ch); // searches iKeyPressMap
128
destination.append(keySequence);
131
// TODO: detect the syllable limits within stream of Jamos in this way:
132
// syllable begins by C + V pair, which is never in the middle of a syllable.
133
// Currently assumes aSource only contains grammatically valid Jamo stream
136
#if defined(WRITE_PRED_SEARCH_LOGS)
137
const int KLogLength = 60;
138
TBuf<KLogLength> log = destination.left(KLogLength).utf16();
139
PRINT1(_L("End CPcsKeyMap::GetMappedString result '%S'"), &log);
144
// ----------------------------------------------------------------------------
145
// CKoreanKeyMap::CKoreanKeyMap
146
// ----------------------------------------------------------------------------
147
CKoreanKeyMap::CKoreanKeyMap()
151
// ----------------------------------------------------------------------------
152
// CKoreanKeyMap::ConstructL
153
// ----------------------------------------------------------------------------
154
void CKoreanKeyMap::ConstructL()
156
PRINT(_L("Enter CKoreanKeyMap::ConstructL"));
159
QT_TRYCATCH_ERROR(err,
167
PRINT1(_L("CKoreanKeyMap::ConstructL exception, err=%d"), err);
171
PRINT(_L("End CKoreanKeyMap::ConstructL"));
174
// ----------------------------------------------------------------------------
175
// CKoreanKeyMap::GetTextCodecs
176
// ----------------------------------------------------------------------------
177
void CKoreanKeyMap::GetTextCodecs()
179
iLatinCodec = QTextCodec::codecForMib(KMibLatin1);
180
iKoreanCodec = QTextCodec::codecForMib(KMibKorean);
183
// ----------------------------------------------------------------------------
184
// CKoreanKeyMap::FillKeyPressMap
185
// Map Korean unicode character values <--> sequence of keypresses
186
// Key presses are identified like this:
192
// Note: multiple Korean chars can map to same key sequence
193
// e.g. U1100 and U3131 are the same char
194
// ----------------------------------------------------------------------------
195
void CKoreanKeyMap::FillKeyPressMap()
197
// When there are multiple keys(unicode chars) mapped to same value (keypresses)
198
// then QMap::key(const T & value) returns the _first_ key with value.
199
// but is there a need for this reverse search at all?
201
MapCharacters("1", 0x1100, 0x3131, 0x11a8);
202
MapCharacters("1a", 0x110f, 0x314b, 0x11bf);
203
MapCharacters("1b", 0x1101, 0x3132, 0x11a9);
205
MapCharacters("2", 0x1102, 0x3134, 0x11ab);
206
MapCharacters("2a", 0x1103, 0x3137, 0x11ae);
207
MapCharacters("2aa", 0x1110, 0x314c, 0x11c0);
208
MapCharacters("2ab", 0x1104, 0x3138);
210
MapCharacters("3", 0x1161, 0x314f);
211
MapCharacters("39", 0x1162, 0x3150);
212
MapCharacters("3a", 0x1163, 0x3151);
213
MapCharacters("3a9", 0x1164, 0x3152);
215
// Double-3 tap is stored as 33
216
MapCharacters("33", 0x1165, 0x3153);
217
MapCharacters("339", 0x1166, 0x3154);
218
MapCharacters("33a", 0x1167, 0x3155);
219
MapCharacters("33a9", 0x1168, 0x3156);
221
MapCharacters("4", 0x1105, 0x3139, 0x11af);
223
MapCharacters("5", 0x1106, 0x3141, 0x11b7);
224
MapCharacters("5a", 0x1107, 0x3142, 0x11b8);
225
MapCharacters("5aa", 0x1111, 0x314d, 0x11c1);
226
MapCharacters("5ab", 0x1108, 0x3143);
228
MapCharacters("6", 0x1169, 0x3157);
229
MapCharacters("63", 0x116a, 0x3158);
230
MapCharacters("639", 0x116b, 0x3159);
231
MapCharacters("69", 0x116c, 0x315a);
232
MapCharacters("6a", 0x116d, 0x315b);
234
// Double-6 tap is stored as 66
235
MapCharacters("66", 0x116e, 0x315c);
236
MapCharacters("663", 0x116f, 0x315d);
237
MapCharacters("6639", 0x1170, 0x315e);
238
MapCharacters("669", 0x1171, 0x315f);
239
MapCharacters("66a", 0x1172, 0x3160);
241
MapCharacters("7", 0x1109, 0x3145, 0x11ba);
242
MapCharacters("7a", 0x110c, 0x3148, 0x11bd);
243
MapCharacters("7aa", 0x110e, 0x314a, 0x11be);
244
MapCharacters("7ab", 0x110d, 0x3149);
245
MapCharacters("7b", 0x110a, 0x3146, 0x11bb);
247
MapCharacters("8", 0x110b, 0x3147, 0x11bc);
248
MapCharacters("8a", 0x1112, 0x314e, 0x11c2);
250
MapCharacters("9", 0x1175, 0x3163);
252
MapCharacters("0", 0x1173, 0x3161);
253
MapCharacters("09", 0x1174, 0x3162);
256
// The 11 jong characters that consist of two consonants.
257
// Map them to key sequence that produces the two consonants (TODO: chk if this is the correct way)
258
MapCharacters("17", 0x11aa);
259
MapCharacters("27a", 0x11ac);
260
MapCharacters("28a", 0x11ad);
261
MapCharacters("41", 0x11b0);
262
MapCharacters("45", 0x11b1);
263
MapCharacters("45a", 0x11b2);
264
MapCharacters("47", 0x11b3);
265
MapCharacters("42aa", 0x11b4);
266
MapCharacters("45aa", 0x11b5);
267
MapCharacters("48a", 0x11b6);
268
MapCharacters("5a7", 0x11b9);
271
// ----------------------------------------------------------------------------
272
// CKoreanKeyMap::MapCharacters
273
// ----------------------------------------------------------------------------
274
void CKoreanKeyMap::MapCharacters(QString aKeySequence,
276
QChar aCompatibilityJamoChar,
277
QChar aOtherJamoChar)
279
iKeyPressMap.insert(aJamoChar, aKeySequence);
280
if (aOtherJamoChar.unicode() > 0)
282
iKeyPressMap.insert(aOtherJamoChar, aKeySequence);
284
if (aCompatibilityJamoChar.unicode() > 0)
286
iKeyPressMap.insert(aCompatibilityJamoChar, aKeySequence);
290
// ----------------------------------------------------------------------------
291
// CKoreanKeyMap::IsSyllable
292
// ----------------------------------------------------------------------------
293
TBool CKoreanKeyMap::IsSyllable(QChar aChar) const
295
int codePoint = aChar.unicode();
296
return (codePoint >= KHangulSyllableLowerLimit &&
297
codePoint <= KHangulSyllableUpperLimit);
300
// ----------------------------------------------------------------------------
301
// CKoreanKeyMap::ExtractJamos
302
// ----------------------------------------------------------------------------
303
const QString CKoreanKeyMap::ExtractJamos(QChar aChar) const
305
PRINT1(_L("Enter CKoreanKeyMap::ExtractJamos aChar=%X"), aChar.unicode());
306
__ASSERT_DEBUG(IsSyllable(aChar),
307
User::Panic(_L("CKoreanKeyMap::ExtractJamos"), KErrArgument));
309
int syllable = aChar.unicode() - KHangulSyllableLowerLimit;
310
int jongValue = syllable % KJongCount;
311
int tmp = (syllable - jongValue) / KJongCount;
312
int jungValue = tmp % KJungCount;
313
int choValue = tmp / KJungCount;
315
PRINT3(_L("cho=%d jung=%d jong=%d"), choValue, jungValue, jongValue);
317
QChar jong = KJongBase + jongValue;
318
QChar jung = KJungBase + jungValue;
319
QChar cho = KChoBase + choValue;
321
QString result = cho;
323
// If jong is zero, it is missing. Such hangul has just cho and jung.
329
PRINT(_L("End CKoreanKeyMap::ExtractJamos"));
333
// ----------------------------------------------------------------------------
334
// CKoreanKeyMap::MapJamoToKeySequence
335
// ----------------------------------------------------------------------------
336
const QString CKoreanKeyMap::MapJamoToKeySequence(QChar aChar) const
338
return iKeyPressMap.value(aChar, "" /* default value */);