static void handleCommandCompletion(const char *buf, linenoiseCompletions *lc) { size_t bufLength = strlen(buf); // First let's split up the command into its constituents. char *commandParts[MAX_CMD_PARTS + 1] = { NULL }; // Create a copy of buf, so that strtok_r() can modify it. char bufCopy[bufLength + 1]; strcpy(bufCopy, buf); // Split string into usable parts. size_t idx = 0; char *tokenSavePtr = NULL, *nextCmdPart = NULL, *currCmdPart = bufCopy; while ((nextCmdPart = strtok_r(currCmdPart, " ", &tokenSavePtr)) != NULL) { if (idx < MAX_CMD_PARTS) { commandParts[idx] = nextCmdPart; } else { // Abort, too many parts. return; } idx++; currCmdPart = NULL; } // Also calculate number of commands already present in line (word-depth). // This is actually much more useful to understand where we are and what to do. size_t commandDepth = idx; if (commandDepth > 0 && bufLength > 1 && buf[bufLength - 1] != ' ') { // If commands are present, ensure they have been "confirmed" by at least // one terminating spacing character. Else don't calculate the last command. commandDepth--; } // Check that we got something. if (commandDepth == 0) { // Always start off with a command/action. size_t cmdActionLength = 0; if (commandParts[CMD_PART_ACTION] != NULL) { cmdActionLength = strlen(commandParts[CMD_PART_ACTION]); } actionCompletion(buf, bufLength, lc, commandParts[CMD_PART_ACTION], cmdActionLength); return; } // Let's get the action code first thing. uint8_t actionCode = UINT8_MAX; for (size_t i = 0; i < actionsLength; i++) { if (strcmp(commandParts[CMD_PART_ACTION], actions[i].name) == 0) { actionCode = actions[i].code; } } switch (actionCode) { case NODE_EXISTS: if (commandDepth == 1) { size_t cmdNodeLength = 0; if (commandParts[CMD_PART_NODE] != NULL) { cmdNodeLength = strlen(commandParts[CMD_PART_NODE]); } nodeCompletion(buf, bufLength, lc, actionCode, commandParts[CMD_PART_NODE], cmdNodeLength); } break; case ATTR_EXISTS: case GET: if (commandDepth == 1) { size_t cmdNodeLength = 0; if (commandParts[CMD_PART_NODE] != NULL) { cmdNodeLength = strlen(commandParts[CMD_PART_NODE]); } nodeCompletion(buf, bufLength, lc, actionCode, commandParts[CMD_PART_NODE], cmdNodeLength); } if (commandDepth == 2) { size_t cmdKeyLength = 0; if (commandParts[CMD_PART_KEY] != NULL) { cmdKeyLength = strlen(commandParts[CMD_PART_KEY]); } keyCompletion(buf, bufLength, lc, actionCode, commandParts[CMD_PART_NODE], strlen(commandParts[CMD_PART_NODE]), commandParts[CMD_PART_KEY], cmdKeyLength); } if (commandDepth == 3) { size_t cmdTypeLength = 0; if (commandParts[CMD_PART_TYPE] != NULL) { cmdTypeLength = strlen(commandParts[CMD_PART_TYPE]); } typeCompletion(buf, bufLength, lc, actionCode, commandParts[CMD_PART_NODE], strlen(commandParts[CMD_PART_NODE]), commandParts[CMD_PART_KEY], strlen(commandParts[CMD_PART_KEY]), commandParts[CMD_PART_TYPE], cmdTypeLength); } break; case PUT: if (commandDepth == 1) { size_t cmdNodeLength = 0; if (commandParts[CMD_PART_NODE] != NULL) { cmdNodeLength = strlen(commandParts[CMD_PART_NODE]); } nodeCompletion(buf, bufLength, lc, actionCode, commandParts[CMD_PART_NODE], cmdNodeLength); } if (commandDepth == 2) { size_t cmdKeyLength = 0; if (commandParts[CMD_PART_KEY] != NULL) { cmdKeyLength = strlen(commandParts[CMD_PART_KEY]); } keyCompletion(buf, bufLength, lc, actionCode, commandParts[CMD_PART_NODE], strlen(commandParts[CMD_PART_NODE]), commandParts[CMD_PART_KEY], cmdKeyLength); } if (commandDepth == 3) { size_t cmdTypeLength = 0; if (commandParts[CMD_PART_TYPE] != NULL) { cmdTypeLength = strlen(commandParts[CMD_PART_TYPE]); } typeCompletion(buf, bufLength, lc, actionCode, commandParts[CMD_PART_NODE], strlen(commandParts[CMD_PART_NODE]), commandParts[CMD_PART_KEY], strlen(commandParts[CMD_PART_KEY]), commandParts[CMD_PART_TYPE], cmdTypeLength); } if (commandDepth == 4) { size_t cmdValueLength = 0; if (commandParts[CMD_PART_VALUE] != NULL) { cmdValueLength = strlen(commandParts[CMD_PART_VALUE]); } valueCompletion(buf, bufLength, lc, actionCode, commandParts[CMD_PART_NODE], strlen(commandParts[CMD_PART_NODE]), commandParts[CMD_PART_KEY], strlen(commandParts[CMD_PART_KEY]), commandParts[CMD_PART_TYPE], strlen(commandParts[CMD_PART_TYPE]), commandParts[CMD_PART_VALUE], cmdValueLength); } break; } }
void addKeyboardEvents() { bool resetShift = false; updateTypeEvents(); if (typingTimeout > 0) { typingTimeout--; if (typingTimeout == 0) { drawAutoComplete(); } } if (DS::getPenDown()) { int x = IPC->touchXpx; int y = IPC->touchYpx; int tx = (x >> 3); int ty = (y >> 3); if (ty >= 12) { int current = -1; if (tx < 12) { current = (ty - 12) / 2; } else { current = 6 + (ty - 12) / 2; } if (selectedCompletion == current) { typeCompletion(current); } else { if (current < autoCompleteCount) { selectedCompletion = current; } } drawAutoComplete(); } tx -= keyboardX; ty -= keyboardY; // consolePrintf("x=%d y=%d\n", tx, ty); for (int r = 0; r < DS_NUM_KEYS; r++) { if (( (tx >= keys[r].x) && (tx <= keys[r].x + 1)) && (ty >= keys[r].y) && (ty <= keys[r].y + 1)) { OSystem_DS *system = OSystem_DS::instance(); Common::Event event; // consolePrintf("Key: %d\n", r); if ((keys[r].character == Common::KEYCODE_INVALID)) { // Close button //DS::closed = true; } else { createKeyEvent(r, event); } //event.kbd.keycode = keys[r].character; //event.kbd.ascii = keys[r].character; event.type = Common::EVENT_KEYDOWN; system->addEvent(event); // event.type = Common::EVENT_KEYUP; // system->addEvent(event); switch (keys[r].character) { case DS_SHIFT: { DS::shiftState = !DS::shiftState; DS::setKeyHighlight(r, DS::shiftState); break; } case DS_CAPSLOCK: { DS::capsLockState = !DS::capsLockState; DS::setKeyHighlight(r, DS::capsLockState); break; } default: { DS::setKeyHighlight(r, true); keys[r].pressed = true; break; } } } } } if (DS::getPenReleased()) { for (int r = 0; r < DS_NUM_KEYS; r++) { if (keys[r].pressed) { DS::setKeyHighlight(r, false); OSystem_DS *system = OSystem_DS::instance(); Common::Event event; if ((keys[r].character == Common::KEYCODE_INVALID)) { // Close button DS::closed = true; } else { createKeyEvent(r, event); event.type = Common::EVENT_KEYUP; system->addEvent(event); } keys[r].pressed = false; if (keys[r].character != DS_SHIFT) { resetShift = true; } } } } if ((resetShift) && (DS::shiftState)) { DS::shiftState = false; resetShift = false; for (int t = 0; t < DS_NUM_KEYS; t++) { if (keys[t].character == DS_SHIFT) { DS::setKeyHighlight(t, false); } } } }