1 /***************************************************************************
2 * Copyright (C) 2008-2014 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 "scrollpad.h"
29 template <typename PropT
>
30 bool regexSearch(NC::Buffer
&buf
, PropT begin
, const std::string
&ws
, PropT end
, size_t id
, boost::regex::flag_type flags
)
33 boost::regex
rx(ws
, flags
);
34 auto first
= boost::sregex_iterator(buf
.str().begin(), buf
.str().end(), rx
);
35 auto last
= boost::sregex_iterator();
36 bool success
= first
!= last
;
37 for (; first
!= last
; ++first
)
39 buf
.setProperty(first
->position(), begin
, id
);
40 buf
.setProperty(first
->position() + first
->length(), end
, id
);
43 } catch (boost::bad_expression
&e
) {
44 std::cerr
<< "regexSearch: bad_expression: " << e
.what() << "\n";
53 Scrollpad::Scrollpad(size_t startx
,
57 const std::string
&title
,
60 : Window(startx
, starty
, width
, height
, title
, color
, border
),
66 void Scrollpad::refresh()
68 assert(m_real_height
>= m_height
);
69 size_t max_beginning
= m_real_height
- m_height
;
70 m_beginning
= std::min(m_beginning
, max_beginning
);
71 prefresh(m_window
, m_beginning
, 0, m_start_y
, m_start_x
, m_start_y
+m_height
-1, m_start_x
+m_width
-1);
74 void Scrollpad::resize(size_t new_width
, size_t new_height
)
76 adjustDimensions(new_width
, new_height
);
77 recreate(new_width
, new_height
);
81 void Scrollpad::scroll(Scroll where
)
83 assert(m_real_height
>= m_height
);
84 size_t max_beginning
= m_real_height
- m_height
;
95 if (m_beginning
< max_beginning
)
101 if (m_beginning
> m_height
)
102 m_beginning
-= m_height
;
107 case Scroll::PageDown
:
109 m_beginning
= std::min(m_beginning
+ m_height
, max_beginning
);
119 m_beginning
= max_beginning
;
125 void Scrollpad::clear()
127 m_real_height
= m_height
;
131 m_window
= newpad(m_height
, m_width
);
132 setTimeout(m_window_timeout
);
133 setColor(m_color
, m_bg_color
);
137 const std::string
&Scrollpad::buffer()
139 return m_buffer
.str();
142 void Scrollpad::flush()
144 auto &w
= static_cast<Window
&>(*this);
145 const auto &s
= m_buffer
.str();
146 const auto &ps
= m_buffer
.properties();
150 auto load_properties
= [&]() {
151 for (; p
!= ps
.end() && p
->position() == i
; ++p
)
154 auto write_whitespace
= [&]() {
155 for (; i
< s
.length() && iswspace(s
[i
]); ++i
)
161 auto write_word
= [&](bool load_properties_
) {
162 for (; i
< s
.length() && !iswspace(s
[i
]); ++i
)
164 if (load_properties_
)
169 auto write_buffer
= [&](bool generate_height_only
) -> size_t {
178 while (i
< s
.length())
180 // write all whitespaces.
183 // if we are generating height, check difference
184 // between previous Y coord and current one and
185 // update height accordingly.
186 if (generate_height_only
)
196 // save current string position state and get current
197 // coordinates as we are before the beginning of a word.
203 // write word to test if it overflows, but do not load properties
204 // yet since if it overflows, we do not want to load them twice.
207 // restore previous indexes state
211 // get new Y coord to see if word overflew into next line.
215 if (generate_height_only
)
217 // if it did, let's update height...
222 // ...or go to old coordinates, erase
223 // part of the string from previous line...
228 // ...start at the beginning of next line...
232 // ...write word again, this time with properties...
235 if (generate_height_only
)
237 // ... and check for potential
238 // difference in Y coordinates again.
245 // word didn't overflow, rewrite it with properties.
250 if (generate_height_only
)
252 // move to the first line, since when we do
253 // generation, m_real_height = m_height and we
254 // don't have many lines to use.
259 // load remaining properties if there are any
260 for (; p
!= ps
.end(); ++p
)
264 m_real_height
= std::max(write_buffer(true), m_height
);
265 if (m_real_height
> m_height
)
266 recreate(m_width
, m_real_height
);
272 void Scrollpad::reset()
277 bool Scrollpad::setProperties(Color begin
, const std::string
&s
, Color end
, size_t id
, boost::regex::flag_type flags
)
279 return regexSearch(m_buffer
, begin
, s
, end
, id
, flags
);
282 bool Scrollpad::setProperties(Format begin
, const std::string
&s
, Format end
, size_t id
, boost::regex::flag_type flags
)
284 return regexSearch(m_buffer
, begin
, s
, end
, id
, flags
);
287 void Scrollpad::removeProperties(size_t id
)
289 m_buffer
.removeProperties(id
);