1 0 yongsun /* 2 82 yongsun * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 82 yongsun * 4 82 yongsun * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. 5 82 yongsun * 6 82 yongsun * The contents of this file are subject to the terms of either the GNU Lesser 7 82 yongsun * General Public License Version 2.1 only ("LGPL") or the Common Development and 8 82 yongsun * Distribution License ("CDDL")(collectively, the "License"). You may not use this 9 82 yongsun * file except in compliance with the License. You can obtain a copy of the CDDL at 10 82 yongsun * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at 11 82 yongsun * http://www.opensource.org/licenses/lgpl-license.php. See the License for the 12 82 yongsun * specific language governing permissions and limitations under the License. When 13 82 yongsun * distributing the software, include this License Header Notice in each file and 14 82 yongsun * include the full text of the License in the License file as well as the 15 82 yongsun * following notice: 16 82 yongsun * 17 82 yongsun * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE 18 82 yongsun * (CDDL) 19 82 yongsun * For Covered Software in this distribution, this License shall be governed by the 20 82 yongsun * laws of the State of California (excluding conflict-of-law provisions). 21 82 yongsun * Any litigation relating to this License shall be subject to the jurisdiction of 22 82 yongsun * the Federal Courts of the Northern District of California and the state courts 23 82 yongsun * of the State of California, with venue lying in Santa Clara County, California. 24 82 yongsun * 25 82 yongsun * Contributor(s): 26 82 yongsun * 27 82 yongsun * If you wish your version of this file to be governed by only the CDDL or only 28 82 yongsun * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to 29 82 yongsun * include this software in this distribution under the [CDDL or LGPL Version 2.1] 30 82 yongsun * license." If you don't indicate a single choice of license, a recipient has the 31 82 yongsun * option to distribute your version of this file under either the CDDL or the LGPL 32 82 yongsun * Version 2.1, or to extend the choice of license to its licensees as provided 33 82 yongsun * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL 34 82 yongsun * Version 2 license, then the option applies only if the new code is made subject 35 82 yongsun * to such option by the copyright holder. 36 0 yongsun */ 37 82 yongsun 38 0 yongsun #ifdef HAVE_CONFIG_H 39 0 yongsun #include <config.h> 40 0 yongsun #endif 41 0 yongsun 42 0 yongsun #include "imi_view_classic.h" 43 0 yongsun #include "imi_uiobjects.h" 44 0 yongsun 45 0 yongsun #include "imi_keys.h" 46 0 yongsun 47 0 yongsun CIMIClassicView::CIMIClassicView() : CIMIView(), 48 0 yongsun m_CursorBone(), m_CursorIdx(0), m_CandiBone(), 49 0 yongsun m_CandiList(), m_CandiFirst(0), m_TailSentence() 50 0 yongsun { } 51 0 yongsun 52 0 yongsun CIMIClassicView::~CIMIClassicView() 53 0 yongsun { } 54 0 yongsun 55 0 yongsun int 56 0 yongsun CIMIClassicView::getViewType(void) 57 0 yongsun { return CIMIViewFactory::SVT_CLASSIC; } 58 0 yongsun 59 0 yongsun 60 0 yongsun void 61 0 yongsun CIMIClassicView::attachIC(CIMIContext* pIC) 62 0 yongsun { 63 0 yongsun CIMIView::attachIC(pIC); 64 0 yongsun 65 0 yongsun CSunpinyinOptions *ppref = dynamic_cast<CSunpinyinOptions*>(m_pPref); 66 0 yongsun 67 0 yongsun m_pIC->setLeft2RightSelection(false); 68 0 yongsun if (ppref) { 69 0 yongsun m_pIC->enableGBK(ppref->m_GBK); 70 0 yongsun m_pIC->setHistoryPower(ppref->m_MemoryPower); 71 0 yongsun m_pIC->enableContextRanking(ppref->m_ContextRanking); 72 0 yongsun } 73 0 yongsun 74 0 yongsun m_pIC->clear(); 75 0 yongsun m_CursorBone = m_pIC->getLastBone(); 76 0 yongsun m_CursorIdx = 0; 77 0 yongsun m_CandiBone = m_pIC->getLastBone(); 78 0 yongsun m_CandiList.clear(); 79 0 yongsun m_CandiFirst = 0; 80 0 yongsun } 81 0 yongsun 82 0 yongsun unsigned 83 0 yongsun CIMIClassicView::clearIC(void) 84 0 yongsun { 85 0 yongsun if (!m_pIC->isEmpty()) { 86 0 yongsun m_pIC->clear(); 87 0 yongsun m_CursorBone = m_pIC->getLastBone(); 88 0 yongsun m_CursorIdx = 0; 89 0 yongsun m_CandiBone = m_pIC->getLastBone(); 90 0 yongsun m_CandiList.clear(); 91 0 yongsun m_CandiFirst = 0; 92 0 yongsun m_TailSentence.clear(); 93 0 yongsun return PREEDIT_MASK | CANDIDATE_MASK; 94 0 yongsun } 95 0 yongsun return 0; 96 0 yongsun } 97 0 yongsun 98 0 yongsun void 99 0 yongsun CIMIClassicView::updateWindows(unsigned int mask) 100 0 yongsun { 101 0 yongsun if (mp_winHandler) { 102 0 yongsun if ((mask & PREEDIT_MASK) != 0) { 103 0 yongsun CPreEditString ps; 104 0 yongsun getPreeditString(ps); 105 0 yongsun mp_winHandler->updatePreedit(&ps); 106 0 yongsun } 107 0 yongsun 108 0 yongsun if ((mask & PREEDIT_MASK) != 0 || (mask & CANDIDATE_MASK) != 0) { 109 0 yongsun int wlen = getSentence(m_TailSentence, m_CandiBone); 110 0 yongsun if (wlen <= 1) m_TailSentence.clear(); 111 0 yongsun } 112 0 yongsun 113 0 yongsun if ((mask & CANDIDATE_MASK) != 0) { 114 0 yongsun CCandidateList cl; 115 0 yongsun getCandidateList(cl, m_CandiFirst, s_CandiWindowSize); 116 0 yongsun mp_winHandler->updateCandidates(&cl); 117 0 yongsun } 118 0 yongsun } 119 0 yongsun } 120 0 yongsun 121 0 yongsun void 122 0 yongsun CIMIClassicView::commitChar(TWCHAR ch) 123 0 yongsun { 124 0 yongsun TWCHAR wa[2] = {ch, 0}; 125 0 yongsun 126 0 yongsun mp_winHandler->commit(wa); 127 0 yongsun } 128 0 yongsun 129 0 yongsun void 130 0 yongsun CIMIClassicView::doCommit(bool bConvert) 131 0 yongsun { 132 0 yongsun wstring bs; 133 0 yongsun 134 0 yongsun if (bConvert) { 135 0 yongsun getIC()->memorize(); 136 0 yongsun getSentence(bs, m_pIC->getFirstBone()); 137 0 yongsun mp_winHandler->commit(bs.c_str()); 138 0 yongsun } else { 139 0 yongsun CSkeletonIter ite = m_pIC->getLastBone(); 140 0 yongsun for (CSkeletonIter it = m_pIC->getFirstBone(); it != ite; ++it) { 141 0 yongsun if (it->isPinyinNode()) 142 0 yongsun bs += it->m_String; 143 0 yongsun else 144 0 yongsun bs += (unsigned)it->m_BoundaryType; 145 0 yongsun if (it->isPinyinNode() && it->isUserBoundary()) 146 0 yongsun bs += TWCHAR('\''); 147 0 yongsun } 148 0 yongsun mp_winHandler->commit(bs.c_str()); 149 0 yongsun } 150 0 yongsun } 151 0 yongsun 152 0 yongsun int 153 0 yongsun CIMIClassicView::onKeyEvent(unsigned keycode, unsigned keyvalue, unsigned modifier) 154 0 yongsun { 155 0 yongsun unsigned changeMasks = 0; 156 0 yongsun CSunpinyinOptions *ppref = dynamic_cast<CSunpinyinOptions*>(m_pPref); 157 84 tchaikov 158 0 yongsun //Clear other mask bit we do not care 159 0 yongsun modifier &= (IM_SHIFT_MASK | IM_CTRL_MASK | IM_ALT_MASK); 160 84 tchaikov 161 0 yongsun #ifdef DEBUG 162 0 yongsun printf("Classic View got a key (0x%x-0x%x-0x%x)...", keycode, keyvalue, modifier); 163 0 yongsun 164 0 yongsun if (((modifier & IM_CTRL_MASK) != 0) && (keyvalue == 'P' || keyvalue=='p')) { 165 0 yongsun m_pIC->print_lattice(); 166 0 yongsun } 167 0 yongsun 168 0 yongsun fflush(stdout); 169 0 yongsun #endif 170 0 yongsun 171 0 yongsun if (keycode == IM_VK_SHIFT && modifier == IM_ALT_MASK) { 172 0 yongsun setStatusAttrValue(CIMIWinHandler::STATUS_ID_CN, (!m_CN)?1:0); 173 0 yongsun return 0; 174 0 yongsun } else if (keyvalue == IM_VK_PERIOD && modifier == IM_CTRL_MASK) { 175 0 yongsun // On CTRL+. switch Full/Half punc 176 0 yongsun changeMasks |= KEYEVENT_USED; 177 0 yongsun setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLPUNC, (!m_FullPunc)?1:0); 178 0 yongsun 179 0 yongsun } else if (keyvalue == IM_VK_SPACE && modifier == IM_SHIFT_MASK) { 180 0 yongsun // On CTRL+, switch Full/Half simbol 181 0 yongsun changeMasks |= KEYEVENT_USED; 182 0 yongsun setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLSIMBOL, (!m_FullSimbol)?1:0); 183 0 yongsun 184 0 yongsun } else if (modifier == IM_CTRL_MASK && keycode == IM_VK_LEFT) { //move left syllable 185 0 yongsun if (!m_pIC->isEmpty()) { 186 0 yongsun changeMasks |= KEYEVENT_USED; 187 0 yongsun moveLeftSyllable(changeMasks); 188 0 yongsun } 189 0 yongsun 190 0 yongsun } else if (modifier == 0 && keycode == IM_VK_LEFT) { //move left 191 0 yongsun if (!m_pIC->isEmpty()) { 192 0 yongsun changeMasks |= KEYEVENT_USED; 193 0 yongsun moveLeft(changeMasks); 194 0 yongsun } 195 0 yongsun 196 0 yongsun } else if (modifier == IM_CTRL_MASK && keycode == IM_VK_RIGHT) { //move syllable right 197 0 yongsun if (!m_pIC->isEmpty()) { 198 0 yongsun changeMasks |= KEYEVENT_USED; 199 0 yongsun moveRightSyllable(changeMasks); 200 0 yongsun } 201 0 yongsun 202 0 yongsun } else if (modifier == 0 && keycode == IM_VK_RIGHT) { //move right 203 0 yongsun if (!m_pIC->isEmpty()) { 204 0 yongsun changeMasks |= KEYEVENT_USED; 205 0 yongsun moveRight(changeMasks); 206 0 yongsun } 207 0 yongsun 208 79 tchaikov } else if ((ppref != NULL) && (ppref->isPageUpKey(keycode, keyvalue, modifier)) && !m_pIC->isEmpty()) { 209 79 tchaikov changeMasks |= KEYEVENT_USED; 210 79 tchaikov int sz = m_CandiList.size() + ((m_TailSentence.size() > 0)?1:0); 211 79 tchaikov if (sz > 0 && m_CandiFirst > 0) { 212 79 tchaikov m_CandiFirst -= s_CandiWindowSize; 213 79 tchaikov if (m_CandiFirst < 0) m_CandiFirst = 0; 214 79 tchaikov changeMasks |= CANDIDATE_MASK; 215 0 yongsun } 216 79 tchaikov 217 79 tchaikov } else if ((ppref != NULL) && (ppref->isPageDnKey(keycode, keyvalue, modifier)) && !m_pIC->isEmpty()) { 218 79 tchaikov changeMasks |= KEYEVENT_USED; 219 79 tchaikov int sz = m_CandiList.size() + ((m_TailSentence.size() > 0)?1:0); 220 79 tchaikov if (sz > 0 && m_CandiFirst + s_CandiWindowSize < sz) { 221 79 tchaikov m_CandiFirst += s_CandiWindowSize; 222 79 tchaikov changeMasks |= CANDIDATE_MASK; 223 0 yongsun } 224 79 tchaikov 225 0 yongsun } else if ((modifier & (IM_CTRL_MASK | IM_ALT_MASK)) == 0) { 226 84 tchaikov if (islower(keyvalue)) { // insert a PINYIN char 227 0 yongsun changeMasks |= KEYEVENT_USED; 228 0 yongsun if (m_pIC->getSkeleton().size() < 32) { 229 0 yongsun insertPinyin(keyvalue, changeMasks); 230 0 yongsun } 231 0 yongsun 232 0 yongsun } else if (keycode == IM_VK_BACK_SPACE || keycode == IM_VK_DELETE) { // delete 233 0 yongsun if (!m_pIC->isEmpty()) { 234 0 yongsun changeMasks |= KEYEVENT_USED; 235 0 yongsun erase((keycode == IM_VK_BACK_SPACE), changeMasks); 236 0 yongsun } 237 0 yongsun 238 0 yongsun } else if (keycode == IM_VK_HOME) { //move home 239 0 yongsun if (!m_pIC->isEmpty()) { 240 0 yongsun changeMasks |= KEYEVENT_USED; 241 0 yongsun moveHome(changeMasks); 242 0 yongsun } 243 0 yongsun } else if (keycode == IM_VK_END) { //move end 244 0 yongsun if (!m_pIC->isEmpty()) { 245 0 yongsun changeMasks |= KEYEVENT_USED; 246 0 yongsun moveEnd(changeMasks); 247 0 yongsun } 248 0 yongsun 249 0 yongsun } else if (keyvalue == '\'') { 250 0 yongsun if (!m_pIC->isEmpty()) { 251 0 yongsun changeMasks |= KEYEVENT_USED; 252 0 yongsun insertBoundary(changeMasks); 253 0 yongsun } 254 0 yongsun 255 84 tchaikov } else if (isdigit(keyvalue) && 256 84 tchaikov ((s_CandiWindowSize >= 10) || 257 85 tchaikov (s_CandiWindowSize < 10 && keyvalue < ('1'+s_CandiWindowSize)))) { // try to make selections 258 118 tonylee #ifdef DEBUG 259 84 tchaikov printf("onKeyEvent:number: %d, %d, %d\n", keycode, keyvalue, s_CandiWindowSize); 260 118 tonylee #endif 261 0 yongsun if (!m_pIC->isEmpty()) { 262 0 yongsun changeMasks |= KEYEVENT_USED; 263 118 tonylee unsigned selection = (keyvalue == '0' ? 9 : keyvalue-'1'); 264 85 tchaikov makeSelection(selection, changeMasks); 265 0 yongsun } 266 0 yongsun 267 0 yongsun } else if (keyvalue == IM_VK_SPACE) { // select or commit 268 0 yongsun if (!m_pIC->isEmpty()) { 269 0 yongsun changeMasks |= KEYEVENT_USED; 270 0 yongsun makeSelection(0, changeMasks); 271 0 yongsun } 272 0 yongsun 273 0 yongsun } else if (keycode == IM_VK_ENTER) { // commit PINYIN string 274 0 yongsun if (!m_pIC->isEmpty()) { 275 0 yongsun changeMasks |= KEYEVENT_USED | CANDIDATE_MASK | PREEDIT_MASK; 276 0 yongsun doCommit(false); 277 0 yongsun clearIC(); 278 0 yongsun } 279 0 yongsun 280 0 yongsun } else if (keycode == IM_VK_ESCAPE) { 281 0 yongsun if (!m_pIC->isEmpty()) { 282 0 yongsun changeMasks |= KEYEVENT_USED | CANDIDATE_MASK | PREEDIT_MASK; 283 0 yongsun clearIC(); 284 0 yongsun } 285 84 tchaikov } else if (keyvalue > 0x20 && keyvalue < 0x7F ) { // isprint() && !isblank() 286 0 yongsun if (m_pIC->getSkeleton().size() < 32) 287 0 yongsun pressNormalKey(keyvalue, changeMasks); 288 0 yongsun else 289 0 yongsun changeMasks |= KEYEVENT_USED; 290 0 yongsun } 291 0 yongsun } 292 0 yongsun 293 0 yongsun #ifdef DEBUG 294 0 yongsun printf(" |-->(Mask=0x%x)\n", changeMasks); 295 0 yongsun fflush(stdout); 296 0 yongsun #endif 297 0 yongsun 298 0 yongsun updateWindows(changeMasks); 299 0 yongsun 300 0 yongsun return ((changeMasks & KEYEVENT_USED) != 0)?1:0; 301 0 yongsun } 302 0 yongsun 303 0 yongsun int 304 0 yongsun CIMIClassicView::onCandidatePageRequest(int pgno, bool relative) 305 0 yongsun { 306 0 yongsun unsigned changeMasks = 0; 307 0 yongsun int ncandi, lastpgidx; 308 0 yongsun 309 0 yongsun if (!m_pIC->isEmpty()) { 310 0 yongsun changeMasks |= KEYEVENT_USED; 311 0 yongsun int sz = m_CandiList.size() + ((m_TailSentence.size() > 0)?1:0); 312 0 yongsun if (sz > 0) { 313 0 yongsun lastpgidx = (sz-1)/s_CandiWindowSize * s_CandiWindowSize; 314 0 yongsun if (relative == true) { 315 0 yongsun ncandi = m_CandiFirst + pgno*s_CandiWindowSize; 316 0 yongsun if (ncandi >= sz) 317 0 yongsun ncandi = lastpgidx; 318 0 yongsun if (ncandi < 0) 319 0 yongsun ncandi =0; 320 0 yongsun if (ncandi != m_CandiFirst) { 321 0 yongsun m_CandiFirst = ncandi; 322 0 yongsun changeMasks |= CANDIDATE_MASK; 323 0 yongsun } 324 0 yongsun } else { 325 0 yongsun if (pgno == -1) { //last page 326 0 yongsun ncandi = lastpgidx; 327 0 yongsun } else { 328 0 yongsun ncandi = pgno * s_CandiWindowSize; 329 0 yongsun if (ncandi > lastpgidx) 330 0 yongsun ncandi = lastpgidx; 331 0 yongsun } 332 0 yongsun if (ncandi != m_CandiFirst) { 333 0 yongsun m_CandiFirst = ncandi; 334 0 yongsun changeMasks |= CANDIDATE_MASK; 335 0 yongsun } 336 0 yongsun } 337 0 yongsun } 338 0 yongsun } 339 0 yongsun 340 0 yongsun updateWindows(changeMasks); 341 0 yongsun return 0; 342 0 yongsun } 343 0 yongsun 344 0 yongsun int 345 0 yongsun CIMIClassicView::onCandidateSelectRequest(int index) 346 0 yongsun { 347 0 yongsun unsigned changeMasks = 0; 348 0 yongsun 349 0 yongsun if (!m_pIC->isEmpty()) { 350 0 yongsun makeSelection(index, changeMasks); 351 0 yongsun } 352 0 yongsun updateWindows(changeMasks); 353 0 yongsun return 0; 354 0 yongsun } 355 0 yongsun 356 0 yongsun 357 0 yongsun void 358 0 yongsun CIMIClassicView::pressNormalKey(unsigned keyvalue, unsigned int& mask) 359 0 yongsun { 360 0 yongsun unsigned orig_key = keyvalue; 361 0 yongsun unsigned int bone_type = CBone::NODE_ASCII; 362 0 yongsun 363 0 yongsun if (m_FullSimbol) { 364 0 yongsun keyvalue = (unsigned int)(getFullSimbol(TWCHAR(keyvalue))); 365 0 yongsun } 366 0 yongsun if (m_FullPunc) { 367 0 yongsun keyvalue = (unsigned int)(getFullPunc(TWCHAR(keyvalue))); 368 0 yongsun bone_type = CBone::NODE_PUNC; 369 0 yongsun } 370 0 yongsun mask |= KEYEVENT_USED; 371 0 yongsun if (m_pIC->isEmpty()) { 372 0 yongsun commitChar(TWCHAR(keyvalue)); 373 0 yongsun } else { 374 0 yongsun insertNormalChar(bone_type, orig_key, keyvalue, mask); 375 0 yongsun } 376 0 yongsun } 377 0 yongsun 378 0 yongsun CSkeletonIter 379 0 yongsun CIMIClassicView::moveLeft(unsigned int& changeMask, bool searchAgain) 380 0 yongsun { 381 0 yongsun CSkeletonIter leftmost = m_pIC->getLastBone(); 382 0 yongsun if (m_CursorIdx > 0) { 383 0 yongsun --m_CursorIdx; 384 0 yongsun changeMask |= PREEDIT_MASK; 385 0 yongsun } else if (m_CursorBone != m_pIC->getFirstBone()) { 386 0 yongsun changeMask |= PREEDIT_MASK; 387 0 yongsun if (m_CursorBone-- == m_CandiBone) { 388 0 yongsun changeMask |= CANDIDATE_MASK; 389 0 yongsun if (m_CursorBone->isValidPinyinNode()) { 390 0 yongsun leftmost = m_CandiBone = m_pIC->cancelSelection(m_CursorBone, searchAgain); 391 0 yongsun } else { 392 0 yongsun m_CandiBone = m_CursorBone; 393 0 yongsun } 394 0 yongsun getCandidates(); 395 0 yongsun } 396 0 yongsun 397 0 yongsun m_CursorIdx = m_CursorBone->m_String.size(); 398 0 yongsun if (!m_CursorBone->isPinyinNode()) 399 0 yongsun --m_CursorIdx; 400 0 yongsun } // else we already at head of the string 401 0 yongsun return leftmost; 402 0 yongsun } 403 0 yongsun 404 0 yongsun CSkeletonIter 405 0 yongsun CIMIClassicView::moveLeftSyllable(unsigned int& changeMask, bool searchAgain) 406 0 yongsun { 407 0 yongsun CSkeletonIter leftmost = m_pIC->getLastBone(); 408 0 yongsun if (m_CursorIdx > 0) { 409 0 yongsun m_CursorIdx = 0; 410 0 yongsun changeMask |= PREEDIT_MASK; 411 0 yongsun } else if (m_CursorBone != m_pIC->getFirstBone()) { 412 0 yongsun changeMask |= PREEDIT_MASK; 413 0 yongsun if (m_CursorBone-- == m_CandiBone) { 414 0 yongsun changeMask |= CANDIDATE_MASK; 415 0 yongsun if (m_CursorBone->isValidPinyinNode()) { 416 0 yongsun leftmost = m_CandiBone = m_pIC->cancelSelection(m_CursorBone, searchAgain); 417 0 yongsun } else { 418 0 yongsun m_CandiBone = m_CursorBone; 419 0 yongsun } 420 0 yongsun getCandidates(); 421 0 yongsun } 422 0 yongsun m_CursorIdx = 0; 423 0 yongsun } // else we already at head of the string 424 0 yongsun return leftmost; 425 0 yongsun } 426 0 yongsun 427 0 yongsun CSkeletonIter 428 0 yongsun CIMIClassicView::moveHome(unsigned int& changeMask, bool searchAgain) 429 0 yongsun { 430 0 yongsun CSkeletonIter leftmost = m_pIC->getLastBone(); 431 0 yongsun CSkeletonIter firstBone = m_pIC->getFirstBone(); 432 0 yongsun 433 0 yongsun if (m_CursorBone != firstBone || m_CursorIdx != 0) 434 0 yongsun changeMask |= PREEDIT_MASK; 435 0 yongsun 436 0 yongsun if (m_CandiBone != firstBone) { 437 0 yongsun bool usCanceled = false; 438 0 yongsun for (CSkeletonIter bit = m_pIC->getFirstBone(); bit != m_CandiBone; ++bit) { 439 0 yongsun if (bit->isValidPinyinNode() && bit->isUserSelectionStart()) { 440 0 yongsun m_pIC->cancelSelection(bit, false); 441 0 yongsun usCanceled = true; 442 0 yongsun } 443 0 yongsun } 444 0 yongsun if (usCanceled) { 445 0 yongsun changeMask |= CANDIDATE_MASK; 446 0 yongsun leftmost = m_CandiBone = firstBone; 447 0 yongsun getCandidates(); 448 0 yongsun if (searchAgain) m_pIC->searchFrom(firstBone); 449 0 yongsun } 450 0 yongsun } 451 0 yongsun m_CursorIdx = 0; 452 0 yongsun m_CursorBone = firstBone; 453 0 yongsun return leftmost; 454 0 yongsun } 455 0 yongsun 456 0 yongsun void 457 0 yongsun CIMIClassicView::moveRight(unsigned int& changeMask) 458 0 yongsun { 459 0 yongsun CSkeletonIter itLast = m_pIC->getLastBone(); 460 0 yongsun if (m_CursorBone != itLast) { 461 0 yongsun CSkeletonIter itNext = ++CSkeletonIter(m_CursorBone); 462 0 yongsun if (m_CursorIdx < m_CursorBone->m_String.size()-1) { 463 0 yongsun ++m_CursorIdx; 464 0 yongsun changeMask |= PREEDIT_MASK; 465 0 yongsun } else if (m_CursorIdx == m_CursorBone->m_String.size()-1) { 466 0 yongsun if (m_CursorBone->isPinyinNode()) { 467 0 yongsun ++m_CursorIdx; 468 0 yongsun changeMask |= PREEDIT_MASK; 469 0 yongsun } else { 470 0 yongsun m_CursorIdx = 0; 471 0 yongsun ++m_CursorBone; 472 0 yongsun changeMask |= PREEDIT_MASK; 473 0 yongsun } 474 0 yongsun } else { // m_CursorIdx == m_CursorBone->m_String.size(), must be PinyinNode 475 0 yongsun if (itNext != itLast || m_CursorBone->isUserBoundary()) { 476 0 yongsun m_CursorIdx = 0; 477 0 yongsun ++m_CursorBone; 478 0 yongsun changeMask |= PREEDIT_MASK; 479 0 yongsun } 480 0 yongsun } 481 0 yongsun } 482 0 yongsun } 483 0 yongsun 484 0 yongsun void 485 0 yongsun CIMIClassicView::moveRightSyllable(unsigned int& changeMask) 486 0 yongsun { 487 0 yongsun CSkeletonIter itLast = m_pIC->getLastBone(); 488 0 yongsun if (m_CursorBone != itLast) { 489 0 yongsun CSkeletonIter itNext = ++CSkeletonIter(m_CursorBone); 490 0 yongsun if (itNext == itLast && m_CursorBone->isPinyinNode() && !m_CursorBone->isUserBoundary()) { 491 0 yongsun if (m_CursorIdx != m_CursorBone->m_String.size()) { 492 0 yongsun m_CursorIdx = m_CursorBone->m_String.size(); 493 0 yongsun changeMask |= PREEDIT_MASK; 494 0 yongsun } // else we already at tail 495 0 yongsun } else { 496 0 yongsun m_CursorIdx = 0; 497 0 yongsun ++m_CursorBone; 498 0 yongsun changeMask |= PREEDIT_MASK; 499 0 yongsun } 500 0 yongsun } 501 0 yongsun } 502 0 yongsun 503 0 yongsun void 504 0 yongsun CIMIClassicView::moveEnd(unsigned int& changeMask) 505 0 yongsun { 506 0 yongsun CSkeletonIter itLast = m_pIC->getLastBone(); 507 0 yongsun if (m_CursorBone != itLast) { 508 0 yongsun CSkeletonIter itPrev = --CSkeletonIter(itLast); 509 0 yongsun if (m_CursorBone != itPrev) { 510 0 yongsun m_CursorBone = itPrev; 511 0 yongsun m_CursorIdx = 0; 512 0 yongsun } 513 0 yongsun moveRightSyllable(changeMask); 514 0 yongsun } 515 0 yongsun } 516 0 yongsun 517 0 yongsun void 518 0 yongsun CIMIClassicView::erase(bool bLeft, unsigned int& changeMask) 519 0 yongsun { 520 0 yongsun if (bLeft && m_CursorBone == m_pIC->getFirstBone() && m_CursorIdx == 0) return; 521 0 yongsun if (!bLeft && cursorAtTail()) return; 522 0 yongsun 523 0 yongsun // default stick direction here 524 0 yongsun bool stickLeft = bLeft; 525 0 yongsun 526 0 yongsun if (bLeft) moveLeft(changeMask); 527 0 yongsun 528 0 yongsun changeMask |= PREEDIT_MASK; 529 0 yongsun if (m_CursorBone->m_String.size() == m_CursorIdx){ 530 0 yongsun if (m_CursorBone->m_BoundaryType == CBone::USER_BOUNDARY) { 531 0 yongsun CSkeleton skel; 532 0 yongsun CSkeletonIter old_cursor = m_CursorBone; 533 0 yongsun skel.push_front(*old_cursor); 534 0 yongsun skel.front().m_BoundaryType = CBone::AUTO_BOUNDARY; 535 0 yongsun m_CursorBone = skel.begin(); 536 0 yongsun bool upd_candi = m_pIC->modifyAndReseg( 537 0 yongsun old_cursor, ++CSkeletonIter(old_cursor), skel, 538 0 yongsun m_CursorBone, m_CursorIdx, m_CandiBone, 539 0 yongsun stickLeft, true 540 0 yongsun ); 541 0 yongsun if (upd_candi) getCandidates(); 542 0 yongsun changeMask |= CANDIDATE_MASK; 543 0 yongsun } else { 544 0 yongsun if (!bLeft) moveRight(changeMask); 545 0 yongsun } 546 0 yongsun } else { 547 0 yongsun CSkeleton skel; 548 0 yongsun CSkeletonIter old_cursor = m_CursorBone; 549 0 yongsun skel.push_front(*old_cursor); 550 0 yongsun skel.front().m_String.erase(m_CursorIdx, 1); 551 0 yongsun if (skel.front().m_String.size() == 0) { 552 0 yongsun skel.pop_front(); 553 0 yongsun m_CursorBone = skel.end(); 554 0 yongsun m_CursorIdx = 0; 555 0 yongsun } else { 556 0 yongsun if (m_CursorIdx == 0) 557 0 yongsun stickLeft = false; 558 0 yongsun else if (m_CursorIdx == m_CursorBone->m_String.size()-1) 559 0 yongsun stickLeft = true; 560 0 yongsun m_CursorBone = skel.begin(); 561 0 yongsun } 562 0 yongsun bool upd_candi = m_pIC->modifyAndReseg( 563 0 yongsun old_cursor, ++CSkeletonIter(old_cursor), skel, 564 0 yongsun m_CursorBone, m_CursorIdx, m_CandiBone, 565 0 yongsun stickLeft, true 566 0 yongsun ); 567 0 yongsun if (upd_candi) getCandidates(); 568 0 yongsun changeMask |= CANDIDATE_MASK; 569 0 yongsun } 570 0 yongsun } 571 0 yongsun 572 0 yongsun void 573 0 yongsun CIMIClassicView::insertPinyin(unsigned int keyvalue, unsigned int& changeMask) 574 0 yongsun { 575 0 yongsun CSkeleton skel; 576 0 yongsun CSkeletonIter cursor1 = m_CursorBone, cursor2 = m_CursorBone; 577 0 yongsun 578 0 yongsun changeMask |= PREEDIT_MASK | CANDIDATE_MASK; 579 0 yongsun if (m_CursorBone == m_pIC->getLastBone()) { 580 0 yongsun skel.push_front(CBone((const TWCHAR*)&keyvalue, 1, CBone::AUTO_BOUNDARY, CBone::NODE_PINYIN)); 581 0 yongsun m_CursorBone = skel.begin(); 582 0 yongsun m_CursorIdx = 1; 583 0 yongsun } else if (!m_CursorBone->isPinyinNode()){ 584 0 yongsun // The cursor could not on the tail of non-pinyin nodes 585 0 yongsun if (m_CursorIdx > 0) { 586 0 yongsun ++cursor2; 587 0 yongsun skel.push_back(CBone(*m_CursorBone)); 588 0 yongsun skel.back().m_String.erase(m_CursorIdx); 589 0 yongsun skel.push_back(CBone((const TWCHAR*)&keyvalue, 1, CBone::AUTO_BOUNDARY, CBone::NODE_PINYIN)); 590 0 yongsun skel.push_back(CBone(*m_CursorBone)); 591 0 yongsun skel.back().m_String.erase(0, m_CursorIdx); 592 0 yongsun m_CursorBone = skel.begin(); ++m_CursorBone; 593 0 yongsun m_CursorIdx = 1; 594 0 yongsun } else { 595 0 yongsun skel.push_front(CBone((const TWCHAR*)&keyvalue, 1, CBone::AUTO_BOUNDARY, CBone::NODE_PINYIN)); 596 0 yongsun m_CursorBone = skel.begin(); 597 0 yongsun m_CursorIdx = 0; 598 0 yongsun } 599 0 yongsun } else { 600 0 yongsun skel.push_front(*m_CursorBone); 601 0 yongsun skel.front().m_String.insert(m_CursorIdx, 1, TWCHAR(keyvalue)); 602 0 yongsun m_CursorBone = skel.begin(); 603 0 yongsun ++m_CursorIdx; 604 0 yongsun ++cursor2; 605 0 yongsun } 606 0 yongsun 607 0 yongsun bool upd_candi = m_pIC->modifyAndReseg(cursor1, cursor2, skel, m_CursorBone, m_CursorIdx, m_CandiBone); 608 0 yongsun 609 0 yongsun if (upd_candi) getCandidates(); 610 0 yongsun } 611 0 yongsun 612 0 yongsun void 613 0 yongsun CIMIClassicView::insertBoundary(unsigned int& changeMask) 614 0 yongsun { 615 0 yongsun CSkeletonIter itLast = m_pIC->getLastBone(); 616 0 yongsun CSkeletonIter itFirst = m_pIC->getFirstBone(); 617 0 yongsun 618 0 yongsun if (m_CursorIdx == 0) { 619 0 yongsun if (m_CursorBone != itFirst) { 620 0 yongsun CSkeletonIter itPrev = --CSkeletonIter(m_CursorBone); 621 0 yongsun if (itPrev->isPinyinNode() && itPrev->isAutoBoundary()) { 622 0 yongsun changeMask |= PREEDIT_MASK; // Only the color of the boundary needed to be updated 623 0 yongsun itPrev->m_BoundaryType = CBone::USER_BOUNDARY; 624 0 yongsun } 625 0 yongsun } 626 0 yongsun } else if (m_CursorBone != itLast && m_CursorIdx == m_CursorBone->m_String.size()) { 627 0 yongsun if (m_CursorBone->isAutoBoundary()) { // hidden condition: it is a pinyin node 628 0 yongsun changeMask |= PREEDIT_MASK; // Only the color of the boundary needed to be updated 629 0 yongsun m_CursorBone->m_BoundaryType = CBone::USER_BOUNDARY; 630 0 yongsun moveRight(changeMask); 631 0 yongsun } 632 0 yongsun } else if (m_CursorBone != itLast && m_CursorIdx < m_CursorBone->m_String.size()) { 633 0 yongsun if (m_CursorBone->isPinyinNode()) { 634 0 yongsun changeMask |= PREEDIT_MASK | CANDIDATE_MASK; 635 140 tonylee 636 140 tonylee if (m_CursorBone != itFirst) { 637 140 tonylee bool saveNonCompleteSyllable = m_pIC->canNonCompleteSyllable(); 638 140 tonylee m_pIC->setNonCompleteSyllable(false); 639 140 tonylee do { // whether current syllable should be connected with the previous one. 640 140 tonylee CSkeletonIter itPrev = --CSkeletonIter(m_CursorBone); 641 140 tonylee if (!itPrev->isAutoBoundary()) break; 642 140 tonylee 643 140 tonylee std::list<CBone> newBones; 644 140 tonylee wstring newSyllable; 645 140 tonylee 646 140 tonylee newSyllable.append(m_CursorBone->m_String, 0, m_CursorIdx); 647 140 tonylee m_pIC->segPinyinSimplest(newSyllable, newBones); 648 140 tonylee if ( !(newBones.size() == 0 || newBones.front().m_BoneType == CBone::NODE_INCOMPLETE_PINYIN) ) break; 649 140 tonylee 650 140 tonylee newBones.clear(); 651 140 tonylee newSyllable.insert(0, itPrev->m_String); 652 140 tonylee m_pIC->segPinyinSimplest(newSyllable, newBones); 653 140 tonylee if (newBones.size() != 1 || newBones.front().m_BoneType != CBone::NODE_PINYIN) break; 654 140 tonylee 655 140 tonylee m_pIC->setNonCompleteSyllable(saveNonCompleteSyllable); 656 140 tonylee 657 140 tonylee newBones.front().m_BoundaryType = CBone::USER_BOUNDARY; 658 140 tonylee m_pIC->modify(itPrev, m_CursorBone, newBones); 659 140 tonylee if (m_CandiBone == itPrev) 660 140 tonylee m_CandiBone = --CSkeletonIter(m_CursorBone); 661 140 tonylee 662 140 tonylee CSkeleton skel; 663 140 tonylee CSkeletonIter cursor1 = m_CursorBone; 664 140 tonylee CSkeletonIter cursor2 = m_CursorBone; 665 140 tonylee ++cursor2; 666 140 tonylee 667 140 tonylee skel.push_back(CBone(*m_CursorBone)); 668 140 tonylee skel.back().m_String.erase(0, m_CursorIdx); 669 140 tonylee m_CursorBone = skel.begin(); 670 140 tonylee m_CursorIdx = 0; 671 140 tonylee m_pIC->modifyAndReseg( 672 140 tonylee cursor1, cursor2, skel, 673 140 tonylee m_CursorBone, m_CursorIdx, m_CandiBone, false 674 140 tonylee ); 675 140 tonylee getCandidates(); 676 140 tonylee return; 677 140 tonylee } while (false); 678 140 tonylee m_pIC->setNonCompleteSyllable(saveNonCompleteSyllable); 679 140 tonylee } 680 140 tonylee 681 0 yongsun CSkeleton skel; 682 0 yongsun CSkeletonIter cursor1 = m_CursorBone; 683 0 yongsun CSkeletonIter cursor2 = m_CursorBone; 684 0 yongsun ++cursor2; 685 0 yongsun 686 0 yongsun skel.push_back(CBone(*m_CursorBone)); 687 0 yongsun skel.back().m_String.erase(m_CursorIdx); 688 0 yongsun skel.back().m_BoundaryType = CBone::USER_BOUNDARY; 689 0 yongsun skel.push_back(CBone(*m_CursorBone)); 690 0 yongsun skel.back().m_String.erase(0, m_CursorIdx); 691 0 yongsun m_CursorBone = skel.begin(); 692 0 yongsun ++m_CursorBone; 693 0 yongsun m_CursorIdx = 0; 694 0 yongsun bool upd_candi = m_pIC->modifyAndReseg( 695 0 yongsun cursor1, cursor2, skel, 696 0 yongsun m_CursorBone, m_CursorIdx, m_CandiBone, false 697 0 yongsun ); 698 0 yongsun if (upd_candi) getCandidates(); 699 0 yongsun } 700 0 yongsun } 701 0 yongsun } 702 0 yongsun 703 0 yongsun int 704 0 yongsun CIMIClassicView::getSentence(wstring& wstr, CSkeletonIter itStart) 705 0 yongsun { 706 0 yongsun return m_pIC->getBestSentence(wstr, itStart, m_pIC->getLastBone()); 707 0 yongsun } 708 0 yongsun 709 0 yongsun void 710 0 yongsun CIMIClassicView::insertNormalChar(int boneType, unsigned originalKey, unsigned keyvalue, unsigned int& mask) 711 0 yongsun { 712 0 yongsun CSkeleton skel; 713 0 yongsun CSkeletonIter cursor1; 714 0 yongsun CSkeletonIter cursor2; 715 0 yongsun CSkeletonIter ite = m_pIC->getLastBone(); 716 0 yongsun mask |= PREEDIT_MASK | CANDIDATE_MASK; 717 0 yongsun if (m_CursorBone == ite || m_CursorBone->m_String.size() == 0) { 718 0 yongsun cursor1 = cursor2 = m_CursorBone; 719 0 yongsun skel.push_back(CBone((TWCHAR*)&keyvalue, 1, originalKey, boneType)); 720 0 yongsun } else if (m_CursorBone != ite && m_CursorBone->m_String.size() == m_CursorIdx) { 721 0 yongsun cursor1 = cursor2 = ++m_CursorBone; 722 0 yongsun skel.push_back(CBone((TWCHAR*)&keyvalue, 1, originalKey, boneType)); 723 0 yongsun m_CursorBone = skel.begin(); 724 0 yongsun ++m_CursorBone; 725 0 yongsun m_CursorIdx = 0; 726 0 yongsun 727 0 yongsun } else { 728 0 yongsun cursor1 = cursor2 = m_CursorBone; ++cursor2; 729 0 yongsun skel.push_back(CBone(*m_CursorBone)); 730 0 yongsun skel.back().m_String.erase(m_CursorIdx); 731 0 yongsun skel.push_back(CBone((TWCHAR*)&keyvalue, 1, originalKey, boneType)); 732 0 yongsun skel.push_back(CBone(*m_CursorBone)); 733 0 yongsun skel.back().m_String.erase(0, m_CursorIdx); 734 0 yongsun m_CursorBone = skel.begin(); 735 0 yongsun ++(++m_CursorBone); 736 0 yongsun m_CursorIdx = 0; 737 0 yongsun } 738 0 yongsun bool upd_candi = m_pIC->modifyAndReseg(cursor1, cursor2, skel, m_CursorBone, 739 0 yongsun m_CursorIdx, m_CandiBone, false); 740 0 yongsun if (upd_candi) getCandidates(); 741 0 yongsun } 742 0 yongsun 743 0 yongsun void 744 0 yongsun CIMIClassicView::getCandidates() 745 0 yongsun { 746 0 yongsun m_CandiFirst = 0; 747 0 yongsun m_pIC->getCandidates(m_CandiBone, m_CandiList); 748 0 yongsun } 749 0 yongsun 750 0 yongsun bool 751 0 yongsun CIMIClassicView::cursorAtTail() 752 0 yongsun { 753 0 yongsun CSkeletonIter itLast = m_pIC->getLastBone(); 754 0 yongsun if (m_CursorBone == itLast) 755 0 yongsun return true; 756 0 yongsun CSkeletonIter itNext = ++CSkeletonIter(m_CursorBone); 757 0 yongsun return (itNext == itLast && m_CursorBone->m_String.size() == m_CursorIdx && !m_CursorBone->isUserBoundary()); 758 0 yongsun // Hidden condition m_CursorBone->isPinyinNode() == true 759 0 yongsun } 760 0 yongsun 761 0 yongsun void 762 0 yongsun CIMIClassicView::makeSelection(int idx, unsigned int& mask) 763 0 yongsun { 764 0 yongsun idx += m_CandiFirst; 765 0 yongsun if (m_TailSentence.size() > 0) --idx; 766 0 yongsun if (idx < 0) { 767 0 yongsun mask |= PREEDIT_MASK | CANDIDATE_MASK; 768 0 yongsun doCommit(true); 769 0 yongsun clearIC(); 770 0 yongsun } else if (idx < m_CandiList.size()) { 771 0 yongsun mask |= PREEDIT_MASK | CANDIDATE_MASK; 772 0 yongsun CCandidate& cand = m_CandiList[idx]; 773 0 yongsun m_pIC->makeSelection(cand); 774 0 yongsun m_CandiBone = cand.m_BoneEnd; 775 0 yongsun while (!m_CandiBone->isTailNode() && !m_CandiBone->isPinyinNode()) 776 0 yongsun ++m_CandiBone; 777 0 yongsun if (m_CandiBone->isTailNode()) { 778 0 yongsun doCommit(true); 779 0 yongsun clearIC(); 780 0 yongsun } else { 781 0 yongsun for (CSkeletonIter it=cand.m_BoneStart; it != m_CandiBone; ++it) { 782 0 yongsun if (m_CursorBone == it) { 783 0 yongsun m_CursorBone = m_CandiBone; 784 0 yongsun m_CursorIdx = 0; 785 0 yongsun break; 786 0 yongsun } 787 0 yongsun } 788 0 yongsun m_CandiFirst = 0; 789 0 yongsun getCandidates(); 790 0 yongsun } 791 0 yongsun } 792 0 yongsun } 793 0 yongsun 794 0 yongsun void 795 0 yongsun CIMIClassicView::getPreeditString(IPreeditString& ps) 796 0 yongsun { 797 0 yongsun ps.clear(); 798 0 yongsun 799 0 yongsun wstring & wstr = ps.getString(); 800 0 yongsun IPreeditString::CCharTypeVec& charTypes = ps.getCharTypeVec(); 801 0 yongsun 802 0 yongsun m_pIC->getBestSentence(wstr, m_pIC->getFirstBone(), m_CandiBone); 803 0 yongsun 804 0 yongsun int caret = wstr.size(); 805 0 yongsun charTypes.reserve(caret); 806 0 yongsun for (int i=0; i < caret; ++i) 807 0 yongsun charTypes.push_back(IPreeditString::HANZI_CHAR | IPreeditString::USER_CHOICE); 808 0 yongsun ps.setCandiStart(caret); 809 0 yongsun 810 0 yongsun CSkeletonIter ite = m_pIC->getLastBone(); 811 0 yongsun for (CSkeletonIter it = m_CandiBone; it != ite; ) { 812 0 yongsun CSkeletonIter curIt = it++; 813 0 yongsun if (curIt == m_CursorBone) 814 0 yongsun caret = wstr.size() + m_CursorIdx; 815 0 yongsun 816 0 yongsun if (curIt->isPinyinNode()) 817 0 yongsun wstr += curIt->m_String; 818 0 yongsun else 819 0 yongsun wstr.push_back((unsigned)curIt->m_BoundaryType); 820 0 yongsun 821 0 yongsun int ct = IPreeditString::PINYIN_CHAR; 822 0 yongsun if (curIt->m_BoneType == CBone::NODE_INVALID_PINYIN) 823 0 yongsun ct |= IPreeditString::ILLEGAL; 824 0 yongsun else if (curIt->m_BoneType == CBone::NODE_ASCII) 825 0 yongsun ct = IPreeditString::ASCII_CHAR; 826 0 yongsun else if (!curIt->isPinyinNode()) 827 0 yongsun ct = IPreeditString::SIMBOL_CHAR; 828 0 yongsun 829 0 yongsun for (int i=0; i < curIt->m_String.size(); ++i) 830 0 yongsun charTypes.push_back(ct); 831 0 yongsun 832 0 yongsun if (curIt->isPinyinNode()) { 833 0 yongsun if (curIt->m_BoundaryType == CBone::USER_BOUNDARY) { 834 0 yongsun wstr += '\''; 835 0 yongsun charTypes.push_back(IPreeditString::BOUNDARY); 836 0 yongsun } else if (it != ite) { 837 0 yongsun wstr += ' '; 838 0 yongsun charTypes.push_back(IPreeditString::BOUNDARY | IPreeditString::USER_CHOICE); 839 0 yongsun } 840 0 yongsun } 841 0 yongsun } 842 0 yongsun if (m_CursorBone == ite) 843 0 yongsun caret = wstr.size(); 844 0 yongsun ps.setCaret(caret); 845 0 yongsun } 846 0 yongsun 847 0 yongsun void 848 0 yongsun CIMIClassicView::getCandidateList(ICandidateList& cl, int start, int size) 849 0 yongsun { 850 0 yongsun cl.clear(); 851 0 yongsun cl.reserve(size); 852 0 yongsun 853 0 yongsun int tscount = (m_TailSentence.size() > 0)?1:0; 854 0 yongsun 855 0 yongsun cl.setFirst(start); 856 0 yongsun cl.setTotal(tscount + m_CandiList.size()); 857 0 yongsun ICandidateList::CCandiStrings& css = cl.getCandiStrings(); 858 0 yongsun ICandidateList::CCandiTypeVec& cts = cl.getCandiTypeVec(); 859 0 yongsun 860 0 yongsun //Loop used for future n-best sentence candidates usage 861 0 yongsun for (; start < tscount && size > 0; ++start, --size) { 862 0 yongsun css.push_back(m_TailSentence); 863 0 yongsun cts.push_back(ICandidateList::BEST_TAIL); 864 0 yongsun } 865 0 yongsun 866 0 yongsun start -= tscount; 867 0 yongsun for (int sz=m_CandiList.size(); start < sz && size > 0; ++start, --size) { 868 0 yongsun css.push_back(m_CandiList[start].m_String); 869 0 yongsun cts.push_back( (start == 0)?(ICandidateList::BEST_WORD):(ICandidateList::NORMAL_WORD) ); 870 0 yongsun } 871 0 yongsun } 872