1 /***************************************************************************
2 * Copyright (C) 2008-2016 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
, boost::regex::flag_type flags
, size_t id
)
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
.addProperty(first
->position(), begin
, id
);
40 buf
.addProperty(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
);
136 const std::string
&Scrollpad::buffer()
138 return m_buffer
.str();
141 void Scrollpad::flush()
143 auto &w
= static_cast<Window
&>(*this);
144 const auto &s
= m_buffer
.str();
145 const auto &ps
= m_buffer
.properties();
149 auto load_properties
= [&]() {
150 for (; p
!= ps
.end() && p
->first
== i
; ++p
)
153 auto write_whitespace
= [&]() {
154 for (; i
< s
.length() && iswspace(s
[i
]); ++i
)
160 auto write_word
= [&](bool load_properties_
) {
161 for (; i
< s
.length() && !iswspace(s
[i
]); ++i
)
163 if (load_properties_
)
168 auto write_buffer
= [&](bool generate_height_only
) -> size_t {
177 while (i
< s
.length())
179 // write all whitespaces.
182 // if we are generating height, check difference
183 // between previous Y coord and current one and
184 // update height accordingly.
185 if (generate_height_only
)
195 // save current string position state and get current
196 // coordinates as we are before the beginning of a word.
202 // write word to test if it overflows, but do not load properties
203 // yet since if it overflows, we do not want to load them twice.
206 // restore previous indexes state
210 // get new Y coord to see if word overflew into next line.
214 if (generate_height_only
)
216 // if it did, let's update height...
221 // ...or go to old coordinates, erase
222 // part of the string from previous line...
227 // ...start at the beginning of next line...
231 // ...write word again, this time with properties...
234 if (generate_height_only
)
236 // ... and check for potential
237 // difference in Y coordinates again.
244 // word didn't overflow, rewrite it with properties.
249 if (generate_height_only
)
251 // move to the first line, since when we do
252 // generation, m_real_height = m_height and we
253 // don't have many lines to use.
258 // load remaining properties if there are any
259 for (; p
!= ps
.end(); ++p
)
263 m_real_height
= std::max(write_buffer(true), m_height
);
264 if (m_real_height
> m_height
)
265 recreate(m_width
, m_real_height
);
271 void Scrollpad::reset()
276 bool Scrollpad::setProperties(Color begin
, const std::string
&s
, Color end
, size_t flags
, size_t id
)
278 return regexSearch(m_buffer
, std::move(begin
), s
, std::move(end
), id
, flags
);
281 bool Scrollpad::setProperties(Format begin
, const std::string
&s
, Format end
, size_t flags
, size_t id
)
283 return regexSearch(m_buffer
, begin
, s
, end
, flags
, id
);
286 void Scrollpad::removeProperties(size_t id
)
288 m_buffer
.removeProperties(id
);