From f1b2855e80ad184e6228635eded14927d10d907d Mon Sep 17 00:00:00 2001
From: Maciej Suminski <maciej.suminski@cern.ch>
Date: Mon, 22 Oct 2018 15:03:55 +0200
Subject: [PATCH] Fix ENV_VAR_NAME_VALIDATOR typing characters backwards

Fixes: lp:1798869
* https://bugs.launchpad.net/kicad/+bug/1798869
---
 common/validators.cpp | 50 +++++++++++++++++++++++++++++++++++++------
 include/validators.h  |  4 +++-
 2 files changed, 47 insertions(+), 7 deletions(-)

diff --git a/common/validators.cpp b/common/validators.cpp
index 28db81c135..5315df598d 100644
--- a/common/validators.cpp
+++ b/common/validators.cpp
@@ -168,15 +168,53 @@ void ENV_VAR_NAME_VALIDATOR::OnChar( wxKeyEvent& aEvent  )
     else if( wxIsalpha( c ) )
     {
         // Capitals only.
-        // Note: changing the keyCode and/or uniChar in the event and passing it on
-        // doesn't work.  Some platforms look at the original copy as long as the event
-        // isn't vetoed.  Insert the capitalized character by hand.
-        wxString s( c, 1 );
-        s = s.Capitalize();
-        GetTextEntry()->WriteText( s );
+
+        if( wxIslower( c ) )
+        {
+            // You may wonder why this scope is so twisted, so make yourself comfortable and read:
+            // 1. Changing the keyCode and/or uniChar in the event and passing it on
+            // doesn't work.  Some platforms look at the original copy as long as the event
+            // isn't vetoed.
+            // 2. Inserting characters by hand does not move the cursor, meaning either you insert
+            // text backwards (lp:#1798869) or always append, no matter where is the cursor.
+            // wxTextEntry::{Get/Set}InsertionPoint() do not work at all here.
+            // 3. There is wxTextEntry::ForceUpper(), but it is not yet available in common
+            // wxWidgets packages.
+            //
+            // So here we are, with a command event handler that converts
+            // the text to upper case upon every change.
+            wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( GetTextEntry() );
+
+            if( textCtrl )
+            {
+                textCtrl->Connect( textCtrl->GetId(), wxEVT_COMMAND_TEXT_UPDATED,
+                        (wxObjectEventFunction) &ENV_VAR_NAME_VALIDATOR::OnTextChanged );
+            }
+        }
+
+        aEvent.Skip();
     }
     else
     {
         wxBell();
     }
 }
+
+
+void ENV_VAR_NAME_VALIDATOR::OnTextChanged( wxCommandEvent& event )
+{
+    wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( event.GetEventObject() );
+
+    if( textCtrl )
+    {
+        if( !textCtrl->IsModified() )
+            return;
+
+        long insertionPoint = textCtrl->GetInsertionPoint();
+        textCtrl->ChangeValue( textCtrl->GetValue().Upper() );
+        textCtrl->SetInsertionPoint( insertionPoint );
+        textCtrl->Disconnect( textCtrl->GetId(), wxEVT_COMMAND_TEXT_UPDATED );
+    }
+
+    event.Skip();
+}
diff --git a/include/validators.h b/include/validators.h
index cbf44ac2d5..fb67e2b496 100644
--- a/include/validators.h
+++ b/include/validators.h
@@ -107,7 +107,9 @@ public:
         return new ENV_VAR_NAME_VALIDATOR( *this );
     }
 
-    void OnChar(wxKeyEvent& event);
+    void OnChar( wxKeyEvent& event );
+
+    void OnTextChanged( wxCommandEvent& event );
 };
 
 #endif  // #ifndef VALIDATORS_H