libyui-ncurses
2.44.1
|
00001 /* 00002 Copyright (C) 2000-2012 Novell, Inc 00003 This library is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU Lesser General Public License as 00005 published by the Free Software Foundation; either version 2.1 of the 00006 License, or (at your option) version 3.0 of the License. This library 00007 is distributed in the hope that it will be useful, but WITHOUT ANY 00008 WARRANTY; without even the implied warranty of MERCHANTABILITY or 00009 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 00010 License for more details. You should have received a copy of the GNU 00011 Lesser General Public License along with this library; if not, write 00012 to the Free Software Foundation, Inc., 51 Franklin Street, Fifth 00013 Floor, Boston, MA 02110-1301 USA 00014 */ 00015 00016 00017 /*-/ 00018 00019 File: NCtext.cc 00020 00021 Author: Michael Andres <ma@suse.de> 00022 00023 /-*/ 00024 00025 #define YUILogComponent "ncurses" 00026 #include <yui/YUILog.h> 00027 #include "NCtext.h" 00028 #include "stringutil.h" 00029 00030 #include <wchar.h> // wcwidth 00031 #include <langinfo.h> 00032 00033 #include <boost/algorithm/string.hpp> 00034 00035 const NCstring NCtext::emptyStr; 00036 00037 00038 00039 00040 NCtext::NCtext( const NCstring & nstr ) 00041 { 00042 lset( nstr ); 00043 } 00044 00045 00046 00047 NCtext::NCtext( const NCstring & nstr, size_t columns ) 00048 { 00049 lbrset( nstr, columns ); 00050 } 00051 00052 00053 00054 NCtext::~NCtext() 00055 {} 00056 00057 00058 00059 void NCtext::lset( const NCstring & ntext ) 00060 { 00061 // FIXME: rewrite this function so one understands it 00062 00063 mtext.clear(); 00064 mtext.push_back( "" ); 00065 00066 if ( ntext.str().empty() ) 00067 return; 00068 00069 std::wstring text( ntext.str() ); 00070 00071 std::wstring::size_type spos = 0; 00072 00073 std::wstring::size_type cpos = std::wstring::npos; 00074 00075 bool sawnl = false; // saw new line 00076 00077 // handle DOS text 00078 boost::erase_all( text, L"\r" ); 00079 00080 while (( cpos = text.find( L'\n', spos ) ) != std::wstring::npos ) 00081 { 00082 if ( sawnl ) 00083 mtext.push_back( "" ); 00084 00085 mtext.back() = NCstring( mtext.back().str() + text.substr( spos, cpos - spos ) ); 00086 00087 sawnl = true; 00088 00089 spos = cpos + 1; 00090 } 00091 00092 if ( spos < text.size() ) 00093 { 00094 if ( sawnl ) 00095 mtext.push_back( "" ); 00096 00097 mtext.back() = NCstring( mtext.back().str() + text.substr( spos ) ); 00098 } 00099 } 00100 00101 00102 00103 void NCtext::lbrset( const NCstring & ntext, size_t columns ) 00104 { 00105 mtext.clear(); 00106 00107 if ( ntext.str().empty() ) 00108 return; 00109 00110 std::wstring text( ntext.str() ); 00111 00112 // handle DOS text 00113 boost::erase_all( text, L"\r" ); 00114 00115 std::wstring::size_type spos = 0; 00116 00117 std::wstring::size_type cpos = std::wstring::npos; 00118 00119 cpos = text.find( L'\n', spos ); 00120 00121 while ( cpos != std::wstring::npos ) 00122 { 00123 std::wstring line = text.substr( spos, cpos - spos ); 00124 00125 if ( line.size() <= columns ) 00126 { 00127 mtext.push_back( NCstring( line ) ); 00128 } 00129 else 00130 { 00131 size_t start = columns; 00132 mtext.push_back( NCstring( line.substr( 0, columns ) ) ); 00133 00134 while ( start < line.size() ) 00135 { 00136 yuiDebug() << "Add: " << line.substr( start, columns ) << std::endl; 00137 mtext.push_back( NCstring( L'~' + line.substr( start, columns - 1 ) ) ); 00138 start += columns - 1; 00139 } 00140 } 00141 00142 spos = cpos + 1; 00143 00144 cpos = text.find( L'\n', spos ); 00145 } 00146 00147 if ( spos < text.size() ) 00148 { 00149 mtext.push_back( NCstring( text.substr( spos ) ) ); 00150 } 00151 } 00152 00153 00154 00155 unsigned NCtext::Lines() const 00156 { 00157 if ( mtext.size() == 1 && mtext.front().Str() == "" ) 00158 { 00159 return 0; 00160 } 00161 else 00162 return mtext.size(); 00163 } 00164 00165 00166 00167 void NCtext::append( const NCstring &line ) 00168 { 00169 mtext.push_back( line ); 00170 } 00171 00172 00173 00174 size_t NCtext::Columns() const 00175 { 00176 size_t llen = 0; // longest line 00177 size_t tmp_len = 0; // width of current line 00178 00179 const_iterator line; // iterator for list <NCstring> mtext 00180 std::wstring::const_iterator wstr_it; // iterator for std::wstring 00181 00182 for ( line = mtext.begin(); line != mtext.end(); ++line ) 00183 { 00184 tmp_len = 0; 00185 00186 for ( wstr_it = ( *line ).str().begin(); wstr_it != ( *line ).str().end() ; ++wstr_it ) 00187 { 00188 if ( iswprint( *wstr_it ) ) 00189 tmp_len += wcwidth( *wstr_it ); 00190 else if ( *wstr_it == L'\t' ) 00191 tmp_len += NCurses::tabsize(); 00192 } 00193 00194 if ( tmp_len > llen ) 00195 llen = tmp_len; 00196 } 00197 00198 return llen; 00199 } 00200 00201 00202 00203 const NCstring & NCtext::operator[]( std::wstring::size_type idx ) const 00204 { 00205 if ( idx >= Lines() ) 00206 return emptyStr; 00207 00208 const_iterator line = mtext.begin(); 00209 00210 for ( ; idx; --idx, ++line ) 00211 ; 00212 00213 return *line; 00214 } 00215 00216 00217 std::ostream & operator<<( std::ostream & STREAM, const NCtext & OBJ ) 00218 { 00219 return STREAM << "[Text:" << OBJ.Lines() << ',' << OBJ.Columns() << ']'; 00220 } 00221 00222 00223 00224 00225 00226 void NClabel::stripHotkey() 00227 { 00228 hotline = std::wstring::npos; 00229 unsigned lineno = 0; 00230 00231 for ( iterator line = mtext.begin(); line != mtext.end(); ++line, ++lineno ) 00232 { 00233 line->getHotkey(); 00234 00235 if ( line->hotpos() != std::wstring::npos ) 00236 { 00237 hotline = lineno; 00238 break; 00239 } 00240 } 00241 } 00242 00243 00244 00245 void NClabel::drawAt( NCursesWindow & w, chtype style, chtype hotstyle, 00246 const wrect & dim, 00247 const NC::ADJUST adjust, 00248 bool fillup ) const 00249 { 00250 wrect area( dim.intersectRelTo( w.area() ) ); 00251 00252 if ( area.Sze > 0 ) 00253 { 00254 unsigned maxlen = area.Sze.W; 00255 unsigned len = ( width() < maxlen ) ? width() : maxlen; 00256 unsigned pre = 0; 00257 unsigned post = 0; 00258 00259 if ( len < maxlen ) 00260 { 00261 unsigned dist = maxlen - len; 00262 00263 if ( adjust & NC::LEFT ) 00264 pre = 0; 00265 else if ( adjust & NC::RIGHT ) 00266 pre = dist; 00267 else 00268 pre = dist / 2; 00269 00270 post = dist - pre; 00271 } 00272 00273 int l = area.Pos.L; 00274 00275 int maxl = area.Pos.L + area.Sze.H; 00276 unsigned lineno = 0; 00277 00278 chtype obg = w.getbkgd(); 00279 w.bkgdset( style ); 00280 00281 for ( NCtext::const_iterator line = begin(); 00282 line != end() && l < maxl; 00283 ++line, ++l, ++lineno ) 00284 { 00285 if ( pre && fillup ) 00286 { 00287 w.move( l, area.Pos.C ); 00288 w.addwstr( std::wstring( pre, L' ' ).c_str() ); 00289 } 00290 else 00291 { 00292 w.move( l, area.Pos.C + pre ); 00293 } 00294 00295 // yuiDebug() << "TERMINAL: " << NCstring::terminalEncoding() << " CODESET: " << nl_langinfo( CODESET) << std::endl; 00296 if ( len ) 00297 { 00298 if ( NCstring::terminalEncoding() != "UTF-8" ) 00299 { 00300 std::string out; 00301 bool ok = NCstring::RecodeFromWchar(( *line ).str(), NCstring::terminalEncoding(), &out ); 00302 00303 if ( ok ) 00304 { 00305 w.printw( "%-*.*s", len, ( int )len, out.c_str() ); 00306 } 00307 } 00308 else 00309 { 00310 w.printw( "%ls", ( *line ).str().substr( 0, len ).c_str() ); 00311 } 00312 } 00313 00314 if ( post && fillup ) 00315 { 00316 w.addwstr( std::wstring( post, L' ' ).c_str() ); 00317 } 00318 00319 if ( lineno == hotline && hotstyle && pre + hotpos() < maxlen ) 00320 { 00321 w.bkgdset( hotstyle ); 00322 00323 w.add_attr_char( l, area.Pos.C + pre + hotpos() ); 00324 00325 w.bkgdset( style ); 00326 } 00327 00328 } 00329 00330 if ( fillup ) 00331 { 00332 for ( ; l < maxl; ++l ) 00333 { 00334 w.printw( l, area.Pos.C, "%-*.*s", area.Sze.W, area.Sze.W, "" ); 00335 } 00336 } 00337 00338 w.bkgdset( obg ); 00339 } 00340 } 00341 00342 00343 std::ostream & operator<<( std::ostream & STREAM, const NClabel & OBJ ) 00344 { 00345 STREAM << "[label" << OBJ.size() << ':' << OBJ[0].str(); 00346 00347 if ( OBJ.hasHotkey() ) 00348 STREAM << ':' << OBJ.hotkey() << " at " << OBJ.hotpos(); 00349 00350 return STREAM << ']'; 00351 } 00352