summaryrefslogtreecommitdiff
path: root/src/conout.cpp
diff options
context:
space:
mode:
authornavewindre <nw@moneybot.cc>2024-07-12 00:55:39 +0200
committernavewindre <nw@moneybot.cc>2024-07-12 00:55:39 +0200
commit2ebf959ec02048c15323e1bbfc63faedcf5067b6 (patch)
tree18862ba5d3b4be44294c0a81317d31eace7ee150 /src/conout.cpp
parentecca2728f1a583ea484f8bdcda390a30e4906f1d (diff)
ha haaa
Diffstat (limited to 'src/conout.cpp')
-rw-r--r--src/conout.cpp333
1 files changed, 333 insertions, 0 deletions
diff --git a/src/conout.cpp b/src/conout.cpp
new file mode 100644
index 0000000..7fb461b
--- /dev/null
+++ b/src/conout.cpp
@@ -0,0 +1,333 @@
+//|_ _ _. _ ._ |_ _. _ |
+//| | (/_ (_| \/ (/_ | | | | (_| (_ |<
+
+#include <windows.h>
+#include <stdio.h>
+#include <malloc.h>
+
+#include "mathutil.h"
+#include "util.h"
+#include "conout.h"
+
+
+CRITICAL_SECTION con_mutex;
+CON_LINE* con_lines = (CON_LINE*)malloc( sizeof( CON_LINE ) * ( CON_MAX_HEIGHT + 1 ) );
+U8 con_selected_line = 0;
+bool con_assert = false;
+
+void con_init() {
+ AllocConsole();
+ freopen( "CONOUT$","w",stdout );
+
+ if( !con_mutex.SpinCount ) {
+ InitializeCriticalSectionAndSpinCount( &con_mutex, 0x100 );
+ }
+
+ HWND con_handle = GetConsoleWindow();
+ SetConsoleMode(
+ con_handle,
+ DISABLE_NEWLINE_AUTO_RETURN|ENABLE_WINDOW_INPUT|ENABLE_VIRTUAL_TERMINAL_INPUT
+ );
+
+ SetConsoleTitleA( "heaven's gate" );
+
+ for( U8 i = 0; i < CON_MAX_HEIGHT; ++i ) {
+ con_lines[i].line_num = -1;
+ }
+
+ con_setpos( 0, 0 );
+ con_resize( CON_WIDTH, CON_HEIGHT );
+ con_print_title();
+
+ HANDLE stdo = GetStdHandle( STD_OUTPUT_HANDLE );
+
+ CONSOLE_CURSOR_INFO info;
+ GetConsoleCursorInfo( stdo, &info );
+ info.bVisible = false;
+ SetConsoleCursorInfo( stdo, &info );
+}
+
+void setc( U8 c ) {
+ SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), c );
+}
+
+void con_resize( U8 w, U8 h ) {
+ SMALL_RECT console_wnd{};
+ console_wnd.Right = w;
+ console_wnd.Bottom = h;
+
+ HANDLE std_handle = GetStdHandle( STD_OUTPUT_HANDLE );
+ SetConsoleWindowInfo( std_handle, true, &console_wnd );
+ SetConsoleScreenBufferSize( std_handle, COORD( w + 1, h + 1 ) );
+ SetConsoleWindowInfo( std_handle,true,&console_wnd );
+
+ HWND con_handle = GetConsoleWindow();
+ HMENU sys_menu = GetSystemMenu( con_handle, false );
+
+ if( sys_menu ) {
+ DeleteMenu( sys_menu, SC_MAXIMIZE, MF_BYCOMMAND );
+ DeleteMenu( sys_menu, SC_SIZE, MF_BYCOMMAND );
+ }
+}
+
+void con_print_internal( U8 color, const char* text, ... ) {
+ SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), color );
+ va_list args;
+ va_start( args, text );
+ vprintf_s( text, args );
+ va_end( args );
+}
+
+void con_print( U8 color, const char* text, ... ) {
+ if( !con_mutex.SpinCount ) {
+ InitializeCriticalSectionAndSpinCount( &con_mutex, 0x100 );
+ }
+
+ EnterCriticalSection( &con_mutex );
+
+ SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), color );
+ va_list args;
+ va_start( args, text );
+ vprintf_s( text, args );
+ va_end( args );
+
+ LeaveCriticalSection( &con_mutex );
+}
+
+void con_print_title() {
+ con_print_internal( 133, " =============== [ heaven's gate ] =============== " );
+ con_print_internal( 15, " [%s]\n", __DATE__ );
+ con_print_internal( 15, "\n" );
+}
+
+void con_setpos( U8 x, U8 y ) {
+ HANDLE std_handle = GetStdHandle( STD_OUTPUT_HANDLE );
+ SetConsoleCursorPosition( std_handle, COORD( x, y ) );
+}
+
+void con_print_line( U8 line ) {
+ EnterCriticalSection( &con_mutex );
+
+ CON_LINE* l = &con_lines[line];
+ l->line_num = line;
+
+ con_setpos( 0, CON_TITLE_HEIGHT + line + 1 );
+
+ U8 border_col = ( !l->active? CONFG_DARKGRAY : CONFG_WHITE );
+
+ con_print_internal( border_col, "\r = " );
+ con_print_internal( l->text_col, l->text );
+
+ U8 spacing = CON_MAX_WIDTH - (U8)( strlen( l->text ) + strlen( l->subtext ) );
+ char* spacer = (char*)_alloca( spacing + 1 );
+ memset( spacer, ' ', spacing );
+ spacer[spacing] = 0;
+
+ con_print_internal( 0, spacer );
+ if( l->subtext_col > 15 || !l->active )
+ con_print_internal( l->subtext_col, l->subtext );
+ else
+ con_print_internal( l->subtext_col + CONBG_DARKGRAY, l->subtext );
+
+ con_print_internal( border_col, " =" );
+ LeaveCriticalSection( &con_mutex );
+}
+
+void con_set_line( U8 line, const char* text, const char* subtext, bool selected, U8 fg, U8 bg ) {
+ if( line > CON_MAX_HEIGHT )
+ return;
+
+ CON_LINE* l = &con_lines[line];
+ strcpy( l->text, text );
+ l->text_col = fg + bg;
+ strcpy( l->subtext, subtext );
+ l->subtext_col = fg + bg;
+ l->active = selected;
+
+ con_print_line( line );
+}
+
+void con_set_line_text( U8 line, const char* text, bool selected, U8 fg, U8 bg ) {
+ if( line > CON_MAX_HEIGHT )
+ return;
+
+ CON_LINE* l = &con_lines[line];
+ strcpy( l->text, text );
+ l->text_col = fg + bg;
+ l->active = selected;
+
+ con_print_line( line );
+}
+
+void con_set_line_subtext( U8 line, const char* text, bool selected, U8 fg, U8 bg ) {
+ if( line > CON_MAX_HEIGHT )
+ return;
+
+ CON_LINE* l = &con_lines[line];
+ strcpy( l->subtext, text );
+ l->subtext_col = fg + bg;
+ l->active = selected;
+
+ con_print_line( line );
+}
+
+void con_set_line_callback( U8 line, LINE_CALLBACK cb ) {
+ if( line > CON_MAX_HEIGHT )
+ return;
+
+ con_lines[line].callback = cb;
+}
+
+void con_clear_line( U8 line ) {
+ EnterCriticalSection( &con_mutex );
+
+ CON_LINE* l = &con_lines[line];
+
+ l->line_num = -1;
+ l->active = false;
+ l->callback = nullptr;
+ l->subtext[0] = 0;
+ l->text[0] = 0;
+
+ con_setpos( 0, CON_TITLE_HEIGHT + line + 1 );
+
+ char* spacer = (char*)_alloca( CON_WIDTH + 1 );
+ memset( spacer, ' ', CON_WIDTH );
+ spacer[CON_WIDTH] = 0;
+
+ con_print_internal( 0, spacer );
+
+ LeaveCriticalSection( &con_mutex );
+}
+
+void con_clear() {
+ for( U8 i = 0; i < CON_MAX_HEIGHT; ++i )
+ con_clear_line( i );
+}
+
+void con_set_bottomline_text( U8 color, const char* text, ... ) {
+ EnterCriticalSection( &con_mutex );
+ if( con_assert )
+ return;
+
+ con_setpos( 0, CON_HEIGHT );
+ setc( color );
+
+ char str_buffer[256]{};
+ va_list args;
+ va_start( args, text );
+ vsprintf_s( str_buffer, 256, text, args );
+ va_end( args );
+
+ strcpy( con_lines[CON_MAX_HEIGHT].text, str_buffer );
+ con_lines[CON_MAX_HEIGHT].text_col = color;
+
+ U8 length = (U8)strlen( str_buffer );
+ U8 spacing = CON_WIDTH - length + 1;
+
+ memset( str_buffer + length, ' ', spacing );
+ str_buffer[CON_WIDTH] = '\0';
+ WriteConsoleA( GetStdHandle( STD_OUTPUT_HANDLE ), str_buffer, CON_WIDTH, 0, 0 );
+
+ LeaveCriticalSection( &con_mutex );
+}
+
+void con_set_bottomline_text( const char* text, ... ) {
+ if( con_assert )
+ return;
+
+ char str_buffer[256]{};
+ va_list args;
+ va_start( args, text );
+ vsprintf_s( str_buffer, 256, text, args );
+ va_end( args );
+
+ con_set_bottomline_text( CONFG_BLACK + CONBG_LIGHTGRAY, str_buffer );
+}
+
+void con_set_assert( const char* text, ... ) {
+ char str_buffer[256]{};
+ va_list args;
+ va_start( args, text );
+ vsprintf_s( str_buffer, 256, text, args );
+ va_end( args );
+
+ con_set_bottomline_text( CONFG_RED + CONBG_LIGHTGRAY, str_buffer );
+ EnterCriticalSection( &con_mutex );
+ con_assert = true;
+ LeaveCriticalSection( &con_mutex );
+}
+
+
+void con_clear_bottomline_text() {
+ EnterCriticalSection( &con_mutex );
+
+ con_setpos( 0, CON_HEIGHT - 1 );
+
+ char* spacer = (char*)_alloca( CON_WIDTH + 1 );
+ memset( spacer, ' ', CON_WIDTH );
+ spacer[CON_WIDTH] = 0;
+
+ con_print_internal( 0, spacer );
+
+ LeaveCriticalSection( &con_mutex );
+}
+
+void con_refresh() {
+ con_print_internal( 0, "\r" );
+ system( "cls" );
+ con_setpos( 0, 0 );
+ con_print_title();
+ for( U8 i = 0; i < CON_MAX_HEIGHT; ++i ) {
+ CON_LINE* line = &con_lines[i];
+
+ if( line->line_num != -1 || !!strlen( line->text ) )
+ con_print_line( i );
+ }
+
+ CON_LINE* bottom_line = &con_lines[CON_MAX_HEIGHT];
+ con_set_bottomline_text( bottom_line->text_col, bottom_line->text );
+}
+
+
+STR<64> con_progressbar( F32 progress, U8 width ) {
+ static U64 last_call = u_tick();
+ static U8 cur_spinner = 0;
+ static char spinner_anim[] = {
+ '-',
+ '\\',
+ '|',
+ '/',
+ '-',
+ '\\',
+ '|',
+ '/'
+ };
+
+ if( width <= 3 )
+ return "";
+
+ STR<64> ret;
+ memset( ret.data, ' ', width );
+ ret[width] = 0;
+
+ ret[0] = '[';
+ ret[width - 1] = ']';
+
+ progress = u_clamp( progress, 0.f, 1.f );
+ U8 total = (U8)( ( width - 1 ) * progress );
+ for( U8 i = 1; i < total; ++i ) {
+ ret[i] = '=';
+ }
+
+ if( progress < 1.0f ) {
+ if( u_tick() - last_call > 200 ) {
+ ++cur_spinner;
+ last_call = u_tick();
+ }
+
+ ret[total + 1] = spinner_anim[cur_spinner % sizeof(spinner_anim)];
+ }
+
+ return ret;
+} \ No newline at end of file