2005-10-17 23:24:12 +10:00
/** \file output.c
Generic output functions
*/
2005-09-20 23:26:39 +10:00
# 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>
2006-08-10 08:53:38 +10:00
# ifdef HAVE_SYS_TERMIOS_H
# include <sys/termios.h>
# endif
# ifdef HAVE_SYS_IOCTL_H
2005-09-20 23:26:39 +10:00
# include <sys/ioctl.h>
2006-08-10 08:53:38 +10:00
# endif
2005-09-20 23:26:39 +10:00
# 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
2006-01-19 22:22:07 +10:00
# if HAVE_TERM_H
2005-09-20 23:26:39 +10:00
# include <term.h>
2006-01-19 22:22:07 +10:00
# elif HAVE_NCURSES_TERM_H
# include <ncurses/term.h>
# endif
2005-09-20 23:26:39 +10:00
# include <signal.h>
# include <fcntl.h>
# include <dirent.h>
# include <time.h>
# include <wchar.h>
2006-02-28 23:17:16 +10:00
# include "fallback.h"
2005-09-20 23:26:39 +10:00
# include "util.h"
2006-02-28 23:17:16 +10:00
2005-09-20 23:26:39 +10:00
# include "wutil.h"
# include "expand.h"
# include "common.h"
# include "output.h"
# include "highlight.h"
2012-02-12 18:05:59 -08:00
# include "env.h"
2005-09-20 23:26:39 +10:00
/**
Number of color names in the col array
*/
# define COLORS (sizeof(col) / sizeof(wchar_t *))
2006-02-17 00:21:00 +10:00
static int writeb_internal ( char c ) ;
2005-09-20 23:26:39 +10:00
/**
2011-12-26 19:18:46 -08:00
Names of different colors .
2005-09-20 23:26:39 +10:00
*/
2012-01-14 22:00:00 -08:00
static const wchar_t * col [ ] =
2005-09-20 23:26:39 +10:00
{
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 .
*/
2012-01-14 22:00:00 -08:00
static const int col_idx [ ] =
2005-09-20 23:26:39 +10:00
{
2011-12-26 19:18:46 -08:00
0 ,
2005-09-20 23:26:39 +10:00
1 ,
2 ,
3 ,
3 ,
4 ,
5 ,
5 ,
6 ,
7 ,
FISH_COLOR_NORMAL ,
2012-02-07 22:44:10 -08:00
} ;
2005-10-14 00:08:33 +10:00
2006-02-16 23:40:25 +10:00
/**
The function used for output
*/
2006-02-17 00:21:00 +10:00
static int ( * out ) ( char c ) = & writeb_internal ;
2006-02-16 23:40:25 +10:00
2008-01-14 02:47:47 +10:00
/**
Name of terminal
*/
2012-02-09 16:06:24 -08:00
static wcstring current_term ;
2007-09-10 00:04:36 +10:00
2006-02-17 00:21:00 +10:00
void output_set_writer ( int ( * writer ) ( char ) )
2006-02-16 23:40:25 +10:00
{
2006-07-11 08:39:56 +10:00
CHECK ( writer , ) ;
2006-02-16 23:40:25 +10:00
out = writer ;
}
2006-10-02 02:02:58 +10:00
int ( * output_get_writer ( ) ) ( char )
{
return out ;
}
2012-02-12 18:05:59 -08:00
bool allow_term256 ( void )
{
//consider using t_Co
ASSERT_IS_MAIN_THREAD ( ) ;
const wchar_t * t = output_get_term ( ) ;
return t & & wcsstr ( t , L " 256color " ) ;
}
static unsigned char index_for_color ( rgb_color_t c ) {
if ( c . is_named ( ) | | ! allow_term256 ( ) ) {
return c . to_name_index ( ) ;
} else {
return c . to_term256_index ( ) ;
}
}
2012-02-11 17:07:56 -08:00
void set_color ( rgb_color_t c , rgb_color_t c2 )
{
2012-02-12 18:05:59 -08:00
#if 0
wcstring tmp = c . description ( ) ;
wcstring tmp2 = c2 . description ( ) ;
printf ( " set_color %ls : %ls \n " , tmp . c_str ( ) , tmp2 . c_str ( ) ) ;
# endif
2012-02-11 17:07:56 -08:00
ASSERT_IS_MAIN_THREAD ( ) ;
const rgb_color_t normal = rgb_color_t : : normal ( ) ;
static rgb_color_t last_color = rgb_color_t : : normal ( ) ;
static rgb_color_t last_color2 = rgb_color_t : : 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 . is_bold ( ) ;
is_bold | = c2 . is_bold ( ) ;
is_underline | = c . is_underline ( ) ;
is_underline | = c2 . is_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 . is_reset ( ) | | c2 . is_reset ( ) )
{
c = c2 = 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 = normal ;
last_color2 = normal ;
was_bold = 0 ;
was_underline = 0 ;
}
2012-02-12 18:05:59 -08:00
if ( ! last_color2 . is_normal ( ) & &
! last_color2 . is_reset ( ) & &
! last_color2 . is_ignore ( ) )
2012-02-11 17:07:56 -08:00
{
/*
Background was set
*/
last_bg_set = 1 ;
}
2012-02-12 18:05:59 -08:00
if ( ! c2 . is_normal ( ) & &
! c2 . is_ignore ( ) )
2012-02-11 17:07:56 -08:00
{
/*
Background is set
*/
bg_set = 1 ;
2012-02-12 18:05:59 -08:00
c = ( c2 = = rgb_color_t : : white ( ) ) ? rgb_color_t : : black ( ) : rgb_color_t : : white ( ) ;
2012-02-11 17:07:56 -08:00
}
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 = rgb_color_t : : black ( ) ;
}
}
}
if ( last_color ! = c )
{
2012-02-12 18:05:59 -08:00
if ( c . is_normal ( ) )
2012-02-11 17:07:56 -08:00
{
if ( fg )
{
writembs ( tparm ( fg , 0 ) ) ;
}
writembs ( exit_attribute_mode ) ;
last_color2 = rgb_color_t : : normal ( ) ;
was_bold = 0 ;
was_underline = 0 ;
}
2012-02-12 18:05:59 -08:00
else if ( ! c . is_special ( ) )
2012-02-11 17:07:56 -08:00
{
if ( fg )
{
2012-02-12 18:05:59 -08:00
writembs ( tparm ( fg , index_for_color ( c ) ) ) ;
2012-02-11 17:07:56 -08:00
}
}
}
last_color = c ;
if ( last_color2 ! = c2 )
{
2012-02-12 18:05:59 -08:00
if ( c2 . is_normal ( ) )
2012-02-11 17:07:56 -08:00
{
if ( bg )
{
writembs ( tparm ( bg , 0 ) ) ;
}
writembs ( exit_attribute_mode ) ;
2012-02-12 18:05:59 -08:00
if ( ! last_color . is_normal ( ) & & fg )
2012-02-11 17:07:56 -08:00
{
2012-02-12 18:05:59 -08:00
writembs ( tparm ( fg , index_for_color ( last_color ) ) ) ;
2012-02-11 17:07:56 -08:00
}
was_bold = 0 ;
was_underline = 0 ;
last_color2 = c2 ;
}
2012-02-12 18:05:59 -08:00
else if ( ! c2 . is_special ( ) )
2012-02-11 17:07:56 -08:00
{
if ( bg )
{
2012-02-12 18:05:59 -08:00
writembs ( tparm ( bg , index_for_color ( c2 ) ) ) ;
2012-02-11 17:07:56 -08:00
}
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 ;
}
2005-10-14 00:08:33 +10:00
2005-09-20 23:26:39 +10:00
void set_color ( int c , int c2 )
{
2012-02-06 20:14:19 -08:00
ASSERT_IS_MAIN_THREAD ( ) ;
static int last_color = FISH_COLOR_NORMAL ;
2005-10-17 23:24:12 +10:00
static int last_color2 = FISH_COLOR_NORMAL ;
2006-05-27 23:39:30 +10:00
static int was_bold = 0 ;
2006-06-14 23:22:40 +10:00
static int was_underline = 0 ;
2005-09-20 23:26:39 +10:00
int bg_set = 0 , last_bg_set = 0 ;
char * fg = 0 , * bg = 0 ;
2006-05-27 23:39:30 +10:00
int is_bold = 0 ;
2006-06-14 23:22:40 +10:00
int is_underline = 0 ;
2006-05-27 23:39:30 +10:00
2007-01-16 03:51:44 +10:00
/*
Test if we have at least basic support for setting fonts , colors
and related bits - otherwise just give up . . .
*/
if ( ! exit_attribute_mode )
{
return ;
}
2011-12-26 19:18:46 -08:00
2007-01-16 03:51:44 +10:00
2006-05-27 23:39:30 +10:00
is_bold | = ( c & FISH_COLOR_BOLD ) ! = 0 ;
is_bold | = ( c2 & FISH_COLOR_BOLD ) ! = 0 ;
2006-06-14 23:22:40 +10:00
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 ) ) ;
2006-05-27 23:39:30 +10:00
2005-09-20 23:26:39 +10:00
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 ;
2006-05-27 23:39:30 +10:00
was_bold = 0 ;
2006-06-14 23:22:40 +10:00
was_underline = 0 ;
2005-09-20 23:26:39 +10:00
if ( fg )
2006-02-20 23:11:46 +10:00
{
2006-05-27 23:39:30 +10:00
/*
If we exit attibute mode , we must first set a color , or
previously coloured text might lose it ' s
color . Terminals are weird . . .
*/
2006-02-17 00:21:00 +10:00
writembs ( tparm ( fg , 0 ) ) ;
2006-02-20 23:11:46 +10:00
}
2006-02-17 00:21:00 +10:00
writembs ( exit_attribute_mode ) ;
2005-09-20 23:26:39 +10:00
return ;
}
2006-05-27 23:39:30 +10:00
if ( was_bold & & ! is_bold )
{
/*
2011-12-26 19:18:46 -08:00
Only way to exit bold mode is a reset of all attributes .
2006-05-27 23:39:30 +10:00
*/
writembs ( exit_attribute_mode ) ;
last_color = FISH_COLOR_NORMAL ;
last_color2 = FISH_COLOR_NORMAL ;
was_bold = 0 ;
2006-06-14 23:22:40 +10:00
was_underline = 0 ;
2006-05-27 23:39:30 +10:00
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
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 )
{
/*
2005-10-17 23:24:12 +10:00
Background color changed and is set , so we enter bold
2006-05-27 23:39:30 +10:00
mode to make reading easier . This means bold mode is
_always_ on when the background color is set .
2005-09-20 23:26:39 +10:00
*/
2006-02-17 00:21:00 +10:00
writembs ( enter_bold_mode ) ;
2005-09-20 23:26:39 +10:00
}
if ( ! bg_set & & last_bg_set )
{
/*
2005-10-17 23:24:12 +10:00
Background color changed and is no longer set , so we
exit bold mode
2005-09-20 23:26:39 +10:00
*/
2006-02-17 00:21:00 +10:00
writembs ( exit_attribute_mode ) ;
2006-06-14 23:22:40 +10:00
was_bold = 0 ;
was_underline = 0 ;
2005-09-20 23:26:39 +10:00
/*
We don ' t know if exit_attribute_mode resets colors , so
we set it to something known .
*/
if ( fg )
{
2006-02-17 00:21:00 +10:00
writembs ( tparm ( fg , 0 ) ) ;
2005-09-20 23:26:39 +10:00
last_color = 0 ;
}
}
}
if ( last_color ! = c )
{
if ( c = = FISH_COLOR_NORMAL )
{
if ( fg )
2006-02-20 23:11:46 +10:00
{
2006-02-17 00:21:00 +10:00
writembs ( tparm ( fg , 0 ) ) ;
2006-02-20 23:11:46 +10:00
}
2006-02-17 00:21:00 +10:00
writembs ( exit_attribute_mode ) ;
2005-09-20 23:26:39 +10:00
last_color2 = FISH_COLOR_NORMAL ;
2006-06-14 23:22:40 +10:00
was_bold = 0 ;
was_underline = 0 ;
2005-09-20 23:26:39 +10:00
}
2006-02-20 23:11:46 +10:00
else if ( ( c > = 0 ) & & ( c < FISH_COLOR_NORMAL ) )
2005-09-20 23:26:39 +10:00
{
if ( fg )
{
2006-02-17 00:21:00 +10:00
writembs ( tparm ( fg , c ) ) ;
2005-09-20 23:26:39 +10:00
}
}
}
last_color = c ;
if ( last_color2 ! = c2 )
{
if ( c2 = = FISH_COLOR_NORMAL )
{
if ( bg )
{
2006-02-17 00:21:00 +10:00
writembs ( tparm ( bg , 0 ) ) ;
2005-09-20 23:26:39 +10:00
}
2006-02-20 23:11:46 +10:00
writembs ( exit_attribute_mode ) ;
if ( ( last_color ! = FISH_COLOR_NORMAL ) & & fg )
2005-09-20 23:26:39 +10:00
{
2006-07-31 10:48:04 +10:00
if ( fg )
{
writembs ( tparm ( fg , last_color ) ) ;
}
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
2006-06-14 23:22:40 +10:00
was_bold = 0 ;
was_underline = 0 ;
2005-09-20 23:26:39 +10:00
last_color2 = c2 ;
}
2006-02-20 23:11:46 +10:00
else if ( ( c2 > = 0 ) & & ( c2 < FISH_COLOR_NORMAL ) )
2005-09-20 23:26:39 +10:00
{
if ( bg )
{
2006-02-17 00:21:00 +10:00
writembs ( tparm ( bg , c2 ) ) ;
2005-09-20 23:26:39 +10:00
}
last_color2 = c2 ;
}
}
2006-05-27 23:39:30 +10:00
/*
2006-06-14 23:22:40 +10:00
Lastly , we set bold mode and underline mode correctly
2006-05-27 23:39:30 +10:00
*/
if ( ( enter_bold_mode ! = 0 ) & & ( strlen ( enter_bold_mode ) > 0 ) & & ! bg_set )
{
if ( is_bold & & ! was_bold )
{
2006-07-31 10:48:04 +10:00
if ( enter_bold_mode )
{
writembs ( tparm ( enter_bold_mode ) ) ;
}
2006-05-27 23:39:30 +10:00
}
2011-12-26 19:18:46 -08:00
was_bold = is_bold ;
2006-05-27 23:39:30 +10:00
}
2006-06-14 23:22:40 +10:00
if ( was_underline & & ! is_underline )
{
2011-12-26 19:18:46 -08:00
writembs ( exit_underline_mode ) ;
2006-06-14 23:22:40 +10:00
}
2011-12-26 19:18:46 -08:00
2006-06-14 23:22:40 +10:00
if ( ! was_underline & & is_underline )
{
2011-12-26 19:18:46 -08:00
writembs ( enter_underline_mode ) ;
2006-06-14 23:22:40 +10:00
}
was_underline = is_underline ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
}
2006-06-20 10:50:10 +10:00
/**
Default output method , simply calls write ( ) on stdout
*/
2006-02-17 00:21:00 +10:00
static int writeb_internal ( char c )
{
2009-02-23 06:28:52 +10:00
write_loop ( 1 , & c , 1 ) ;
2006-02-17 00:21:00 +10:00
return 0 ;
}
2006-02-16 23:40:25 +10:00
int writeb ( tputs_arg_t b )
{
2006-02-17 00:21:00 +10:00
out ( b ) ;
2006-02-16 23:40:25 +10:00
return 0 ;
}
2007-09-10 00:04:36 +10:00
int writembs_internal ( char * str )
2005-09-20 23:26:39 +10:00
{
2006-07-11 08:39:56 +10:00
CHECK ( str , 1 ) ;
2011-12-26 19:18:46 -08:00
2006-02-28 23:17:16 +10:00
return tputs ( str , 1 , & writeb ) = = ERR ? 1 : 0 ;
2005-09-20 23:26:39 +10:00
}
int writech ( wint_t ch )
{
2006-02-25 04:40:50 +10:00
mbstate_t state ;
2012-01-14 22:32:45 -08:00
size_t i ;
2007-01-23 02:51:25 +10:00
char buff [ MB_LEN_MAX + 1 ] ;
2006-02-25 04:40:50 +10:00
size_t bytes ;
if ( ( ch > = ENCODE_DIRECT_BASE ) & &
( ch < ENCODE_DIRECT_BASE + 256 ) )
{
2006-02-25 12:21:39 +10:00
buff [ 0 ] = ch - ENCODE_DIRECT_BASE ;
2006-02-25 04:40:50 +10:00
bytes = 1 ;
}
else
{
memset ( & state , 0 , sizeof ( state ) ) ;
bytes = wcrtomb ( buff , ch , & state ) ;
2011-12-26 19:18:46 -08:00
2006-02-25 04:40:50 +10:00
switch ( bytes )
{
case ( size_t ) ( - 1 ) :
{
return 1 ;
}
}
}
2011-12-26 19:18:46 -08:00
2006-02-17 00:21:00 +10:00
for ( i = 0 ; i < bytes ; i + + )
2006-02-20 23:11:46 +10:00
{
2006-02-17 00:21:00 +10:00
out ( buff [ i ] ) ;
2006-02-20 23:11:46 +10:00
}
2005-09-20 23:26:39 +10:00
return 0 ;
}
void writestr ( const wchar_t * str )
{
2006-02-17 00:21:00 +10:00
char * pos ;
2006-07-11 08:39:56 +10:00
CHECK ( str , ) ;
2011-12-26 19:18:46 -08:00
2005-10-15 10:51:26 +10:00
// while( *str )
// writech( *str++ );
2005-10-17 23:24:12 +10:00
/*
Check amount of needed space
*/
size_t len = wcstombs ( 0 , str , 0 ) ;
2011-12-26 19:18:46 -08:00
2005-10-17 23:24:12 +10:00
if ( len = = ( size_t ) - 1 )
{
debug ( 1 , L " Tried to print invalid wide character string " ) ;
return ;
}
2011-12-26 19:18:46 -08:00
2005-10-17 23:24:12 +10:00
len + + ;
2011-12-26 19:18:46 -08:00
2005-10-17 23:24:12 +10:00
/*
Convert
*/
2012-02-07 22:44:10 -08:00
char * buffer , static_buffer [ 256 ] ;
if ( len < = sizeof static_buffer )
buffer = static_buffer ;
else
buffer = new char [ len ] ;
wcstombs ( buffer ,
2005-10-14 00:08:33 +10:00
str ,
2012-02-07 22:44:10 -08:00
len ) ;
2005-10-14 00:08:33 +10:00
2005-10-17 23:24:12 +10:00
/*
Write
*/
2012-02-07 22:44:10 -08:00
for ( pos = buffer ; * pos ; pos + + )
2006-02-20 23:11:46 +10:00
{
2006-02-17 00:21:00 +10:00
out ( * pos ) ;
2006-02-20 23:11:46 +10:00
}
2012-02-07 22:44:10 -08:00
if ( buffer ! = static_buffer )
delete [ ] buffer ;
2005-09-20 23:26:39 +10:00
}
void writestr_ellipsis ( const wchar_t * str , int max_width )
{
int written = 0 ;
2006-07-11 08:39:56 +10:00
int tot ;
CHECK ( str , ) ;
2011-12-26 19:18:46 -08:00
2006-07-11 08:39:56 +10:00
tot = my_wcswidth ( str ) ;
2005-09-20 23:26:39 +10:00
if ( tot < = max_width )
{
writestr ( str ) ;
return ;
}
while ( * str ! = 0 )
{
int w = wcwidth ( * str ) ;
if ( written + w + wcwidth ( ellipsis_char ) > max_width )
2006-02-20 23:11:46 +10:00
{
2005-09-20 23:26:39 +10:00
break ;
2006-02-20 23:11:46 +10:00
}
2005-09-20 23:26:39 +10:00
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 )
{
2006-07-11 08:39:56 +10:00
wchar_t * out ;
2005-09-20 23:26:39 +10:00
int i ;
2006-07-11 08:39:56 +10:00
int len ;
2005-09-20 23:26:39 +10:00
int written = 0 ;
2006-07-11 08:39:56 +10:00
CHECK ( str , 0 ) ;
2011-12-26 19:18:46 -08:00
2006-07-11 08:39:56 +10:00
out = escape ( str , 1 ) ;
len = my_wcswidth ( out ) ;
2005-09-20 23:26:39 +10:00
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 ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
for ( i = written ; i < max_len ; i + + )
{
writech ( L ' ' ) ;
written + + ;
}
}
else
{
written = len ;
writestr ( out ) ;
}
free ( out ) ;
return written ;
}
2012-02-06 20:14:19 -08:00
int output_color_code ( const wcstring & val , bool is_background ) {
2012-01-14 22:32:45 -08:00
size_t i ;
int color = FISH_COLOR_NORMAL ;
2006-05-27 23:39:30 +10:00
int is_bold = 0 ;
2006-06-14 23:22:40 +10:00
int is_underline = 0 ;
2011-12-26 19:18:46 -08:00
2012-02-06 20:14:19 -08:00
if ( val . empty ( ) )
2006-05-27 23:39:30 +10:00
return FISH_COLOR_NORMAL ;
2011-12-26 19:18:46 -08:00
2012-01-14 22:32:45 -08:00
wcstring_list_t el ;
2012-02-10 01:37:30 -08:00
tokenize_variable_array ( val , el ) ;
2011-12-26 19:18:46 -08:00
2012-02-06 20:14:19 -08:00
for ( size_t j = 0 ; j < el . size ( ) ; j + + ) {
const wcstring & next = el . at ( j ) ;
wcstring color_name ;
if ( is_background ) {
// look for something like "--background=red"
const wcstring prefix = L " --background= " ;
if ( string_prefixes_string ( prefix , next ) ) {
color_name = wcstring ( next , prefix . size ( ) ) ;
}
} else {
if ( next = = L " --bold " | | next = = L " -o " )
is_bold = true ;
else if ( next = = L " --underline " | | next = = L " -u " )
is_underline = true ;
else
color_name = next ;
}
if ( ! color_name . empty ( ) ) {
for ( i = 0 ; i < COLORS ; i + + )
{
if ( wcscasecmp ( col [ i ] , color_name . c_str ( ) ) = = 0 )
{
color = col_idx [ i ] ;
break ;
}
}
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
2012-02-11 17:07:56 -08:00
return color | ( is_bold ? FISH_COLOR_BOLD : 0 ) | ( is_underline ? FISH_COLOR_UNDERLINE : 0 ) ;
}
rgb_color_t parse_color ( const wcstring & val , bool is_background ) {
int is_bold = 0 ;
int is_underline = 0 ;
2012-02-13 09:52:17 -08:00
std : : vector < rgb_color_t > candidates ;
2012-02-11 17:07:56 -08:00
wcstring_list_t el ;
tokenize_variable_array ( val , el ) ;
2011-12-26 19:18:46 -08:00
2012-02-11 17:07:56 -08:00
for ( size_t j = 0 ; j < el . size ( ) ; j + + ) {
const wcstring & next = el . at ( j ) ;
wcstring color_name ;
if ( is_background ) {
// look for something like "--background=red"
const wcstring prefix = L " --background= " ;
if ( string_prefixes_string ( prefix , next ) ) {
color_name = wcstring ( next , prefix . size ( ) ) ;
}
} else {
if ( next = = L " --bold " | | next = = L " -o " )
is_bold = true ;
else if ( next = = L " --underline " | | next = = L " -u " )
is_underline = true ;
else
color_name = next ;
}
if ( ! color_name . empty ( ) ) {
2012-02-13 09:52:17 -08:00
rgb_color_t color = rgb_color_t ( color_name ) ;
if ( ! color . is_none ( ) ) {
candidates . push_back ( color ) ;
2012-02-12 18:05:59 -08:00
}
2012-02-11 17:07:56 -08:00
}
}
2012-02-13 09:52:17 -08:00
// Pick the best candidate
rgb_color_t first_rgb = rgb_color_t : : none ( ) , first_named = rgb_color_t : : none ( ) ;
for ( size_t i = 0 ; i < candidates . size ( ) ; i + + ) {
const rgb_color_t & color = candidates . at ( i ) ;
if ( color . is_rgb ( ) & & first_rgb . is_none ( ) )
first_rgb = color ;
if ( color . is_named ( ) & & first_named . is_none ( ) )
first_named = color ;
}
// If we have both RGB and named colors, then prefer rgb if term256 is supported
rgb_color_t result ;
if ( ( ! first_rgb . is_none ( ) & & allow_term256 ( ) ) | | first_named . is_none ( ) ) {
result = first_rgb ;
} else {
result = first_named ;
}
if ( result . is_none ( ) )
result = rgb_color_t : : normal ( ) ;
result . set_bold ( is_bold ) ;
result . set_underline ( is_underline ) ;
2012-02-12 18:05:59 -08:00
#if 0
wcstring desc = result . description ( ) ;
printf ( " Parsed %ls from %ls (%s) \n " , desc . c_str ( ) , val . c_str ( ) , is_background ? " background " : " foreground " ) ;
# endif
2012-02-13 09:52:17 -08:00
2012-02-11 17:07:56 -08:00
return result ;
2005-09-20 23:26:39 +10:00
}
2007-09-10 00:04:36 +10:00
2012-01-12 23:11:07 +05:30
void output_set_term ( const wchar_t * term )
2007-09-10 00:04:36 +10:00
{
2012-02-09 16:06:24 -08:00
current_term = term ;
2007-09-10 00:04:36 +10:00
}
2012-02-09 16:06:24 -08:00
const wchar_t * output_get_term ( )
2007-09-10 00:04:36 +10:00
{
2012-02-09 16:06:24 -08:00
return current_term . empty ( ) ? L " <unknown> " : current_term . c_str ( ) ;
2007-09-10 00:04:36 +10:00
}