Ejemplo n.º 1
0
/* Given a map from key to value, add values to out of the form key=value */
static void export_func(const std::map<wcstring, wcstring> &envs, std::vector<std::string> &out)
{
    out.reserve(out.size() + envs.size());
    std::map<wcstring, wcstring>::const_iterator iter;
    for (iter = envs.begin(); iter != envs.end(); ++iter)
    {
        const wcstring &key = iter->first;
        const std::string &ks = wcs2string(key);
        std::string vs = wcs2string(iter->second);

        /* Arrays in the value are ASCII record separator (0x1e) delimited. But some variables should have colons. Add those. */
        if (variable_is_colon_delimited_array(key))
        {
            /* Replace ARRAY_SEP with colon */
            std::replace(vs.begin(), vs.end(), (char)ARRAY_SEP, ':');
        }

        /* Put a string on the vector */
        out.push_back(std::string());
        std::string &str = out.back();
        str.reserve(ks.size() + 1 + vs.size());

        /* Append our environment variable data to it */
        str.append(ks);
        str.append("=");
        str.append(vs);
    }
}
Ejemplo n.º 2
0
static void export_func(const std::map<wcstring, wcstring> &envs, std::vector<std::string> &out)
{
    std::map<wcstring, wcstring>::const_iterator iter;
    for (iter = envs.begin(); iter != envs.end(); ++iter)
    {
        const std::string ks = wcs2string(iter->first);
        std::string vs = wcs2string(iter->second);

        for (size_t i=0; i < vs.size(); i++)
        {
            char &vc = vs.at(i);
            if (vc == ARRAY_SEP)
                vc = ':';
        }

        /* Put a string on the vector */
        out.push_back(std::string());
        std::string &str = out.back();
        str.reserve(ks.size() + 1 + vs.size());

        /* Append our environment variable data to it */
        str.append(ks);
        str.append("=");
        str.append(vs);
    }
}
Ejemplo n.º 3
0
/// Properly sets all locale information.
static void handle_locale(const wchar_t *env_var_name) {
    debug(2, L"handle_locale() called in response to '%ls' changing", env_var_name);
    const char *old_msg_locale = setlocale(LC_MESSAGES, NULL);
    const env_var_t val = env_get_string(env_var_name, ENV_EXPORT);
    const std::string &value = wcs2string(val);
    const std::string &name = wcs2string(env_var_name);
    debug(2, L"locale var %s='%s'", name.c_str(), value.c_str());
    if (val.empty()) {
        unsetenv(name.c_str());
    } else {
        setenv(name.c_str(), value.c_str(), 1);
    }

    char *locale = setlocale(LC_ALL, "");
    fish_setlocale();
    debug(2, L"handle_locale() setlocale(): '%s'", locale);

    const char *new_msg_locale = setlocale(LC_MESSAGES, NULL);
    debug(3, L"old LC_MESSAGES locale: '%s'", old_msg_locale);
    debug(3, L"new LC_MESSAGES locale: '%s'", new_msg_locale);
#ifdef HAVE__NL_MSG_CAT_CNTR
    if (strcmp(old_msg_locale, new_msg_locale)) {
        // Make change known to GNU gettext.
        extern int _nl_msg_cat_cntr;
        _nl_msg_cat_cntr++;
    }
#endif
}
Ejemplo n.º 4
0
/// Properly sets all timezone information.
static void handle_timezone(const wchar_t *env_var_name) {
    debug(2, L"handle_timezone() called in response to '%ls' changing", env_var_name);
    const env_var_t val = env_get_string(env_var_name, ENV_EXPORT);
    const std::string &value = wcs2string(val);
    const std::string &name = wcs2string(env_var_name);
    debug(2, L"timezone var %s='%s'", name.c_str(), value.c_str());
    if (val.empty()) {
        unsetenv(name.c_str());
    } else {
        setenv(name.c_str(), value.c_str(), 1);
    }
    tzset();
}
Ejemplo n.º 5
0
static bool load_or_save_variables(bool save)
{
    const wcstring wdir = fishd_get_config();
    const std::string dir = wcs2string(wdir);
    if (dir.empty())
        return false;

    const std::string machine_id = get_machine_identifier();
    const std::string machine_id_path = get_variables_file_path(dir, machine_id);
    bool success = load_or_save_variables_at_path(save, machine_id_path);
    if (! success && ! save && errno == ENOENT)
    {
        /* We failed to load, because the file was not found. Older fish used the hostname only. Try *moving* the filename based on the hostname into place; if that succeeds try again. Silently "upgraded." */
        std::string hostname_id;
        if (get_hostname_identifier(&hostname_id) && hostname_id != machine_id)
        {
            std::string hostname_path = get_variables_file_path(dir, hostname_id);
            if (0 == rename(hostname_path.c_str(), machine_id_path.c_str()))
            {
                /* We renamed - try again */
                success = load_or_save_variables_at_path(save, machine_id_path);
            }
        }
    }
    return success;
}
Ejemplo n.º 6
0
/// Push all curses/terminfo env vars into the global environment where they can be found by those
/// libraries.
static void handle_curses(const wchar_t *env_var_name) {
    debug(2, L"handle_curses() called in response to '%ls' changing", env_var_name);
    const env_var_t val = env_get_string(env_var_name, ENV_EXPORT);
    const std::string &name = wcs2string(env_var_name);
    const std::string &value = wcs2string(val);
    debug(2, L"curses var %s='%s'", name.c_str(), value.c_str());
    if (val.empty()) {
        unsetenv(name.c_str());
    } else {
        setenv(name.c_str(), value.c_str(), 1);
    }
    // TODO: Modify input_init() to allow calling it when the terminfo env vars are dynamically
    // changed. At the present time it can be called just once. Also, we should really only do this
    // if the TERM var is set.
    // input_init();
}
Ejemplo n.º 7
0
 void make_pipe(const wchar_t *test_path)
 {
     wcstring vars_path = test_path ? wcstring(test_path) : default_vars_path();
     vars_path.append(L".notifier");
     const std::string narrow_path = wcs2string(vars_path);
     
     int fd = wopen_cloexec(vars_path, O_RDWR | O_NONBLOCK, 0600);
     if (fd < 0 && errno == ENOENT)
     {
         /* File doesn't exist, try creating it */
         if (mkfifo(narrow_path.c_str(), 0600) >= 0)
         {
             fd = wopen_cloexec(vars_path, O_RDWR | O_NONBLOCK, 0600);
         }
     }
     if (fd < 0)
     {
         // Maybe open failed, maybe mkfifo failed
         int err = errno;
         report_error(err, L"Unable to make or open a FIFO for universal variables with path '%ls'", vars_path.c_str());
     }
     else
     {
         pipe_fd = fd;
     }
 }
Ejemplo n.º 8
0
wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path) {
    cstring narrow_path = wcs2string(pathname);
    char *narrow_res = realpath(narrow_path.c_str(), NULL);

    if (!narrow_res) return NULL;

    wchar_t *res;
    wcstring wide_res = str2wcstring(narrow_res);
    if (resolved_path) {
        wcslcpy(resolved_path, wide_res.c_str(), PATH_MAX);
        res = resolved_path;
    } else {
        res = wcsdup(wide_res.c_str());
    }

#if __APPLE__ && __DARWIN_C_LEVEL < 200809L
// OS X Snow Leopard is broken with respect to the dynamically allocated buffer returned by
// realpath(). It's not dynamically allocated so attempting to free that buffer triggers a
// malloc/free error. Thus we don't attempt the free in this case.
#else
    free(narrow_res);
#endif

    return res;
}
Ejemplo n.º 9
0
wcstring wgettext2(const wcstring &in)
{
    wgettext_init_if_necessary();
    std::string mbs_in = wcs2string(in);
    char *out = gettext(mbs_in.c_str());
    wcstring result = format_string(L"%s", out);
    return result;
}
Ejemplo n.º 10
0
/* Helper function to convert from a null_terminated_array_t<wchar_t> to a null_terminated_array_t<char_t> */
null_terminated_array_t<char> convert_wide_array_to_narrow(const null_terminated_array_t<wchar_t> &wide_arr) {
    const wchar_t *const *arr = wide_arr.get();
    if (! arr)
        return null_terminated_array_t<char>();
        
    std::vector<std::string> list;
    for (size_t i=0; arr[i]; i++) {
        list.push_back(wcs2string(arr[i]));
    }
    return null_terminated_array_t<char>(list);
}
Ejemplo n.º 11
0
wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path) {
    if (pathname.size() == 0) return NULL;

    cstring real_path("");
    cstring narrow_path = wcs2string(pathname);

    // Strip trailing slashes. This is needed to be bug-for-bug compatible with GNU realpath which
    // treats "/a//" as equivalent to "/a" whether or not /a exists.
    while (narrow_path.size() > 1 && narrow_path.at(narrow_path.size() - 1) == '/') {
        narrow_path.erase(narrow_path.size() - 1, 1);
    }

    char *narrow_res = realpath(narrow_path.c_str(), NULL);
    if (narrow_res) {
        real_path.append(narrow_res);
    } else {
        size_t pathsep_idx = narrow_path.rfind('/');
        if (pathsep_idx == 0) {
            // If the only pathsep is the first character then it's an absolute path with a
            // single path component and thus doesn't need conversion.
            real_path = narrow_path;
        } else {
            if (pathsep_idx == cstring::npos) {
                // No pathsep means a single path component relative to pwd.
                narrow_res = realpath(".", NULL);
                if (!narrow_res) DIE("unexpected realpath(\".\") failure");
                pathsep_idx = 0;
            } else {
                // Only call realpath() on the portion up to the last component.
                narrow_res = realpath(narrow_path.substr(0, pathsep_idx).c_str(), NULL);
                if (!narrow_res) return NULL;
                pathsep_idx++;
            }
            real_path.append(narrow_res);
            // This test is to deal with pathological cases such as /../../x => //x.
            if (real_path.size() > 1) real_path.append("/");
            real_path.append(narrow_path.substr(pathsep_idx, cstring::npos));
        }
    }
#if __APPLE__ && __DARWIN_C_LEVEL < 200809L
// OS X Snow Leopard is broken with respect to the dynamically allocated buffer returned by
// realpath(). It's not dynamically allocated so attempting to free that buffer triggers a
// malloc/free error. Thus we don't attempt the free in this case.
#else
    free(narrow_res);
#endif

    wcstring wreal_path = str2wcstring(real_path);
    if (resolved_path) {
        wcslcpy(resolved_path, wreal_path.c_str(), PATH_MAX);
        return resolved_path;
    }
    return wcsdup(wreal_path.c_str());
}
Ejemplo n.º 12
0
static wcstring default_vars_path()
{
    wcstring wdir = fishd_get_config();
    const std::string dir = wcs2string(wdir);
    if (dir.empty())
        return L"";
    
    const std::string machine_id = get_machine_identifier();
    const std::string machine_id_path = get_variables_file_path(dir, machine_id);
    return str2wcstring(machine_id_path);
}
Ejemplo n.º 13
0
static std::string html_colorize(const wcstring &text,
                                 const std::vector<highlight_spec_t> &colors) {
    if (text.empty()) {
        return "";
    }

    assert(colors.size() == text.size());
    wcstring html = L"<pre><code>";
    highlight_spec_t last_color = highlight_spec_normal;
    for (size_t i = 0; i < text.size(); i++) {
        // Handle colors.
        highlight_spec_t color = colors.at(i);
        if (i > 0 && color != last_color) {
            html.append(L"</span>");
        }
        if (i == 0 || color != last_color) {
            append_format(html, L"<span class=\"%ls\">", html_class_name_for_color(color));
        }
        last_color = color;

        // Handle text.
        wchar_t wc = text.at(i);
        switch (wc) {
            case L'&': {
                html.append(L"&amp;");
                break;
            }
            case L'\'': {
                html.append(L"&apos;");
                break;
            }
            case L'"': {
                html.append(L"&quot;");
                break;
            }
            case L'<': {
                html.append(L"&lt;");
                break;
            }
            case L'>': {
                html.append(L"&gt;");
                break;
            }
            default: {
                html.push_back(wc);
                break;
            }
        }
    }
    html.append(L"</span></code></pre>");
    return wcs2string(html);
}
Ejemplo n.º 14
0
bool wreaddir_resolving(DIR *dir, const std::wstring &dir_path, std::wstring &out_name, bool *out_is_dir)
{
    struct dirent *d = readdir(dir);
    if (!d) return false;

    out_name = str2wcstring(d->d_name);
    if (out_is_dir)
    {
        /* The caller cares if this is a directory, so check */
        bool is_dir = false;
        
        /* We may be able to skip stat, if the readdir can tell us the file type directly */
        bool check_with_stat = true;
#ifdef HAVE_STRUCT_DIRENT_D_TYPE
        if (d->d_type == DT_DIR)
        {
            /* Known directory */
            is_dir = true;
            check_with_stat = false;
        }
        else if (d->d_type == DT_LNK || d->d_type == DT_UNKNOWN)
        {
            /* We want to treat symlinks to directories as directories. Use stat to resolve it. */
            check_with_stat = true;
        }
        else
        {
            /* Regular file */
            is_dir = false;
            check_with_stat = false;
        }
#endif // HAVE_STRUCT_DIRENT_D_TYPE
        if (check_with_stat)
        {
            /* We couldn't determine the file type from the dirent; check by stat'ing it */
            cstring fullpath = wcs2string(dir_path);
            fullpath.push_back('/');
            fullpath.append(d->d_name);
            struct stat buf;
            if (stat(fullpath.c_str(), &buf) != 0)
            {
                is_dir = false;
            }
            else
            {
                is_dir = !!(S_ISDIR(buf.st_mode));
            }
        }
        *out_is_dir = is_dir;
    }
    return true;
}
Ejemplo n.º 15
0
/* Output our YAML to a file */
bool history_lru_node_t::write_yaml_to_file(FILE *f) const {
    std::string cmd = wcs2string(key);
    escape_yaml(cmd);
    if (fprintf(f, "- cmd: %s\n", cmd.c_str()) < 0)
        return false;
        
    if (fprintf(f, "   when: %ld\n", (long)timestamp) < 0)
        return false;
    
    if (! required_paths.empty()) {
        if (fputs("   paths:\n", f) < 0)
            return false;
            
        for (path_list_t::const_iterator iter = required_paths.begin(); iter != required_paths.end(); ++iter) {
            std::string path = wcs2string(*iter);
            escape_yaml(path);
            
            if (fprintf(f, "    - %s\n", path.c_str()) < 0)
                return false;
        }
    }
    return true;
}
Ejemplo n.º 16
0
const wchar_t *wgetenv(const wcstring &name)
{
    ASSERT_IS_MAIN_THREAD();
    cstring name_narrow = wcs2string(name);
    char *res_narrow = getenv(name_narrow.c_str());
    static wcstring out;

    if (!res_narrow)
        return 0;

    out = format_string(L"%s", res_narrow);
    return out.c_str();

}
Ejemplo n.º 17
0
/**
   Attempts tilde expansion of the string specified, modifying it in place.
*/
static void expand_home_directory(wcstring &input)
{
    const wchar_t * const in = input.c_str();
    if (in[0] == HOME_DIRECTORY)
    {
        int tilde_error = 0;
        size_t tail_idx;
        wcstring home;

        if (in[1] == '/' || in[1] == '\0')
        {
            /* Current users home directory */

            home = env_get_string(L"HOME");
            tail_idx = 1;
        }
        else
        {
            /* Some other users home directory */
            const wchar_t *name_end = wcschr(in, L'/');
            if (name_end)
            {
                tail_idx = name_end - in;
            }
            else
            {
                tail_idx = wcslen(in);
            }
            wcstring name_str = input.substr(1, tail_idx - 1);
            std::string name_cstr = wcs2string(name_str);
            struct passwd *userinfo = getpwnam(name_cstr.c_str());

            if (userinfo == NULL)
            {
                tilde_error = 1;
                input[0] = L'~';
            }
            else
            {
                home = str2wcstring(userinfo->pw_dir);
            }
        }

        if (! tilde_error)
        {
            input.replace(input.begin(), input.begin() + tail_idx, home);
        }
    }
}
Ejemplo n.º 18
0
/**
   Load or save all variables
*/
static void load_or_save( int save)
{
	const wcstring wdir = fishd_get_config();
	char hostname[HOSTNAME_LEN];
	connection_t c;
	int fd;
	
	if (wdir.empty())
		return;
	
	std::string dir = wcs2string( wdir );
	
	gethostname( hostname, HOSTNAME_LEN );
	
    std::string name;
    name.append(dir);
    name.append("/");
    name.append(FILE);
    name.append(hostname);
	
	debug( 4, L"Open file for %s: '%s'", 
		   save?"saving":"loading", 
		   name.c_str() );
	
    /* OK to not use CLO_EXEC here because fishd is single threaded */
	fd = open(name.c_str(), save?(O_CREAT | O_TRUNC | O_WRONLY):O_RDONLY, 0600);
	
	if( fd == -1 )
	{
		debug( 1, L"Could not open load/save file. No previous saves?" );
		wperror( L"open" );
		return;		
	}
	debug( 4, L"File open on fd %d", c.fd );

	connection_init( &c, fd );

	if( save )
	{
		
		write_loop( c.fd, SAVE_MSG, strlen(SAVE_MSG) );
		enqueue_all( &c );
	}
	else
		read_message( &c );

	connection_destroy( &c );	
}
Ejemplo n.º 19
0
wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path) {
    cstring tmp = wcs2string(pathname);
    char narrow_buff[PATH_MAX];
    char *narrow_res = realpath(tmp.c_str(), narrow_buff);
    wchar_t *res;

    if (!narrow_res) return 0;

    const wcstring wide_res = str2wcstring(narrow_res);
    if (resolved_path) {
        wcslcpy(resolved_path, wide_res.c_str(), PATH_MAX);
        res = resolved_path;
    } else {
        res = wcsdup(wide_res.c_str());
    }
    return res;
}
Ejemplo n.º 20
0
/// Evaluate math expressions.
static int evaluate_expression(const wchar_t *cmd, parser_t &parser, io_streams_t &streams,
                               math_cmd_opts_t &opts, wcstring &expression) {
    UNUSED(parser);

    int retval = STATUS_CMD_OK;
    te_error_t error;
    std::string narrow_str = wcs2string(expression);
    // Switch locale while computing stuff.
    // This means that the "." is always the radix character,
    // so numbers work the same across locales.
    char *saved_locale = strdup(setlocale(LC_NUMERIC, NULL));
    setlocale(LC_NUMERIC, "C");
    double v = te_interp(narrow_str.c_str(), &error);

    if (error.position == 0) {
        // Check some runtime errors after the fact.
        // TODO: Really, this should be done in tinyexpr
        // (e.g. infinite is the result of "x / 0"),
        // but that's much more work.
        const char *error_message = NULL;
        if (std::isinf(v)) {
            error_message = "Result is infinite";
        } else if (std::isnan(v)) {
            error_message = "Result is not a number";
        } else if (std::abs(v) >= kMaximumContiguousInteger) {
            error_message = "Result magnitude is too large";
        }
        if (error_message) {
            streams.err.append_format(L"%ls: Error: %s\n", cmd, error_message);
            streams.err.append_format(L"'%ls'\n", expression.c_str());
            retval = STATUS_CMD_ERROR;
        } else {
            streams.out.append(format_double(v, opts));
            streams.out.push_back(L'\n');
        }
    } else {
        streams.err.append_format(L"%ls: Error: %ls\n", cmd, math_describe_error(error).c_str());
        streams.err.append_format(L"'%ls'\n", expression.c_str());
        streams.err.append_format(L"%*ls%ls\n", error.position - 1, L" ",L"^");
        retval = STATUS_CMD_ERROR;
    }
    setlocale(LC_NUMERIC, saved_locale);
    free(saved_locale);
    return retval;
}
Ejemplo n.º 21
0
const wcstring &wgettext(const wchar_t *in) {
    // Preserve errno across this since this is often used in printing error messages.
    int err = errno;
    wcstring key = in;

    wgettext_init_if_necessary();
    auto wmap = wgettext_map.acquire();
    wcstring &val = wmap.value[key];
    if (val.empty()) {
        cstring mbs_in = wcs2string(key);
        char *out = fish_gettext(mbs_in.c_str());
        val = format_string(L"%s", out);
    }
    errno = err;

    // The returned string is stored in the map.
    // TODO: If we want to shrink the map, this would be a problem.
    return val;
}
Ejemplo n.º 22
0
static int wopen_internal(const wcstring &pathname, int flags, mode_t mode, bool cloexec) {
    ASSERT_IS_NOT_FORKED_CHILD();
    cstring tmp = wcs2string(pathname);
    int fd;

#ifdef O_CLOEXEC
    // Prefer to use O_CLOEXEC. It has to both be defined and nonzero.
    if (cloexec) {
        fd = open(tmp.c_str(), flags | O_CLOEXEC, mode);
    } else {
        fd = open(tmp.c_str(), flags, mode);
    }
#else
    fd = open(tmp.c_str(), flags, mode);
    if (fd >= 0 && !set_cloexec(fd)) {
        close(fd);
        fd = -1;
    }
#endif
    return fd;
}
Ejemplo n.º 23
0
static int wopen_internal(const wcstring &pathname, int flags, mode_t mode, bool cloexec)
{
    ASSERT_IS_NOT_FORKED_CHILD();
    cstring tmp = wcs2string(pathname);
    /* Prefer to use O_CLOEXEC. It has to both be defined and nonzero. */
#ifdef O_CLOEXEC
    if (cloexec && (O_CLOEXEC != 0))
    {
        flags |= O_CLOEXEC;
        cloexec = false;
    }
#endif
    int fd = ::open(tmp.c_str(), flags, mode);
    if (cloexec && fd >= 0 && ! set_cloexec(fd))
    {
        close(fd);
        fd = -1;
    }
    return fd;

}
Ejemplo n.º 24
0
bool wreaddir_resolving(DIR *dir, const std::wstring &dir_path, std::wstring &out_name, bool *out_is_dir)
{
    struct dirent *d = readdir(dir);
    if (!d) return false;

    out_name = str2wcstring(d->d_name);
    if (out_is_dir)
    {
        /* The caller cares if this is a directory, so check */
        bool is_dir;
        if (d->d_type == DT_DIR)
        {
            is_dir = true;
        }
        else if (d->d_type == DT_LNK || d->d_type == DT_UNKNOWN)
        {
            /* We want to treat symlinks to directories as directories. Use stat to resolve it. */
            cstring fullpath = wcs2string(dir_path);
            fullpath.push_back('/');
            fullpath.append(d->d_name);
            struct stat buf;
            if (stat(fullpath.c_str(), &buf) != 0)
            {
                is_dir = false;
            }
            else
            {
                is_dir = !!(S_ISDIR(buf.st_mode));
            }
        }
        else
        {
            is_dir = false;
        }
        *out_is_dir = is_dir;
    }
    return true;
}
Ejemplo n.º 25
0
/// Return the key name if the recent sequence of characters matches a known terminfo sequence.
char *const key_name(unsigned char c) {
    static char recent_chars[8] = {0};

    recent_chars[0] = recent_chars[1];
    recent_chars[1] = recent_chars[2];
    recent_chars[2] = recent_chars[3];
    recent_chars[3] = recent_chars[4];
    recent_chars[4] = recent_chars[5];
    recent_chars[5] = recent_chars[6];
    recent_chars[6] = recent_chars[7];
    recent_chars[7] = c;

    for (int idx = 7; idx >= 0; idx--) {
        wcstring out_name;
        wcstring seq = str2wcstring(recent_chars + idx, 8 - idx);
        bool found = input_terminfo_get_name(seq, &out_name);
        if (found) {
            return strdup(wcs2string(out_name).c_str());
        }
    }

    return NULL;
}
Ejemplo n.º 26
0
const wchar_t *wgettext(const wchar_t *in)
{
    if (!in)
        return in;

    // preserve errno across this since this is often used in printing error messages
    int err = errno;

    wgettext_init_if_necessary();

    wcstring key = in;
    scoped_lock lock(wgettext_lock);

    wcstring *& val = wgettext_map[key];
    if (val == NULL)
    {
        cstring mbs_in = wcs2string(key);
        char *out = gettext(mbs_in.c_str());
        val = new wcstring(format_string(L"%s", out));
    }
    errno = err;
    return val->c_str();
}
Ejemplo n.º 27
0
const wchar_t *wgettext(const wchar_t *in)
{
    if (!in)
        return in;

    // preserve errno across this since this is often used in printing error messages
    int err = errno;

    wgettext_init_if_necessary();

    wcstring key = in;
    scoped_lock lock(wgettext_lock);

    wcstring *& val = wgettext_map[key];
    if (val == NULL)
    {
        cstring mbs_in = wcs2string(key);
        char *out = fish_gettext(mbs_in.c_str());
        val = new wcstring(format_string(L"%s", out)); //note that this writes into the map!
    }
    errno = err;
    return val->c_str(); //looks dangerous but is safe, since the string is stored in the map
}
Ejemplo n.º 28
0
wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path)
{
    cstring narrow_path = wcs2string(pathname);
    char *narrow_res = realpath(narrow_path.c_str(), NULL);

    if (!narrow_res)
        return NULL;

    wchar_t *res;
    wcstring wide_res = str2wcstring(narrow_res);
    if (resolved_path)
    {
        wcslcpy(resolved_path, wide_res.c_str(), PATH_MAX);
        res = resolved_path;
    }
    else
    {
        res = wcsdup(wide_res.c_str());
    }

    free(narrow_res);

    return res;
}
Ejemplo n.º 29
0
static std::string no_colorize(const wcstring &text)
{
    return wcs2string(text);
}
Ejemplo n.º 30
0
void s_write(screen_t *s, const wcstring &left_prompt, const wcstring &right_prompt,
             const wcstring &commandline, size_t explicit_len,
             const std::vector<highlight_spec_t> &colors, const std::vector<int> &indent,
             size_t cursor_pos, const page_rendering_t &pager, bool cursor_is_within_pager) {
    screen_data_t::cursor_t cursor_arr;

    // Turn the command line into the explicit portion and the autosuggestion.
    const wcstring explicit_command_line = commandline.substr(0, explicit_len);
    const wcstring autosuggestion = commandline.substr(explicit_len);

    // If we are using a dumb terminal, don't try any fancy stuff, just print out the text.
    // right_prompt not supported.
    if (is_dumb()) {
        const std::string prompt_narrow = wcs2string(left_prompt);
        const std::string command_line_narrow = wcs2string(explicit_command_line);

        write_loop(STDOUT_FILENO, "\r", 1);
        write_loop(STDOUT_FILENO, prompt_narrow.c_str(), prompt_narrow.size());
        write_loop(STDOUT_FILENO, command_line_narrow.c_str(), command_line_narrow.size());

        return;
    }

    s_check_status(s);
    const size_t screen_width = common_get_width();

    // Completely ignore impossibly small screens.
    if (screen_width < 4) {
        return;
    }

    // Compute a layout.
    const screen_layout_t layout = compute_layout(s, screen_width, left_prompt, right_prompt,
                                                  explicit_command_line, autosuggestion, indent);

    // Determine whether, if we have an autosuggestion, it was truncated.
    s->autosuggestion_is_truncated =
        !autosuggestion.empty() && autosuggestion != layout.autosuggestion;

    // Clear the desired screen.
    s->desired.resize(0);
    s->desired.cursor.x = s->desired.cursor.y = 0;

    // Append spaces for the left prompt.
    for (size_t i = 0; i < layout.left_prompt_space; i++) {
        s_desired_append_char(s, L' ', highlight_spec_t{}, 0, layout.left_prompt_space);
    }

    // If overflowing, give the prompt its own line to improve the situation.
    size_t first_line_prompt_space = layout.left_prompt_space;
    if (layout.prompts_get_own_line) {
        s_desired_append_char(s, L'\n', highlight_spec_t{}, 0, 0);
        first_line_prompt_space = 0;
    }

    // Reconstruct the command line.
    wcstring effective_commandline = explicit_command_line + layout.autosuggestion;

    // Output the command line.
    size_t i;
    for (i = 0; i < effective_commandline.size(); i++) {
        // Grab the current cursor's x,y position if this character matches the cursor's offset.
        if (!cursor_is_within_pager && i == cursor_pos) {
            cursor_arr = s->desired.cursor;
        }
        s_desired_append_char(s, effective_commandline.at(i), colors[i], indent[i],
                              first_line_prompt_space);
    }

    // Cursor may have been at the end too.
    if (!cursor_is_within_pager && i == cursor_pos) {
        cursor_arr = s->desired.cursor;
    }

    // Now that we've output everything, set the cursor to the position that we saved in the loop
    // above.
    s->desired.cursor = cursor_arr;

    if (cursor_is_within_pager) {
        s->desired.cursor.x = (int)cursor_pos;
        s->desired.cursor.y = (int)s->desired.line_count();
    }

    // Append pager_data (none if empty).
    s->desired.append_lines(pager.screen_data);

    s_update(s, layout.left_prompt, layout.right_prompt);
    s_save_status(s);
}