/** roflcat Copyright (C) 2019 rexy712 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef PRINTER_BASE_TPP #define PRINTER_BASE_TPP #include "printer_base.hpp" #include "cmd.hpp" #include //std::declval #ifndef _XOPEN_SOURCE #define _XOPEN_SOURCE //wcwidth #endif #include //wcwidth #include //wprintf, putwchar #include //mbstowcs template constexpr printer_base::printer_base(const wchar_t* tabstr, const cmd_args& args)noexcept: m_show_ends(args.ends), m_print_ln(args.number), m_squeeze_blank(args.squeeze), m_tab_str(tabstr), m_tab_size(wcslen(tabstr)){} template constexpr auto printer_base::print(wchar_t s)noexcept(noexcept(std::declval()._print(s))) -> Derived&{ Derived& dv = static_cast(*this); //suppress repeated blank lines if(m_squeeze_blank){ //if 2 newlines in a row if(m_newline && s == L'\n'){ if(m_squeeze_cnt == 0){ //don't suppress the first blank line ++m_squeeze_cnt; }else{ return dv; } }else{ m_squeeze_cnt = 0; } } //if we want to print line numbers and our last char was a newline if(m_print_ln != PRINT_LINE_NEVER && m_newline){ //if we want to print always or if we want nonblanks and last char wasn't a newline (ie nonblank) if(m_print_ln == PRINT_LINE_ALWAYS || s != L'\n'){ m_newline = false; wchar_t buffer[24]; //excessive swprintf(buffer, sizeof(buffer)/sizeof(buffer[0])-1, L"%" LINE_NUMBERING_SPACE "d", m_line_num++); for(wchar_t* c = buffer;*c != 0;++c){ dv._print(*c); } dv._print(L' '); } } //update status of last character if(s == L'\n'){ m_newline = true; if(m_show_ends) dv._print(L'$'); }else{ m_newline = false; } //tabs character can be changed with the -T switch, so treat it special if(s == L'\t'){ for(size_t i = 0;i < m_tab_size;++i){ dv._print(m_tab_str[i]); } }else{ dv._print(s); } return dv; } template constexpr auto printer_base::print(const wchar_t* s)noexcept(noexcept(std::declval>().print(std::declval()))) -> Derived&{ for(;*s != 0;++s){ print(*s); } return static_cast(*this); } template constexpr auto printer_base::print(char s) -> Derived&{ wchar_t tmp; mbstowcs(&tmp, &s, 1); return print(tmp); } template constexpr auto printer_base::print(const char* s) -> Derived&{ for(;*s != 0;++s){ print(*s); } return static_cast(*this); } template constexpr auto printer_base::reset(void) -> Derived&{ if constexpr(HAS_FUNC(_reset)::value){ return static_cast(*this)._reset(); }else{ return static_cast(*this); } } #endif