visualizer: refresh screen immediately after clearing it
[ncmpcpp.git] / src / strbuffer.h
blob2cb798542d0234343be17594b0c2b04e50d78f5c
1 /***************************************************************************
2 * Copyright (C) 2008-2010 by Andrzej Rybczak *
3 * electricityispower@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
21 #ifndef _STRBUFFER_H
22 #define _STRBUFFER_H
24 #include "tolower.h"
25 #include "window.h"
27 #include <sstream>
28 #include <list>
30 namespace NCurses
32 /// Buffer template class that can store text along with its
33 /// format attributes. The content can be easily printed to
34 /// window or taken as raw string at any time.
35 ///
36 template <typename C> class basic_buffer
38 /// Struct used for storing information about
39 /// one color/format flag along with its position
40 ///
41 struct FormatPos
43 size_t Position;
44 short Value;
46 bool operator<(const FormatPos &f)
48 return Position < f.Position;
51 bool operator==(const FormatPos &f)
53 return Position == f.Position && Value == f.Value;
57 /// Internal buffer for storing raw text
58 ///
59 std::basic_ostringstream<C> itsString;
61 /// List used for storing formatting informations
62 ///
63 std::list<FormatPos> itsFormat;
65 /// Pointer to temporary string
66 /// @see SetTemp()
67 ///
68 std::basic_string<C> *itsTempString;
70 public:
71 /// Constructs an empty buffer
72 ///
73 basic_buffer() : itsTempString(0) { }
75 /// Constructs a buffer from the existed one
76 /// @param b copied buffer
77 ///
78 basic_buffer(const basic_buffer &b);
80 /// @return raw content of the buffer without formatting informations
81 ///
82 std::basic_string<C> Str() const;
84 /// Searches for given string in buffer and sets format/color at the
85 /// beginning and end of it using val_b and val_e flags accordingly
86 /// @param val_b flag set at the beginning of found occurence of string
87 /// @param s string that function seaches for
88 /// @param val_e flag set at the end of found occurence of string
89 /// @param case_sensitive indicates whether algorithm should care about case sensitivity
90 /// @param for_each indicates whether function searches through whole buffer and sets
91 /// the format for all occurences of given string or stops after the first one
92 /// @return true if at least one occurence of the string was found, false otherwise
93 ///
94 bool SetFormatting(short val_b, std::basic_string<C> s, short val_e,
95 bool case_sensitive, bool for_each = 1);
97 /// Searches for given string in buffer and removes given
98 /// format/color from the beginning and end of its occurence
99 /// @param val_b flag to be removed from the beginning of the string
100 /// @param s string that function seaches for
101 /// @param val_e flag to be removed from the end of the string
102 /// @param case_sensitive indicates whether algorithm should care about case sensitivity
103 /// @param for_each indicates whether function searches through whole buffer and removes
104 /// given format from all occurences of given string or stops after the first one
106 void RemoveFormatting(short val_b, std::basic_string<C> pattern, short val_e,
107 bool case_sensitive, bool for_each = 1);
109 /// Removes all formating applied to string in buffer.
111 void RemoveFormatting();
113 /// Sets the pointer to string, that will be passed in operator<<() to window
114 /// object instead of the internal buffer. This is useful if you took the content
115 /// of the buffer, modified it somehow and want to print the modified version instead
116 /// of the original one, but with the original formatting informations. Note that after
117 /// you're done with the printing etc., this pointer has to be set to null.
118 /// @param tmp address of the temporary string
120 void SetTemp(std::basic_string<C> *tmp);
122 /// Prints to window object given part of the string, loading all needed formatting info
123 /// and cleaning up after. The main goal of this function is to provide interface for
124 /// colorful scrollers.
125 /// @param w window object that we want to print to
126 /// @param start_pos reference to start position of the string. note that this variable is
127 /// incremented by one after each call or set to 0 if end of string is reached
128 /// @param width width of the string to be printed
129 /// @param separator additional text to be placed between the end and the beginning of
130 /// the string
132 void Write(Window &w, size_t &start_pos, size_t width,
133 const std::basic_string<C> &separator) const;
135 /// Clears the content of the buffer and its formatting informations
137 void Clear();
139 /// @param t any object that has defined ostream &operator<<()
140 /// @return reference to itself
142 template <typename T> basic_buffer<C> &operator<<(const T &t)
144 itsString << t;
145 return *this;
148 /// Handles colors
149 /// @return reference to itself
151 basic_buffer<C> &operator<<(Color color);
153 /// Handles format flags
154 /// @return reference to itself
156 basic_buffer<C> &operator<<(Format f);
158 /// Handles copying one buffer to another using operator<<()
159 /// @param buf buffer to be copied
160 /// @return reference to itself
162 basic_buffer<C> &operator<<(const basic_buffer<C> &buf);
164 /// Friend operator, that handles printing
165 /// the content of buffer to window object
166 friend Window &operator<< <>(Window &, const basic_buffer<C> &);
168 private:
169 /// Loads an attribute to given window object
170 /// @param w window object we want to load attribute to
171 /// @param value value of attribute to be loaded
173 void LoadAttribute(Window &w, short value) const;
176 /// Standard buffer that uses narrow characters
178 typedef basic_buffer<char> Buffer;
180 /// Standard buffer that uses wide characters
182 typedef basic_buffer<wchar_t> WBuffer;
185 template <typename C> NCurses::basic_buffer<C>::basic_buffer(const basic_buffer &b) : itsFormat(b.itsFormat),
186 itsTempString(b.itsTempString)
188 itsString << b.itsString.str();
191 template <typename C> std::basic_string<C> NCurses::basic_buffer<C>::Str() const
193 return itsString.str();
196 template <typename C> bool NCurses::basic_buffer<C>::SetFormatting( short val_b,
197 std::basic_string<C> s,
198 short val_e,
199 bool case_sensitive,
200 bool for_each
203 if (s.empty())
204 return false;
205 bool result = false;
206 std::basic_string<C> base = itsString.str();
207 if (!case_sensitive)
209 ToLower(s);
210 ToLower(base);
212 FormatPos fp;
213 for (size_t i = base.find(s); i != std::basic_string<C>::npos; i = base.find(s, i))
215 result = true;
216 fp.Value = val_b;
217 fp.Position = i;
218 itsFormat.push_back(fp);
219 i += s.length();
220 fp.Value = val_e;
221 fp.Position = i;
222 itsFormat.push_back(fp);
223 if (!for_each)
224 break;
226 itsFormat.sort();
227 return result;
230 template <typename C> void NCurses::basic_buffer<C>::RemoveFormatting( short val_b,
231 std::basic_string<C> pattern,
232 short val_e,
233 bool case_sensitive,
234 bool for_each
237 if (pattern.empty())
238 return;
239 std::basic_string<C> base = itsString.str();
240 if (!case_sensitive)
242 ToLower(pattern);
243 ToLower(base);
245 FormatPos fp;
246 for (size_t i = base.find(pattern); i != std::basic_string<C>::npos; i = base.find(pattern, i))
248 fp.Value = val_b;
249 fp.Position = i;
250 itsFormat.remove(fp);
251 i += pattern.length();
252 fp.Value = val_e;
253 fp.Position = i;
254 itsFormat.remove(fp);
255 if (!for_each)
256 break;
260 template <typename C> void NCurses::basic_buffer<C>::RemoveFormatting()
262 itsFormat.clear();
265 template <typename C> void NCurses::basic_buffer<C>::SetTemp(std::basic_string<C> *tmp)
267 itsTempString = tmp;
270 template <typename C> void NCurses::basic_buffer<C>::Write( Window &w,
271 size_t &start_pos,
272 size_t width,
273 const std::basic_string<C> &separator
274 ) const
276 std::basic_string<C> s = itsString.str();
277 size_t len = Window::Length(s);
279 if (len > width)
281 s += separator;
282 len = 0;
284 typename std::list<typename NCurses::basic_buffer<C>::FormatPos>::const_iterator lb = itsFormat.begin();
285 if (itsFormat.back().Position > start_pos) // if there is no attributes from current position, don't load them
287 // load all attributes that are before start position
288 for (; lb->Position < start_pos; ++lb)
289 LoadAttribute(w, lb->Value);
292 for (size_t i = start_pos; i < s.length() && len < width; ++i)
294 while (i == lb->Position && lb != itsFormat.end())
296 LoadAttribute(w, lb->Value);
297 ++lb;
299 if ((len += wcwidth(s[i])) > width)
300 break;
301 w << s[i];
303 if (++start_pos >= s.length())
304 start_pos = 0;
306 if (len < width)
307 lb = itsFormat.begin();
308 for (size_t i = 0; len < width; ++i)
310 while (i == lb->Position && lb != itsFormat.end())
312 LoadAttribute(w, lb->Value);
313 ++lb;
315 if ((len += wcwidth(s[i])) > width)
316 break;
317 w << s[i];
319 // load all remained attributes to clean up
320 for (; lb != itsFormat.end(); ++lb)
321 LoadAttribute(w, lb->Value);
323 else
324 w << *this;
327 template <typename C> void NCurses::basic_buffer<C>::Clear()
329 itsString.str(std::basic_string<C>());
330 itsFormat.clear();
333 template <typename C> void NCurses::basic_buffer<C>::LoadAttribute(Window &w, short value) const
335 if (value < NCurses::fmtNone)
336 w << NCurses::Color(value);
337 else
338 w << NCurses::Format(value);
341 template <typename C> NCurses::basic_buffer<C> &NCurses::basic_buffer<C>::operator<<(Color color)
343 FormatPos f;
344 f.Position = itsString.str().length();
345 f.Value = color;
346 itsFormat.push_back(f);
347 return *this;
350 template <typename C> NCurses::basic_buffer<C> &NCurses::basic_buffer<C>::operator<<(Format f)
352 return operator<<(Color(f));
355 template <typename C> NCurses::basic_buffer<C> &NCurses::basic_buffer<C>::operator<<(const NCurses::basic_buffer<C> &buf)
357 size_t len = itsString.str().length();
358 itsString << buf.itsString.str();
359 std::list<FormatPos> tmp = buf.itsFormat;
360 if (len)
361 for (typename std::list<typename NCurses::basic_buffer<C>::FormatPos>::iterator it = tmp.begin(); it != tmp.end(); ++it)
362 it->Position += len;
363 itsFormat.merge(tmp);
364 return *this;
367 template <typename C> NCurses::Window &operator<<(NCurses::Window &w, const NCurses::basic_buffer<C> &buf)
369 const std::basic_string<C> &s = buf.itsTempString ? *buf.itsTempString : buf.itsString.str();
370 if (buf.itsFormat.empty())
372 w << s;
374 else
376 std::basic_string<C> tmp;
377 typename std::list<typename NCurses::basic_buffer<C>::FormatPos>::const_iterator b = buf.itsFormat.begin();
378 typename std::list<typename NCurses::basic_buffer<C>::FormatPos>::const_iterator e = buf.itsFormat.end();
379 for (size_t i = 0; i < s.length() || b != e; ++i)
381 while (b != e && i == b->Position)
383 if (!tmp.empty())
385 w << tmp;
386 tmp.clear();
388 buf.LoadAttribute(w, b->Value);
389 b++;
391 if (i < s.length())
392 tmp += s[i];
394 if (!tmp.empty())
395 w << tmp;
397 return w;
400 #endif