/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2016-2017 Danny Robson */ #include "term.hpp" #include "string.hpp" #include #include #include using cruft::term::csi::graphics; const graphics graphics::RESET (0); /////////////////////////////////////////////////////////////////////////////// // find the terminfo path within a directory, for a key // // throws an exception if not found static std::filesystem::path find_terminfo_path (const std::filesystem::path &dir, const std::string &key) { const char letter[2] = { key[0], '\0' }; auto candidate = dir / letter / key; if (!std::filesystem::is_directory (candidate)) throw std::runtime_error ("path not found"); return candidate; } //----------------------------------------------------------------------------- // find the terminfo path for a given key. // // throws an exception if not found static std::filesystem::path find_terminfo_path [[gnu::unused]] (const std::string &key) { static const std::filesystem::path DEFAULT_SEARCH_DIR = "/usr/share/terminfo"; // check if the path is explicitly listed. must not fall through. if (const char *dir = getenv ("TERMINFO")) { return find_terminfo_path (dir, key); } // check if we have a path at $HOME. falls through. if (const char *home = getenv ("HOME")) { std::filesystem::path HOME (home); try { return find_terminfo_path (HOME / ".terminfo", key); } catch (...) { } } // check colon seperated list in TERMINFO_DIRS if (const char *dirs = getenv ("TERMINFO_DIRS")) { auto tok = cruft::tokeniser (dirs, ':'); for (auto i: tok) { try { return find_terminfo_path ( i.empty () ? DEFAULT_SEARCH_DIR : std::filesystem::path (i.cbegin (), i.cend ()), key ); } catch (...) { } } } return find_terminfo_path ("/usr/share/terminfo", key); } /////////////////////////////////////////////////////////////////////////////// bool cruft::term::has_csi_support (void) { // HACK: this will do until we get a terminfo/termcap reader return getenv ("TERM") == std::string ("XTERM"); } /////////////////////////////////////////////////////////////////////////////// graphics::graphics (layer _layer, hue _hue): m_value (_layer + int (_hue)) { ; } //----------------------------------------------------------------------------- graphics::graphics (char _value): m_value (_value) { ; } /////////////////////////////////////////////////////////////////////////////// char graphics::value (void) const { return m_value; } //----------------------------------------------------------------------------- char graphics::value (char _value) { return m_value = _value; } /////////////////////////////////////////////////////////////////////////////// std::ostream& cruft::term::csi::operator<< (std::ostream &os, graphics g) { return os << code::CSI << '[' << +g.value () << decltype(g)::terminator; }