// // aegis - project change supervisor // Copyright (C) 1999-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 void wide_output_wrap::wrap() { trace(("wide_output_wrap::wrap(this = %08lX)\n{\n", (long)this)); const wchar_t *s = buf.get_data(); const wchar_t *s_end = s + buf.size(); while (s < s_end) { // // remember where the line starts within the buffer // const wchar_t *s_start = s; int s_wid = 0; // // Collect characters until we run out of width. // language_human(); if (s < s_end && *s != '\n') { // // Always use the first character. This avoids // an infinite loop where you have a 1-position // wide column, and a 2-position wide character. // (Or other variations on the same theme.) // s_wid += wcwidth(*s++); } while (s < s_end && *s != '\n') { int c_wid = s_wid + wcwidth(*s); if (c_wid > width) break; ++s; s_wid = c_wid; } trace(("s_wid=%d width=%d\n", s_wid, width)); // // If we reached the end of the line, // write it out and stop. // if (s >= s_end) { trace(("s_start=%08lX s=%08lX\n", (long)s_start, (long)s)); language_C(); deeper->write(s_start, s - s_start); break; } // // The line needs to be wrapped. // See if there is a better place to wrap it. // trace(("mark\n")); if (s < s_end && !iswspace(*s)) { const wchar_t *s2 = s; while ( s2 > s_start && !iswspace(s2[-1]) && s2[-1] != L'-' && s2[-1] != L'_' && s2[-1] != L'/' ) --s2; if (s2 > s_start) { while (s2 > s_start && iswspace(s2[-1])) --s2; s = s2; } } // // Write out the line so far, plus the newline, // and then skip any trailing spaces (including any newlines). // trace(("s_start=%08lX s=%08lX\n", (long)s_start, (long)s)); language_C(); deeper->write(s_start, s - s_start); while (s < s_end && iswspace(*s)) ++s; trace(("s=%08lX\n", (long)s)); if (s >= s_end) break; deeper->put_wc(L'\n'); } // // End the line with a newline, even if the input didn't have one. // deeper->put_wc(L'\n'); // // Reset the line, now that we've written it out. // buf.clear(); trace(("}\n")); } wide_output_wrap::~wide_output_wrap() { trace(("wide_output_wrap::destructor(this = %08lX)\n{\n", (long)this)); flush(); if (!buf.empty()) wrap(); trace(("}\n")); } wide_output_wrap::wide_output_wrap(const wide_output::pointer &a_deeper, int a_width) : deeper(a_deeper), width(a_width <= 0 ? a_deeper->page_width() : a_width) { trace(("%s\n", __PRETTY_FUNCTION__)); } wide_output::pointer wide_output_wrap::open(const wide_output::pointer &a_deeper, int a_width) { trace(("%s\n", __PRETTY_FUNCTION__)); return pointer(new wide_output_wrap(a_deeper, a_width)); } nstring wide_output_wrap::filename() { return deeper->filename(); } void wide_output_wrap::write_inner(const wchar_t *data, size_t len) { trace(("wide_output_wrap::write(this = %08lX, data = %08lX, " "len = %ld)\n{\n", (long)this, (long)data, (long)len)); while (len > 0) { wchar_t wc = *data++; --len; if (wc == L'\n') wrap(); else buf.push_back(wc); } trace(("}\n")); } void wide_output_wrap::flush_inner() { deeper->flush(); } int wide_output_wrap::page_width() { return width; } int wide_output_wrap::page_length() { return deeper->page_length(); } void wide_output_wrap::end_of_line_inner() { trace(("wide_output_wrap::eoln(this = %08lX)\n{\n", (long)this)); if (!buf.empty()) put_wc(L'\n'); trace(("}\n")); } const char * wide_output_wrap::type_name() const { return "wide_output_wrap"; }