/** Remove backslashes from all newlines. This makes a string from the history file better formated for on screen display. The memory for the return value will be reused by subsequent calls to this function. */ static wchar_t *history_unescape_newlines( wchar_t *in ) { static string_buffer_t *out = 0; if( !out ) { out = sb_halloc( global_context ); if( !out ) { DIE_MEM(); } } else { sb_clear( out ); } for( ; *in; in++ ) { if( *in == L'\\' ) { if( *(in+1)!= L'\n') { sb_append_char( out, *in ); } } else { sb_append_char( out, *in ); } } return (wchar_t *)out->buff; }
const wchar_t *input_terminfo_get_name( const wchar_t *seq ) { int i; static string_buffer_t *buff = 0; CHECK( seq, 0 ); input_init(); if( !buff ) { buff = sb_halloc( global_context ); } for( i=0; i<al_get_count( terminfo_mappings ); i++ ) { terminfo_mapping_t *m = (terminfo_mapping_t *)al_get( terminfo_mappings, i ); if( !m->seq ) { continue; } sb_clear( buff ); sb_printf( buff, L"%s", m->seq ); if( !wcscmp( seq, (wchar_t *)buff->buff ) ) { return m->name; } } return 0; }
const wchar_t *wsetlocale(int category, const wchar_t *locale) { char *lang = locale?wcs2str( locale ):0; char * res = setlocale(category,lang); free( lang ); /* Use ellipsis if on known unicode system, otherwise use $ */ char *ctype = setlocale( LC_CTYPE, (void *)0 ); ellipsis_char = (strstr( ctype, ".UTF")||strstr( ctype, ".utf") )?L'\u2026':L'$'; if( !res ) return 0; if( !setlocale_buff ) { setlocale_buff = sb_halloc( global_context); } sb_clear( setlocale_buff ); sb_printf( setlocale_buff, L"%s", res ); return (wchar_t *)setlocale_buff->buff; }
/** Add backslashes to all newlines, so that the returning string is suitable for writing to the history file. The memory for the return value will be reused by subsequent calls to this function. */ static wchar_t *history_escape_newlines( wchar_t *in ) { static string_buffer_t *out = 0; if( !out ) { out = sb_halloc( global_context ); if( !out ) { DIE_MEM(); } } else { sb_clear( out ); } for( ; *in; in++ ) { if( *in == L'\\' ) { sb_append_char( out, *in ); if( *(in+1) ) { in++; sb_append_char( out, *in ); } else { /* This is a weird special case. When we are trying to save a string that ends with a backslash, we need to handle it specially, otherwise this command would be combined with the one following it. We hack around this by adding an additional newline. */ sb_append_char( out, L'\n' ); } } else if( *in == L'\n' ) { sb_append_char( out, L'\\' ); sb_append_char( out, *in ); } else { sb_append_char( out, *in ); } } return (wchar_t *)out->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; }
wchar_t *wdirname( 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 ); wcscpy( path, (wchar_t *)sb->buff ); return path; }
const wchar_t *input_terminfo_get_sequence( const wchar_t *name ) { const char *res = 0; int i; static string_buffer_t *buff = 0; int err = ENOENT; CHECK( name, 0 ); input_init(); for( i=0; i<al_get_count( terminfo_mappings ); i++ ) { terminfo_mapping_t *m = (terminfo_mapping_t *)al_get( terminfo_mappings, i ); if( !wcscmp( name, m->name ) ) { res = m->seq; err = EILSEQ; break; } } if( !res ) { errno = err; return 0; } if( !buff ) { buff = sb_halloc( global_context ); } sb_clear( buff ); sb_printf( buff, L"%s", res ); return (wchar_t *)buff->buff; }
wchar_t *wgetenv( const wchar_t *name ) { char *name_narrow =wutil_wcs2str(name); char *res_narrow = getenv( name_narrow ); static string_buffer_t *out = 0; if( !res_narrow ) return 0; if( !out ) { out = sb_halloc( global_context ); } else { sb_clear( out ); } sb_printf( out, L"%s", res_narrow ); return (wchar_t *)out->buff; }
/** Returns an item_t for the specified adress. The adress must come from the item list of the specified mode. Later calls to this function may erase the output of a previous call to this function. */ static item_t *item_get( history_mode_t *m, void *d ) { char *begin = (char *)d; if( item_is_new( m, d ) ) { return (item_t *)d; } else { char *end = m->mmap_start + m->mmap_length; char *pos=begin; int was_backslash = 0; static string_buffer_t *out = 0; static item_t narrow_item; int first_char = 1; int timestamp_mode = 0; narrow_item.timestamp = 0; if( !out ) { out = sb_halloc( global_context ); if( !out ) { DIE_MEM(); } } else { sb_clear( out ); } while( 1 ) { wchar_t c; mbstate_t state; size_t res; memset( &state, 0, sizeof(state) ); res = mbrtowc( &c, pos, end-pos, &state ); if( res == (size_t)-1 ) { pos++; continue; } else if( res == (size_t)-2 ) { break; } else if( res == (size_t)0 ) { pos++; continue; } pos += res; if( c == L'\n' ) { if( timestamp_mode ) { wchar_t *time_string = (wchar_t *)out->buff; while( *time_string && !iswdigit(*time_string)) time_string++; errno=0; if( *time_string ) { time_t tm; wchar_t *end; errno = 0; tm = (time_t)wcstol( time_string, &end, 10 ); if( tm && !errno && !*end ) { narrow_item.timestamp = tm; } } sb_clear( out ); timestamp_mode = 0; continue; } if( !was_backslash ) break; } if( first_char ) { if( c == L'#' ) timestamp_mode = 1; } first_char = 0; sb_append_char( out, c ); was_backslash = ( (c == L'\\') && !was_backslash); } narrow_item.data = history_unescape_newlines((wchar_t *)out->buff); return &narrow_item; } }