diff --git a/CMakeLists.txt b/CMakeLists.txt
index c8f24dde81f0a63fbb5d55f17bb51e0fd9f36d06..da59bcd46e693ca1c2cd2a5ef11baa89323fb346 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,6 +35,9 @@ cmake_minimum_required(VERSION 3.15.0 FATAL_ERROR)
 
 project(FLTK VERSION 1.5.0)
 
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
+
 #######################################################################
 # include macro and function definitions for general usage
 #######################################################################
diff --git a/FL/Fl_Preferences.H b/FL/Fl_Preferences.H
index 6c6407a5791efe5ac3374e095f3b2eddc1c50671..92cc966b3f99357afb7487083f7b0465694bdefb 100644
--- a/FL/Fl_Preferences.H
+++ b/FL/Fl_Preferences.H
@@ -24,10 +24,7 @@
 #  include "Fl_Export.H"
 #  include "fl_attr.h"
 
-//class Fl_String;
-#if (FLTK_USE_STD)
 #include <string>
-#endif
 
 /**
  \brief Fl_Preferences store user settings between application starts.
@@ -245,6 +242,7 @@ public:
   char set( const char *entry, double value, int precision );
   char set( const char *entry, const char *value );
   char set( const char *entry, const void *value, int size );
+  char set( const char *entry, const std::string &value );
 
   char get( const char *entry, int &value, int defaultValue );
   char get( const char *entry, float &value,  float defaultValue );
@@ -254,14 +252,7 @@ public:
   char get( const char *entry, void *&value,  const void *defaultValue, int defaultSize );
   char get( const char *entry, void *value,   const void *defaultValue, int defaultSize, int maxSize );
   char get( const char *entry, void *value,   const void *defaultValue, int defaultSize, int *size );
-
-//  char set( const char *entry, const Fl_String &value );
-//  char get( const char *entry, Fl_String &value, const Fl_String &defaultValue );
-
-#if (FLTK_USE_STD)
-  char set( const char *entry, const std::string &value );
   char get( const char *entry, std::string &value, const std::string &defaultValue );
-#endif
 
   int size( const char *entry );
 
diff --git a/fluid/fluid_filename.h b/fluid/fluid_filename.h
index 8a97f132ca42ba856fbebea1cde21455788a92d2..2ac489ee670645f1fd7eba9a63dc13f282a5f639 100644
--- a/fluid/fluid_filename.h
+++ b/fluid/fluid_filename.h
@@ -39,7 +39,7 @@
 
 #  if defined(__cplusplus)
 
-class Fl_String;
+#include "../src/Fl_String.H"
 
 Fl_String fl_filename_shortened(const Fl_String &filename, int maxchars);
 Fl_String fl_filename_name(const Fl_String &filename);
diff --git a/src/Fl_Preferences.cxx b/src/Fl_Preferences.cxx
index 586416bf5cc0c2ce7b560c12ef24cedf5a428883..94b17e994cb4e84e350ed233d1b9d500fa22840c 100644
--- a/src/Fl_Preferences.cxx
+++ b/src/Fl_Preferences.cxx
@@ -28,9 +28,7 @@
 #include <stdlib.h>
 #include <stdarg.h>
 
-#if (FLTK_USE_STD)
 #include <string>
-#endif
 
 /*
  The format of preferences files is not part of the FLTK specification
@@ -966,12 +964,12 @@ char Fl_Preferences::get( const char *key, char *&text, const char *defaultValue
   return ( v != defaultValue );
 }
 
-#if (FLTK_USE_STD)
-
 /**
- Reads an entry from the group. A default value must be
- supplied. The return value indicates if the value was available
- (non-zero) or the default was used (0).
+ Reads an entry from the group.
+
+ A default value must be supplied. The return value indicates if the value was
+ available (non-zero) or the default was used (0). NUL characters in std::string
+ are treated as the end of the text.
 
  \param[in] key name of entry
  \param[out] value returned from preferences or default value if none was set
@@ -995,8 +993,6 @@ char Fl_Preferences::get( const char *key, std::string &value, const std::string
   }
 }
 
-#endif
-
 /**
  Sets an entry (name/value pair). The return value indicates if there
  was a problem storing the data in memory. However it does not
@@ -1167,12 +1163,12 @@ char Fl_Preferences::set( const char *key, const void *data, int dsize ) {
   return 1;
 }
 
-#if (FLTK_USE_STD)
-
 /**
- Sets an entry (name/value pair). The return value indicates if there
- was a problem storing the data in memory. However it does not
- reflect if the value was actually stored in the preference file.
+ Sets an entry (name/value pair).
+
+ The return value indicates if there was a problem storing the data in memory.
+ However it does not reflect if the value was actually stored in the preference
+ file. NUL characters in std::string are treated as the end of the text.
 
  \param[in] entry name of entry
  \param[in] value set this entry to value (stops at the first nul character).
@@ -1182,8 +1178,6 @@ char Fl_Preferences::set( const char *entry, const std::string &value ) {
   return set(entry, value.c_str());
 }
 
-#endif // FLTK_USE_STD
-
 /**
  Returns the size of the value part of an entry.
 
diff --git a/src/Fl_String.H b/src/Fl_String.H
index e7fbf49ebd5737bc92c99ed13f0c4f0b58babe50..13dfd8cf0d818689a03e219ad1ac5e6896b41cbf 100644
--- a/src/Fl_String.H
+++ b/src/Fl_String.H
@@ -29,6 +29,18 @@
 
 #include <FL/Fl_Export.H>
 
+#include <string>
+
+#if 1
+
+// Since fltk 1.5.0, Fl_String is no longer needed and now maps to std::string.
+// Fl_String is not part of the public API. All occurrences of Fl_String in the
+// core library and in Fluid should be replaced with std::string. When done,
+// src/Fl_String.H and src/Fl_String.cxx can be deleted.
+using Fl_String = std::string;
+
+#else
+
 // See: https://en.cppreference.com/w/cpp/string/basic_string/basic_string
 
 /**
@@ -142,4 +154,6 @@ FL_EXPORT bool operator!=(const Fl_String & lhs, const Fl_String & rhs);
 \endcond
 */
 
+#endif
+
 #endif // _FL_Fl_String_H_
diff --git a/src/Fl_String.cxx b/src/Fl_String.cxx
index 60d50ef998f62d819dc25890f060d9c73ecf181c..705b7cd9f1217b11c67eb5a09213b25a06c4d318 100644
--- a/src/Fl_String.cxx
+++ b/src/Fl_String.cxx
@@ -14,6 +14,8 @@
 //     https://www.fltk.org/bugs.php
 //
 
+#if 0
+
 /**
  \cond DriverDev
  \addtogroup DriverDeveloper
@@ -662,3 +664,5 @@ bool operator!=(const Fl_String &lhs, const Fl_String &rhs) {
 \}
 \endcond
 */
+
+#endif
diff --git a/test/unittest_core.cxx b/test/unittest_core.cxx
index bc91c8dd4c417f573088f9294f299252871ea35d..476fdfeb02cfb2625a533f843fe9998e970cd930 100644
--- a/test/unittest_core.cxx
+++ b/test/unittest_core.cxx
@@ -25,159 +25,6 @@
 #include <FL/filename.H>
 #include <FL/fl_utf8.h>
 
-/* Test Fl_String constructor and assignment. */
-TEST(Fl_String, Assignment) {
-  Fl_String null;
-  EXPECT_STREQ(null.c_str(), "");   // default initialisation is an empty string
-  EXPECT_TRUE(null.empty());
-
-  Fl_String null2(NULL);
-  EXPECT_STREQ(null2.c_str(), "");  // initialise with a NULL pointer gets an empty string
-  EXPECT_TRUE(null2.empty());
-
-  Fl_String empty("");
-  EXPECT_STREQ(empty.c_str(), "");  // also, empty CString make empty Fl_String
-  EXPECT_TRUE(empty.empty());
-
-  Fl_String text("hello");
-  EXPECT_STREQ(text.c_str(), "hello");  // Load some text from a CString
-  EXPECT_EQ(text.size(), 5);        // did we get the size right?
-  EXPECT_EQ(text.strlen(), 5);      // do we have a trailing 0
-  EXPECT_GE(text.capacity(), 5);    // do we have the capacity
-  EXPECT_TRUE(!text.empty());       // test the empty() method
-
-  Fl_String text2("abcdef", 3);
-  EXPECT_STREQ(text2.c_str(), "abc");
-  EXPECT_EQ(text2.size(), 3);
-
-  Fl_String text3("abc\0def", 7);
-  EXPECT_EQ(text3.strlen(), 3);
-  EXPECT_EQ(text3.size(), 7);
-
-  Fl_String text4(text);
-  EXPECT_STREQ(text4.c_str(), "hello");
-
-  Fl_String text5 = text;
-  EXPECT_STREQ(text5.c_str(), "hello");
-
-  Fl_String text6 = "yoohoo";
-  EXPECT_STREQ(text6.c_str(), "yoohoo");
-
-  return true;
-}
-
-/* Test methods that access Fl_String content and parts of it. */
-TEST(Fl_String, Access) {
-  Fl_String hello = "hello";
-  EXPECT_STREQ(hello.c_str(), "hello");
-  EXPECT_STREQ(hello.data(), "hello");
-  EXPECT_EQ(hello[1], 'e');
-  EXPECT_EQ(hello[hello.size()], 0);
-  EXPECT_EQ(hello.at(1), 'e');
-  EXPECT_EQ(hello.at(-1), 0);
-  EXPECT_EQ(hello.at(11), 0);
-
-  hello[1] = 'a';
-  EXPECT_STREQ(hello.c_str(), "hallo");
-
-  hello.data()[1] = 'e';
-  EXPECT_STREQ(hello.c_str(), "hello");
-
-  return true;
-}
-
-/* Test the Fl_String capacity management. */
-TEST(Fl_String, Capacity) {
-  Fl_String hello;
-  EXPECT_EQ(hello.capacity(), 0);
-
-  hello = "hi";
-  EXPECT_STREQ(hello.c_str(), "hi");
-  EXPECT_GE(hello.capacity(), 2);
-
-  hello = "the quick brown fox jumps over the lazy dog";
-  EXPECT_STREQ(hello.c_str(), "the quick brown fox jumps over the lazy dog");
-  EXPECT_GE(hello.capacity(), 41);
-
-  int c = hello.capacity();
-  hello.reserve(c+100);
-  EXPECT_STREQ(hello.c_str(), "the quick brown fox jumps over the lazy dog");
-  EXPECT_GE(hello.capacity(), 141);
-
-  hello = "hi";
-  hello.shrink_to_fit();
-  EXPECT_EQ(hello.capacity(), 2);
-
-  return true;
-}
-
-/* Test all methods that operate on Fl_String. */
-TEST(Fl_String, Operations) {
-  Fl_String empty;
-  Fl_String hello = "Hello", world = "World";
-  hello.resize(4);
-  EXPECT_STREQ(hello.c_str(), "Hell");
-
-  hello.clear();
-  EXPECT_TRUE(hello.empty());
-
-  hello = "Hello";
-  hello.insert(3, "-");
-  EXPECT_STREQ(hello.c_str(), "Hel-lo");
-  hello = "Hello";
-  hello.erase(2, 2);
-  EXPECT_STREQ(hello.c_str(), "Heo");
-
-  hello = "Hello";
-  hello.push_back('!');
-  EXPECT_STREQ(hello.c_str(), "Hello!");
-  hello.pop_back();
-  EXPECT_STREQ(hello.c_str(), "Hello");
-  hello.append(world);
-  EXPECT_STREQ(hello.c_str(), "HelloWorld");
-  hello.append("!");
-  EXPECT_STREQ(hello.c_str(), "HelloWorld!");
-  hello = "Hello";
-  hello += world;
-  EXPECT_STREQ(hello.c_str(), "HelloWorld");
-  hello += "!";
-  EXPECT_STREQ(hello.c_str(), "HelloWorld!");
-  hello += '?';
-  EXPECT_STREQ(hello.c_str(), "HelloWorld!?");
-
-  hello = "Hello";
-  hello.replace(0, 0, "Say ", 4);
-  EXPECT_STREQ(hello.c_str(), "Say Hello");
-  hello.replace(0, 4, "");
-  EXPECT_STREQ(hello.c_str(), "Hello");
-  hello.replace(2, 2, "bb");
-  EXPECT_STREQ(hello.c_str(), "Hebbo");
-  hello.replace(2, 2, "xxx");
-  EXPECT_STREQ(hello.c_str(), "Hexxxo");
-  hello.replace(2, 3, "ll");
-  EXPECT_STREQ(hello.c_str(), "Hello");
-  hello.replace(2, 0, NULL, 0);
-  EXPECT_STREQ(hello.c_str(), "Hello");
-  hello.replace(Fl_String::npos, Fl_String::npos, world);
-  EXPECT_STREQ(hello.c_str(), "HelloWorld");
-
-  hello = "Hello";
-  Fl_String sub = hello.substr();
-  EXPECT_STREQ(sub.c_str(), "Hello"); // check correct usage
-  sub = hello.substr(2);
-  EXPECT_STREQ(sub.c_str(), "llo");
-  sub = hello.substr(2, 2);
-  EXPECT_STREQ(sub.c_str(), "ll");
-  sub = hello.substr(-1, 2);
-  EXPECT_TRUE(sub.empty()); // check faulty values
-  sub = hello.substr(20, 2);
-  EXPECT_TRUE(sub.empty());
-  sub = empty.substr(0, 2);
-  EXPECT_TRUE(sub.empty());
-
-  return true;
-}
-
 #if (0) // FIXME - Fl_String
 
 /* Test all Fl_String functions that are no part of the class. */
@@ -225,28 +72,32 @@ TEST(Fl_String, fl_filename_...) {
   return true;
 }
 
+#endif
+
 /* Test additions to Fl_Preferences. */
-//TEST(Fl_Preferences, Strings) {
-//  {
-//    Fl_Preferences prefs(Fl_Preferences::USER_L, "fltk.org", "unittests");
-//    prefs.set("a", Fl_String());
-//    prefs.set("b", Fl_String("Hello"));
-//    prefs.set("c", Fl_String("Hel\\l\nö"));
-//  }
-//  {
-//    Fl_Preferences prefs(Fl_Preferences::USER_L, "fltk.org", "unittests");
-//    Fl_String r;
-//    prefs.get("a", r, "x");
-//    EXPECT_STREQ(r.c_str(), "");
-//    prefs.get("b", r, "x");
-//    EXPECT_STREQ(r.c_str(), "Hello");
-//    prefs.get("c", r, "x");
-//    EXPECT_STREQ(r.c_str(), "Hel\\l\nö");
-//    prefs.get("d", r, "x");
-//    EXPECT_STREQ(r.c_str(), "x");
-//  }
-//  return true;
-//}
+TEST(Fl_Preferences, Strings) {
+  {
+    Fl_Preferences prefs(Fl_Preferences::USER_L, "fltk.org", "unittests");
+    prefs.set("a", Fl_String());
+    prefs.set("b", Fl_String("Hello"));
+    prefs.set("c", Fl_String("Hel\\l\nö"));
+  }
+  {
+    Fl_Preferences prefs(Fl_Preferences::USER_L, "fltk.org", "unittests");
+    Fl_String r;
+    prefs.get("a", r, "x");
+    EXPECT_STREQ(r.c_str(), "");
+    prefs.get("b", r, "x");
+    EXPECT_STREQ(r.c_str(), "Hello");
+    prefs.get("c", r, "x");
+    EXPECT_STREQ(r.c_str(), "Hel\\l\nö");
+    prefs.get("d", r, "x");
+    EXPECT_STREQ(r.c_str(), "x");
+  }
+  return true;
+}
+
+#if 0
 
 TEST(fl_filename, ext) {
   Fl_String r = fl_filename_ext("test.txt");