rewrite major part of strbuffer and Scrollpad::flush

This commit is contained in:
Andrzej Rybczak
2012-10-06 02:42:24 +02:00
parent 1eb0003714
commit eda2ea37a9
6 changed files with 259 additions and 399 deletions

View File

@@ -1970,8 +1970,8 @@ void Find::Run()
Statusbar::msg("Searching..."); Statusbar::msg("Searching...");
auto s = static_cast<Screen<NC::Scrollpad> *>(myScreen); auto s = static_cast<Screen<NC::Scrollpad> *>(myScreen);
s->main().removeFormatting(); s->main().removeProperties();
Statusbar::msg("%s", findme.empty() || s->main().setFormatting(NC::fmtReverse, ToWString(findme), NC::fmtReverseEnd, 0) ? "Done" : "No matching patterns found"); Statusbar::msg("%s", findme.empty() || s->main().setProperties(NC::fmtReverse, ToWString(findme), NC::fmtReverseEnd) ? "Done" : "No matching patterns found");
s->main().flush(); s->main().flush();
} }

View File

@@ -131,7 +131,7 @@ void showSongs(NC::Menu<T> &menu, const MPD::Song &s, const ProxySongList &pl, c
buf << " "; buf << " ";
stringToBuffer(++it, line.end(), buf); stringToBuffer(++it, line.end(), buf);
if (discard_colors) if (discard_colors)
buf.removeFormatting(); buf.removeProperties();
size_t x_off = menu.getWidth() - wideLength(ToWString(buf.str())); size_t x_off = menu.getWidth() - wideLength(ToWString(buf.str()));
if (is_now_playing) if (is_now_playing)
x_off -= Config.now_playing_suffix_length; x_off -= Config.now_playing_suffix_length;

View File

@@ -104,10 +104,8 @@ bool ArtistInfo::checkArgs(const Args &args)
void ArtistInfo::colorizeOutput(NC::Scrollpad &w) void ArtistInfo::colorizeOutput(NC::Scrollpad &w)
{ {
w.setFormatting(NC::fmtBold, L"\n\nSimilar artists:\n", NC::fmtBoldEnd, false); w.setProperties(NC::fmtBold, L"\n\nSimilar artists:\n", NC::fmtBoldEnd, 0);
w.setFormatting(Config.color2, L"\n * ", NC::clEnd, true); w.setProperties(Config.color2, L"\n * ", NC::clEnd, 0);
// below is used so format won't be removed using removeFormatting() by accident.
w.forgetFormatting();
} }
bool ArtistInfo::parse(std::string &data) bool ArtistInfo::parse(std::string &data)

View File

@@ -26,99 +26,139 @@
namespace NC {// namespace NC {//
Scrollpad::Scrollpad(size_t startx, Scrollpad::Scrollpad(size_t startx,
size_t starty, size_t starty,
size_t width, size_t width,
size_t height, size_t height,
const std::string &title, const std::string &title,
Color color, Color color,
Border border) Border border)
: Window(startx, starty, width, height, title, color, border), : Window(startx, starty, width, height, title, color, border),
m_beginning(0), m_beginning(0),
m_found_value_begin(-1), m_real_height(height)
m_found_value_end(-1),
m_real_height(height)
{ {
} }
void Scrollpad::flush() void Scrollpad::flush()
{ {
m_real_height = 1; recreate(m_width, m_height);
std::wstring s = m_buffer.str(); auto &w = static_cast<Window &>(*this);
const auto &s = m_buffer.str();
const auto &ps = m_buffer.properties();
auto p = ps.begin();
auto old_p = p;
int x, y;
size_t i = 0, old_i;
size_t x = 0; auto load_properties = [&]() {
int x_pos = 0; for (; p != ps.end() && p->position() == i; ++p)
int space_pos = 0; w << *p;
};
for (size_t i = 0; i < s.length(); ++i) auto write_whitespace = [&]() {
{ for (; i < s.length() && iswspace(s[i]); ++i)
x += s[i] != '\t' ? wcwidth(s[i]) : 8-x%8; // tab size
if (s[i] == ' ') // if space, remember its position;
{ {
space_pos = i; load_properties();
x_pos = x; w << s[i];
} }
};
if (x >= m_width) auto write_word = [&]() {
for (; i < s.length() && !iswspace(s[i]); ++i)
{ {
// if line is over, there was at least one space in this line and we are in the middle of the word, restore position to last known space and make it EOL load_properties();
if (space_pos > 0 && (s[i] != ' ' || s[i+1] != ' ')) w << s[i];
}
};
auto write_buffer = [&](bool generate_height_only) -> size_t {
int new_y;
size_t height = 1;
i = 0;
p = ps.begin();
y = getY();
while (true)
{
// write all whitespaces.
write_whitespace();
// if we are generating height, check difference
// between previous Y coord and current one and
// update height accordingly.
if (generate_height_only)
{ {
i = space_pos; new_y = getY();
x = x_pos; height += new_y - y;
s[i] = '\n'; y = new_y;
}
if (i == s.length())
break;
// save current string position state and get current
// coordinates as we are before the beginning of a word.
old_i = i;
old_p = p;
x = getX();
y = getY();
write_word();
// get new Y coord to see if word overflew into next line.
new_y = getY();
if (new_y != y)
{
if (generate_height_only)
{
// if it did, let's update height...
++height;
}
else
{
// ...or go to old coordinates, erase
// part of the string from previous line...
goToXY(x, y);
wclrtoeol(m_window);
}
// ...start at the beginning of next line...
++y;
goToXY(0, y);
i = old_i;
p = old_p;
// ...write this word again...
write_word();
if (generate_height_only)
{
// ... and check for potential
// difference in Y coordinates again.
new_y = getY();
height += new_y - y;
}
}
if (i == s.length())
break;
if (generate_height_only)
{
// move to the first line, since when we do
// generation, m_real_height = m_height and we
// don't have many lines to use.
goToXY(getX(), 0);
y = 0;
} }
} }
return height;
};
if (x >= m_width || s[i] == '\n') m_real_height = std::max(write_buffer(true), m_height);
{
m_real_height++;
x = 0;
space_pos = 0;
}
}
m_real_height = std::max(m_height, m_real_height);
recreate(m_width, m_real_height); recreate(m_width, m_real_height);
// print our modified string write_buffer(false);
std::swap(s, m_buffer.m_string);
static_cast<Window &>(*this) << m_buffer;
// restore original one
std::swap(s, m_buffer.m_string);
}
bool Scrollpad::setFormatting(short val_b, const std::wstring &s, short val_e, bool case_sensitive, bool for_each)
{
bool result = m_buffer.setFormatting(val_b, s, val_e, case_sensitive, for_each);
if (result)
{
m_found_for_each = for_each;
m_found_case_sensitive = case_sensitive;
m_found_value_begin = val_b;
m_found_value_end = val_e;
m_found_pattern = s;
}
else
forgetFormatting();
return result;
}
void Scrollpad::forgetFormatting()
{
m_found_value_begin = -1;
m_found_value_end = -1;
m_found_pattern.clear();
}
void Scrollpad::removeFormatting()
{
if (m_found_value_begin >= 0 && m_found_value_end >= 0)
m_buffer.removeFormatting(m_found_value_begin, m_found_pattern, m_found_value_end, m_found_case_sensitive, m_found_for_each);
} }
void Scrollpad::refresh() void Scrollpad::refresh()
{ {
assert(m_real_height >= m_real_height); assert(m_real_height >= m_height);
size_t max_beginning = m_real_height - m_height; size_t max_beginning = m_real_height - m_height;
m_beginning = std::min(m_beginning, max_beginning); m_beginning = std::min(m_beginning, max_beginning);
prefresh(m_window, m_beginning, 0, m_start_y, m_start_x, m_start_y+m_height-1, m_start_x+m_width-1); prefresh(m_window, m_beginning, 0, m_start_y, m_start_x, m_start_y+m_height-1, m_start_x+m_width-1);
@@ -183,7 +223,6 @@ void Scrollpad::clear()
m_window = newpad(m_height, m_width); m_window = newpad(m_height, m_width);
setTimeout(m_window_timeout); setTimeout(m_window_timeout);
setColor(m_color, m_bg_color); setColor(m_color, m_bg_color);
forgetFormatting();
keypad(m_window, 1); keypad(m_window, 1);
} }

View File

@@ -26,86 +26,41 @@
namespace NC {// namespace NC {//
/// Scrollpad is specialized window that can hold large portion of text and /// Scrollpad is specialized window that holds large portions of text and
/// supports scrolling if the amount of it is bigger than the window area. /// supports scrolling if the amount of it is bigger than the window area.
struct Scrollpad: public Window struct Scrollpad: public Window
{ {
Scrollpad() { } Scrollpad() { }
/// Constructs an empty scrollpad with given parameters
/// @param startx X position of left upper corner of constructed window
/// @param starty Y position of left upper corner of constructed window
/// @param width width of constructed window
/// @param height height of constructed window
/// @param title title of constructed window
/// @param color base color of constructed window
/// @param border border of constructed window
Scrollpad(size_t startx, size_t starty, size_t width, size_t height, Scrollpad(size_t startx, size_t starty, size_t width, size_t height,
const std::string &title, Color color, Border border); const std::string &title, Color color, Border border);
const std::wstring &buffer() { return m_buffer.str(); }
/// Prints the text stored in internal buffer to window. Note that
/// all changes that has been made for text stored in scrollpad won't
/// be visible until one invokes this function
void flush(); void flush();
/// Searches for given string in text and sets format/color at the
/// beginning and end of it using val_b and val_e flags accordingly
/// @param val_b flag set at the beginning of found occurence of string
/// @param s string that function seaches for
/// @param val_e flag set at the end of found occurence of string
/// @param case_sensitive indicates whether algorithm should care about case sensitivity
/// @param for_each indicates whether function searches through whole text and sets
/// given format for all occurences of given string or stops after first occurence
/// @return true if at least one occurence of the string was found, false otherwise
/// @see BasicBuffer::setFormatting()
bool setFormatting(short val_b, const std::wstring &s,
short val_e, bool case_sensitive, bool for_each = 1);
/// Removes all format flags and colors from stored text
void forgetFormatting();
/// Removes all format flags and colors that was applied
/// by the most recent call to setFormatting() function
/// @see setFormatting()
/// @see BasicBuffer::removeFormatting()
void removeFormatting();
/// @return text stored in internal buffer
///
const std::wstring &content() { return m_buffer.str(); }
/// Refreshes the window
/// @see Window::refresh()
///
virtual void refresh() OVERRIDE;
/// Scrolls by given amount of lines
/// @param where indicates where exactly one wants to go
/// @see Window::scroll()
///
virtual void scroll(Scroll where) OVERRIDE;
/// Resizes the window
/// @param new_width new window's width
/// @param new_height new window's height
/// @see Window::resize()
///
virtual void resize(size_t new_width, size_t new_height) OVERRIDE;
/// Cleares the content of scrollpad
/// @see Window::clear()
///
virtual void clear() OVERRIDE;
/// Sets starting position to the beginning
///
void reset(); void reset();
/// Template function that redirects all data passed template <typename PropertyT>
/// to the scrollpad window to its internal buffer bool setProperties(PropertyT begin, const std::wstring &ws, PropertyT end, size_t id = -2)
/// @param obj any object that has ostream &operator<<() defined {
/// @return reference to itself bool success = false;
/// for (size_t i = 0; (i = m_buffer.str().find(ws, i)) != std::string::npos;)
{
success = true;
m_buffer.setProperty(i, begin, id);
i += ws.length();
m_buffer.setProperty(i, end, id);
}
return success;
}
void removeProperties(size_t id = -2) { m_buffer.removeProperties(id); }
virtual void refresh() OVERRIDE;
virtual void scroll(Scroll where) OVERRIDE;
virtual void resize(size_t new_width, size_t new_height) OVERRIDE;
virtual void clear() OVERRIDE;
template <typename T> Scrollpad &operator<<(const T &obj) template <typename T> Scrollpad &operator<<(const T &obj)
{ {
m_buffer << obj; m_buffer << obj;
@@ -117,13 +72,6 @@ private:
WBuffer m_buffer; WBuffer m_buffer;
size_t m_beginning; size_t m_beginning;
bool m_found_for_each;
bool m_found_case_sensitive;
short m_found_value_begin;
short m_found_value_end;
std::wstring m_found_pattern;
size_t m_real_height; size_t m_real_height;
}; };

View File

@@ -21,117 +21,122 @@
#ifndef NCMPCPP_STRBUFFER_H #ifndef NCMPCPP_STRBUFFER_H
#define NCMPCPP_STRBUFFER_H #define NCMPCPP_STRBUFFER_H
#include <list> #include <set>
#include "utility/numeric_conversions.h" #include "utility/numeric_conversions.h"
#include "utility/wide_string.h" #include "utility/wide_string.h"
#include "window.h" #include "window.h"
namespace NC {// namespace NC {//
/// Buffer template class that can store text along with its /// Buffer template class that stores text
/// format attributes. The content can be easily printed to /// along with its properties (colors/formatting).
/// window or taken as raw string at any time.
template <typename CharT> class BasicBuffer template <typename CharT> class BasicBuffer
{ {
friend struct Scrollpad; struct Property
/// Struct used for storing information about
/// one color/format flag along with its position
struct FormatPos
{ {
size_t Position; enum class Type { Color, Format };
short Value;
bool operator<(const FormatPos &f) Property(size_t position_, NC::Color color_, int id_)
: m_type(Type::Color), m_position(position_), m_color(color_), m_id(id_) { }
Property(size_t position_, NC::Format format_, int id_)
: m_type(Type::Format), m_position(position_), m_format(format_), m_id(id_) { }
size_t position() const { return m_position; }
size_t id() const { return m_id; }
bool operator<(const Property &rhs) const
{ {
return Position < f.Position; if (m_position != rhs.m_position)
return m_position < rhs.m_position;
return m_id < rhs.m_id;
} }
bool operator==(const FormatPos &f) friend Window &operator<<(Window &w, const Property &p)
{ {
return Position == f.Position && Value == f.Value; switch (p.m_type)
{
case Type::Color:
w << p.m_color;
break;
case Type::Format:
w << p.m_format;
break;
}
return w;
} }
private:
Type m_type;
size_t m_position;
Color m_color;
Format m_format;
size_t m_id;
}; };
/// Internal buffer for storing raw text
std::basic_string<CharT> m_string;
/// List used for storing formatting informations
std::list<FormatPos> m_format;
public: public:
/// Constructs an empty buffer typedef std::basic_string<CharT> StringType;
typedef std::set<Property> Properties;
BasicBuffer() { } BasicBuffer() { }
/// Constructs a buffer from the existed one const StringType &str() const { return m_string; }
/// @param b copied buffer const Properties &properties() const { return m_properties; }
BasicBuffer(const BasicBuffer &b);
/// @return raw content of the buffer without formatting informations template <typename PropertyT>
const std::basic_string<CharT> &str() const; void setProperty(size_t position, PropertyT property, size_t id = -1)
{
m_properties.insert(Property(position, property, id));
}
/// Searches for given string in buffer and sets format/color at the template <typename PropertyT>
/// beginning and end of it using val_b and val_e flags accordingly bool removeProperty(size_t position, PropertyT property, size_t id = -1)
/// @param val_b flag set at the beginning of found occurence of string {
/// @param s string that function seaches for auto it = m_properties.find(Property(position, property, id));
/// @param val_e flag set at the end of found occurence of string bool found = it != m_properties.end();
/// @param case_sensitive indicates whether algorithm should care about case sensitivity if (found)
/// @param for_each indicates whether function searches through whole buffer and sets m_properties.erase(it);
/// the format for all occurences of given string or stops after the first one return found;
/// @return true if at least one occurence of the string was found, false otherwise }
bool setFormatting(short val_b, std::basic_string<CharT> s, short val_e,
bool case_sensitive, bool for_each = 1);
/// Searches for given string in buffer and removes given void removeProperties(size_t id = -1)
/// format/color from the beginning and end of its occurence {
/// @param val_b flag to be removed from the beginning of the string auto it = m_properties.begin();
/// @param s string that function seaches for while (it != m_properties.end())
/// @param val_e flag to be removed from the end of the string {
/// @param case_sensitive indicates whether algorithm should care about case sensitivity if (it->id() == id)
/// @param for_each indicates whether function searches through whole buffer and removes m_properties.erase(it++);
/// given format from all occurences of given string or stops after the first one else
void removeFormatting(short val_b, std::basic_string<CharT> pattern, short val_e, ++it;
bool case_sensitive, bool for_each = 1); }
}
/// Removes all formating applied to string in buffer. void clear()
void removeFormatting(); {
m_string.clear();
/// Prints to window object given part of the string, loading all needed formatting info m_properties.clear();
/// and cleaning up after. The main goal of this function is to provide interface for }
/// colorful scrollers.
/// @param w window object that we want to print to
/// @param start_pos reference to start position of the string. note that this variable is
/// incremented by one after each call or set to 0 if end of string is reached
/// @param width width of the string to be printed
/// @param separator additional text to be placed between the end and the beginning of
/// the string
void write(Window &w, size_t &start_pos, size_t width,
const std::basic_string<CharT> &separator) const;
/// Clears the content of the buffer and its formatting informations
void clear();
BasicBuffer<CharT> &operator<<(int n) BasicBuffer<CharT> &operator<<(int n)
{ {
m_string += intTo< std::basic_string<CharT> >::apply(n); m_string += intTo<StringType>::apply(n);
return *this; return *this;
} }
BasicBuffer<CharT> &operator<<(long int n) BasicBuffer<CharT> &operator<<(long int n)
{ {
m_string += longIntTo< std::basic_string<CharT> >::apply(n); m_string += longIntTo<StringType>::apply(n);
return *this; return *this;
} }
BasicBuffer<CharT> &operator<<(unsigned int n) BasicBuffer<CharT> &operator<<(unsigned int n)
{ {
m_string += unsignedIntTo< std::basic_string<CharT> >::apply(n); m_string += unsignedIntTo<StringType>::apply(n);
return *this; return *this;
} }
BasicBuffer<CharT> &operator<<(unsigned long int n) BasicBuffer<CharT> &operator<<(unsigned long int n)
{ {
m_string += unsignedLongIntTo< std::basic_string<CharT> >::apply(n); m_string += unsignedLongIntTo<StringType>::apply(n);
return *this; return *this;
} }
@@ -153,151 +158,59 @@ public:
return *this; return *this;
} }
BasicBuffer<CharT> &operator<<(const std::basic_string<CharT> &s) BasicBuffer<CharT> &operator<<(const StringType &s)
{ {
m_string += s; m_string += s;
return *this; return *this;
} }
/// Handles colors BasicBuffer<CharT> &operator<<(Color color)
/// @return reference to itself
BasicBuffer<CharT> &operator<<(Color color);
/// Handles format flags
/// @return reference to itself
BasicBuffer<CharT> &operator<<(Format f);
/// Handles copying one buffer to another using operator<<()
/// @param buf buffer to be copied
/// @return reference to itself
BasicBuffer<CharT> &operator<<(const BasicBuffer<CharT> &buf);
/// Friend operator that handles printing
/// the content of buffer to window object
friend Window &operator<<(Window &w, const BasicBuffer<CharT> &buf)
{ {
const std::basic_string<CharT> &s = buf.m_string; setProperty(m_string.size(), color);
if (buf.m_format.empty()) return *this;
w << s;
else
{
std::basic_string<CharT> tmp;
auto b = buf.m_format.begin(), e = buf.m_format.end();
for (size_t i = 0; i < s.length() || b != e; ++i)
{
while (b != e && i == b->Position)
{
if (!tmp.empty())
{
w << tmp;
tmp.clear();
}
buf.loadAttribute(w, b->Value);
b++;
}
tmp += s[i];
}
if (!tmp.empty())
w << tmp;
}
return w;
} }
BasicBuffer<CharT> &operator<<(Format format)
{
setProperty(m_string.size(), format);
return *this;
}
void write(GNUC_UNUSED Window &w, GNUC_UNUSED size_t &start_pos, GNUC_UNUSED size_t width,
GNUC_UNUSED const std::basic_string<CharT> &separator) const { }
private: private:
/// Loads an attribute to given window object StringType m_string;
/// @param w window object we want to load attribute to Properties m_properties;
/// @param value value of attribute to be loaded
void loadAttribute(Window &w, short value) const;
}; };
/// Standard buffer that uses narrow characters
typedef BasicBuffer<char> Buffer; typedef BasicBuffer<char> Buffer;
/// Standard buffer that uses wide characters
typedef BasicBuffer<wchar_t> WBuffer; typedef BasicBuffer<wchar_t> WBuffer;
template <typename CharT> BasicBuffer<CharT>::BasicBuffer(const BasicBuffer &b) template <typename CharT>
: m_string(b.m_string), m_format(b.m_format) { } Window operator<<(Window &w, const BasicBuffer<CharT> &buffer)
template <typename CharT> const std::basic_string<CharT> &BasicBuffer<CharT>::str() const
{ {
return m_string; if (buffer.properties().empty())
} w << buffer.str();
template <typename CharT> bool BasicBuffer<CharT>::setFormatting(
short val_b,
std::basic_string<CharT> s,
short val_e,
bool case_sensitive,
bool for_each
)
{
if (s.empty())
return false;
bool result = false;
std::basic_string<CharT> base;
if (case_sensitive)
base = m_string;
else else
{ {
base = lowercase(m_string); auto &s = buffer.str();
s = lowercase(s); auto &ps = buffer.properties();
auto p = ps.begin();
for (size_t i = 0; i < s.size(); ++i)
{
for (; p != ps.end() && p->position() == i; ++p)
w << *p;
w << s[i];
}
// load remaining properties
for (; p != ps.end(); ++p)
w << *p;
} }
FormatPos fp; return w;
for (size_t i = base.find(s); i != std::basic_string<CharT>::npos; i = base.find(s, i))
{
result = true;
fp.Value = val_b;
fp.Position = i;
m_format.push_back(fp);
i += s.length();
fp.Value = val_e;
fp.Position = i;
m_format.push_back(fp);
if (!for_each)
break;
}
m_format.sort();
return result;
} }
template <typename CharT> void BasicBuffer<CharT>::removeFormatting( /*
short val_b,
std::basic_string<CharT> pattern,
short val_e,
bool case_sensitive,
bool for_each
)
{
if (pattern.empty())
return;
std::basic_string<CharT> base;
if (case_sensitive)
base = m_string;
else
{
base = lowercase(base);
pattern = lowercase(pattern);
}
FormatPos fp;
for (size_t i = base.find(pattern); i != std::basic_string<CharT>::npos; i = base.find(pattern, i))
{
fp.Value = val_b;
fp.Position = i;
m_format.remove(fp);
i += pattern.length();
fp.Value = val_e;
fp.Position = i;
m_format.remove(fp);
if (!for_each)
break;
}
}
template <typename CharT> void BasicBuffer<CharT>::removeFormatting()
{
m_format.clear();
}
template <typename CharT> void BasicBuffer<CharT>::write( template <typename CharT> void BasicBuffer<CharT>::write(
Window &w, Window &w,
@@ -314,8 +227,8 @@ template <typename CharT> void BasicBuffer<CharT>::write(
s += separator; s += separator;
len = 0; len = 0;
auto lb = m_format.begin(); auto lb = m_properties.begin();
if (m_format.back().Position > start_pos) // if there is no attributes from current position, don't load them if (m_properties.back().Position > start_pos) // if there is no attributes from current position, don't load them
{ {
// load all attributes that are before start position // load all attributes that are before start position
for (; lb->Position < start_pos; ++lb) for (; lb->Position < start_pos; ++lb)
@@ -324,7 +237,7 @@ template <typename CharT> void BasicBuffer<CharT>::write(
for (size_t i = start_pos; i < s.length() && len < width; ++i) for (size_t i = start_pos; i < s.length() && len < width; ++i)
{ {
while (i == lb->Position && lb != m_format.end()) while (i == lb->Position && lb != m_properties.end())
{ {
loadAttribute(w, lb->Value); loadAttribute(w, lb->Value);
++lb; ++lb;
@@ -337,10 +250,10 @@ template <typename CharT> void BasicBuffer<CharT>::write(
start_pos = 0; start_pos = 0;
if (len < width) if (len < width)
lb = m_format.begin(); lb = m_properties.begin();
for (size_t i = 0; len < width; ++i) for (size_t i = 0; len < width; ++i)
{ {
while (i == lb->Position && lb != m_format.end()) while (i == lb->Position && lb != m_properties.end())
{ {
loadAttribute(w, lb->Value); loadAttribute(w, lb->Value);
++lb; ++lb;
@@ -350,52 +263,14 @@ template <typename CharT> void BasicBuffer<CharT>::write(
w << s[i]; w << s[i];
} }
// load all remained attributes to clean up // load all remained attributes to clean up
for (; lb != m_format.end(); ++lb) for (; lb != m_properties.end(); ++lb)
loadAttribute(w, lb->Value); loadAttribute(w, lb->Value);
} }
else else
w << *this; w << *this;
} }
template <typename CharT> void BasicBuffer<CharT>::clear() */
{
m_string.clear();
m_format.clear();
}
template <typename CharT> void BasicBuffer<CharT>::loadAttribute(Window &w, short value) const
{
if (value < fmtNone)
w << Color(value);
else
w << Format(value);
}
template <typename CharT> BasicBuffer<CharT> &BasicBuffer<CharT>::operator<<(Color color)
{
FormatPos f;
f.Position = m_string.length();
f.Value = color;
m_format.push_back(f);
return *this;
}
template <typename CharT> BasicBuffer<CharT> &BasicBuffer<CharT>::operator<<(Format f)
{
return operator<<(Color(f));
}
template <typename CharT> BasicBuffer<CharT> &BasicBuffer<CharT>::operator<<(const BasicBuffer<CharT> &buf)
{
size_t length = m_string.length();
m_string += buf.m_string;
std::list<FormatPos> tmp = buf.m_format;
if (length)
for (auto it = tmp.begin(); it != tmp.end(); ++it)
it->Position += length;
m_format.merge(tmp);
return *this;
}
} }