// // aegis - project change supervisor // Copyright (C) 1999-2006, 2008 Peter Miller // // 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 // . // #include #include #include #include #include #include #include #include #include wide_output_to_narrow::~wide_output_to_narrow() { // // There could be outstanding state to flush. // trace(("wide_output_to_narrow::destructor(this = %08lX)\n{\n", (long)this)); flush(); language_human(); char buf[MB_LEN_MAX + 1]; int n = wcrtomb(buf, (wchar_t)0, &state); language_C(); // The last one should be a NUL. if (n > 0 && buf[n - 1] == 0) --n; if (n > 0) deeper->write(buf, n); trace(("}\n")); } static mbstate_t initial_state; wide_output_to_narrow::wide_output_to_narrow(const output::pointer &a_deeper) : deeper(a_deeper), state(initial_state), prev_was_newline(true) { } wide_output::pointer wide_output_to_narrow::open(const output::pointer &a_deeper) { return pointer(new wide_output_to_narrow(a_deeper)); } nstring wide_output_to_narrow::filename() { return deeper->filename(); } void wide_output_to_narrow::write_inner(const wchar_t *data, size_t len) { // // This is very similar to the single character case, however // we minimize the number of locale changes. // trace(("wide_output_to_narrow::write_inner(this = %08lX, data = %08lX, " "len = %ld)\n{\n", (long)this, (long)data, (long)len)); while (len > 0) { char buf[2000]; language_human(); size_t buf_pos = 0; while (buf_pos + MB_LEN_MAX <= sizeof(buf) && len > 0) { trace(("data = %08lX, len = %ld\n", (long)data, (long)len)); wchar_t wc = *data++; --len; mbstate_t sequester = state; // // this could be recoded to use the wcsrtombs function, now // that it has sensible semantics around errors. // int n = wcrtomb(buf + buf_pos, wc, &state); if (n == -1) { state = sequester; language_C(); deeper->write(buf, buf_pos); buf_pos = 0; deeper->fprintf("\\x%lX", (unsigned long)wc); language_human(); } else buf_pos += n; prev_was_newline = (wc == L'\n'); } language_C(); deeper->write(buf, buf_pos); buf_pos = 0; } trace(("}\n")); } void wide_output_to_narrow::flush_inner() { deeper->flush(); } int wide_output_to_narrow::page_width() { return deeper->page_width(); } int wide_output_to_narrow::page_length() { return deeper->page_length(); } void wide_output_to_narrow::end_of_line_inner() { trace(("wide_output_to_narrow::end_of_line_inner(this = %08lX)\n{\n", (long)this)); if (!prev_was_newline) put_wc(L'\n'); trace(("}\n")); } const char * wide_output_to_narrow::type_name() const { return "wide_output_to_narrow"; }