//
// aegis - project change supervisor
// Copyright (C) 1999, 2001-2008, 2012 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
wide_output_column::~wide_output_column()
{
trace(("wide_output_column::destructor(this = %p)\n{\n", this));
flush();
for (size_t j = 0; j < nrows; ++j)
{
column_row_ty *rp = row + j;
if (rp->text)
{
delete [] rp->text;
rp->text = 0;
}
}
delete [] row;
row = 0;
nrows = 0;
nrows_max = 0;
trace(("}\n"));
}
wide_output_column::wide_output_column(int a_width, int a_length) :
width(a_width <= 0 ? page_width_get(-1) : a_width),
length(a_length <= 0 ? page_length_get(-1) : a_length),
row(0),
nrows(0),
nrows_max(0)
{
}
wide_output_column::cpointer
wide_output_column::open(int a_width, int a_length)
{
return cpointer(new wide_output_column(a_width, a_length));
}
nstring
wide_output_column::filename()
{
return "(column)";
}
void
wide_output_column::write_inner(const wchar_t *buf, size_t buflen)
{
trace(("wide_output_column::write(this = %p, buf = %p, len = %ld)\n"
"{\n", this, buf, (long)buflen));
language_human();
while (buflen > 0)
{
wchar_t wc = *buf++;
--buflen;
//
// newlines simply advance down the column
//
if (wc == L'\n')
++nrows;
//
// Make sure we have a row structure to park the
// character in.
//
while (nrows >= nrows_max)
{
//
// The nrows_max value can easily be beyond the
// end of the array. For example, if the text starts with
// a couple of newlines. You must be careful about array
// bounds here.
//
size_t prev = nrows_max;
for (;;)
{
nrows_max = 4 + 2 * nrows_max;
if (nrows < nrows_max)
break;
}
column_row_ty *new_row =
new column_row_ty [nrows_max];
for (size_t k = 0; k < prev; ++k)
new_row[k] = row[k];
delete [] row;
row = new_row;
for (size_t j = prev; j < nrows_max; ++j)
{
column_row_ty *rp = row + j;
rp->length_max = 0;
rp->length = 0;
rp->text = 0;
rp->printing_width = 0;
}
}
if (wc == L'\n')
continue;
//
// Make sure we have text space enough to park the character.
//
column_row_ty *rp = row + nrows;
while (rp->length >= rp->length_max)
{
rp->length_max = 16 + 2 * rp->length_max;
wchar_t *new_text = new wchar_t [rp->length_max ];
for (size_t k = 0; k < rp->length; ++k)
new_text[k] = rp->text[k];
delete [] rp->text;
rp->text = new_text;
}
//
// Remember the character,
// and keep a running tally of the printing width.
//
rp->text[rp->length++] = wc;
rp->printing_width += wcwidth(wc);
}
language_C();
trace(("}\n"));
}
int
wide_output_column::page_width()
{
return width;
}
void
wide_output_column::flush_inner()
{
}
int
wide_output_column::page_length()
{
return length;
}
void
wide_output_column::end_of_line_inner()
{
trace(("wide_output_column::end_of_line_inner(this = %p)\n{\n",
this));
if (nrows > 0 && nrows < nrows_max)
{
column_row_ty *rp = row + nrows;
if (rp->length > 0)
put_wc(L'\n');
}
trace(("}\n"));
}
column_row_ty *
wide_output_column::get(int n)
{
trace(("wide_output_column::get(this = %p, n = %d)\n{\n",
this, n));
if (n < 0)
{
trace(("return NULL;\n"));
trace(("}\n"));
return 0;
}
if (n >= (int)nrows_max)
{
trace(("return NULL;\n"));
trace(("}\n"));
return 0;
}
column_row_ty *rp = row + n;
if (rp->length == 0)
{
//
// See if all rows after this one are empty, too.
// If they are, pretend this row doesn't exist.
//
size_t k;
bool end_of_the_road = true;
for (k = n + 1; k < nrows; ++k)
{
if (row[k].length)
{
end_of_the_road = false;
break;
}
}
if (end_of_the_road)
{
trace(("return NULL;\n"));
trace(("}\n"));
return 0;
}
}
trace(("return %p;\n", rp));
trace(("}\n"));
return rp;
}
void
wide_output_column::clear_buffers()
{
trace(("wide_output_column::reset(this = %p)\n{\n", this));
for (size_t j = 0; j < nrows_max; ++j)
{
row[j].length = 0;
row[j].printing_width = 0;
}
nrows = 0;
trace(("}\n"));
}
const char *
wide_output_column::type_name()
const
{
return "wide_output_column";
}
// vim: set ts=8 sw=4 et :