/* * Copyright (c) 2018-2020, Andreas Kling * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include extern "C" { char PC; char* UP; char* BC; int tgetent([[maybe_unused]] char* bp, [[maybe_unused]] const char* name) { #if TERMCAP_DEBUG fprintf(stderr, "tgetent: bp=%p, name='%s'\n", bp, name); #endif PC = '\0'; BC = const_cast("\033[D"); UP = const_cast("\033[A"); return 1; } static HashMap* caps = nullptr; static void ensure_caps() { if (caps) return; caps = new HashMap; caps->set("DC", "\033[%p1%dP"); caps->set("IC", "\033[%p1%d@"); caps->set("ce", "\033[K"); caps->set("cl", "\033[H\033[J"); caps->set("cr", "\015"); caps->set("dc", "\033[P"); caps->set("ei", ""); caps->set("ic", ""); caps->set("im", ""); caps->set("kd", "\033[B"); caps->set("kl", "\033[D"); caps->set("kr", "\033[C"); caps->set("ku", "\033[A"); caps->set("ks", ""); caps->set("ke", ""); caps->set("le", "\033[D"); caps->set("mm", ""); caps->set("mo", ""); caps->set("pc", ""); caps->set("up", "\033[A"); caps->set("vb", ""); caps->set("am", ""); caps->set("@7", ""); caps->set("kH", ""); caps->set("kI", "\033[L"); caps->set("kh", "\033[H"); caps->set("vs", ""); caps->set("ve", ""); caps->set("E3", ""); caps->set("kD", ""); caps->set("nd", "\033[C"); caps->set("co", "80"); caps->set("li", "25"); } // Unfortunately, tgetstr() doesn't accept a size argument for the buffer // pointed to by area, so we have to use bare strcpy(). #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" char* tgetstr(const char* id, char** area) { ensure_caps(); #if TERMCAP_DEBUG fprintf(stderr, "tgetstr: id='%s'\n", id); #endif auto it = caps->find(id); if (it != caps->end()) { char* ret = *area; const char* val = (*it).value; strcpy(*area, val); *area += strlen(val) + 1; return ret; } fprintf(stderr, "tgetstr: missing cap id='%s'\n", id); return nullptr; } #pragma GCC diagnostic pop int tgetflag([[maybe_unused]] const char* id) { #if TERMCAP_DEBUG fprintf(stderr, "tgetflag: '%s'\n", id); #endif auto it = caps->find(id); if (it != caps->end()) return 1; return 0; } int tgetnum(const char* id) { #if TERMCAP_DEBUG fprintf(stderr, "tgetnum: '%s'\n", id); #endif auto it = caps->find(id); if (it != caps->end()) return atoi((*it).value); VERIFY_NOT_REACHED(); } static Vector s_tgoto_buffer; char* tgoto([[maybe_unused]] const char* cap, [[maybe_unused]] int col, [[maybe_unused]] int row) { auto cap_str = String(cap); cap_str.replace("%p1%d", String::number(col)); cap_str.replace("%p2%d", String::number(row)); s_tgoto_buffer.clear_with_capacity(); s_tgoto_buffer.ensure_capacity(cap_str.length()); (void)cap_str.copy_characters_to_buffer(s_tgoto_buffer.data(), cap_str.length()); return s_tgoto_buffer.data(); } int tputs(const char* str, [[maybe_unused]] int affcnt, int (*putc)(int)) { size_t len = strlen(str); for (size_t i = 0; i < len; ++i) putc(str[i]); return 0; } }