1 /***************************************************************************
2 * Copyright (C) 2008-2017 by Andrzej Rybczak *
3 * electricityispower@gmail.com *
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. *
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. *
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 ***************************************************************************/
22 #include <boost/regex.hpp>
25 #include "curses/scrollpad.h"
26 #include "utility/storage_kind.h"
30 template <typename BeginT
, typename EndT
>
31 bool regexSearch(NC::Buffer
&buf
, const BeginT
&begin
, const std::string
&ws
,
32 const EndT
&end
, boost::regex::flag_type flags
, size_t id
)
35 boost::regex
rx(ws
, flags
);
36 auto first
= boost::sregex_iterator(buf
.str().begin(), buf
.str().end(), rx
);
37 auto last
= boost::sregex_iterator();
38 bool success
= first
!= last
;
39 for (; first
!= last
; ++first
)
41 buf
.addProperty(first
->position(), begin
, id
);
42 buf
.addProperty(first
->position() + first
->length(), end
, id
);
45 } catch (boost::bad_expression
&e
) {
46 std::cerr
<< "regexSearch: bad_expression: " << e
.what() << "\n";
55 Scrollpad::Scrollpad(size_t startx
,
59 const std::string
&title
,
62 : Window(startx
, starty
, width
, height
, title
, color
, border
),
68 void Scrollpad::refresh()
70 assert(m_real_height
>= m_height
);
71 size_t max_beginning
= m_real_height
- m_height
;
72 m_beginning
= std::min(m_beginning
, max_beginning
);
73 prefresh(m_window
, m_beginning
, 0, m_start_y
, m_start_x
, m_start_y
+m_height
-1, m_start_x
+m_width
-1);
76 void Scrollpad::resize(size_t new_width
, size_t new_height
)
78 adjustDimensions(new_width
, new_height
);
79 recreate(new_width
, new_height
);
83 void Scrollpad::scroll(Scroll where
)
85 assert(m_real_height
>= m_height
);
86 size_t max_beginning
= m_real_height
- m_height
;
97 if (m_beginning
< max_beginning
)
103 if (m_beginning
> m_height
)
104 m_beginning
-= m_height
;
109 case Scroll::PageDown
:
111 m_beginning
= std::min(m_beginning
+ m_height
, max_beginning
);
121 m_beginning
= max_beginning
;
127 void Scrollpad::clear()
129 m_real_height
= m_height
;
134 const std::string
&Scrollpad::buffer()
136 return m_buffer
.str();
139 void Scrollpad::flush()
141 auto &w
= static_cast<Window
&>(*this);
142 const auto &s
= m_buffer
.str();
143 const auto &ps
= m_buffer
.properties();
147 auto load_properties
= [&]() {
148 for (; p
!= ps
.end() && p
->first
== i
; ++p
)
151 auto write_whitespace
= [&]() {
152 for (; i
< s
.length() && iswspace(s
[i
]); ++i
)
158 auto write_word
= [&](bool load_properties_
) {
159 for (; i
< s
.length() && !iswspace(s
[i
]); ++i
)
161 if (load_properties_
)
166 auto write_buffer
= [&](bool generate_height_only
) -> size_t {
175 while (i
< s
.length())
177 // write all whitespaces.
180 // if we are generating height, check difference
181 // between previous Y coord and current one and
182 // update height accordingly.
183 if (generate_height_only
)
193 // save current string position state and get current
194 // coordinates as we are before the beginning of a word.
200 // write word to test if it overflows, but do not load properties
201 // yet since if it overflows, we do not want to load them twice.
204 // restore previous indexes state
208 // get new Y coord to see if word overflew into next line.
212 if (generate_height_only
)
214 // if it did, let's update height...
219 // ...or go to old coordinates, erase
220 // part of the string from previous line...
225 // ...start at the beginning of next line...
229 // ...write word again, this time with properties...
232 if (generate_height_only
)
234 // ... and check for potential
235 // difference in Y coordinates again.
242 // word didn't overflow, rewrite it with properties.
247 if (generate_height_only
)
249 // move to the first line, since when we do
250 // generation, m_real_height = m_height and we
251 // don't have many lines to use.
256 // load remaining properties if there are any
257 for (; p
!= ps
.end(); ++p
)
261 m_real_height
= std::max(write_buffer(true), m_height
);
262 if (m_real_height
> m_height
)
263 recreate(m_width
, m_real_height
);
269 void Scrollpad::reset()
274 bool Scrollpad::setProperties(const Color
&begin
, const std::string
&s
,
275 const Color
&end
, size_t flags
, size_t id
)
277 return regexSearch(m_buffer
, std::move(begin
), s
, std::move(end
), id
, flags
);
280 bool Scrollpad::setProperties(const Format
&begin
, const std::string
&s
,
281 const Format
&end
, size_t flags
, size_t id
)
283 return regexSearch(m_buffer
, begin
, s
, end
, flags
, id
);
286 bool Scrollpad::setProperties(const FormattedColor
&fc
, const std::string
&s
,
287 size_t flags
, size_t id
)
289 return regexSearch(m_buffer
,
292 FormattedColor::End
<StorageKind::Value
>(fc
),
297 void Scrollpad::removeProperties(size_t id
)
299 m_buffer
.removeProperties(id
);