111 lines
3.1 KiB
C++
111 lines
3.1 KiB
C++
#include "TermInfo.h"
|
|
|
|
#include <vector>
|
|
#include "File.h"
|
|
#include <stdexcept>
|
|
#include <iostream>
|
|
|
|
bool TermInfo::load_terminfo(const std::string& terminfo_dir,
|
|
const std::string& term)
|
|
{
|
|
const auto path = std::filesystem::path(terminfo_dir);
|
|
if (!std::filesystem::is_directory(path))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
std::string suffix = "/" + term;
|
|
suffix = term[0] + suffix;
|
|
|
|
const auto file_path = path / std::filesystem::path(suffix);
|
|
|
|
auto file = File(file_path);
|
|
|
|
std::cout << "trying: " << file_path << std::endl;
|
|
if (!file.pathExists())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!file.open(File::AccessMode::Read))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
std::vector<unsigned char> content;
|
|
file.readBinary(content);
|
|
short header_size = 12;
|
|
if (content.size() < static_cast<std::size_t>(header_size))
|
|
{
|
|
std::cerr << "terminfo file missing header: " << content.size() << std::endl;
|
|
return false;
|
|
}
|
|
|
|
short magic_number = 256*content[1] + content[0];
|
|
if (magic_number != 282) // octal 0432
|
|
{
|
|
std::cerr << "unexpected magic number" << std::endl;
|
|
}
|
|
short name_size = 256*content[3] + content[2];
|
|
//short bool_size = 256*content[5] + content[4];
|
|
//short numbers_size = 256*content[7] + content[6];
|
|
//short strings_size = 256*content[9] + content[8];
|
|
//short string_table_size = 256*content[11] + content[10];
|
|
std::cout << "got name size: " << name_size << std::endl;
|
|
|
|
const auto bool_offset = static_cast<std::size_t>(header_size + name_size);
|
|
if (content.size() < bool_offset)
|
|
{
|
|
std::cerr << "unexpected terminfo size" << std::endl;
|
|
}
|
|
std::vector<std::string> names;
|
|
std::string working_name;
|
|
for(std::size_t idx=header_size; idx<bool_offset; idx++)
|
|
{
|
|
const auto c = content[idx];
|
|
if (c == '|')
|
|
{
|
|
names.push_back(working_name);
|
|
//std::cout << "got name: " << working_name << std::endl;
|
|
}
|
|
else
|
|
{
|
|
working_name += c;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void TermInfo::load()
|
|
{
|
|
const auto term = std::getenv("TERM");
|
|
if (!term || std::string(term).empty())
|
|
{
|
|
throw std::runtime_error("TERM environment variable not set or empty - can't proceed.");
|
|
}
|
|
|
|
const auto terminfo = std::getenv("TERMINFO");
|
|
if (terminfo)
|
|
{
|
|
if (load_terminfo(terminfo, term))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
std::vector<std::string> common_paths = {"/usr/share/terminfo"};
|
|
for (const auto& path : common_paths)
|
|
{
|
|
if (load_terminfo(path, term))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
std::cerr << "Couldn't find terminfo" << std::endl;
|
|
}
|
|
|
|
|
|
|