From b0febda5b4e6d5ec61d2c7d159563150e3c41ccb Mon Sep 17 00:00:00 2001 From: Markus Gans Date: Sun, 24 Feb 2019 20:21:12 +0100 Subject: [PATCH] Added the 7-segment example --- ChangeLog | 2 + examples/7segment | 210 ++++++++++++++++++++++++++++++++++++++++++ examples/7segment.cpp | 207 +++++++++++++++++++++++++++++++++++++++++ examples/Makefile.am | 2 + src/fstring.cpp | 4 +- 5 files changed, 423 insertions(+), 2 deletions(-) create mode 100755 examples/7segment create mode 100644 examples/7segment.cpp diff --git a/ChangeLog b/ChangeLog index 50387185..09ffe79d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,8 @@ via regular expression (regex) * Now FLineEdit can define a maximum character length for the input * The cursor position can now be set directly in FLineEdit + * Added the 7-segment example to demonstrate the use of FTermBuffer + and FLineEdit input filters 2019-02-07 Markus Gans * Add a "dynamic layout" Chapter into the first steps document diff --git a/examples/7segment b/examples/7segment new file mode 100755 index 00000000..acd32646 --- /dev/null +++ b/examples/7segment @@ -0,0 +1,210 @@ +#! /bin/bash + +# 7segment - temporary wrapper script for .libs/7segment +# Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-2 +# +# The 7segment program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command="" + +# This environment variable determines our operation mode. +if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then + # install mode needs the following variables: + generated_by_libtool_version='2.4.6' + notinst_deplibs=' /usr/local/src/MyProgs/finalcut/src/.libs/libfinal.la' +else + # When we are sourced in execute mode, $file and $ECHO are already set. + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + file="$0" + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + ECHO="printf %s\\n" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string --lt- +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's ../libtool value, followed by no. +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=$0 + shift + for lt_opt + do + case "$lt_opt" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` + test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. + lt_dump_F=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%^.*/%%'` + cat "$lt_dump_D/$lt_dump_F" + exit 0 + ;; + --lt-*) + $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n "$lt_option_debug"; then + echo "7segment:7segment:$LINENO: libtool wrapper (GNU libtool) 2.4.6 Debian-2.4.6-2" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + $ECHO "7segment:7segment:$LINENO: newargv[$lt_dump_args_N]: $lt_arg" + lt_dump_args_N=`expr $lt_dump_args_N + 1` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ + + if test -n "$lt_option_debug"; then + $ECHO "7segment:7segment:$LINENO: newargv[0]: $progdir/$program" 1>&2 + func_lt_dump_args ${1+"$@"} 1>&2 + fi + exec "$progdir/$program" ${1+"$@"} + + $ECHO "$0: cannot exec $program $*" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from $@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case " $* " in + *\ --lt-*) + for lt_wr_arg + do + case $lt_wr_arg in + --lt-*) ;; + *) set x "$@" "$lt_wr_arg"; shift;; + esac + shift + done ;; + esac + func_exec_program_core ${1+"$@"} +} + + # Parse options + func_parse_lt_options "$0" ${1+"$@"} + + # Find the directory that this script lives in. + thisdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'` + test "x$thisdir" = "x$file" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'` + while test -n "$file"; do + destdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'` + + # If there was a directory component, then change thisdir. + if test "x$destdir" != "x$file"; then + case "$destdir" in + [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; + *) thisdir="$thisdir/$destdir" ;; + esac + fi + + file=`$ECHO "$file" | /bin/sed 's%^.*/%%'` + file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no + if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then + # special case for '.' + if test "$thisdir" = "."; then + thisdir=`pwd` + fi + # remove .libs from thisdir + case "$thisdir" in + *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /bin/sed 's%[\\/][^\\/]*$%%'` ;; + .libs ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=`cd "$thisdir" && pwd` + test -n "$absdir" && thisdir="$absdir" + + program='7segment' + progdir="$thisdir/.libs" + + + if test -f "$progdir/$program"; then + # Add our own library path to LD_LIBRARY_PATH + LD_LIBRARY_PATH="/usr/local/src/MyProgs/finalcut/src/.libs:$LD_LIBRARY_PATH" + + # Some systems cannot cope with colon-terminated LD_LIBRARY_PATH + # The second colon is a workaround for a bug in BeOS R4 sed + LD_LIBRARY_PATH=`$ECHO "$LD_LIBRARY_PATH" | /bin/sed 's/::*$//'` + + export LD_LIBRARY_PATH + + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + # Run the actual program with our arguments. + func_exec_program ${1+"$@"} + fi + else + # The program doesn't exist. + $ECHO "$0: error: '$progdir/$program' does not exist" 1>&2 + $ECHO "This script is just a wrapper for $program." 1>&2 + $ECHO "See the libtool documentation for more information." 1>&2 + exit 1 + fi +fi diff --git a/examples/7segment.cpp b/examples/7segment.cpp new file mode 100644 index 00000000..7ca2c021 --- /dev/null +++ b/examples/7segment.cpp @@ -0,0 +1,207 @@ +#include + +using finalcut::FColorPair; +using finalcut::FPoint; +using finalcut::FSize; + + +//---------------------------------------------------------------------- +// class TextWindow +//---------------------------------------------------------------------- + +#pragma pack(push) +#pragma pack(1) + +class SegmentView : public finalcut::FDialog +{ + public: + explicit SegmentView (finalcut::FWidget* = nullptr); + + private: + // Typedef + typedef struct + { + unsigned char a : 1; + unsigned char b : 1; + unsigned char c : 1; + unsigned char d : 1; + unsigned char e : 1; + unsigned char f : 1; + unsigned char g : 1; + unsigned char : 1; // padding bit + } sevenSegment; + + // Methods + void hexEncoding(); + void get7Segment (const wchar_t); + virtual void draw() override; + + // Data Members + std::map code; + finalcut::FString line[3]; + finalcut::FLineEdit Input{"0123", this}; + finalcut::FButton Exit{"E&xit", this}; +}; +#pragma pack(pop) + +//---------------------------------------------------------------------- +SegmentView::SegmentView (finalcut::FWidget* parent) + : FDialog(parent) +{ + // Set encoding + hexEncoding(); + + // Dialog settings + setText ("Seven-segment display"); + setGeometry (FPoint(25, 5), FSize(42, 15)); + + // Input field + Input.setGeometry (FPoint(2, 2), FSize(12, 1)); + Input.setLabelText (L"&Hex value"); + Input.setLabelText (L"&Hex-digits or (.) (:) (H) (L) (P) (U)"); + Input.setLabelOrientation(finalcut::FLineEdit::label_above); + Input.setMaxLength(9); + Input.setInputFilter("[:.hHlLpPuU[:xdigit:]]"); + + // Exit button + Exit.setGeometry(FPoint(28, 11), FSize(10, 1)); + + // Add some function callbacks + Input.addCallback + ( + "changed", + [] (finalcut::FWidget*, FDataPtr data) + { + auto dialog = static_cast(data); + dialog->redraw(); + }, + this + ); + + Exit.addCallback + ( + "clicked", + F_METHOD_CALLBACK (this, &finalcut::FApplication::cb_exitApp) + ); +} + +//---------------------------------------------------------------------- +void SegmentView::hexEncoding() +{ + code['0'] = sevenSegment{1, 1, 1, 1, 1, 1, 0}; + code['1'] = sevenSegment{0, 1, 1, 0, 0, 0, 0}; + code['2'] = sevenSegment{1, 1, 0, 1, 1, 0, 1}; + code['3'] = sevenSegment{1, 1, 1, 1, 0, 0, 1}; + code['4'] = sevenSegment{0, 1, 1, 0, 0, 1, 1}; + code['5'] = sevenSegment{1, 0, 1, 1, 0, 1, 1}; + code['6'] = sevenSegment{1, 0, 1, 1, 1, 1, 1}; + code['7'] = sevenSegment{1, 1, 1, 0, 0, 0, 0}; + code['8'] = sevenSegment{1, 1, 1, 1, 1, 1, 1}; + code['9'] = sevenSegment{1, 1, 1, 1, 0, 1, 1}; + code['A'] = sevenSegment{1, 1, 1, 0, 1, 1, 1}; + code['B'] = sevenSegment{0, 0, 1, 1, 1, 1, 1}; + code['C'] = sevenSegment{1, 0, 0, 1, 1, 1, 0}; + code['D'] = sevenSegment{0, 1, 1, 1, 1, 0, 1}; + code['E'] = sevenSegment{1, 0, 0, 1, 1, 1, 1}; + code['F'] = sevenSegment{1, 0, 0, 0, 1, 1, 1}; +} + +//---------------------------------------------------------------------- +void SegmentView::get7Segment (const wchar_t c) +{ + sevenSegment& s = code[c]; + constexpr char h[2]{' ', '_'}; + constexpr char v[2]{' ', '|'}; + + for (int i = 0; i < 3; i++) + line[i].clear(); + + switch ( c ) + { + case ':': + line[0] = ' '; + line[1] = '.'; + line[2] = '.'; + break; + + case '.': + line[0] = ' '; + line[1] = ' '; + line[2] = '.'; + break; + + case 'H': + line[0] = " "; + line[1] = "|_|"; + line[2] = "| |"; + break; + + case 'L': + line[0] = " "; + line[1] = "| "; + line[2] = "|_ "; + break; + + case 'P': + line[0] = " _ "; + line[1] = "|_|"; + line[2] = "| "; + break; + + case 'U': + line[0] = " "; + line[1] = "| |"; + line[2] = "|_|"; + break; + + default: + // Hexadecimal digit from 0 up to f + line[0] << ' ' << h[s.a] << ' '; + line[1] << v[s.f] << h[s.g] << v[s.b]; + line[2] << v[s.e] << h[s.d] << v[s.c]; + } +} + +//---------------------------------------------------------------------- +void SegmentView::draw() +{ + std::vector tbuffer{3}; + finalcut::FTermBuffer left_space{}; + + FDialog::draw(); + setColor(finalcut::fc::LightGray, finalcut::fc::Black); + FWidget::drawBorder(3, 6, 40, 11); + + for (auto&& ch : Input.getText().toUpper()) + { + FColorPair color(finalcut::fc::LightRed, finalcut::fc::Black); + get7Segment(ch); + + for (std::size_t i = 0; i < 3; i++) + tbuffer[i] << color << line[i] << " "; + } + + std::size_t length = tbuffer[0].getLength(); + + if ( length < 36 ) + left_space << finalcut::FString(36 - length, ' '); + + print() << FPoint (4, 7) << left_space << tbuffer[0] + << FPoint (4, 8) << left_space << tbuffer[1] + << FPoint (4, 9) << left_space << tbuffer[2] + << FPoint (4, 10) << finalcut::FString(36, ' '); +} + + +//---------------------------------------------------------------------- +// main part +//---------------------------------------------------------------------- + +int main (int argc, char* argv[]) +{ + finalcut::FApplication app(argc, argv); + SegmentView dialog(&app); + app.setMainWidget(&dialog); + dialog.show(); + return app.exec(); +} diff --git a/examples/Makefile.am b/examples/Makefile.am index f0a0304e..73a0df1c 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -11,6 +11,7 @@ noinst_PROGRAMS = \ hello \ dialog \ input-dialog \ + 7segment \ choice \ listbox \ listview \ @@ -35,6 +36,7 @@ noinst_PROGRAMS = \ hello_SOURCES = hello.cpp dialog_SOURCES = dialog.cpp input_dialog_SOURCES = input-dialog.cpp +7segment_SOURCES = 7segment.cpp choice_SOURCES = choice.cpp listbox_SOURCES = listbox.cpp listview_SOURCES = listview.cpp diff --git a/src/fstring.cpp b/src/fstring.cpp index d0db046f..616734a1 100644 --- a/src/fstring.cpp +++ b/src/fstring.cpp @@ -1091,7 +1091,7 @@ bool FString::operator == (const FString& s) const if ( ! (string || s.string) ) return true; - if ( bool(string) != bool(s.string) ) + if ( bool(string) != bool(s.string) || length != s.length ) return false; return ( std::wcscmp(string, s.string) == 0 ); @@ -1103,7 +1103,7 @@ bool FString::operator != (const FString& s) const if ( ! (string || s.string) ) return false; - if ( bool(string) != bool(s.string) ) + if ( bool(string) != bool(s.string) || length != s.length ) return true; return ( std::wcscmp(string, s.string) != 0 );