// Takes ownership of "candidate" void R2RegionCoverer::deleteCandidate( Candidate* candidate, bool freeChildren ) { if (freeChildren) { for (int i = 0; i < candidate->numChildren; i++) { deleteCandidate(candidate->children[i], true); } } delete candidate; }
void R2RegionCoverer::getCovering( const R2Region& region, vector<GeoHash>* cover ) { // Strategy: Start with the full plane. Discard any // that do not intersect the shape. Then repeatedly choose the // largest cell that intersects the shape and subdivide it. // // _result contains the cells that will be part of the output, while the // queue contains cells that we may still subdivide further. Cells that // are entirely contained within the region are immediately added to the // output, while cells that do not intersect the region are immediately // discarded. Therefore the queue only contains cells that partially // intersect the region. Candidates are prioritized first according to // cell size (larger cells first), then by the number of intersecting // children they have (fewest children first), and then by the number of // fully contained children (fewest children first). verify(_minLevel <= _maxLevel); dassert(_candidateQueue->empty()); dassert(_results->empty()); _region = ®ion; getInitialCandidates(); while(!_candidateQueue->empty()) { Candidate* candidate = _candidateQueue->top().second; // Owned _candidateQueue->pop(); LOG(3) << "Pop: " << candidate->cell; // Try to expand this cell into its children if (candidate->cell.getBits() < _minLevel || candidate->numChildren == 1 || (int)_results->size() + (int)_candidateQueue->size() + candidate->numChildren <= _maxCells) { for (int i = 0; i < candidate->numChildren; i++) { addCandidate(candidate->children[i]); } deleteCandidate(candidate, false); } else { // Reached max cells. Move all candidates from the queue into results. candidate->isTerminal = true; addCandidate(candidate); } LOG(3) << "Queue: " << _candidateQueue->size(); } _region = NULL; cover->swap(*_results); }
// Takes ownership of "candidate" void R2RegionCoverer::addCandidate( Candidate* candidate ) { if (candidate == NULL) return; if (candidate->isTerminal) { _results->push_back(candidate->cell); deleteCandidate(candidate, true); return; } verify(candidate->numChildren == 0); // Expand children int numTerminals = expandChildren(candidate); if (candidate->numChildren == 0) { deleteCandidate(candidate, true); } else if (numTerminals == 4 && candidate->cell.getBits() >= _minLevel) { // Optimization: add the parent cell rather than all of its children. candidate->isTerminal = true; addCandidate(candidate); } else { // Add the cell into the priority queue for further subdivision. // // We negate the priority so that smaller absolute priorities are returned // first. The heuristic is designed to refine the largest cells first, // since those are where we have the largest potential gain. Among cells // at the same level, we prefer the cells with the smallest number of // intersecting children. Finally, we prefer cells that have the smallest // number of children that cannot be refined any further. int priority = -((((candidate->cell.getBits() << 4) + candidate->numChildren) << 4) + numTerminals); _candidateQueue->push(make_pair(priority, candidate)); // queue owns candidate LOG(3) << "Push: " << candidate->cell << " (" << priority << ") "; } }
bool CIMIClassicView::onKeyEvent(const CKeyEvent& key) { unsigned changeMasks = 0; unsigned keycode = key.code; unsigned keyvalue = key.value; unsigned modifiers = key.modifiers; #ifdef DEBUG printf("Classic View got a key (0x%x-0x%x-0x%x)...", keycode, keyvalue, modifiers); if (((modifiers & IM_CTRL_MASK) != 0) && (keyvalue == 'P' || keyvalue == 'p')) m_pIC->printLattice(); #endif if (m_pHotkeyProfile && m_pHotkeyProfile->isModeSwitchKey(key)) { setStatusAttrValue(CIMIWinHandler::STATUS_ID_CN, (!m_bCN) ? 1 : 0); if (!m_pIC->isEmpty()) { changeMasks |= CANDIDATE_MASK | PREEDIT_MASK; clearIC(); } } else if (m_pHotkeyProfile && m_pHotkeyProfile->isPunctSwitchKey(key)) { // On CTRL+. switch Full/Half punc changeMasks |= KEYEVENT_USED; setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLPUNC, (!m_bFullPunct) ? 1 : 0); } else if (m_pHotkeyProfile && m_pHotkeyProfile->isSymbolSwitchKey(key)) { // On SHIFT+SPACE switch Full/Half symbol changeMasks |= KEYEVENT_USED; setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLSYMBOL, (!m_bFullSymbol) ? 1 : 0); } else if (modifiers == IM_CTRL_MASK && keycode == IM_VK_LEFT) { // move left if (!m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED; _moveLeft(changeMasks); } } else if (modifiers == IM_CTRL_MASK && keycode == IM_VK_RIGHT) { // move right if (!m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED; _moveRight(changeMasks); } } else if (((modifiers == 0 && keycode == IM_VK_PAGE_UP) || (m_pHotkeyProfile && m_pHotkeyProfile->isPageUpKey(key))) && !m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED; if (m_candiPageFirst > 0) { m_candiPageFirst -= m_candiWindowSize; if (m_candiPageFirst < 0) m_candiPageFirst = 0; changeMasks |= CANDIDATE_MASK; } } else if (((modifiers == 0 && keycode == IM_VK_PAGE_DOWN) || (m_pHotkeyProfile && m_pHotkeyProfile->isPageDownKey(key))) && !m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED; if (m_candiPageFirst + m_candiWindowSize < candidateListSize()) { m_candiPageFirst += m_candiWindowSize; changeMasks |= CANDIDATE_MASK; } } else if (m_pHotkeyProfile && m_pHotkeyProfile->isCandiDeleteKey(key, m_candiWindowSize) && !m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED; unsigned sel = (keyvalue == '0' ? 9 : keyvalue - '1'); deleteCandidate(sel, changeMasks); goto PROCESSED; } else if ((modifiers & (IM_CTRL_MASK | IM_ALT_MASK | IM_SUPER_MASK | IM_RELEASE_MASK)) == 0) { if ((keyvalue >= '0' && keyvalue <= '9') && (m_candiWindowSize >= 10 || keyvalue < ('1' + m_candiWindowSize))) { // try to make selection if (!m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED; unsigned sel = (keyvalue == '0' ? 9 : keyvalue - '1'); makeSelection(sel, changeMasks); } else if (m_smartPunct) { m_pIC->omitNextPunct(); } goto PROCESSED; } if (keyvalue > 0x60 && keyvalue < 0x7b) { /* islower(keyvalue) */ changeMasks |= KEYEVENT_USED; #if !defined(__APPLE__) _insert(keyvalue, changeMasks); #else _insert(keyvalue, changeMasks, ^{}); #endif } else if (keyvalue > 0x20 && keyvalue < 0x7f) {
bool CIMIXhView::onKeyEvent(const CKeyEvent& key) { unsigned changeMasks = 0; unsigned keycode = key.code; unsigned keyvalue = key.value; unsigned modifiers = key.modifiers; bool isKeyStroke = false; #ifdef DEBUG printf("Xh View got a key (0x%x-0x%x-0x%x)...\n", keycode, keyvalue, modifiers); if (((modifiers & IM_CTRL_MASK) != 0) && (keyvalue == 'P' || keyvalue == 'p')) m_pIC->printLattice(); #endif if (m_pHotkeyProfile && m_pHotkeyProfile->isModeSwitchKey(key)) { setStatusAttrValue(CIMIWinHandler::STATUS_ID_CN, (!m_bCN) ? 1 : 0); if (!m_pIC->isEmpty()) { changeMasks |= CANDIDATE_MASK | PREEDIT_MASK; clearIC(); } } else if (m_pHotkeyProfile && m_pHotkeyProfile->isPunctSwitchKey(key)) { // On CTRL+. switch Full/Half punc changeMasks |= KEYEVENT_USED; setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLPUNC, (!m_bFullPunct) ? 1 : 0); } else if (m_pHotkeyProfile && m_pHotkeyProfile->isSymbolSwitchKey(key)) { // On SHIFT+SPACE switch Full/Half symbol changeMasks |= KEYEVENT_USED; setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLSYMBOL, (!m_bFullSymbol) ? 1 : 0); } else if (modifiers == IM_CTRL_MASK && keycode == IM_VK_LEFT) { // move left if (!m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED; _moveLeft(changeMasks); } } else if (modifiers == IM_CTRL_MASK && keycode == IM_VK_RIGHT) { // move right if (!m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED; _moveRight(changeMasks); } } else if (((modifiers == 0 && keycode == IM_VK_PAGE_UP) || (m_pHotkeyProfile && m_pHotkeyProfile->isPageUpKey(key))) && !m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED; if (m_candiPageFirst > 0) { m_candiPageFirst -= m_candiWindowSize; if (m_candiPageFirst < 0) m_candiPageFirst = 0; changeMasks |= CANDIDATE_MASK; } } else if (((modifiers == 0 && keycode == IM_VK_PAGE_DOWN) || (m_pHotkeyProfile && m_pHotkeyProfile->isPageDownKey(key))) && !m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED; if (m_candiPageFirst + m_candiWindowSize < candidateListSize()) { m_candiPageFirst += m_candiWindowSize; changeMasks |= CANDIDATE_MASK; } } else if (m_pHotkeyProfile && m_pHotkeyProfile->isCandiDeleteKey(key, m_candiWindowSize) && !m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED; unsigned sel = (keyvalue == '0' ? 9 : keyvalue - '1'); deleteCandidate(sel, changeMasks); goto PROCESSED; } else if ((modifiers & (IM_CTRL_MASK | IM_ALT_MASK | IM_SUPER_MASK | IM_RELEASE_MASK)) == 0) { if (isKeyValueSelectNumber(keyvalue)) { // try to make selection if (!m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED; unsigned sel = getSelectionNumber(keyvalue); makeSelection(sel, changeMasks); } else if (m_smartPunct) { m_pIC->omitNextPunct(); } // using the same keys between selections isKeyStroke = true; goto PROCESSED; } if (keyvalue >= '1' && keyvalue <= '5') { changeMasks |= KEYEVENT_USED; _insert(keyvalue, changeMasks); isKeyStroke = true; } else if (keyvalue > 0x60 && keyvalue < 0x7b) { /* islower(keyvalue) */ changeMasks |= KEYEVENT_USED; _insert(keyvalue, changeMasks); isKeyStroke = true; } else if (keyvalue > 0x20 && keyvalue < 0x7f) { /* isprint(keyvalue) && !isspace(keyvalue) */ changeMasks |= KEYEVENT_USED; if (m_pIC->isEmpty()) { _insert(keyvalue, changeMasks); _doCommit(); clearIC(); } else { _insert(keyvalue, changeMasks); } isKeyStroke = true; } else if (keycode == IM_VK_BACK_SPACE || keycode == IM_VK_DELETE) { if (!m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED; _erase(keycode == IM_VK_BACK_SPACE, changeMasks); } isKeyStroke = true; } else if (keycode == IM_VK_SPACE) { if (!m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED; makeSelection(0, changeMasks); } else { wstring wstr = (CFullCharManager::fullPuncOp())(keyvalue); if (wstr.size()) { _commitString(wstr); changeMasks |= KEYEVENT_USED; } } } else if (keycode == IM_VK_ENTER) { if (!m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED | CANDIDATE_MASK | PREEDIT_MASK; _doCommit(false); clearIC(); } } else if (keycode == IM_VK_ESCAPE) { if (!m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED | CANDIDATE_MASK | PREEDIT_MASK; clearIC(); } } else if (keycode == IM_VK_LEFT) { // move left syllable if (!m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED; _moveLeftSyllable(changeMasks); } } else if (keycode == IM_VK_RIGHT) { // move right syllable if (!m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED; _moveRightSyllable(changeMasks); } } else if (keycode == IM_VK_HOME) { // move home if (!m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED; _moveHome(changeMasks); } } else if (keycode == IM_VK_END) { // move end if (!m_pIC->isEmpty()) { changeMasks |= KEYEVENT_USED; _moveEnd(changeMasks); } } } else { goto RETURN; } PROCESSED:; m_pHotkeyProfile->rememberLastKey(key); RETURN:; if (isKeyStroke) { setOpMode(XHVOM_INPUT); } else { setOpMode(XHVOM_SELECT); } #ifdef DEBUG printf(" |-->(Mask=0x%x)\n", changeMasks); #endif updateWindows(changeMasks); return changeMasks & KEYEVENT_USED; }