Hello community,

here is the log from the commit of package libyui-ncurses for openSUSE:Factory 
checked in at 2020-06-10 00:38:55
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libyui-ncurses (Old)
 and      /work/SRC/openSUSE:Factory/.libyui-ncurses.new.3606 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libyui-ncurses"

Wed Jun 10 00:38:55 2020 rev:54 rq:812559 version:2.55.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/libyui-ncurses/libyui-ncurses.changes    
2020-01-30 09:41:16.285485950 +0100
+++ /work/SRC/openSUSE:Factory/.libyui-ncurses.new.3606/libyui-ncurses.changes  
2020-06-10 00:39:17.577537818 +0200
@@ -1,0 +2,7 @@
+Thu Jun  4 12:05:43 UTC 2020 - Stefan Hundhammer <[email protected]>
+
+- Added autoWrap to label widget (bsc#1172513)
+- Bumped SO version to 12
+- 2.55.0
+
+-------------------------------------------------------------------

Old:
----
  libyui-ncurses-2.54.5.tar.bz2

New:
----
  libyui-ncurses-2.55.0.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libyui-ncurses-doc.spec ++++++
--- /var/tmp/diff_new_pack.wEr6Mf/_old  2020-06-10 00:39:18.393539957 +0200
+++ /var/tmp/diff_new_pack.wEr6Mf/_new  2020-06-10 00:39:18.397539968 +0200
@@ -17,10 +17,10 @@
 
 
 %define parent libyui-ncurses
-%define so_version 11
+%define so_version 12
 
 Name:           %{parent}-doc
-Version:        2.54.5
+Version:        2.55.0
 Release:        0
 Source:         %{parent}-%{version}.tar.bz2
 
@@ -32,8 +32,8 @@
 BuildRequires:  gcc-c++
 BuildRequires:  graphviz-gnome
 BuildRequires:  texlive-latex
-# YCustomStatusItemSelector
-BuildRequires:  libyui-devel >= 3.8.4
+# YLabel::setAutoWrap()
+BuildRequires:  libyui-devel >= 3.10.0
 
 Url:            http://github.com/libyui/
 Summary:        Libyui-ncurses documentation

++++++ libyui-ncurses.spec ++++++
--- /var/tmp/diff_new_pack.wEr6Mf/_old  2020-06-10 00:39:18.421540031 +0200
+++ /var/tmp/diff_new_pack.wEr6Mf/_new  2020-06-10 00:39:18.425540041 +0200
@@ -17,11 +17,11 @@
 
 
 Name:           libyui-ncurses
-Version:        2.54.5
+Version:        2.55.0
 Release:        0
 Source:         %{name}-%{version}.tar.bz2
 
-%define so_version 11
+%define so_version 12
 %define bin_name %{name}%{so_version}
 
 %if 0%{?suse_version} > 1325
@@ -33,8 +33,8 @@
 BuildRequires:  gcc-c++
 BuildRequires:  pkg-config
 
-# YTableCell::sortKey
-%define libyui_devel_version libyui-devel >= 3.9.1
+# YLabel::setAutoWrap()
+%define libyui_devel_version libyui-devel >= 3.10.0
 BuildRequires:  %{libyui_devel_version}
 BuildRequires:  ncurses-devel
 

++++++ libyui-ncurses-2.54.5.tar.bz2 -> libyui-ncurses-2.55.0.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libyui-ncurses-2.54.5/SOURCECONF.cmake 
new/libyui-ncurses-2.55.0/SOURCECONF.cmake
--- old/libyui-ncurses-2.54.5/SOURCECONF.cmake  2020-01-24 13:50:49.000000000 
+0100
+++ new/libyui-ncurses-2.55.0/SOURCECONF.cmake  2020-06-08 13:09:53.000000000 
+0200
@@ -61,6 +61,7 @@
   NCLogView.cc
   NCMultiLineEdit.cc
   NCFileSelection.cc
+  NCWordWrapper.cc
 
   NCPopup.cc
   NCPopupTable.cc
@@ -137,6 +138,7 @@
   NCLogView.h
   NCMultiLineEdit.h
   NCFileSelection.h
+  NCWordWrapper.h
   NCPopup.h
   NCPopupTable.h
   NCPopupList.h
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libyui-ncurses-2.54.5/VERSION.cmake 
new/libyui-ncurses-2.55.0/VERSION.cmake
--- old/libyui-ncurses-2.54.5/VERSION.cmake     2020-01-24 13:50:49.000000000 
+0100
+++ new/libyui-ncurses-2.55.0/VERSION.cmake     2020-06-08 13:09:53.000000000 
+0200
@@ -1,11 +1,11 @@
 SET( VERSION_MAJOR "2" )
-SET( VERSION_MINOR "54" )
-SET( VERSION_PATCH "5" )
+SET( VERSION_MINOR "55" )
+SET( VERSION_PATCH "0" )
 SET( VERSION 
"${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}${GIT_SHA1_VERSION}" )
 
-##### This is need for the libyui core, ONLY.
+##### This is needed for the libyui core ONLY.
 ##### These will be overridden from exports in LibyuiConfig.cmake
-SET( SONAME_MAJOR "11" )
+SET( SONAME_MAJOR "12" )
 SET( SONAME_MINOR "0" )
 SET( SONAME_PATCH "0" )
 SET( SONAME "${SONAME_MAJOR}.${SONAME_MINOR}.${SONAME_PATCH}" )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libyui-ncurses-2.54.5/package/libyui-ncurses-doc.spec 
new/libyui-ncurses-2.55.0/package/libyui-ncurses-doc.spec
--- old/libyui-ncurses-2.54.5/package/libyui-ncurses-doc.spec   2020-01-24 
13:50:49.000000000 +0100
+++ new/libyui-ncurses-2.55.0/package/libyui-ncurses-doc.spec   2020-06-08 
13:09:53.000000000 +0200
@@ -16,10 +16,10 @@
 #
 
 %define parent libyui-ncurses
-%define so_version 11
+%define so_version 12
 
 Name:           %{parent}-doc
-Version:        2.54.5
+Version:        2.55.0
 Release:        0
 Source:         %{parent}-%{version}.tar.bz2
 
@@ -31,8 +31,8 @@
 BuildRequires:  gcc-c++
 BuildRequires:  graphviz-gnome
 BuildRequires:  texlive-latex
-# YCustomStatusItemSelector
-BuildRequires:  libyui-devel >= 3.8.4
+# YLabel::setAutoWrap()
+BuildRequires:  libyui-devel >= 3.10.0
 
 Url:            http://github.com/libyui/
 Summary:        Libyui-ncurses documentation
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libyui-ncurses-2.54.5/package/libyui-ncurses.changes 
new/libyui-ncurses-2.55.0/package/libyui-ncurses.changes
--- old/libyui-ncurses-2.54.5/package/libyui-ncurses.changes    2020-01-24 
13:50:49.000000000 +0100
+++ new/libyui-ncurses-2.55.0/package/libyui-ncurses.changes    2020-06-08 
13:09:53.000000000 +0200
@@ -1,4 +1,11 @@
 -------------------------------------------------------------------
+Thu Jun  4 12:05:43 UTC 2020 - Stefan Hundhammer <[email protected]>
+
+- Added autoWrap to label widget (bsc#1172513)
+- Bumped SO version to 12
+- 2.55.0
+
+-------------------------------------------------------------------
 Fri Jan 24 09:44:50 UTC 2020 - Michal Filka <[email protected]>
 
 - bsc#1154694
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libyui-ncurses-2.54.5/package/libyui-ncurses.spec 
new/libyui-ncurses-2.55.0/package/libyui-ncurses.spec
--- old/libyui-ncurses-2.54.5/package/libyui-ncurses.spec       2020-01-24 
13:50:49.000000000 +0100
+++ new/libyui-ncurses-2.55.0/package/libyui-ncurses.spec       2020-06-08 
13:09:53.000000000 +0200
@@ -17,11 +17,11 @@
 
 
 Name:           libyui-ncurses
-Version:        2.54.5
+Version:        2.55.0
 Release:        0
 Source:         %{name}-%{version}.tar.bz2
 
-%define so_version 11
+%define so_version 12
 %define bin_name %{name}%{so_version}
 
 %if 0%{?suse_version} > 1325
@@ -33,8 +33,8 @@
 BuildRequires:  gcc-c++
 BuildRequires:  pkg-config
 
-# YTableCell::sortKey
-%define libyui_devel_version libyui-devel >= 3.9.1
+# YLabel::setAutoWrap()
+%define libyui_devel_version libyui-devel >= 3.10.0
 BuildRequires:  %{libyui_devel_version}
 BuildRequires:  ncurses-devel
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libyui-ncurses-2.54.5/src/NCLabel.cc 
new/libyui-ncurses-2.55.0/src/NCLabel.cc
--- old/libyui-ncurses-2.54.5/src/NCLabel.cc    2020-01-24 13:50:49.000000000 
+0100
+++ new/libyui-ncurses-2.55.0/src/NCLabel.cc    2020-06-08 13:09:53.000000000 
+0200
@@ -27,9 +27,14 @@
 #include "NCurses.h"
 #include "NCLabel.h"
 
+#define AUTO_WRAP_WIDTH         10
+#define AUTO_WRAP_HEIGHT        1
+
+using std::string;
+
 
 NCLabel::NCLabel( YWidget *      parent,
-                 const std::string & nlabel,
+                 const string & nlabel,
                  bool           isHeading,
                  bool           isOutputField )
     : YLabel( parent, nlabel, isHeading, isOutputField )
@@ -51,13 +56,76 @@
 
 int NCLabel::preferredWidth()
 {
-    return wGetDefsze().W;
+    int width;
+
+    if ( autoWrap() )
+    {
+        if ( layoutPass() == 2 )
+        {
+            // Use the width passed down to us from the parent layout manager
+            // in the last setSize() call. This is the definitive width that
+            // will be used after taking all other children of the layout into
+            // consideration, also including making widgets smaller due to size
+            // restrictions, or redistributing excess space.
+            //
+            // Since this widget can auto-wrap its contents, we accept
+            // basically any width; we just need to adapt the preferred height
+            // accordingly.
+            width = wrapper.lineWidth();
+        }
+        else
+        {
+            // Use a preliminary width. Typically, this widget should be
+            // wrapped into a MinSize or MinWidth which hopefully gives us a
+            // much more useful width than this.
+            //
+            // We would also just use 0 here, but that would make debugging
+            // really hard since the widget might completly disappear.
+            //
+            // The real width that will be used will be set in the setSize()
+            // call following the recursive preferredWidth() /
+            // preferredHeight() calls in the widget tree.
+            width = AUTO_WRAP_WIDTH;
+        }
+    }
+    else  // ! autoWrap()
+    {
+        width = wGetDefsze().W;
+    }
+
+    return width;
 }
 
 
 int NCLabel::preferredHeight()
 {
-    return wGetDefsze().H;
+    int height;
+
+    if ( autoWrap() )
+    {
+        if ( layoutPass() == 2 )
+        {
+            // This is where the magic happens:
+            //
+            // setSize() in the first layout pass gave us the real width which
+            // we stored in as the wrapper's lineWidth. We can now let the
+            // wrapper wrap the text into that width and calculate the height
+            // (the number of lines of the wrapped text) that is really needed
+            // based on that width.
+            height = wrapper.lines();
+            label  = NCstring( wrapper.wrappedText() );
+        }
+        else
+        {
+            height = AUTO_WRAP_HEIGHT;
+        }
+    }
+    else  // ! autoWrap()
+    {
+        height = wGetDefsze().H;
+    }
+
+    return height;
 }
 
 
@@ -68,18 +136,20 @@
 }
 
 
-void NCLabel::setSize( int newwidth, int newheight )
+void NCLabel::setSize( int newWidth, int newHeight )
 {
-    wRelocate( wpos( 0 ), wsze( newheight, newwidth ) );
+    if ( autoWrap() && layoutPass() == 1 )
+        wrapper.setLineWidth( newWidth );
+
+    wRelocate( wpos( 0 ), wsze( newHeight, newWidth ) );
 }
 
 
-void NCLabel::setText( const std::string & nlabel )
+void NCLabel::setText( const string & newLabel )
 {
-    label  = NCstring( nlabel );
-    yuiDebug() << "LABEL: " << NCstring( nlabel ) << " Longest line: " << 
label.width() << std::endl;
+    label = NCstring( newLabel );
     defsze = label.size();
-    YLabel::setText( nlabel );
+    YLabel::setText( newLabel );
     Redraw();
 }
 
@@ -94,5 +164,35 @@
 
     win->bkgd( bg );
     win->clear();
+
+    if ( autoWrap() )
+        label = NCstring( wrapper.wrappedText() );
+
     label.drawAt( *win, bg, bg );
 }
+
+
+void NCLabel::setAutoWrap( bool autoWrap )
+{
+    YLabel::setAutoWrap( autoWrap );
+
+    if ( autoWrap )
+    {
+        wrapper.setText( NCstring( text() ).str() );
+        // Delay setting 'label' until the line width for wrapping is set
+    }
+    else
+    {
+        // This will probably never happen since the default for autoWrap is
+        // 'false' and nobody will ever set an auto-wrapping label back to
+        // non-autowrapping programatically.
+        //
+        // But anyway, just in case: Let's revert the values to the initial
+        // defaults.
+
+        label = NCstring( text() );
+        defsze = label.size();
+        wrapper.clear();
+    }
+}
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libyui-ncurses-2.54.5/src/NCLabel.h 
new/libyui-ncurses-2.55.0/src/NCLabel.h
--- old/libyui-ncurses-2.54.5/src/NCLabel.h     2020-01-24 13:50:49.000000000 
+0100
+++ new/libyui-ncurses-2.55.0/src/NCLabel.h     2020-06-08 13:09:53.000000000 
+0200
@@ -29,6 +29,7 @@
 
 #include <yui/YLabel.h>
 #include "NCWidget.h"
+#include "NCWordWrapper.h"
 
 class NCLabel;
 
@@ -43,8 +44,9 @@
     NCLabel( const NCLabel & );
 
 
-    bool    heading;
-    NClabel label;
+    bool          heading;
+    NClabel       label;
+    NCWordWrapper wrapper;
 
 protected:
 
@@ -69,6 +71,7 @@
     virtual void setText( const std::string & nlabel );
 
     virtual void setEnabled( bool do_bv );
+    virtual void setAutoWrap( bool autoWrap = true );
 };
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libyui-ncurses-2.54.5/src/NCWordWrapper.cc 
new/libyui-ncurses-2.55.0/src/NCWordWrapper.cc
--- old/libyui-ncurses-2.54.5/src/NCWordWrapper.cc      1970-01-01 
01:00:00.000000000 +0100
+++ new/libyui-ncurses-2.55.0/src/NCWordWrapper.cc      2020-06-08 
13:09:53.000000000 +0200
@@ -0,0 +1,293 @@
+/*
+  Copyright (C) 2020 SUSE LLC
+
+  This library is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation; either version 2.1 of the
+  License, or (at your option) version 3.0 of the License. This library
+  is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+  License for more details. You should have received a copy of the GNU
+  Lesser General Public License along with this library; if not, write
+  to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+  Floor, Boston, MA 02110-1301 USA
+*/
+
+
+/*-/
+
+   File:       NCWordWrapper.h
+
+   Author:     Stefan Hundhammer <[email protected]>
+
+/-*/
+
+
+#include <cwctype>
+#include <iostream>
+#include "NCWordWrapper.h"
+
+
+#define DEFAULT_LINE_WIDTH      78
+
+using std::wstring;
+using std::endl;
+using std::wcout;
+
+
+NCWordWrapper::NCWordWrapper():
+    _lineWidth( DEFAULT_LINE_WIDTH ),
+    _lines( 0 ),
+    _dirty( false )
+{
+
+}
+
+
+void NCWordWrapper::setText( const wstring & origText )
+{
+    if ( origText != _origText )
+    {
+        _origText = origText;
+        _dirty = true;
+    }
+}
+
+
+void NCWordWrapper::setLineWidth( int width )
+{
+    if ( width != _lineWidth )
+    {
+        _lineWidth = width;
+        _dirty = true;
+    }
+}
+
+
+void NCWordWrapper::clear()
+{
+    _origText.clear();
+    _wrappedText.clear();
+    _lineWidth = DEFAULT_LINE_WIDTH;
+    _lines = 0;
+    _dirty = false;
+}
+
+
+int NCWordWrapper::lines()
+{
+    ensureWrapped();
+
+    return _lines;
+}
+
+
+const wstring & NCWordWrapper::wrappedText()
+{
+    ensureWrapped();
+
+    return _wrappedText;
+}
+
+
+void NCWordWrapper::ensureWrapped()
+{
+    if ( _dirty )
+        wrap();
+
+    _dirty = false;
+}
+
+
+wstring NCWordWrapper::normalizeWhitespace( const wstring & orig )
+{
+    wstring normalized;
+    normalized.reserve( orig.size() );
+    bool skippingWhitespace = false;
+
+    for ( wchar_t c: orig )
+    {
+        switch ( c )
+        {
+           case L' ':  // Whitespace
+           case L'\t':
+           case L'\n':
+           case L'\v':
+           case L'\r':
+            case L'\f':
+                // Don't add any whitespace right now: Wait until there is 
real content.
+
+                if ( ! normalized.empty() ) // Ignore any leading whitspace
+                    skippingWhitespace = true;
+                break;
+
+            default:    // Non-whitespace
+
+                // Add one blank for any skipped whitespace.
+                //
+                // This will not add trailing whitespace which is exactly the
+                // desired behaviour.
+
+                if ( skippingWhitespace )
+                    normalized += ' ';
+
+                normalized += c;
+                skippingWhitespace = false;
+                break;
+        }
+    }
+
+    return normalized;
+}
+
+
+void NCWordWrapper::wrap()
+{
+    wstring unwrapped = normalizeWhitespace( _origText );
+    _wrappedText.clear();
+    _wrappedText.reserve( unwrapped.size() );
+    _lines = 0;
+
+    while ( ! unwrapped.empty() )
+    {
+        wstring line = nextLine( unwrapped );
+
+#ifdef WORD_WRAPPER_TESTER
+        wcout << "Line: \"" << line << "\"  length: " << line.size() << endl;
+        wcout << "Rest: \"" << unwrapped << "\"\n" << endl;
+#endif
+
+        if ( ! _wrappedText.empty() )
+            _wrappedText += L'\n';
+
+        _wrappedText += line;
+        _lines++;
+    }
+
+    _dirty = false;
+}
+
+
+wstring NCWordWrapper::nextLine( wstring & unwrapped )
+{
+    wstring line;
+
+#ifdef WORD_WRAPPER_TESTER
+    wcout << "nextLine( \"" << unwrapped << "\" )" << endl;
+#endif
+
+    if ( (int) unwrapped.size() <= _lineWidth )
+    {
+        // The remaining unwrapped text fits into one line
+
+        line = unwrapped;
+        unwrapped.clear();
+
+        return line;
+    }
+
+
+    // Try to wrap at the rightmost possible whitespace
+
+    int pos = _lineWidth; // The whitespace will be removed here
+
+    while ( pos > 0 && unwrapped[ pos ] != L' ' )
+        --pos;
+
+    if ( unwrapped[ pos ] == L' ' )
+    {
+        line = unwrapped.substr( 0, pos );
+        unwrapped.erase( 0, pos + 1 );
+
+        return line;
+    }
+
+
+    // Try to wrap at the rightmost possible non-alphanum character
+
+    pos = _lineWidth - 1; // We'll need to keep the separator character
+
+    while ( pos > 0 && iswalnum( unwrapped[ pos ] ) )
+        --pos;
+
+    if ( ! iswalnum( unwrapped[ pos ] ) )
+    {
+#ifdef WORD_WRAPPER_TESTER
+        wcout << "iswalnum wrap" << endl;
+#endif
+
+        line = unwrapped.substr( 0, pos + 1 );
+        unwrapped.erase( 0, pos + 1 );
+
+        return line;
+    }
+
+
+    // Still no chance to break the line? So we'll have to break in mid-word.
+    // This is crude and brutal, but in some locales (Chinese, Japanese,
+    // Korean) there is very little whitespace, so sometimes we have no other
+    // choice.
+
+#ifdef WORD_WRAPPER_TESTER
+    wcout << "desperation wrap" << endl;
+#endif
+
+    pos = _lineWidth - 1;
+    line = unwrapped.substr( 0, pos + 1 );
+    unwrapped.erase( 0, pos + 1 );
+
+    return line;
+}
+
+
+// ----------------------------------------------------------------------
+
+
+// Standalone test frame for this class.
+//
+// Build with
+//
+//     g++ -D WORD_WRAPPER_TESTER -o word-wrapper-tester NCWordWrapper.cc
+//
+// Usage:
+//
+//    ./word-wrapper-tester "text to wrap" <line-length>
+//
+// Notice that this does not do any fancy UTF-8 recoding of the command line
+// arguments, so non-ASCII characters may be slightly broken. This is expected,
+// and for the sake of simplicity, this will not be fixed. This only affects
+// this test frame; the tested class can handle UTF-8 characters just fine
+// (thus "Lörem üpsum" instead of "Lorem ipsum" in the AutoWrap*.cc libyui
+// examples).
+
+#ifdef WORD_WRAPPER_TESTER
+
+
+int main( int argc, char *argv[] )
+{
+    NCWordWrapper wrapper;
+
+    if ( argc != 3 )
+    {
+        std::cerr << "\nUsage: " << argv[0] << " \"text to wrap\" 
<line-length>\n" << endl;
+        exit( 1 );
+    }
+
+    std::string src( argv[1] );
+    wstring input( src.begin(), src.end() );
+    int lineWidth = atoi( argv[2] );
+
+    wcout << "Wrapping to " << lineWidth << " columns:\n\"" << input << "\"\n" 
<< endl;
+
+    wrapper.setText( input );
+    wrapper.setLineWidth( lineWidth );
+    wrapper.wrap();
+
+    wcout << "         10        20        30        40        50" << endl;
+    wcout << "12345678901234567890123456789012345678901234567890"  << endl;
+    wcout << wrapper.wrappedText() << endl;
+    wcout << "-- Wrapped lines: " << wrapper.lines() << endl;
+}
+
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libyui-ncurses-2.54.5/src/NCWordWrapper.h 
new/libyui-ncurses-2.55.0/src/NCWordWrapper.h
--- old/libyui-ncurses-2.54.5/src/NCWordWrapper.h       1970-01-01 
01:00:00.000000000 +0100
+++ new/libyui-ncurses-2.55.0/src/NCWordWrapper.h       2020-06-08 
13:09:53.000000000 +0200
@@ -0,0 +1,124 @@
+/*
+  Copyright (C) 2020 SUSE LLC
+
+  This library is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation; either version 2.1 of the
+  License, or (at your option) version 3.0 of the License. This library
+  is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+  License for more details. You should have received a copy of the GNU
+  Lesser General Public License along with this library; if not, write
+  to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+  Floor, Boston, MA 02110-1301 USA
+*/
+
+
+/*-/
+
+   File:       NCWordWrapper.h
+
+   Author:     Stefan Hundhammer <[email protected]>
+
+/-*/
+
+
+#ifndef NCWordWrapper_h
+#define NCWordWrapper_h
+
+#include <string>
+
+/**
+ * Helper class to word-wrap text into a specified maximum line width.
+ * Whitespace is normalized in the process, i.e. any sequence of whitespace
+ * (blanks, newlines, tabs, ...) is replaced by a single blank. All lines end
+ * with a single newline character except the last one which has no newline.
+ **/
+class NCWordWrapper
+{
+public:
+
+    /**
+     * Constructor.
+     **/
+    NCWordWrapper();
+
+    /**
+     * Set the original text to wrap.
+     **/
+    void setText( const std::wstring & origText );
+
+    /**
+     * Set the maximum line width to wrap into.
+     **/
+    void setLineWidth( int width );
+
+    /**
+     * Return the number of lines after wrapping the original text.
+     **/
+    int lines();
+
+    /**
+     * Wrap the original text and return the wrapped text.
+     **/
+    const std::wstring & wrappedText();
+
+    /**
+     * Return the original unwrapped text.
+     **/
+    const std::wstring & origText() const { return _origText; }
+
+    /**
+     * Return the last used maximum line width.
+     **/
+    int lineWidth() const { return _lineWidth; }
+
+    /**
+     * Return a string where any sequence of whitespace in the original text is
+     * replaced with a single blank and without leading or trailing whitespace.
+     **/
+    static std::wstring normalizeWhitespace( const std::wstring & orig );
+
+    /**
+     * Do the wrapping.
+     *
+     * This normally doesn't need to be called manually; it is done
+     * automatically when retrieving the wrapped text or the number of wrapped
+     * lines (and when the internal 'dirty' flag is set).
+     *
+     * But it can be useful to call it manually for debugging and testing.
+     **/
+    void wrap();
+
+    /**
+     * Clear the old content.
+     **/
+    void clear();
+
+
+protected:
+
+    /**
+     * Do the wrapping if necessary.
+     **/
+    void ensureWrapped();
+
+    /**
+     * Return the next line that fits into the line width and removed it from
+     * 'unwrapped'.
+     **/
+    std::wstring nextLine( std::wstring & unwrapped );
+
+    //
+    // Data members
+    //
+
+    std::wstring _origText;
+    std::wstring _wrappedText;
+    int          _lineWidth;
+    int          _lines;
+    bool         _dirty;
+};
+
+#endif  // NCWordWrapper_h


Reply via email to