// Visits all PtNodes in post-order depth first manner. // For example, visits c -> b -> y -> x -> a for the following dictionary: // a _ b _ c // \ x _ y bool DynamicPatriciaTrieReadingHelper::traverseAllPtNodesInPostorderDepthFirstManner( TraversingEventListener *const listener) { bool alreadyVisitedChildren = false; // Descend from the root to the root PtNode array. if (!listener->onDescend(getPosOfLastPtNodeArrayHead())) { return false; } while (!isEnd()) { if (!alreadyVisitedChildren) { if (mNodeReader.hasChildren()) { // Move to the first child. if (!listener->onDescend(mNodeReader.getChildrenPos())) { return false; } pushReadingStateToStack(); readChildNode(); } else { alreadyVisitedChildren = true; } } else { if (!listener->onVisitingPtNode(&mNodeReader, mMergedNodeCodePoints)) { return false; } readNextSiblingNode(); if (isEnd()) { // All PtNodes in current linked PtNode arrays have been visited. // Return to the parent. if (!listener->onReadingPtNodeArrayTail()) { return false; } if (mReadingStateStack.size() <= 0) { break; } if (!listener->onAscend()) { return false; } popReadingStateFromStack(); alreadyVisitedChildren = true; } else { // Process sibling PtNode. alreadyVisitedChildren = false; } } } // Ascend from the root PtNode array to the root. if (!listener->onAscend()) { return false; } return !isError(); }
/*! \fn guiAskForLoginSelect(pNode* p, cNode* c, uint16_t parentNodeAddress) * \brief Ask for user login selection / approval * \param p Pointer to a parent node * \param c Pointer to a child node * \param parentNodeAddress Address of the parent node * \param bypass_confirmation Bool to bypass authorisation request * \return Valid child node address or 0 otherwise */ uint16_t guiAskForLoginSelect(pNode* p, cNode* c, uint16_t parentNodeAddress, uint8_t bypass_confirmation) { uint16_t first_child_address, temp_child_address; uint16_t picked_child = NODE_ADDR_NULL; uint16_t addresses[4]; uint8_t led_mask; int8_t i, j; // Check parent node address if (parentNodeAddress == NODE_ADDR_NULL) { return NODE_ADDR_NULL; } // Read the parent node readParentNode(p, parentNodeAddress); // Read its first child address first_child_address = p->nextChildAddress; // Check if there are stored credentials if (first_child_address == NODE_ADDR_NULL) { guiDisplayInformationOnScreenAndWait(ID_STRING_NO_CREDS); return NODE_ADDR_NULL; } // Read child node readChildNode(c, first_child_address); // Check if there's only one child, that's a confirmation screen if (c->nextChildAddress == NODE_ADDR_NULL) { confirmationText_t temp_conf_text; // Prepare asking confirmation screen temp_conf_text.lines[0] = readStoredStringToBuffer(ID_STRING_CONFACCESSTO); temp_conf_text.lines[1] = (char*)p->service; temp_conf_text.lines[2] = readStoredStringToBuffer(ID_STRING_WITHTHISLOGIN); temp_conf_text.lines[3] = (char*)c->login; // Prompt user for confirmation, flash the screen if ((bypass_confirmation == TRUE) || (guiAskForConfirmation(0xF0 | 4, &temp_conf_text) == RETURN_OK)) { picked_child = first_child_address; } } else { temp_child_address = first_child_address; uint8_t action_chosen = FALSE; while (action_chosen == FALSE) { // Draw asking bitmap oledBitmapDrawFlash(0, 0, BITMAP_LOGIN, 0); // Write domain name on screen char temp_string[INDEX_TRUNCATE_SERVICE_CENTER+1]; memcpy(temp_string, (char*)p->service, sizeof(temp_string)); temp_string[INDEX_TRUNCATE_SERVICE_CENTER] = 0; oledPutstrXY(0, 24, OLED_CENTRE, temp_string); // Clear led_mask led_mask = 0; i = 0; // List logins on screen while ((temp_child_address != NODE_ADDR_NULL) && (i != 4)) { // Read child node to get login readChildNode(c, temp_child_address); // Print Login at the correct slot displayCredentialAtSlot(i, (char*)c->login, INDEX_TRUNCATE_LOGIN_FAV); // Store address in array, fetch next address addresses[i] = temp_child_address; temp_child_address = c->nextChildAddress; i++; } // If nothing after, hide right arrow if ((i != 4) || (c->nextChildAddress == NODE_ADDR_NULL)) { oledFillXY(177, 25, 16, 14, 0x00); led_mask |= LED_MASK_RIGHT; } // Light only the available choices for (j = i; j < 4; j++) { led_mask |= (1 << j); } // Display picture oledDisplayOtherBuffer(); // Get touched quarter j = getTouchedPositionAnswer(led_mask); // Check its validity, knowing that by default we will return NODE_ADDR_NULL if (j == -1) { // Time out action_chosen = TRUE; } else if (j < i) { picked_child = addresses[j]; action_chosen = TRUE; } else if (j == TOUCHPOS_LEFT) { // If there is a previous children, go back 4 indexes if (addresses[0] != first_child_address) { c->prevChildAddress = addresses[0]; for (i = 0; i < 5; i++) { temp_child_address = c->prevChildAddress; readChildNode(c, temp_child_address); } } else { // otherwise, return action_chosen = TRUE; } } else if ((j == TOUCHPOS_RIGHT) && (i == 4) && (c->nextChildAddress != NODE_ADDR_NULL)) { // If there are more nodes to display, let it loop // temp_child_address = c->nextChildAddress; } else { // Wrong position temp_child_address = addresses[0]; } } } return picked_child; }
/*! \fn favoriteSelectionScreen(pNode* p, cNode* c) * \brief Screen displayed to let the user choose a favorite * \param p Pointer to a parent node * \param c Pointer to a child node * \return Valid child node address or 0 otherwise */ uint16_t favoriteSelectionScreen(pNode* p, cNode* c) { uint16_t picked_child = NODE_ADDR_NULL; uint16_t parentAddresses[USER_MAX_FAV]; uint16_t childAddresses[USER_MAX_FAV]; uint16_t tempparaddr, tempchildaddr; uint8_t action_chosen = FALSE; uint8_t nbFavorites = 0; uint8_t offset = 0; uint8_t led_mask; int8_t i, j; // Browse through the favorites for (i = 0; i < USER_MAX_FAV; i++) { // Read favorite, check that it is valid readFav(i, &tempparaddr, &tempchildaddr); // If so, store it in our know addresses if (tempparaddr != NODE_ADDR_NULL) { parentAddresses[nbFavorites] = tempparaddr; childAddresses[nbFavorites++] = tempchildaddr; } } // If no favorite, return if (nbFavorites == 0) { guiDisplayInformationOnScreenAndWait(ID_STRING_NOSTOREDFAV); return NODE_ADDR_NULL; } // Loop until the user chooses smth while (action_chosen != TRUE) { // Draw asking bitmap oledBitmapDrawFlash(0, 0, BITMAP_LOGIN, 0); // Clear led_mask led_mask = 0; i = 0; // List logins on screen while (((offset + i) < nbFavorites) && (i != 4)) { // Read child node to get login readChildNode(c, childAddresses[offset+i]); readParentNode(p, parentAddresses[offset+i]); // Print service / login on screen displayCredentialAtSlot(i+((i&0x02)<<2), (char*)c->login, INDEX_TRUNCATE_LOGIN_FAV); displayCredentialAtSlot(i+((~i&0x02)<<2), (char*)p->service, INDEX_TRUNCATE_LOGIN_FAV); // Increment i i++; } // If nothing after, hide right arrow if ((i != 4) || ((offset+i) == nbFavorites)) { oledFillXY(177, 25, 16, 14, 0x00); led_mask |= LED_MASK_RIGHT; } // Light only the available choices for (j = i; j < 4; j++) { led_mask |= (1 << j); } // Display picture oledDisplayOtherBuffer(); // Get touched quarter j = getTouchedPositionAnswer(led_mask); // Check its validity, knowing that by default we will return NODE_ADDR_NULL if (j == -1) { action_chosen = TRUE; // Time out } else if (j < i) { // Valid choice, load parent node as it will be used later readParentNode(p, parentAddresses[offset+j]); picked_child = childAddresses[offset+j]; action_chosen = TRUE; } else if (j == TOUCHPOS_LEFT) { if (offset > 0) { offset -= 4; } else { // User wants to go back action_chosen = TRUE; } } else if ((j == TOUCHPOS_RIGHT) && (i == 4) && ((offset+i) != nbFavorites)) { // If there are more nodes to display offset += 4; } } // Return selected child return picked_child; }
// Visits all PtNodes in PtNode array level pre-order depth first manner, which is the same order // that PtNodes are written in the dictionary buffer. // For example, visits a -> b -> x -> c -> y for the following dictionary: // a _ b _ c // \ x _ y bool DynamicPatriciaTrieReadingHelper::traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner( TraversingEventListener *const listener) { bool alreadyVisitedAllPtNodesInArray = false; bool alreadyVisitedChildren = false; // Descend from the root to the root PtNode array. if (!listener->onDescend(getPosOfLastPtNodeArrayHead())) { return false; } if (isEnd()) { // Empty dictionary. Needs to notify the listener of the tail of empty PtNode array. if (!listener->onReadingPtNodeArrayTail()) { return false; } } pushReadingStateToStack(); while (!isEnd()) { if (alreadyVisitedAllPtNodesInArray) { if (alreadyVisitedChildren) { // Move to next sibling PtNode's children. readNextSiblingNode(); if (isEnd()) { // Return to the parent PTNode. if (!listener->onAscend()) { return false; } if (mReadingStateStack.size() <= 0) { break; } popReadingStateFromStack(); alreadyVisitedChildren = true; alreadyVisitedAllPtNodesInArray = true; } else { alreadyVisitedChildren = false; } } else { if (mNodeReader.hasChildren()) { // Move to the first child. if (!listener->onDescend(mNodeReader.getChildrenPos())) { return false; } pushReadingStateToStack(); readChildNode(); // Push state to return the head of PtNode array. pushReadingStateToStack(); alreadyVisitedAllPtNodesInArray = false; alreadyVisitedChildren = false; } else { alreadyVisitedChildren = true; } } } else { if (!listener->onVisitingPtNode(&mNodeReader, mMergedNodeCodePoints)) { return false; } readNextSiblingNode(); if (isEnd()) { if (!listener->onReadingPtNodeArrayTail()) { return false; } // Return to the head of current PtNode array. popReadingStateFromStack(); alreadyVisitedAllPtNodesInArray = true; } } } popReadingStateFromStack(); // Ascend from the root PtNode array to the root. if (!listener->onAscend()) { return false; } return !isError(); }