~ubuntu-branches/ubuntu/quantal/qtmobility/quantal

« back to all changes in this revision

Viewing changes to plugins/contacts/symbian/contactsmodel/cntplsql/src/ckoreankeymap.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2010-11-16 16:18:07 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20101116161807-k2dzt2nyse975r3l
Tags: 1.1.0-0ubuntu1
* New upstream release
* Syncronise with Debian, no remaining changes

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
* Copyright (c) 2010 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: Retrieves the character map for each of the numeric keys.
 
15
*/
 
16
 
 
17
// INCLUDE FILES
 
18
#include "ckoreankeymap.h"
 
19
#include <QString>
 
20
#include <QTextCodec>
 
21
 
 
22
#include "predictivesearchkeymapdefs.h"
 
23
// This macro suppresses log writes
 
24
// #define NO_PRED_SEARCH_LOGS
 
25
#include "predictivesearchlog.h"
 
26
 
 
27
 
 
28
const int KMibKorean = 36;
 
29
 
 
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;
 
34
 
 
35
const int KJamoLowerLimit = 0x1100;
 
36
const int KJamoUpperLimit = 0x11FF;
 
37
 
 
38
const int KChoCount  = 19;
 
39
const int KJungCount = 21;
 
40
const int KJongCount = 28;
 
41
 
 
42
const int KChoBase  = KJamoLowerLimit;
 
43
const int KJungBase = 0x1161;
 
44
const int KJongBase = 0x11A7;
 
45
 
 
46
 
 
47
 
 
48
// ============================== MEMBER FUNCTIONS ============================
 
49
 
 
50
// ----------------------------------------------------------------------------
 
51
// CKoreanKeyMap::NewL
 
52
// ----------------------------------------------------------------------------
 
53
CKoreanKeyMap* CKoreanKeyMap::NewL()
 
54
    {
 
55
        CKoreanKeyMap* self = new (ELeave) CKoreanKeyMap;
 
56
        CleanupStack::PushL(self);
 
57
    self->ConstructL();
 
58
    CleanupStack::Pop(self);
 
59
    return self;
 
60
    }
 
61
 
 
62
// ----------------------------------------------------------------------------
 
63
// CKoreanKeyMap::~CKoreanKeyMap
 
64
// ----------------------------------------------------------------------------
 
65
CKoreanKeyMap::~CKoreanKeyMap()
 
66
    {
 
67
    }
 
68
 
 
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
 
76
        {
 
77
        if (iLatinCodec && iLatinCodec->canEncode(aSource))
 
78
                {
 
79
                return EFalse;
 
80
                }
 
81
 
 
82
        int len = aSource.length();
 
83
        for (int i = 0; i < len; ++i)
 
84
                {
 
85
                int unicode = aSource[i].unicode();
 
86
                if (unicode >= KJamoLowerLimit && unicode <= KJamoUpperLimit)
 
87
                        {
 
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;
 
92
                        }
 
93
                }
 
94
 
 
95
    return iKoreanCodec && iKoreanCodec->canEncode(aSource);
 
96
        }
 
97
 
 
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
 
103
// later tokenizing.
 
104
// ----------------------------------------------------------------------------
 
105
QString CKoreanKeyMap::GetMappedString(QString aSource) const
 
106
        {
 
107
        QString destination;
 
108
        TInt length = aSource.length();
 
109
 
 
110
    for (int i = 0; i < length; ++i)
 
111
        {
 
112
                QChar ch = aSource[i];
 
113
                if (IsSyllable(ch))
 
114
                        {
 
115
                        QString jamos = ExtractJamos(ch);
 
116
                        destination.append(GetMappedString(jamos));
 
117
                        destination.append(KSeparatorChar); // Syllable is one token
 
118
                        }
 
119
                else
 
120
                        {
 
121
                        if (ch == KSpaceChar)
 
122
                                {
 
123
                                destination.append(KSeparatorChar);
 
124
                                }
 
125
                        else
 
126
                                {
 
127
                                QString keySequence = MapJamoToKeySequence(ch); // searches iKeyPressMap
 
128
                                destination.append(keySequence);
 
129
                                }
 
130
 
 
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
 
134
                        }
 
135
                }
 
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);
 
140
#endif
 
141
    return destination;
 
142
        }
 
143
 
 
144
// ----------------------------------------------------------------------------
 
145
// CKoreanKeyMap::CKoreanKeyMap
 
146
// ----------------------------------------------------------------------------
 
147
CKoreanKeyMap::CKoreanKeyMap()
 
148
        {
 
149
        }
 
150
 
 
151
// ----------------------------------------------------------------------------
 
152
// CKoreanKeyMap::ConstructL
 
153
// ----------------------------------------------------------------------------
 
154
void CKoreanKeyMap::ConstructL()
 
155
        {
 
156
        PRINT(_L("Enter CKoreanKeyMap::ConstructL"));
 
157
 
 
158
        TInt err(KErrNone);
 
159
        QT_TRYCATCH_ERROR(err,
 
160
                {
 
161
                GetTextCodecs();
 
162
                FillKeyPressMap();
 
163
                });             
 
164
                
 
165
    if (err != KErrNone)
 
166
        {
 
167
        PRINT1(_L("CKoreanKeyMap::ConstructL exception, err=%d"), err);
 
168
        User::Leave(err);
 
169
        }
 
170
 
 
171
        PRINT(_L("End CKoreanKeyMap::ConstructL"));
 
172
        }
 
173
 
 
174
// ----------------------------------------------------------------------------
 
175
// CKoreanKeyMap::GetTextCodecs
 
176
// ----------------------------------------------------------------------------
 
177
void CKoreanKeyMap::GetTextCodecs()
 
178
    {
 
179
    iLatinCodec = QTextCodec::codecForMib(KMibLatin1);
 
180
    iKoreanCodec = QTextCodec::codecForMib(KMibKorean);
 
181
    }
 
182
 
 
183
// ----------------------------------------------------------------------------
 
184
// CKoreanKeyMap::FillKeyPressMap
 
185
// Map Korean unicode character values <--> sequence of keypresses
 
186
// Key presses are identified like this:
 
187
//   key 1 -> "1"
 
188
//   key 2 -> "2" etc.
 
189
//   key * -> "a"
 
190
//   key # -> "b"
 
191
//
 
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()
 
196
    {
 
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?
 
200
 
 
201
        MapCharacters("1", 0x1100, 0x3131, 0x11a8);
 
202
        MapCharacters("1a", 0x110f, 0x314b, 0x11bf);
 
203
        MapCharacters("1b", 0x1101, 0x3132, 0x11a9);
 
204
 
 
205
        MapCharacters("2", 0x1102, 0x3134, 0x11ab);
 
206
        MapCharacters("2a", 0x1103, 0x3137, 0x11ae);
 
207
        MapCharacters("2aa", 0x1110, 0x314c, 0x11c0);
 
208
        MapCharacters("2ab", 0x1104, 0x3138);
 
209
 
 
210
        MapCharacters("3", 0x1161, 0x314f);
 
211
        MapCharacters("39", 0x1162, 0x3150);
 
212
        MapCharacters("3a", 0x1163, 0x3151);
 
213
        MapCharacters("3a9", 0x1164, 0x3152);
 
214
 
 
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);
 
220
 
 
221
        MapCharacters("4", 0x1105, 0x3139, 0x11af);
 
222
 
 
223
        MapCharacters("5", 0x1106, 0x3141, 0x11b7);
 
224
        MapCharacters("5a", 0x1107, 0x3142, 0x11b8);
 
225
        MapCharacters("5aa", 0x1111, 0x314d, 0x11c1);
 
226
        MapCharacters("5ab", 0x1108, 0x3143);
 
227
 
 
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);
 
233
 
 
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);
 
240
 
 
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);
 
246
 
 
247
        MapCharacters("8", 0x110b, 0x3147, 0x11bc);
 
248
        MapCharacters("8a", 0x1112, 0x314e, 0x11c2);
 
249
 
 
250
        MapCharacters("9", 0x1175, 0x3163);
 
251
 
 
252
        MapCharacters("0", 0x1173, 0x3161);
 
253
        MapCharacters("09", 0x1174, 0x3162);
 
254
 
 
255
 
 
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);
 
269
        }
 
270
 
 
271
// ----------------------------------------------------------------------------
 
272
// CKoreanKeyMap::MapCharacters
 
273
// ----------------------------------------------------------------------------
 
274
void CKoreanKeyMap::MapCharacters(QString aKeySequence,
 
275
                                                                  QChar aJamoChar,
 
276
                                                                  QChar aCompatibilityJamoChar,
 
277
                                                                  QChar aOtherJamoChar)
 
278
        {
 
279
        iKeyPressMap.insert(aJamoChar, aKeySequence);
 
280
        if (aOtherJamoChar.unicode() > 0)
 
281
                {
 
282
                iKeyPressMap.insert(aOtherJamoChar, aKeySequence);
 
283
                }
 
284
        if (aCompatibilityJamoChar.unicode() > 0)
 
285
                {
 
286
                iKeyPressMap.insert(aCompatibilityJamoChar, aKeySequence);
 
287
                }
 
288
        }
 
289
 
 
290
// ----------------------------------------------------------------------------
 
291
// CKoreanKeyMap::IsSyllable
 
292
// ----------------------------------------------------------------------------
 
293
TBool CKoreanKeyMap::IsSyllable(QChar aChar) const
 
294
        {
 
295
        int codePoint = aChar.unicode();
 
296
        return (codePoint >= KHangulSyllableLowerLimit &&
 
297
                        codePoint <= KHangulSyllableUpperLimit);
 
298
        }
 
299
 
 
300
// ----------------------------------------------------------------------------
 
301
// CKoreanKeyMap::ExtractJamos
 
302
// ----------------------------------------------------------------------------
 
303
const QString CKoreanKeyMap::ExtractJamos(QChar aChar) const
 
304
        {
 
305
        PRINT1(_L("Enter CKoreanKeyMap::ExtractJamos aChar=%X"), aChar.unicode());
 
306
        __ASSERT_DEBUG(IsSyllable(aChar),
 
307
                                   User::Panic(_L("CKoreanKeyMap::ExtractJamos"), KErrArgument));
 
308
 
 
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;
 
314
        
 
315
        PRINT3(_L("cho=%d jung=%d jong=%d"), choValue, jungValue, jongValue);
 
316
 
 
317
        QChar jong = KJongBase + jongValue;
 
318
        QChar jung = KJungBase + jungValue;
 
319
        QChar cho  = KChoBase + choValue;
 
320
 
 
321
        QString result = cho;
 
322
        result += jung;
 
323
        // If jong is zero, it is missing. Such hangul has just cho and jung.
 
324
        if (jongValue > 0)
 
325
                {
 
326
                result += jong;
 
327
                }
 
328
 
 
329
        PRINT(_L("End CKoreanKeyMap::ExtractJamos"));
 
330
        return result;
 
331
        }
 
332
 
 
333
// ----------------------------------------------------------------------------
 
334
// CKoreanKeyMap::MapJamoToKeySequence
 
335
// ----------------------------------------------------------------------------
 
336
const QString CKoreanKeyMap::MapJamoToKeySequence(QChar aChar) const
 
337
        {
 
338
        return iKeyPressMap.value(aChar, "" /* default value */);
 
339
        }
 
340
 
 
341
// End of file