public KeyboardInputResult ApplyKeyboardInput(StringBuilder m_SBuilder, UpdateState state, int cursorIndex, int cursorEndIndex, bool allowInput)
{
var PressedKeys = state.KeyboardState.GetPressedKeys();
int charCount = 0;
if (state.FrameTextInput == null) charCount = 0;
else charCount = state.FrameTextInput.Count;
if (PressedKeys.Length + charCount == 0) { return null; }
//bit of a legacy thing going on here
//we support both "pressed keys" and the keyboard event system.
//todo: clean up a bit
var didChange = false;
var result = new KeyboardInputResult();
var m_CurrentKeyState = state.KeyboardState;
var m_OldKeyState = state.PreviousKeyboardState;
result.ShiftDown = PressedKeys.Contains(Keys.LeftShift) || PressedKeys.Contains(Keys.RightShift);
result.CapsDown = state.KeyboardState.CapsLock;
result.NumLockDown = state.KeyboardState.NumLock;
result.CtrlDown = PressedKeys.Contains(Keys.LeftControl) || PressedKeys.Contains(Keys.RightControl);
for (int j = 0; j < state.NewKeys.Count + charCount; j++)
{
var key = (j<state.NewKeys.Count)?state.NewKeys[j]:Keys.None;
bool processChar = true;
if (key != Keys.None)
{
processChar = false;
if (key == Keys.Back || key == Keys.Delete)
{
if (m_SBuilder.Length > 0)
{
/**
* Delete previous character or delete selection
*/
if (cursorEndIndex == -1 && result.CtrlDown)
{
/** Delete up until the previous whitespace char **/
int newEndIndex = cursorIndex;
if (newEndIndex == -1)
{
newEndIndex = m_SBuilder.Length - 1;
}
while (newEndIndex >= 0)
{
if (Char.IsWhiteSpace(m_SBuilder[newEndIndex]))
{
/** Keep the whitespace char **/
newEndIndex++;
break;
}
newEndIndex--;
}
cursorEndIndex = newEndIndex;
}
if (cursorEndIndex == -1)
{
/** Previous character **/
var index = cursorIndex == -1 ? m_SBuilder.Length : cursorIndex;
if ((key == Keys.Back) && (index > 0))
{
var numToDelete = 1;
if (index > 1 && m_SBuilder[index - 1] == '\n' && m_SBuilder[index - 2] == '\r')
{
numToDelete = 2;
}
m_SBuilder.Remove(index - numToDelete, numToDelete);
result.NumDeletes += numToDelete;
if (cursorIndex != -1)
{
cursorIndex -= numToDelete;
}
}
else if ((key == Keys.Delete) && (index < m_SBuilder.Length))
{
/** Guys, delete removes the next character, not the last!! **/
var numToDelete = 1;
if ((index < m_SBuilder.Length - 1) && m_SBuilder[index] == '\r' && m_SBuilder[index + 1] == '\n')
{
numToDelete = 2;
}
m_SBuilder.Remove(index, numToDelete);
result.NumDeletes += numToDelete;
}
}
else
{
DeleteSelectedText(m_SBuilder, ref cursorIndex, ref cursorEndIndex, ref didChange, result);
}
result.SelectionChanged = true;
didChange = true;
}
}
else if (key == Keys.Enter)
{
if (allowInput)
{
/** Line break **/
if (cursorEndIndex != -1)
{
/** Delete selected text **/
DeleteSelectedText(m_SBuilder, ref cursorIndex, ref cursorEndIndex, ref didChange, result);
}
if (cursorIndex == -1)
{
m_SBuilder.Append("\r\n");
}
else
{
m_SBuilder.Insert(cursorIndex, "\r\n");
cursorIndex += 2;
}
result.NumInsertions += 2;
didChange = true;
result.EnterPressed = true;
}
}
else if (key == Keys.Tab)
{
result.TabPressed = true;
}
else if (result.CtrlDown)
{
if (key != Keys.LeftControl) { }
switch (key)
{
case Keys.A:
/** Select all **/
cursorIndex = 0;
cursorEndIndex = m_SBuilder.Length;
result.SelectionChanged = true;
break;
case Keys.C:
case Keys.X:
/** Copy text to clipboard **/
if (cursorEndIndex > 0)
{
var selectionStart = Math.Max(0, cursorIndex);
var selectionEnd = cursorEndIndex;
GetSelectionRange(ref selectionStart, ref selectionEnd);
var str = m_SBuilder.ToString().Substring(selectionStart, selectionEnd - selectionStart);
var copyThread = new Thread(x =>
{
//System.Windows.Forms.Clipboard.SetText((String.IsNullOrEmpty(str)) ? " " : str);
});
copyThread.SetApartmentState(ApartmentState.STA);
copyThread.Start();
if (key == Keys.X)
{
DeleteSelectedText(m_SBuilder, ref cursorIndex, ref cursorEndIndex, ref didChange, result);
}
}
break;
case Keys.V:
/** Paste text in **/
var wait = new AutoResetEvent(false);
string clipboardText = "";
var clipThread = new Thread(x =>
{
//clipboardText = System.Windows.Forms.Clipboard.GetText(System.Windows.Forms.TextDataFormat.Text);
wait.Set();
});
clipThread.SetApartmentState(ApartmentState.STA);
clipThread.Start();
wait.WaitOne();
if (clipboardText != null)
{
/** TODO: Cleanup the clipboard text to make sure its valid **/
/** If i have selection, delete it **/
if (cursorEndIndex != -1)
{
DeleteSelectedText(m_SBuilder, ref cursorIndex, ref cursorEndIndex, ref didChange, result);
}
/** Paste **/
if (cursorIndex == -1)
{
m_SBuilder.Append(clipboardText);
}
else
{
m_SBuilder.Insert(Math.Min(cursorIndex, m_SBuilder.Length), clipboardText);
cursorIndex += clipboardText.Length;
}
result.NumInsertions += clipboardText.Length;
didChange = true;
}
break;
}
} else {
processChar = true;
}
}
if (processChar)
{
char value;
if (j >= state.NewKeys.Count) value = state.FrameTextInput[j - state.NewKeys.Count];
else if (state.FrameTextInput != null) continue;
else value = TranslateChar(key, result.ShiftDown, result.CapsDown, result.NumLockDown);
/** For now we dont support tabs in text **/
if (value != '\0' && value != '\t' && value != '\b' && value != '\r')
{
if (allowInput)
{
if (cursorEndIndex != -1)
{
/** Delete selected text **/
DeleteSelectedText(m_SBuilder, ref cursorIndex, ref cursorEndIndex, ref didChange, result);
}
if (cursorIndex == -1)
{
m_SBuilder.Append(value);
}
else
{
m_SBuilder.Insert(cursorIndex, value);
cursorIndex++;
}
result.NumInsertions++;
didChange = true;
}
}
else
{
result.UnhandledKeys.Add(key);
}
}
}
result.SelectionStart = cursorIndex;
result.SelectionEnd = cursorEndIndex;
result.ContentChanged = didChange;
return result;
}