rewrite major part of strbuffer and Scrollpad::flush
This commit is contained in:
@@ -1970,8 +1970,8 @@ void Find::Run()
|
||||
|
||||
Statusbar::msg("Searching...");
|
||||
auto s = static_cast<Screen<NC::Scrollpad> *>(myScreen);
|
||||
s->main().removeFormatting();
|
||||
Statusbar::msg("%s", findme.empty() || s->main().setFormatting(NC::fmtReverse, ToWString(findme), NC::fmtReverseEnd, 0) ? "Done" : "No matching patterns found");
|
||||
s->main().removeProperties();
|
||||
Statusbar::msg("%s", findme.empty() || s->main().setProperties(NC::fmtReverse, ToWString(findme), NC::fmtReverseEnd) ? "Done" : "No matching patterns found");
|
||||
s->main().flush();
|
||||
}
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ void showSongs(NC::Menu<T> &menu, const MPD::Song &s, const ProxySongList &pl, c
|
||||
buf << " ";
|
||||
stringToBuffer(++it, line.end(), buf);
|
||||
if (discard_colors)
|
||||
buf.removeFormatting();
|
||||
buf.removeProperties();
|
||||
size_t x_off = menu.getWidth() - wideLength(ToWString(buf.str()));
|
||||
if (is_now_playing)
|
||||
x_off -= Config.now_playing_suffix_length;
|
||||
|
||||
@@ -104,10 +104,8 @@ bool ArtistInfo::checkArgs(const Args &args)
|
||||
|
||||
void ArtistInfo::colorizeOutput(NC::Scrollpad &w)
|
||||
{
|
||||
w.setFormatting(NC::fmtBold, L"\n\nSimilar artists:\n", NC::fmtBoldEnd, false);
|
||||
w.setFormatting(Config.color2, L"\n * ", NC::clEnd, true);
|
||||
// below is used so format won't be removed using removeFormatting() by accident.
|
||||
w.forgetFormatting();
|
||||
w.setProperties(NC::fmtBold, L"\n\nSimilar artists:\n", NC::fmtBoldEnd, 0);
|
||||
w.setProperties(Config.color2, L"\n * ", NC::clEnd, 0);
|
||||
}
|
||||
|
||||
bool ArtistInfo::parse(std::string &data)
|
||||
|
||||
@@ -26,99 +26,139 @@
|
||||
namespace NC {//
|
||||
|
||||
Scrollpad::Scrollpad(size_t startx,
|
||||
size_t starty,
|
||||
size_t width,
|
||||
size_t height,
|
||||
const std::string &title,
|
||||
Color color,
|
||||
Border border)
|
||||
: Window(startx, starty, width, height, title, color, border),
|
||||
m_beginning(0),
|
||||
m_found_value_begin(-1),
|
||||
m_found_value_end(-1),
|
||||
m_real_height(height)
|
||||
size_t starty,
|
||||
size_t width,
|
||||
size_t height,
|
||||
const std::string &title,
|
||||
Color color,
|
||||
Border border)
|
||||
: Window(startx, starty, width, height, title, color, border),
|
||||
m_beginning(0),
|
||||
m_real_height(height)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
int x_pos = 0;
|
||||
int space_pos = 0;
|
||||
|
||||
for (size_t i = 0; i < s.length(); ++i)
|
||||
{
|
||||
x += s[i] != '\t' ? wcwidth(s[i]) : 8-x%8; // tab size
|
||||
|
||||
if (s[i] == ' ') // if space, remember its position;
|
||||
auto load_properties = [&]() {
|
||||
for (; p != ps.end() && p->position() == i; ++p)
|
||||
w << *p;
|
||||
};
|
||||
auto write_whitespace = [&]() {
|
||||
for (; i < s.length() && iswspace(s[i]); ++i)
|
||||
{
|
||||
space_pos = i;
|
||||
x_pos = x;
|
||||
load_properties();
|
||||
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
|
||||
if (space_pos > 0 && (s[i] != ' ' || s[i+1] != ' '))
|
||||
load_properties();
|
||||
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;
|
||||
x = x_pos;
|
||||
s[i] = '\n';
|
||||
new_y = getY();
|
||||
height += new_y - y;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (x >= m_width || s[i] == '\n')
|
||||
{
|
||||
m_real_height++;
|
||||
x = 0;
|
||||
space_pos = 0;
|
||||
}
|
||||
}
|
||||
m_real_height = std::max(m_height, m_real_height);
|
||||
return height;
|
||||
};
|
||||
|
||||
m_real_height = std::max(write_buffer(true), m_height);
|
||||
recreate(m_width, m_real_height);
|
||||
// print our modified string
|
||||
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);
|
||||
write_buffer(false);
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
@@ -183,7 +223,6 @@ void Scrollpad::clear()
|
||||
m_window = newpad(m_height, m_width);
|
||||
setTimeout(m_window_timeout);
|
||||
setColor(m_color, m_bg_color);
|
||||
forgetFormatting();
|
||||
keypad(m_window, 1);
|
||||
}
|
||||
|
||||
|
||||
102
src/scrollpad.h
102
src/scrollpad.h
@@ -26,86 +26,41 @@
|
||||
|
||||
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.
|
||||
struct Scrollpad: public Window
|
||||
{
|
||||
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,
|
||||
const std::string &title, Color color, Border border);
|
||||
const std::string &title, Color color, Border border);
|
||||
|
||||
/// 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
|
||||
const std::wstring &buffer() { return m_buffer.str(); }
|
||||
|
||||
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();
|
||||
|
||||
/// Template function that redirects all data passed
|
||||
/// to the scrollpad window to its internal buffer
|
||||
/// @param obj any object that has ostream &operator<<() defined
|
||||
/// @return reference to itself
|
||||
///
|
||||
template <typename PropertyT>
|
||||
bool setProperties(PropertyT begin, const std::wstring &ws, PropertyT end, size_t id = -2)
|
||||
{
|
||||
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)
|
||||
{
|
||||
m_buffer << obj;
|
||||
@@ -117,13 +72,6 @@ private:
|
||||
WBuffer m_buffer;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
353
src/strbuffer.h
353
src/strbuffer.h
@@ -21,117 +21,122 @@
|
||||
#ifndef NCMPCPP_STRBUFFER_H
|
||||
#define NCMPCPP_STRBUFFER_H
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include "utility/numeric_conversions.h"
|
||||
#include "utility/wide_string.h"
|
||||
#include "window.h"
|
||||
|
||||
namespace NC {//
|
||||
|
||||
/// Buffer template class that can store text along with its
|
||||
/// format attributes. The content can be easily printed to
|
||||
/// window or taken as raw string at any time.
|
||||
/// Buffer template class that stores text
|
||||
/// along with its properties (colors/formatting).
|
||||
template <typename CharT> class BasicBuffer
|
||||
{
|
||||
friend struct Scrollpad;
|
||||
|
||||
/// Struct used for storing information about
|
||||
/// one color/format flag along with its position
|
||||
struct FormatPos
|
||||
struct Property
|
||||
{
|
||||
size_t Position;
|
||||
short Value;
|
||||
enum class Type { Color, Format };
|
||||
|
||||
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:
|
||||
/// Constructs an empty buffer
|
||||
typedef std::basic_string<CharT> StringType;
|
||||
typedef std::set<Property> Properties;
|
||||
|
||||
BasicBuffer() { }
|
||||
|
||||
/// Constructs a buffer from the existed one
|
||||
/// @param b copied buffer
|
||||
BasicBuffer(const BasicBuffer &b);
|
||||
const StringType &str() const { return m_string; }
|
||||
const Properties &properties() const { return m_properties; }
|
||||
|
||||
/// @return raw content of the buffer without formatting informations
|
||||
const std::basic_string<CharT> &str() const;
|
||||
template <typename PropertyT>
|
||||
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
|
||||
/// 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 buffer and sets
|
||||
/// the format for all occurences of given string or stops after the first one
|
||||
/// @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);
|
||||
template <typename PropertyT>
|
||||
bool removeProperty(size_t position, PropertyT property, size_t id = -1)
|
||||
{
|
||||
auto it = m_properties.find(Property(position, property, id));
|
||||
bool found = it != m_properties.end();
|
||||
if (found)
|
||||
m_properties.erase(it);
|
||||
return found;
|
||||
}
|
||||
|
||||
/// Searches for given string in buffer and removes given
|
||||
/// format/color from the beginning and end of its occurence
|
||||
/// @param val_b flag to be removed from the beginning of the string
|
||||
/// @param s string that function seaches for
|
||||
/// @param val_e flag to be removed from the end of the string
|
||||
/// @param case_sensitive indicates whether algorithm should care about case sensitivity
|
||||
/// @param for_each indicates whether function searches through whole buffer and removes
|
||||
/// given format from all occurences of given string or stops after the first one
|
||||
void removeFormatting(short val_b, std::basic_string<CharT> pattern, short val_e,
|
||||
bool case_sensitive, bool for_each = 1);
|
||||
void removeProperties(size_t id = -1)
|
||||
{
|
||||
auto it = m_properties.begin();
|
||||
while (it != m_properties.end())
|
||||
{
|
||||
if (it->id() == id)
|
||||
m_properties.erase(it++);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes all formating applied to string in buffer.
|
||||
void removeFormatting();
|
||||
|
||||
/// Prints to window object given part of the string, loading all needed formatting info
|
||||
/// 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();
|
||||
void clear()
|
||||
{
|
||||
m_string.clear();
|
||||
m_properties.clear();
|
||||
}
|
||||
|
||||
BasicBuffer<CharT> &operator<<(int n)
|
||||
{
|
||||
m_string += intTo< std::basic_string<CharT> >::apply(n);
|
||||
m_string += intTo<StringType>::apply(n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasicBuffer<CharT> &operator<<(long int n)
|
||||
{
|
||||
m_string += longIntTo< std::basic_string<CharT> >::apply(n);
|
||||
m_string += longIntTo<StringType>::apply(n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasicBuffer<CharT> &operator<<(unsigned int n)
|
||||
{
|
||||
m_string += unsignedIntTo< std::basic_string<CharT> >::apply(n);
|
||||
m_string += unsignedIntTo<StringType>::apply(n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasicBuffer<CharT> &operator<<(unsigned long int n)
|
||||
{
|
||||
m_string += unsignedLongIntTo< std::basic_string<CharT> >::apply(n);
|
||||
m_string += unsignedLongIntTo<StringType>::apply(n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -153,151 +158,59 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasicBuffer<CharT> &operator<<(const std::basic_string<CharT> &s)
|
||||
BasicBuffer<CharT> &operator<<(const StringType &s)
|
||||
{
|
||||
m_string += s;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Handles colors
|
||||
/// @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)
|
||||
BasicBuffer<CharT> &operator<<(Color color)
|
||||
{
|
||||
const std::basic_string<CharT> &s = buf.m_string;
|
||||
if (buf.m_format.empty())
|
||||
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;
|
||||
setProperty(m_string.size(), color);
|
||||
return *this;
|
||||
}
|
||||
|
||||
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:
|
||||
/// Loads an attribute to given window object
|
||||
/// @param w window object we want to load attribute to
|
||||
/// @param value value of attribute to be loaded
|
||||
void loadAttribute(Window &w, short value) const;
|
||||
StringType m_string;
|
||||
Properties m_properties;
|
||||
};
|
||||
|
||||
/// Standard buffer that uses narrow characters
|
||||
typedef BasicBuffer<char> Buffer;
|
||||
|
||||
/// Standard buffer that uses wide characters
|
||||
typedef BasicBuffer<wchar_t> WBuffer;
|
||||
|
||||
template <typename CharT> BasicBuffer<CharT>::BasicBuffer(const BasicBuffer &b)
|
||||
: m_string(b.m_string), m_format(b.m_format) { }
|
||||
|
||||
template <typename CharT> const std::basic_string<CharT> &BasicBuffer<CharT>::str() const
|
||||
template <typename CharT>
|
||||
Window operator<<(Window &w, const BasicBuffer<CharT> &buffer)
|
||||
{
|
||||
return m_string;
|
||||
}
|
||||
|
||||
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;
|
||||
if (buffer.properties().empty())
|
||||
w << buffer.str();
|
||||
else
|
||||
{
|
||||
base = lowercase(m_string);
|
||||
s = lowercase(s);
|
||||
auto &s = buffer.str();
|
||||
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;
|
||||
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;
|
||||
return w;
|
||||
}
|
||||
|
||||
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(
|
||||
Window &w,
|
||||
@@ -314,8 +227,8 @@ template <typename CharT> void BasicBuffer<CharT>::write(
|
||||
s += separator;
|
||||
len = 0;
|
||||
|
||||
auto lb = m_format.begin();
|
||||
if (m_format.back().Position > start_pos) // if there is no attributes from current position, don't load them
|
||||
auto lb = m_properties.begin();
|
||||
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
|
||||
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)
|
||||
{
|
||||
while (i == lb->Position && lb != m_format.end())
|
||||
while (i == lb->Position && lb != m_properties.end())
|
||||
{
|
||||
loadAttribute(w, lb->Value);
|
||||
++lb;
|
||||
@@ -337,10 +250,10 @@ template <typename CharT> void BasicBuffer<CharT>::write(
|
||||
start_pos = 0;
|
||||
|
||||
if (len < width)
|
||||
lb = m_format.begin();
|
||||
lb = m_properties.begin();
|
||||
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);
|
||||
++lb;
|
||||
@@ -350,52 +263,14 @@ template <typename CharT> void BasicBuffer<CharT>::write(
|
||||
w << s[i];
|
||||
}
|
||||
// load all remained attributes to clean up
|
||||
for (; lb != m_format.end(); ++lb)
|
||||
for (; lb != m_properties.end(); ++lb)
|
||||
loadAttribute(w, lb->Value);
|
||||
}
|
||||
else
|
||||
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;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user