Serenity Operating System
at master 132 lines 3.6 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/Debug.h> 8#include <AK/DeprecatedString.h> 9#include <AK/HashMap.h> 10#include <AK/Vector.h> 11#include <assert.h> 12#include <string.h> 13#include <termcap.h> 14 15extern "C" { 16 17char PC; 18char* UP; 19char* BC; 20 21int __attribute__((weak)) tgetent([[maybe_unused]] char* bp, [[maybe_unused]] char const* name) 22{ 23 warnln_if(TERMCAP_DEBUG, "tgetent: bp={:p}, name='{}'", bp, name); 24 PC = '\0'; 25 BC = const_cast<char*>("\033[D"); 26 UP = const_cast<char*>("\033[A"); 27 return 1; 28} 29 30static HashMap<DeprecatedString, char const*>* caps = nullptr; 31 32static void ensure_caps() 33{ 34 if (caps) 35 return; 36 caps = new HashMap<DeprecatedString, char const*>; 37 caps->set("DC", "\033[%p1%dP"); 38 caps->set("IC", "\033[%p1%d@"); 39 caps->set("ce", "\033[K"); 40 caps->set("cl", "\033[H\033[J"); 41 caps->set("cr", "\015"); 42 caps->set("dc", "\033[P"); 43 caps->set("ei", ""); 44 caps->set("ic", ""); 45 caps->set("im", ""); 46 caps->set("kd", "\033[B"); 47 caps->set("kl", "\033[D"); 48 caps->set("kr", "\033[C"); 49 caps->set("ku", "\033[A"); 50 caps->set("ks", ""); 51 caps->set("ke", ""); 52 caps->set("le", "\033[D"); 53 caps->set("mm", ""); 54 caps->set("mo", ""); 55 caps->set("pc", ""); 56 caps->set("up", "\033[A"); 57 caps->set("vb", ""); 58 caps->set("am", ""); 59 caps->set("@7", ""); 60 caps->set("kH", ""); 61 caps->set("kI", "\033[L"); 62 caps->set("kh", "\033[H"); 63 caps->set("vs", ""); 64 caps->set("ve", ""); 65 caps->set("E3", ""); 66 caps->set("kD", ""); 67 caps->set("nd", "\033[C"); 68 69 caps->set("co", "80"); 70 caps->set("li", "25"); 71} 72 73// Unfortunately, tgetstr() doesn't accept a size argument for the buffer 74// pointed to by area, so we have to use bare strcpy(). 75#pragma GCC diagnostic push 76#pragma GCC diagnostic ignored "-Wdeprecated-declarations" 77 78char* __attribute__((weak)) tgetstr(char const* id, char** area) 79{ 80 ensure_caps(); 81 warnln_if(TERMCAP_DEBUG, "tgetstr: id='{}'", id); 82 auto it = caps->find(id); 83 if (it != caps->end()) { 84 char* ret = *area; 85 char const* val = (*it).value; 86 strcpy(*area, val); 87 *area += strlen(val) + 1; 88 return ret; 89 } 90 warnln_if(TERMCAP_DEBUG, "tgetstr: missing cap id='{}'", id); 91 return nullptr; 92} 93 94#pragma GCC diagnostic pop 95 96int __attribute__((weak)) tgetflag([[maybe_unused]] char const* id) 97{ 98 warnln_if(TERMCAP_DEBUG, "tgetflag: '{}'", id); 99 auto it = caps->find(id); 100 if (it != caps->end()) 101 return 1; 102 return 0; 103} 104 105int __attribute__((weak)) tgetnum(char const* id) 106{ 107 warnln_if(TERMCAP_DEBUG, "tgetnum: '{}'", id); 108 auto it = caps->find(id); 109 if (it != caps->end()) 110 return atoi((*it).value); 111 return -1; 112} 113 114static Vector<char> s_tgoto_buffer; 115char* __attribute__((weak)) tgoto([[maybe_unused]] char const* cap, [[maybe_unused]] int col, [[maybe_unused]] int row) 116{ 117 auto cap_str = StringView { cap, strlen(cap) }.replace("%p1%d"sv, DeprecatedString::number(col), ReplaceMode::FirstOnly).replace("%p2%d"sv, DeprecatedString::number(row), ReplaceMode::FirstOnly); 118 119 s_tgoto_buffer.clear_with_capacity(); 120 s_tgoto_buffer.ensure_capacity(cap_str.length()); 121 (void)cap_str.copy_characters_to_buffer(s_tgoto_buffer.data(), cap_str.length()); 122 return s_tgoto_buffer.data(); 123} 124 125int __attribute__((weak)) tputs(char const* str, [[maybe_unused]] int affcnt, int (*putc)(int)) 126{ 127 size_t len = strlen(str); 128 for (size_t i = 0; i < len; ++i) 129 putc(str[i]); 130 return 0; 131} 132}