From 53aa80e1b50ba640ae91b0bdd44afa8c06969a8b Mon Sep 17 00:00:00 2001 From: Gwenhael Le Moine Date: Wed, 18 Oct 2023 16:35:07 +0200 Subject: [PATCH] add --small TUI drawing 4 pixels per character --- dist/config.lua | 1 + dist/x48ng.man.1 | 2 + src/runtime_options.c | 18 ++++++- src/runtime_options.h | 8 ++- src/ui_text.c | 117 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 131 insertions(+), 15 deletions(-) diff --git a/dist/config.lua b/dist/config.lua index 1b4770d..51135af 100644 --- a/dist/config.lua +++ b/dist/config.lua @@ -27,6 +27,7 @@ hide_chrome = false fullscreen = false mono = false gray = false +small = false x11_visual = "default" netbook = false diff --git a/dist/x48ng.man.1 b/dist/x48ng.man.1 index 6ea2161..dc138f4 100644 --- a/dist/x48ng.man.1 +++ b/dist/x48ng.man.1 @@ -110,6 +110,8 @@ where options include (depending on compiled front-ends): \-\-mono make the UI monochrome (default: false) .br \-\-gray make the UI grayscale (default: false) +.br + \-\-small make the text UI small (2×2 pixels per character) (default: false) .SH DESCRIPTION .I x48ng diff --git a/src/runtime_options.c b/src/runtime_options.c index 742ec0d..1d213b0 100644 --- a/src/runtime_options.c +++ b/src/runtime_options.c @@ -37,6 +37,12 @@ char* port2FileName = NULL; int frontend_type = FRONTEND_TEXT; +bool mono = false; +bool gray = false; + +/* tui */ +bool small = false; + /* sdl */ bool hide_chrome = false; bool show_ui_fullscreen = false; @@ -49,8 +55,6 @@ char* x11_visual = NULL; /* default | staticgray | staticcolor | truecolor | grayscale | * pseudocolor | directcolor | 0xnn | nn */ -bool mono = false; -bool gray = false; bool monoIcon = false; bool iconic = false; bool xrm = true; @@ -233,6 +237,7 @@ int parse_args( int argc, char* argv[] ) int clopt_netbook = -1; int clopt_mono = -1; int clopt_gray = -1; + int clopt_small = -1; char* optstring = "c:hvVtsirT"; struct option long_options[] = { @@ -275,6 +280,7 @@ int parse_args( int argc, char* argv[] ) { "mono", no_argument, &clopt_mono, true }, { "gray", no_argument, &clopt_gray, true }, + { "small", no_argument, &clopt_small, true }, { 0, 0, 0, 0 } }; @@ -331,6 +337,8 @@ int parse_args( int argc, char* argv[] ) " --mono make the UI monochrome (default: " "false)\n" " --gray make the UI grayscale (default: " + "false)\n" + " --small make the text UI small (2×2 pixels per character) (default: " "false)\n"; while ( c != EOF ) { c = getopt_long( argc, argv, optstring, long_options, &option_index ); @@ -494,6 +502,9 @@ int parse_args( int argc, char* argv[] ) lua_getglobal( config_lua_values, "gray" ); gray = lua_toboolean( config_lua_values, -1 ); + lua_getglobal( config_lua_values, "small" ); + small = lua_toboolean( config_lua_values, -1 ); + lua_getglobal( config_lua_values, "x11_visual" ); x11_visual = ( char* )luaL_optstring( config_lua_values, -1, "default" ); @@ -559,6 +570,8 @@ int parse_args( int argc, char* argv[] ) mono = clopt_mono; if ( clopt_gray != -1 ) gray = clopt_gray; + if ( clopt_small != -1 ) + small = clopt_small; /* After getting configs and params */ /* normalize config_dir again in case it's been modified */ @@ -608,6 +621,7 @@ int parse_args( int argc, char* argv[] ) fprintf( stdout, "fullscreen = %s\n", show_ui_fullscreen ? "true" : "false" ); fprintf( stdout, "mono = %s\n", mono ? "true" : "false" ); fprintf( stdout, "gray = %s\n", gray ? "true" : "false" ); + fprintf( stdout, "small = %s\n", small ? "true" : "false" ); fprintf( stdout, "\n" ); fprintf( stdout, "x11_visual = \"%s\"\n", x11_visual ); fprintf( stdout, "netbook = %s\n", netbook ? "true" : "false" ); diff --git a/src/runtime_options.h b/src/runtime_options.h index 0be559a..8023c87 100644 --- a/src/runtime_options.h +++ b/src/runtime_options.h @@ -19,6 +19,12 @@ extern int frontend_type; extern char* serialLine; +extern bool mono; +extern bool gray; + +/* tui */ +extern bool small; + /* sdl */ extern bool hide_chrome; extern bool show_ui_fullscreen; @@ -28,8 +34,6 @@ extern bool netbook; extern char* name; extern char* title; extern char* x11_visual; -extern bool mono; -extern bool gray; extern bool monoIcon; extern bool iconic; extern bool xrm; diff --git a/src/ui_text.c b/src/ui_text.c index 9089add..e3b80b4 100644 --- a/src/ui_text.c +++ b/src/ui_text.c @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -22,14 +23,15 @@ #define LCD_HEIGHT 64 #define LCD_OFFSET_X 1 #define LCD_OFFSET_Y 2 -#define LCD_BOTTOM LCD_HEIGHT + LCD_OFFSET_Y -#define LCD_RIGHT LCD_WIDTH + LCD_OFFSET_X +#define LCD_BOTTOM LCD_OFFSET_Y + ( small ? ( LCD_HEIGHT / 2 ) + 1 : LCD_HEIGHT ) +#define LCD_RIGHT LCD_OFFSET_X + ( small ? ( LCD_WIDTH / 2 ) + 1 : LCD_WIDTH ) #define LCD_COLOR_BG 48 #define LCD_COLOR_FG 49 #define LCD_PIXEL_ON 1 #define LCD_PIXEL_OFF 2 +#define LCD_COLORS_PAIR 3 /************************/ /* functions prototypes */ @@ -54,15 +56,103 @@ static inline void ncurses_draw_annunciators( void ) mvaddwstr( 0, 4 + ( i * 4 ), ( ( annunciators_bits[ i ] & val ) == annunciators_bits[ i ] ) ? annunciators_icons[ i ] : L" " ); } +static inline wchar_t bitsquare_to_small_char( bool top_left, bool top_right, bool bottom_left, bool bottom_right ) +{ + if ( top_left ) { + if ( top_right && bottom_left && bottom_right ) + return L'█'; + if ( top_right && bottom_left && !bottom_right ) + return L'▛'; + if ( top_right && !bottom_left && bottom_right ) + return L'▜'; + if ( top_right && !bottom_left && !bottom_right ) + return L'▀'; + + if ( !top_right && bottom_left && bottom_right ) + return L'▙'; + if ( !top_right && bottom_left && !bottom_right ) + return L'▌'; + if ( !top_right && !bottom_left && bottom_right ) + return L'▚'; + if ( !top_right && !bottom_left && !bottom_right ) + return L'▘'; + } else { + if ( top_right && bottom_left && bottom_right ) + return L'▟'; + if ( top_right && bottom_left && !bottom_right ) + return L'▞'; + if ( top_right && !bottom_left && bottom_right ) + return L'▐'; + if ( top_right && !bottom_left && !bottom_right ) + return L'▝'; + + if ( !top_right && bottom_left && bottom_right ) + return L'▄'; + if ( !top_right && bottom_left && !bottom_right ) + return L'▖'; + if ( !top_right && !bottom_left && bottom_right ) + return L'▗'; + if ( !top_right && !bottom_left && !bottom_right ) + return L' '; + } +} + +static inline void ncurses_draw_lcd_small( void ) +{ + bool top_left, top_right, bottom_left, bottom_right; + int nibble_top, nibble_bottom; + int step_x = 2; + int step_y = 2; + + wchar_t line[ 66 ]; /* ( LCD_WIDTH / step_x ) + 1 */ + + if ( !mono && has_colors() ) + attron( COLOR_PAIR( LCD_COLORS_PAIR ) ); + + for ( int y = 0; y < LCD_HEIGHT; y += step_y ) { + wcscpy( line, L"" ); + + for ( int nibble_x = 0; nibble_x < NIBBLES_PER_ROW - 1; ++nibble_x ) { + nibble_top = lcd_nibbles_buffer[ y ][ nibble_x ]; + nibble_top &= 0x0f; + nibble_bottom = lcd_nibbles_buffer[ y + 1 ][ nibble_x ]; + nibble_bottom &= 0x0f; + + for ( int bit_x = 0; bit_x < NIBBLES_NB_BITS; bit_x += step_x ) { + top_left = 0 != ( nibble_top & ( 1 << ( bit_x & 3 ) ) ); + top_right = 0 != ( nibble_top & ( 1 << ( ( bit_x + 1 ) & 3 ) ) ); + + bottom_left = 0 != ( nibble_bottom & ( 1 << ( bit_x & 3 ) ) ); + bottom_right = 0 != ( nibble_bottom & ( 1 << ( ( bit_x + 1 ) & 3 ) ) ); + + wchar_t pixels = bitsquare_to_small_char( top_left, top_right, bottom_left, bottom_right ); + wcsncat( line, &pixels, 1 ); + } + } + mvaddwstr( LCD_OFFSET_Y + ( y / step_y ), LCD_OFFSET_X, line ); + } + + if ( !mono && has_colors() ) + attroff( COLOR_PAIR( LCD_COLORS_PAIR ) ); + + wrefresh( stdscr ); +} + static inline void ncurses_draw_lcd( void ) { - chtype pixel; - short bit; + bool bit; int nibble; int bit_stop; int init_x; + wchar_t line[ LCD_WIDTH ]; + + if ( !mono && has_colors() ) + attron( COLOR_PAIR( LCD_COLORS_PAIR ) ); + for ( int y = 0; y < LCD_HEIGHT; ++y ) { + wcscpy( line, L"" ); + for ( int nibble_x = 0; nibble_x < NIBBLES_PER_ROW; ++nibble_x ) { nibble = lcd_nibbles_buffer[ y ][ nibble_x ]; nibble &= 0x0f; @@ -71,17 +161,18 @@ static inline void ncurses_draw_lcd( void ) bit_stop = ( ( init_x + NIBBLES_NB_BITS >= LCD_WIDTH ) ? LCD_WIDTH - init_x : 4 ); for ( int bit_x = 0; bit_x < bit_stop; bit_x++ ) { - bit = nibble & ( 1 << ( bit_x & 3 ) ); + bit = 0 != ( nibble & ( 1 << ( bit_x & 3 ) ) ); - pixel = bit ? ACS_BLOCK : ' '; - if ( !mono && has_colors() ) - pixel |= COLOR_PAIR( bit ? LCD_PIXEL_ON : LCD_PIXEL_OFF ); - - mvaddch( y + LCD_OFFSET_Y, ( nibble_x * NIBBLES_NB_BITS ) + bit_x + LCD_OFFSET_X, pixel ); + wchar_t pixel = bit ? L'█' : L' '; + wcsncat( line, &pixel, 1 ); } } + mvaddwstr( LCD_OFFSET_Y + y, LCD_OFFSET_X, line ); } + if ( !mono && has_colors() ) + attroff( COLOR_PAIR( LCD_COLORS_PAIR ) ); + wrefresh( stdscr ); } @@ -321,6 +412,7 @@ static inline void ncurses_init_ui( void ) init_pair( LCD_PIXEL_OFF, LCD_COLOR_BG, LCD_COLOR_BG ); init_pair( LCD_PIXEL_ON, LCD_COLOR_FG, LCD_COLOR_FG ); + init_pair( LCD_COLORS_PAIR, LCD_COLOR_FG, LCD_COLOR_BG ); } mvaddch( 0, 0, ACS_ULCORNER ); @@ -404,7 +496,10 @@ void text_update_LCD( void ) } else memset( lcd_nibbles_buffer, 0xf0, sizeof( lcd_nibbles_buffer ) ); - ncurses_draw_lcd(); + if ( small ) + ncurses_draw_lcd_small(); + else + ncurses_draw_lcd(); } void text_refresh_LCD( void ) {}