using Mindmagma.Curses; namespace SCI.CursesWrapper.UiElements; public class InputBox { public delegate void InputCompleted (string input); public void RequestInput (nint screen, InputHandler inputHandler, InputCompleted callback, string question) { const int boxPaddingTop = 1; const int boxPaddingSides = 2; const int boxPaddingBottom = 2; const int boxMarginTopBottom = 1; const int boxMarginSides = 2; NCurses.GetMaxYX (screen, out int height, out int width); // Contents inside the question box may not be larger than these int maxInnerWidth = width - (boxPaddingSides * 2) - (boxMarginSides * 2); int maxInnerHeight = height - boxPaddingTop - boxPaddingBottom - boxMarginTopBottom; using var strReader = new StringReader (question); string? inStr; int innerWidth = 1; int innerHeight = 1; while ((inStr = strReader.ReadLine ()) is not null) { if (inStr.Length > innerWidth) innerWidth = inStr.Length; if (innerWidth > maxInnerWidth) { innerWidth = maxInnerWidth; innerHeight += (int) Math.Ceiling (inStr.Length / (double) maxInnerWidth); } else { innerHeight ++; } } int boxWidth = innerWidth + (boxPaddingSides * 2); int boxHeight = innerHeight + boxPaddingTop + boxPaddingBottom; int boxAnchorX = (width / 2) - (boxWidth / 2); int boxAnchorY = (height / 2) - (boxHeight / 2); var boxWin = NCurses.SubWindow (screen, boxHeight, boxWidth, boxAnchorY, boxAnchorX); NCurses.Box (boxWin, (char) 0, (char) 0); NCurses.Refresh (); NCurses.WindowRefresh (boxWin); int questionTextWinAnchorX = boxAnchorX + boxPaddingSides; int questionTextWinAnchorY = boxAnchorY + boxPaddingTop; var questionTextWin = NCurses.SubWindow (boxWin, innerHeight, innerWidth, questionTextWinAnchorY, questionTextWinAnchorX); NCurses.WindowAddString (questionTextWin, question.Trim ()); NCurses.WindowRefresh (questionTextWin); int inputFieldWinX = questionTextWinAnchorX; int inputFieldWinY = boxAnchorY + boxHeight - boxMarginTopBottom - 1; var inputFieldWin = NCurses.SubWindow (boxWin, 1, innerWidth, inputFieldWinY, inputFieldWinX); NCurses.WindowBackground (inputFieldWin, ColorSchemes.TextInputField ()); NCurses.WindowAttributeSet (inputFieldWin, ColorSchemes.TextInputField ()); NCurses.WindowRefresh (inputFieldWin); NCurses.MoveWindow (inputFieldWin, inputFieldWinY, inputFieldWinX); NCurses.SetCursor (1); NCurses.Echo (); var userInput = ""; InputHandler.KeypressEventHandler handlerFunction = (object sender, NCursesKeyPressEventArgs e) => { if (e.KeyCode == '\n' || e.KeyCode == CursesKey.ENTER) { callback (userInput); } if (e.KeyCode == '\n' || e.KeyCode == CursesKey.ENTER || e.KeyCode == CursesKey.ESC) { NCurses.SetCursor (0); NCurses.NoEcho (); //inputHandler.DisableRawEventHandler (screen); NCurses.MoveWindow (screen, 0, 0); NCurses.DeleteWindow (inputFieldWin); NCurses.DeleteWindow (questionTextWin); NCurses.DeleteWindow (boxWin); NCurses.Refresh (); } else if (e.KeyCode == CursesKey.BACKSPACE) { userInput = userInput.Substring (0, userInput.Length - 2); } else if (char.IsAscii ((char) e.KeyCode)) { userInput += (char) e.KeyCode; } NCurses.MoveWindow (inputFieldWin, inputFieldWinY, inputFieldWinX); }; //inputHandler.EnableRawEventHandler (handlerFunction, inputFieldWin); } }