From baa0c60c79b536278291ff628b64dfa62efe1db9 Mon Sep 17 00:00:00 2001 From: Markus Gans Date: Tue, 9 Feb 2021 22:01:21 +0100 Subject: [PATCH] Added support for combined unicode characters --- .travis.yml | 15 + ChangeLog | 7 +- doc/first-steps.md | 58 +- examples/7segment.cpp | 3 +- examples/checklist.cpp | 3 +- examples/listview.cpp | 3 +- examples/mandelbrot.cpp | 3 +- examples/mouse.cpp | 3 +- examples/rotozoomer.cpp | 3 +- examples/scrollview.cpp | 3 +- examples/term-attributes.cpp | 3 +- examples/termcap.cpp | 5 +- examples/timer.cpp | 4 +- examples/transparent.cpp | 3 +- examples/treeview.cpp | 3 +- examples/windows.cpp | 3 +- src/flabel.cpp | 28 +- src/flineedit.cpp | 56 +- src/flistview.cpp | 39 +- src/foptiattr.cpp | 12 +- src/fscrollview.cpp | 62 +- src/fstring.cpp | 4 +- src/fterm.cpp | 9 +- src/fterm_functions.cpp | 170 +- src/ftermbuffer.cpp | 138 +- src/ftermcap.cpp | 12 +- src/ftermlinux.cpp | 4 +- src/ftextview.cpp | 24 +- src/fvterm.cpp | 107 +- src/include/final/fc.h | 2 +- src/include/final/flineedit.h | 1 + src/include/final/fstring.h | 50 +- src/include/final/fterm.h | 17 +- src/include/final/ftermbuffer.h | 5 +- src/include/final/ftermlinux.h | 2 +- src/include/final/ftypes.h | 4 +- src/include/final/fvterm.h | 8 +- test/Makefile.am | 6 + test/fterm_functions-test.cpp | 2561 +++++++++++++++++++++++++++++++ test/ftermbuffer-test.cpp | 848 ++++++++++ 40 files changed, 3965 insertions(+), 326 deletions(-) create mode 100644 test/fterm_functions-test.cpp create mode 100644 test/ftermbuffer-test.cpp diff --git a/.travis.yml b/.travis.yml index 8c339351..b2a31ff1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -154,3 +154,18 @@ jobs: - autoreconf -v --install --force - ./configure --prefix=/usr - make -j10 + + # + # FreeBSD + # + - os: freebsd + env: + - TEST="FreeBSD" + before_install: + - uname -a + - g++ --version + script: + - autoreconf -v --install --force + - ./configure --prefix=/usr + - make -j10 + diff --git a/ChangeLog b/ChangeLog index 8702f271..397cfa31 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ +2021-02-09 Markus Gans + * Added support for combined unicode characters + * Added a unit test for the FTermBuffera class + * Added a unit test for the FTterm functions + 2020-12-31 Markus Gans - * Refactoring to scaled enumerations + * Refactoring to scoped enumerations 2020-11-18 Markus Gans * The terminal update rate is now limited to 60 Hz diff --git a/doc/first-steps.md b/doc/first-steps.md index 67b6c402..93e9c6f7 100644 --- a/doc/first-steps.md +++ b/doc/first-steps.md @@ -330,32 +330,32 @@ types and send them to other objects and widgets. ### Available event types ### ```cpp -enum events +enum class Event { - None_Event, // invalid event - KeyPress_Event, // key pressed - KeyUp_Event, // key released - KeyDown_Event, // key pressed - MouseDown_Event, // mouse button pressed - MouseUp_Event, // mouse button released - MouseDoubleClick_Event, // mouse button double click - MouseWheel_Event, // mouse wheel rolled - MouseMove_Event, // mouse move - FocusIn_Event, // focus in - FocusOut_Event, // focus out - ChildFocusIn_Event, // child focus in - ChildFocusOut_Event, // child focus out - WindowActive_Event, // activate window - WindowInactive_Event, // deactivate window - WindowRaised_Event, // raise window - WindowLowered_Event, // lower window - Accelerator_Event, // keyboard accelerator - Resize_Event, // terminal resize - Show_Event, // widget is shown - Hide_Event, // widget is hidden - Close_Event, // widget close - Timer_Event, // timer event occur - User_Event // user defined event + None, // invalid event + KeyPress, // key pressed + KeyUp, // key released + KeyDown, // key pressed + MouseDown, // mouse button pressed + MouseUp, // mouse button released + MouseDoubleClick, // mouse button double click + MouseWheel, // mouse wheel rolled + MouseMove, // mouse move + FocusIn, // focus in + FocusOut, // focus out + ChildFocusIn, // child focus in + ChildFocusOut, // child focus out + WindowActive, // activate window + WindowInactive, // deactivate window + WindowRaised, // raise window + WindowLowered, // lower window + Accelerator, // keyboard accelerator + Resize, // terminal resize + Show, // widget is shown + Hide, // widget is hidden + Close, // widget close + Timer, // timer event occur + User // user defined event }; ``` @@ -1337,15 +1337,15 @@ requires it. You can controll this behavior by the two methods `setHorizontalScrollBarMode()` and `setVerticalScrollBarMode()`. ```cpp -setHorizontalScrollBarMode (fc::scrollBarMode); -setVerticalScrollBarMode (fc::scrollBarMode); +setHorizontalScrollBarMode (finalcut::ScrollBarMode); +setVerticalScrollBarMode (finalcut::ScrollBarMode); ``` You pass the scroll bar visibility mode as a value of the enum type -`fc::scrollBarMode`. +`finalcut::ScrollBarMode`. ```cpp -enum scrollBarMode +enum class ScrollBarMode { Auto = 0, // Shows a scroll bar when area is larger than viewport Hidden = 1, // Never shows a scroll bar diff --git a/examples/7segment.cpp b/examples/7segment.cpp index 36153294..25a393ea 100644 --- a/examples/7segment.cpp +++ b/examples/7segment.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2012-2020 Markus Gans * +* Copyright 2012-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -26,7 +26,6 @@ #include -namespace fc = finalcut::fc; using finalcut::FColorPair; using finalcut::FColor; using finalcut::FRect; diff --git a/examples/checklist.cpp b/examples/checklist.cpp index 08d0bba8..a92d0ed5 100644 --- a/examples/checklist.cpp +++ b/examples/checklist.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2017-2020 Markus Gans * +* Copyright 2017-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -28,7 +28,6 @@ #include -namespace fc = finalcut::fc; using finalcut::FPoint; using finalcut::FRect; using finalcut::FSize; diff --git a/examples/listview.cpp b/examples/listview.cpp index ee681c60..473c95e9 100644 --- a/examples/listview.cpp +++ b/examples/listview.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2017-2020 Markus Gans * +* Copyright 2017-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -28,7 +28,6 @@ #include -namespace fc = finalcut::fc; using finalcut::FPoint; using finalcut::FSize; diff --git a/examples/mandelbrot.cpp b/examples/mandelbrot.cpp index 62b5cd38..9fca2a02 100644 --- a/examples/mandelbrot.cpp +++ b/examples/mandelbrot.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2015-2020 Markus Gans * +* Copyright 2015-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -22,7 +22,6 @@ #include -namespace fc = finalcut::fc; using finalcut::FColor; using finalcut::FPoint; using finalcut::FSize; diff --git a/examples/mouse.cpp b/examples/mouse.cpp index b5d2b884..b40e5a9e 100644 --- a/examples/mouse.cpp +++ b/examples/mouse.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2017-2020 Markus Gans * +* Copyright 2017-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -22,7 +22,6 @@ #include -namespace fc = finalcut::fc; using finalcut::FColorPair; using finalcut::FColor; using finalcut::FRect; diff --git a/examples/rotozoomer.cpp b/examples/rotozoomer.cpp index 1b317f20..e9e5af8c 100644 --- a/examples/rotozoomer.cpp +++ b/examples/rotozoomer.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2020 Markus Gans * +* Copyright 2020-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -28,7 +28,6 @@ #include -namespace fc = finalcut::fc; using std::chrono::duration_cast; using std::chrono::milliseconds; using std::chrono::system_clock; diff --git a/examples/scrollview.cpp b/examples/scrollview.cpp index 0e09e921..84b7af07 100644 --- a/examples/scrollview.cpp +++ b/examples/scrollview.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2017-2020 Markus Gans * +* Copyright 2017-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -22,7 +22,6 @@ #include -namespace fc = finalcut::fc; using finalcut::FPoint; using finalcut::FSize; diff --git a/examples/term-attributes.cpp b/examples/term-attributes.cpp index f0d267d2..4a8c1e7d 100644 --- a/examples/term-attributes.cpp +++ b/examples/term-attributes.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2015-2020 Markus Gans * +* Copyright 2015-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -24,7 +24,6 @@ #include #include -namespace fc = finalcut::fc; using finalcut::FPoint; using finalcut::FSize; using finalcut::FColorPair; diff --git a/examples/termcap.cpp b/examples/termcap.cpp index b90065b1..d9fc91a9 100644 --- a/examples/termcap.cpp +++ b/examples/termcap.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2017-2020 Markus Gans * +* Copyright 2017-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -27,7 +27,6 @@ #include -namespace fc = finalcut::fc; using finalcut::Termcap; // Function prototype @@ -239,7 +238,7 @@ void debug (const finalcut::FApplication& TermApp) std::cout << "`------------------- debug -------------------\r\n"; } #else -void debug (finalcut::FApplication&) +void debug (const finalcut::FApplication&) { // FINAL CUT was compiled without debug option } diff --git a/examples/timer.cpp b/examples/timer.cpp index 2a6ea9e9..df5c089e 100644 --- a/examples/timer.cpp +++ b/examples/timer.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2014-2020 Markus Gans * +* Copyright 2014-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -22,8 +22,6 @@ #include -namespace fc = finalcut::fc; - //---------------------------------------------------------------------- // class Timer diff --git a/examples/transparent.cpp b/examples/transparent.cpp index 6d7a6a4a..fb3faaec 100644 --- a/examples/transparent.cpp +++ b/examples/transparent.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2016-2020 Markus Gans * +* Copyright 2016-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -22,7 +22,6 @@ #include -namespace fc = finalcut::fc; using finalcut::FColorPair; using finalcut::FColor; using finalcut::FPoint; diff --git a/examples/treeview.cpp b/examples/treeview.cpp index e84cc1fc..730f1327 100644 --- a/examples/treeview.cpp +++ b/examples/treeview.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2017-2020 Markus Gans * +* Copyright 2017-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -27,7 +27,6 @@ #include -namespace fc = finalcut::fc; using finalcut::FPoint; using finalcut::FSize; diff --git a/examples/windows.cpp b/examples/windows.cpp index fc6c8970..e0d6ad9b 100644 --- a/examples/windows.cpp +++ b/examples/windows.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2016-2020 Markus Gans * +* Copyright 2016-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -25,7 +25,6 @@ #include -namespace fc = finalcut::fc; using finalcut::FPoint; using finalcut::FSize; diff --git a/src/flabel.cpp b/src/flabel.cpp index a9c87c2d..6ed4c1d0 100644 --- a/src/flabel.cpp +++ b/src/flabel.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2014-2020 Markus Gans * +* Copyright 2014-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -252,26 +252,16 @@ void FLabel::setHotkeyAccelerator() std::size_t FLabel::getAlignOffset (const std::size_t length) const { const std::size_t width(getWidth()); - assert ( alignment == Align::Left - || alignment == Align::Center - || alignment == Align::Right ); - switch ( alignment ) + if ( alignment == Align::Center ) { - case Align::Left: - return 0; - - case Align::Center: - if ( length < width ) - return (width - length) / 2; - else - return 0; - - case Align::Right: - if ( length < width ) - return width - length; - else - return 0; + if ( length < width ) + return (width - length) / 2; + } + else if ( alignment == Align::Right ) + { + if ( length < width ) + return width - length; } return 0; diff --git a/src/flineedit.cpp b/src/flineedit.cpp index 52f628ee..e7270875 100644 --- a/src/flineedit.cpp +++ b/src/flineedit.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2012-2020 Markus Gans * +* Copyright 2012-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -938,21 +938,52 @@ void FLineEdit::adjustTextOffset() //---------------------------------------------------------------------- inline void FLineEdit::cursorLeft() { - if ( cursor_pos > 0 ) - cursor_pos--; + auto prev_char_len = getPrevCharLength(text, cursor_pos); - adjustTextOffset(); + if ( prev_char_len < 0 ) + { + const auto pos = searchLeftCharBegin(text, cursor_pos); + + if ( pos != NOT_FOUND ) + { + cursor_pos = pos; + adjustTextOffset(); + } + + return; + } + + if ( cursor_pos >= std::size_t(prev_char_len) ) + { + cursor_pos -= std::size_t(prev_char_len); + adjustTextOffset(); + } } //---------------------------------------------------------------------- inline void FLineEdit::cursorRight() { - const auto& len = text.getLength(); + const auto len = text.getLength(); + const auto char_len = getCharLength(text, cursor_pos); - if ( cursor_pos < len ) - cursor_pos++; + if ( char_len < 0 ) + { + const auto pos = searchRightCharBegin(text, cursor_pos); - adjustTextOffset(); + if ( pos != NOT_FOUND ) + { + cursor_pos = pos; + adjustTextOffset(); + } + + return; + } + + if ( cursor_pos + std::size_t(char_len) <= len ) + { + cursor_pos += std::size_t(char_len); + adjustTextOffset(); + } } //---------------------------------------------------------------------- @@ -981,10 +1012,15 @@ inline void FLineEdit::deleteCurrentCharacter() // Delete key functionality const auto& len = text.getLength(); + const auto char_len = getCharLength(text, cursor_pos); - if ( len > 0 && cursor_pos < len ) + if ( char_len < 0 ) + return; + + if ( len >= std::size_t(char_len) + && cursor_pos <= len - std::size_t(char_len) ) { - text.remove(cursor_pos, 1); + text.remove(cursor_pos, std::size_t(char_len)); print_text = ( isPasswordField() ) ? getPasswordText() : text; processChanged(); } diff --git a/src/flistview.cpp b/src/flistview.cpp index 0b8508dc..a643907d 100644 --- a/src/flistview.cpp +++ b/src/flistview.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2017-2020 Markus Gans * +* Copyright 2017-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -1479,26 +1479,15 @@ std::size_t FListView::getAlignOffset ( const Align align , const std::size_t column_width , const std::size_t width ) const { - assert ( align == Align::Left - || align == Align::Center - || align == Align::Right ); - - switch ( align ) + if ( align == Align::Center ) { - case Align::Left: - return 0; - - case Align::Center: - if ( column_width < width ) - return (width - column_width) / 2; - else - return 0; - - case Align::Right: - if ( column_width < width ) - return width - column_width; - else - return 0; + if ( column_width < width ) + return (width - column_width) / 2; + } + else if ( align == Align::Right ) + { + if ( column_width < width ) + return width - column_width; } return 0; @@ -1603,15 +1592,9 @@ void FListView::drawHeadlines() while ( iter != header.end() ) { - const auto& text = iter->name; + if ( ! iter->name.isEmpty() ) + drawHeadlineLabel(iter); // Draw into FTermBuffer object - if ( text.isNull() || text.isEmpty() ) - { - ++iter; - continue; - } - - drawHeadlineLabel(iter); // Draw into FTermBuffer object ++iter; } diff --git a/src/foptiattr.cpp b/src/foptiattr.cpp index b9e4b0c6..ff44625f 100644 --- a/src/foptiattr.cpp +++ b/src/foptiattr.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2016-2020 Markus Gans * +* Copyright 2016-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -1386,13 +1386,13 @@ inline void FOptiAttr::change_current_color ( const FChar& term if ( term.fg_color != fg || frev ) { - color_str = FTermcap::encodeParameter(AF, ansi_fg, 0, 0, 0, 0, 0, 0, 0, 0); + color_str = FTermcap::encodeParameter(AF, uInt16(ansi_fg), 0, 0, 0, 0, 0, 0, 0, 0); append_sequence (color_str); } if ( term.bg_color != bg || frev ) { - color_str = FTermcap::encodeParameter(AB, ansi_bg, 0, 0, 0, 0, 0, 0, 0, 0); + color_str = FTermcap::encodeParameter(AB, uInt16(ansi_bg), 0, 0, 0, 0, 0, 0, 0, 0); append_sequence (color_str); } } @@ -1400,13 +1400,13 @@ inline void FOptiAttr::change_current_color ( const FChar& term { if ( term.fg_color != fg || frev ) { - color_str = FTermcap::encodeParameter(Sf, fg, 0, 0, 0, 0, 0, 0, 0, 0); + color_str = FTermcap::encodeParameter(Sf, uInt16(fg), 0, 0, 0, 0, 0, 0, 0, 0); append_sequence (color_str); } if ( term.bg_color != bg || frev ) { - color_str = FTermcap::encodeParameter(Sb, bg, 0, 0, 0, 0, 0, 0, 0, 0); + color_str = FTermcap::encodeParameter(Sb, uInt16(bg), 0, 0, 0, 0, 0, 0, 0, 0); append_sequence (color_str); } } @@ -1414,7 +1414,7 @@ inline void FOptiAttr::change_current_color ( const FChar& term { fg = vga2ansi(fg); bg = vga2ansi(bg); - color_str = FTermcap::encodeParameter(sp, fg, bg, 0, 0, 0, 0, 0, 0, 0); + color_str = FTermcap::encodeParameter(sp, uInt16(fg), uInt16(bg), 0, 0, 0, 0, 0, 0, 0); append_sequence (color_str); } } diff --git a/src/fscrollview.cpp b/src/fscrollview.cpp index 6c410b4e..83e0ffb8 100644 --- a/src/fscrollview.cpp +++ b/src/fscrollview.cpp @@ -4,7 +4,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2017-2020 Markus Gans * +* Copyright 2017-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -799,52 +799,40 @@ void FScrollView::calculateScrollbarPos() const //---------------------------------------------------------------------- void FScrollView::setHorizontalScrollBarVisibility() const { - assert ( h_mode == ScrollBarMode::Auto - || h_mode == ScrollBarMode::Hidden - || h_mode == ScrollBarMode::Scroll ); - - switch ( h_mode ) + if ( h_mode == ScrollBarMode::Auto ) { - case ScrollBarMode::Auto: - if ( getScrollWidth() > getViewportWidth() ) - hbar->show(); - else - hbar->hide(); - break; - - case ScrollBarMode::Hidden: - hbar->hide(); - break; - - case ScrollBarMode::Scroll: + if ( getScrollWidth() > getViewportWidth() ) hbar->show(); - break; + else + hbar->hide(); + } + else if ( h_mode == ScrollBarMode::Hidden ) + { + hbar->hide(); + } + else if ( h_mode == ScrollBarMode::Scroll ) + { + hbar->show(); } } //---------------------------------------------------------------------- void FScrollView::setVerticalScrollBarVisibility() const { - assert ( v_mode == ScrollBarMode::Auto - || v_mode == ScrollBarMode::Hidden - || v_mode == ScrollBarMode::Scroll ); - - switch ( v_mode ) + if ( v_mode == ScrollBarMode::Auto ) { - case ScrollBarMode::Auto: - if ( getScrollHeight() > getViewportHeight() ) - vbar->show(); - else - vbar->hide(); - break; - - case ScrollBarMode::Hidden: - vbar->hide(); - break; - - case ScrollBarMode::Scroll: + if ( getScrollHeight() > getViewportHeight() ) vbar->show(); - break; + else + vbar->hide(); + } + else if ( v_mode == ScrollBarMode::Hidden ) + { + vbar->hide(); + } + else if ( v_mode == ScrollBarMode::Scroll ) + { + vbar->show(); } } diff --git a/src/fstring.cpp b/src/fstring.cpp index 32137c95..0d1da758 100644 --- a/src/fstring.cpp +++ b/src/fstring.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2012-2020 Markus Gans * +* Copyright 2012-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -745,7 +745,7 @@ FStringList FString::split (const FString& delimiter) const while ( token ) { - string_list.push_back (FString{token}); + string_list.emplace_back(token); token = _extractToken (&rest, nullptr, delimiter.wc_str()); } diff --git a/src/fterm.cpp b/src/fterm.cpp index db08629e..f6f11d67 100644 --- a/src/fterm.cpp +++ b/src/fterm.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2012-2020 Markus Gans * +* Copyright 2012-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -903,9 +903,9 @@ void FTerm::setPalette (FColor index, int r, int g, int b) const int bb = (b * 1001) / 256; if ( Ic ) - color_str = FTermcap::encodeParameter(Ic, index, rr, gg, bb, 0, 0, 0, 0, 0); + color_str = FTermcap::encodeParameter(Ic, uInt16(index), rr, gg, bb, 0, 0, 0, 0, 0); else if ( Ip ) - color_str = FTermcap::encodeParameter(Ip, index, 0, 0, 0, rr, gg, bb, 0, 0); + color_str = FTermcap::encodeParameter(Ip, uInt16(index), 0, 0, 0, rr, gg, bb, 0, 0); if ( color_str ) { @@ -1949,7 +1949,7 @@ void FTerm::enableMouse() #if defined(__linux__) if ( isLinuxTerm() && openConsole() == 0 ) { - if ( FTerm::getFTermLinux()->isLinuxConsole() ) + if ( FTermLinux::isLinuxConsole() ) gpm_mouse = true; closeConsole(); @@ -2364,6 +2364,7 @@ void FTerm::finishOSspecifics() const const auto& freebsd_console = FTerm::getFTermFreeBSD(); freebsd_console->finish(); #elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(UNIT_TEST) + const auto& openbsd_console = FTerm::getFTermOpenBSD(); openbsd_console->finish(); #endif } diff --git a/src/fterm_functions.cpp b/src/fterm_functions.cpp index 132ab1b3..70755212 100644 --- a/src/fterm_functions.cpp +++ b/src/fterm_functions.cpp @@ -50,6 +50,9 @@ enum class FullWidthSupport Yes = 1 }; +// Constant +constexpr std::size_t NOT_FOUND = static_cast(-1); + // global state static FullWidthSupport has_fullwidth_support = FullWidthSupport::Unknown; @@ -407,7 +410,11 @@ FString getColumnSubString ( const FString& str } else { - if ( col_num + width <= col_len ) + if ( col_first == col_pos && width == 0 && num == 0 ) + { + first++; + } + else if ( col_num + width <= col_len ) { col_num += width; num++; @@ -418,6 +425,8 @@ FString getColumnSubString ( const FString& str num++; break; } + else + break; } } @@ -447,7 +456,7 @@ std::size_t getLengthFromColumnWidth ( const FString& str } //---------------------------------------------------------------------- -std::size_t getColumnWidth (const FString& s, std::size_t pos) +std::size_t getColumnWidth (const FString& s, std::size_t end_pos) { if ( s.isEmpty() ) return 0; @@ -455,10 +464,10 @@ std::size_t getColumnWidth (const FString& s, std::size_t pos) std::size_t column_width{0}; const auto length = s.getLength(); - if ( pos > length ) - pos = length; + if ( end_pos > length ) + end_pos = length; - for (std::size_t i{0}; i < pos; i++) + for (std::size_t i{0}; i < end_pos; i++) { try { @@ -501,17 +510,40 @@ std::size_t getColumnWidth (const wchar_t wchar) else #endif + column_width = wcwidth(wchar); + if ( (wchar >= UniChar::NF_rev_left_arrow2 && wchar <= UniChar::NF_check_mark) || ! hasFullWidthSupports() ) - column_width = 1; - else - column_width = wcwidth(wchar); + { + column_width = std::min(column_width, 1); + } return ( column_width == -1 ) ? 0 : std::size_t(column_width); } //---------------------------------------------------------------------- -std::size_t getColumnWidth (FChar& term_char) +std::size_t getColumnWidth (const FChar& term_char) +{ + return std::size_t(term_char.attr.bit.char_width); +} + +//---------------------------------------------------------------------- +std::size_t getColumnWidth (const FTermBuffer& tbuf) +{ + return ( tbuf.isEmpty() ) + ? 0 + : std::accumulate ( std::next(tbuf.begin()) + , tbuf.end() + , tbuf.front().attr.bit.char_width + , [] (std::size_t s, const FChar& c) + { + return s + c.attr.bit.char_width; + } + ); +} + +//---------------------------------------------------------------------- +void addColumnWidth (FChar& term_char) { const std::size_t char_width = getColumnWidth(term_char.ch[0]); @@ -522,21 +554,117 @@ std::size_t getColumnWidth (FChar& term_char) } else term_char.attr.bit.char_width = char_width & 0x03; - - return char_width; } //---------------------------------------------------------------------- -std::size_t getColumnWidth (const FTermBuffer& tb) +inline int isWhitespace (const wchar_t ch) noexcept { - return std::accumulate ( std::next(tb.begin()) - , tb.end() - , tb.front().attr.bit.char_width - , [] (std::size_t s, const FChar& c) - { - return s + c.attr.bit.char_width; - } - ); + return std::iswspace(static_cast(ch)); +} + +//---------------------------------------------------------------------- +int getCharLength (const FString& string, std::size_t pos) +{ + // Gets the number of characters of the combined character + // at string position pos + + const std::size_t len = string.getLength(); + std::size_t n = pos; + const auto& ch = string[n]; + std::size_t char_width = getColumnWidth(ch); + + if ( isWhitespace(ch) ) + return 1; + + if ( char_width == 0 || n >= len ) + return -1; + + do + { + n++; + char_width = getColumnWidth(string[n]); + } + while ( n < len && char_width == 0 && ! isWhitespace(string[n]) ); + + return int(n - pos); +} + +//---------------------------------------------------------------------- +int getPrevCharLength (const FString& string, std::size_t pos) +{ + // Gets the number of characters of the previous combined character + // at string position pos + + const std::size_t len = string.getLength(); + std::size_t n = pos; + const auto& ch = string[n]; + std::size_t char_width = getColumnWidth(ch); + + if ( (char_width == 0 || n == 0 || n >= len) && ! isWhitespace(ch) ) + return -1; + + do + { + n--; + char_width = getColumnWidth(string[n]); + } + while ( n > 0 && char_width == 0 && ! isWhitespace(string[n]) ); + + if ( char_width == 0 ) + return -1; + + return int(pos - n); +} + +//---------------------------------------------------------------------- +std::size_t searchLeftCharBegin (const FString& string, std::size_t pos) +{ + // Search for the next character position to the left of string position pos + + std::size_t n = pos; + + if ( n == 0 ) + return NOT_FOUND; + + std::size_t char_width{0}; + + do + { + n--; + char_width = getColumnWidth(string[n]); + } + while ( n > 0 && char_width == 0 && ! isWhitespace(string[n]) ); + + if ( n == 0 && char_width == 0 ) + return NOT_FOUND; + + return n; +} + +//---------------------------------------------------------------------- +std::size_t searchRightCharBegin (const FString& string, std::size_t pos) +{ + // Search for the next character position to the right of string position pos + + const std::size_t len = string.getLength(); + std::size_t n = pos; + + if ( n >= len ) + return NOT_FOUND; + + std::size_t char_width{0}; + + do + { + n++; + char_width = getColumnWidth(string[n]); + } + while ( n < len && char_width == 0 && ! isWhitespace(string[n]) ); + + if ( n == len && char_width == 0 ) + return NOT_FOUND; + + return n; } //---------------------------------------------------------------------- @@ -581,7 +709,7 @@ FPoint readCursorPos() if ( pos > 4 ) { constexpr auto parse = "\033[%4d;%4dR"; - std::sscanf(temp.data(), parse, &x, &y); + std::sscanf(temp.data(), parse, &y, &x ); } return FPoint{x, y}; diff --git a/src/ftermbuffer.cpp b/src/ftermbuffer.cpp index 51ce2e7e..a221ced6 100644 --- a/src/ftermbuffer.cpp +++ b/src/ftermbuffer.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2017-2020 Markus Gans * +* Copyright 2017-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -47,14 +47,19 @@ FString FTermBuffer::toString() const { std::wstring wide_string{}; wide_string.reserve(data.size()); - std::transform ( data.begin() - , data.end() - , std::back_inserter(wide_string) - , [] (const FChar& fchar) - { - return fchar.ch[0]; - } - ); + std::for_each ( data.begin() + , data.end() + , [&wide_string] (const FChar& fchar) + { + for (auto&& ch : fchar.ch) + { + if ( ch == L'\0' ) + return; + else + wide_string.push_back(ch); + } + } + ); return wide_string; } @@ -62,19 +67,41 @@ FString FTermBuffer::toString() const int FTermBuffer::write (const FString& string) { assert ( ! string.isNull() ); - const auto len = int(string.getLength()); + data.reserve(data.size() + string.getLength()); + const auto last = string.end(); + auto begin = string.begin(); + auto iter = begin; + int char_width{0}; - for (auto&& c : string) + for (auto&& ch : string) { - FChar nc{FVTerm::getAttribute()}; // next character - nc.ch[0] = c; - nc.attr.byte[2] = 0; - nc.attr.byte[3] = 0; - getColumnWidth(nc); // add column width - data.emplace_back(nc); + auto width = getColumnWidth(ch); + auto wspace = std::iswspace(wint_t(ch)); + + if ( width == 0 && ! wspace ) // zero-width character + { + if ( iter == begin) + ++begin; + + ++iter; + } + else if ( iter != begin ) + add(begin, iter, char_width); + + if ( iter == begin && (width > 0 || is7bit(ch)) ) // 1st char + ++iter; + + if ( width > 0 ) + char_width += width; + + if ( wspace ) + add(begin, iter, char_width); } - return len; + if ( iter == last ) + add(begin, iter, char_width); + + return int(string.getLength()); } //---------------------------------------------------------------------- @@ -82,7 +109,7 @@ int FTermBuffer::write (wchar_t ch) { FChar nc{FVTerm::getAttribute()}; // next character nc.ch[0] = ch; - getColumnWidth(nc); // add column width + addColumnWidth(nc); // add column width nc.attr.bit.no_changes = false; nc.attr.bit.printed = false; data.emplace_back(nc); @@ -96,34 +123,23 @@ void FTermBuffer::write (const FStyle& style) const if ( attr == Style::None ) FVTerm::setNormal(); - else if ( (attr & Style::Bold) != Style::None ) - FVTerm::setBold(); - else if ( (attr & Style::Dim) != Style::None ) - FVTerm::setDim(); - else if ( (attr & Style::Italic) != Style::None ) - FVTerm::setItalic(); - else if ( (attr & Style::Underline) != Style::None ) - FVTerm::setUnderline(); - else if ( (attr & Style::Blink) != Style::None ) - FVTerm::setBlink(); - else if ( (attr & Style::Reverse) != Style::None ) - FVTerm::setReverse(); - else if ( (attr & Style::Standout) != Style::None ) - FVTerm::setStandout(); - else if ( (attr & Style::Invisible) != Style::None ) - FVTerm::setInvisible(); - else if ( (attr & Style::Protected) != Style::None ) - FVTerm::setProtected(); - else if ( (attr & Style::CrossedOut) != Style::None ) - FVTerm::setCrossedOut(); - else if ( (attr & Style::DoubleUnderline) != Style::None ) - FVTerm::setDoubleUnderline(); - else if ( (attr & Style::Transparent) != Style::None ) - FVTerm::setTransparent(); - else if ( (attr & Style::ColorOverlay) != Style::None ) - FVTerm::setColorOverlay(); - else if ( (attr & Style::InheritBackground) != Style::None ) - FVTerm::setInheritBackground(); + else + { + if ( (attr & Style::Bold) != Style::None ) FVTerm::setBold(); + if ( (attr & Style::Dim) != Style::None ) FVTerm::setDim(); + if ( (attr & Style::Italic) != Style::None ) FVTerm::setItalic(); + if ( (attr & Style::Underline) != Style::None ) FVTerm::setUnderline(); + if ( (attr & Style::Blink) != Style::None ) FVTerm::setBlink(); + if ( (attr & Style::Reverse) != Style::None ) FVTerm::setReverse(); + if ( (attr & Style::Standout) != Style::None ) FVTerm::setStandout(); + if ( (attr & Style::Invisible) != Style::None ) FVTerm::setInvisible(); + if ( (attr & Style::Protected) != Style::None ) FVTerm::setProtected(); + if ( (attr & Style::CrossedOut) != Style::None ) FVTerm::setCrossedOut(); + if ( (attr & Style::DoubleUnderline) != Style::None ) FVTerm::setDoubleUnderline(); + if ( (attr & Style::Transparent) != Style::None ) FVTerm::setTransparent(); + if ( (attr & Style::ColorOverlay) != Style::None ) FVTerm::setColorOverlay(); + if ( (attr & Style::InheritBackground) != Style::None ) FVTerm::setInheritBackground(); + } } //---------------------------------------------------------------------- @@ -133,6 +149,34 @@ void FTermBuffer::write (const FColorPair& pair) const } +// private methods of FTermBuffer +//---------------------------------------------------------------------- +void FTermBuffer::add ( FString::const_iterator& begin + , FString::const_iterator& end + , int& char_width ) +{ + if ( begin == end ) + return; + + FChar nc{FVTerm::getAttribute()}; // next character + nc.attr.byte[2] = 0; + nc.attr.byte[3] = 0; + + if ( char_width == 2 && FTerm::getEncoding() != Encoding::UTF8 ) + { + nc.ch[0] = '.'; + nc.attr.bit.char_width = 1; + } + else + nc.attr.bit.char_width = char_width & 0x03; + + std::copy(begin, std::min(end, begin + UNICODE_MAX), nc.ch.begin()); + data.emplace_back(nc); + begin = end; + char_width = 0; +} + + // FTermBuffer non-member operators //---------------------------------------------------------------------- FTermBuffer::FCharVector& operator << ( FTermBuffer::FCharVector& termString diff --git a/src/ftermcap.cpp b/src/ftermcap.cpp index 08f05c9e..9d7dc3b9 100644 --- a/src/ftermcap.cpp +++ b/src/ftermcap.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2015-2020 Markus Gans * +* Copyright 2015-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -92,14 +92,14 @@ void FTermcap::termcap() #else const char* termtype = fterm_data->getTermType(); #endif - terminals.push_back(termtype); // available terminal type + terminals.emplace_back(termtype); // available terminal type if ( color256 ) // 1st fallback if not found - terminals.push_back("xterm-256color"); + terminals.emplace_back("xterm-256color"); - terminals.push_back("xterm"); // 2nd fallback if not found - terminals.push_back("ansi"); // 3rd fallback if not found - terminals.push_back("vt100"); // 4th fallback if not found + terminals.emplace_back("xterm"); // 2nd fallback if not found + terminals.emplace_back("ansi"); // 3rd fallback if not found + terminals.emplace_back("vt100"); // 4th fallback if not found auto iter = terminals.begin(); while ( iter != terminals.end() ) diff --git a/src/ftermlinux.cpp b/src/ftermlinux.cpp index ef0e676f..452713e6 100644 --- a/src/ftermlinux.cpp +++ b/src/ftermlinux.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2018-2020 Markus Gans * +* Copyright 2018-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -241,7 +241,7 @@ void FTermLinux::initCharMap() const } //---------------------------------------------------------------------- -void FTermLinux::finish() +void FTermLinux::finish() const { if ( FTerm::isLinuxTerm() ) { diff --git a/src/ftextview.cpp b/src/ftextview.cpp index b024cfb5..5e730a54 100644 --- a/src/ftextview.cpp +++ b/src/ftextview.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2014-2020 Markus Gans * +* Copyright 2014-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -29,6 +29,7 @@ #include "final/fstring.h" #include "final/fscrollbar.h" #include "final/fstatusbar.h" +#include "final/ftermbuffer.h" #include "final/ftextview.h" #include "final/fwidgetcolors.h" @@ -224,7 +225,6 @@ void FTextView::insert (const FString& str, int pos) else s = FString{str}.rtrim().expandTabs(FTerm::getTabstop()); - auto text_split = s.split("\r\n"); for (auto&& line : text_split) // Line loop @@ -641,19 +641,17 @@ void FTextView::drawText() const std::size_t pos = std::size_t(xoffset) + 1; const auto text_width = getTextWidth(); const FString line(getColumnSubString(data[n], pos, text_width)); - const auto column_width = getColumnWidth(line); std::size_t trailing_whitespace{0}; print() << FPoint{2, 2 - nf_offset + int(y)}; + FTermBuffer line_buffer{}; + line_buffer.write(line); - for (auto&& ch : line) // Column loop - { - if ( getColumnWidth(ch) == 0 ) - continue; - else if ( isPrintable(ch) ) - print (ch); - else - print ('.'); - } + for (auto&& fchar : line_buffer) // Column loop + if ( ! isPrintable(fchar.ch[0]) ) + fchar.ch[0] = L'.'; + + print(line_buffer); + const auto column_width = getColumnWidth(line); if ( column_width <= text_width ) trailing_whitespace = text_width - column_width; @@ -693,7 +691,7 @@ inline bool FTextView::isPrintable (wchar_t ch) const const bool utf8 = ( FTerm::getEncoding() == Encoding::UTF8 ) ? true : false; if ( (utf8 && std::iswprint(std::wint_t(ch))) - || (!utf8 && std::isprint(char(ch))) ) + || (! utf8 && std::isprint(char(ch))) ) return true; return false; diff --git a/src/fvterm.cpp b/src/fvterm.cpp index 9f59f680..8cbc2a95 100644 --- a/src/fvterm.cpp +++ b/src/fvterm.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2016-2020 Markus Gans * +* Copyright 2016-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -40,8 +40,10 @@ #include "final/fstyle.h" #include "final/fsystem.h" #include "final/fterm.h" -#include "final/ftermdata.h" #include "final/ftermbuffer.h" +#include "final/ftermdata.h" +#include "final/ftermdetection.h" +#include "final/ftermfreebsd.h" #include "final/ftermcap.h" #include "final/ftypes.h" #include "final/fvterm.h" @@ -53,6 +55,7 @@ namespace finalcut // static class attributes bool FVTerm::draw_completed{false}; +bool FVTerm::combined_char_support{false}; bool FVTerm::no_terminal_updates{false}; bool FVTerm::cursor_hideable{false}; bool FVTerm::force_terminal_update{false}; @@ -490,10 +493,11 @@ int FVTerm::print (FTermArea* area, FChar& term_char) const int ax = area->cursor_x - 1; const int ay = area->cursor_y - 1; - std::size_t char_width = term_char.attr.bit.char_width; - if ( char_width == 0 ) - char_width = getColumnWidth(term_char); // add column width + if ( term_char.attr.bit.char_width == 0 ) + addColumnWidth(term_char); // add column width + + auto char_width = term_char.attr.bit.char_width; if ( char_width == 0 && ! term_char.attr.bit.fullwidth_padding ) return 0; @@ -535,34 +539,23 @@ void FVTerm::print (const FStyle& style) if ( attr == Style::None ) setNormal(); - else if ( (attr & Style::Bold) != Style::None ) - setBold(); - else if ( (attr & Style::Dim) != Style::None ) - setDim(); - else if ( (attr & Style::Italic) != Style::None ) - setItalic(); - else if ( (attr & Style::Underline) != Style::None ) - setUnderline(); - else if ( (attr & Style::Blink) != Style::None ) - setBlink(); - else if ( (attr & Style::Reverse) != Style::None ) - setReverse(); - else if ( (attr & Style::Standout) != Style::None ) - setStandout(); - else if ( (attr & Style::Invisible) != Style::None ) - setInvisible(); - else if ( (attr & Style::Protected) != Style::None ) - setProtected(); - else if ( (attr & Style::CrossedOut) != Style::None ) - setCrossedOut(); - else if ( (attr & Style::DoubleUnderline) != Style::None ) - setDoubleUnderline(); - else if ( (attr & Style::Transparent) != Style::None ) - setTransparent(); - else if ( (attr & Style::ColorOverlay) != Style::None ) - setColorOverlay(); - else if ( (attr & Style::InheritBackground) != Style::None ) - setInheritBackground(); + else + { + if ( (attr & Style::Bold) != Style::None ) setBold(); + if ( (attr & Style::Dim) != Style::None ) setDim(); + if ( (attr & Style::Italic) != Style::None ) setItalic(); + if ( (attr & Style::Underline) != Style::None ) setUnderline(); + if ( (attr & Style::Blink) != Style::None ) setBlink(); + if ( (attr & Style::Reverse) != Style::None ) setReverse(); + if ( (attr & Style::Standout) != Style::None ) setStandout(); + if ( (attr & Style::Invisible) != Style::None ) setInvisible(); + if ( (attr & Style::Protected) != Style::None ) setProtected(); + if ( (attr & Style::CrossedOut) != Style::None ) setCrossedOut(); + if ( (attr & Style::DoubleUnderline) != Style::None ) setDoubleUnderline(); + if ( (attr & Style::Transparent) != Style::None ) setTransparent(); + if ( (attr & Style::ColorOverlay) != Style::None ) setColorOverlay(); + if ( (attr & Style::InheritBackground) != Style::None ) setInheritBackground(); + } } //---------------------------------------------------------------------- @@ -1285,6 +1278,9 @@ void FVTerm::initTerminal() // Initialize character lengths init_characterLengths(); + + // Check for support for combined characters + init_combined_character(); } @@ -1884,6 +1880,31 @@ void FVTerm::init_characterLengths() if ( clr_eol_length == 0 ) clr_eol_length = INT_MAX; } +#include +//---------------------------------------------------------------------- +void FVTerm::init_combined_character() +{ +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(UNIT_TEST) + if ( FTermFreeBSD::isFreeBSDConsole() ) + return; +#endif + + if ( FTerm::getEncoding() != Encoding::UTF8 ) + return; + + const auto& term_detection = FTerm::getFTermDetection(); + + if ( term_detection->isCygwinTerminal() ) + return; + + if ( term_detection->isXTerminal() + || term_detection->isUrxvtTerminal() + || term_detection->isMinttyTerm() + || term_detection->isPuttyTerminal() ) + { + combined_char_support = true; + } +} //---------------------------------------------------------------------- void FVTerm::finish() @@ -2006,7 +2027,7 @@ void FVTerm::getAreaCharacter ( const FPoint& pos, const FTermArea* area } //---------------------------------------------------------------------- -bool FVTerm::clearTerm (int fillchar) const +bool FVTerm::clearTerm (wchar_t fillchar) const { // Clear the real terminal and put cursor at home @@ -2018,7 +2039,7 @@ bool FVTerm::clearTerm (int fillchar) const appendAttributes (next_attribute); if ( ! ( (cl || cd || cb) && (normal || ut) ) - || fillchar != ' ' ) + || fillchar != L' ' ) { return false; } @@ -2570,7 +2591,7 @@ FVTerm::PrintState FVTerm::repeatCharacter (uInt& x, uInt xmax, uInt y) const const uInt start_pos = x; if ( repetitions > repeat_char_length - && print_char.ch[0] < 128 ) + && is7bit(print_char.ch[0]) && print_char.ch[1] == L'\0' ) { newFontChanges (print_char); charsetChanges (print_char); @@ -2917,7 +2938,9 @@ inline void FVTerm::newFontChanges (FChar& next_char) inline void FVTerm::charsetChanges (FChar& next_char) { const wchar_t& ch = next_char.ch[0]; - next_char.encoded_char[0] = ch; + std::copy( next_char.ch.begin() + , next_char.ch.end() + , next_char.encoded_char.begin() ); if ( FTerm::getEncoding() == Encoding::UTF8 ) return; @@ -2979,7 +3002,15 @@ inline void FVTerm::appendChar (FChar& next_char) const charsetChanges (next_char); appendAttributes (next_char); characterFilter (next_char); - appendOutputBuffer (next_char.encoded_char[0]); + + for (auto&& ch : next_char.encoded_char) + { + if ( ch != L'\0') + appendOutputBuffer(ch); + + if ( ! combined_char_support ) + return; + } } //---------------------------------------------------------------------- diff --git a/src/include/final/fc.h b/src/include/final/fc.h index fd6f6016..3a220efe 100644 --- a/src/include/final/fc.h +++ b/src/include/final/fc.h @@ -801,7 +801,7 @@ enum class FKey : uInt32 struct FKeyHash { - std::size_t operator () (const FKey& p) const + std::size_t operator () (const FKey& p) const noexcept { return std::hash()(uInt32(p)); } diff --git a/src/include/final/flineedit.h b/src/include/final/flineedit.h index 615f8a82..79fb154a 100644 --- a/src/include/final/flineedit.h +++ b/src/include/final/flineedit.h @@ -170,6 +170,7 @@ class FLineEdit : public FWidget // Constants static constexpr auto NOT_SET = static_cast(-1); + static constexpr auto NOT_FOUND = static_cast(-1); // Methods void init(); diff --git a/src/include/final/fstring.h b/src/include/final/fstring.h index 4cfaeb23..1b77b994 100644 --- a/src/include/final/fstring.h +++ b/src/include/final/fstring.h @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2012-2020 Markus Gans * +* Copyright 2012-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -167,21 +167,21 @@ class FString virtual FString getClassName() const; // inquiries - bool isNull() const; - bool isEmpty() const; + bool isNull() const noexcept; + bool isEmpty() const noexcept; // Methods - std::size_t getLength() const; - std::size_t capacity() const; + std::size_t getLength() const noexcept; + std::size_t capacity() const noexcept; - iterator begin(); - iterator end(); - const_iterator begin() const; - const_iterator end() const; - reference front(); - reference back() ; - const_reference front() const; - const_reference back() const; + iterator begin() noexcept; + iterator end() noexcept; + const_iterator begin() const noexcept; + const_iterator end() const noexcept; + reference front() noexcept; + reference back() noexcept; + const_reference front() const noexcept; + const_reference back() const noexcept; template FString& sprintf (const FString&, Args&&...); @@ -371,60 +371,60 @@ inline FString FString::getClassName() const { return "FString"; } //---------------------------------------------------------------------- -inline bool FString::isNull() const +inline bool FString::isNull() const noexcept { return ( bufsize == 0 || (bufsize > 0 && ! string) ); } //---------------------------------------------------------------------- -inline bool FString::isEmpty() const +inline bool FString::isEmpty() const noexcept { return ( length == 0 || (length > 0 && string[0] == L'\0') ); } //---------------------------------------------------------------------- -inline std::size_t FString::getLength() const +inline std::size_t FString::getLength() const noexcept { return length; } //---------------------------------------------------------------------- -inline std::size_t FString::capacity() const +inline std::size_t FString::capacity() const noexcept { return ( length > 0 ) ? bufsize - 1 : 0; } //---------------------------------------------------------------------- -inline FString::iterator FString::begin() +inline FString::iterator FString::begin() noexcept { return string; } //---------------------------------------------------------------------- -inline FString::iterator FString::end() +inline FString::iterator FString::end() noexcept { return string + length; } //---------------------------------------------------------------------- -inline FString::const_iterator FString::begin() const +inline FString::const_iterator FString::begin() const noexcept { return string; } //---------------------------------------------------------------------- -inline FString::const_iterator FString::end() const +inline FString::const_iterator FString::end() const noexcept { return string + length; } //---------------------------------------------------------------------- -inline FString::reference FString::front() +inline FString::reference FString::front() noexcept { assert ( ! isEmpty() ); return (*this)[0]; } //---------------------------------------------------------------------- -inline FString::reference FString::back() +inline FString::reference FString::back() noexcept { assert( ! isEmpty() ); return (*this)[length - 1]; } //---------------------------------------------------------------------- -inline FString::const_reference FString::front() const +inline FString::const_reference FString::front() const noexcept { assert ( ! isEmpty() ); return (*this)[0]; } //---------------------------------------------------------------------- -inline FString::const_reference FString::back() const +inline FString::const_reference FString::back() const noexcept { assert( ! isEmpty() ); return (*this)[length - 1]; diff --git a/src/include/final/fterm.h b/src/include/final/fterm.h index e7b26554..c1c6cdb2 100644 --- a/src/include/final/fterm.h +++ b/src/include/final/fterm.h @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2012-2020 Markus Gans * +* Copyright 2012-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -381,10 +381,23 @@ std::size_t getLengthFromColumnWidth (const FString&, std::size_t); std::size_t getColumnWidth (const FString&, std::size_t); std::size_t getColumnWidth (const FString&); std::size_t getColumnWidth (const wchar_t); -std::size_t getColumnWidth (FChar&); +std::size_t getColumnWidth (const FChar&); std::size_t getColumnWidth (const FTermBuffer&); +void addColumnWidth (FChar&); +int getCharLength (const FString&, std::size_t); +int getPrevCharLength (const FString&, std::size_t); +std::size_t searchLeftCharBegin (const FString&, std::size_t); +std::size_t searchRightCharBegin (const FString&, std::size_t); FPoint readCursorPos(); +// Check for 7-bit ASCII +template +inline bool is7bit (CharT ch) +{ + using char_type = typename std::make_unsigned::type; + return static_cast(ch) < 128; +} + // FTerm inline functions //---------------------------------------------------------------------- inline FString FTerm::getClassName() diff --git a/src/include/final/ftermbuffer.h b/src/include/final/ftermbuffer.h index 868f2417..e5700fe3 100644 --- a/src/include/final/ftermbuffer.h +++ b/src/include/final/ftermbuffer.h @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2017-2020 Markus Gans * +* Copyright 2017-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -110,6 +110,9 @@ class FTermBuffer private: FCharVector data{}; + void add ( FString::const_iterator& + , FString::const_iterator& + , int& ); // Non-member operators friend FCharVector& operator << ( FCharVector& diff --git a/src/include/final/ftermlinux.h b/src/include/final/ftermlinux.h index c837c54e..7084dbaf 100644 --- a/src/include/final/ftermlinux.h +++ b/src/include/final/ftermlinux.h @@ -109,7 +109,7 @@ class FTermLinux final // Methods void init(); void initCharMap() const; - void finish(); + void finish() const; bool loadVGAFont(); bool loadNewFont(); bool loadOldFont(); diff --git a/src/include/final/ftypes.h b/src/include/final/ftypes.h index 713c1b49..76826716 100644 --- a/src/include/final/ftypes.h +++ b/src/include/final/ftypes.h @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2017-2020 Markus Gans * +* Copyright 2017-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -157,7 +157,7 @@ union attribute uInt8 byte[4]; }; -static constexpr uInt UNICODE_MAX = 5; +static constexpr std::size_t UNICODE_MAX = 5; using FUnicode = std::array; diff --git a/src/include/final/fvterm.h b/src/include/final/fvterm.h index 6f3fb0e5..d0e98470 100644 --- a/src/include/final/fvterm.h +++ b/src/include/final/fvterm.h @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2016-2020 Markus Gans * +* Copyright 2016-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -339,7 +339,7 @@ class FVTerm // Constants // Buffer size for character output on the terminal - static constexpr uInt TERMINAL_OUTPUT_BUFFER_SIZE = 131072; + static constexpr std::size_t TERMINAL_OUTPUT_BUFFER_SIZE = 131072; // Methods void resetTextAreaToDefault ( const FTermArea* @@ -371,13 +371,14 @@ class FVTerm static FChar getOverlappedCharacter (const FPoint&, const FTermArea*); void init(); static void init_characterLengths(); + static void init_combined_character(); void finish(); static void putAreaLine (const FChar&, FChar&, std::size_t); static void putAreaCharacter ( const FPoint&, const FTermArea* , const FChar&, FChar& ); static void getAreaCharacter ( const FPoint&, const FTermArea* , FChar*& ); - bool clearTerm (int = ' ') const; + bool clearTerm (wchar_t = L' ') const; bool clearFullArea (const FTermArea*, FChar&) const; static void clearAreaWithShadow (const FTermArea*, const FChar&); static bool canClearToEOL (uInt, uInt); @@ -439,6 +440,7 @@ class FVTerm static timeval time_last_flush; static timeval last_term_size_check; static bool draw_completed; + static bool combined_char_support; static bool no_terminal_updates; static bool force_terminal_update; static uInt64 flush_wait; diff --git a/test/Makefile.am b/test/Makefile.am index 35396361..53dd0b99 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -12,7 +12,9 @@ noinst_PROGRAMS = \ fdata_test \ fmouse_test \ fkeyboard_test \ + fterm_functions_test \ ftermdata_test \ + ftermbuffer_test \ ftermdetection_test \ ftermcapquirks_test \ ftermlinux_test \ @@ -34,7 +36,9 @@ fcallback_test_SOURCES = fcallback-test.cpp fdata_test_SOURCES = fdata-test.cpp fmouse_test_SOURCES = fmouse-test.cpp fkeyboard_test_SOURCES = fkeyboard-test.cpp +fterm_functions_test_SOURCES = fterm_functions-test.cpp ftermdata_test_SOURCES = ftermdata-test.cpp +ftermbuffer_test_SOURCES = ftermbuffer-test.cpp ftermdetection_test_SOURCES = ftermdetection-test.cpp ftermcapquirks_test_SOURCES = ftermcapquirks-test.cpp ftermlinux_test_SOURCES = ftermlinux-test.cpp @@ -56,7 +60,9 @@ TESTS = fobject_test \ fdata_test \ fmouse_test \ fkeyboard_test \ + fterm_functions_test \ ftermdata_test \ + ftermbuffer_test \ ftermdetection_test \ ftermcapquirks_test \ ftermlinux_test \ diff --git a/test/fterm_functions-test.cpp b/test/fterm_functions-test.cpp new file mode 100644 index 00000000..ea0b6b54 --- /dev/null +++ b/test/fterm_functions-test.cpp @@ -0,0 +1,2561 @@ +/*********************************************************************** +* fterm_functions-test.cpp - FTerm function unit tests * +* * +* This file is part of the FINAL CUT widget toolkit * +* * +* Copyright 2021 Markus Gans * +* * +* FINAL CUT 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 3 of * +* the License, or (at your option) any later version. * +* * +* FINAL CUT 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 program. If not, see * +* . * +***********************************************************************/ +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +//---------------------------------------------------------------------- +// class FTermFunctionsTest +//---------------------------------------------------------------------- + +class FTermFunctionsTest : public CPPUNIT_NS::TestFixture, test::ConEmu +{ + public: + FTermFunctionsTest() + { + std::setlocale (LC_CTYPE, "en_US.UTF-8"); + fwide(stdout, 1); // Makes stream wide-character oriented + } + + protected: + void env2uintTest(); + void isReverseNewFontcharTest(); + void cp437Test(); + void FullWidthHalfWidthTest(); + void combiningCharacterTest(); + void readCursorPosTest(); + + private: + // Constant + constexpr static std::size_t NOT_FOUND = static_cast(-1); + + // Adds code needed to register the test suite + CPPUNIT_TEST_SUITE (FTermFunctionsTest); + + // Add a methods to the test suite + CPPUNIT_TEST (env2uintTest); + CPPUNIT_TEST (isReverseNewFontcharTest); + CPPUNIT_TEST (cp437Test); + CPPUNIT_TEST (FullWidthHalfWidthTest); + CPPUNIT_TEST (combiningCharacterTest); + CPPUNIT_TEST (readCursorPosTest); + + // End of test suite definition + CPPUNIT_TEST_SUITE_END(); +}; + + +//---------------------------------------------------------------------- +void FTermFunctionsTest::env2uintTest() +{ + setenv ("NUM1", "123", 1); + CPPUNIT_ASSERT ( finalcut::env2uint("NUM1") == 123 ); + setenv ("NUM2", "4294967295", 1); + CPPUNIT_ASSERT ( finalcut::env2uint("NUM2") == UINT_MAX ); + // Overflow + setenv ("NUM3", "999999999999999999999999999999999", 1); + CPPUNIT_ASSERT ( finalcut::env2uint("NUM3") == UINT_MAX ); + // not unsigned! + setenv ("NUM4", "-123", 1); + CPPUNIT_ASSERT ( finalcut::env2uint("NUM4") == 0 ); + // Invalid + CPPUNIT_ASSERT ( finalcut::env2uint("NON_EXISTENT_VARIABLE") == 0 ); +} + +//---------------------------------------------------------------------- +void FTermFunctionsTest::isReverseNewFontcharTest() +{ + CPPUNIT_ASSERT ( ! finalcut::isReverseNewFontchar(L'A') ); + CPPUNIT_ASSERT ( ! finalcut::isReverseNewFontchar(L'£') ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_left_arrow2)) ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_right_arrow2)) ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_border_corner_upper_right)) ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_border_line_right)) ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_border_line_vertical_left)) ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_border_corner_lower_right)) ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_up_arrow2)) ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_down_arrow2)) ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_up_arrow1)) ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_down_arrow1)) ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_left_arrow1)) ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_right_arrow1)) ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_menu_button1)) ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_menu_button2)) ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_up_pointing_triangle1)) ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_down_pointing_triangle1)) ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_up_pointing_triangle2)) ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_down_pointing_triangle2)) ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_menu_button3)) ); + CPPUNIT_ASSERT ( finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_rev_border_line_right_and_left)) ); + CPPUNIT_ASSERT ( ! finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_shadow_box_checked)) ); + CPPUNIT_ASSERT ( ! finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::NF_Bullet)) ); + CPPUNIT_ASSERT ( ! finalcut::isReverseNewFontchar(wchar_t(finalcut::UniChar::SquareRoot)) ); +} + +//---------------------------------------------------------------------- +void FTermFunctionsTest::cp437Test() +{ + // CP437 -> Unicode + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x01) == L'☺' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x02) == L'☻' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x03) == L'♥' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x04) == L'♦' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x05) == L'♣' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x06) == L'♠' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x07) == L'•' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x08) == L'◘' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x09) == L'○' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x0a) == L'◙' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x0b) == L'♂' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x0c) == L'♀' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x0d) == L'♪' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x0e) == L'♫' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x0f) == L'☼' ); + + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x10) == L'►' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x11) == L'◄' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x12) == L'↕' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x13) == L'‼' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x14) == L'¶' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x15) == L'§' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x16) == L'▬' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x17) == L'↨' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x18) == L'↑' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x19) == L'↓' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x1a) == L'→' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x1b) == L'←' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x1c) == L'∟' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x1d) == L'↔' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x1e) == L'▲' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x1f) == L'▼' ); + + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x9b) == L'¢' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x9c) == L'£' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x9d) == L'¥' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0x9e) == L'₧' ); + + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0xb0) == L'░' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0xb1) == L'▒' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0xb2) == L'▓' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0xdb) == L'█' ); + + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0xdf) == L'▀' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0xdc) == L'▄' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0xdd) == L'▌' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0xde) == L'▐' ); + + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0xc4) == L'─' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0xb3) == L'│' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0xc3) == L'├' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0xb4) == L'┤' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0xc5) == L'┼' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0xbf) == L'┐' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0xc0) == L'└' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0xda) == L'┌' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0xd9) == L'┘' ); + + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0xf4) == L'⌠' ); + CPPUNIT_ASSERT ( finalcut::cp437_to_unicode(0xf5) == L'⌡' ); + + // Unicode -> CP437 + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'☺') == 0x01 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'☻') == 0x02 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'♥') == 0x03 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'♦') == 0x04 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'♣') == 0x05 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'♠') == 0x06 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'•') == 0x07 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'◘') == 0x08 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'○') == 0x09 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'◙') == 0x0a ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'♂') == 0x0b ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'♀') == 0x0c ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'♪') == 0x0d ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'♫') == 0x0e ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'☼') == 0x0f ); + + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'►') == 0x10 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'◄') == 0x11 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'↕') == 0x12 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'‼') == 0x13 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'¶') == 0x14 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'§') == 0x15 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'▬') == 0x16 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'↨') == 0x17 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'↑') == 0x18 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'↓') == 0x19 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'→') == 0x1a ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'←') == 0x1b ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'∟') == 0x1c ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'↔') == 0x1d ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'▲') == 0x1e ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'▼') == 0x1f ); + + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'¢') == 0x9b ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'£') == 0x9c ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'¥') == 0x9d ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'₧') == 0x9e ); + + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'░') == 0xb0 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'▒') == 0xb1 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'▓') == 0xb2 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'█') == 0xdb ); + + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'▀') == 0xdf ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'▄') == 0xdc ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'▌') == 0xdd ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'▐') == 0xde ); + + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'─') == 0xc4 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'│') == 0xb3 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'├') == 0xc3 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'┤') == 0xb4 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'┼') == 0xc5 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'┐') == 0xbf ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'└') == 0xc0 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'┌') == 0xda ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'┘') == 0xd9 ); + + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'⌠') == 0xf4 ); + CPPUNIT_ASSERT ( finalcut::unicode_to_cp437(L'⌡') == 0xf5 ); +} + +//---------------------------------------------------------------------- +void FTermFunctionsTest::FullWidthHalfWidthTest() +{ + CPPUNIT_ASSERT ( finalcut::hasFullWidthSupports() ); + + // Test the conversion from half-width to full-width characters + CPPUNIT_ASSERT ( finalcut::getFullWidth(L' ') == L" " ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'!') == L"!" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'"') == L""" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'#') == L"#" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'$') == L"$" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'%') == L"%" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'&') == L"&" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'\'') == L"'" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'(') == L"(" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L')') == L")" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'*') == L"*" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'+') == L"+" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L',') == L"," ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'-') == L"-" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'.') == L"." ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'/') == L"/" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'0') == L"0" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'1') == L"1" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'2') == L"2" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'3') == L"3" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'4') == L"4" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'5') == L"5" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'6') == L"6" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'7') == L"7" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'8') == L"8" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'9') == L"9" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L':') == L":" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L';') == L";" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'<') == L"<" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'=') == L"=" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'>') == L">" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'?') == L"?" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'@') == L"@" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'A') == L"A" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'B') == L"B" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'C') == L"C" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'D') == L"D" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'E') == L"E" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'F') == L"F" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'G') == L"G" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'H') == L"H" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'I') == L"I" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'J') == L"J" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'K') == L"K" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'L') == L"L" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'M') == L"M" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'N') == L"N" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'O') == L"O" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'P') == L"P" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'Q') == L"Q" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'R') == L"R" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'S') == L"S" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'T') == L"T" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'U') == L"U" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'V') == L"V" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'W') == L"W" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'X') == L"X" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'Y') == L"Y" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'Z') == L"Z" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'[') == L"[" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'\\') == L"\" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L']') == L"]" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'^') == L"^" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'_') == L"_" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'`') == L"`" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'a') == L"a" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'b') == L"b" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'c') == L"c" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'd') == L"d" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'e') == L"e" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'f') == L"f" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'g') == L"g" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'h') == L"h" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'i') == L"i" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'j') == L"j" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'k') == L"k" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'l') == L"l" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'm') == L"m" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'n') == L"n" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'o') == L"o" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'p') == L"p" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'q') == L"q" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'r') == L"r" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L's') == L"s" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L't') == L"t" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'u') == L"u" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'v') == L"v" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'w') == L"w" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'x') == L"x" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'y') == L"y" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'z') == L"z" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'{') == L"{" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'|') == L"|" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'}') == L"}" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'~') == L"~" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'←') == L"←" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'↑') == L"↑" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'→') == L"→" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'↓') == L"↓" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'¢') == L"¢" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'£') == L"£" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'ア') == L"ア" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'イ') == L"イ" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'ウ') == L"ウ" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'エ') == L"エ" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'ᄀ') == L"ㄱ" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'ᄁ') == L"ㄲ" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'ᆪ') == L"ㄳ" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'ᄂ') == L"ㄴ" ); + // Only half-width + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'Ā') == L"Ā" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'ā') == L"ā" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'Ă') == L"Ă" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'ă') == L"ă" ); + CPPUNIT_ASSERT ( finalcut::getFullWidth(L'Ą') == L"Ą" ); + + // Test the conversion from full-width to half-width characters + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L" ") == L" " ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"!") == L"!" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L""") == L"\"" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"#") == L"#" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"$") == L"$" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"%") == L"%" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"&") == L"&" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"'") == L"'" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"(") == L"(" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L")") == L")" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"*") == L"*" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"+") == L"+" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L",") == L"," ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"-") == L"-" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L".") == L"." ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"/") == L"/" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"0") == L"0" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"1") == L"1" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"2") == L"2" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"3") == L"3" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"4") == L"4" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"5") == L"5" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"6") == L"6" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"7") == L"7" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"8") == L"8" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"9") == L"9" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L":") == L":" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L";") == L";" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"<") == L"<" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"=") == L"=" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L">") == L">" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"?") == L"?" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"@") == L"@" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"A") == L"A" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"B") == L"B" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"C") == L"C" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"D") == L"D" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"E") == L"E" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"F") == L"F" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"G") == L"G" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"H") == L"H" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"I") == L"I" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"J") == L"J" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"K") == L"K" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"L") == L"L" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"M") == L"M" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"N") == L"N" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"O") == L"O" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"P") == L"P" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"Q") == L"Q" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"R") == L"R" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"S") == L"S" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"T") == L"T" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"U") == L"U" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"V") == L"V" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"W") == L"W" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"X") == L"X" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"Y") == L"Y" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"Z") == L"Z" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"[") == L"[" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"\") == L"\\" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"]") == L"]" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"^") == L"^" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"_") == L"_" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"`") == L"`" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"a") == L"a" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"b") == L"b" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"c") == L"c" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"d") == L"d" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"e") == L"e" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"f") == L"f" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"g") == L"g" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"h") == L"h" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"i") == L"i" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"j") == L"j" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"k") == L"k" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"l") == L"l" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"m") == L"m" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"n") == L"n" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"o") == L"o" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"p") == L"p" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"q") == L"q" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"r") == L"r" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"s") == L"s" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"t") == L"t" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"u") == L"u" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"v") == L"v" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"w") == L"w" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"x") == L"x" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"y") == L"y" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"z") == L"z" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"{") == L"{" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"|") == L"|" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"}") == L"}" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"~") == L"~" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"←" ) == L"←"); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"↑" ) == L"↑"); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"→" ) == L"→"); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"↓" ) == L"↓"); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"¢") == L"¢" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"£") == L"£" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"ア") == L"ア" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"イ") == L"イ" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"ウ") == L"ウ" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"エ") == L"エ" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"ㄱ") == L"ᄀ" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"ㄲ") == L"ᄁ" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"ㄳ") == L"ᆪ" ); + CPPUNIT_ASSERT ( finalcut::getHalfWidth(L"ㄴ") == L"ᄂ" ); + + // Column width (wchar_t) + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"\t") == 0 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"\r") == 0 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"\n") == 0 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"\v") == 0 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L" ") == 1 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"0") == 1 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1") == 1 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"2") == 1 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"3") == 1 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"0") == 2 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1") == 2 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"2") == 2 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"3") == 2 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"\U00000300") == 0 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"\U00000348") == 0 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"\U0000094d") == 0 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"\U00000e37") == 0 ); + + // Column width (FString) + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"\v\t 100") == 4 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"0123456789") == 10 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"0123456789") == 20 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"abc") == 3 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"abc") == 5 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"你好") == 4 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"你好 one CUT more") == 20 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more") == 23 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"o\U0000031b\U00000323=\U00001ee3") == 3 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"STARGΛ̊TE") == 8 ); + + // Column width (FString) with end position + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"\v\t 100", 0) == 0 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"\v\t 100", 1) == 0 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"\v\t 100", 2) == 0 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"\v\t 100", 3) == 1 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"\v\t 100", 4) == 2 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"\v\t 100", 5) == 3 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"\v\t 100", 6) == 4 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"\v\t 100", 7) == 4 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"0123", 0) == 0 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"0123", 1) == 1 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"0123", 2) == 2 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"0123", 3) == 3 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"0123", 4) == 4 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"0123", 0) == 0 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"0123", 1) == 2 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"0123", 2) == 4 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"0123", 3) == 6 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"0123", 4) == 8 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"你好 one CUT more", 0) == 0 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"你好 one CUT more", 1) == 2 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"你好 one CUT more", 2) == 4 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"你好 one CUT more", 3) == 5 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"你好 one CUT more", 4) == 6 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"你好 one CUT more", 5) == 7 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"你好 one CUT more", 6) == 8 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"你好 one CUT more", 7) == 9 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"你好 one CUT more", 8) == 11 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"你好 one CUT more", 9) == 13 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"你好 one CUT more", 10) == 15 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"你好 one CUT more", 11) == 16 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"你好 one CUT more", 12) == 17 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"你好 one CUT more", 13) == 18 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"你好 one CUT more", 14) == 19 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"你好 one CUT more", 15) == 20 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 0) == 0 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 1) == 1 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 2) == 2 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 3) == 3 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 4) == 4 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 5) == 5 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 6) == 6 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 7) == 7 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 8) == 8 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 9) == 9 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 10) == 10 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 11) == 11 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 12) == 12 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 13) == 14 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 14) == 16 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 15) == 18 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 16) == 19 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 17) == 20 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 18) == 21 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 19) == 22 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"1234567 one CUT more", 20) == 23 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"o\U0000031b\U00000323=\U00001ee3", 0) == 0 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"o\U0000031b\U00000323=\U00001ee3", 1) == 1 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"o\U0000031b\U00000323=\U00001ee3", 2) == 1 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"o\U0000031b\U00000323=\U00001ee3", 3) == 1 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"o\U0000031b\U00000323=\U00001ee3", 4) == 2 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"o\U0000031b\U00000323=\U00001ee3", 5) == 3 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"STARGΛ̊TE", 0) == 0 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"STARGΛ̊TE", 1) == 1 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"STARGΛ̊TE", 2) == 2 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"STARGΛ̊TE", 3) == 3 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"STARGΛ̊TE", 4) == 4 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"STARGΛ̊TE", 5) == 5 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"STARGΛ̊TE", 6) == 6 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"STARGΛ̊TE", 7) == 6 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"STARGΛ̊TE", 8) == 7 ); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(L"STARGΛ̊TE", 9) == 8 ); + + // String length from the first to the specified end column + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"\v\t 100", 0) == 0 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"\v\t 100", 1) == 3 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"\v\t 100", 2) == 4 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"\v\t 100", 3) == 5 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"\v\t 100", 4) == 6 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"\v\t 100", 5) == 6 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"0123", 0) == 0 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"0123", 1) == 1 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"0123", 2) == 2 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"0123", 3) == 3 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"0123", 4) == 4 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"0123", 0) == 0 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"0123", 1) == 1 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"0123", 2) == 1 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"0123", 3) == 2 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"0123", 4) == 2 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"0123", 5) == 3 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"0123", 6) == 3 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"0123", 7) == 4 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"0123", 8) == 4 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 0) == 0 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 1) == 1 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 2) == 1 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 3) == 2 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 4) == 2 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 5) == 3 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 6) == 4 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 7) == 5 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 8) == 6 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 9) == 7 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 10) == 8 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 11) == 8 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 12) == 9 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 13) == 9 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 14) == 10 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 15) == 10 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 16) == 11 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 17) == 12 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 18) == 13 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 19) == 14 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"你好 one CUT more", 20) == 15 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 0) == 0 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 1) == 1 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 2) == 2 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 3) == 3 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 4) == 4 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 5) == 5 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 6) == 6 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 7) == 7 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 8) == 8 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 9) == 9 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 10) == 10 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 11) == 11 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 12) == 12 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 13) == 13 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 14) == 13 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 15) == 14 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 16) == 14 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 17) == 15 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 18) == 15 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 19) == 16 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 20) == 17 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 21) == 18 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 22) == 19 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"1234567 one CUT more", 23) == 20 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"o\U0000031b\U00000323=\U00001ee3", 0) == 0 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"o\U0000031b\U00000323=\U00001ee3", 1) == 1 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"o\U0000031b\U00000323=\U00001ee3", 2) == 4 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"o\U0000031b\U00000323=\U00001ee3", 3) == 5 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"STARGΛ̊TE", 0) == 0 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"STARGΛ̊TE", 1) == 1 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"STARGΛ̊TE", 2) == 2 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"STARGΛ̊TE", 3) == 3 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"STARGΛ̊TE", 4) == 4 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"STARGΛ̊TE", 5) == 5 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"STARGΛ̊TE", 6) == 6 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"STARGΛ̊TE", 7) == 8 ); + CPPUNIT_ASSERT ( finalcut::getLengthFromColumnWidth(L"STARGΛ̊TE", 8) == 9 ); + + // Column width (FChar) + finalcut::FChar fchar{}; + std::wstring s = L"1"; + std::copy(std::begin(s), std::end(s), std::begin(fchar.ch)); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + finalcut::addColumnWidth(fchar); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 1 ); + fchar.attr.bit.char_width = 0x00 & 0x03; + s = L"\t"; + std::copy(std::begin(s), std::end(s), std::begin(fchar.ch)); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + finalcut::addColumnWidth(fchar); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + fchar.attr.bit.char_width = 0x00 & 0x03; + s = L"\r"; + std::copy(std::begin(s), std::end(s), std::begin(fchar.ch)); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + finalcut::addColumnWidth(fchar); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + fchar.attr.bit.char_width = 0x00 & 0x03; + s = L"\n"; + std::copy(std::begin(s), std::end(s), std::begin(fchar.ch)); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + finalcut::addColumnWidth(fchar); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + fchar.attr.bit.char_width = 0x00 & 0x03; + s = L"\v"; + std::copy(std::begin(s), std::end(s), std::begin(fchar.ch)); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + finalcut::addColumnWidth(fchar); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + fchar.attr.bit.char_width = 0x00 & 0x03; + s = L" "; + std::copy(std::begin(s), std::end(s), std::begin(fchar.ch)); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + finalcut::addColumnWidth(fchar); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 1 ); + fchar.attr.bit.char_width = 0x00 & 0x03; + s = L"0"; + std::copy(std::begin(s), std::end(s), std::begin(fchar.ch)); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + finalcut::addColumnWidth(fchar); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 1 ); + fchar.attr.bit.char_width = 0x00 & 0x03; + s = L"1"; + std::copy(std::begin(s), std::end(s), std::begin(fchar.ch)); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + finalcut::addColumnWidth(fchar); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 1 ); + fchar.attr.bit.char_width = 0x00 & 0x03; + s = L"2"; + std::copy(std::begin(s), std::end(s), std::begin(fchar.ch)); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + finalcut::addColumnWidth(fchar); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 1 ); + fchar.attr.bit.char_width = 0x00 & 0x03; + s = L"3"; + std::copy(std::begin(s), std::end(s), std::begin(fchar.ch)); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + finalcut::addColumnWidth(fchar); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 1 ); + fchar.attr.bit.char_width = 0x00 & 0x03; + s = L"0"; + std::copy(std::begin(s), std::end(s), std::begin(fchar.ch)); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + finalcut::addColumnWidth(fchar); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 1 ); + fchar.attr.bit.char_width = 0x00 & 0x03; + s = L"1"; + std::copy(std::begin(s), std::end(s), std::begin(fchar.ch)); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + finalcut::addColumnWidth(fchar); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 1 ); + fchar.attr.bit.char_width = 0x00 & 0x03; + s = L"2"; + std::copy(std::begin(s), std::end(s), std::begin(fchar.ch)); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + finalcut::addColumnWidth(fchar); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 1 ); + fchar.attr.bit.char_width = 0x00 & 0x03; + s = L"3"; + std::copy(std::begin(s), std::end(s), std::begin(fchar.ch)); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + finalcut::addColumnWidth(fchar); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 1 ); + fchar.attr.bit.char_width = 0x00 & 0x03; + s = L"\U00000300"; + std::copy(std::begin(s), std::end(s), std::begin(fchar.ch)); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + finalcut::addColumnWidth(fchar); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + fchar.attr.bit.char_width = 0x00 & 0x03; + s = L"\U00000348"; + std::copy(std::begin(s), std::end(s), std::begin(fchar.ch)); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + finalcut::addColumnWidth(fchar); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + fchar.attr.bit.char_width = 0x00 & 0x03; + s = L"\U0000094d"; + std::copy(std::begin(s), std::end(s), std::begin(fchar.ch)); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + finalcut::addColumnWidth(fchar); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + fchar.attr.bit.char_width = 0x00 & 0x03; + s = L"\U00000e37"; + std::copy(std::begin(s), std::end(s), std::begin(fchar.ch)); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + finalcut::addColumnWidth(fchar); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(fchar) == 0 ); + fchar.attr.bit.char_width = 0x00 & 0x03; + + // Column width (FTermBuffer) + const auto& data = finalcut::FTerm::getFTermData(); + data->setTermEncoding (finalcut::Encoding::UTF8); + finalcut::FTermBuffer term_buf{}; + term_buf << L"\v\t 100"; + CPPUNIT_ASSERT ( finalcut::getColumnWidth(term_buf) == 4 ); + term_buf.clear(); + term_buf << L"0123456789"; + CPPUNIT_ASSERT ( finalcut::getColumnWidth(term_buf) == 10 ); + term_buf.clear(); + term_buf << L"0123456789"; + CPPUNIT_ASSERT ( finalcut::getColumnWidth(term_buf) == 20 ); // UTF-8 + term_buf.clear(); + data->setTermEncoding (finalcut::Encoding::PC); + term_buf << L"0123456789"; + CPPUNIT_ASSERT ( finalcut::getColumnWidth(term_buf) == 10 ); // CP-437 + term_buf.clear(); + data->setTermEncoding (finalcut::Encoding::UTF8); + CPPUNIT_ASSERT ( finalcut::getColumnWidth(term_buf) == 0 ); // after clear + term_buf << L"abc"; + CPPUNIT_ASSERT ( finalcut::getColumnWidth(term_buf) == 3 ); + term_buf.clear(); + term_buf << L"abc"; + CPPUNIT_ASSERT ( finalcut::getColumnWidth(term_buf) == 5 ); + term_buf.clear(); + term_buf << L"你好"; + CPPUNIT_ASSERT ( finalcut::getColumnWidth(term_buf) == 4 ); + term_buf.clear(); + term_buf << L"你好 one CUT more"; + CPPUNIT_ASSERT ( finalcut::getColumnWidth(term_buf) == 20 ); + term_buf.clear(); + term_buf << L"1234567 one CUT more"; + CPPUNIT_ASSERT ( finalcut::getColumnWidth(term_buf) == 23 ); + term_buf.clear(); + term_buf << L"o\U0000031b\U00000323=\U00001ee3"; + CPPUNIT_ASSERT ( finalcut::getColumnWidth(term_buf) == 3 ); + term_buf.clear(); + term_buf << L"STARGΛ̊TE"; + CPPUNIT_ASSERT ( finalcut::getColumnWidth(term_buf) == 8 ); + + // Extracts a substring that starts at a specified column position + // and has a specified number of columns + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 0, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 1, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 2, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 3, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 4, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 5, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 0, 1) == L" " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 1, 1) == L" " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 2, 1) == L"1" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 3, 1) == L"0" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 4, 1) == L"0" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 5, 1) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 0, 2) == L" 1" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 1, 2) == L" 1" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 2, 2) == L"10" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 3, 2) == L"00" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 4, 2) == L"0" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 5, 2) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 0, 3) == L" 10" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 1, 3) == L" 10" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 2, 3) == L"100" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 3, 3) == L"00" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 4, 3) == L"0" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 5, 3) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 0, 4) == L" 100" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 1, 4) == L" 100" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 2, 4) == L"100" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 3, 4) == L"00" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 4, 4) == L"0" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"\v\t 100", 5, 4) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 0, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 1, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 2, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 3, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 4, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 5, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 0, 1) == L"0" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 1, 1) == L"0" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 2, 1) == L"1" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 3, 1) == L"2" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 4, 1) == L"3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 5, 1) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 0, 2) == L"01" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 1, 2) == L"01" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 2, 2) == L"12" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 3, 2) == L"23" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 4, 2) == L"3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 5, 2) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 0, 3) == L"012" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 1, 3) == L"012" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 2, 3) == L"123" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 3, 3) == L"23" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 4, 3) == L"3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 5, 3) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 0, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 1, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 2, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 3, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 4, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 5, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 6, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 7, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 8, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 9, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 0, 1) == L"›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 1, 1) == L"›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 2, 1) == L"‹" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 3, 1) == L"›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 4, 1) == L"‹" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 5, 1) == L"›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 6, 1) == L"‹" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 7, 1) == L"›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 8, 1) == L"‹" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 9, 1) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 0, 2) == L"0" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 1, 2) == L"0" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 2, 2) == L"‹›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 3, 2) == L"1" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 4, 2) == L"‹›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 5, 2) == L"2" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 6, 2) == L"‹›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 7, 2) == L"3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 8, 2) == L"‹" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 9, 2) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 0, 3) == L"0›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 1, 3) == L"0›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 2, 3) == L"‹1" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 3, 3) == L"1›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 4, 3) == L"‹2" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 5, 3) == L"2›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 6, 3) == L"‹3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 7, 3) == L"3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 8, 3) == L"‹" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 9, 3) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 0, 4) == L"01" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 1, 4) == L"01" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 2, 4) == L"‹1›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 3, 4) == L"12" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 4, 4) == L"‹2›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 5, 4) == L"23" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 6, 4) == L"‹3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 7, 4) == L"3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 8, 4) == L"‹" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 9, 4) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 0, 5) == L"01›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 1, 5) == L"01›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 2, 5) == L"‹12" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 3, 5) == L"12›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 4, 5) == L"‹23" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 5, 5) == L"23" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 6, 5) == L"‹3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 7, 5) == L"3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 8, 5) == L"‹" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 9, 5) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 0, 6) == L"012" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 1, 6) == L"012" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 2, 6) == L"‹12›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 3, 6) == L"123" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 4, 6) == L"‹23" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 5, 6) == L"23" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 6, 6) == L"‹3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 7, 6) == L"3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 8, 6) == L"‹" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 9, 6) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 0, 7) == L"012›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 1, 7) == L"012›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 2, 7) == L"‹123" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 3, 7) == L"123" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 4, 7) == L"‹23" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 5, 7) == L"23" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 6, 7) == L"‹3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 7, 7) == L"3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 8, 7) == L"‹" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 9, 7) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 0, 8) == L"0123" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 1, 8) == L"0123" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 2, 8) == L"‹123" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 3, 8) == L"123" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 4, 8) == L"‹23" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 5, 8) == L"23" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 6, 8) == L"‹3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 7, 8) == L"3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 8, 8) == L"‹" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"0123", 9, 8) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 1) == L"›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 1) == L"›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 1) == L"‹" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 1) == L"›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 1) == L"‹" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 1) == L" " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 1) == L"o" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 1) == L"n" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 1) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 1) == L" " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 1) == L"›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 1) == L"‹" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 1) == L"›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 1) == L"‹" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 1) == L"›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 1) == L"‹" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 1) == L" " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 1) == L"m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 1) == L"o" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 1) == L"r" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 1) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 1) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 2) == L"你" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 2) == L"你" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 2) == L"‹›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 2) == L"好" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 2) == L"‹ " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 2) == L" o" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 2) == L"on" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 2) == L"ne" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 2) == L"e " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 2) == L" ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 2) == L"C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 2) == L"‹›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 2) == L"U" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 2) == L"‹›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 2) == L"T" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 2) == L"‹ " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 2) == L" m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 2) == L"mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 2) == L"or" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 2) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 2) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 2) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 3) == L"你›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 3) == L"你›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 3) == L"‹好" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 3) == L"好 " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 3) == L"‹ o" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 3) == L" on" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 3) == L"one" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 3) == L"ne " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 3) == L"e ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 3) == L" C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 3) == L"C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 3) == L"‹U" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 3) == L"U›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 3) == L"‹T" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 3) == L"T " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 3) == L"‹ m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 3) == L" mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 3) == L"mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 3) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 3) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 3) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 3) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 4) == L"你好" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 4) == L"你好" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 4) == L"‹好 " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 4) == L"好 o" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 4) == L"‹ on" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 4) == L" one" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 4) == L"one " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 4) == L"ne ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 4) == L"e C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 4) == L" C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 4) == L"CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 4) == L"‹U›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 4) == L"UT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 4) == L"‹T " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 4) == L"T m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 4) == L"‹ mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 4) == L" mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 4) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 4) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 4) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 4) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 4) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 5) == L"你好 " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 5) == L"你好 " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 5) == L"‹好 o" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 5) == L"好 on" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 5) == L"‹ one" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 5) == L" one " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 5) == L"one ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 5) == L"ne C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 5) == L"e C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 5) == L" CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 5) == L"CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 5) == L"‹UT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 5) == L"UT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 5) == L"‹T m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 5) == L"T mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 5) == L"‹ mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 5) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 5) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 5) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 5) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 5) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 5) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 6) == L"你好 o" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 6) == L"你好 o" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 6) == L"‹好 on" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 6) == L"好 one" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 6) == L"‹ one " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 6) == L" one ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 6) == L"one C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 6) == L"ne C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 6) == L"e CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 6) == L" CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 6) == L"CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 6) == L"‹UT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 6) == L"UT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 6) == L"‹T mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 6) == L"T mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 6) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 6) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 6) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 6) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 6) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 6) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 6) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 7) == L"你好 on" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 7) == L"你好 on" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 7) == L"‹好 one" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 7) == L"好 one " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 7) == L"‹ one ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 7) == L" one C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 7) == L"one C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 7) == L"ne CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 7) == L"e CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 7) == L" CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 7) == L"CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 7) == L"‹UT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 7) == L"UT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 7) == L"‹T mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 7) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 7) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 7) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 7) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 7) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 7) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 7) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 7) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 8) == L"你好 one" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 8) == L"你好 one" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 8) == L"‹好 one " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 8) == L"好 one ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 8) == L"‹ one C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 8) == L" one C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 8) == L"one CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 8) == L"ne CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 8) == L"e CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 8) == L" CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 8) == L"CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 8) == L"‹UT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 8) == L"UT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 8) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 8) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 8) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 8) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 8) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 8) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 8) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 8) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 8) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 9) == L"你好 one " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 9) == L"你好 one " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 9) == L"‹好 one ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 9) == L"好 one C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 9) == L"‹ one C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 9) == L" one CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 9) == L"one CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 9) == L"ne CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 9) == L"e CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 9) == L" CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 9) == L"CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 9) == L"‹UT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 9) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 9) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 9) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 9) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 9) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 9) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 9) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 9) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 9) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 9) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 10) == L"你好 one ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 10) == L"你好 one ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 10) == L"‹好 one C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 10) == L"好 one C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 10) == L"‹ one CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 10) == L" one CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 10) == L"one CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 10) == L"ne CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 10) == L"e CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 10) == L" CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 10) == L"CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 10) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 10) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 10) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 10) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 10) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 10) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 10) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 10) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 10) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 10) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 10) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 11) == L"你好 one C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 11) == L"你好 one C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 11) == L"‹好 one C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 11) == L"好 one CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 11) == L"‹ one CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 11) == L" one CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 11) == L"one CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 11) == L"ne CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 11) == L"e CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 11) == L" CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 11) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 11) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 11) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 11) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 11) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 11) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 11) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 11) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 11) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 11) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 11) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 11) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 12) == L"你好 one C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 12) == L"你好 one C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 12) == L"‹好 one CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 12) == L"好 one CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 12) == L"‹ one CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 12) == L" one CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 12) == L"one CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 12) == L"ne CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 12) == L"e CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 12) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 12) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 12) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 12) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 12) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 12) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 12) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 12) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 12) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 12) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 12) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 12) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 12) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 13) == L"你好 one CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 13) == L"你好 one CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 13) == L"‹好 one CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 13) == L"好 one CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 13) == L"‹ one CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 13) == L" one CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 13) == L"one CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 13) == L"ne CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 13) == L"e CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 13) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 13) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 13) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 13) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 13) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 13) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 13) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 13) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 13) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 13) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 13) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 13) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 13) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 14) == L"你好 one CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 14) == L"你好 one CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 14) == L"‹好 one CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 14) == L"好 one CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 14) == L"‹ one CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 14) == L" one CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 14) == L"one CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 14) == L"ne CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 14) == L"e CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 14) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 14) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 14) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 14) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 14) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 14) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 14) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 14) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 14) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 14) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 14) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 14) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 14) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 15) == L"你好 one CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 15) == L"你好 one CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 15) == L"‹好 one CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 15) == L"好 one CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 15) == L"‹ one CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 15) == L" one CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 15) == L"one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 15) == L"ne CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 15) == L"e CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 15) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 15) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 15) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 15) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 15) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 15) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 15) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 15) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 15) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 15) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 15) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 15) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 15) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 16) == L"你好 one CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 16) == L"你好 one CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 16) == L"‹好 one CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 16) == L"好 one CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 16) == L"‹ one CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 16) == L" one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 16) == L"one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 16) == L"ne CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 16) == L"e CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 16) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 16) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 16) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 16) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 16) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 16) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 16) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 16) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 16) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 16) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 16) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 16) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 16) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 17) == L"你好 one CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 17) == L"你好 one CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 17) == L"‹好 one CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 17) == L"好 one CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 17) == L"‹ one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 17) == L" one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 17) == L"one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 17) == L"ne CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 17) == L"e CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 17) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 17) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 17) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 17) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 17) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 17) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 17) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 17) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 17) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 17) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 17) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 17) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 17) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 18) == L"你好 one CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 18) == L"你好 one CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 18) == L"‹好 one CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 18) == L"好 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 18) == L"‹ one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 18) == L" one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 18) == L"one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 18) == L"ne CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 18) == L"e CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 18) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 18) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 18) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 18) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 18) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 18) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 18) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 18) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 18) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 18) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 18) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 18) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 18) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 19) == L"你好 one CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 19) == L"你好 one CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 19) == L"‹好 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 19) == L"好 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 19) == L"‹ one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 19) == L" one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 19) == L"one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 19) == L"ne CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 19) == L"e CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 19) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 19) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 19) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 19) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 19) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 19) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 19) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 19) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 19) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 19) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 19) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 19) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 19) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 0, 20) == L"你好 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 1, 20) == L"你好 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 2, 20) == L"‹好 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 3, 20) == L"好 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 4, 20) == L"‹ one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 5, 20) == L" one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 6, 20) == L"one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 7, 20) == L"ne CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 8, 20) == L"e CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 9, 20) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 10, 20) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 11, 20) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 12, 20) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 13, 20) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 14, 20) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 15, 20) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 16, 20) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 17, 20) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 18, 20) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 19, 20) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 20, 20) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"你好 one CUT more", 21, 20) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 1) == L"1" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 1) == L"1" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 1) == L"2" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 1) == L"3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 1) == L"4" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 1) == L"5" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 1) == L"6" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 1) == L"7" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 1) == L" " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 1) == L"o" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 1) == L"n" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 1) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 1) == L" " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 1) == L"›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 1) == L"‹" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 1) == L"›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 1) == L"‹" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 1) == L"›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 1) == L"‹" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 1) == L" " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 1) == L"m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 1) == L"o" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 1) == L"r" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 1) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 1) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 2) == L"12" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 2) == L"12" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 2) == L"23" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 2) == L"34" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 2) == L"45" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 2) == L"56" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 2) == L"67" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 2) == L"7 " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 2) == L" o" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 2) == L"on" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 2) == L"ne" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 2) == L"e " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 2) == L" ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 2) == L"C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 2) == L"‹›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 2) == L"U" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 2) == L"‹›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 2) == L"T" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 2) == L"‹ " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 2) == L" m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 2) == L"mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 2) == L"or" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 2) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 2) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 2) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 3) == L"123" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 3) == L"123" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 3) == L"234" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 3) == L"345" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 3) == L"456" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 3) == L"567" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 3) == L"67 " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 3) == L"7 o" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 3) == L" on" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 3) == L"one" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 3) == L"ne " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 3) == L"e ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 3) == L" C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 3) == L"C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 3) == L"‹U" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 3) == L"U›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 3) == L"‹T" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 3) == L"T " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 3) == L"‹ m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 3) == L" mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 3) == L"mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 3) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 3) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 3) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 3) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 4) == L"1234" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 4) == L"1234" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 4) == L"2345" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 4) == L"3456" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 4) == L"4567" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 4) == L"567 " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 4) == L"67 o" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 4) == L"7 on" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 4) == L" one" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 4) == L"one " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 4) == L"ne ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 4) == L"e C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 4) == L" C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 4) == L"CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 4) == L"‹U›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 4) == L"UT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 4) == L"‹T " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 4) == L"T m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 4) == L"‹ mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 4) == L" mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 4) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 4) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 4) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 4) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 4) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 5) == L"12345" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 5) == L"12345" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 5) == L"23456" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 5) == L"34567" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 5) == L"4567 " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 5) == L"567 o" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 5) == L"67 on" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 5) == L"7 one" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 5) == L" one " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 5) == L"one ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 5) == L"ne C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 5) == L"e C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 5) == L" CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 5) == L"CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 5) == L"‹UT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 5) == L"UT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 5) == L"‹T m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 5) == L"T mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 5) == L"‹ mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 5) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 5) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 5) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 5) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 5) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 5) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 6) == L"123456" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 6) == L"123456" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 6) == L"234567" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 6) == L"34567 " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 6) == L"4567 o" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 6) == L"567 on" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 6) == L"67 one" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 6) == L"7 one " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 6) == L" one ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 6) == L"one C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 6) == L"ne C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 6) == L"e CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 6) == L" CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 6) == L"CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 6) == L"‹UT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 6) == L"UT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 6) == L"‹T mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 6) == L"T mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 6) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 6) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 6) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 6) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 6) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 6) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 6) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 7) == L"1234567" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 7) == L"1234567" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 7) == L"234567 " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 7) == L"34567 o" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 7) == L"4567 on" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 7) == L"567 one" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 7) == L"67 one " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 7) == L"7 one ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 7) == L" one C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 7) == L"one C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 7) == L"ne CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 7) == L"e CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 7) == L" CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 7) == L"CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 7) == L"‹UT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 7) == L"UT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 7) == L"‹T mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 7) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 7) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 7) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 7) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 7) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 7) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 7) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 7) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 8) == L"1234567 " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 8) == L"1234567 " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 8) == L"234567 o" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 8) == L"34567 on" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 8) == L"4567 one" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 8) == L"567 one " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 8) == L"67 one ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 8) == L"7 one C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 8) == L" one C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 8) == L"one CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 8) == L"ne CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 8) == L"e CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 8) == L" CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 8) == L"CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 8) == L"‹UT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 8) == L"UT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 8) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 8) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 8) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 8) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 8) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 8) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 8) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 8) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 8) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 9) == L"1234567 o" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 9) == L"1234567 o" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 9) == L"234567 on" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 9) == L"34567 one" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 9) == L"4567 one " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 9) == L"567 one ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 9) == L"67 one C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 9) == L"7 one C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 9) == L" one CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 9) == L"one CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 9) == L"ne CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 9) == L"e CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 9) == L" CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 9) == L"CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 9) == L"‹UT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 9) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 9) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 9) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 9) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 9) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 9) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 9) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 9) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 9) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 9) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 10) == L"1234567 on" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 10) == L"1234567 on" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 10) == L"234567 one" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 10) == L"34567 one " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 10) == L"4567 one ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 10) == L"567 one C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 10) == L"67 one C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 10) == L"7 one CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 10) == L" one CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 10) == L"one CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 10) == L"ne CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 10) == L"e CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 10) == L" CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 10) == L"CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 10) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 10) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 10) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 10) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 10) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 10) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 10) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 10) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 10) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 10) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 10) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 11) == L"1234567 one" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 11) == L"1234567 one" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 11) == L"234567 one " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 11) == L"34567 one ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 11) == L"4567 one C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 11) == L"567 one C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 11) == L"67 one CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 11) == L"7 one CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 11) == L" one CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 11) == L"one CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 11) == L"ne CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 11) == L"e CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 11) == L" CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 11) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 11) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 11) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 11) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 11) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 11) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 11) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 11) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 11) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 11) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 11) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 11) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 12) == L"1234567 one " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 12) == L"1234567 one " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 12) == L"234567 one ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 12) == L"34567 one C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 12) == L"4567 one C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 12) == L"567 one CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 12) == L"67 one CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 12) == L"7 one CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 12) == L" one CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 12) == L"one CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 12) == L"ne CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 12) == L"e CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 12) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 12) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 12) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 12) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 12) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 12) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 12) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 12) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 12) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 12) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 12) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 12) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 12) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 13) == L"1234567 one ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 13) == L"1234567 one ›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 13) == L"234567 one C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 13) == L"34567 one C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 13) == L"4567 one CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 13) == L"567 one CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 13) == L"67 one CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 13) == L"7 one CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 13) == L" one CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 13) == L"one CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 13) == L"ne CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 13) == L"e CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 13) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 13) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 13) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 13) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 13) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 13) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 13) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 13) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 13) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 13) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 13) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 13) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 13) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 14) == L"1234567 one C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 14) == L"1234567 one C" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 14) == L"234567 one C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 14) == L"34567 one CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 14) == L"4567 one CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 14) == L"567 one CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 14) == L"67 one CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 14) == L"7 one CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 14) == L" one CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 14) == L"one CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 14) == L"ne CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 14) == L"e CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 14) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 14) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 14) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 14) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 14) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 14) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 14) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 14) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 14) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 14) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 14) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 14) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 14) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 15) == L"1234567 one C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 15) == L"1234567 one C›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 15) == L"234567 one CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 15) == L"34567 one CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 15) == L"4567 one CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 15) == L"567 one CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 15) == L"67 one CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 15) == L"7 one CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 15) == L" one CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 15) == L"one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 15) == L"ne CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 15) == L"e CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 15) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 15) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 15) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 15) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 15) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 15) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 15) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 15) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 15) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 15) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 15) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 15) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 15) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 16) == L"1234567 one CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 16) == L"1234567 one CU" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 16) == L"234567 one CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 16) == L"34567 one CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 16) == L"4567 one CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 16) == L"567 one CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 16) == L"67 one CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 16) == L"7 one CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 16) == L" one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 16) == L"one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 16) == L"ne CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 16) == L"e CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 16) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 16) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 16) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 16) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 16) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 16) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 16) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 16) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 16) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 16) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 16) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 16) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 16) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 17) == L"1234567 one CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 17) == L"1234567 one CU›" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 17) == L"234567 one CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 17) == L"34567 one CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 17) == L"4567 one CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 17) == L"567 one CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 17) == L"67 one CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 17) == L"7 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 17) == L" one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 17) == L"one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 17) == L"ne CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 17) == L"e CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 17) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 17) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 17) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 17) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 17) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 17) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 17) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 17) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 17) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 17) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 17) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 17) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 17) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 18) == L"1234567 one CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 18) == L"1234567 one CUT" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 18) == L"234567 one CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 18) == L"34567 one CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 18) == L"4567 one CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 18) == L"567 one CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 18) == L"67 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 18) == L"7 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 18) == L" one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 18) == L"one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 18) == L"ne CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 18) == L"e CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 18) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 18) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 18) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 18) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 18) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 18) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 18) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 18) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 18) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 18) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 18) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 18) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 18) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 19) == L"1234567 one CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 19) == L"1234567 one CUT " ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 19) == L"234567 one CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 19) == L"34567 one CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 19) == L"4567 one CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 19) == L"567 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 19) == L"67 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 19) == L"7 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 19) == L" one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 19) == L"one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 19) == L"ne CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 19) == L"e CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 19) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 19) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 19) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 19) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 19) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 19) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 19) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 19) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 19) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 19) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 19) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 19) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 19) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 20) == L"1234567 one CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 20) == L"1234567 one CUT m" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 20) == L"234567 one CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 20) == L"34567 one CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 20) == L"4567 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 20) == L"567 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 20) == L"67 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 20) == L"7 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 20) == L" one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 20) == L"one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 20) == L"ne CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 20) == L"e CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 20) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 20) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 20) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 20) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 20) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 20) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 20) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 20) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 20) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 20) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 20) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 20) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 20) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 21) == L"1234567 one CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 21) == L"1234567 one CUT mo" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 21) == L"234567 one CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 21) == L"34567 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 21) == L"4567 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 21) == L"567 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 21) == L"67 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 21) == L"7 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 21) == L" one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 21) == L"one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 21) == L"ne CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 21) == L"e CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 21) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 21) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 21) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 21) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 21) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 21) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 21) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 21) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 21) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 21) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 21) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 21) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 21) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 22) == L"1234567 one CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 22) == L"1234567 one CUT mor" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 22) == L"234567 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 22) == L"34567 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 22) == L"4567 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 22) == L"567 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 22) == L"67 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 22) == L"7 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 22) == L" one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 22) == L"one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 22) == L"ne CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 22) == L"e CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 22) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 22) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 22) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 22) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 22) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 22) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 22) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 22) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 22) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 22) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 22) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 22) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 22) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 0, 23) == L"1234567 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 1, 23) == L"1234567 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 2, 23) == L"234567 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 3, 23) == L"34567 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 4, 23) == L"4567 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 5, 23) == L"567 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 6, 23) == L"67 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 7, 23) == L"7 one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 8, 23) == L" one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 9, 23) == L"one CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 10, 23) == L"ne CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 11, 23) == L"e CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 12, 23) == L" CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 13, 23) == L"CUT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 14, 23) == L"‹UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 15, 23) == L"UT more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 16, 23) == L"‹T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 17, 23) == L"T more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 18, 23) == L"‹ more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 19, 23) == L" more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 20, 23) == L"more" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 21, 23) == L"ore" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 22, 23) == L"re" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 23, 23) == L"e" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"1234567 one CUT more", 24, 23) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 0, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 1, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 2, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 3, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 4, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 0, 1) == L"o\U0000031b\U00000323" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 1, 1) == L"o\U0000031b\U00000323" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 2, 1) == L"=" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 3, 1) == L"\U00001ee3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 4, 1) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 0, 2) == L"o\U0000031b\U00000323=" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 1, 2) == L"o\U0000031b\U00000323=" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 2, 2) == L"=\U00001ee3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 3, 2) == L"\U00001ee3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 4, 2) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 0, 3) == L"o\U0000031b\U00000323=\U00001ee3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 1, 3) == L"o\U0000031b\U00000323=\U00001ee3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 2, 3) == L"=\U00001ee3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 3, 3) == L"\U00001ee3" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"o\U0000031b\U00000323=\U00001ee3", 4, 3) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 0, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 1, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 2, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 3, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 4, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 5, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 6, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 7, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 8, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 9, 0) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 0, 1) == L"S" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 1, 1) == L"S" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 2, 1) == L"T" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 3, 1) == L"A" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 4, 1) == L"R" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 5, 1) == L"G" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 6, 1) == L"Λ̊" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 7, 1) == L"T" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 8, 1) == L"E" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 9, 1) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 0, 2) == L"ST" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 1, 2) == L"ST" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 2, 2) == L"TA" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 3, 2) == L"AR" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 4, 2) == L"RG" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 5, 2) == L"GΛ̊" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 6, 2) == L"Λ̊T" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 7, 2) == L"TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 8, 2) == L"E" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 9, 2) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 0, 3) == L"STA" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 1, 3) == L"STA" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 2, 3) == L"TAR" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 3, 3) == L"ARG" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 4, 3) == L"RGΛ̊" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 5, 3) == L"GΛ̊T" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 6, 3) == L"Λ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 7, 3) == L"TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 8, 3) == L"E" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 9, 3) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 0, 4) == L"STAR" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 1, 4) == L"STAR" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 2, 4) == L"TARG" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 3, 4) == L"ARGΛ̊" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 4, 4) == L"RGΛ̊T" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 5, 4) == L"GΛ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 6, 4) == L"Λ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 7, 4) == L"TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 8, 4) == L"E" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 9, 4) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 0, 5) == L"STARG" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 1, 5) == L"STARG" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 2, 5) == L"TARGΛ̊" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 3, 5) == L"ARGΛ̊T" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 4, 5) == L"RGΛ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 5, 5) == L"GΛ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 6, 5) == L"Λ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 7, 5) == L"TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 8, 5) == L"E" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 9, 5) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 0, 6) == L"STARGΛ̊" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 1, 6) == L"STARGΛ̊" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 2, 6) == L"TARGΛ̊T" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 3, 6) == L"ARGΛ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 4, 6) == L"RGΛ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 5, 6) == L"GΛ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 6, 6) == L"Λ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 7, 6) == L"TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 8, 6) == L"E" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 9, 6) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 0, 7) == L"STARGΛ̊T" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 1, 7) == L"STARGΛ̊T" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 2, 7) == L"TARGΛ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 3, 7) == L"ARGΛ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 4, 7) == L"RGΛ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 5, 7) == L"GΛ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 6, 7) == L"Λ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 7, 7) == L"TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 8, 7) == L"E" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 9, 7) == L"" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 0, 8) == L"STARGΛ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 1, 8) == L"STARGΛ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 2, 8) == L"TARGΛ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 3, 8) == L"ARGΛ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 4, 8) == L"RGΛ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 5, 8) == L"GΛ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 6, 8) == L"Λ̊TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 7, 8) == L"TE" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 8, 8) == L"E" ); + CPPUNIT_ASSERT ( finalcut::getColumnSubString(L"STARGΛ̊TE", 9, 8) == L"" ); +} + +//---------------------------------------------------------------------- +void FTermFunctionsTest::combiningCharacterTest() +{ + // Leading zero-width characters + std::wstring combining = L"\U00000323\U00000300\U0000ff2f\n"; // [] [] O [NL] + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 0) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 1) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 2) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 3) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 0) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 1) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 2) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 3) == 1 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 0) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 1) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 2) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 3) == 2 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 4) == 3 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 0) == 2 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 1) == 2 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 2) == 3 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 3) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 4) == NOT_FOUND ); + + // Characters with separate and with combined diacritical marks + combining = L"u\U00000300=\U000000f9"; // u ` = ù + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 0) == 2 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 1) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 2) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 3) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 4) == -1 ); // Position is outside the string + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 0) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 1) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 2) == 2 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 3) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 4) == -1 ); // Position is outside the string + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 0) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 1) == 0 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 2) == 0 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 3) == 2 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 4) == 3 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 0) == 2 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 1) == 2 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 2) == 3 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 3) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 4) == NOT_FOUND ); + + combining = L"o\U0000031b\U00000323=\U00001ee3"; // o ‍̛ ‍̣ = ợ + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 0) == 3 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 1) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 2) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 3) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 4) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 0) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 1) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 2) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 3) == 3 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 4) == 1 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 0) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 1) == 0 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 2) == 0 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 3) == 0 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 4) == 3 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 5) == 4 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 0) == 3 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 1) == 3 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 2) == 3 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 3) == 4 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 4) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 5) == NOT_FOUND ); + + // Many combination characters + combining = L"v" \ + L"\U00000300\U0000032e\U00000368" \ + L"\U00000364\U00000348\U0000034b"; // v ̀ ̮ ͨ ͤ ͈ ͋ + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 0) == 7 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 1) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 2) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 3) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 4) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 5) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 6) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 0) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 1) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 2) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 3) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 4) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 5) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 6) == -1 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 0) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 1) == 0 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 2) == 0 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 3) == 0 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 4) == 0 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 5) == 0 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 6) == 0 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 7) == 0 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 0) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 1) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 2) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 3) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 4) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 5) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 6) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 7) == NOT_FOUND ); + + // Trailing uncombined zero-width characters + combining = L"a\t\U00000300\U00000323"; // a [Tab] [] [] + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 0) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 1) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 2) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 3) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 0) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 1) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 2) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 3) == -1 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 0) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 1) == 0 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 2) == 1 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 3) == 1 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 4) == 1 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 0) == 1 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 1) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 2) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 3) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 4) == NOT_FOUND ); + + // Thai (ISO 10646-1 - UCS implementation level 2) + combining = L"๏ แผ่นดินฮั่นเสื่อมโทรมแสนสังเวช"; + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 0) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 1) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 2) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 3) == 2 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 4) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 5) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 6) == 2 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 7) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 8) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 9) == 3 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 10) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 11) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 12) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 13) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 14) == 3 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 15) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 16) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 17) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 18) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 19) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 20) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 21) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 22) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 23) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 24) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 25) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 26) == 2 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 27) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 28) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 29) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 30) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 31) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 0) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 1) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 2) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 3) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 4) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 5) == 2 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 6) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 7) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 8) == 2 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 9) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 10) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 11) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 12) == 3 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 13) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 14) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 15) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 16) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 17) == 3 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 18) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 19) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 20) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 21) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 22) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 23) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 24) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 25) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 26) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 27) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 28) == 2 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 29) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 30) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 31) == 1 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 0) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 1) == 0 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 2) == 1 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 3) == 2 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 4) == 3 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 5) == 3 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 6) == 5 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 7) == 6 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 8) == 6 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 9) == 8 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 10) == 9 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 11) == 9 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 12) == 9 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 13) == 12 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 14) == 13 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 15) == 14 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 16) == 14 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 17) == 14 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 18) == 17 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 19) == 18 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 20) == 19 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 21) == 20 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 22) == 21 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 23) == 22 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 24) == 23 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 25) == 24 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 26) == 25 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 27) == 26 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 28) == 26 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 29) == 28 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 30) == 29 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 31) == 30 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 32) == 31 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 0) == 1 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 1) == 2 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 2) == 3 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 3) == 5 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 4) == 5 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 5) == 6 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 6) == 8 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 7) == 8 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 8) == 9 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 9) == 12 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 10) == 12 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 11) == 12 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 12) == 13 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 13) == 14 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 14) == 17 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 15) == 17 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 16) == 17 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 17) == 18 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 18) == 19 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 19) == 20 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 20) == 21 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 21) == 22 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 22) == 23 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 23) == 24 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 24) == 25 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 25) == 26 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 26) == 28 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 27) == 28 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 28) == 29 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 29) == 30 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 30) == 31 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 31) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 32) == NOT_FOUND ); + + // Devanagari script (ISO 10646-1 - UCS implementation level 2) + combining = L"पन्ह पन्ह त्र र्च कृकृ ड्ड न्ह"; + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 0) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 1) == 2 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 2) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 3) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 4) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 5) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 6) == 2 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 7) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 8) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 9) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 10) == 2 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 11) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 12) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 13) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 14) == 2 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 15) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 16) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 17) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 18) == 2 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 19) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 20) == 2 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 21) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 22) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 23) == 2 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 24) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 25) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 26) == 1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 27) == 2 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 28) == -1 ); + CPPUNIT_ASSERT ( finalcut::getCharLength(combining, 29) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 0) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 1) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 2) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 3) == 2 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 4) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 5) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 6) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 7) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 8) == 2 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 9) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 10) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 11) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 12) == 2 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 13) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 14) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 15) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 16) == 2 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 17) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 18) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 19) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 20) == 2 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 21) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 22) == 2 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 23) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 24) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 25) == 2 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 26) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 27) == 1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 28) == -1 ); + CPPUNIT_ASSERT ( finalcut::getPrevCharLength(combining, 29) == 2 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 0) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 1) == 0 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 2) == 1 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 3) == 1 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 4) == 3 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 5) == 4 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 6) == 5 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 7) == 6 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 8) == 6 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 9) == 8 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 10) == 9 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 11) == 10 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 12) == 10 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 13) == 12 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 14) == 13 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 15) == 14 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 16) == 14 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 17) == 16 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 18) == 17 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 19) == 18 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 20) == 18 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 21) == 20 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 22) == 20 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 23) == 22 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 24) == 23 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 25) == 23 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 26) == 25 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 27) == 26 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 28) == 27 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 29) == 27 ); + CPPUNIT_ASSERT ( finalcut::searchLeftCharBegin(combining, 30) == 29 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 0) == 1 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 1) == 3 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 2) == 3 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 3) == 4 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 4) == 5 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 5) == 6 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 6) == 8 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 7) == 8 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 8) == 9 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 9) == 10 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 10) == 12 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 11) == 12 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 12) == 13 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 13) == 14 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 14) == 16 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 15) == 16 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 16) == 17 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 17) == 18 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 18) == 20 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 19) == 20 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 20) == 22 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 21) == 22 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 22) == 23 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 23) == 25 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 24) == 25 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 25) == 26 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 26) == 27 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 27) == 29 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 28) == 29 ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 29) == NOT_FOUND ); + CPPUNIT_ASSERT ( finalcut::searchRightCharBegin(combining, 30) == NOT_FOUND ); +} + +//---------------------------------------------------------------------- +void FTermFunctionsTest::readCursorPosTest() +{ + finalcut::FTermData& data = *finalcut::FTerm::getFTermData(); + finalcut::FTermDetection detect; + data.setTermType("xterm"); + detect.setTerminalDetection(true); + + pid_t pid = forkConEmu(); + + if ( isConEmuChildProcess(pid) ) + { + const finalcut::FPoint cursor_pos = finalcut::readCursorPos(); + CPPUNIT_ASSERT ( cursor_pos.getX() == 80 ); + CPPUNIT_ASSERT ( cursor_pos.getY() == 25 ); + + closeConEmuStdStreams(); + exit(EXIT_SUCCESS); + } + else // Parent + { + // Start the terminal emulation + startConEmuTerminal (ConEmu::xterm); + + if ( waitpid(pid, 0, WUNTRACED) != pid ) + std::cerr << "waitpid error" << std::endl; + } +} + + +// Put the test suite in the registry +CPPUNIT_TEST_SUITE_REGISTRATION (FTermFunctionsTest); + +// The general unit test main part +#include diff --git a/test/ftermbuffer-test.cpp b/test/ftermbuffer-test.cpp new file mode 100644 index 00000000..40135f9e --- /dev/null +++ b/test/ftermbuffer-test.cpp @@ -0,0 +1,848 @@ +/*********************************************************************** +* ftermbuffer-test.cpp - FTermBuffer unit tests * +* * +* This file is part of the FINAL CUT widget toolkit * +* * +* Copyright 2021 Markus Gans * +* * +* FINAL CUT 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 3 of * +* the License, or (at your option) any later version. * +* * +* FINAL CUT 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 program. If not, see * +* . * +***********************************************************************/ +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +//---------------------------------------------------------------------- +// class FTermBufferTest +//---------------------------------------------------------------------- + +class FTermBufferTest : public CPPUNIT_NS::TestFixture +{ + public: + FTermBufferTest() + { + std::setlocale (LC_CTYPE, "en_US.UTF-8"); + fwide(stdout, 1); // Makes stream wide-character oriented + } + + protected: + void classNameTest(); + void noArgumentTest(); + void writeTest(); + void streamTest(); + void combiningCharacterTest(); + + private: + // Adds code needed to register the test suite + CPPUNIT_TEST_SUITE (FTermBufferTest); + + // Add a methods to the test suite + CPPUNIT_TEST (classNameTest); + CPPUNIT_TEST (noArgumentTest); + CPPUNIT_TEST (writeTest); + CPPUNIT_TEST (streamTest); + CPPUNIT_TEST (combiningCharacterTest); + + // End of test suite definition + CPPUNIT_TEST_SUITE_END(); +}; + + +//---------------------------------------------------------------------- +void FTermBufferTest::classNameTest() +{ + const finalcut::FTermBuffer s; + const finalcut::FString& classname = s.getClassName(); + CPPUNIT_ASSERT ( classname == "FTermBuffer" ); +} + +//---------------------------------------------------------------------- +void FTermBufferTest::noArgumentTest() +{ + const finalcut::FTermBuffer term_buf{}; + CPPUNIT_ASSERT ( term_buf.isEmpty() ); + CPPUNIT_ASSERT ( term_buf.getLength() == 0 ); + std::vector data{}; + CPPUNIT_ASSERT ( term_buf.getBuffer() == data ); + CPPUNIT_ASSERT ( term_buf.getBuffer().size() == 0 ); + CPPUNIT_ASSERT ( term_buf.begin() == term_buf.end() ); + CPPUNIT_ASSERT ( finalcut::UNICODE_MAX == 5 ); +} + +//---------------------------------------------------------------------- +void FTermBufferTest::writeTest() +{ + const auto& data = finalcut::FTerm::getFTermData(); + data->setTermEncoding (finalcut::Encoding::UTF8); + finalcut::FTermBuffer term_buf{}; + + // Write wchar_t + const wchar_t wch{L'\U0000263a'}; // ☺ + term_buf.write(wch); + CPPUNIT_ASSERT ( ! term_buf.isEmpty() ); + CPPUNIT_ASSERT ( term_buf.getLength() == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer().size() == 1 ); + CPPUNIT_ASSERT ( term_buf.begin() + 1 == term_buf.end() ); + CPPUNIT_ASSERT ( term_buf.front().ch[0] == L'☺' ); + CPPUNIT_ASSERT ( term_buf.front().ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().ch[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().ch[4] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().encoded_char[0] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().encoded_char[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().encoded_char[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().encoded_char[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().encoded_char[4] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().fg_color == 0 ); + CPPUNIT_ASSERT ( term_buf.front().bg_color == 0 ); + CPPUNIT_ASSERT ( term_buf.front().attr.byte[0] == 0 ); + CPPUNIT_ASSERT ( term_buf.front().attr.byte[1] == 0 ); + CPPUNIT_ASSERT ( term_buf.front().attr.byte[2] != 0 ); + CPPUNIT_ASSERT ( term_buf.front().attr.byte[3] == 0 ); + CPPUNIT_ASSERT ( term_buf.front().attr.bit.char_width == 1 ); + term_buf.front().attr.bit.char_width = 0; + CPPUNIT_ASSERT ( term_buf.front().attr.byte[2] == 0 ); + CPPUNIT_ASSERT ( term_buf.toString() == finalcut::FString(wch) ); + + // Clear after write + term_buf.clear(); + CPPUNIT_ASSERT ( term_buf.isEmpty() ); + CPPUNIT_ASSERT ( term_buf.getLength() == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer().size() == 0 ); + CPPUNIT_ASSERT ( term_buf.begin() == term_buf.end() ); + CPPUNIT_ASSERT ( term_buf.toString() == finalcut::FString() ); + + // Write char + const char ch{'@'}; + term_buf.write(ch); + CPPUNIT_ASSERT ( ! term_buf.isEmpty() ); + CPPUNIT_ASSERT ( term_buf.getLength() == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer().size() == 1 ); + CPPUNIT_ASSERT ( term_buf.begin() + 1 == term_buf.end() ); + CPPUNIT_ASSERT ( term_buf.front().ch[0] == L'@' ); + CPPUNIT_ASSERT ( term_buf.front().ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().ch[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().ch[4] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().encoded_char[0] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().encoded_char[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().encoded_char[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().encoded_char[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().encoded_char[4] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().fg_color == 0 ); + CPPUNIT_ASSERT ( term_buf.front().bg_color == 0 ); + CPPUNIT_ASSERT ( term_buf.front().attr.byte[0] == 0 ); + CPPUNIT_ASSERT ( term_buf.front().attr.byte[1] == 0 ); + CPPUNIT_ASSERT ( term_buf.front().attr.byte[2] != 0 ); + CPPUNIT_ASSERT ( term_buf.front().attr.byte[3] == 0 ); + CPPUNIT_ASSERT ( term_buf.front().attr.bit.char_width == 1 ); + term_buf.front().attr.bit.char_width = 0; + CPPUNIT_ASSERT ( term_buf.front().attr.byte[2] == 0 ); + CPPUNIT_ASSERT ( term_buf.toString() == finalcut::FString(ch) ); + + // Write FString + const finalcut::FString str = "abc…xyz"; + term_buf.clear(); + term_buf.write(str); + CPPUNIT_ASSERT ( ! term_buf.isEmpty() ); + CPPUNIT_ASSERT ( term_buf.getLength() == 7 ); + CPPUNIT_ASSERT ( term_buf.getBuffer().size() == 7 ); + CPPUNIT_ASSERT ( term_buf.begin() + 7 == term_buf.end() ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[0] == L'a' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].ch[0] == L'b' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].ch[0] == L'c' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].ch[0] == L'…' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[4].ch[0] == L'x' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[5].ch[0] == L'y' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[6].ch[0] == L'z' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[4].attr.bit.char_width == 2 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[5].attr.bit.char_width == 2 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[6].attr.bit.char_width == 2 ); + CPPUNIT_ASSERT ( term_buf.toString() == str ); + + for (std::size_t i{0}; i < 7; i++) + { + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[4] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[0] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[4] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].fg_color == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].bg_color == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].attr.byte[0] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].attr.byte[1] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].attr.byte[2] != 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].attr.byte[3] == 0 ); + } + + // Write formatted output + term_buf.clear(); + term_buf.writef ("%'.2f%C", 0.25 * 7.0, L'£'); + CPPUNIT_ASSERT ( ! term_buf.isEmpty() ); + CPPUNIT_ASSERT ( term_buf.getLength() == 5 ); + CPPUNIT_ASSERT ( term_buf.getBuffer().size() == 5 ); + CPPUNIT_ASSERT ( term_buf.begin() + 5 == term_buf.end() ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[0] == L'1' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].ch[0] == L'.' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].ch[0] == L'7' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].ch[0] == L'5' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[4].ch[0] == L'£' ); + CPPUNIT_ASSERT ( term_buf.toString() == "1.75£" ); + + for (std::size_t i{0}; i < 5; i++) + { + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[4] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[0] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[4] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].fg_color == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].bg_color == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].attr.byte[0] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].attr.byte[1] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].attr.byte[2] != 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].attr.byte[3] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].attr.bit.char_width == 1 ); + } + + // Write with color + term_buf.clear(); + finalcut::FVTerm::setColor(finalcut::FColor::Default, finalcut::FColor::Default); + term_buf.write (L'♥'); + auto color_pair = finalcut::FColorPair(finalcut::FColor::DarkRed, finalcut::FColor::Yellow4); + term_buf.write (color_pair); + term_buf.write (L'☺'); + finalcut::FVTerm::setNormal(); + term_buf.write ("♪"); + color_pair = finalcut::FColorPair(finalcut::FColor::Black, finalcut::FColor::White); + term_buf.write (color_pair); + term_buf.write ("↑"); + CPPUNIT_ASSERT ( ! term_buf.isEmpty() ); + CPPUNIT_ASSERT ( term_buf.getLength() == 4 ); + CPPUNIT_ASSERT ( term_buf.getBuffer().size() == 4 ); + CPPUNIT_ASSERT ( term_buf.begin() + 4 == term_buf.end() ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[0] == L'♥' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].ch[0] == L'☺' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].ch[0] == L'♪' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].ch[0] == L'↑' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].fg_color == finalcut::FColor::Default ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].bg_color == finalcut::FColor::Default ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].fg_color == finalcut::FColor::DarkRed ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].bg_color == finalcut::FColor::Yellow4 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].fg_color == finalcut::FColor::Default ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].bg_color == finalcut::FColor::Default ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].fg_color == finalcut::FColor::Black ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].bg_color == finalcut::FColor::White ); + CPPUNIT_ASSERT ( term_buf.toString() == "♥☺♪↑" ); + + for (std::size_t i{0}; i < 4; i++) + { + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[4] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[0] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[4] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].attr.byte[0] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].attr.byte[1] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].attr.byte[2] != 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].attr.byte[3] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].attr.bit.char_width == 1 ); + } + + // Write with style + term_buf.clear(); + auto style = finalcut::FStyle(finalcut::Style::Italic | finalcut::Style::Reverse); + term_buf.write (style); + CPPUNIT_ASSERT ( uInt(style.getStyle()) == uInt(finalcut::FVTerm::getAttribute().attr.byte[0]) ); + term_buf.write (L'☕'); + term_buf.write ( finalcut::FStyle(finalcut::Style::None) ); // Reset style + style = finalcut::FStyle(finalcut::Style::Bold | finalcut::Style::Underline); + term_buf.write (style); + term_buf.write (L'⛄'); + term_buf.write ( finalcut::FStyle(finalcut::Style::Transparent) ); + term_buf.write (L'🧸'); + term_buf.write ( finalcut::FStyle(finalcut::Style::None) ); // Reset style + term_buf.write (L'🦡'); + CPPUNIT_ASSERT ( ! term_buf.isEmpty() ); + CPPUNIT_ASSERT ( term_buf.getLength() == 4 ); + CPPUNIT_ASSERT ( term_buf.getBuffer().size() == 4 ); + CPPUNIT_ASSERT ( term_buf.begin() + 4 == term_buf.end() ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[0] == L'☕' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].attr.bit.italic == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].attr.bit.reverse == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].attr.byte[0] != 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].attr.byte[1] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].ch[0] == L'⛄' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].attr.bit.bold == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].attr.bit.underline == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].attr.byte[0] != 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].attr.byte[1] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].ch[0] == L'🧸' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].attr.bit.bold == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].attr.bit.underline == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].attr.bit.transparent == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].attr.byte[0] != 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].attr.byte[1] != 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].ch[0] == L'🦡' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].attr.bit.bold == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].attr.bit.underline == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].attr.bit.transparent == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].attr.byte[0] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].attr.byte[1] == 0 ); + CPPUNIT_ASSERT ( term_buf.toString() == "☕⛄🧸🦡" ); + + for (std::size_t i{0}; i < 3; i++) + { + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[4] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[0] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[4] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].attr.byte[2] != 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].attr.byte[3] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].attr.bit.char_width == 2 ); + } +} + +//---------------------------------------------------------------------- +void FTermBufferTest::streamTest() +{ + const auto& data = finalcut::FTerm::getFTermData(); + data->setTermEncoding (finalcut::Encoding::UTF8); + finalcut::FTermBuffer::FCharVector fchar_vec = { finalcut::FChar{} }; + CPPUNIT_ASSERT ( fchar_vec.size() == 1 ); + fchar_vec.front().ch[0] = L'🥨'; + fchar_vec.front().fg_color = finalcut::FColor::White; + fchar_vec.front().bg_color = finalcut::FColor::Cyan; + finalcut::addColumnWidth(fchar_vec.front()); + finalcut::FTermBuffer term_buf{}; + term_buf.write() << L'a' + << finalcut::FColorPair{finalcut::FColor::Yellow, finalcut::FColor::Blue} + << 1 + << finalcut::FColorPair{finalcut::FColor::Cyan, finalcut::FColor::White} + << finalcut::FStyle(finalcut::Style::Dim) + << finalcut::UniChar::NF_Bullet + << finalcut::FStyle(finalcut::Style::Blink) + << fchar_vec + << std::string("🧭") + << finalcut::FStyle(finalcut::Style::None) + << finalcut::FStyle(finalcut::Style::DoubleUnderline) + << finalcut::FColorPair{finalcut::FColor::Black, finalcut::FColor::White} + << std::wstring(L"🚴"); + + CPPUNIT_ASSERT ( ! term_buf.isEmpty() ); + CPPUNIT_ASSERT ( term_buf.getLength() == 6 ); + CPPUNIT_ASSERT ( term_buf.getBuffer().size() == 6 ); + CPPUNIT_ASSERT ( term_buf.begin() + 6 == term_buf.end() ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[0] == L'a' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].fg_color == finalcut::FColor::Default ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].bg_color == finalcut::FColor::Default ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].attr.byte[0] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].attr.byte[1] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].ch[0] == L'1' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].fg_color == finalcut::FColor::Yellow ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].bg_color == finalcut::FColor::Blue ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].attr.byte[0] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].attr.byte[1] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].ch[0] == L'\U0000e1f9' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].fg_color == finalcut::FColor::Cyan ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].bg_color == finalcut::FColor::White ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].attr.bit.dim == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].attr.byte[0] != 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].attr.byte[1] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].ch[0] == L'🥨' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].fg_color == finalcut::FColor::White ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].bg_color == finalcut::FColor::Cyan ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].attr.byte[0] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].attr.byte[1] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].attr.bit.char_width == 2 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[4].ch[0] == L'🧭' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[4].fg_color == finalcut::FColor::Cyan ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[4].bg_color == finalcut::FColor::White ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[4].attr.bit.dim == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[4].attr.bit.blink == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[4].attr.byte[0] != 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[4].attr.byte[1] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[4].attr.bit.char_width == 2 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[5].ch[0] == L'🚴' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[5].fg_color == finalcut::FColor::Black ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[5].bg_color == finalcut::FColor::White ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[5].attr.bit.dbl_underline == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[5].attr.byte[0] == 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[5].attr.byte[1] != 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[5].attr.bit.char_width == 2 ); + CPPUNIT_ASSERT ( term_buf.toString() == "a1\U0000e1f9🥨🧭🚴" ); + + for (std::size_t i{0}; i < 6; i++) + { + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].ch[4] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[0] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].encoded_char[4] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].attr.byte[2] != 0 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[i].attr.byte[3] == 0 ); + } +} + +//---------------------------------------------------------------------- +void FTermBufferTest::combiningCharacterTest() +{ + const auto& data = finalcut::FTerm::getFTermData(); + data->setTermEncoding (finalcut::Encoding::UTF8); + finalcut::FTermBuffer term_buf{}; + // Skip leading zero-width characters + std::wstring combining = L"\U00000323\U00000300\U0000ff2f\n"; // [] [] O [NL] + term_buf.write(combining); + CPPUNIT_ASSERT ( ! term_buf.isEmpty() ); + CPPUNIT_ASSERT ( combining.length() == 4 ); + CPPUNIT_ASSERT ( wcwidth(combining[0]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[1]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[2]) == 2 ); + CPPUNIT_ASSERT ( wcwidth(combining[3]) == -1 ); + CPPUNIT_ASSERT ( term_buf.getLength() == 2 ); + CPPUNIT_ASSERT ( term_buf.getBuffer().size() == 2 ); + CPPUNIT_ASSERT ( term_buf.begin() != term_buf.end() ); + CPPUNIT_ASSERT ( term_buf.front().ch[0] == L'O' ); + CPPUNIT_ASSERT ( term_buf.front().ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().ch[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().ch[4] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.front().attr.bit.char_width == 2 ); + CPPUNIT_ASSERT ( term_buf.back().ch[0] == L'\012' ); + CPPUNIT_ASSERT ( term_buf.back().ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.back().ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.back().ch[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.back().ch[4] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.back().attr.bit.char_width == 0 ); + CPPUNIT_ASSERT ( term_buf.toString() != combining ); + CPPUNIT_ASSERT ( term_buf.toString() == L"O\012" ); + + // Characters with separate and with combined diacritical marks + combining = L"u\U00000300=\U000000f9"; // u ` = ù + term_buf.clear(); + term_buf.write(combining); + CPPUNIT_ASSERT ( ! term_buf.isEmpty() ); + CPPUNIT_ASSERT ( combining.length() == 4 ); + CPPUNIT_ASSERT ( wcwidth(combining[0]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[1]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[2]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[3]) == 1 ); + CPPUNIT_ASSERT ( term_buf.getLength() == 3 ); + CPPUNIT_ASSERT ( term_buf.getBuffer().size() == 3 ); + CPPUNIT_ASSERT ( term_buf.begin() != term_buf.end() ); + CPPUNIT_ASSERT ( term_buf.front().ch[0] == L'u' ); + CPPUNIT_ASSERT ( int(term_buf.front().ch[1]) == 0x300 ); + CPPUNIT_ASSERT ( term_buf.front().ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[0] == L'u' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[1] == L'\U00000300' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].ch[0] == L'=' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].ch[0] == L'ù' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.back().ch[0] == L'ù' ); + CPPUNIT_ASSERT ( term_buf.back().ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.toString() == combining ); + CPPUNIT_ASSERT ( term_buf.toString() == L"ù=ù" ); + + combining = L"o\U0000031b\U00000323=\U00001ee3"; // o ‍̛ ‍̣ = ợ + term_buf.clear(); + term_buf.write(combining); + CPPUNIT_ASSERT ( combining.length() == 5 ); + CPPUNIT_ASSERT ( wcwidth(combining[0]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[1]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[2]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[3]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[4]) == 1 ); + CPPUNIT_ASSERT ( term_buf.getLength() == 3 ); + CPPUNIT_ASSERT ( term_buf.getBuffer().size() == 3 ); + CPPUNIT_ASSERT ( term_buf.begin() != term_buf.end() ); + CPPUNIT_ASSERT ( term_buf.front().ch[0] == L'o' ); + CPPUNIT_ASSERT ( term_buf.front().ch[1] == L'\U0000031b' ); + CPPUNIT_ASSERT ( term_buf.front().ch[2] == L'\U00000323' ); + CPPUNIT_ASSERT ( term_buf.front().ch[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[0] == L'o' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[1] == L'\U0000031b' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[2] == L'\U00000323' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].ch[0] == L'=' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].ch[0] == L'ợ' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.back().ch[0] == L'ợ' ); + CPPUNIT_ASSERT ( term_buf.back().ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.toString() == combining ); + CPPUNIT_ASSERT ( term_buf.toString() == L"ợ=ợ" ); + + // Too many combination characters + combining = L"v" \ + L"\U00000300\U0000032e\U00000368" \ + L"\U00000364\U00000348\U0000034b"; // v ̀ ̮ ͨ ͤ ͈ ͋ + term_buf.clear(); + term_buf << combining; + CPPUNIT_ASSERT ( combining.length() == 7 ); + CPPUNIT_ASSERT ( wcwidth(combining[0]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[1]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[2]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[3]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[4]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[5]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[6]) == 0 ); + CPPUNIT_ASSERT ( term_buf.getLength() == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer().size() == 1 ); + CPPUNIT_ASSERT ( term_buf.begin() != term_buf.end() ); + CPPUNIT_ASSERT ( term_buf.front() == term_buf.back() ); + CPPUNIT_ASSERT ( term_buf.front().ch[0] == L'v' ); + CPPUNIT_ASSERT ( term_buf.front().ch[1] == L'\U00000300' ); + CPPUNIT_ASSERT ( term_buf.front().ch[2] == L'\U0000032e' ); + CPPUNIT_ASSERT ( term_buf.front().ch[3] == L'\U00000368' ); + CPPUNIT_ASSERT ( term_buf.front().ch[4] == L'\U00000364' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[0] == L'v' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[1] == L'\U00000300' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[2] == L'\U0000032e' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[3] == L'\U00000368' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[4] == L'\U00000364' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.back().ch[0] == L'v' ); + CPPUNIT_ASSERT ( term_buf.back().ch[1] == L'\U00000300' ); + CPPUNIT_ASSERT ( term_buf.back().ch[2] == L'\U0000032e' ); + CPPUNIT_ASSERT ( term_buf.back().ch[3] == L'\U00000368' ); + CPPUNIT_ASSERT ( term_buf.back().ch[4] == L'\U00000364' ); + CPPUNIT_ASSERT ( term_buf.toString() != combining ); + CPPUNIT_ASSERT ( term_buf.toString() == L"v̮̀ͨͤ" ); + + // Ignore trailing uncombined zero-width characters + combining = L"a\t\U00000300\U00000323"; // a [Tab] [] [] + term_buf.clear(); + term_buf.write(combining); + CPPUNIT_ASSERT ( combining.length() == 4 ); + CPPUNIT_ASSERT ( wcwidth(combining[0]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[1]) == -1 ); + CPPUNIT_ASSERT ( wcwidth(combining[2]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[3]) == 0 ); + CPPUNIT_ASSERT ( term_buf.getLength() == 2 ); + CPPUNIT_ASSERT ( term_buf.getBuffer().size() == 2 ); + CPPUNIT_ASSERT ( term_buf.begin() != term_buf.end() ); + CPPUNIT_ASSERT ( term_buf.front().ch[0] == L'a' ); + CPPUNIT_ASSERT ( term_buf.front().ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[0] == L'a' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].ch[0] == L'\t' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].attr.bit.char_width == 0 ); + CPPUNIT_ASSERT ( term_buf.back().ch[0] == L'\t' ); + CPPUNIT_ASSERT ( term_buf.back().ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.toString() != combining ); + CPPUNIT_ASSERT ( term_buf.toString() == L"a\t" ); + + // Thai (ISO 10646-1 - UCS implementation level 2) + combining = L"๏ แผ่นดินฮั่นเสื่อมโทรมแสนสังเวช"; + term_buf.clear(); + term_buf.write(combining); + CPPUNIT_ASSERT ( combining.length() == 32 ); + CPPUNIT_ASSERT ( wcwidth(combining[0]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[1]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[2]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[3]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[4]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[5]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[6]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[7]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[8]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[9]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[10]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[11]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[12]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[13]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[14]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[15]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[16]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[17]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[18]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[19]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[20]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[21]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[22]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[23]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[24]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[25]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[26]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[27]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[28]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[29]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[30]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[31]) == 1 ); + CPPUNIT_ASSERT ( term_buf.getLength() == 25 ); + CPPUNIT_ASSERT ( term_buf.getBuffer().size() == 25 ); + CPPUNIT_ASSERT ( term_buf.begin() != term_buf.end() ); + CPPUNIT_ASSERT ( term_buf.front().ch[0] == L'๏' ); + CPPUNIT_ASSERT ( term_buf.front().ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[0] == L'\U00000e4f' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].ch[0] == L' ' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].ch[0] == L'\U00000e41' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].ch[0] == L'\U00000e1c' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].ch[1] == L'\U00000e48' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[4].ch[0] == L'\U00000e19' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[4].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[5].ch[0] == L'\U00000e14' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[5].ch[1] == L'\U00000e34' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[5].ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[6].ch[0] == L'\U00000e19' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[6].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[7].ch[0] == L'\U00000e2e' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[7].ch[1] == L'\U00000e31' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[7].ch[2] == L'\U00000e48' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[7].ch[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[8].ch[0] == L'\U00000e19' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[8].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[9].ch[0] == L'\U00000e40' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[9].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[10].ch[0] == L'\U00000e2a' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[10].ch[1] == L'\U00000e37' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[10].ch[2] == L'\U00000e48' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[10].ch[3] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[11].ch[0] == L'\U00000e2d' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[11].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[12].ch[0] == L'\U00000e21' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[12].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[13].ch[0] == L'\U00000e42' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[13].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[14].ch[0] == L'\U00000e17' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[14].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[15].ch[0] == L'\U00000e23' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[15].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[16].ch[0] == L'\U00000e21' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[16].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[17].ch[0] == L'\U00000e41' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[17].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[18].ch[0] == L'\U00000e2a' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[18].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[19].ch[0] == L'\U00000e19' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[19].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[20].ch[0] == L'\U00000e2a' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[20].ch[1] == L'\U00000e31' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[20].ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[21].ch[0] == L'\U00000e07' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[21].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[22].ch[0] == L'\U00000e40' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[22].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[23].ch[0] == L'\U00000e27' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[23].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[24].ch[0] == L'\U00000e0a' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[24].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[4].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[5].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[6].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[7].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[8].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[9].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[10].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[11].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[12].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[13].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[14].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[15].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[16].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[17].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[18].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[19].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[20].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[21].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[22].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[23].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[24].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.back().ch[0] == L'ช' ); + CPPUNIT_ASSERT ( term_buf.back().ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.toString() == combining ); + CPPUNIT_ASSERT ( term_buf.toString() == L"๏ แผ่นดินฮั่นเสื่อมโทรมแสนสังเวช" ); + + // Devanagari script (ISO 10646-1 - UCS implementation level 2) + combining = L"पन्ह पन्ह त्र र्च कृकृ ड्ड न्ह"; + term_buf.clear(); + term_buf.write(combining); + CPPUNIT_ASSERT ( combining.length() == 30 ); + CPPUNIT_ASSERT ( wcwidth(combining[0]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[1]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[2]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[3]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[4]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[5]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[6]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[7]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[8]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[9]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[10]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[11]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[12]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[13]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[14]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[15]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[16]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[17]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[18]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[19]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[20]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[21]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[22]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[23]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[24]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[25]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[26]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[27]) == 1 ); + CPPUNIT_ASSERT ( wcwidth(combining[28]) == 0 ); + CPPUNIT_ASSERT ( wcwidth(combining[29]) == 1 ); + CPPUNIT_ASSERT ( term_buf.getLength() == 22 ); + CPPUNIT_ASSERT ( term_buf.getBuffer().size() == 22 ); + CPPUNIT_ASSERT ( term_buf.begin() != term_buf.end() ); + CPPUNIT_ASSERT ( term_buf.front().ch[0] == L'\U0000092a' ); + CPPUNIT_ASSERT ( term_buf.front().ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[0] == L'\U0000092a' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].ch[0] == L'\U00000928' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].ch[1] == L'\U0000094d' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].ch[0] == L'\U00000939' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].ch[0] == L' ' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[4].ch[0] == L'\U0000092a' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[4].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[5].ch[0] == L'\U00000928' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[5].ch[1] == L'\U0000094d' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[5].ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[6].ch[0] == L'\U00000939' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[6].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[7].ch[0] == L' ' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[7].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[8].ch[0] == L'\U00000924' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[8].ch[1] == L'\U0000094d' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[8].ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[9].ch[0] == L'\U00000930' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[9].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[10].ch[0] == L' ' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[10].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[11].ch[0] == L'\U00000930' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[11].ch[1] == L'\U0000094d' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[11].ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[12].ch[0] == L'\U0000091a' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[12].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[13].ch[0] == L' ' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[13].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[14].ch[0] == L'\U00000915' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[14].ch[1] == L'\U00000943' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[14].ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[15].ch[0] == L'\U00000915' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[15].ch[1] == L'\U00000943' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[15].ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[16].ch[0] == L' ' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[16].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[17].ch[0] == L'\U00000921' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[17].ch[1] == L'\U0000094d' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[17].ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[18].ch[0] == L'\U00000921' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[18].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[19].ch[0] == L' ' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[19].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[20].ch[0] == L'\U00000928' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[20].ch[1] == L'\U0000094d' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[20].ch[2] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[21].ch[0] == L'\U00000939' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[21].ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[0].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[1].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[2].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[3].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[4].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[5].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[6].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[7].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[8].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[9].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[10].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[11].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[12].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[13].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[14].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[15].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[16].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[17].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[18].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[19].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[20].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.getBuffer()[21].attr.bit.char_width == 1 ); + CPPUNIT_ASSERT ( term_buf.back().ch[0] == L'\U00000939' ); + CPPUNIT_ASSERT ( term_buf.back().ch[1] == L'\0' ); + CPPUNIT_ASSERT ( term_buf.toString() == combining ); + CPPUNIT_ASSERT ( term_buf.toString() == L"पन्ह पन्ह त्र र्च कृकृ ड्ड न्ह" ); +} + + +// Put the test suite in the registry +CPPUNIT_TEST_SUITE_REGISTRATION (FTermBufferTest); + +// The general unit test main part +#include