From 11de95778b1869b2604e2f2d484ab64d0330352c Mon Sep 17 00:00:00 2001
From: Marek Roszko <mark.roszko@gmail.com>
Date: Sat, 9 Sep 2023 00:10:57 -0400
Subject: [PATCH] Unwrap the FROM_UTF8 macro in favor of direct function

The extern just gets annoying to try to export the func later. We also yeet TO_UTF8 to string_utils.h for parity.
---
 3d-viewer/3d_canvas/eda_3d_canvas.cpp         |  4 +-
 .../3d_model_viewer/eda_3d_model_viewer.cpp   |  2 +-
 common/dialogs/dialog_page_settings.cpp       |  1 +
 common/dialogs/dialog_plugin_options.cpp      |  6 +-
 .../dialogs/eda_reorderable_list_dialog.cpp   |  2 +-
 common/drawing_sheet/ds_data_model_io.cpp     |  4 +-
 common/drawing_sheet/ds_proxy_undo_item.cpp   |  2 +-
 common/font/fontconfig.cpp                    |  4 +-
 common/import_gfx/dxf_import_plugin.cpp       |  4 +-
 common/markup_parser.cpp                      |  4 +-
 common/pgm_base.cpp                           |  3 +-
 common/plotters/PS_plotter.cpp                |  1 +
 common/reporter.cpp                           |  3 +-
 common/richio.cpp                             |  4 +-
 common/search_stack.cpp                       |  2 +-
 common/string_utils.cpp                       |  4 +-
 common/swig/wx_python_helpers.cpp             |  4 +-
 common/template_fieldnames.cpp                |  4 +-
 common/xnode.cpp                              |  2 +-
 cvpcb/auto_associate.cpp                      |  2 +-
 cvpcb/cvpcb_mainframe.cpp                     |  2 +-
 cvpcb/display_footprints_frame.cpp            |  4 +-
 cvpcb/readwrite_dlgs.cpp                      |  4 +-
 eeschema/cross-probing.cpp                    |  6 +-
 .../dialogs/panel_template_fieldnames.cpp     |  4 +-
 eeschema/eeschema_jobs_handler.cpp            |  1 +
 eeschema/eeschema_settings.cpp                |  2 +-
 .../netlist_exporter_spice_model.cpp          |  1 +
 .../legacy/sch_legacy_lib_plugin_cache.cpp    |  2 +-
 .../sch_plugins/legacy/sch_legacy_plugin.cpp  |  2 +-
 .../legacy/sch_legacy_plugin_helpers.cpp      |  6 +-
 eeschema/sch_reference_list.cpp               | 18 +++++-
 eeschema/sch_reference_list.h                 | 16 +-----
 eeschema/sch_view.cpp                         |  1 +
 eeschema/sim/spice_circuit_model.cpp          |  2 +-
 eeschema/tools/assign_footprints.cpp          |  6 +-
 eeschema/tools/backannotate.cpp               |  2 +-
 gerbview/X2_gerber_attributes.cpp             |  6 +-
 gerbview/excellon_read_drill_file.cpp         |  2 +-
 gerbview/gerbview.cpp                         |  1 +
 gerbview/job_file_reader.cpp                  |  4 +-
 gerbview/rs274x.cpp                           |  5 +-
 include/macros.h                              | 22 --------
 include/ptree.h                               |  2 +-
 include/string_utils.h                        | 11 ++++
 kicad/cli/command.cpp                         | 10 ++--
 kicad/cli/command_fp_export_svg.cpp           |  5 +-
 kicad/cli/command_pcb_drc.cpp                 |  5 +-
 kicad/cli/command_pcb_export_3d.cpp           | 11 ++--
 kicad/cli/command_pcb_export_base.cpp         |  3 +-
 kicad/cli/command_pcb_export_drill.cpp        | 13 +++--
 kicad/cli/command_pcb_export_dxf.cpp          |  3 +-
 kicad/cli/command_pcb_export_gerbers.cpp      |  3 +-
 kicad/cli/command_pcb_export_pdf.cpp          |  3 +-
 kicad/cli/command_pcb_export_pos.cpp          |  7 ++-
 kicad/cli/command_pcb_export_svg.cpp          |  3 +-
 kicad/cli/command_sch_erc.cpp                 |  5 +-
 kicad/cli/command_sch_export_bom.cpp          | 19 ++++---
 kicad/cli/command_sch_export_netlist.cpp      |  3 +-
 kicad/cli/command_sch_export_plot.cpp         |  4 +-
 kicad/cli/command_sym_export_svg.cpp          |  5 +-
 kicad/cli/command_version.cpp                 |  4 +-
 kicad/import_proj.cpp                         |  1 +
 kicad/kicad_cli.cpp                           |  6 +-
 kicad/project_tree_pane.cpp                   |  1 +
 libs/sexpr/sexpr_parser.cpp                   |  4 +-
 pagelayout_editor/tools/pl_edit_tool.cpp      |  1 +
 pcb_calculator/datafile_read_write.cpp        |  2 +-
 pcbnew/build_BOM_from_board.cpp               |  2 +-
 pcbnew/cross-probing.cpp                      |  4 +-
 pcbnew/dialogs/dialog_exchange_footprints.cpp |  4 +-
 pcbnew/exporters/export_idf.cpp               |  4 +-
 pcbnew/exporters/exporter_vrml.cpp            |  2 +-
 pcbnew/exporters/gen_drill_report_files.cpp   |  4 +-
 pcbnew/exporters/gerber_placefile_writer.cpp  |  4 +-
 pcbnew/footprint_edit_frame.cpp               |  4 +-
 .../netlist_reader/kicad_netlist_reader.cpp   | 40 ++++++-------
 .../netlist_reader/legacy_netlist_reader.cpp  | 18 +++---
 pcbnew/netlist_reader/netlist_reader.cpp      |  6 +-
 pcbnew/pcb_plot_params.cpp                    |  4 +-
 pcbnew/plugins/geda/gpcb_plugin.cpp           |  2 +-
 pcbnew/plugins/kicad/pcb_parser.cpp           |  6 +-
 pcbnew/plugins/legacy/legacy_plugin.cpp       | 56 +++++++++----------
 pcbnew/python/scripting/pcbnew_scripting.cpp  |  2 +-
 .../specctra_import.cpp                       | 14 ++---
 .../specctra_import_export/specctra_test.cpp  |  2 +-
 qa/qa_utils/test_app_main.cpp                 |  8 +--
 scripting/python_scripting.cpp                |  6 +-
 thirdparty/markdown2html/markdown2html.cpp    |  5 +-
 utils/idftools/idf_helpers.h                  |  2 +-
 90 files changed, 266 insertions(+), 248 deletions(-)

diff --git a/3d-viewer/3d_canvas/eda_3d_canvas.cpp b/3d-viewer/3d_canvas/eda_3d_canvas.cpp
index 367f0d6f72..88db847653 100644
--- a/3d-viewer/3d_canvas/eda_3d_canvas.cpp
+++ b/3d-viewer/3d_canvas/eda_3d_canvas.cpp
@@ -227,10 +227,10 @@ bool  EDA_3D_CANVAS::initializeOpenGL()
     else
     {
         wxLogTrace( m_logTrace, wxT( "EDA_3D_CANVAS::initializeOpenGL Using GLEW version %s" ),
-                    FROM_UTF8( (char*) glewGetString( GLEW_VERSION ) ) );
+                    From_UTF8( (char*) glewGetString( GLEW_VERSION ) ) );
     }
 
-    wxString version = FROM_UTF8( (char *) glGetString( GL_VERSION ) );
+    wxString version = From_UTF8( (char *) glGetString( GL_VERSION ) );
 
     wxLogTrace( m_logTrace, wxT( "EDA_3D_CANVAS::%s OpenGL version string %s." ),
                 __WXFUNCTION__, version );
diff --git a/3d-viewer/3d_model_viewer/eda_3d_model_viewer.cpp b/3d-viewer/3d_model_viewer/eda_3d_model_viewer.cpp
index 3e89bde576..b807ca96ee 100644
--- a/3d-viewer/3d_model_viewer/eda_3d_model_viewer.cpp
+++ b/3d-viewer/3d_model_viewer/eda_3d_model_viewer.cpp
@@ -197,7 +197,7 @@ void EDA_3D_MODEL_VIEWER::ogl_initialize()
     else
     {
         wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::ogl_initialize Using GLEW version %s" ),
-                    FROM_UTF8( (char*) glewGetString( GLEW_VERSION ) ) );
+                    From_UTF8( (char*) glewGetString( GLEW_VERSION ) ) );
     }
 
     glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
diff --git a/common/dialogs/dialog_page_settings.cpp b/common/dialogs/dialog_page_settings.cpp
index 20d111de75..22ff04ce8a 100644
--- a/common/dialogs/dialog_page_settings.cpp
+++ b/common/dialogs/dialog_page_settings.cpp
@@ -37,6 +37,7 @@
 #include <wildcards_and_files_ext.h>
 #include <drawing_sheet/ds_data_model.h>
 #include <drawing_sheet/ds_painter.h>
+#include <string_utils.h>
 #include <widgets/std_bitmap_button.h>
 #include <wx/valgen.h>
 #include <wx/tokenzr.h>
diff --git a/common/dialogs/dialog_plugin_options.cpp b/common/dialogs/dialog_plugin_options.cpp
index 311260b107..8079625a22 100644
--- a/common/dialogs/dialog_plugin_options.cpp
+++ b/common/dialogs/dialog_plugin_options.cpp
@@ -30,7 +30,7 @@
 #include <widgets/wx_grid.h>
 #include <widgets/std_bitmap_button.h>
 #include <bitmaps.h>
-#include <macros.h>
+#include <string_utils.h>
 
 
 #define INITIAL_HELP    \
@@ -67,7 +67,7 @@ DIALOG_PLUGIN_OPTIONS::DIALOG_PLUGIN_OPTIONS( wxWindow* aParent,
         for( STRING_UTF8_MAP::const_iterator it = m_choices.begin(); it != m_choices.end();
                 ++it, ++row )
         {
-            wxString item = FROM_UTF8( it->first.c_str() );
+            wxString item = From_UTF8( it->first.c_str() );
 
             m_listbox->InsertItems( 1, &item, row );
         }
@@ -113,7 +113,7 @@ bool DIALOG_PLUGIN_OPTIONS::TransferDataToWindow()
         for( STRING_UTF8_MAP::const_iterator it = props->begin(); it != props->end();
                 ++it, ++row )
         {
-            m_grid->SetCellValue( row, 0, FROM_UTF8( it->first.c_str() ) );
+            m_grid->SetCellValue( row, 0, From_UTF8( it->first.c_str() ) );
             m_grid->SetCellValue( row, 1, it->second );
         }
 
diff --git a/common/dialogs/eda_reorderable_list_dialog.cpp b/common/dialogs/eda_reorderable_list_dialog.cpp
index b7be51e839..d0e95f35ff 100644
--- a/common/dialogs/eda_reorderable_list_dialog.cpp
+++ b/common/dialogs/eda_reorderable_list_dialog.cpp
@@ -19,7 +19,7 @@
 
 #include <algorithm>
 #include <bitmaps.h>
-#include <macros.h>
+#include <string_utils.h>
 #include <dialogs/eda_reorderable_list_dialog.h>
 
 
diff --git a/common/drawing_sheet/ds_data_model_io.cpp b/common/drawing_sheet/ds_data_model_io.cpp
index 1a2a063fac..0671f207fd 100644
--- a/common/drawing_sheet/ds_data_model_io.cpp
+++ b/common/drawing_sheet/ds_data_model_io.cpp
@@ -26,7 +26,6 @@
 
 #include <string_utils.h>
 #include <locale_io.h>
-#include <macros.h>
 #include <math/vector2d.h>
 #include <drawing_sheet/ds_painter.h>
 #include <drawing_sheet/ds_data_item.h>
@@ -34,6 +33,7 @@
 #include <drawing_sheet/drawing_sheet_lexer.h>
 #include <drawing_sheet/ds_file_versions.h>
 #include <font/font.h>
+#include <string_utils.h>
 
 #include <wx/base64.h>
 #include <wx/msgdlg.h>
@@ -125,7 +125,7 @@ public:
 
     ~DS_DATA_MODEL_STRINGIO()
     {
-        *m_output = FROM_UTF8( m_writer->GetString().c_str() );
+        *m_output = From_UTF8( m_writer->GetString().c_str() );
         delete m_writer;
     }
 
diff --git a/common/drawing_sheet/ds_proxy_undo_item.cpp b/common/drawing_sheet/ds_proxy_undo_item.cpp
index 75dec48078..cc5c44b834 100644
--- a/common/drawing_sheet/ds_proxy_undo_item.cpp
+++ b/common/drawing_sheet/ds_proxy_undo_item.cpp
@@ -26,7 +26,7 @@
 #include <drawing_sheet/ds_data_model.h>
 #include <view/view.h>
 #include <eda_draw_frame.h>
-#include <macros.h>
+#include <string_utils.h>
 
 using namespace KIGFX;
 
diff --git a/common/font/fontconfig.cpp b/common/font/fontconfig.cpp
index 3fc02e8cb7..644be0fe47 100644
--- a/common/font/fontconfig.cpp
+++ b/common/font/fontconfig.cpp
@@ -137,7 +137,7 @@ std::string FONTCONFIG::getFamilyStringByLang( FONTCONFIG_PAT& aPat, const wxStr
 
     for( auto const& [key, val] : famStrings )
     {
-        if( isLanguageMatch( aDesiredLang, FROM_UTF8( key.c_str() ) ) )
+        if( isLanguageMatch( aDesiredLang, From_UTF8( key.c_str() ) ) )
         {
             return val;
         }
@@ -297,7 +297,7 @@ void FONTCONFIG::ListFonts( std::vector<std::string>& aFonts, const std::string&
 
                 FONTCONFIG_PAT patHolder{ font };
                 std::string    theFamily =
-                        getFamilyStringByLang( patHolder, FROM_UTF8( aDesiredLang.c_str() ) );
+                        getFamilyStringByLang( patHolder, From_UTF8( aDesiredLang.c_str() ) );
 
 #ifdef __WXMAC__
                 // On Mac (at least) some of the font names are in their own language.  If
diff --git a/common/import_gfx/dxf_import_plugin.cpp b/common/import_gfx/dxf_import_plugin.cpp
index ede1756e34..5708dc797a 100644
--- a/common/import_gfx/dxf_import_plugin.cpp
+++ b/common/import_gfx/dxf_import_plugin.cpp
@@ -316,8 +316,8 @@ void DXF_IMPORT_PLUGIN::addLayer( const DL_LayerData& aData )
 void DXF_IMPORT_PLUGIN::addLinetype( const DL_LinetypeData& data )
 {
 #if 0
-    wxString name = FROM_UTF8( data.name.c_str() );
-    wxString description = FROM_UTF8( data.description.c_str() );
+    wxString name = From_UTF8( data.name.c_str() );
+    wxString description = From_UTF8( data.description.c_str() );
 #endif
 }
 
diff --git a/common/markup_parser.cpp b/common/markup_parser.cpp
index e94f522177..58b6bd524c 100644
--- a/common/markup_parser.cpp
+++ b/common/markup_parser.cpp
@@ -21,7 +21,7 @@
 
 #include <markup_parser.h>
 #include <sstream>
-#include "macros.h"
+#include <string_utils.h>
 
 using namespace MARKUP;
 
@@ -65,7 +65,7 @@ std::string NODE::typeString() const
 
 wxString NODE::asWxString() const
 {
-    return FROM_UTF8( string().c_str() );
+    return From_UTF8( string().c_str() );
 }
 
 
diff --git a/common/pgm_base.cpp b/common/pgm_base.cpp
index c3c617275f..9a868fa428 100644
--- a/common/pgm_base.cpp
+++ b/common/pgm_base.cpp
@@ -64,6 +64,7 @@
 #include <python_scripting.h>
 #include <settings/common_settings.h>
 #include <settings/settings_manager.h>
+#include <string_utils.h>
 #include <systemdirsappend.h>
 #include <core/thread_pool.h>
 #include <trace_helpers.h>
@@ -945,7 +946,7 @@ void PGM_BASE::HandleException( std::exception_ptr aPtr )
 #endif
 
         wxLogError( wxT( "Unhandled exception class: %s  what: %s" ),
-                    FROM_UTF8( typeid( e ).name() ), FROM_UTF8( e.what() ) );
+                    From_UTF8( typeid( e ).name() ), From_UTF8( e.what() ) );
     }
     catch( ... )
     {
diff --git a/common/plotters/PS_plotter.cpp b/common/plotters/PS_plotter.cpp
index 14fd0aeabb..d0ba6cf1f5 100644
--- a/common/plotters/PS_plotter.cpp
+++ b/common/plotters/PS_plotter.cpp
@@ -30,6 +30,7 @@
 #include <convert_basic_shapes_to_polygon.h>
 #include <macros.h>
 #include <math/util.h>      // for KiROUND
+#include <string_utils.h>
 #include <trigo.h>
 
 #include <plotters/plotters_pslike.h>
diff --git a/common/reporter.cpp b/common/reporter.cpp
index 2ffea4d10f..2fca9d9f04 100644
--- a/common/reporter.cpp
+++ b/common/reporter.cpp
@@ -27,6 +27,7 @@
 
 #include <macros.h>
 #include <reporter.h>
+#include <string_utils.h>
 #include <widgets/wx_infobar.h>
 #include <widgets/wx_html_report_panel.h>
 #include <wx/crt.h>
@@ -36,7 +37,7 @@
 
 REPORTER& REPORTER::Report( const char* aText, SEVERITY aSeverity )
 {
-    Report( FROM_UTF8( aText ) );
+    Report( From_UTF8( aText ) );
     return *this;
 }
 
diff --git a/common/richio.cpp b/common/richio.cpp
index 4f6cdf7f4b..a82444b0d8 100644
--- a/common/richio.cpp
+++ b/common/richio.cpp
@@ -109,7 +109,7 @@ std::string StrPrintf( const char* format, ... )
 
 wxString SafeReadFile( const wxString& aFilePath, const wxString& aReadType )
 {
-    auto FROM_UTF8_WINE =
+    auto From_UTF8_WINE =
             []( const char* cstring )
             {
                 wxString line = wxString::FromUTF8( cstring );
@@ -142,7 +142,7 @@ wxString SafeReadFile( const wxString& aFilePath, const wxString& aReadType )
     wxString contents;
 
     while( fileReader.ReadLine() )
-        contents += FROM_UTF8_WINE( fileReader.Line() );
+        contents += From_UTF8_WINE( fileReader.Line() );
 
     return contents;
 }
diff --git a/common/search_stack.cpp b/common/search_stack.cpp
index 32a8a37f4f..e75b187a2d 100644
--- a/common/search_stack.cpp
+++ b/common/search_stack.cpp
@@ -22,8 +22,8 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <macros.h>
 #include <search_stack.h>
+#include <string_utils.h>
 #include <trace_helpers.h>
 #include <wx/tokenzr.h>
 #include <wx/log.h>
diff --git a/common/string_utils.cpp b/common/string_utils.cpp
index 971c36546b..7227c3bf0c 100644
--- a/common/string_utils.cpp
+++ b/common/string_utils.cpp
@@ -412,7 +412,7 @@ int ReadDelimitedText( wxString* aDest, const char* aSource )
         }
     }
 
-    *aDest = FROM_UTF8( utf8.c_str() );
+    *aDest = From_UTF8( utf8.c_str() );
 
     return aSource - start;
 }
@@ -1016,7 +1016,7 @@ int GetTrailingInt( const wxString& aStr )
 
 wxString GetIllegalFileNameWxChars()
 {
-    return FROM_UTF8( illegalFileNameChars );
+    return From_UTF8( illegalFileNameChars );
 }
 
 
diff --git a/common/swig/wx_python_helpers.cpp b/common/swig/wx_python_helpers.cpp
index 47f2905623..08ac530624 100644
--- a/common/swig/wx_python_helpers.cpp
+++ b/common/swig/wx_python_helpers.cpp
@@ -28,7 +28,7 @@
  */
 
 #include <Python.h> // must be first to avoid wx/python typedef conflicts on msvc
-#include <macros.h>
+#include <string_utils.h>
 #include <wx/intl.h>
 #include <wx/string.h>
 #include <wx/arrstr.h>
@@ -87,7 +87,7 @@ wxString Py2wxString( PyObject* src )
     size_t len = PyUnicode_GET_LENGTH( uni_str );
 
     if( len )
-        result = FROM_UTF8( PyUnicode_AsUTF8( uni_str ) );
+        result = From_UTF8( PyUnicode_AsUTF8( uni_str ) );
 
     if( must_unref_str )
     {
diff --git a/common/template_fieldnames.cpp b/common/template_fieldnames.cpp
index 38f60c8ca8..577fea79a6 100644
--- a/common/template_fieldnames.cpp
+++ b/common/template_fieldnames.cpp
@@ -24,9 +24,9 @@
 
 #include <mutex>
 
-#include <macros.h>
 #include <template_fieldnames.h>
 #include <pgm_base.h>
+#include <string_utils.h>
 
 using namespace TFIELD_T;
 
@@ -95,7 +95,7 @@ void TEMPLATE_FIELDNAME::Parse( TEMPLATE_FIELDNAMES_LEXER* in )
 
     in->NeedSYMBOLorNUMBER();
 
-    m_Name = FROM_UTF8( in->CurText() );
+    m_Name = From_UTF8( in->CurText() );
 
     in->NeedRIGHT();    // end (name ...)
 
diff --git a/common/xnode.cpp b/common/xnode.cpp
index 0fb2854a87..62b6477c45 100644
--- a/common/xnode.cpp
+++ b/common/xnode.cpp
@@ -24,7 +24,7 @@
 
 
 #include <xnode.h>
-#include <macros.h>
+#include <string_utils.h>
 
 typedef wxXmlAttribute   XATTR;
 
diff --git a/cvpcb/auto_associate.cpp b/cvpcb/auto_associate.cpp
index 5144fa52c7..1b50f666d8 100644
--- a/cvpcb/auto_associate.cpp
+++ b/cvpcb/auto_associate.cpp
@@ -141,7 +141,7 @@ int CVPCB_MAINFRAME::buildEquivalenceList( FOOTPRINT_EQUIVALENCE_LIST& aList,
             if( *line == 0 )
                 continue;
 
-            wxString wtext = FROM_UTF8( line );
+            wxString wtext = From_UTF8( line );
             wxString value = GetQuotedText( wtext );
 
             if( value.IsEmpty() )
diff --git a/cvpcb/cvpcb_mainframe.cpp b/cvpcb/cvpcb_mainframe.cpp
index 6981b2e176..d346253ca1 100644
--- a/cvpcb/cvpcb_mainframe.cpp
+++ b/cvpcb/cvpcb_mainframe.cpp
@@ -705,7 +705,7 @@ void CVPCB_MAINFRAME::refreshAfterSymbolSearch( COMPONENT* aSymbol )
     // selected footprint.
     if( FindFocus() == m_symbolsListBox || FindFocus() == m_librariesListBox )
     {
-        wxString footprintName = FROM_UTF8( aSymbol->GetFPID().Format().c_str() );
+        wxString footprintName = From_UTF8( aSymbol->GetFPID().Format().c_str() );
 
         m_footprintListBox->SetSelection( m_footprintListBox->GetSelection(), false );
 
diff --git a/cvpcb/display_footprints_frame.cpp b/cvpcb/display_footprints_frame.cpp
index 1bb8a47edf..14429d19ed 100644
--- a/cvpcb/display_footprints_frame.cpp
+++ b/cvpcb/display_footprints_frame.cpp
@@ -409,8 +409,8 @@ FOOTPRINT* DISPLAY_FOOTPRINTS_FRAME::GetFootprint( const wxString& aFootprintNam
         return nullptr;
     }
 
-    wxString libNickname = FROM_UTF8( fpid.GetLibNickname().c_str() );
-    wxString fpName      = FROM_UTF8( fpid.GetLibItemName().c_str() );
+    wxString libNickname = From_UTF8( fpid.GetLibNickname().c_str() );
+    wxString fpName      = From_UTF8( fpid.GetLibItemName().c_str() );
 
     FP_LIB_TABLE* fpTable = Prj().PcbFootprintLibs();
     wxASSERT( fpTable );
diff --git a/cvpcb/readwrite_dlgs.cpp b/cvpcb/readwrite_dlgs.cpp
index 2932c189ab..a4a247ba35 100644
--- a/cvpcb/readwrite_dlgs.cpp
+++ b/cvpcb/readwrite_dlgs.cpp
@@ -28,7 +28,7 @@
 #include <dialogs/html_message_box.h>
 #include <kiway.h>
 #include <lib_id.h>
-#include <macros.h>
+#include <string_utils.h>
 
 #include <cvpcb_mainframe.h>
 #include <fp_conflict_assignment_selector.h>
@@ -268,7 +268,7 @@ bool CVPCB_MAINFRAME::readNetListAndFpFiles( const std::string& aNetlist )
         msg = formatSymbolDesc( m_symbolsListBox->GetCount() + 1,
                                 component->GetReference(),
                                 component->GetValue(),
-                                FROM_UTF8( component->GetFPID().Format().c_str() ) );
+                                From_UTF8( component->GetFPID().Format().c_str() ) );
 
         m_symbolsListBox->AppendLine( msg );
 
diff --git a/eeschema/cross-probing.cpp b/eeschema/cross-probing.cpp
index c63dd5e009..3f2837c02b 100644
--- a/eeschema/cross-probing.cpp
+++ b/eeschema/cross-probing.cpp
@@ -218,7 +218,7 @@ void SCH_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
         if( !crossProbingSettings.auto_highlight )
             return;
 
-        wxString netName = FROM_UTF8( text );
+        wxString netName = From_UTF8( text );
 
         if( auto sg = Schematic().ConnectionGraph()->FindFirstSubgraphByName( netName ) )
             m_highlightedConn = sg->GetDriverConnection()->Name();
@@ -245,7 +245,7 @@ void SCH_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
     if( strcmp( idcmd, "$PART:" ) != 0 )
         return;
 
-    wxString part_ref = FROM_UTF8( text );
+    wxString part_ref = From_UTF8( text );
 
     /* look for a complement */
     idcmd = strtok( nullptr, " \n\r" );
@@ -262,7 +262,7 @@ void SCH_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
     if( text == nullptr )
         return;
 
-    wxString msg = FROM_UTF8( text );
+    wxString msg = From_UTF8( text );
 
     if( strcmp( idcmd, "$REF:" ) == 0 )
     {
diff --git a/eeschema/dialogs/panel_template_fieldnames.cpp b/eeschema/dialogs/panel_template_fieldnames.cpp
index 46c435bc08..59186e0de5 100644
--- a/eeschema/dialogs/panel_template_fieldnames.cpp
+++ b/eeschema/dialogs/panel_template_fieldnames.cpp
@@ -29,7 +29,7 @@
 #include <template_fieldnames.h>
 #include <grid_tricks.h>
 #include <bitmaps.h>
-#include <macros.h>
+#include <string_utils.h>
 #include <panel_template_fieldnames.h>
 
 PANEL_TEMPLATE_FIELDNAMES::PANEL_TEMPLATE_FIELDNAMES( wxWindow* aWindow,
@@ -200,7 +200,7 @@ bool PANEL_TEMPLATE_FIELDNAMES::TransferDataFromWindow()
             STRING_FORMATTER sf;
             m_templateMgr->Format( &sf, 0, true );
 
-            wxString record = FROM_UTF8( sf.GetString().c_str() );
+            wxString record = From_UTF8( sf.GetString().c_str() );
             record.Replace( wxT("\n"), wxT(""), true );   // strip all newlines
             record.Replace( wxT("  "), wxT(" "), true );  // double space to single
 
diff --git a/eeschema/eeschema_jobs_handler.cpp b/eeschema/eeschema_jobs_handler.cpp
index 657f917a09..533ab3823e 100644
--- a/eeschema/eeschema_jobs_handler.cpp
+++ b/eeschema/eeschema_jobs_handler.cpp
@@ -45,6 +45,7 @@
 #include <plotters/plotters_pslike.h>
 #include <drawing_sheet/ds_data_model.h>
 #include <reporter.h>
+#include <string_utils.h>
 
 #include <settings/settings_manager.h>
 
diff --git a/eeschema/eeschema_settings.cpp b/eeschema/eeschema_settings.cpp
index c834a4072c..231e33d4a0 100644
--- a/eeschema/eeschema_settings.cpp
+++ b/eeschema/eeschema_settings.cpp
@@ -28,7 +28,7 @@
 #include <eeschema_settings.h>
 #include <layer_ids.h>
 #include <symbol_editor_settings.h>
-#include <macros.h>
+#include <string_utils.h>
 #include <pgm_base.h>
 #include <settings/common_settings.h>
 #include <settings/json_settings_internals.h>
diff --git a/eeschema/netlist_exporters/netlist_exporter_spice_model.cpp b/eeschema/netlist_exporters/netlist_exporter_spice_model.cpp
index c93afa0ac6..f9b7923f99 100644
--- a/eeschema/netlist_exporters/netlist_exporter_spice_model.cpp
+++ b/eeschema/netlist_exporters/netlist_exporter_spice_model.cpp
@@ -25,6 +25,7 @@
 #include "netlist_exporter_spice_model.h"
 #include <sch_screen.h>
 #include <sch_label.h>
+#include <string_utils.h>
 
 
 void NETLIST_EXPORTER_SPICE_MODEL::WriteHead( OUTPUTFORMATTER& aFormatter,
diff --git a/eeschema/sch_plugins/legacy/sch_legacy_lib_plugin_cache.cpp b/eeschema/sch_plugins/legacy/sch_legacy_lib_plugin_cache.cpp
index 90deea6a03..21a8b567ae 100644
--- a/eeschema/sch_plugins/legacy/sch_legacy_lib_plugin_cache.cpp
+++ b/eeschema/sch_plugins/legacy/sch_legacy_lib_plugin_cache.cpp
@@ -220,7 +220,7 @@ void SCH_LEGACY_PLUGIN_CACHE::loadDocs()
             if( strCompare( "$ENDCMP", line, &line ) )
                 break;
 
-            text = FROM_UTF8( line + 2 );
+            text = From_UTF8( line + 2 );
             // Remove spaces at eol, and eol chars:
             text = text.Trim();
 
diff --git a/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp b/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp
index 0afbcaa453..1a35769a71 100644
--- a/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp
+++ b/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp
@@ -1059,7 +1059,7 @@ SCH_TEXT* SCH_LEGACY_PLUGIN::loadText( LINE_READER& aReader )
     char* tmp = aReader.ReadLine();
 
     tmp = strtok( tmp, "\r\n" );
-    wxString val = FROM_UTF8( tmp );
+    wxString val = From_UTF8( tmp );
 
     for( ; ; )
     {
diff --git a/eeschema/sch_plugins/legacy/sch_legacy_plugin_helpers.cpp b/eeschema/sch_plugins/legacy/sch_legacy_plugin_helpers.cpp
index 5c366226b5..9819585f95 100644
--- a/eeschema/sch_plugins/legacy/sch_legacy_plugin_helpers.cpp
+++ b/eeschema/sch_plugins/legacy/sch_legacy_plugin_helpers.cpp
@@ -22,7 +22,7 @@
 #include <wx/intl.h>
 #include <wx/string.h>
 
-#include <macros.h>
+#include <string_utils.h>
 #include <richio.h>
 
 #include <config.h> // contains strncasecmp for msvc
@@ -216,7 +216,7 @@ void parseUnquotedString( wxString& aString, LINE_READER& aReader, const char* a
     while( *tmp && !isspace( *tmp ) )
         utf8 += *tmp++;
 
-    aString = FROM_UTF8( utf8.c_str() );
+    aString = From_UTF8( utf8.c_str() );
 
     if( aString.IsEmpty() && !aCanBeEmpty )
         SCH_PARSE_ERROR( _( "expected unquoted string" ), aReader, aCurrentToken );
@@ -293,7 +293,7 @@ void parseQuotedString( wxString& aString, LINE_READER& aReader, const char* aCu
         tmp++;
     }
 
-    aString = FROM_UTF8( utf8.c_str() );
+    aString = From_UTF8( utf8.c_str() );
 
     if( aString.IsEmpty() && !aCanBeEmpty )
         SCH_PARSE_ERROR( "expected quoted string", aReader, aCurrentToken );
diff --git a/eeschema/sch_reference_list.cpp b/eeschema/sch_reference_list.cpp
index e6448bca9a..868539c0b7 100644
--- a/eeschema/sch_reference_list.cpp
+++ b/eeschema/sch_reference_list.cpp
@@ -831,7 +831,7 @@ void SCH_REFERENCE::Annotate()
     else
         m_ref = TO_UTF8( GetRef() << GetRefNumber() );
 
-    m_rootSymbol->SetRef( &m_sheetPath, FROM_UTF8( m_ref.c_str() ) );
+    m_rootSymbol->SetRef( &m_sheetPath, From_UTF8( m_ref.c_str() ) );
     m_rootSymbol->SetUnit( m_unit );
     m_rootSymbol->SetUnitSelection( &m_sheetPath, m_unit );
 }
@@ -952,3 +952,19 @@ wxString SCH_REFERENCE_LIST::Shorthand( std::vector<SCH_REFERENCE> aList,
 
     return retVal;
 }
+
+
+#if defined( DEBUG )
+void SCH_REFERENCE_LIST::Show( const char* aPrefix )
+{
+    printf( "%s\n", aPrefix );
+
+    for( unsigned i = 0; i < m_flatList.size(); ++i )
+    {
+        SCH_REFERENCE& schref = m_flatList[i];
+
+        printf( " [%-2d] ref:%-8s num:%-3d lib_part:%s\n", i, schref.m_ref.ToStdString().c_str(),
+                schref.m_numRef, TO_UTF8( schref.GetLibPart()->GetName() ) );
+    }
+}
+#endif
\ No newline at end of file
diff --git a/eeschema/sch_reference_list.h b/eeschema/sch_reference_list.h
index 141b1d99fd..7d355796c0 100644
--- a/eeschema/sch_reference_list.h
+++ b/eeschema/sch_reference_list.h
@@ -560,21 +560,7 @@ public:
     std::vector<SCH_SYMBOL_INSTANCE> GetSymbolInstances() const;
 
 #if defined(DEBUG)
-    void Show( const char* aPrefix = "" )
-    {
-        printf( "%s\n", aPrefix );
-
-        for( unsigned i=0; i < m_flatList.size(); ++i )
-        {
-            SCH_REFERENCE& schref = m_flatList[i];
-
-            printf( " [%-2d] ref:%-8s num:%-3d lib_part:%s\n",
-                    i,
-                    schref.m_ref.ToStdString().c_str(),
-                    schref.m_numRef,
-                    TO_UTF8( schref.GetLibPart()->GetName() ) );
-        }
-    }
+    void Show( const char* aPrefix = "" );
 #endif
 
     /**
diff --git a/eeschema/sch_view.cpp b/eeschema/sch_view.cpp
index e14ce3e963..00d8c7e3ec 100644
--- a/eeschema/sch_view.cpp
+++ b/eeschema/sch_view.cpp
@@ -37,6 +37,7 @@
 #include <schematic.h>
 #include <sch_base_frame.h>
 #include <sch_edit_frame.h>
+#include <string_utils.h>
 
 #include "sch_view.h"
 
diff --git a/eeschema/sim/spice_circuit_model.cpp b/eeschema/sim/spice_circuit_model.cpp
index 7b9bbded67..8be5e29382 100644
--- a/eeschema/sim/spice_circuit_model.cpp
+++ b/eeschema/sim/spice_circuit_model.cpp
@@ -24,7 +24,7 @@
  */
 
 #include "spice_circuit_model.h"
-#include <macros.h>     // for TO_UTF8 def
+#include <string_utils.h>
 #include <wx/regex.h>
 #include <wx/tokenzr.h>
 #include <locale_io.h>
diff --git a/eeschema/tools/assign_footprints.cpp b/eeschema/tools/assign_footprints.cpp
index d6d1af7cdd..27e7b5bd76 100644
--- a/eeschema/tools/assign_footprints.cpp
+++ b/eeschema/tools/assign_footprints.cpp
@@ -51,7 +51,7 @@ void SCH_EDITOR_CONTROL::AssignFootprints( const std::string& aChangedSetOfRefer
 
     sheets.GetSymbols( refs, false );
 
-    DSNLEXER lexer( aChangedSetOfReferences, FROM_UTF8( __func__ ) );
+    DSNLEXER lexer( aChangedSetOfReferences, From_UTF8( __func__ ) );
     PTREE    doc;
 
     try
@@ -150,7 +150,7 @@ bool SCH_EDITOR_CONTROL::processCmpToFootprintLinkFile( const wxString& aFullFil
 
     while( cmpFileReader.ReadLine() )
     {
-        buffer = FROM_UTF8( cmpFileReader.Line() );
+        buffer = From_UTF8( cmpFileReader.Line() );
 
         if( !buffer.StartsWith( wxT( "BeginCmp" ) ) )
             continue;
@@ -161,7 +161,7 @@ bool SCH_EDITOR_CONTROL::processCmpToFootprintLinkFile( const wxString& aFullFil
 
         while( cmpFileReader.ReadLine() )
         {
-            buffer = FROM_UTF8( cmpFileReader.Line() );
+            buffer = From_UTF8( cmpFileReader.Line() );
 
             if( buffer.StartsWith( wxT( "EndCmp" ) ) )
                 break;
diff --git a/eeschema/tools/backannotate.cpp b/eeschema/tools/backannotate.cpp
index 1c033fa807..a787a1dc20 100644
--- a/eeschema/tools/backannotate.cpp
+++ b/eeschema/tools/backannotate.cpp
@@ -135,7 +135,7 @@ void BACK_ANNOTATE::getPcbModulesFromString( const std::string& aPayload )
                       return UTF8( pt.front().first );
                   };
 
-    DSNLEXER lexer( aPayload, FROM_UTF8( __func__ ) );
+    DSNLEXER lexer( aPayload, From_UTF8( __func__ ) );
     PTREE    doc;
 
     // NOTE: KiCad's PTREE scanner constructs a property *name* tree, not a property tree.
diff --git a/gerbview/X2_gerber_attributes.cpp b/gerbview/X2_gerber_attributes.cpp
index 6814349bdb..251625a6fe 100644
--- a/gerbview/X2_gerber_attributes.cpp
+++ b/gerbview/X2_gerber_attributes.cpp
@@ -43,7 +43,7 @@
 
 #include <wx/log.h>
 #include <X2_gerber_attributes.h>
-#include <macros.h>
+#include <string_utils.h>
 
 
 X2_ATTRIBUTE::X2_ATTRIBUTE()
@@ -107,14 +107,14 @@ bool X2_ATTRIBUTE::ParseAttribCmd( FILE* aFile, char *aBuffer, int aBuffSize, ch
                 break;
 
             case '*':       // End of block
-                m_Prms.Add( FROM_UTF8( data.c_str() ) );
+                m_Prms.Add( From_UTF8( data.c_str() ) );
                 data.clear();
                 aText++;
                 break;
 
             case ',':       // End of parameter (separator)
                 aText++;
-                m_Prms.Add( FROM_UTF8( data.c_str() ) );
+                m_Prms.Add( From_UTF8( data.c_str() ) );
                 data.clear();
                 break;
 
diff --git a/gerbview/excellon_read_drill_file.cpp b/gerbview/excellon_read_drill_file.cpp
index 1172f4e17e..328f179ce7 100644
--- a/gerbview/excellon_read_drill_file.cpp
+++ b/gerbview/excellon_read_drill_file.cpp
@@ -1045,7 +1045,7 @@ bool EXCELLON_IMAGE::Execute_EXCELLON_G_Command( char*& text )
 
     case DRILL_G_UNKNOWN:
     default:
-        AddMessageToList( wxString::Format( _( "Unknown Excellon G Code: &lt;%s&gt;" ), FROM_UTF8(gcmd) ) );
+        AddMessageToList( wxString::Format( _( "Unknown Excellon G Code: &lt;%s&gt;" ), From_UTF8(gcmd) ) );
         while( *text )
             text++;
         return false;
diff --git a/gerbview/gerbview.cpp b/gerbview/gerbview.cpp
index 1f30fcdd3f..beb73619ed 100644
--- a/gerbview/gerbview.cpp
+++ b/gerbview/gerbview.cpp
@@ -36,6 +36,7 @@
 #include <pgm_base.h>
 #include <richio.h>
 #include <settings/settings_manager.h>
+#include <string_utils.h>
 #include <dialogs/panel_gerbview_display_options.h>
 #include <dialogs/panel_gerbview_excellon_settings.h>
 #include <dialogs/panel_gerbview_color_settings.h>
diff --git a/gerbview/job_file_reader.cpp b/gerbview/job_file_reader.cpp
index 478cd74658..93f1612097 100644
--- a/gerbview/job_file_reader.cpp
+++ b/gerbview/job_file_reader.cpp
@@ -33,7 +33,7 @@
 #include <gerbview.h>
 #include <richio.h>
 #include <locale_io.h>
-#include <macros.h>
+#include <string_utils.h>
 #include <gerber_file_image.h>
 #include <gerber_file_image_list.h>
 #include <gerbview_frame.h>
@@ -169,7 +169,7 @@ wxString GERBER_JOBFILE_READER::formatStringFromJSON( const std::string& name )
     // to encode unicode chars
     // Our json11 library returns in this case a UTF8 sequence. Just convert it to
     // a wxString.
-    wxString wstr = FROM_UTF8( name.c_str() );
+    wxString wstr = From_UTF8( name.c_str() );
     return wstr;
 }
 
diff --git a/gerbview/rs274x.cpp b/gerbview/rs274x.cpp
index 89654fb2d2..b6c4ada0d5 100644
--- a/gerbview/rs274x.cpp
+++ b/gerbview/rs274x.cpp
@@ -33,6 +33,7 @@
 #include <gerber_file_image.h>
 #include <core/ignore.h>
 #include <macros.h>
+#include <string_utils.h>
 #include <X2_gerber_attributes.h>
 #include <gbr_metadata.h>
 #include <wx/log.h>
@@ -1032,7 +1033,7 @@ bool GERBER_FILE_IMAGE::ReadApertureMacro( char *aBuff, unsigned int aBuffSize,
         else if( !isdigit(*aText)  )     // Ill. symbol
         {
             msg.Printf( wxT( "RS274X: Aperture Macro \"%s\": ill. symbol, line: \"%s\"" ),
-                        am.m_AmName, FROM_UTF8( aBuff ) );
+                        am.m_AmName, From_UTF8( aBuff ) );
             AddMessageToList( msg );
             primitive_type = AMP_COMMENT;
         }
@@ -1086,7 +1087,7 @@ bool GERBER_FILE_IMAGE::ReadApertureMacro( char *aBuff, unsigned int aBuffSize,
 
         default:
             msg.Printf( wxT( "RS274X: Aperture Macro \"%s\": Invalid primitive id code %d, line %d: \"%s\"" ),
-                        am.m_AmName, primitive_type, m_LineNum, FROM_UTF8( aBuff ) );
+                        am.m_AmName, primitive_type, m_LineNum, From_UTF8( aBuff ) );
             AddMessageToList( msg );
             return false;
         }
diff --git a/include/macros.h b/include/macros.h
index 6b51e6fcef..e5333cd6ab 100644
--- a/include/macros.h
+++ b/include/macros.h
@@ -84,17 +84,6 @@
 
 #endif
 
-/**
- * Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
- *
- * wxstring is a wxString, not a wxT() or _().  The scope of the return value
- * is very limited and volatile, but can be used with printf() style functions well.
- *
- * @note Trying to convert it to a function is tricky because of the type of the
- *       parameter!
- */
-#define TO_UTF8( wxstring )  ( (const char*) (wxstring).utf8_str() )
-
 /**
  * Stringifies the given parameter by placing in quotes.
  *
@@ -104,17 +93,6 @@
 #define TO_STR2(x) #x
 #define TO_STR(x) TO_STR2(x)
 
-/**
- * Convert an expected UTF8 encoded C string to a wxString.
- * If fails, tray to convert using current locale
- * If still fails, return an empty wxString
- * This macro is obsolete. Replaced by
- * wxString From_UTF8( const char* cstring )
- * (and also wxString From_UTF8( const std::string& aString ) )
- */
-wxString From_UTF8( const char* cstring );
-#define FROM_UTF8(x) From_UTF8(x)
-
 #define UNIMPLEMENTED_FOR( type ) \
         wxFAIL_MSG( wxString::Format( wxT( "%s: unimplemented for %s" ), __FUNCTION__, type ) )
 
diff --git a/include/ptree.h b/include/ptree.h
index 03c49de891..65023e2f85 100644
--- a/include/ptree.h
+++ b/include/ptree.h
@@ -68,7 +68,7 @@ typedef boost::property_tree::ptree_error   PTREE_ERROR;
  *
  * static const KEYWORD empty_keywords[1] = {};
  *
- * DSNLEXER   lexer( empty_keywords, 0, fp, wxString( FROM_UTF8( argv[1] ) ) );
+ * DSNLEXER   lexer( empty_keywords, 0, fp, wxString( From_UTF8( argv[1] ) ) );
  *
  * try
  * {
diff --git a/include/string_utils.h b/include/string_utils.h
index 87cd70e0ae..cf5e709aca 100644
--- a/include/string_utils.h
+++ b/include/string_utils.h
@@ -364,6 +364,17 @@ std::string UIDouble2Str( double aValue );
  */
 std::string FormatDouble2Str( double aValue );
 
+/**
+ * Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
+ *
+ * wxstring is a wxString, not a wxT() or _().  The scope of the return value
+ * is very limited and volatile, but can be used with printf() style functions well.
+ *
+ * @note Trying to convert it to a function is tricky because of the type of the
+ *       parameter!
+ */
+#define TO_UTF8( wxstring ) ( (const char*) ( wxstring ).utf8_str() )
+
 /**
  * Convert an expected UTF8 encoded std::string to a wxString.
  * If fails, tray to convert using current locale
diff --git a/kicad/cli/command.cpp b/kicad/cli/command.cpp
index 74693bba1d..b6fa49b512 100644
--- a/kicad/cli/command.cpp
+++ b/kicad/cli/command.cpp
@@ -49,7 +49,7 @@ void CLI::COMMAND::PrintHelp()
 {
     std::stringstream ss;
     ss << m_argParser;
-    wxPrintf( FROM_UTF8( ss.str().c_str() ) );
+    wxPrintf( From_UTF8( ss.str().c_str() ) );
 }
 
 
@@ -64,17 +64,17 @@ int CLI::COMMAND::Perform( KIWAY& aKiway )
 
     if ( m_hasInputArg )
     {
-        m_argInput = FROM_UTF8( m_argParser.get<std::string>( ARG_INPUT ).c_str() );
+        m_argInput = From_UTF8( m_argParser.get<std::string>( ARG_INPUT ).c_str() );
     }
 
     if( m_hasOutputArg )
     {
-        m_argOutput = FROM_UTF8( m_argParser.get<std::string>( ARG_OUTPUT ).c_str() );
+        m_argOutput = From_UTF8( m_argParser.get<std::string>( ARG_OUTPUT ).c_str() );
     }
 
     if( m_hasDrawingSheetArg )
     {
-        m_argDrawingSheet = FROM_UTF8( m_argParser.get<std::string>( ARG_DRAWING_SHEET ).c_str() );
+        m_argDrawingSheet = From_UTF8( m_argParser.get<std::string>( ARG_DRAWING_SHEET ).c_str() );
     }
 
 
@@ -84,7 +84,7 @@ int CLI::COMMAND::Perform( KIWAY& aKiway )
 
         for( const std::string& def : defines )
         {
-            wxString      str = FROM_UTF8( def.c_str() );
+            wxString      str = From_UTF8( def.c_str() );
             wxArrayString bits;
             wxStringSplit( str, bits, wxS( '=' ) );
 
diff --git a/kicad/cli/command_fp_export_svg.cpp b/kicad/cli/command_fp_export_svg.cpp
index 55af4e5fc2..8b9563cc58 100644
--- a/kicad/cli/command_fp_export_svg.cpp
+++ b/kicad/cli/command_fp_export_svg.cpp
@@ -23,6 +23,7 @@
 #include "jobs/job_fp_export_svg.h"
 #include <kiface_base.h>
 #include <layer_ids.h>
+#include <string_utils.h>
 #include <wx/crt.h>
 #include <wx/dir.h>
 
@@ -65,7 +66,7 @@ int CLI::FP_EXPORT_SVG_COMMAND::doPerform( KIWAY& aKiway )
     svgJob->m_libraryPath = m_argInput;
     svgJob->m_outputDirectory = m_argOutput;
     svgJob->m_blackAndWhite = m_argParser.get<bool>( ARG_BLACKANDWHITE );
-    svgJob->m_footprint = FROM_UTF8( m_argParser.get<std::string>( ARG_FOOTPRINT ).c_str() );
+    svgJob->m_footprint = From_UTF8( m_argParser.get<std::string>( ARG_FOOTPRINT ).c_str() );
     svgJob->SetVarOverrides( m_argDefineVars );
 
     if( !wxDir::Exists( svgJob->m_libraryPath ) )
@@ -74,7 +75,7 @@ int CLI::FP_EXPORT_SVG_COMMAND::doPerform( KIWAY& aKiway )
         return EXIT_CODES::ERR_INVALID_INPUT_FILE;
     }
 
-    svgJob->m_colorTheme = FROM_UTF8( m_argParser.get<std::string>( ARG_THEME ).c_str() );
+    svgJob->m_colorTheme = From_UTF8( m_argParser.get<std::string>( ARG_THEME ).c_str() );
 
     if( m_selectedLayers.count() > 0 )
         svgJob->m_printMaskLayer = m_selectedLayers;
diff --git a/kicad/cli/command_pcb_drc.cpp b/kicad/cli/command_pcb_drc.cpp
index 1e6828bb1e..4a84d7f6df 100644
--- a/kicad/cli/command_pcb_drc.cpp
+++ b/kicad/cli/command_pcb_drc.cpp
@@ -23,6 +23,7 @@
 #include "jobs/job_pcb_drc.h"
 #include <kiface_base.h>
 #include <layer_ids.h>
+#include <string_utils.h>
 #include <wx/crt.h>
 
 #include <macros.h>
@@ -118,7 +119,7 @@ int CLI::PCB_DRC_COMMAND::doPerform( KIWAY& aKiway )
 
     drcJob->m_reportAllTrackErrors = m_argParser.get<bool>( ARG_ALL_TRACK_ERRORS );
 
-    wxString units = FROM_UTF8( m_argParser.get<std::string>( ARG_UNITS ).c_str() );
+    wxString units = From_UTF8( m_argParser.get<std::string>( ARG_UNITS ).c_str() );
 
     if( units == wxS( "mm" ) )
     {
@@ -138,7 +139,7 @@ int CLI::PCB_DRC_COMMAND::doPerform( KIWAY& aKiway )
         return EXIT_CODES::ERR_ARGS;
     }
 
-    wxString format = FROM_UTF8( m_argParser.get<std::string>( ARG_FORMAT ).c_str() );
+    wxString format = From_UTF8( m_argParser.get<std::string>( ARG_FORMAT ).c_str() );
     if( format == "report" )
     {
         drcJob->m_format = JOB_PCB_DRC::OUTPUT_FORMAT::REPORT;
diff --git a/kicad/cli/command_pcb_export_3d.cpp b/kicad/cli/command_pcb_export_3d.cpp
index 44d85bfb01..d4ce0c590c 100644
--- a/kicad/cli/command_pcb_export_3d.cpp
+++ b/kicad/cli/command_pcb_export_3d.cpp
@@ -22,6 +22,7 @@
 #include <cli/exit_codes.h>
 #include <kiface_base.h>
 #include <regex>
+#include <string_utils.h>
 #include <locale_io.h>
 #include <wx/crt.h>
 
@@ -169,7 +170,7 @@ int CLI::PCB_EXPORT_3D_COMMAND::doPerform( KIWAY& aKiway )
 
     if( step->m_format == JOB_EXPORT_PCB_3D::FORMAT::UNKNOWN )
     {
-        wxString format = FROM_UTF8( m_argParser.get<std::string>( ARG_FORMAT ).c_str() );
+        wxString format = From_UTF8( m_argParser.get<std::string>( ARG_FORMAT ).c_str() );
 
         if( format == wxS( "step" ) )
             step->m_format = JOB_EXPORT_PCB_3D::FORMAT::STEP;
@@ -184,7 +185,7 @@ int CLI::PCB_EXPORT_3D_COMMAND::doPerform( KIWAY& aKiway )
 
     if( step->m_format == JOB_EXPORT_PCB_3D::FORMAT::VRML )
     {
-        wxString units = FROM_UTF8( m_argParser.get<std::string>( ARG_VRML_UNITS ).c_str() );
+        wxString units = From_UTF8( m_argParser.get<std::string>( ARG_VRML_UNITS ).c_str() );
 
         if( units == wxS( "in" ) )
             step->m_vrmlUnits = JOB_EXPORT_PCB_3D::VRML_UNITS::INCHES;
@@ -200,12 +201,12 @@ int CLI::PCB_EXPORT_3D_COMMAND::doPerform( KIWAY& aKiway )
             return EXIT_CODES::ERR_ARGS;
         }
 
-        step->m_vrmlModelDir = FROM_UTF8( m_argParser.get<std::string>( ARG_VRML_MODELS_DIR ).c_str() );
+        step->m_vrmlModelDir = From_UTF8( m_argParser.get<std::string>( ARG_VRML_MODELS_DIR ).c_str() );
 
         step->m_vrmlRelativePaths = m_argParser.get<bool>( ARG_VRML_MODELS_RELATIVE );
     }
 
-    wxString userOrigin = FROM_UTF8( m_argParser.get<std::string>( ARG_USER_ORIGIN ).c_str() );
+    wxString userOrigin = From_UTF8( m_argParser.get<std::string>( ARG_USER_ORIGIN ).c_str() );
 
     LOCALE_IO dummy;    // Switch to "C" locale
 
@@ -254,7 +255,7 @@ int CLI::PCB_EXPORT_3D_COMMAND::doPerform( KIWAY& aKiway )
     if( m_format == JOB_EXPORT_PCB_3D::FORMAT::STEP || m_format == JOB_EXPORT_PCB_3D::FORMAT::GLB )
     {
         wxString minDistance =
-                FROM_UTF8( m_argParser.get<std::string>( ARG_MIN_DISTANCE ).c_str() );
+                From_UTF8( m_argParser.get<std::string>( ARG_MIN_DISTANCE ).c_str() );
 
         if( !minDistance.IsEmpty() )
         {
diff --git a/kicad/cli/command_pcb_export_base.cpp b/kicad/cli/command_pcb_export_base.cpp
index d64409d249..927cb5c860 100644
--- a/kicad/cli/command_pcb_export_base.cpp
+++ b/kicad/cli/command_pcb_export_base.cpp
@@ -23,6 +23,7 @@
 #include <kiface_base.h>
 #include <bitset>
 #include <layer_ids.h>
+#include <string_utils.h>
 
 #include <macros.h>
 #include <wx/tokenzr.h>
@@ -124,7 +125,7 @@ int CLI::PCB_EXPORT_BASE_COMMAND::doPerform( KIWAY& aKiway )
 {
     if( m_hasLayerArg )
     {
-        wxString layers = FROM_UTF8( m_argParser.get<std::string>( ARG_LAYERS ).c_str() );
+        wxString layers = From_UTF8( m_argParser.get<std::string>( ARG_LAYERS ).c_str() );
 
         LSET layerMask = convertLayerStringList( layers, m_selectedLayersSet );
         if( m_requireLayers && layerMask.Seq().size() < 1 )
diff --git a/kicad/cli/command_pcb_export_drill.cpp b/kicad/cli/command_pcb_export_drill.cpp
index 218eb3a1cf..69a999d7b2 100644
--- a/kicad/cli/command_pcb_export_drill.cpp
+++ b/kicad/cli/command_pcb_export_drill.cpp
@@ -23,6 +23,7 @@
 #include "jobs/job_export_pcb_drill.h"
 #include <kiface_base.h>
 #include <layer_ids.h>
+#include <string_utils.h>
 #include <wx/crt.h>
 
 #include <macros.h>
@@ -118,7 +119,7 @@ int CLI::PCB_EXPORT_DRILL_COMMAND::doPerform( KIWAY& aKiway )
         }
     }
 
-    wxString format = FROM_UTF8( m_argParser.get<std::string>( ARG_FORMAT ).c_str() );
+    wxString format = From_UTF8( m_argParser.get<std::string>( ARG_FORMAT ).c_str() );
     if( format == "excellon" )
     {
         drillJob->m_format = JOB_EXPORT_PCB_DRILL::DRILL_FORMAT::EXCELLON;
@@ -133,7 +134,7 @@ int CLI::PCB_EXPORT_DRILL_COMMAND::doPerform( KIWAY& aKiway )
         return EXIT_CODES::ERR_ARGS;
     }
 
-    wxString units = FROM_UTF8( m_argParser.get<std::string>( ARG_EXCELLON_UNITS ).c_str() );
+    wxString units = From_UTF8( m_argParser.get<std::string>( ARG_EXCELLON_UNITS ).c_str() );
 
     if( units == wxS( "mm" ) )
     {
@@ -149,7 +150,7 @@ int CLI::PCB_EXPORT_DRILL_COMMAND::doPerform( KIWAY& aKiway )
         return EXIT_CODES::ERR_ARGS;
     }
 
-    wxString zeroFormat = FROM_UTF8( m_argParser.get<std::string>( ARG_EXCELLON_ZEROS_FORMAT ).c_str() );
+    wxString zeroFormat = From_UTF8( m_argParser.get<std::string>( ARG_EXCELLON_ZEROS_FORMAT ).c_str() );
 
     if( zeroFormat == wxS( "decimal" ) )
     {
@@ -174,7 +175,7 @@ int CLI::PCB_EXPORT_DRILL_COMMAND::doPerform( KIWAY& aKiway )
     }
 
     wxString drillFormat =
-            FROM_UTF8( m_argParser.get<std::string>( ARG_EXCELLON_OVAL_FORMAT ).c_str() );
+            From_UTF8( m_argParser.get<std::string>( ARG_EXCELLON_OVAL_FORMAT ).c_str() );
     if( drillFormat == wxS( "route" ) )
     {
         drillJob->m_excellonOvalDrillRoute = true;
@@ -189,7 +190,7 @@ int CLI::PCB_EXPORT_DRILL_COMMAND::doPerform( KIWAY& aKiway )
         return EXIT_CODES::ERR_ARGS;
     }
 
-    wxString mapFormat = FROM_UTF8( m_argParser.get<std::string>( ARG_MAP_FORMAT ).c_str() );
+    wxString mapFormat = From_UTF8( m_argParser.get<std::string>( ARG_MAP_FORMAT ).c_str() );
 
     if( mapFormat == wxS( "pdf" ) )
     {
@@ -217,7 +218,7 @@ int CLI::PCB_EXPORT_DRILL_COMMAND::doPerform( KIWAY& aKiway )
         return EXIT_CODES::ERR_ARGS;
     }
 
-    wxString origin = FROM_UTF8( m_argParser.get<std::string>( ARG_DRILL_ORIGIN ).c_str() );
+    wxString origin = From_UTF8( m_argParser.get<std::string>( ARG_DRILL_ORIGIN ).c_str() );
 
     if( origin == wxS( "absolute" ) )
     {
diff --git a/kicad/cli/command_pcb_export_dxf.cpp b/kicad/cli/command_pcb_export_dxf.cpp
index f26fa4e643..b438ef7fcc 100644
--- a/kicad/cli/command_pcb_export_dxf.cpp
+++ b/kicad/cli/command_pcb_export_dxf.cpp
@@ -23,6 +23,7 @@
 #include "jobs/job_export_pcb_dxf.h"
 #include <kiface_base.h>
 #include <layer_ids.h>
+#include <string_utils.h>
 #include <wx/crt.h>
 
 #include <macros.h>
@@ -92,7 +93,7 @@ int CLI::PCB_EXPORT_DXF_COMMAND::doPerform( KIWAY& aKiway )
     dxfJob->m_plotGraphicItemsUsingContours = m_argParser.get<bool>( ARG_USE_CONTOURS );
     dxfJob->m_plotBorderTitleBlocks = m_argParser.get<bool>( ARG_INCLUDE_BORDER_TITLE );
 
-    wxString units = FROM_UTF8( m_argParser.get<std::string>( ARG_OUTPUT_UNITS ).c_str() );
+    wxString units = From_UTF8( m_argParser.get<std::string>( ARG_OUTPUT_UNITS ).c_str() );
 
     if( units == wxS( "mm" ) )
     {
diff --git a/kicad/cli/command_pcb_export_gerbers.cpp b/kicad/cli/command_pcb_export_gerbers.cpp
index d24170f63c..488932884f 100644
--- a/kicad/cli/command_pcb_export_gerbers.cpp
+++ b/kicad/cli/command_pcb_export_gerbers.cpp
@@ -23,6 +23,7 @@
 #include "jobs/job_export_pcb_gerbers.h"
 #include <kiface_base.h>
 #include <layer_ids.h>
+#include <string_utils.h>
 #include <wx/crt.h>
 
 #include <macros.h>
@@ -72,7 +73,7 @@ int CLI::PCB_EXPORT_GERBERS_COMMAND::doPerform( KIWAY& aKiway )
     if( exitCode != EXIT_CODES::OK )
         return exitCode;
 
-    wxString layers = FROM_UTF8( m_argParser.get<std::string>( ARG_COMMON_LAYERS ).c_str() );
+    wxString layers = From_UTF8( m_argParser.get<std::string>( ARG_COMMON_LAYERS ).c_str() );
     gerberJob->m_layersIncludeOnAll =
             convertLayerStringList( layers, gerberJob->m_layersIncludeOnAllSet );
     gerberJob->m_useBoardPlotParams = m_argParser.get<bool>( ARG_USE_BOARD_PLOT_PARAMS );
diff --git a/kicad/cli/command_pcb_export_pdf.cpp b/kicad/cli/command_pcb_export_pdf.cpp
index 12594e23d4..e395f5cff0 100644
--- a/kicad/cli/command_pcb_export_pdf.cpp
+++ b/kicad/cli/command_pcb_export_pdf.cpp
@@ -23,6 +23,7 @@
 #include "jobs/job_export_pcb_pdf.h"
 #include <kiface_base.h>
 #include <layer_ids.h>
+#include <string_utils.h>
 #include <wx/crt.h>
 
 #include <macros.h>
@@ -111,7 +112,7 @@ int CLI::PCB_EXPORT_PDF_COMMAND::doPerform( KIWAY& aKiway )
 
     pdfJob->m_mirror = m_argParser.get<bool>( ARG_MIRROR );
     pdfJob->m_blackAndWhite = m_argParser.get<bool>( ARG_BLACKANDWHITE );
-    pdfJob->m_colorTheme = FROM_UTF8( m_argParser.get<std::string>( ARG_THEME ).c_str() );
+    pdfJob->m_colorTheme = From_UTF8( m_argParser.get<std::string>( ARG_THEME ).c_str() );
     pdfJob->m_negative = m_argParser.get<bool>( ARG_NEGATIVE );
 
     pdfJob->m_drillShapeOption = m_argParser.get<int>( ARG_DRILL_SHAPE_OPTION );
diff --git a/kicad/cli/command_pcb_export_pos.cpp b/kicad/cli/command_pcb_export_pos.cpp
index b4325a3b1a..6ca8d90aa3 100644
--- a/kicad/cli/command_pcb_export_pos.cpp
+++ b/kicad/cli/command_pcb_export_pos.cpp
@@ -23,6 +23,7 @@
 #include "jobs/job_export_pcb_pos.h"
 #include <kiface_base.h>
 #include <layer_ids.h>
+#include <string_utils.h>
 #include <wx/crt.h>
 
 #include <macros.h>
@@ -119,7 +120,7 @@ int CLI::PCB_EXPORT_POS_COMMAND::doPerform( KIWAY& aKiway )
     aPosJob->m_excludeDNP = m_argParser.get<bool>( ARG_EXCLUDE_DNP );
     aPosJob->m_gerberBoardEdge = m_argParser.get<bool>( ARG_GERBER_BOARD_EDGE );
 
-    wxString format = FROM_UTF8( m_argParser.get<std::string>( ARG_FORMAT ).c_str() );
+    wxString format = From_UTF8( m_argParser.get<std::string>( ARG_FORMAT ).c_str() );
     if( format == wxS( "ascii" ) )
     {
         aPosJob->m_format = JOB_EXPORT_PCB_POS::FORMAT::ASCII;
@@ -138,7 +139,7 @@ int CLI::PCB_EXPORT_POS_COMMAND::doPerform( KIWAY& aKiway )
         return EXIT_CODES::ERR_ARGS;
     }
 
-    wxString units = FROM_UTF8( m_argParser.get<std::string>( ARG_UNITS ).c_str() );
+    wxString units = From_UTF8( m_argParser.get<std::string>( ARG_UNITS ).c_str() );
 
     if( units == wxS( "mm" ) )
     {
@@ -154,7 +155,7 @@ int CLI::PCB_EXPORT_POS_COMMAND::doPerform( KIWAY& aKiway )
         return EXIT_CODES::ERR_ARGS;
     }
 
-    wxString side = FROM_UTF8( m_argParser.get<std::string>( ARG_SIDE ).c_str() );
+    wxString side = From_UTF8( m_argParser.get<std::string>( ARG_SIDE ).c_str() );
 
     if( side == wxS( "both" ) )
     {
diff --git a/kicad/cli/command_pcb_export_svg.cpp b/kicad/cli/command_pcb_export_svg.cpp
index cb5f947217..3f5a9f58bd 100644
--- a/kicad/cli/command_pcb_export_svg.cpp
+++ b/kicad/cli/command_pcb_export_svg.cpp
@@ -25,6 +25,7 @@
 #include "jobs/job_export_pcb_svg.h"
 #include <kiface_base.h>
 #include <layer_ids.h>
+#include <string_utils.h>
 #include <regex>
 #include <wx/crt.h>
 
@@ -102,7 +103,7 @@ int CLI::PCB_EXPORT_SVG_COMMAND::doPerform( KIWAY& aKiway )
 
     svgJob->m_filename = m_argInput;
     svgJob->m_outputFile = m_argOutput;
-    svgJob->m_colorTheme = FROM_UTF8( m_argParser.get<std::string>( ARG_THEME ).c_str() );
+    svgJob->m_colorTheme = From_UTF8( m_argParser.get<std::string>( ARG_THEME ).c_str() );
     svgJob->m_plotDrawingSheet = !m_argParser.get<bool>( ARG_EXCLUDE_DRAWING_SHEET );
     svgJob->SetVarOverrides( m_argDefineVars );
 
diff --git a/kicad/cli/command_sch_erc.cpp b/kicad/cli/command_sch_erc.cpp
index 8b380cbb32..320bb1f726 100644
--- a/kicad/cli/command_sch_erc.cpp
+++ b/kicad/cli/command_sch_erc.cpp
@@ -23,6 +23,7 @@
 #include "jobs/job_sch_erc.h"
 #include <kiface_base.h>
 #include <layer_ids.h>
+#include <string_utils.h>
 #include <wx/crt.h>
 
 #include <macros.h>
@@ -107,7 +108,7 @@ int CLI::SCH_ERC_COMMAND::doPerform( KIWAY& aKiway )
     {
         ercJob->m_severity |= RPT_SEVERITY_EXCLUSION;
     }
-    wxString units = FROM_UTF8( m_argParser.get<std::string>( ARG_UNITS ).c_str() );
+    wxString units = From_UTF8( m_argParser.get<std::string>( ARG_UNITS ).c_str() );
 
     if( units == wxS( "mm" ) )
     {
@@ -127,7 +128,7 @@ int CLI::SCH_ERC_COMMAND::doPerform( KIWAY& aKiway )
         return EXIT_CODES::ERR_ARGS;
     }
 
-    wxString format = FROM_UTF8( m_argParser.get<std::string>( ARG_FORMAT ).c_str() );
+    wxString format = From_UTF8( m_argParser.get<std::string>( ARG_FORMAT ).c_str() );
     if( format == "report" )
     {
         ercJob->m_format = JOB_SCH_ERC::OUTPUT_FORMAT::REPORT;
diff --git a/kicad/cli/command_sch_export_bom.cpp b/kicad/cli/command_sch_export_bom.cpp
index 5325abc9f5..1dd3c16f99 100644
--- a/kicad/cli/command_sch_export_bom.cpp
+++ b/kicad/cli/command_sch_export_bom.cpp
@@ -23,6 +23,7 @@
 #include "jobs/job_export_sch_bom.h"
 #include <kiface_base.h>
 #include <layer_ids.h>
+#include <string_utils.h>
 #include <wx/crt.h>
 #include <schematic_settings.h>
 
@@ -128,25 +129,25 @@ int CLI::SCH_EXPORT_BOM_COMMAND::doPerform( KIWAY& aKiway )
 
     // Format options
     bomJob->m_fieldDelimiter =
-            FROM_UTF8( m_argParser.get<std::string>( ARG_FIELD_DELIMITER ).c_str() );
+            From_UTF8( m_argParser.get<std::string>( ARG_FIELD_DELIMITER ).c_str() );
     bomJob->m_stringDelimiter =
-            FROM_UTF8( m_argParser.get<std::string>( ARG_STRING_DELIMITER ).c_str() );
-    bomJob->m_refDelimiter = FROM_UTF8( m_argParser.get<std::string>( ARG_REF_DELIMITER ).c_str() );
+            From_UTF8( m_argParser.get<std::string>( ARG_STRING_DELIMITER ).c_str() );
+    bomJob->m_refDelimiter = From_UTF8( m_argParser.get<std::string>( ARG_REF_DELIMITER ).c_str() );
     bomJob->m_refRangeDelimiter =
-            FROM_UTF8( m_argParser.get<std::string>( ARG_REF_RANGE_DELIMITER ).c_str() );
+            From_UTF8( m_argParser.get<std::string>( ARG_REF_RANGE_DELIMITER ).c_str() );
     bomJob->m_keepTabs = m_argParser.get<bool>( ARG_KEEP_TABS );
     bomJob->m_keepLineBreaks = m_argParser.get<bool>( ARG_KEEP_LINE_BREAKS );
 
     // Output fields options
     bomJob->m_fieldsOrdered =
-            convertStringList( FROM_UTF8( m_argParser.get<std::string>( ARG_FIELDS ).c_str() ) );
+            convertStringList( From_UTF8( m_argParser.get<std::string>( ARG_FIELDS ).c_str() ) );
     bomJob->m_fieldsLabels =
-            convertStringList( FROM_UTF8( m_argParser.get<std::string>( ARG_LABELS ).c_str() ) );
+            convertStringList( From_UTF8( m_argParser.get<std::string>( ARG_LABELS ).c_str() ) );
     bomJob->m_fieldsGroupBy =
-            convertStringList( FROM_UTF8( m_argParser.get<std::string>( ARG_GROUP_BY ).c_str() ) );
-    bomJob->m_sortField = FROM_UTF8( m_argParser.get<std::string>( ARG_SORT_FIELD ).c_str() );
+            convertStringList( From_UTF8( m_argParser.get<std::string>( ARG_GROUP_BY ).c_str() ) );
+    bomJob->m_sortField = From_UTF8( m_argParser.get<std::string>( ARG_SORT_FIELD ).c_str() );
     bomJob->m_sortAsc = m_argParser.get<bool>( ARG_SORT_ASC );
-    bomJob->m_filterString = FROM_UTF8( m_argParser.get<std::string>( ARG_FILTER ).c_str() );
+    bomJob->m_filterString = From_UTF8( m_argParser.get<std::string>( ARG_FILTER ).c_str() );
     bomJob->m_excludeDNP = m_argParser.get<bool>( ARG_EXCLUDE_DNP );
 
     if( !wxFile::Exists( bomJob->m_filename ) )
diff --git a/kicad/cli/command_sch_export_netlist.cpp b/kicad/cli/command_sch_export_netlist.cpp
index f2bcf1bba7..fe03540ab2 100644
--- a/kicad/cli/command_sch_export_netlist.cpp
+++ b/kicad/cli/command_sch_export_netlist.cpp
@@ -23,6 +23,7 @@
 #include "jobs/job_export_sch_netlist.h"
 #include <kiface_base.h>
 #include <layer_ids.h>
+#include <string_utils.h>
 #include <wx/crt.h>
 
 #include <macros.h>
@@ -56,7 +57,7 @@ int CLI::SCH_EXPORT_NETLIST_COMMAND::doPerform( KIWAY& aKiway )
         return EXIT_CODES::ERR_INVALID_INPUT_FILE;
     }
 
-    wxString format = FROM_UTF8( m_argParser.get<std::string>( ARG_FORMAT ).c_str() );
+    wxString format = From_UTF8( m_argParser.get<std::string>( ARG_FORMAT ).c_str() );
     if( format == "kicadsexpr" )
     {
         netJob->format = JOB_EXPORT_SCH_NETLIST::FORMAT::KICADSEXPR;
diff --git a/kicad/cli/command_sch_export_plot.cpp b/kicad/cli/command_sch_export_plot.cpp
index 89a0f643ac..ba266a20bb 100644
--- a/kicad/cli/command_sch_export_plot.cpp
+++ b/kicad/cli/command_sch_export_plot.cpp
@@ -107,7 +107,7 @@ int CLI::SCH_EXPORT_PLOT_COMMAND::doPerform( KIWAY& aKiway )
     }
 
     std::vector<wxString> pages;
-    wxString              pagesStr = FROM_UTF8( m_argParser.get<std::string>( ARG_PAGES ).c_str() );
+    wxString              pagesStr = From_UTF8( m_argParser.get<std::string>( ARG_PAGES ).c_str() );
     wxStringTokenizer     tokenizer( pagesStr, "," );
     while( tokenizer.HasMoreTokens() )
     {
@@ -123,7 +123,7 @@ int CLI::SCH_EXPORT_PLOT_COMMAND::doPerform( KIWAY& aKiway )
     settings.m_blackAndWhite = m_argParser.get<bool>( ARG_BLACKANDWHITE );
     settings.m_pageSizeSelect = PAGE_SIZE_AUTO;
     settings.m_useBackgroundColor = !m_argParser.get<bool>( ARG_NO_BACKGROUND_COLOR );
-    settings.m_theme = FROM_UTF8( m_argParser.get<std::string>( ARG_THEME ).c_str() );
+    settings.m_theme = From_UTF8( m_argParser.get<std::string>( ARG_THEME ).c_str() );
     if( m_outputArgExpectsDir )
         settings.m_outputDirectory = m_argOutput;
     else
diff --git a/kicad/cli/command_sym_export_svg.cpp b/kicad/cli/command_sym_export_svg.cpp
index 482dee3eb3..525f0d5572 100644
--- a/kicad/cli/command_sym_export_svg.cpp
+++ b/kicad/cli/command_sym_export_svg.cpp
@@ -23,6 +23,7 @@
 #include "jobs/job_sym_export_svg.h"
 #include <kiface_base.h>
 #include <layer_ids.h>
+#include <string_utils.h>
 #include <wx/crt.h>
 
 #include <macros.h>
@@ -73,7 +74,7 @@ int CLI::SYM_EXPORT_SVG_COMMAND::doPerform( KIWAY& aKiway )
     svgJob->m_libraryPath = m_argInput;
     svgJob->m_outputDirectory = m_argOutput;
     svgJob->m_blackAndWhite = m_argParser.get<bool>( ARG_BLACKANDWHITE );
-    svgJob->m_symbol = FROM_UTF8( m_argParser.get<std::string>( ARG_SYMBOL ).c_str() );
+    svgJob->m_symbol = From_UTF8( m_argParser.get<std::string>( ARG_SYMBOL ).c_str() );
     svgJob->m_includeHiddenFields = m_argParser.get<bool>( ARG_INC_HIDDEN_FIELDS );
     svgJob->m_includeHiddenPins = m_argParser.get<bool>( ARG_INC_HIDDEN_PINS );
 
@@ -83,7 +84,7 @@ int CLI::SYM_EXPORT_SVG_COMMAND::doPerform( KIWAY& aKiway )
         return EXIT_CODES::ERR_INVALID_INPUT_FILE;
     }
 
-    svgJob->m_colorTheme = FROM_UTF8( m_argParser.get<std::string>( ARG_THEME ).c_str() );
+    svgJob->m_colorTheme = From_UTF8( m_argParser.get<std::string>( ARG_THEME ).c_str() );
 
     int exitCode = aKiway.ProcessJob( KIWAY::FACE_SCH, svgJob.get() );
 
diff --git a/kicad/cli/command_version.cpp b/kicad/cli/command_version.cpp
index 0a177048ad..afd52127ff 100644
--- a/kicad/cli/command_version.cpp
+++ b/kicad/cli/command_version.cpp
@@ -23,7 +23,7 @@
 #include <wx/crt.h>
 #include <build_version.h>
 
-#include <macros.h>
+#include <string_utils.h>
 #include <build_version.h>
 
 #define ARG_FORMAT "--format"
@@ -50,7 +50,7 @@ int CLI::VERSION_COMMAND::doPerform( KIWAY& aKiway )
         return EXIT_CODES::OK;
     }
 
-    wxString format = FROM_UTF8( m_argParser.get<std::string>( ARG_FORMAT ).c_str() );
+    wxString format = From_UTF8( m_argParser.get<std::string>( ARG_FORMAT ).c_str() );
     if( format == wxS( "plain" ) )
     {
         wxPrintf( "%s\n", GetMajorMinorPatchVersion() );
diff --git a/kicad/import_proj.cpp b/kicad/import_proj.cpp
index 3510ef437f..e173d8586b 100644
--- a/kicad/import_proj.cpp
+++ b/kicad/import_proj.cpp
@@ -24,6 +24,7 @@
 #include <kiway_player.h>
 #include <wildcards_and_files_ext.h>
 #include <macros.h>
+#include <string_utils.h>
 #include <richio.h>
 
 #include <wx/msgdlg.h>
diff --git a/kicad/kicad_cli.cpp b/kicad/kicad_cli.cpp
index 7e73326c7f..0d7d257dfc 100644
--- a/kicad/kicad_cli.cpp
+++ b/kicad/kicad_cli.cpp
@@ -29,7 +29,7 @@
 #include <wx/wxcrtvararg.h>     //for wxPrintf
 
 #include <kiway.h>
-#include <macros.h>
+#include <string_utils.h>
 #include <paths.h>
 #include <settings/settings_manager.h>
 #include <settings/kicad_settings.h>
@@ -276,7 +276,7 @@ static void printHelp( argparse::ArgumentParser& argParser )
 {
     std::stringstream ss;
     ss << argParser;
-    wxPrintf( FROM_UTF8( ss.str().c_str() ) );
+    wxPrintf( From_UTF8( ss.str().c_str() ) );
 }
 
 
@@ -368,7 +368,7 @@ int PGM_KICAD::OnPgmRun()
     {
         std::stringstream ss;
         ss << argParser;
-        wxPrintf( FROM_UTF8( ss.str().c_str() ) );
+        wxPrintf( From_UTF8( ss.str().c_str() ) );
 
         return 0;
     }
diff --git a/kicad/project_tree_pane.cpp b/kicad/project_tree_pane.cpp
index da92efd213..94f6ab24c2 100644
--- a/kicad/project_tree_pane.cpp
+++ b/kicad/project_tree_pane.cpp
@@ -41,6 +41,7 @@
 #include <kiplatform/environment.h>
 #include <core/kicad_algo.h>
 #include <paths.h>
+#include <string_utils.h>
 #include <launch_ext.h>
 #include <wx/dcclient.h>
 #include <wx/settings.h>
diff --git a/libs/sexpr/sexpr_parser.cpp b/libs/sexpr/sexpr_parser.cpp
index b454656d70..a15b2ce5c9 100644
--- a/libs/sexpr/sexpr_parser.cpp
+++ b/libs/sexpr/sexpr_parser.cpp
@@ -28,7 +28,7 @@
 #include <wx/file.h>
 #include <wx/ffile.h>
 
-#include <macros.h>
+#include <string_utils.h>
 
 namespace SEXPR
 {
@@ -62,7 +62,7 @@ namespace SEXPR
 
         // the filename is not always a UTF7 string, so do not use ifstream
         // that do not work with unicode chars.
-        wxString fname( FROM_UTF8( aFileName.c_str() ) );
+        wxString fname( From_UTF8( aFileName.c_str() ) );
         wxFFile file( fname, "rb" );
         size_t length = file.Length();
 
diff --git a/pagelayout_editor/tools/pl_edit_tool.cpp b/pagelayout_editor/tools/pl_edit_tool.cpp
index 3238a2a15b..bddd207f9f 100644
--- a/pagelayout_editor/tools/pl_edit_tool.cpp
+++ b/pagelayout_editor/tools/pl_edit_tool.cpp
@@ -34,6 +34,7 @@
 #include <confirm.h>
 #include <eda_item.h>
 #include <macros.h>
+#include <string_utils.h>
 #include <view/view.h>
 #include <math/util.h>      // for KiROUND
 
diff --git a/pcb_calculator/datafile_read_write.cpp b/pcb_calculator/datafile_read_write.cpp
index d8e972b51e..984215c519 100644
--- a/pcb_calculator/datafile_read_write.cpp
+++ b/pcb_calculator/datafile_read_write.cpp
@@ -232,7 +232,7 @@ void PCB_CALCULATOR_DATAFILE_PARSER::ParseRegulatorDescr( PCB_CALCULATOR_DATAFIL
 
             // Read name
             token = NextTok();
-            name = FROM_UTF8( CurText() );
+            name = From_UTF8( CurText() );
 
             while( ( token = NextTok() ) != T_RIGHT )
             {
diff --git a/pcbnew/build_BOM_from_board.cpp b/pcbnew/build_BOM_from_board.cpp
index b9ec4c39da..cd5605a7bf 100644
--- a/pcbnew/build_BOM_from_board.cpp
+++ b/pcbnew/build_BOM_from_board.cpp
@@ -164,7 +164,7 @@ void PCB_EDIT_FRAME::RecreateBOMFileFromBoard( wxCommandEvent& aEvent )
 
         msg << curEntry->m_Id << wxT( ";\"" );
         msg << curEntry->m_Ref << wxT( "\";\"" );
-        msg << FROM_UTF8( curEntry->m_FPID.GetLibItemName().c_str() ) << wxT( "\";" );
+        msg << From_UTF8( curEntry->m_FPID.GetLibItemName().c_str() ) << wxT( "\";" );
         msg << curEntry->m_Count << wxT( ";\"" );
         msg << curEntry->m_Val << wxT( "\";;;\n" );
         fprintf( fp_bom, "%s", TO_UTF8( msg ) );
diff --git a/pcbnew/cross-probing.cpp b/pcbnew/cross-probing.cpp
index 7ff6509522..c85fd8ac34 100644
--- a/pcbnew/cross-probing.cpp
+++ b/pcbnew/cross-probing.cpp
@@ -131,7 +131,7 @@ void PCB_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
         if( !crossProbingSettings.auto_highlight )
             return;
 
-        wxString net_name = FROM_UTF8( text );
+        wxString net_name = From_UTF8( text );
 
         NETINFO_ITEM* netinfo = pcb->FindNet( net_name );
 
@@ -151,7 +151,7 @@ void PCB_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
         if( !crossProbingSettings.auto_highlight )
             return;
 
-        wxStringTokenizer netsTok = wxStringTokenizer( FROM_UTF8( text ), wxT( "," ) );
+        wxStringTokenizer netsTok = wxStringTokenizer( From_UTF8( text ), wxT( "," ) );
         bool first = true;
 
         while( netsTok.HasMoreTokens() )
diff --git a/pcbnew/dialogs/dialog_exchange_footprints.cpp b/pcbnew/dialogs/dialog_exchange_footprints.cpp
index 906890685d..b524981c27 100644
--- a/pcbnew/dialogs/dialog_exchange_footprints.cpp
+++ b/pcbnew/dialogs/dialog_exchange_footprints.cpp
@@ -101,7 +101,7 @@ DIALOG_EXCHANGE_FOOTPRINTS::DIALOG_EXCHANGE_FOOTPRINTS( PCB_EDIT_FRAME* aParent,
 
     if( m_currentFootprint )
     {
-        m_newID->AppendText( FROM_UTF8( m_currentFootprint->GetFPID().Format().c_str() ) );
+        m_newID->AppendText( From_UTF8( m_currentFootprint->GetFPID().Format().c_str() ) );
     }
     else
         m_upperSizer->FindItem( m_matchSelected )->Show( false );
@@ -114,7 +114,7 @@ DIALOG_EXCHANGE_FOOTPRINTS::DIALOG_EXCHANGE_FOOTPRINTS( PCB_EDIT_FRAME* aParent,
         m_specifiedValue->ChangeValue( m_currentFootprint->GetValue() );
 
     if( m_currentFootprint )
-        m_specifiedID->ChangeValue( FROM_UTF8( m_currentFootprint->GetFPID().Format().c_str() ) );
+        m_specifiedID->ChangeValue( From_UTF8( m_currentFootprint->GetFPID().Format().c_str() ) );
 
     m_specifiedIDBrowseButton->SetBitmap( KiBitmap( BITMAPS::small_library ) );
 
diff --git a/pcbnew/exporters/export_idf.cpp b/pcbnew/exporters/export_idf.cpp
index 330c7f4a69..a62c59287c 100644
--- a/pcbnew/exporters/export_idf.cpp
+++ b/pcbnew/exporters/export_idf.cpp
@@ -649,7 +649,7 @@ bool PCB_EDIT_FRAME::Export_IDF3( BOARD* aPcb, const wxString& aFullFileName,
         if( !idfBoard.WriteFile( aFullFileName, idfUnit, false ) )
         {
             wxString msg;
-            msg << _( "IDF Export Failed:\n" ) << FROM_UTF8( idfBoard.GetError().c_str() );
+            msg << _( "IDF Export Failed:\n" ) << From_UTF8( idfBoard.GetError().c_str() );
             wxMessageBox( msg );
 
             ok = false;
@@ -666,7 +666,7 @@ bool PCB_EDIT_FRAME::Export_IDF3( BOARD* aPcb, const wxString& aFullFileName,
     catch( const std::exception& e )
     {
         wxString msg;
-        msg << _( "IDF Export Failed:\n" ) << FROM_UTF8( e.what() );
+        msg << _( "IDF Export Failed:\n" ) << From_UTF8( e.what() );
         wxMessageBox( msg );
         ok = false;
     }
diff --git a/pcbnew/exporters/exporter_vrml.cpp b/pcbnew/exporters/exporter_vrml.cpp
index 503f5bee78..7f98a3288c 100644
--- a/pcbnew/exporters/exporter_vrml.cpp
+++ b/pcbnew/exporters/exporter_vrml.cpp
@@ -1301,7 +1301,7 @@ bool EXPORTER_PCB_VRML::ExportVRML_File( PROJECT* aProject, wxString *aMessages,
     catch( const std::exception& e )
     {
         if( aMessages )
-            *aMessages << _( "VRML Export Failed:\n" ) << FROM_UTF8( e.what() );
+            *aMessages << _( "VRML Export Failed:\n" ) << From_UTF8( e.what() );
 
         success = false;
     }
diff --git a/pcbnew/exporters/gen_drill_report_files.cpp b/pcbnew/exporters/gen_drill_report_files.cpp
index 365da54eeb..ce907cd579 100644
--- a/pcbnew/exporters/gen_drill_report_files.cpp
+++ b/pcbnew/exporters/gen_drill_report_files.cpp
@@ -316,7 +316,7 @@ bool GENDRILL_WRITER_BASE::genDrillMapFile( const wxString& aFullFileName, PLOT_
         snprintf( line, sizeof(line), "%3.3fmm / %2.4f\" ", diameter_in_mm( tool.m_Diameter ),
                  diameter_in_inches( tool.m_Diameter ) );
 
-        msg = FROM_UTF8( line );
+        msg = From_UTF8( line );
 
         // Now list how many holes and ovals are associated with each drill.
         if( ( tool.m_TotalCount == 1 ) && ( tool.m_OvalCount == 0 ) )
@@ -331,7 +331,7 @@ bool GENDRILL_WRITER_BASE::genDrillMapFile( const wxString& aFullFileName, PLOT_
             snprintf( line, sizeof(line), "(%d holes + %d slots)", tool.m_TotalCount - tool.m_OvalCount,
                      tool.m_OvalCount );
 
-        msg += FROM_UTF8( line );
+        msg += From_UTF8( line );
 
         if( tool.m_Hole_NotPlated )
             msg += wxT( " (not plated)" );
diff --git a/pcbnew/exporters/gerber_placefile_writer.cpp b/pcbnew/exporters/gerber_placefile_writer.cpp
index 69764b627c..788a6c4519 100644
--- a/pcbnew/exporters/gerber_placefile_writer.cpp
+++ b/pcbnew/exporters/gerber_placefile_writer.cpp
@@ -162,11 +162,11 @@ int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, PCB_LAYER
                                                             allowUtf8, true );
 
         // Add component footprint info:
-        wxString fp_info = FROM_UTF8( footprint->GetFPID().GetLibItemName().c_str() );
+        wxString fp_info = From_UTF8( footprint->GetFPID().GetLibItemName().c_str() );
         pnpAttrib.m_Footprint = ConvertNotAllowedCharsInGerber( fp_info, allowUtf8, true );
 
         // Add footprint lib name:
-        fp_info = FROM_UTF8( footprint->GetFPID().GetLibNickname().c_str() );
+        fp_info = From_UTF8( footprint->GetFPID().GetLibNickname().c_str() );
         pnpAttrib.m_LibraryName = ConvertNotAllowedCharsInGerber( fp_info, allowUtf8, true );
 
         metadata.m_NetlistMetadata.SetExtraData( pnpAttrib.FormatCmpPnPMetadata() );
diff --git a/pcbnew/footprint_edit_frame.cpp b/pcbnew/footprint_edit_frame.cpp
index bd5b1ec486..b94f08b381 100644
--- a/pcbnew/footprint_edit_frame.cpp
+++ b/pcbnew/footprint_edit_frame.cpp
@@ -936,7 +936,7 @@ void FOOTPRINT_EDIT_FRAME::UpdateTitle()
         if( IsContentModified() )
             title = wxT( "*" );
 
-        title += FROM_UTF8( footprint->GetFPID().Format().c_str() );
+        title += From_UTF8( footprint->GetFPID().Format().c_str() );
 
         if( !writable )
             title += wxS( " " ) + _( "[Read Only]" );
@@ -947,7 +947,7 @@ void FOOTPRINT_EDIT_FRAME::UpdateTitle()
         if( IsContentModified() )
             title = wxT( "*" );
 
-        title += FROM_UTF8( footprint->GetFPID().GetLibItemName().c_str() );
+        title += From_UTF8( footprint->GetFPID().GetLibItemName().c_str() );
         title += wxS( " " ) + _( "[Unsaved]" );
     }
     else
diff --git a/pcbnew/netlist_reader/kicad_netlist_reader.cpp b/pcbnew/netlist_reader/kicad_netlist_reader.cpp
index 25f505edbb..8f7f04f5c7 100644
--- a/pcbnew/netlist_reader/kicad_netlist_reader.cpp
+++ b/pcbnew/netlist_reader/kicad_netlist_reader.cpp
@@ -23,7 +23,7 @@
  */
 
 #include <netlist_lexer.h>  // netlist_lexer is common to Eeschema and Pcbnew
-#include <macros.h>
+#include <string_utils.h>
 #include <nlohmann/json.hpp>
 
 #include "pcb_netlist.h"
@@ -203,13 +203,13 @@ void KICAD_NETLIST_PARSER::parseNet()
         {
         case T_code:
             NeedSYMBOLorNUMBER();
-            code = FROM_UTF8( CurText() );
+            code = From_UTF8( CurText() );
             NeedRIGHT();
             break;
 
         case T_name:
             NeedSYMBOLorNUMBER();
-            name = FROM_UTF8( CurText() );
+            name = From_UTF8( CurText() );
             NeedRIGHT();
             break;
 
@@ -229,25 +229,25 @@ void KICAD_NETLIST_PARSER::parseNet()
                 {
                 case T_ref:
                     NeedSYMBOLorNUMBER();
-                    reference = FROM_UTF8( CurText() );
+                    reference = From_UTF8( CurText() );
                     NeedRIGHT();
                     break;
 
                 case T_pin:
                     NeedSYMBOLorNUMBER();
-                    pin_number = FROM_UTF8( CurText() );
+                    pin_number = From_UTF8( CurText() );
                     NeedRIGHT();
                     break;
 
                 case T_pinfunction:
                     NeedSYMBOLorNUMBER();
-                    pin_function = FROM_UTF8( CurText() );
+                    pin_function = From_UTF8( CurText() );
                     NeedRIGHT();
                     break;
 
                 case T_pintype:
                     NeedSYMBOLorNUMBER();
-                    pin_type = FROM_UTF8( CurText() );
+                    pin_type = From_UTF8( CurText() );
                     NeedRIGHT();
                     break;
 
@@ -323,13 +323,13 @@ void KICAD_NETLIST_PARSER::parseComponent()
         {
         case T_ref:
             NeedSYMBOLorNUMBER();
-            ref = FROM_UTF8( CurText() );
+            ref = From_UTF8( CurText() );
             NeedRIGHT();
             break;
 
         case T_value:
             NeedSYMBOLorNUMBER();
-            value = FROM_UTF8( CurText() );
+            value = From_UTF8( CurText() );
             NeedRIGHT();
             break;
 
@@ -349,13 +349,13 @@ void KICAD_NETLIST_PARSER::parseComponent()
                 if( token == T_lib )
                 {
                     NeedSYMBOLorNUMBER();
-                    library = FROM_UTF8( CurText() );
+                    library = From_UTF8( CurText() );
                     NeedRIGHT();
                 }
                 else if( token == T_part )
                 {
                     NeedSYMBOLorNUMBER();
-                    name = FROM_UTF8( CurText() );
+                    name = From_UTF8( CurText() );
                     NeedRIGHT();
                 }
                 else if( token == T_description )
@@ -383,13 +383,13 @@ void KICAD_NETLIST_PARSER::parseComponent()
                 if( token == T_name )
                 {
                     NeedSYMBOLorNUMBER();
-                    propName = FROM_UTF8( CurText() );
+                    propName = From_UTF8( CurText() );
                     NeedRIGHT();
                 }
                 else if( token == T_value )
                 {
                     NeedSYMBOLorNUMBER();
-                    propValue = FROM_UTF8( CurText() );
+                    propValue = From_UTF8( CurText() );
                     NeedRIGHT();
                 }
                 else
@@ -424,7 +424,7 @@ void KICAD_NETLIST_PARSER::parseComponent()
                         if( token == T_name )
                         {
                             NeedSYMBOLorNUMBER();
-                            fieldName = FROM_UTF8( CurText() );
+                            fieldName = From_UTF8( CurText() );
                             NeedRIGHT();
                         }
                         else if( token == T_STRING )
@@ -451,7 +451,7 @@ void KICAD_NETLIST_PARSER::parseComponent()
             }
 
             NeedSYMBOLorNUMBER();
-            path = KIID_PATH( FROM_UTF8( CurText() ) );
+            path = KIID_PATH( From_UTF8( CurText() ) );
             NeedRIGHT();
             NeedRIGHT();
             break;
@@ -462,7 +462,7 @@ void KICAD_NETLIST_PARSER::parseComponent()
                 if( token == T_RIGHT )
                     break;
 
-                uuids.emplace_back( FROM_UTF8( CurText() ) );
+                uuids.emplace_back( From_UTF8( CurText() ) );
             }
 
             break;
@@ -531,13 +531,13 @@ void KICAD_NETLIST_PARSER::parseLibPartList()
         {
         case T_lib:
             NeedSYMBOLorNUMBER();
-            libName = FROM_UTF8( CurText() );
+            libName = From_UTF8( CurText() );
             NeedRIGHT();
             break;
 
         case T_part:
             NeedSYMBOLorNUMBER();
-            libPartName = FROM_UTF8( CurText() );
+            libPartName = From_UTF8( CurText() );
             NeedRIGHT();
             break;
 
@@ -552,7 +552,7 @@ void KICAD_NETLIST_PARSER::parseLibPartList()
                     Expecting( T_fp );
 
                 NeedSYMBOLorNUMBER();
-                footprintFilters.Add( FROM_UTF8( CurText() ) );
+                footprintFilters.Add( From_UTF8( CurText() ) );
                 NeedRIGHT();
             }
             break;
@@ -567,7 +567,7 @@ void KICAD_NETLIST_PARSER::parseLibPartList()
                     Expecting( T_alias );
 
                 NeedSYMBOLorNUMBER();
-                aliases.Add( FROM_UTF8( CurText() ) );
+                aliases.Add( From_UTF8( CurText() ) );
                 NeedRIGHT();
             }
             break;
diff --git a/pcbnew/netlist_reader/legacy_netlist_reader.cpp b/pcbnew/netlist_reader/legacy_netlist_reader.cpp
index e99c0fcb1b..854dfcecf7 100644
--- a/pcbnew/netlist_reader/legacy_netlist_reader.cpp
+++ b/pcbnew/netlist_reader/legacy_netlist_reader.cpp
@@ -116,7 +116,7 @@ COMPONENT* LEGACY_NETLIST_READER::loadComponent( char* aText )
                            m_lineReader->Length() );
     }
 
-    KIID_PATH path( FROM_UTF8( text ) );
+    KIID_PATH path( From_UTF8( text ) );
 
     // Read footprint name (second word)
     if( ( text = strtok( nullptr, " ()\t\n" ) ) == nullptr )
@@ -126,7 +126,7 @@ COMPONENT* LEGACY_NETLIST_READER::loadComponent( char* aText )
                            m_lineReader->Length() );
     }
 
-    footprintName = FROM_UTF8( text );
+    footprintName = From_UTF8( text );
 
     // The footprint name will have to be looked up in the *.cmp file.
     if( footprintName == wxT( "$noname" ) )
@@ -140,7 +140,7 @@ COMPONENT* LEGACY_NETLIST_READER::loadComponent( char* aText )
                            m_lineReader->Length() );
     }
 
-    reference = FROM_UTF8( text );
+    reference = From_UTF8( text );
 
     // Read schematic value (forth word)
     if( ( text = strtok( nullptr, " ()\t\n" ) ) == nullptr )
@@ -150,13 +150,13 @@ COMPONENT* LEGACY_NETLIST_READER::loadComponent( char* aText )
                            m_lineReader->Length() );
     }
 
-    value = FROM_UTF8( text );
+    value = From_UTF8( text );
 
     // Read component name (fifth word) {Lib=C}
     // This is an optional field (a comment), which does not always exists
     if( ( text = strtok( nullptr, " ()\t\n" ) ) != nullptr )
     {
-        name = FROM_UTF8( text ).AfterFirst( wxChar( '=' ) ).BeforeLast( wxChar( '}' ) );
+        name = From_UTF8( text ).AfterFirst( wxChar( '=' ) ).BeforeLast( wxChar( '}' ) );
     }
 
     LIB_ID fpid;
@@ -187,7 +187,7 @@ void LEGACY_NETLIST_READER::loadNet( char* aText, COMPONENT* aComponent )
                            m_lineReader->Length() );
     }
 
-    wxString pinName = FROM_UTF8( p );
+    wxString pinName = From_UTF8( p );
 
     if( ( p = strtok( nullptr, " ()\t\n" ) ) == nullptr )
     {
@@ -196,7 +196,7 @@ void LEGACY_NETLIST_READER::loadNet( char* aText, COMPONENT* aComponent )
                            m_lineReader->Length() );
     }
 
-    wxString netName = FROM_UTF8( p );
+    wxString netName = From_UTF8( p );
 
     if( (char) netName[0] == '?' )       // ? indicates no net connected to pin.
         netName = wxEmptyString;
@@ -229,7 +229,7 @@ void LEGACY_NETLIST_READER::loadFootprintFilters()
 
         if( strncasecmp( line, "$component", 10 ) == 0 ) // New component reference found
         {
-            cmpRef = FROM_UTF8( line + 11 );
+            cmpRef = From_UTF8( line + 11 );
             cmpRef.Trim( true );
             cmpRef.Trim( false );
 
@@ -248,7 +248,7 @@ void LEGACY_NETLIST_READER::loadFootprintFilters()
         else
         {
             // Add new filter to list
-            wxString fp = FROM_UTF8( line + 1 );
+            wxString fp = From_UTF8( line + 1 );
             fp.Trim( false );
             fp.Trim( true );
             filters.Add( fp );
diff --git a/pcbnew/netlist_reader/netlist_reader.cpp b/pcbnew/netlist_reader/netlist_reader.cpp
index 0be49834d7..97e5565280 100644
--- a/pcbnew/netlist_reader/netlist_reader.cpp
+++ b/pcbnew/netlist_reader/netlist_reader.cpp
@@ -64,7 +64,7 @@ NETLIST_READER::NETLIST_FILE_T NETLIST_READER::GuessNetlistFileType( LINE_READER
 
     while( aLineReader->ReadLine() )
     {
-        line = FROM_UTF8( aLineReader->Line() );
+        line = From_UTF8( aLineReader->Line() );
 
         if( reLegacy.Matches( line ) )
             return LEGACY;
@@ -126,7 +126,7 @@ bool CMP_READER::Load( NETLIST* aNetlist )
 
     while( m_lineReader->ReadLine() )
     {
-        buffer = FROM_UTF8( m_lineReader->Line() );
+        buffer = From_UTF8( m_lineReader->Line() );
 
         if( !buffer.StartsWith( wxT( "BeginCmp" ) ) )
             continue;
@@ -138,7 +138,7 @@ bool CMP_READER::Load( NETLIST* aNetlist )
 
         while( m_lineReader->ReadLine() )
         {
-            buffer = FROM_UTF8( m_lineReader->Line() );
+            buffer = From_UTF8( m_lineReader->Line() );
 
             if( buffer.StartsWith( wxT( "EndCmp" ) ) )
                 break;
diff --git a/pcbnew/pcb_plot_params.cpp b/pcbnew/pcb_plot_params.cpp
index af67b86d16..db467ea1c2 100644
--- a/pcbnew/pcb_plot_params.cpp
+++ b/pcbnew/pcb_plot_params.cpp
@@ -24,7 +24,7 @@
 #include <board_design_settings.h>
 #include <charconv>
 #include <layer_ids.h>
-#include <macros.h>
+#include <string_utils.h>
 #include <math/util.h> // for KiROUND
 #include <pcb_plot_params.h>
 #include <pcb_plot_params_parser.h>
@@ -644,7 +644,7 @@ void PCB_PLOT_PARAMS_PARSER::Parse( PCB_PLOT_PARAMS* aPcbPlotParams )
 
         case T_outputdirectory:
             NeedSYMBOLorNUMBER();   // a dir name can be like a number
-            aPcbPlotParams->m_outputDirectory = FROM_UTF8( CurText() );
+            aPcbPlotParams->m_outputDirectory = From_UTF8( CurText() );
             break;
 
         default:
diff --git a/pcbnew/plugins/geda/gpcb_plugin.cpp b/pcbnew/plugins/geda/gpcb_plugin.cpp
index 72bd130c90..76e250aba5 100644
--- a/pcbnew/plugins/geda/gpcb_plugin.cpp
+++ b/pcbnew/plugins/geda/gpcb_plugin.cpp
@@ -891,7 +891,7 @@ void GPCB_PLUGIN::FootprintEnumerate( wxArrayString& aFootprintNames, const wxSt
     // the library.
 
     for( const auto& footprint : m_cache->GetFootprints() )
-        aFootprintNames.Add( FROM_UTF8( footprint.first.c_str() ) );
+        aFootprintNames.Add( From_UTF8( footprint.first.c_str() ) );
 
     if( !errorMsg.IsEmpty() && !aBestEfforts )
         THROW_IO_ERROR( errorMsg );
diff --git a/pcbnew/plugins/kicad/pcb_parser.cpp b/pcbnew/plugins/kicad/pcb_parser.cpp
index cf693e7f21..676bf79242 100644
--- a/pcbnew/plugins/kicad/pcb_parser.cpp
+++ b/pcbnew/plugins/kicad/pcb_parser.cpp
@@ -589,7 +589,7 @@ void PCB_PARSER::parseRenderCache( EDA_TEXT* text )
     T token;
 
     NeedSYMBOLorNUMBER();
-    wxString  cacheText = FROM_UTF8( CurText() );
+    wxString  cacheText = From_UTF8( CurText() );
     EDA_ANGLE cacheAngle( parseDouble( "render cache angle" ), DEGREES_T );
 
     text->SetupRenderCache( cacheText, cacheAngle );
@@ -1430,13 +1430,13 @@ void PCB_PARSER::parseLayer( LAYER* aLayer )
         Expecting( "hide, user defined name, or )" );
     }
 
-    aLayer->m_name    = FROM_UTF8( name.c_str() );
+    aLayer->m_name    = From_UTF8( name.c_str() );
     aLayer->m_type    = LAYER::ParseType( type.c_str() );
     aLayer->m_number  = layer_num;
     aLayer->m_visible = isVisible;
 
     if( !userName.empty() )
-        aLayer->m_userName = FROM_UTF8( userName.c_str() );
+        aLayer->m_userName = From_UTF8( userName.c_str() );
 
     // The canonical name will get reset back to the default for copper layer on the next
     // save.  The user defined name is now a separate optional layer token from the canonical
diff --git a/pcbnew/plugins/legacy/legacy_plugin.cpp b/pcbnew/plugins/legacy/legacy_plugin.cpp
index 38c1117e5f..3d9aa4b745 100644
--- a/pcbnew/plugins/legacy/legacy_plugin.cpp
+++ b/pcbnew/plugins/legacy/legacy_plugin.cpp
@@ -786,7 +786,7 @@ void LEGACY_PLUGIN::loadSHEET()
 
             if( sname )
             {
-                wxString wname = FROM_UTF8( sname );
+                wxString wname = From_UTF8( sname );
 
                 if( !page.SetType( wname ) )
                 {
@@ -826,67 +826,67 @@ void LEGACY_PLUGIN::loadSHEET()
         else if( TESTLINE( "Title" ) )
         {
             ReadDelimitedText( buf, line, sizeof(buf) );
-            tb.SetTitle( FROM_UTF8( buf ) );
+            tb.SetTitle( From_UTF8( buf ) );
         }
         else if( TESTLINE( "Date" ) )
         {
             ReadDelimitedText( buf, line, sizeof(buf) );
-            tb.SetDate( FROM_UTF8( buf ) );
+            tb.SetDate( From_UTF8( buf ) );
         }
         else if( TESTLINE( "Rev" ) )
         {
             ReadDelimitedText( buf, line, sizeof(buf) );
-            tb.SetRevision( FROM_UTF8( buf ) );
+            tb.SetRevision( From_UTF8( buf ) );
         }
         else if( TESTLINE( "Comp" ) )
         {
             ReadDelimitedText( buf, line, sizeof(buf) );
-            tb.SetCompany( FROM_UTF8( buf ) );
+            tb.SetCompany( From_UTF8( buf ) );
         }
         else if( TESTLINE( "Comment1" ) )
         {
             ReadDelimitedText( buf, line, sizeof(buf) );
-            tb.SetComment( 0, FROM_UTF8( buf ) );
+            tb.SetComment( 0, From_UTF8( buf ) );
         }
         else if( TESTLINE( "Comment2" ) )
         {
             ReadDelimitedText( buf, line, sizeof(buf) );
-            tb.SetComment( 1, FROM_UTF8( buf ) );
+            tb.SetComment( 1, From_UTF8( buf ) );
         }
         else if( TESTLINE( "Comment3" ) )
         {
             ReadDelimitedText( buf, line, sizeof(buf) );
-            tb.SetComment( 2, FROM_UTF8( buf ) );
+            tb.SetComment( 2, From_UTF8( buf ) );
         }
         else if( TESTLINE( "Comment4" ) )
         {
             ReadDelimitedText( buf, line, sizeof(buf) );
-            tb.SetComment( 3, FROM_UTF8( buf ) );
+            tb.SetComment( 3, From_UTF8( buf ) );
         }
         else if( TESTLINE( "Comment5" ) )
         {
             ReadDelimitedText( buf, line, sizeof(buf) );
-            tb.SetComment( 4, FROM_UTF8( buf ) );
+            tb.SetComment( 4, From_UTF8( buf ) );
         }
         else if( TESTLINE( "Comment6" ) )
         {
             ReadDelimitedText( buf, line, sizeof(buf) );
-            tb.SetComment( 5, FROM_UTF8( buf ) );
+            tb.SetComment( 5, From_UTF8( buf ) );
         }
         else if( TESTLINE( "Comment7" ) )
         {
             ReadDelimitedText( buf, line, sizeof(buf) );
-            tb.SetComment( 6, FROM_UTF8( buf ) );
+            tb.SetComment( 6, From_UTF8( buf ) );
         }
         else if( TESTLINE( "Comment8" ) )
         {
             ReadDelimitedText( buf, line, sizeof(buf) );
-            tb.SetComment( 7, FROM_UTF8( buf ) );
+            tb.SetComment( 7, From_UTF8( buf ) );
         }
         else if( TESTLINE( "Comment9" ) )
         {
             ReadDelimitedText( buf, line, sizeof(buf) );
-            tb.SetComment( 8, FROM_UTF8( buf ) );
+            tb.SetComment( 8, From_UTF8( buf ) );
         }
         else if( TESTLINE( "$EndSHEETDESCR" ) )
         {
@@ -943,7 +943,7 @@ void LEGACY_PLUGIN::loadSETUP()
 
             if( data )
             {
-                wxString layerName = FROM_UTF8( data );
+                wxString layerName = From_UTF8( data );
                 m_board->SetLayerName( layer_id, layerName );
 
                 data = strtok_r( nullptr, delims, &saveptr );
@@ -1289,7 +1289,7 @@ void LEGACY_PLUGIN::loadFOOTPRINT( FOOTPRINT* aFootprint )
             data = strtok_r( line + SZ( "AR" ), delims, (char**) &data );
 
             if( data )
-                aFootprint->SetPath( KIID_PATH( FROM_UTF8( data ) ) );
+                aFootprint->SetPath( KIID_PATH( From_UTF8( data ) ) );
         }
         else if( TESTLINE( "$SHAPE3D" ) )
         {
@@ -1298,11 +1298,11 @@ void LEGACY_PLUGIN::loadFOOTPRINT( FOOTPRINT* aFootprint )
         else if( TESTLINE( "Cd" ) )
         {
             // e.g. "Cd Double rangee de contacts 2 x 4 pins\r\n"
-            aFootprint->SetLibDescription( FROM_UTF8( StrPurge( line + SZ( "Cd" ) ) ) );
+            aFootprint->SetLibDescription( From_UTF8( StrPurge( line + SZ( "Cd" ) ) ) );
         }
         else if( TESTLINE( "Kw" ) )         // Key words
         {
-            aFootprint->SetKeywords( FROM_UTF8( StrPurge( line + SZ( "Kw" ) ) ) );
+            aFootprint->SetKeywords( From_UTF8( StrPurge( line + SZ( "Kw" ) ) ) );
         }
         else if( TESTLINE( ".SolderPasteRatio" ) )
         {
@@ -1427,7 +1427,7 @@ void LEGACY_PLUGIN::loadPAD( FOOTPRINT* aFootprint )
             else
             {
                 // version 2, which is UTF8.
-                padNumber = FROM_UTF8( mypadnumber );
+                padNumber = From_UTF8( mypadnumber );
             }
 
             // chances are both were ASCII, but why take chances?
@@ -1510,7 +1510,7 @@ void LEGACY_PLUGIN::loadPAD( FOOTPRINT* aFootprint )
             if( m_board )
             {
                 wxASSERT( m_board->FindNet( getNetCode( netcode ) )->GetNetname()
-                          == ConvertToNewOverbarNotation( FROM_UTF8( StrPurge( buf ) ) ) );
+                          == ConvertToNewOverbarNotation( From_UTF8( StrPurge( buf ) ) ) );
             }
         }
         else if( TESTLINE( "Po" ) )         // (Po)sition
@@ -1979,7 +1979,7 @@ void LEGACY_PLUGIN::loadNETINFO_ITEM()
 
             if( net == nullptr )
             {
-                net = new NETINFO_ITEM( m_board, ConvertToNewOverbarNotation( FROM_UTF8( buf ) ),
+                net = new NETINFO_ITEM( m_board, ConvertToNewOverbarNotation( From_UTF8( buf ) ),
                                         netCode );
             }
             else
@@ -2055,12 +2055,12 @@ void LEGACY_PLUGIN::loadPCB_TEXT()
         if( TESTLINE( "Te" ) )          // Text line (or first line for multi line texts)
         {
             ReadDelimitedText( text, line + SZ( "Te" ), sizeof(text) );
-            pcbtxt->SetText( ConvertToNewOverbarNotation( FROM_UTF8( text ) ) );
+            pcbtxt->SetText( ConvertToNewOverbarNotation( From_UTF8( text ) ) );
         }
         else if( TESTLINE( "nl" ) )     // next line of the current text
         {
             ReadDelimitedText( text, line + SZ( "nl" ), sizeof(text) );
-            pcbtxt->SetText( pcbtxt->GetText() + wxChar( '\n' ) +  FROM_UTF8( text ) );
+            pcbtxt->SetText( pcbtxt->GetText() + wxChar( '\n' ) +  From_UTF8( text ) );
         }
         else if( TESTLINE( "Po" ) )
         {
@@ -2299,7 +2299,7 @@ void LEGACY_PLUGIN::loadNETCLASS()
         {
             // e.g. "AddNet "V3.3D"\n"
             ReadDelimitedText( buf, line + SZ( "AddNet" ), sizeof(buf) );
-            netname = ConvertToNewOverbarNotation( FROM_UTF8( buf ) );
+            netname = ConvertToNewOverbarNotation( From_UTF8( buf ) );
 
             m_board->GetDesignSettings().m_NetSettings->m_NetClassPatternAssignments.push_back(
                     {
@@ -2340,12 +2340,12 @@ void LEGACY_PLUGIN::loadNETCLASS()
         else if( TESTLINE( "Name" ) )
         {
             ReadDelimitedText( buf, line + SZ( "Name" ), sizeof(buf) );
-            nc->SetName( FROM_UTF8( buf ) );
+            nc->SetName( From_UTF8( buf ) );
         }
         else if( TESTLINE( "Desc" ) )
         {
             ReadDelimitedText( buf, line + SZ( "Desc" ), sizeof(buf) );
-            nc->SetDescription( FROM_UTF8( buf ) );
+            nc->SetDescription( From_UTF8( buf ) );
         }
         else if( TESTLINE( "$EndNCLASS" ) )
         {
@@ -2695,7 +2695,7 @@ void LEGACY_PLUGIN::loadDIMENSION()
             char  buf[2048];
 
             ReadDelimitedText( buf, line + SZ( "Te" ), sizeof(buf) );
-            dim->SetOverrideText( FROM_UTF8( buf ) );
+            dim->SetOverrideText( From_UTF8( buf ) );
             dim->SetOverrideTextEnabled( true );
             dim->SetUnitsFormat( DIM_UNITS_FORMAT::NO_SUFFIX );
             dim->SetAutoUnits();
@@ -3208,7 +3208,7 @@ void LEGACY_PLUGIN::FootprintEnumerate( wxArrayString& aFootprintNames, const wx
     // the library.
 
     for( const auto& footprint : m_cache->m_footprints )
-        aFootprintNames.Add( FROM_UTF8( footprint.first.c_str() ) );
+        aFootprintNames.Add( From_UTF8( footprint.first.c_str() ) );
 
     if( !errorMsg.IsEmpty() && !aBestEfforts )
         THROW_IO_ERROR( errorMsg );
diff --git a/pcbnew/python/scripting/pcbnew_scripting.cpp b/pcbnew/python/scripting/pcbnew_scripting.cpp
index 9679fe4aba..14718a0f07 100644
--- a/pcbnew/python/scripting/pcbnew_scripting.cpp
+++ b/pcbnew/python/scripting/pcbnew_scripting.cpp
@@ -93,7 +93,7 @@ static void pcbnewRunPythonMethodWithReturnedString( const char* aMethodName, wx
             if( temp_bytes != nullptr )
             {
                 str_res = PyBytes_AS_STRING( temp_bytes );
-                aNames = FROM_UTF8( str_res );
+                aNames = From_UTF8( str_res );
                 Py_DECREF( temp_bytes );
             }
             else
diff --git a/pcbnew/specctra_import_export/specctra_import.cpp b/pcbnew/specctra_import_export/specctra_import.cpp
index 12cd099cc9..f3d1776963 100644
--- a/pcbnew/specctra_import_export/specctra_import.cpp
+++ b/pcbnew/specctra_import_export/specctra_import.cpp
@@ -158,7 +158,7 @@ PCB_TRACK* SPECCTRA_DB::makeTRACK( WIRE* wire, PATH* aPath, int aPointIndex, int
     if( layerNdx == -1 )
     {
         THROW_IO_ERROR( wxString::Format( _( "Session file uses invalid layer id '%s'." ),
-                                          FROM_UTF8( aPath->layer_id.c_str() ) ) );
+                                          From_UTF8( aPath->layer_id.c_str() ) ) );
     }
 
     PCB_TRACK* track = new PCB_TRACK( m_sessionBoard );
@@ -283,7 +283,7 @@ PCB_VIA* SPECCTRA_DB::makeVIA( WIRE_VIA*aVia, PADSTACK* aPadstack, const POINT&
             int layerNdx = findLayerName( circle->layer_id );
             if( layerNdx == -1 )
             {
-                wxString layerName = FROM_UTF8( circle->layer_id.c_str() );
+                wxString layerName = From_UTF8( circle->layer_id.c_str() );
                 THROW_IO_ERROR( wxString::Format( _( "Session file uses invalid layer id '%s'" ),
                                                   layerName ) );
             }
@@ -392,7 +392,7 @@ void SPECCTRA_DB::FromSESSION( BOARD* aBoard )
             {
                 PLACE* place = &places[i];  // '&' even though places[] holds a pointer!
 
-                wxString   reference = FROM_UTF8( place->m_component_id.c_str() );
+                wxString   reference = From_UTF8( place->m_component_id.c_str() );
                 FOOTPRINT* footprint = aBoard->FindFootprintByReference( reference );
 
                 if( !footprint )
@@ -455,7 +455,7 @@ void SPECCTRA_DB::FromSESSION( BOARD* aBoard )
         // page 143 of spec says wire's net_id is optional
         if( net->net_id.size() )
         {
-            wxString netName = FROM_UTF8( net->net_id.c_str() );
+            wxString netName = From_UTF8( net->net_id.c_str() );
             NETINFO_ITEM* netinfo = aBoard->FindNet( netName );
 
             if( netinfo )
@@ -476,7 +476,7 @@ void SPECCTRA_DB::FromSESSION( BOARD* aBoard )
                  * back in as session here.  We kept our own zones in the BOARD, so ignore this
                  * so called 'wire'.
 
-                wxString netId = FROM_UTF8( wire->net_id.c_str() );
+                wxString netId = From_UTF8( wire->net_id.c_str() );
                 THROW_IO_ERROR( wxString::Format( _( "Unsupported wire shape: '%s' for net: '%s'" ),
                                                     DLEX::GetTokenString(shape).GetData(),
                                                     netId.GetData() ) );
@@ -504,7 +504,7 @@ void SPECCTRA_DB::FromSESSION( BOARD* aBoard )
             // page 144 of spec says wire_via's net_id is optional
             if( net->net_id.size() )
             {
-                wxString netName = FROM_UTF8( net->net_id.c_str() );
+                wxString netName = From_UTF8( net->net_id.c_str() );
                 NETINFO_ITEM* netvia = aBoard->FindNet( netName );
 
                 if( netvia )
@@ -524,7 +524,7 @@ void SPECCTRA_DB::FromSESSION( BOARD* aBoard )
                 // in in the session library, even though they may be actually used in the
                 // pre-routed, protected wire_vias. So until that is fixed, create the padstack
                 // from its name as a work around.
-                wxString psid( FROM_UTF8( wire_via->GetPadstackId().c_str() ) );
+                wxString psid( From_UTF8( wire_via->GetPadstackId().c_str() ) );
 
                 THROW_IO_ERROR( wxString::Format( _( "A wire_via refers to missing padstack '%s'." ),
                                                   psid ) );
diff --git a/pcbnew/specctra_import_export/specctra_test.cpp b/pcbnew/specctra_import_export/specctra_test.cpp
index e357cad4b5..88fa7f59ec 100644
--- a/pcbnew/specctra_import_export/specctra_test.cpp
+++ b/pcbnew/specctra_import_export/specctra_test.cpp
@@ -55,7 +55,7 @@ int main( int argc, char** argv )
 
     if( argc == 2 )
     {
-        filename = FROM_UTF8( argv[1] );
+        filename = From_UTF8( argv[1] );
     }
 
     try
diff --git a/qa/qa_utils/test_app_main.cpp b/qa/qa_utils/test_app_main.cpp
index 5a1c396c85..df9b92cf6b 100644
--- a/qa/qa_utils/test_app_main.cpp
+++ b/qa/qa_utils/test_app_main.cpp
@@ -33,7 +33,7 @@
 
 
 #include <typeinfo>
-#include <macros.h>
+#include <string_utils.h>
 #include <wx/filename.h>
 #include <wx/stdpaths.h>
 #include <wx/snglinst.h>
@@ -182,7 +182,7 @@ struct APP_TEST : public wxApp
         catch( const std::exception& e )
         {
             wxLogError( wxT( "Unhandled exception class: %s  what: %s" ),
-                        FROM_UTF8( typeid(e).name() ), FROM_UTF8( e.what() ) );
+                        From_UTF8( typeid(e).name() ), From_UTF8( e.what() ) );
         }
         catch( const IO_ERROR& ioe )
         {
@@ -215,8 +215,8 @@ struct APP_TEST : public wxApp
         catch( const std::exception& e )
         {
             wxLogError( wxT( "Unhandled exception class: %s  what: %s" ),
-                FROM_UTF8( typeid(e).name() ),
-                FROM_UTF8( e.what() ) );
+                From_UTF8( typeid(e).name() ),
+                From_UTF8( e.what() ) );
         }
         catch( const IO_ERROR& ioe )
         {
diff --git a/scripting/python_scripting.cpp b/scripting/python_scripting.cpp
index ef4348992a..d678d1d588 100644
--- a/scripting/python_scripting.cpp
+++ b/scripting/python_scripting.cpp
@@ -366,7 +366,7 @@ static void RunPythonMethodWithReturnedString( const char* aMethodName, wxString
             if( temp_bytes != nullptr )
             {
                 str_res = PyBytes_AS_STRING( temp_bytes );
-                aNames = FROM_UTF8( str_res );
+                aNames = From_UTF8( str_res );
                 Py_DECREF( temp_bytes );
             }
             else
@@ -452,7 +452,7 @@ wxString PyStringToWx( PyObject* aString )
     if( temp_bytes != nullptr )
     {
         str_res = PyBytes_AS_STRING( temp_bytes );
-        ret = FROM_UTF8( str_res );
+        ret = From_UTF8( str_res );
         Py_DECREF( temp_bytes );
     }
     else
@@ -485,7 +485,7 @@ wxArrayString PyArrayStringToWx( PyObject* aArrayString )
             if( temp_bytes != nullptr )
             {
                 str_res = PyBytes_AS_STRING( temp_bytes );
-                ret.Add( FROM_UTF8( str_res ), 1 );
+                ret.Add( From_UTF8( str_res ), 1 );
                 Py_DECREF( temp_bytes );
             }
             else
diff --git a/thirdparty/markdown2html/markdown2html.cpp b/thirdparty/markdown2html/markdown2html.cpp
index 50d265448a..f4fb041234 100644
--- a/thirdparty/markdown2html/markdown2html.cpp
+++ b/thirdparty/markdown2html/markdown2html.cpp
@@ -17,8 +17,9 @@
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <string>
 #include <macros.h>
+#include <string>
+#include <string_utils.h>
 
 #include "markdown.h"
 #include "html.h"
@@ -43,7 +44,7 @@ void ConvertMarkdown2Html( const wxString& aMarkdownInput, wxString& aHtmlOutput
     sd_markdown_free( markdown );
 
     std::string out( (char*)ob->data, ob->size );
-    aHtmlOutput = FROM_UTF8( out.data() );
+    aHtmlOutput = From_UTF8( out.data() );
 
     /* cleanup */
     bufrelease( ob );
diff --git a/utils/idftools/idf_helpers.h b/utils/idftools/idf_helpers.h
index 7d1becf866..4c5205be3c 100644
--- a/utils/idftools/idf_helpers.h
+++ b/utils/idftools/idf_helpers.h
@@ -45,7 +45,7 @@
  *
  * NOTE: Taken from KiCad include/macros.h
  */
-static inline wxString FROM_UTF8( const char* cstring )
+static inline wxString From_UTF8( const char* cstring )
 {
     wxString line = wxString::FromUTF8( cstring );