libyui-ncurses  2.44.1
/usr/src/RPM/BUILD/libyui-ncurses-2.44.1/src/NCtext.cc
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 
 All Classes Functions Variables