# HG changeset patch # User Teemu Piippo # Date 1418448960 -7200 # Node ID 33b8f428bacb95750962624d87fb97975be80735 # Parent 09dcaeaa216baf4e119665486355af865a05d3da - begin work on interface - input line works for the most part :) diff -r 09dcaeaa216b -r 33b8f428bacb CMakeLists.txt --- a/CMakeLists.txt Sat Dec 13 04:50:33 2014 +0200 +++ b/CMakeLists.txt Sat Dec 13 07:36:00 2014 +0200 @@ -4,6 +4,7 @@ set (SOURCE_FILES sources/filesystem.cpp sources/format.cpp + sources/interface.cpp sources/main.cpp sources/md5.cpp sources/mystring.cpp diff -r 09dcaeaa216b -r 33b8f428bacb sources/basics.h --- a/sources/basics.h Sat Dec 13 04:50:33 2014 +0200 +++ b/sources/basics.h Sat Dec 13 07:36:00 2014 +0200 @@ -31,6 +31,7 @@ #pragma once #include #include +#include #define FUNCTION auto #define STATIC @@ -38,10 +39,18 @@ #define MACRO_TO_STRING_2(A) #A #define MACRO_TO_STRING(A) MACRO_TO_STRING_2(A) +class String; + using std::swap; using std::min; using std::max; +template +using SharedPointer = std::shared_ptr; + +template +using WeakPointer = std::weak_ptr; + enum Color { BLACK, @@ -59,3 +68,5 @@ template using Function = std::function; + +FUNCTION print_to_console (const String& a) -> void; diff -r 09dcaeaa216b -r 33b8f428bacb sources/format.h --- a/sources/format.h Sat Dec 13 04:50:33 2014 +0200 +++ b/sources/format.h Sat Dec 13 07:36:00 2014 +0200 @@ -185,7 +185,7 @@ { FILE* handle; - if ((handle = fopen (filename, "w+"))) + if ((handle = fopen (filename, "a"))) { print_to (handle, fmtstr, args...); fclose (handle); @@ -193,10 +193,10 @@ } // ------------------------------------------------------------------------------------------------- -// Prints the formatting result to stdout +// Prints the formatting result to the console // template void print (const String& fmtstr, const argtypes&... args) { - print_to (stdout, fmtstr, args...); + print_to_console (format (fmtstr, args...); } diff -r 09dcaeaa216b -r 33b8f428bacb sources/interface.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/interface.cpp Sat Dec 13 07:36:00 2014 +0200 @@ -0,0 +1,213 @@ +/* + Copyright 2014 Teemu Piippo + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include "interface.h" + +static String g_input; +static int g_cursor = 0; +static int g_pan = 0; +static bool g_needRefresh = false; + +// ------------------------------------------------------------------------------------------------- +// +static FUNCTION +interface_sessions_width() -> int +{ + return COLS / 3; +} + +// ------------------------------------------------------------------------------------------------- +// +static FUNCTION +interface_render_titlebar() -> void +{ + String versionText = format (APPNAME " %1 (%2)", + full_version_string(), changeset_date_string()); + + if (versionText.length() <= COLS) + mvprintw (0, (COLS - versionText.length()) / 2, "%s", versionText.chars()); +} + +// ------------------------------------------------------------------------------------------------- +// +static FUNCTION +interface_render_log_area() -> void +{ + +} + +// ------------------------------------------------------------------------------------------------- +// +static FUNCTION +interface_render_input() -> void +{ + static char prompt[] = "> "; + int displaylength = COLS - strlen (prompt) - 1; + int y = LINES - 2; + + // Ensure that the cursor is always in view, adjust panning if this is not the case + if (g_cursor > g_pan + displaylength) + g_pan = g_cursor - displaylength; // cursor went too far right + else if (g_cursor < g_pan) + g_pan = g_cursor; // cursor went past the pan value to the left + + int start = g_pan; + int end = min (g_input.length(), start + displaylength); + assert (g_cursor >= start and g_cursor <= end); + String displayTextBegin = g_input.mid (start, g_cursor); + String displayTextEnd = g_input.mid (g_cursor, end); + + // Clear, but only as much as is necessary. I want to avoid clearing the entire line to save + // bandwidth over SSH connections. Perhaps needlessly? I'm paranoid. + int renderLength = strlen (prompt) + displayTextBegin.length() + displayTextEnd.length(); + static int lastRenderLength = 0; + + if (lastRenderLength > renderLength) + mvhline (y, renderLength, ' ', lastRenderLength - renderLength); + + lastRenderLength = renderLength; + + // Render the input line, with the part of the input string that's before the cursor written + // AFTER the part that comes afterwards. This is to ensure that the cursor is placed at the + // position where our cursor is. It looks nice like that. :) + mvprintw (y, 0, "%s", prompt); + mvprintw (y, strlen (prompt) + displayTextBegin.length(), "%s", displayTextEnd.chars()); + mvprintw (y, strlen (prompt), "%s", displayTextBegin.chars()); + g_needRefresh = true; +} + +// ------------------------------------------------------------------------------------------------- +// +static FUNCTION +interface_render_statusbar() -> void +{ + +} + +// ------------------------------------------------------------------------------------------------- +// +static FUNCTION +interface_render_full() -> void +{ + interface_render_titlebar(); + interface_render_log_area(); + interface_render_statusbar(); + interface_render_input(); + g_needRefresh = true; +} + +// ------------------------------------------------------------------------------------------------- +// +FUNCTION +Interface::initialize() -> void +{ + ::initscr(); + ::start_color(); + ::raw(); + ::keypad (stdscr, true); + ::noecho(); + ::refresh(); + ::timeout (0); + interface_render_full(); + refresh(); + g_needRefresh = false; +} + +// ------------------------------------------------------------------------------------------------- +// +FUNCTION +Interface::handle_input() -> void +{ + int ch = ::getch(); + + if (ch == KEY_F(1)) + { + endwin(); + exit (EXIT_SUCCESS); + } + else if (ch >= 0x20 and ch <= 0x7E) + { + g_input.insert (g_cursor++, char (ch)); + interface_render_input(); + refresh(); + } + else if (ch == KEY_LEFT) + { + if (g_cursor > 0) + { + g_cursor--; + interface_render_input(); + } + } + else if (ch == KEY_RIGHT) + { + if (g_cursor < g_input.length()) + { + g_cursor++; + interface_render_input(); + } + } + else if (ch == KEY_HOME) + { + if (g_cursor != 0) + { + g_cursor = 0; + interface_render_input(); + } + } + else if (ch == KEY_END) + { + if (g_cursor != g_input.length()) + { + g_cursor = g_input.length(); + interface_render_input(); + } + } + else if (ch == KEY_BACKSPACE) + { + if (not g_input.is_empty() and g_cursor > 0) + { + g_input.remove_at (--g_cursor); + interface_render_input(); + } + } + + if (g_needRefresh) + { + refresh(); + g_needRefresh = false; + } +} + +FUNCTION print_to_console (const String& a) -> void +{ + +} diff -r 09dcaeaa216b -r 33b8f428bacb sources/interface.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/interface.h Sat Dec 13 07:36:00 2014 +0200 @@ -0,0 +1,38 @@ +/* + Copyright 2014 Teemu Piippo + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#pragma once +#include "main.h" + +namespace Interface +{ + void initialize(); + void handle_input(); +}; diff -r 09dcaeaa216b -r 33b8f428bacb sources/main.cpp --- a/sources/main.cpp Sat Dec 13 04:50:33 2014 +0200 +++ b/sources/main.cpp Sat Dec 13 07:36:00 2014 +0200 @@ -33,13 +33,7 @@ #include "main.h" #include "network/rconsession.h" #include "huffman/huffman.h" - -// ------------------------------------------------------------------------------------------------- -// -FUNCTION handle_input() -> void -{ - int ch = getch(); -} +#include "interface.h" // ------------------------------------------------------------------------------------------------- // @@ -47,20 +41,15 @@ main (int argc, char* argv[]) -> int { HUFFMAN_Construct(); + Interface::initialize(); + /* - ::initscr(); - ::start_color(); - ::raw(); - ::keypad (stdscr, true); - ::noecho(); - ::refresh(); - ::timeout (0); - */ Vector rconsessions; RCONSession* sess = new RCONSession; sess->set_password ("testpassword"); sess->connect (IPAddress (localhost, 10666)); rconsessions << sess; + */ for (;;) { @@ -70,29 +59,28 @@ timeout.tv_sec = 0; timeout.tv_usec = 250000; // 0.25 seconds FD_ZERO (&fdset); - //FD_SET (0, &fdset); + FD_SET (0, &fdset); + /* for (RCONSession* session : rconsessions) { int fd = session->socket()->file_descriptor(); highest = max (highest, fd); FD_SET (fd, &fdset); } + */ select (highest + 1, &fdset, nullptr, nullptr, &timeout); - /* if (FD_ISSET (0, &fdset)) - { // stdin is ready, what's incoming? - handle_input(); - } - */ + Interface::handle_input(); + /* for (RCONSession* session : rconsessions) session->tick(); + */ } - endwin(); return EXIT_SUCCESS; } diff -r 09dcaeaa216b -r 33b8f428bacb sources/mystring.cpp --- a/sources/mystring.cpp Sat Dec 13 04:50:33 2014 +0200 +++ b/sources/mystring.cpp Sat Dec 13 07:36:00 2014 +0200 @@ -63,7 +63,7 @@ for (char c : unwanted) { for (int pos = 0; (pos = copy.find (String (c))) != -1;) - copy.remove (pos--); + copy.remove_at (pos--); } return copy; diff -r 09dcaeaa216b -r 33b8f428bacb sources/mystring.h --- a/sources/mystring.h Sat Dec 13 04:50:33 2014 +0200 +++ b/sources/mystring.h Sat Dec 13 07:36:00 2014 +0200 @@ -83,8 +83,8 @@ inline METHOD modify_index (int& a) -> void; METHOD normalize (int (*filter)(int) = &std::isspace) -> void; inline METHOD prepend (String a) -> void; - inline METHOD remove (int pos) -> void; inline METHOD remove (int pos, int len) -> void; + inline METHOD remove_at (int pos) -> void; inline METHOD remove_from_end (int len) -> void; inline METHOD remove_from_start (int len) -> void; METHOD replace (const char* a, const char* b) -> void; @@ -228,7 +228,7 @@ // ------------------------------------------------------------------------------------------------- inline METHOD -String::remove (int pos) -> void +String::remove_at (int pos) -> void { m_string.erase (m_string.begin() + pos); } diff -r 09dcaeaa216b -r 33b8f428bacb sources/network/rconsession.cpp --- a/sources/network/rconsession.cpp Sat Dec 13 04:50:33 2014 +0200 +++ b/sources/network/rconsession.cpp Sat Dec 13 07:36:00 2014 +0200 @@ -1,5 +1,7 @@ #include "rconsession.h" +static Vector g_allSessions; + // ------------------------------------------------------------------------------------------------- // RCONSession::RCONSession() : @@ -236,3 +238,11 @@ time (&now); m_lastPing = now; } + +// ------------------------------------------------------------------------------------------------- +// +STATIC METHOD +RCONSession::all_sessions() -> const Vector& +{ + return g_allSessions; +} diff -r 09dcaeaa216b -r 33b8f428bacb sources/network/rconsession.h --- a/sources/network/rconsession.h Sat Dec 13 04:50:33 2014 +0200 +++ b/sources/network/rconsession.h Sat Dec 13 07:36:00 2014 +0200 @@ -103,6 +103,8 @@ METHOD tick() -> void; METHOD bump_last_ping() -> void; + static METHOD all_sessions() -> const Vector>&; + private: RCONSessionState m_state; IPAddress m_address; @@ -113,3 +115,5 @@ int m_serverProtocol; String m_hostname; }; + +using RCONSessionPointer = SharedPointer;