aboutsummaryrefslogtreecommitdiffhomepage
path: root/output.cpp
diff options
context:
space:
mode:
authorGravatar ridiculousfish <corydoras@ridiculousfish.com>2011-12-26 19:11:54 -0800
committerGravatar ridiculousfish <corydoras@ridiculousfish.com>2011-12-26 19:11:54 -0800
commit3f16ace6784caab54fb054836ee93902e9701913 (patch)
tree6ae6170f86bd45ce7fd0dae4a4242bb8dc67c505 /output.cpp
parent834ea94eb97d37c65fcbf2fcc3b69303f6fb7e24 (diff)
Initial C++ conversion
Diffstat (limited to 'output.cpp')
-rw-r--r--output.cpp600
1 files changed, 600 insertions, 0 deletions
diff --git a/output.cpp b/output.cpp
new file mode 100644
index 00000000..37fc99f0
--- /dev/null
+++ b/output.cpp
@@ -0,0 +1,600 @@
+/** \file output.c
+ Generic output functions
+*/
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <termios.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_SYS_TERMIOS_H
+#include <sys/termios.h>
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#include <sys/time.h>
+#include <unistd.h>
+#include <wctype.h>
+
+#if HAVE_NCURSES_H
+#include <ncurses.h>
+#else
+#include <curses.h>
+#endif
+
+#if HAVE_TERMIO_H
+#include <termio.h>
+#endif
+
+#if HAVE_TERM_H
+#include <term.h>
+#elif HAVE_NCURSES_TERM_H
+#include <ncurses/term.h>
+#endif
+
+#include <signal.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <time.h>
+#include <wchar.h>
+
+
+#include "fallback.h"
+#include "util.h"
+
+#include "wutil.h"
+#include "expand.h"
+#include "common.h"
+#include "output.h"
+#include "halloc_util.h"
+#include "highlight.h"
+
+/**
+ Number of color names in the col array
+*/
+#define COLORS (sizeof(col)/sizeof(wchar_t *))
+
+static int writeb_internal( char c );
+
+/**
+ Names of different colors.
+*/
+static wchar_t *col[]=
+{
+ L"black",
+ L"red",
+ L"green",
+ L"brown",
+ L"yellow",
+ L"blue",
+ L"magenta",
+ L"purple",
+ L"cyan",
+ L"white"
+ L"normal"
+}
+ ;
+
+/**
+ Mapping from color name (the 'col' array) to color index as used in
+ ANSI color terminals, and also the fish_color_* constants defined
+ in highlight.h. Non-ANSI terminals will display the wrong colors,
+ since they use a different mapping.
+*/
+static int col_idx[]=
+{
+ 0,
+ 1,
+ 2,
+ 3,
+ 3,
+ 4,
+ 5,
+ 5,
+ 6,
+ 7,
+ FISH_COLOR_NORMAL,
+}
+ ;
+
+/**
+ Size of writestr_buff
+*/
+static size_t writestr_buff_sz=0;
+
+/**
+ Temp buffer used for converting from wide to narrow strings
+*/
+static char *writestr_buff = 0;
+
+/**
+ The function used for output
+*/
+
+static int (*out)(char c) = &writeb_internal;
+
+/**
+ Name of terminal
+ */
+static wchar_t *current_term = 0;
+
+
+/**
+ Cleanup function. Run automatically through halloc
+*/
+static void output_destroy()
+{
+ free( writestr_buff );
+}
+
+void output_set_writer( int (*writer)(char) )
+{
+ CHECK( writer, );
+ out = writer;
+}
+
+int (*output_get_writer())(char)
+{
+ return out;
+}
+
+
+void set_color( int c, int c2 )
+{
+ static int last_color = FISH_COLOR_NORMAL;
+ static int last_color2 = FISH_COLOR_NORMAL;
+ static int was_bold=0;
+ static int was_underline=0;
+ int bg_set=0, last_bg_set=0;
+ char *fg = 0, *bg=0;
+
+ int is_bold = 0;
+ int is_underline = 0;
+
+ /*
+ Test if we have at least basic support for setting fonts, colors
+ and related bits - otherwise just give up...
+ */
+ if( !exit_attribute_mode )
+ {
+ return;
+ }
+
+
+ is_bold |= (c&FISH_COLOR_BOLD)!=0;
+ is_bold |= (c2&FISH_COLOR_BOLD)!=0;
+
+ is_underline |= (c&FISH_COLOR_UNDERLINE)!=0;
+ is_underline |= (c2&FISH_COLOR_UNDERLINE)!=0;
+
+ c = c&(~(FISH_COLOR_BOLD|FISH_COLOR_UNDERLINE));
+ c2 = c2&(~(FISH_COLOR_BOLD|FISH_COLOR_UNDERLINE));
+
+ if( (set_a_foreground != 0) && (strlen( set_a_foreground) != 0 ) )
+ {
+ fg = set_a_foreground;
+ bg = set_a_background;
+ }
+ else if( (set_foreground != 0) && (strlen( set_foreground) != 0 ) )
+ {
+ fg = set_foreground;
+ bg = set_background;
+ }
+
+ if( (c == FISH_COLOR_RESET) || (c2 == FISH_COLOR_RESET))
+ {
+ c = c2 = FISH_COLOR_NORMAL;
+ was_bold=0;
+ was_underline=0;
+ if( fg )
+ {
+ /*
+ If we exit attibute mode, we must first set a color, or
+ previously coloured text might lose it's
+ color. Terminals are weird...
+ */
+ writembs( tparm( fg, 0 ) );
+ }
+ writembs( exit_attribute_mode );
+ return;
+ }
+
+ if( was_bold && !is_bold )
+ {
+ /*
+ Only way to exit bold mode is a reset of all attributes.
+ */
+ writembs( exit_attribute_mode );
+ last_color = FISH_COLOR_NORMAL;
+ last_color2 = FISH_COLOR_NORMAL;
+ was_bold=0;
+ was_underline=0;
+ }
+
+ if( last_color2 != FISH_COLOR_NORMAL &&
+ last_color2 != FISH_COLOR_RESET &&
+ last_color2 != FISH_COLOR_IGNORE )
+ {
+ /*
+ Background was set
+ */
+ last_bg_set=1;
+ }
+
+ if( c2 != FISH_COLOR_NORMAL &&
+ c2 != FISH_COLOR_IGNORE )
+ {
+ /*
+ Background is set
+ */
+ bg_set=1;
+ c = (c2==FISH_COLOR_WHITE)?FISH_COLOR_BLACK:FISH_COLOR_WHITE;
+ }
+
+ if( (enter_bold_mode != 0) && (strlen(enter_bold_mode) > 0))
+ {
+ if(bg_set && !last_bg_set)
+ {
+ /*
+ Background color changed and is set, so we enter bold
+ mode to make reading easier. This means bold mode is
+ _always_ on when the background color is set.
+ */
+ writembs( enter_bold_mode );
+ }
+ if(!bg_set && last_bg_set)
+ {
+ /*
+ Background color changed and is no longer set, so we
+ exit bold mode
+ */
+ writembs( exit_attribute_mode );
+ was_bold=0;
+ was_underline=0;
+ /*
+ We don't know if exit_attribute_mode resets colors, so
+ we set it to something known.
+ */
+ if( fg )
+ {
+ writembs( tparm( fg, 0 ) );
+ last_color=0;
+ }
+ }
+ }
+
+ if( last_color != c )
+ {
+ if( c==FISH_COLOR_NORMAL )
+ {
+ if( fg )
+ {
+ writembs( tparm( fg, 0 ) );
+ }
+ writembs( exit_attribute_mode );
+
+ last_color2 = FISH_COLOR_NORMAL;
+ was_bold=0;
+ was_underline=0;
+ }
+ else if( ( c >= 0 ) && ( c < FISH_COLOR_NORMAL ) )
+ {
+ if( fg )
+ {
+ writembs( tparm( fg, c ) );
+ }
+ }
+ }
+
+ last_color = c;
+
+ if( last_color2 != c2 )
+ {
+ if( c2 == FISH_COLOR_NORMAL )
+ {
+ if( bg )
+ {
+ writembs( tparm( bg, 0 ) );
+ }
+
+ writembs( exit_attribute_mode );
+ if( ( last_color != FISH_COLOR_NORMAL ) && fg )
+ {
+ if( fg )
+ {
+ writembs( tparm( fg, last_color ) );
+ }
+ }
+
+
+ was_bold=0;
+ was_underline=0;
+ last_color2 = c2;
+ }
+ else if ( ( c2 >= 0 ) && ( c2 < FISH_COLOR_NORMAL ) )
+ {
+ if( bg )
+ {
+ writembs( tparm( bg, c2 ) );
+ }
+ last_color2 = c2;
+ }
+ }
+
+ /*
+ Lastly, we set bold mode and underline mode correctly
+ */
+ if( (enter_bold_mode != 0) && (strlen(enter_bold_mode) > 0) && !bg_set )
+ {
+ if( is_bold && !was_bold )
+ {
+ if( enter_bold_mode )
+ {
+ writembs( tparm( enter_bold_mode ) );
+ }
+ }
+ was_bold = is_bold;
+ }
+
+ if( was_underline && !is_underline )
+ {
+ writembs( exit_underline_mode );
+ }
+
+ if( !was_underline && is_underline )
+ {
+ writembs( enter_underline_mode );
+ }
+ was_underline = is_underline;
+
+}
+
+/**
+ Default output method, simply calls write() on stdout
+*/
+static int writeb_internal( char c )
+{
+ write_loop( 1, &c, 1 );
+ return 0;
+}
+
+int writeb( tputs_arg_t b )
+{
+ out( b );
+ return 0;
+}
+
+int writembs_internal( char *str )
+{
+ CHECK( str, 1 );
+
+ return tputs(str,1,&writeb)==ERR?1:0;
+}
+
+int writech( wint_t ch )
+{
+ mbstate_t state;
+ int i;
+ char buff[MB_LEN_MAX+1];
+ size_t bytes;
+
+ if( ( ch >= ENCODE_DIRECT_BASE) &&
+ ( ch < ENCODE_DIRECT_BASE+256) )
+ {
+ buff[0] = ch - ENCODE_DIRECT_BASE;
+ bytes=1;
+ }
+ else
+ {
+ memset( &state, 0, sizeof(state) );
+ bytes= wcrtomb( buff, ch, &state );
+
+ switch( bytes )
+ {
+ case (size_t)(-1):
+ {
+ return 1;
+ }
+ }
+ }
+
+ for( i=0; i<bytes; i++ )
+ {
+ out( buff[i] );
+ }
+ return 0;
+}
+
+void writestr( const wchar_t *str )
+{
+ char *pos;
+
+ CHECK( str, );
+
+// while( *str )
+// writech( *str++ );
+
+ /*
+ Check amount of needed space
+ */
+ size_t len = wcstombs( 0, str, 0 );
+
+ if( len == (size_t)-1 )
+ {
+ debug( 1, L"Tried to print invalid wide character string" );
+ return;
+ }
+
+ len++;
+
+ /*
+ Reallocate if needed
+ */
+ if( writestr_buff_sz < len )
+ {
+ if( !writestr_buff )
+ {
+ halloc_register_function_void( global_context, &output_destroy );
+ }
+
+ writestr_buff = realloc( writestr_buff, len );
+ if( !writestr_buff )
+ {
+ DIE_MEM();
+ }
+ writestr_buff_sz = len;
+ }
+
+ /*
+ Convert
+ */
+ wcstombs( writestr_buff,
+ str,
+ writestr_buff_sz );
+
+ /*
+ Write
+ */
+ for( pos = writestr_buff; *pos; pos++ )
+ {
+ out( *pos );
+ }
+}
+
+
+void writestr_ellipsis( const wchar_t *str, int max_width )
+{
+ int written=0;
+ int tot;
+
+ CHECK( str, );
+
+ tot = my_wcswidth(str);
+
+ if( tot <= max_width )
+ {
+ writestr( str );
+ return;
+ }
+
+ while( *str != 0 )
+ {
+ int w = wcwidth( *str );
+ if( written+w+wcwidth( ellipsis_char )>max_width )
+ {
+ break;
+ }
+ written+=w;
+ writech( *(str++) );
+ }
+
+ written += wcwidth( ellipsis_char );
+ writech( ellipsis_char );
+
+ while( written < max_width )
+ {
+ written++;
+ writestr( L" " );
+ }
+}
+
+int write_escaped_str( const wchar_t *str, int max_len )
+{
+
+ wchar_t *out;
+ int i;
+ int len;
+ int written=0;
+
+ CHECK( str, 0 );
+
+ out = escape( str, 1 );
+ len = my_wcswidth( out );
+
+ if( max_len && (max_len < len))
+ {
+ for( i=0; (written+wcwidth(out[i]))<=(max_len-1); i++ )
+ {
+ writech( out[i] );
+ written += wcwidth( out[i] );
+ }
+ writech( ellipsis_char );
+ written += wcwidth( ellipsis_char );
+
+ for( i=written; i<max_len; i++ )
+ {
+ writech( L' ' );
+ written++;
+ }
+ }
+ else
+ {
+ written = len;
+ writestr( out );
+ }
+
+ free( out );
+ return written;
+}
+
+
+int output_color_code( const wchar_t *val )
+{
+ int j, i, color=FISH_COLOR_NORMAL;
+ array_list_t el;
+ int is_bold=0;
+ int is_underline=0;
+
+ if( !val )
+ return FISH_COLOR_NORMAL;
+
+ al_init( &el );
+ tokenize_variable_array( val, &el );
+
+ for( j=0; j<al_get_count( &el ); j++ )
+ {
+ wchar_t *next = (wchar_t *)al_get( &el, j );
+
+ is_bold |= (wcsncmp( next, L"--bold", wcslen(next) ) == 0 ) && wcslen(next)>=3;
+ is_bold |= wcscmp( next, L"-o" ) == 0;
+
+ is_underline |= (wcsncmp( next, L"--underline", wcslen(next) ) == 0 ) && wcslen(next)>=3;
+ is_underline |= wcscmp( next, L"-u" ) == 0;
+
+ for( i=0; i<COLORS; i++ )
+ {
+ if( wcscasecmp( col[i], next ) == 0 )
+ {
+ color = col_idx[i];
+ break;
+ }
+ }
+
+ }
+
+ al_foreach( &el, &free );
+ al_destroy( &el );
+
+ return color | (is_bold?FISH_COLOR_BOLD:0) | (is_underline?FISH_COLOR_UNDERLINE:0);
+
+}
+
+void output_set_term( wchar_t *term )
+{
+ current_term = halloc_wcsdup(global_context, term);
+}
+
+wchar_t *output_get_term()
+{
+ return current_term ? current_term : L"<unknown>";
+}
+
+