New method setInputType() in FLineEdit that allows to obscure password entries

This commit is contained in:
Markus Gans 2019-10-20 20:06:33 +02:00
parent 5e4a71dc0d
commit 5ceee8b4c8
12 changed files with 924 additions and 850 deletions

View File

@ -1,3 +1,8 @@
2019-10-20 Markus Gans <guru.mail@muenster.de>
* New method setInputType() in FLineEdit that allows to obscure
password entries
* FAcceleratorList reimplemented as non-pointer
2019-10-15 Markus Gans <guru.mail@muenster.de>
* Version 0.6.0

View File

@ -514,3 +514,4 @@ bit 0 (EGA Only) Output to pin 21 of the Feature Connector.
is the logical OR of the vertical sync and the vertical display
enable.
Note: On the VGA this register can be read from port 3CAh.

View File

@ -71,25 +71,28 @@ int main (int argc, char* argv[])
// Create input fields
finalcut::FLineEdit name_field (&dgl);
finalcut::FLineEdit pw_field (&dgl);
finalcut::FLineEdit email_field (&dgl);
finalcut::FLineEdit org_field (&dgl);
finalcut::FLineEdit city_field (&dgl);
finalcut::FLineEdit st_field (&dgl);
finalcut::FLineEdit c_field (&dgl);
// Set input type to password
pw_field.setInputType (finalcut::FLineEdit::password);
name_field.setLabelText (L"&Name");
pw_field.setLabelText (L"&Password");
email_field.setLabelText (L"&Email");
org_field.setLabelText (L"Or&ganization");
city_field.setLabelText (L"&City");
st_field.setLabelText (L"&State");
c_field.setLabelText (L"&Country");
name_field.setGeometry (FPoint(15, 1), FSize(19, 1));
email_field.setGeometry (FPoint(15, 3), FSize(19, 1));
org_field.setGeometry (FPoint(15, 5), FSize(19, 1));
city_field.setGeometry (FPoint(15, 7), FSize(19, 1));
st_field.setGeometry (FPoint(15, 9), FSize(19, 1));
c_field.setGeometry (FPoint(15, 11), FSize(4, 1));
name_field.setGeometry (FPoint(11, 1), FSize(23, 1));
pw_field.setGeometry (FPoint(11, 3), FSize(23, 1));
email_field.setGeometry (FPoint(11, 5), FSize(23, 1));
city_field.setGeometry (FPoint(11, 7), FSize(23, 1));
st_field.setGeometry (FPoint(11, 9), FSize(23, 1));
c_field.setGeometry (FPoint(11, 11), FSize(4, 1));
// Create the button group
finalcut::FButtonGroup radioButtonGroup ("Sex", &dgl);

View File

@ -13,10 +13,13 @@ License: LGPL-3.0-or-later
Group: Development/Libraries/C and C++
URL: https://github.com/gansm/finalcut/
Source: https://github.com/gansm/finalcut/archive/%{version}.tar.gz#/%{name}-%{version}.tar.gz
BuildRequires: autoconf
BuildRequires: autoconf-archive
BuildRequires: automake
BuildRequires: gcc-c++
BuildRequires: gcc-c++ >= 5.1
BuildRequires: glib2-devel
BuildRequires: gpm-devel
BuildRequires: gdb
BuildRequires: libtool
BuildRequires: ncurses-devel
@ -35,12 +38,13 @@ Group: Development/Libraries/C and C++
Requires: libfinal%{sover} = %{version}
Requires: bdftopcf
Requires: coreutils
Requires: gcc-c++
Requires: gcc-c++ >= 5.1
Requires: grep
Requires: gzip
Requires: sed
Requires: vim
Provides: libfinal-devel = %{version}
Obsoletes: libfinal-devel < %{version}
Recommends: libfinal-examples = %{version}
%description -n libfinal-devel
@ -56,6 +60,8 @@ radio buttons, input lines, list boxes, status bars and so on.
Summary: Example files for the FINAL CUT library
Group: Development/Languages/C and C++
BuildArch: noarch
Provides: libfinal-examples = %{version}
Obsoletes: libfinal-examples < %{version}
%description -n libfinal-examples
FINAL CUT is a class library and widget toolkit with full mouse
@ -108,8 +114,10 @@ make %{?_smp_mflags} V=1
make install libdir=%{buildroot}%{_libdir}/ \
includedir=%{buildroot}%{_includedir} \
bindir=%{buildroot}%{_bindir} \
docdir=%{buildroot}%{_docdir}/%{name}/
docdir=%{buildroot}%{_docdir}/%{name}/ \
fontdir=%{buildroot}%{_miscfontsdir}/%{name}/
mkdir -p %{buildroot}%{_docdir}/%{name}/examples
mkdir -p %{buildroot}%{_miscfontsdir}/%{name}/
cp -p examples/*.cpp %{buildroot}%{_docdir}/%{name}/examples
cp -p examples/Makefile.clang %{buildroot}%{_docdir}/%{name}/examples
cp -p examples/Makefile.gcc %{buildroot}%{_docdir}/%{name}/examples

View File

@ -716,11 +716,10 @@ bool FApplication::processAccelerator (const FWidget*& widget)
bool accpt{false};
if ( widget
&& widget->getAcceleratorList()
&& ! widget->getAcceleratorList()->empty() )
&& ! widget->getAcceleratorList().empty() )
{
auto iter = widget->getAcceleratorList()->begin();
auto last = widget->getAcceleratorList()->end();
auto iter = widget->getAcceleratorList().begin();
auto last = widget->getAcceleratorList().end();
while ( iter != last )
{

View File

@ -794,9 +794,6 @@ void FDialog::init()
old_focus->redraw();
}
// Create your own accelerator list for this dialog
createWidgetAcceleratorList();
// Add the dialog menu
initDialogMenu();
}

View File

@ -263,6 +263,8 @@ void FLineEdit::setText (const FString& txt)
else
text.setString("");
print_text = ( isPasswordField() ) ? getPasswordText() : text;
if ( isShown() )
{
cursorEnd();
@ -276,7 +278,10 @@ void FLineEdit::setMaxLength (std::size_t max)
max_length = max;
if ( text.getLength() > max_length )
{
text.setString(text.left(max_length));
print_text = ( isPasswordField() ) ? getPasswordText() : text;
}
if ( isShown() )
{
@ -343,6 +348,7 @@ void FLineEdit::clear()
text_offset = 0;
char_width_offset = 0;
text.clear();
print_text.clear();
}
//----------------------------------------------------------------------
@ -439,7 +445,7 @@ void FLineEdit::onMouseDown (FMouseEvent* ev)
if ( mouse_x >= xmin && mouse_x <= int(getWidth()) && mouse_y == 1 )
{
std::size_t len = text.getLength();
std::size_t len = print_text.getLength();
cursor_pos = clickPosToCursorPos (std::size_t(mouse_x) - 2);
if ( cursor_pos >= len )
@ -470,7 +476,7 @@ void FLineEdit::onMouseMove (FMouseEvent* ev)
if ( ev->getButton() != fc::LeftButton )
return;
std::size_t len = text.getLength();
std::size_t len = print_text.getLength();
int mouse_x = ev->getX();
int mouse_y = ev->getY();
@ -531,7 +537,7 @@ void FLineEdit::onMouseMove (FMouseEvent* ev)
//----------------------------------------------------------------------
void FLineEdit::onTimer (FTimerEvent*)
{
auto len = text.getLength();
auto len = print_text.getLength();
switch ( int(drag_scroll) )
{
@ -765,20 +771,24 @@ void FLineEdit::drawInputField()
if ( isActiveFocus && getMaxColor() < 16 )
setBold();
auto text_offset_column = getColumnWidth (text, text_offset);
std::size_t start_column = text_offset_column - char_width_offset + 1;
const FString& show_text = \
getColumnSubString(text, start_column, getWidth() - 2);
std::size_t text_offset_column = [&] () -> std::size_t
{
switch ( input_type )
{
case FLineEdit::textfield:
return printTextField();
if ( show_text )
print (show_text);
case FLineEdit::password:
return printPassword();
}
std::size_t x = getColumnWidth(show_text);
return 0;
}();
while ( x + 1 < getWidth() )
while ( x_pos + 1 < getWidth() )
{
print (' ');
x++;
x_pos++;
}
if ( isActiveFocus && getMaxColor() < 16 )
@ -794,26 +804,81 @@ void FLineEdit::drawInputField()
drawShadow(this);
// set the cursor to the insert pos.
auto cursor_pos_column = getColumnWidth (text, cursor_pos);
auto cursor_pos_column = getCursorColumnPos();
int xpos = int(2 + cursor_pos_column
- text_offset_column
+ char_width_offset);
setCursorPos (FPoint(xpos, 1));
}
//----------------------------------------------------------------------
inline std::size_t FLineEdit::printTextField()
{
std::size_t text_offset_column = getColumnWidth (print_text, text_offset);
std::size_t start_column = text_offset_column - char_width_offset + 1;
const FString& show_text = \
getColumnSubString(print_text, start_column, getWidth() - 2);
if ( ! show_text.isEmpty() )
print (show_text);
x_pos = getColumnWidth(show_text);
return text_offset_column;
}
//----------------------------------------------------------------------
inline std::size_t FLineEdit::printPassword()
{
std::size_t text_offset_column = text_offset;
FString show_text(print_text.mid(1 + text_offset, getWidth() - 2));
if ( ! show_text.isEmpty() )
print() << FString(show_text.getLength(), fc::Bullet); // •
x_pos = show_text.getLength();
return text_offset_column;
}
//----------------------------------------------------------------------
inline std::size_t FLineEdit::getCursorColumnPos()
{
switch ( input_type )
{
case FLineEdit::textfield:
return getColumnWidth (print_text, cursor_pos);
case FLineEdit::password:
return cursor_pos;
}
return 0;
}
//----------------------------------------------------------------------
inline const FString FLineEdit::getPasswordText() const
{
return FString(text.getLength(), fc::Bullet); // •
}
//----------------------------------------------------------------------
inline bool FLineEdit::isPasswordField() const
{
return bool( input_type == FLineEdit::password );
}
//----------------------------------------------------------------------
inline FLineEdit::offsetPair FLineEdit::endPosToOffset (std::size_t pos)
{
std::size_t input_width = getWidth() - 2;
std::size_t fullwidth_char_offset{0};
std::size_t len = text.getLength();
std::size_t len = print_text.getLength();
if ( pos >= len )
pos = len - 1;
while ( pos > 0 && input_width > 0 )
{
std::size_t char_width = getColumnWidth(text[pos]);
std::size_t char_width = getColumnWidth(print_text[pos]);
if ( input_width >= char_width )
input_width -= char_width;
@ -825,7 +890,7 @@ inline FLineEdit::offsetPair FLineEdit::endPosToOffset (std::size_t pos)
{
if ( char_width == 1 )
{
if ( getColumnWidth(text[pos - 1]) == 2 ) // pos is always > 0
if ( getColumnWidth(print_text[pos - 1]) == 2 ) // pos is always > 0
{
fullwidth_char_offset = 1;
break;
@ -850,12 +915,12 @@ std::size_t FLineEdit::clickPosToCursorPos (std::size_t pos)
{
std::size_t click_width{0};
std::size_t idx = text_offset;
std::size_t len = text.getLength();
std::size_t len = print_text.getLength();
pos -= char_width_offset;
while ( click_width < pos && idx < len )
{
std::size_t char_width = getColumnWidth(text[idx]);
std::size_t char_width = getColumnWidth(print_text[idx]);
idx++;
click_width += char_width;
@ -870,25 +935,25 @@ std::size_t FLineEdit::clickPosToCursorPos (std::size_t pos)
void FLineEdit::adjustTextOffset()
{
std::size_t input_width = getWidth() - 2;
std::size_t len = text.getLength();
std::size_t len_column = getColumnWidth (text);
std::size_t text_offset_column = getColumnWidth (text, text_offset);
std::size_t cursor_pos_column = getColumnWidth (text, cursor_pos);
std::size_t len = print_text.getLength();
std::size_t len_column = getColumnWidth (print_text);
std::size_t text_offset_column = getColumnWidth (print_text, text_offset);
std::size_t cursor_pos_column = getColumnWidth (print_text, cursor_pos);
std::size_t first_char_width{0};
std::size_t cursor_char_width{1};
char_width_offset = 0;
if ( cursor_pos < len )
cursor_char_width = getColumnWidth(text[cursor_pos]);
cursor_char_width = getColumnWidth(print_text[cursor_pos]);
if ( len > 0 )
first_char_width = getColumnWidth(text[0]);
first_char_width = getColumnWidth(print_text[0]);
// Text alignment right for long lines
while ( text_offset > 0 && len_column - text_offset_column < input_width )
{
text_offset--;
text_offset_column = getColumnWidth (text, text_offset);
text_offset_column = getColumnWidth (print_text, text_offset);
}
// Right cursor overflow
@ -897,7 +962,7 @@ void FLineEdit::adjustTextOffset()
offsetPair offset_pair = endPosToOffset(cursor_pos);
text_offset = offset_pair.first;
char_width_offset = offset_pair.second;
text_offset_column = getColumnWidth (text, text_offset);
text_offset_column = getColumnWidth (print_text, text_offset);
}
// Right full-width cursor overflow
@ -965,6 +1030,7 @@ inline void FLineEdit::deleteCurrentCharacter()
if ( len > 0 && cursor_pos < len )
{
text.remove(cursor_pos, 1);
print_text = ( isPasswordField() ) ? getPasswordText() : text;
processChanged();
}
@ -1035,6 +1101,7 @@ inline bool FLineEdit::keyInput (FKey key)
text.setString(ch);
cursor_pos++;
print_text = ( isPasswordField() ) ? getPasswordText() : text;
adjustTextOffset();
processChanged();
return true;

View File

@ -208,10 +208,10 @@ void FMenuItem::addAccelerator (FKey key, FWidget* obj)
auto root = getRootWidget();
FAccelerator accel = { key, obj };
if ( root && root->getAcceleratorList() )
if ( root )
{
accel_key = key;
root->getAcceleratorList()->push_back(accel);
root->setAcceleratorList().push_back(accel);
}
updateSuperMenuDimensions();
@ -223,17 +223,16 @@ void FMenuItem::delAccelerator (FWidget* obj)
auto root = getRootWidget();
if ( root
&& root->getAcceleratorList()
&& ! root->getAcceleratorList()->empty() )
&& ! root->getAcceleratorList().empty() )
{
auto iter = root->getAcceleratorList()->begin();
auto iter = root->getAcceleratorList().begin();
while ( iter != root->getAcceleratorList()->end() )
while ( iter != root->getAcceleratorList().end() )
{
if ( iter->object == obj )
{
accel_key = 0;
iter = root->getAcceleratorList()->erase(iter);
iter = root->setAcceleratorList().erase(iter);
}
else
++iter;

View File

@ -124,11 +124,7 @@ FWidget::~FWidget() // destructor
quit();
}
if ( accelerator_list )
{
delete accelerator_list;
accelerator_list = nullptr;
}
accelerator_list.clear();
// finish the program
if ( rootObject == this )
@ -929,8 +925,8 @@ void FWidget::addAccelerator (FKey key, FWidget* obj)
if ( ! widget || widget == statusbar || widget == menubar )
widget = getRootWidget();
if ( widget && widget->accelerator_list )
widget->accelerator_list->push_back(accel);
if ( widget )
widget->accelerator_list.push_back(accel);
}
//----------------------------------------------------------------------
@ -944,15 +940,14 @@ void FWidget::delAccelerator (FWidget* obj)
widget = getRootWidget();
if ( widget
&& widget->accelerator_list
&& ! widget->accelerator_list->empty() )
&& ! widget->accelerator_list.empty() )
{
auto iter = widget->accelerator_list->begin();
auto iter = widget->accelerator_list.begin();
while ( iter != widget->accelerator_list->end() )
while ( iter != widget->accelerator_list.end() )
{
if ( iter->object == obj )
iter = widget->accelerator_list->erase(iter);
iter = widget->accelerator_list.erase(iter);
else
++iter;
}
@ -1393,23 +1388,6 @@ void FWidget::hideArea (const FSize& size)
flushOutputBuffer();
}
//----------------------------------------------------------------------
void FWidget::createWidgetAcceleratorList()
{
if ( accelerator_list == 0 )
{
try
{
accelerator_list = new FAcceleratorList();
}
catch (const std::bad_alloc& ex)
{
std::cerr << bad_alloc_str << ex.what() << std::endl;
std::abort();
}
}
}
//----------------------------------------------------------------------
bool FWidget::focusNextChild()
{
@ -1734,9 +1712,6 @@ void FWidget::init()
foreground_color = wcolors.term_fg;
background_color = wcolors.term_bg;
init_desktop = false;
// Create the root object accelerator list
createWidgetAcceleratorList();
}
//----------------------------------------------------------------------

View File

@ -70,13 +70,19 @@ class FLabel;
class FLineEdit : public FWidget
{
public:
// Enumeration
// Enumerations
enum label_o
{
label_above = 0,
label_left = 1
};
enum inputType
{
textfield = 0,
password = 1
};
// Using-declaration
using FWidget::setGeometry;
@ -121,6 +127,7 @@ class FLineEdit : public FWidget
void setMaxLength (std::size_t);
void setCursorPosition (std::size_t);
void setLabelText (const FString&);
void setInputType (const inputType);
void setLabelOrientation (const label_o);
void setGeometry ( const FPoint&, const FSize&
, bool = true ) override;
@ -177,6 +184,11 @@ class FLineEdit : public FWidget
bool hasHotkey();
void draw() override;
void drawInputField();
std::size_t printTextField();
std::size_t printPassword();
std::size_t getCursorColumnPos();
const FString getPasswordText() const;
bool isPasswordField() const;
offsetPair endPosToOffset (std::size_t);
std::size_t clickPosToCursorPos (std::size_t);
void adjustTextOffset();
@ -195,17 +207,20 @@ class FLineEdit : public FWidget
// Data members
FString text{""};
FString print_text{""};
FString label_text{""};
FLabel* label{};
std::wstring input_filter{};
dragScroll drag_scroll{FLineEdit::noScroll};
label_o label_orientation{FLineEdit::label_left};
inputType input_type{FLineEdit::textfield};
int scroll_repeat{100};
bool scroll_timer{false};
bool insert_mode{true};
std::size_t cursor_pos{NOT_SET};
std::size_t text_offset{0};
std::size_t char_width_offset{0};
std::size_t x_pos{0};
std::size_t max_length{std::numeric_limits<std::size_t>::max()};
};
@ -239,6 +254,10 @@ inline void FLineEdit::setInputFilter (const FString& regex_string)
inline void FLineEdit::clearInputFilter()
{ input_filter.clear(); }
//----------------------------------------------------------------------
inline void FLineEdit::setInputType (const inputType type)
{ input_type = type; }
//----------------------------------------------------------------------
inline bool FLineEdit::setEnable()
{ return setEnable(true); }

View File

@ -36,9 +36,19 @@
#endif
#if defined(__linux__)
#if defined(__x86_64__) || defined(__i386) || defined(__arm__)
#include <sys/io.h> // <asm/io.h> is deprecated
#endif // defined(__x86_64__) || defined(__i386) || defined(__arm__)
#if defined(__arm__) && defined(__GLIBC__) && defined(__GLIBC_PREREQ)
// ISA sysctl support on arm processors only up to glibc-2.29
#if !__GLIBC_PREREQ(2,30)
#define ARM_ISA_SYSCTL
#endif
#endif
#if defined(__x86_64__) || defined(__i386) || defined(ARM_ISA_SYSCTL)
#define ISA_SYSCTL_SUPPORT
#include <sys/io.h>
#endif // defined(__x86_64__) || defined(__i386) || defined(ARM_ISA_SYSCTL)
#endif // defined(__linux__)
#if defined(__sun) && defined(__SVR4)
@ -88,8 +98,7 @@ class FSystemImpl : public FSystem
virtual ~FSystemImpl();
// Methods
#if defined(__linux__)
#if defined(__x86_64__) || defined(__i386) || defined(__arm__)
#if defined(ISA_SYSCTL_SUPPORT)
uChar inPortByte (uShort port) override
{
return ::inb (port);
@ -100,16 +109,9 @@ class FSystemImpl : public FSystem
return 0;
}
#endif
#else
uChar inPortByte (uShort) override
{
return 0;
}
#endif
#if defined(__linux__)
#if defined(__x86_64__) || defined(__i386) || defined(__arm__)
#if defined(ISA_SYSCTL_SUPPORT)
void outPortByte (uChar value, uShort port) override
{
::outb (value, port);
@ -118,11 +120,6 @@ class FSystemImpl : public FSystem
void outPortByte (uChar, uShort) override
{ }
#endif
#else
void outPortByte (uChar, uShort) override
{ }
#endif
int isTTY (int fd) override
{

View File

@ -202,7 +202,8 @@ class FWidget : public FVTerm, public FObject
static FStatusBar* getStatusBar();
virtual FWidget* getFirstFocusableWidget (FObjectList);
virtual FWidget* getLastFocusableWidget (FObjectList);
FAcceleratorList* getAcceleratorList() const;
const FAcceleratorList& getAcceleratorList() const;
FAcceleratorList& setAcceleratorList();
FString getStatusbarMessage() const;
FColor getForegroundColor() const; // get the primary
FColor getBackgroundColor() const; // widget colors
@ -379,7 +380,6 @@ class FWidget : public FVTerm, public FObject
virtual void adjustSize();
void adjustSizeGlobal();
void hideArea (const FSize&);
void createWidgetAcceleratorList();
virtual bool focusNextChild(); // Change child...
virtual bool focusPrevChild(); // ...focus
@ -486,7 +486,7 @@ class FWidget : public FVTerm, public FObject
FColor foreground_color{fc::Default};
FColor background_color{fc::Default};
FString statusbar_message{};
FAcceleratorList* accelerator_list{nullptr};
FAcceleratorList accelerator_list{};
FCallbackObjects callback_objects{};
static FStatusBar* statusbar;
@ -583,7 +583,11 @@ inline FStatusBar* FWidget::getStatusBar()
{ return statusbar; }
//----------------------------------------------------------------------
inline FWidget::FAcceleratorList* FWidget::getAcceleratorList() const
inline const FWidget::FAcceleratorList& FWidget::getAcceleratorList() const
{ return accelerator_list; }
//----------------------------------------------------------------------
inline FWidget::FAcceleratorList& FWidget::setAcceleratorList()
{ return accelerator_list; }
//----------------------------------------------------------------------