commit e6778c95c2a44a183acacb4df20c9db5706352be
parent 02d2827aa257ae919123ef1d046732b388eaa2d2
Author: Morel Bérenger <berengermorel76@gmail.com>
Date:   Mon, 11 Jan 2021 04:18:43 +0100
btl: new functions: term_ch_size and indent_txt
Diffstat:
2 files changed, 82 insertions(+), 0 deletions(-)
diff --git a/btl/src/utils.cpp b/btl/src/utils.cpp
@@ -24,8 +24,12 @@
 
 #include <iterator>
 #include <algorithm>
+
 #include "utils.hpp"
 
+#include <sys/ioctl.h>
+#include <termios.h>
+
 //would probably be better without that many ifs
 int esc_fputs( const char *s, FILE *stream )
 {
@@ -91,3 +95,71 @@ size_t ungets( char const* const str, size_t str_sz )
 	}
 	return 0;
 }
+
+bool term_ch_size( uint16_t *w, uint16_t *h, int fd )
+{
+	struct winsize wsz;
+	if( -1 == ioctl( fd, TIOCGWINSZ, &wsz ) )
+	{
+		return true;
+	}
+	*w = wsz.ws_col;
+	*h = wsz.ws_row;
+	return false;
+}
+
+bool indent_txt( char const* txt, char const* end, uint8_t level, uint16_t max_width, uint8_t tab_width, FILE* target )
+{
+	uint16_t indent_size = tab_width * level;
+	//bad args
+	if( !txt || !target )
+	{
+		return true;
+	}
+	//overflow
+	if( indent_size < tab_width || indent_size < level )
+	{
+		return true;
+	}
+	//indent wider than screen
+	if( indent_size > max_width )
+	{
+		return true;
+	}
+	max_width -= indent_size;
+	assert( max_width > 0 );
+
+	uint16_t pos        = 0;
+	uint16_t last_blank = 0;
+	char const* ptr = txt;
+	for( ; ptr != end; ++ptr, ++pos )
+	{
+		if( isblank( *ptr ) )
+		{
+			last_blank = pos;
+		}
+
+		if( *ptr == '\n' || pos == max_width )
+		{
+			if( *ptr != '\n' && last_blank != 0 )
+			{
+				assert( pos >= last_blank );
+				ptr -= pos - last_blank;
+				pos = last_blank;
+			}
+			for( uint8_t l = 0; l < level; ++l )
+			{
+				fputc( '\t', target );
+			}
+			fprintf( target, "%.*s", pos, txt );
+			last_blank = 0;
+			pos = 0;
+			txt = ptr + 1;
+			if( *ptr != '\n' )
+			{
+				fputc( '\n', target );
+			}
+		}
+	}
+	return false;
+}
diff --git a/btl/src/utils.hpp b/btl/src/utils.hpp
@@ -98,4 +98,14 @@ inline uint16_t find_unescaped( int end, int esc, char ** str )
 	return find_unescaped( end, esc, str, strlen( *str ) );
 }
 
+// returns the size in characters of terminal fd in w and h.
+// returns true on error.
+bool term_ch_size( uint16_t *w, uint16_t *h, int fd );
+
+// print [txt,end) on target, indenting it level times.
+// When a line is wider than max_width, try to break at last isblank(3).
+// returns true on error.
+// note:
+bool indent_txt( char const* txt, char const* end, uint8_t level, uint16_t max_width, uint8_t tab_width, FILE* target );
+
 #endif