public void ProcessFunctionKey(FunctionKeys functionKey) { Log.DebugFormat("Processing captured function key '{0}'", functionKey); lastTextChangeWasSuggestion = false; switch (functionKey) { case FunctionKeys.BackMany: if (!string.IsNullOrEmpty(Text)) { var backManyCount = Text.CountBackToLastCharCategoryBoundary(); dictionaryService.DecrementEntryUsageCount(Text.Substring(Text.Length - backManyCount, backManyCount).Trim()); var textAfterBackMany = Text.Substring(0, Text.Length - backManyCount); var textChangedByBackMany = Text != textAfterBackMany; Text = textAfterBackMany; if (backManyCount == 0) { backManyCount = 1; //Always publish at least one backspace } for (int i = 0; i < backManyCount; i++) { PublishKeyPress(FunctionKeys.BackOne); ReleaseUnlockedKeys(); } if (textChangedByBackMany || string.IsNullOrEmpty(Text)) { AutoPressShiftIfAppropriate(); } StoreLastTextChange(null); GenerateAutoCompleteSuggestions(); Log.Debug("Suppressing next auto space."); suppressNextAutoSpace = true; } else { //Scratchpad is empty, but publish 1 backspace anyway, as per the behaviour for 'BackOne' PublishKeyPress(FunctionKeys.BackOne); } break; case FunctionKeys.BackOne: var backOneCount = string.IsNullOrEmpty(lastTextChange) ? 1 //Default to removing one character if no lastTextChange : lastTextChange.Length; var textChangedByBackOne = false; if (!string.IsNullOrEmpty(Text)) { if (Text.Length < backOneCount) { backOneCount = Text.Length; //Coallesce backCount if somehow the Text length is less } var textAfterBackOne = Text.Substring(0, Text.Length - backOneCount); textChangedByBackOne = Text != textAfterBackOne; if (backOneCount > 1) { //Removing more than one character - only decrement removed string dictionaryService.DecrementEntryUsageCount(Text.Substring(Text.Length - backOneCount, backOneCount).Trim()); } else if (!string.IsNullOrEmpty(lastTextChange) && lastTextChange.Length == 1 && !char.IsWhiteSpace(lastTextChange[0])) { dictionaryService.DecrementEntryUsageCount(Text.InProgressWord(Text.Length)); //We are removing a non-whitespace character - decrement the in progress word dictionaryService.IncrementEntryUsageCount(textAfterBackOne.InProgressWord(Text.Length)); //And increment the in progress word that is left after the removal } Text = textAfterBackOne; } for (int i = 0; i < backOneCount; i++) { PublishKeyPress(FunctionKeys.BackOne); ReleaseUnlockedKeys(); } if (textChangedByBackOne || string.IsNullOrEmpty(Text)) { AutoPressShiftIfAppropriate(); } StoreLastTextChange(null); GenerateAutoCompleteSuggestions(); Log.Debug("Suppressing next auto space."); suppressNextAutoSpace = true; break; case FunctionKeys.ClearScratchpad: Text = null; StoreLastTextChange(null); ClearSuggestions(); AutoPressShiftIfAppropriate(); Log.Debug("Suppressing next auto space."); suppressNextAutoSpace = true; break; case FunctionKeys.Suggestion1: SwapLastTextChangeForSuggestion(0); lastTextChangeWasSuggestion = true; break; case FunctionKeys.Suggestion2: SwapLastTextChangeForSuggestion(1); lastTextChangeWasSuggestion = true; break; case FunctionKeys.Suggestion3: SwapLastTextChangeForSuggestion(2); lastTextChangeWasSuggestion = true; break; case FunctionKeys.Suggestion4: SwapLastTextChangeForSuggestion(3); lastTextChangeWasSuggestion = true; break; case FunctionKeys.Suggestion5: SwapLastTextChangeForSuggestion(4); lastTextChangeWasSuggestion = true; break; case FunctionKeys.Suggestion6: SwapLastTextChangeForSuggestion(5); lastTextChangeWasSuggestion = true; break; default: if (functionKey.ToVirtualKeyCode() != null) { //Key corresponds to physical keyboard key GenerateAutoCompleteSuggestions(); //If the key cannot be pressed or locked down (these are handled in //ReactToPublishableKeyDownStateChanges) then publish it and release unlocked keys var keyValue = new KeyValue(functionKey); if (!KeyValues.KeysWhichCanBePressedOrLockedDown.Contains(keyValue)) { PublishKeyPress(functionKey); ReleaseUnlockedKeys(); } } if (functionKey == FunctionKeys.LeftShift) { shiftStateSetAutomatically = false; } break; } }