aboutsummaryrefslogtreecommitdiffhomepage
path: root/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'output.c')
-rw-r--r--output.c367
1 files changed, 367 insertions, 0 deletions
diff --git a/output.c b/output.c
new file mode 100644
index 00000000..92f97f03
--- /dev/null
+++ b/output.c
@@ -0,0 +1,367 @@
+#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>
+#include <sys/ioctl.h>
+#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
+
+#include <term.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <time.h>
+#include <wchar.h>
+
+#include "util.h"
+#include "wutil.h"
+#include "expand.h"
+#include "common.h"
+#include "output.h"
+#include "highlight.h"
+
+/**
+ Number of color names in the col array
+*/
+#define COLORS (sizeof(col)/sizeof(wchar_t *))
+
+/**
+ 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,
+}
+ ;
+
+void set_color( int c, int c2 )
+{
+ static int last_color = FISH_COLOR_NORMAL, last_color2=FISH_COLOR_NORMAL;
+ int bg_set=0, last_bg_set=0;
+ char *fg = 0, *bg=0;
+
+ 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;
+ if( fg )
+ writembs( tparm( set_a_foreground, 0 ) );
+ writembs( exit_attribute_mode );
+ return;
+ }
+
+ 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_RESET &&
+ 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
+ */
+ 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 );
+ /*
+ 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;
+ }
+ 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 )
+ {
+ writembs(tparm( fg, last_color ));
+ }
+
+ last_color2 = c2;
+ }
+ else if ((c2 >= 0 ) &&(c2 < FISH_COLOR_NORMAL))
+ {
+ if( bg )
+ {
+ writembs( tparm( bg, c2 ) );
+ }
+ last_color2 = c2;
+ }
+ }
+}
+
+int writembs( char *str )
+{
+#ifdef TPUTS_KLUDGE
+ write( 1, str, strlen(str));
+#else
+ tputs(str,1,&writeb);
+#endif
+ return 0;
+}
+
+/**
+ Write a wide character to fd 1.
+*/
+int writech( wint_t ch )
+{
+ static mbstate_t out_state;
+ char buff[MB_CUR_MAX];
+ size_t bytes = wcrtomb( buff, ch, &out_state );
+ int err;
+
+ while( (err =write( 1, buff, bytes ) ) )
+ {
+ if( err >= 0 )
+ break;
+
+ if( errno == EINTR )
+ continue;
+
+ wperror( L"write" );
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ Write a wide character string to FD 1.
+*/
+void writestr( const wchar_t *str )
+{
+ while( *str != 0 )
+ writech( *(str++) );
+}
+
+
+/**
+ Write a wide character string to FD 1. If the string is wider than
+ the specified maximum, truncate and ellipsize it.
+*/
+void writestr_ellipsis( const wchar_t *str, int max_width )
+{
+ int written=0;
+ int 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" " );
+ }
+}
+
+/**
+ Escape and write a string to fd 1
+*/
+int write_escaped_str( const wchar_t *str, int max_len )
+{
+
+ wchar_t *out = escape( wcsdup(str), 1 );
+ int i;
+ int len = my_wcswidth( out );
+ int written=0;
+
+ 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;
+}
+
+
+/**
+ parm_ich seems to often be undefined, so we use this
+ workalike. Writes the specified number of spaces.
+*/
+int writespace( int c )
+{
+ if( repeat_char && strlen(repeat_char) )
+ {
+ debug( 1, L"YAY" );
+
+ writembs( tparm( repeat_char, ' ', c ) );
+ }
+ else
+ {
+ write( 1, " ", mini(c,8) );
+ if( c>8)
+ {
+ writespace( c-8);
+ }
+ }
+
+ return 0;
+}
+
+
+int output_color_code( const wchar_t *val )
+{
+ int i, color=-1;
+
+ for( i=0; i<COLORS; i++ )
+ {
+ if( wcscasecmp( col[i], val ) == 0 )
+ {
+ color = col_idx[i];
+ break;
+ }
+ }
+
+ if( color >= 0 )
+ return color;
+ else
+ return FISH_COLOR_NORMAL;
+}