From 8fdc46a105cb6f787569dadb9932d8a49d75b891 Mon Sep 17 00:00:00 2001
From: axel <axel@liljencrantz.se>
Date: Wed, 14 Jun 2006 23:22:40 +1000
Subject: [PATCH] Add support for hishlighting potentially valid paths -
 default behaviour is to underline them

darcs-hash:20060614132240-ac50b-448a4f8c43007262876d1ab6b52480e46b0e2981.gz
---
 builtin_commandline.c |   4 +-
 common.c              |   4 +-
 common.h              |   2 +-
 complete.c            |   2 +-
 expand.c              |   4 +-
 highlight.c           | 199 +++++++++++++++++++++++++++++++++++++-----
 output.c              |  40 ++++++++-
 output.h              |  30 +++----
 parse_util.c          |  82 ++++++++---------
 parse_util.h          |  24 ++---
 parser.c              |   2 +-
 reader.c              |  12 +--
 wutil.c               |  48 +++++++++-
 wutil.h               |  11 +++
 14 files changed, 352 insertions(+), 112 deletions(-)

diff --git a/builtin_commandline.c b/builtin_commandline.c
index 19e604715..951eb788d 100644
--- a/builtin_commandline.c
+++ b/builtin_commandline.c
@@ -461,13 +461,13 @@ static int builtin_commandline( wchar_t **argv )
 		buffer_part = STRING_MODE;
 	}
 		
-	const wchar_t *begin, *end;
+	wchar_t *begin, *end;
 	
 	switch( buffer_part )
 	{
 		case STRING_MODE:
 		{			
-			begin = get_buffer();
+			begin = (wchar_t *)get_buffer();
 			end = begin+wcslen(begin);
 			break;			
 		}
diff --git a/common.c b/common.c
index 9475fd64c..f2c8f18e2 100644
--- a/common.c
+++ b/common.c
@@ -438,7 +438,7 @@ int my_wcswidth( const wchar_t *c )
 	return res;
 }
 
-const wchar_t *quote_end( const wchar_t *pos )
+wchar_t *quote_end( const wchar_t *pos )
 {
 	wchar_t c = *pos;
 	
@@ -457,7 +457,7 @@ const wchar_t *quote_end( const wchar_t *pos )
 		{
 			if( *pos == c )
 			{
-				return pos;
+				return (wchar_t *)pos;
 			}
 		}
 	}
diff --git a/common.h b/common.h
index 0466c562b..8c5338c87 100644
--- a/common.h
+++ b/common.h
@@ -172,7 +172,7 @@ int my_wcswidth( const wchar_t *c );
 
    \param in the position of the opening quote
 */
-const wchar_t *quote_end( const wchar_t *in );
+wchar_t *quote_end( const wchar_t *in );
 
 /**
    A call to this function will reset the error counter. Some
diff --git a/complete.c b/complete.c
index 661ba5eb6..c170ecfff 100644
--- a/complete.c
+++ b/complete.c
@@ -1955,7 +1955,7 @@ static int try_complete_user( const wchar_t *cmd,
 void complete( const wchar_t *cmd,
 			   array_list_t *comp )
 {
-	const wchar_t *begin, *end, *prev_begin, *prev_end;
+	wchar_t *begin, *end, *prev_begin, *prev_end;
 	wchar_t *buff;
 	tokenizer tok;
 	wchar_t *current_token=0, *current_command=0, *prev_token=0;
diff --git a/expand.c b/expand.c
index 4f99428d0..67a6b8138 100644
--- a/expand.c
+++ b/expand.c
@@ -1108,7 +1108,7 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
 */
 static int expand_subshell( wchar_t *in, array_list_t *out )
 {
-	const wchar_t *paran_begin=0, *paran_end=0;
+	wchar_t *paran_begin=0, *paran_end=0;
 	int len1, len2;
 	wchar_t prev=0;
 	wchar_t *subcmd;
@@ -1371,7 +1371,7 @@ int expand_string( void *context,
 
 	if( EXPAND_SKIP_SUBSHELL & flags )
 	{
-		const wchar_t *begin, *end;
+		wchar_t *begin, *end;
 		
 		if( parse_util_locate_cmdsubst( str,
 										&begin,
diff --git a/highlight.c b/highlight.c
index 84115ea85..53a130611 100644
--- a/highlight.c
+++ b/highlight.c
@@ -33,6 +33,8 @@
 #include "halloc.h"
 #include "halloc_util.h"
 
+#define VAR_COUNT ( sizeof(highlight_var)/sizeof(wchar_t *) )
+
 static void highlight_universal_internal( wchar_t * buff, 
 										  int *color, 
 										  int pos, 
@@ -45,39 +47,166 @@ static void highlight_universal_internal( wchar_t * buff,
 static wchar_t *highlight_var[] = 
 {
 	L"fish_color_normal",
-	L"fish_color_command",
-	L"fish_color_redirection",
-	L"fish_color_end",
 	L"fish_color_error",
+	L"fish_color_command",
+	L"fish_color_end",
 	L"fish_color_param",
 	L"fish_color_comment",
 	L"fish_color_match",
 	L"fish_color_search_match",
 	L"fish_color_operator",
 	L"fish_color_escape",
-	L"fish_color_quote"
+	L"fish_color_quote",
+	L"fish_color_redirection",
+	L"fish_color_valid_path"
 }
 	;
 
-#define VAR_COUNT ( sizeof(highlight_var)/sizeof(wchar_t *) )
+static int is_potential_path( const wchar_t *path )
+{
+	wchar_t *tilde, *unescaped;
+	wchar_t *in, *out;
+	int has_magic = 0;
+	int res = 0;
+
+	void *context = halloc( 0, 0 );
+
+	tilde = expand_tilde( wcsdup(path) );
+	
+	unescaped = unescape( tilde, 1 );
+//	debug( 1, L"%ls -> %ls ->%ls", path, tilde, unescaped );
+	
+	halloc_register( context, unescaped );
+	halloc_register( context, tilde );
+			
+	for( in = out = unescaped; *in; in++ )
+	{
+		switch( *in )
+		{
+			case PROCESS_EXPAND:
+			case VARIABLE_EXPAND:
+			case VARIABLE_EXPAND_SINGLE:
+			case BRACKET_BEGIN:
+			case BRACKET_END:
+			case BRACKET_SEP:
+			{
+				has_magic = 1;
+				break;		
+			}
+
+			case INTERNAL_SEPARATOR:
+			{
+				break;
+			}
+						
+			default:
+			{
+				*(out++) = *in;
+				break;
+			}
+			
+		}
+		
+	}
+	*out = 0;
+	
+	if( !has_magic )
+	{
+		int must_be_dir = 0;
+		DIR *dir;
+		must_be_dir = unescaped[wcslen(unescaped)-1] == L'/';
+		if( must_be_dir )
+		{
+			dir = wopendir( unescaped );
+			res = !!dir;
+			closedir( dir );
+		}
+		else
+		{
+			wchar_t *dir_name, *base;
+			struct wdirent *ent;
+		
+			dir_name = wdirname( halloc_wcsdup(context, unescaped) );
+			base = wbasename( halloc_wcsdup(context, unescaped) );			
+			
+			if( (wcscmp( dir_name, L"/" ) == 0 ) &&
+				(wcscmp( base, L"/" ) == 0 ) )
+			{
+				res = 1;
+			}
+			else if( (dir = wopendir( dir_name )) )
+			{
+				
+				while( (ent = wreaddir( dir )) )
+				{
+					if( wcsncmp( ent->d_name, base, wcslen(base) ) == 0 )
+					{
+						res = 1;
+						break;
+					}
+				}
+						
+				closedir( dir );
+			}
+		}
+		
+	}
+	
+	halloc_free( context );
+		
+	return res;
+	
+}
+
+
 
 int highlight_get_color( int highlight )
 {
+	int i;
+	int idx=0;
+	int result = 0;
+	
 	if( highlight < 0 )
 		return FISH_COLOR_NORMAL;
-	if( highlight >= VAR_COUNT )
+	if( highlight >= (1<<VAR_COUNT) )
 		return FISH_COLOR_NORMAL;
-	
-	wchar_t *val = env_get( highlight_var[highlight]);
-	if( val == 0 )
-		val = env_get( highlight_var[HIGHLIGHT_NORMAL]);
-	
-	if( val == 0 )
+
+	for( i=0; i<(VAR_COUNT-1); i++ )
 	{
-		return FISH_COLOR_NORMAL;
+		if( highlight & (1<<i ))
+		{
+			idx = i;
+			break;
+		}
 	}
+		
+	wchar_t *val = env_get( highlight_var[idx]);
+
+//	debug( 1, L"%d -> %d -> %ls", highlight, idx, val );	
+
+	if( val == 0 )
+		val = env_get( highlight_var[0]);
+	
+	if( val )
+		result = output_color_code( val );
+	
+	if( highlight & HIGHLIGHT_VALID_PATH )
+	{
+		wchar_t *val2 = env_get( L"fish_color_valid_path" );
+		int result2 = output_color_code( val2 );
+		if( result == FISH_COLOR_NORMAL )
+			result = result2;
+		else 
+		{
+			if( result2 & FISH_COLOR_BOLD )
+				result |= FISH_COLOR_BOLD;
+			if( result2 & FISH_COLOR_UNDERLINE )
+				result |= FISH_COLOR_UNDERLINE;
+		}
+		
+	}
+	return result;
 	
-	return output_color_code( val );
 }
 
 /**
@@ -679,8 +808,8 @@ void highlight_shell( wchar_t * buff,
 		wchar_t *begin, *end;
 	
 		if( parse_util_locate_cmdsubst( subpos, 
-										(const wchar_t **)&begin, 
-										(const wchar_t **)&end,
+										&begin, 
+										&end,
 										1) <= 0)
 		{
 			break;
@@ -710,6 +839,32 @@ void highlight_shell( wchar_t * buff,
 			color[i] = last_val;
 	}
 
+	/*
+	  Color potentially valid paths in a special path color if they
+	  are the current token.
+	*/
+
+	if( pos >= 0 && pos <= len )
+	{
+		
+		wchar_t *tok_begin, *tok_end;
+		wchar_t *token;
+
+		parse_util_token_extent( buff, pos, &tok_begin, &tok_end, 0, 0 );
+		if( tok_begin )
+		{
+			token = halloc_wcsndup( context, tok_begin, tok_end-tok_begin );
+			
+			if( is_potential_path( token ) )
+			{
+				for( i=tok_begin-buff; i < (tok_end-buff); i++ )
+				{
+					color[i] |= HIGHLIGHT_VALID_PATH;
+				}
+			}
+		}
+	}
+	
 
 	highlight_universal_internal( buff, color, pos, error );
 
@@ -782,8 +937,8 @@ static void highlight_universal_internal( wchar_t * buff,
 								pos2 = str-buff;
 								if( pos1==pos || pos2==pos )
 								{
-									color[pos1]|=HIGHLIGHT_MATCH<<8;
-									color[pos2]|=HIGHLIGHT_MATCH<<8;
+									color[pos1]|=HIGHLIGHT_MATCH<<16;
+									color[pos2]|=HIGHLIGHT_MATCH<<16;
 									match_found = 1;
 									
 								}
@@ -808,7 +963,7 @@ static void highlight_universal_internal( wchar_t * buff,
 			al_destroy( &l );
 		
 			if( !match_found )
-				color[pos] = HIGHLIGHT_ERROR<<8;
+				color[pos] = HIGHLIGHT_ERROR<<16;
 		}
 
 		/*
@@ -832,8 +987,8 @@ static void highlight_universal_internal( wchar_t * buff,
 				if( level == 0 )
 				{
 					int pos2 = str-buff;
-					color[pos]|=HIGHLIGHT_MATCH<<8;
-					color[pos2]|=HIGHLIGHT_MATCH<<8;
+					color[pos]|=HIGHLIGHT_MATCH<<16;
+					color[pos2]|=HIGHLIGHT_MATCH<<16;
 					match_found=1;
 					break;
 				}
@@ -841,7 +996,7 @@ static void highlight_universal_internal( wchar_t * buff,
 			}
 			
 			if( !match_found )
-				color[pos] = HIGHLIGHT_ERROR<<8;
+				color[pos] = HIGHLIGHT_ERROR<<16;
 		}
 	}
 }
diff --git a/output.c b/output.c
index 548289345..4a801eb42 100644
--- a/output.c
+++ b/output.c
@@ -129,18 +129,23 @@ 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;
 
 	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;
+
 //	debug( 1, L"WOO %d %d %d", is_bold, c&FISH_COLOR_BOLD,c2&FISH_COLOR_BOLD);
 
-	c = c&(~FISH_COLOR_BOLD);
-	c2 = c2&(~FISH_COLOR_BOLD);
+	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 ) )
 	{
@@ -157,6 +162,7 @@ void set_color( int c, int c2 )
 	{
 		c = c2 = FISH_COLOR_NORMAL;
 		was_bold=0;
+		was_underline=0;
 		if( fg )
 		{
 			/*
@@ -179,6 +185,7 @@ void set_color( int c, int c2 )
 		last_color = FISH_COLOR_NORMAL;
 		last_color2 = FISH_COLOR_NORMAL;
 		was_bold=0;
+		was_underline=0;
 	}
 	
 	if( last_color2 != FISH_COLOR_NORMAL &&
@@ -219,6 +226,8 @@ void set_color( int c, int c2 )
 			  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.
@@ -242,6 +251,8 @@ void set_color( int c, int c2 )
 			writembs( exit_attribute_mode );
 
 			last_color2 = FISH_COLOR_NORMAL;
+			was_bold=0;
+			was_underline=0;
 		}
 		else if( ( c >= 0 ) && ( c < FISH_COLOR_NORMAL ) )
 		{
@@ -269,6 +280,8 @@ void set_color( int c, int c2 )
 				writembs( tparm( fg, last_color ) );
 			}
 
+			was_bold=0;
+			was_underline=0;
 			last_color2 = c2;
 		}
 		else if ( ( c2 >= 0 ) && ( c2 < FISH_COLOR_NORMAL ) )
@@ -282,7 +295,7 @@ void set_color( int c, int c2 )
 	}
 
 	/*
-	  Lastly, we set bold mode correctly
+	  Lastly, we set bold mode and underline mode correctly
 	*/
 	if( (enter_bold_mode != 0) && (strlen(enter_bold_mode) > 0) && !bg_set )
 	{
@@ -292,6 +305,18 @@ void set_color( int c, int c2 )
 		}
 		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;
+	
 }
 
 
@@ -336,6 +361,9 @@ int writeb( tputs_arg_t b )
 
 int writembs( char *str )
 {
+	if( !str )
+		return 1;
+	
 	return tputs(str,1,&writeb)==ERR?1:0;
 }
 
@@ -519,6 +547,7 @@ 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;
@@ -533,6 +562,9 @@ int output_color_code( const wchar_t *val )
 		is_bold |= (wcsncmp( next, L"--bold", wcslen(next) ) == 0 ) && wcslen(next)>=3;
 		is_bold |= wcscmp( next, L"-b" ) == 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 )
@@ -547,6 +579,6 @@ int output_color_code( const wchar_t *val )
 	al_foreach( &el, &free );
 	al_destroy( &el );
 
-	return color | (is_bold?FISH_COLOR_BOLD:0);
+	return color | (is_bold?FISH_COLOR_BOLD:0) | (is_underline?FISH_COLOR_UNDERLINE:0);
 	
 }
diff --git a/output.h b/output.h
index 434cbc61c..8e90eb458 100644
--- a/output.h
+++ b/output.h
@@ -10,22 +10,19 @@
 
 #include <wchar.h>
 
-enum
-{
-	HIGHLIGHT_NORMAL,
-	HIGHLIGHT_COMMAND,
-	HIGHLIGHT_REDIRECTION, 
-	HIGHLIGHT_END, 
-	HIGHLIGHT_ERROR,
-	HIGHLIGHT_PARAM,
-	HIGHLIGHT_COMMENT,
-	HIGHLIGHT_MATCH,
-	HIGHLIGHT_SEARCH_MATCH,
-	HIGHLIGHT_OPERATOR,
-	HIGHLIGHT_ESCAPE,
-	HIGHLIGHT_QUOTE,
-}
-	;
+#define HIGHLIGHT_NORMAL 0x1
+#define HIGHLIGHT_ERROR 0x2
+#define HIGHLIGHT_COMMAND 0x4
+#define HIGHLIGHT_END 0x8
+#define HIGHLIGHT_PARAM 0x10
+#define HIGHLIGHT_COMMENT 0x20
+#define HIGHLIGHT_MATCH 0x40
+#define HIGHLIGHT_SEARCH_MATCH 0x80
+#define HIGHLIGHT_OPERATOR 0x100
+#define HIGHLIGHT_ESCAPE 0x200
+#define HIGHLIGHT_QUOTE 0x400
+#define HIGHLIGHT_REDIRECTION 0x800 
+#define HIGHLIGHT_VALID_PATH 0x1000
 
 /**
    Constants for various colors as used by the set_color function. 
@@ -48,6 +45,7 @@ enum
 ;
 
 #define FISH_COLOR_BOLD 0x80
+#define FISH_COLOR_UNDERLINE 0x100
 
 /**
    Sets the fg and bg color. May be called as often as you like, since
diff --git a/parse_util.c b/parse_util.c
index 7f9f7e863..c9ac4e5a5 100644
--- a/parse_util.c
+++ b/parse_util.c
@@ -42,14 +42,14 @@ int parse_util_lineno( const wchar_t *str, int len )
 	/**
 	   First cached state
 	*/
-	static const wchar_t *prev_str = 0;
+	static wchar_t *prev_str = 0;
 	static int i=0;
 	static int res = 1;
 
 	/**
 	   Second cached state
 	*/
-	static const wchar_t *prev_str2 = 0;
+	static wchar_t *prev_str2 = 0;
 	static int i2 = 0;
 	static int res2 = 1;
 	
@@ -57,7 +57,7 @@ int parse_util_lineno( const wchar_t *str, int len )
 	{
 		if( prev_str2 == str && i2 <= len )
 		{
-			const wchar_t *tmp_str = prev_str;
+			wchar_t *tmp_str = prev_str;
 			int tmp_i = i;
 			int tmp_res = res;
 			prev_str = prev_str2;
@@ -74,7 +74,7 @@ int parse_util_lineno( const wchar_t *str, int len )
 			i2 = i;
 			res2=res;
 				
-			prev_str = str;
+			prev_str = (wchar_t *)str;
 			i=0;
 			res=1;
 		}
@@ -89,27 +89,27 @@ int parse_util_lineno( const wchar_t *str, int len )
 }
 
 int parse_util_locate_cmdsubst( const wchar_t *in, 
-								const wchar_t **begin, 
-								const wchar_t **end,
+								wchar_t **begin, 
+								wchar_t **end,
 								int allow_incomplete )
 {
-	const wchar_t *pos;
+	wchar_t *pos;
 	wchar_t prev=0;
 	int syntax_error=0;
 	int paran_count=0;	
 
-	const wchar_t *paran_begin=0, *paran_end=0;
+	wchar_t *paran_begin=0, *paran_end=0;
 
-	for( pos=in; *pos; pos++ )
+	for( pos=(wchar_t *)in; *pos; pos++ )
 	{
 		if( prev != '\\' )
 		{
 			if( wcschr( L"\'\"", *pos ) )
 			{
-				const wchar_t *end = quote_end( pos );
-				if( end && *end)
+				wchar_t *q_end = quote_end( pos );
+				if( q_end && *q_end)
 				{
-					pos=end;
+					pos=q_end;
 				}
 				else
 					break;
@@ -161,7 +161,7 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
 	if( begin )
 		*begin = paran_begin;
 	if( end )
-		*end = paran_count?in+wcslen(in):paran_end;
+		*end = paran_count?(wchar_t *)in+wcslen(in):paran_end;
 	
 	return 1;
 }
@@ -169,11 +169,11 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
 
 void parse_util_cmdsubst_extent( const wchar_t *buff,
 								 int cursor_pos,
-								 const wchar_t **a, 
-								 const wchar_t **b )
+								 wchar_t **a, 
+								 wchar_t **b )
 {
-	const wchar_t *begin, *end;
-	const wchar_t *pos;
+	wchar_t *begin, *end;
+	wchar_t *pos;
 	
 	if( a )
 		*a=0;
@@ -183,7 +183,7 @@ void parse_util_cmdsubst_extent( const wchar_t *buff,
 	if( !buff )
 		return;
 
-	pos = buff;
+	pos = (wchar_t *)buff;
 	
 	while( 1 )
 	{
@@ -194,14 +194,14 @@ void parse_util_cmdsubst_extent( const wchar_t *buff,
 										&end,
 										1 ) <= 0)
 		{
-			begin=buff;
-			end = buff + wcslen(buff);
+			begin=(wchar_t *)buff;
+			end = (wchar_t *)buff + wcslen(buff);
 			break;
 		}
 
 		if( !end )
 		{
-			end = buff + wcslen(buff);
+			end = (wchar_t *)buff + wcslen(buff);
 		}
 
 		bc = begin-buff;
@@ -225,11 +225,11 @@ void parse_util_cmdsubst_extent( const wchar_t *buff,
 */
 static void job_or_process_extent( const wchar_t *buff,
 								   int cursor_pos,
-								   const wchar_t **a, 
-								   const wchar_t **b, 
+								   wchar_t **a, 
+								   wchar_t **b, 
 								   int process )
 {
-	const wchar_t *begin, *end;
+	wchar_t *begin, *end;
 	int pos;
 	wchar_t *buffcpy;
 	int finished=0;
@@ -284,12 +284,12 @@ static void job_or_process_extent( const wchar_t *buff,
 				{
 					finished=1;					
 					if( b )
-						*b = buff + tok_begin;
+						*b = (wchar_t *)buff + tok_begin;
 				}
 				else
 				{
 					if( a )
-						*a = buff + tok_begin+1;
+						*a = (wchar_t *)buff + tok_begin+1;
 				}
 				break;
 				
@@ -305,16 +305,16 @@ static void job_or_process_extent( const wchar_t *buff,
 
 void parse_util_process_extent( const wchar_t *buff,
 								int pos,
-								const wchar_t **a, 
-								const wchar_t **b )
+								wchar_t **a, 
+								wchar_t **b )
 {
 	job_or_process_extent( buff, pos, a, b, 1 );	
 }
 
 void parse_util_job_extent( const wchar_t *buff,
 							int pos,
-							const wchar_t **a, 
-							const wchar_t **b )
+							wchar_t **a, 
+							wchar_t **b )
 {
 	job_or_process_extent( buff,pos,a, b, 0 );	
 }
@@ -322,18 +322,20 @@ void parse_util_job_extent( const wchar_t *buff,
 
 void parse_util_token_extent( const wchar_t *buff,
 							  int cursor_pos,
-							  const wchar_t **tok_begin,
-							  const wchar_t **tok_end,
-							  const wchar_t **prev_begin, 
-							  const wchar_t **prev_end )
+							  wchar_t **tok_begin,
+							  wchar_t **tok_end,
+							  wchar_t **prev_begin, 
+							  wchar_t **prev_end )
 {
-	const wchar_t *begin, *end;
+	wchar_t *begin, *end;
 	int pos;
 	wchar_t *buffcpy;
 
 	tokenizer tok;
 
-	const wchar_t *a, *b, *pa, *pb;
+	wchar_t *a, *b, *pa, *pb;
+	
+	assert( cursor_pos >= 0 );
 	
 
 	a = b = pa = pb = 0;
@@ -345,9 +347,9 @@ void parse_util_token_extent( const wchar_t *buff,
 
 	pos = cursor_pos - (begin - buff);
 
-	a = buff + pos;
+	a = (wchar_t *)buff + pos;
 	b = a;
-	pa = buff + pos;
+	pa = (wchar_t *)buff + pos;
 	pb = pa;
 
 	assert( begin >= buff );
@@ -382,7 +384,7 @@ void parse_util_token_extent( const wchar_t *buff,
 		*/
 		if( tok_begin > pos )
 		{
-			a = b = buff + pos;
+			a = b = (wchar_t *)buff + pos;
 			break;
 		}
 
@@ -495,7 +497,7 @@ int parse_util_load( const wchar_t *cmd,
 	int reloaded = 0;
 	hash_table_t *loaded;
 
-	const wchar_t *path_var = env_get( path_var_name );
+	wchar_t *path_var = env_get( path_var_name );
 
 	/*
 	  Do we know where to look
diff --git a/parse_util.h b/parse_util.h
index 19591f838..d484dc5d7 100644
--- a/parse_util.h
+++ b/parse_util.h
@@ -20,8 +20,8 @@
 */
 
 int parse_util_locate_cmdsubst( const wchar_t *in, 
-								const wchar_t **begin, 
-								const wchar_t **end,
+								wchar_t **begin, 
+								wchar_t **end,
 								int allow_incomplete );
 
 /**
@@ -34,8 +34,8 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
 */
 void parse_util_cmdsubst_extent( const wchar_t *buff,
 								 int cursor_pos,
-								 const wchar_t **a, 
-								 const wchar_t **b );
+								 wchar_t **a, 
+								 wchar_t **b );
 
 /**
    Find the beginning and end of the process definition under the cursor
@@ -47,8 +47,8 @@ void parse_util_cmdsubst_extent( const wchar_t *buff,
 */
 void parse_util_process_extent( const wchar_t *buff,
 								int cursor_pos,
-								const wchar_t **a, 
-								const wchar_t **b );
+								wchar_t **a, 
+								wchar_t **b );
 
 
 /**
@@ -61,8 +61,8 @@ void parse_util_process_extent( const wchar_t *buff,
 */
 void parse_util_job_extent( const wchar_t *buff,
 							int cursor_pos,
-							const wchar_t **a, 
-							const wchar_t **b );
+							wchar_t **a, 
+							wchar_t **b );
 
 /**
    Find the beginning and end of the token under the cursor
@@ -74,10 +74,10 @@ void parse_util_job_extent( const wchar_t *buff,
 */
 void parse_util_token_extent( const wchar_t *buff,
 							  int cursor_pos,
-							  const wchar_t **tok_begin,
-							  const wchar_t **tok_end,
-							  const wchar_t **prev_begin, 
-							  const wchar_t **prev_end );
+							  wchar_t **tok_begin,
+							  wchar_t **tok_end,
+							  wchar_t **prev_begin, 
+							  wchar_t **prev_end );
 
 
 /**
diff --git a/parser.c b/parser.c
index daedbdad5..4d6a3e147 100644
--- a/parser.c
+++ b/parser.c
@@ -2656,7 +2656,7 @@ static int parser_test_argument( const wchar_t *arg, string_buffer_t *out, const
 	wchar_t *pos;
 	int err=0;
 	
-	const wchar_t *paran_begin, *paran_end;
+	wchar_t *paran_begin, *paran_end;
 	wchar_t *arg_cpy;
 	int do_loop = 1;
 	
diff --git a/reader.c b/reader.c
index 965f9163f..3f979b080 100644
--- a/reader.c
+++ b/reader.c
@@ -609,8 +609,8 @@ static void remove_duplicates( array_list_t *l )
 */
 static void set_color_translated( int c )
 {
-	set_color( highlight_get_color( c & 0xff ),
-			   highlight_get_color( (c>>8)&0xff ) );
+	set_color( highlight_get_color( c & 0xffff ),
+			   highlight_get_color( (c>>16)&0xffff ) );
 }
 
 int reader_interupted()
@@ -1697,7 +1697,7 @@ void reader_sanity_check()
 void reader_replace_current_token( wchar_t *new_token )
 {
 
-	const wchar_t *begin, *end;
+	wchar_t *begin, *end;
 	string_buffer_t sb;
 	int new_pos;
 
@@ -1764,7 +1764,7 @@ static int contains( const wchar_t *needle,
 */
 static void reset_token_history()
 {
-	const wchar_t *begin, *end;
+	wchar_t *begin, *end;
 
 	parse_util_token_extent( data->buff, data->buff_pos, &begin, &end, 0, 0 );
 	if( begin )
@@ -2494,8 +2494,8 @@ wchar_t *reader_readline()
 
  				if( comp_empty )
 				{
-					const wchar_t *begin, *end;
-					const wchar_t *token_begin, *token_end;
+					wchar_t *begin, *end;
+					wchar_t *token_begin, *token_end;
 					wchar_t *buffcpy;
 					int len;
 					int cursor_steps;
diff --git a/wutil.c b/wutil.c
index b18d3ccdf..bd29cdd7e 100644
--- a/wutil.c
+++ b/wutil.c
@@ -18,6 +18,7 @@
 #include <dirent.h>
 #include <stdarg.h>
 #include <limits.h>
+#include <libgen.h>
 
 
 #include "fallback.h"
@@ -25,6 +26,8 @@
 
 #include "common.h"
 #include "wutil.h"
+#include "halloc.h"
+#include "halloc_util.h"
 
 #define TMP_LEN_MIN 256
 
@@ -41,12 +44,12 @@
    the \c wutil_wcs2str() function.
 */
 static char *tmp=0;
-static wchar_t *tmp2=0;
+static wchar_t *tmp2;
 /**
    Length of the \c tmp buffer.
 */
 static size_t tmp_len=0;
-static size_t tmp2_len=0;
+static size_t tmp2_len;
 
 /**
    Counts the number of calls to the wutil wrapper functions
@@ -63,6 +66,7 @@ void wutil_destroy()
 {
 	free( tmp );
 	free( tmp2 );
+
 	tmp=0;
 	tmp_len=0;
 	debug( 3, L"wutil functions called %d times", wutil_calls );
@@ -117,7 +121,7 @@ static wchar_t *wutil_str2wcs( const char *in )
 		}
 		tmp2_len = new_sz;
 	}
-
+	
 	return str2wcs_internal( in, tmp2 );
 }
 
@@ -343,3 +347,41 @@ wchar_t *wrealpath(const wchar_t *pathname, wchar_t *resolved_path)
 }
 
 #endif
+
+
+wchar_t *wdirname( const wchar_t *path )
+{
+	static string_buffer_t *sb = 0;
+	if( sb )
+		sb_clear(sb);
+	else 
+		sb = sb_halloc( global_context );
+	
+	char *tmp =wutil_wcs2str(path);
+	char *narrow_res = dirname( tmp );
+	if( !narrow_res )
+		return 0;
+	
+	sb_printf( sb, L"%s", narrow_res );
+	return (wchar_t *)sb->buff;
+}
+
+wchar_t *wbasename( const wchar_t *path )
+{
+	static string_buffer_t *sb = 0;
+	if( sb )
+		sb_clear(sb);
+	else 
+		sb = sb_halloc( global_context );
+	
+	char *tmp =wutil_wcs2str(path);
+	char *narrow_res = basename( tmp );
+	if( !narrow_res )
+		return 0;
+	
+	sb_printf( sb, L"%s", narrow_res );
+	return (wchar_t *)sb->buff;
+}
+
+
+
diff --git a/wutil.h b/wutil.h
index 6009af653..31651f33a 100644
--- a/wutil.h
+++ b/wutil.h
@@ -99,4 +99,15 @@ wchar_t *wrealpath(const wchar_t *pathname, wchar_t *resolved_path);
 
 struct wdirent *wreaddir(DIR *dir );
 
+/**
+   Wide character version of dirname()
+*/
+wchar_t *wdirname( const wchar_t *path );
+
+/**
+   Wide character version of basename()
+*/
+wchar_t *wbasename( const wchar_t *path );
+
+
 #endif