FLTK logo

[master] 2141c63 - Implement + deploy fl_strdup()

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 All Forums  |  Back to fltk.commit  ]
 
Previous Message ]Next Message ]

[master] 2141c63 - Implement + deploy fl_strdup() "Greg Ercolano" Aug 01, 2020  
 
commit 2141c63628a831d3f53dad7035c94028f8d0d629
Author: Greg Ercolano <erco@seriss.com>
Date:   Tue Jul 21 20:15:41 2020 -0700

    Implement + deploy fl_strdup()

 FL/fl_string.h                                     | 47 ++++++++++++++++++++++
 examples/table-as-container.cxx                    |  3 +-
 examples/table-sort.cxx                            |  3 +-
 fluid/ExternalCodeEditor_UNIX.cxx                  |  3 +-
 fluid/ExternalCodeEditor_WIN32.cxx                 |  3 +-
 fluid/Fl_Function_Type.cxx                         | 15 +++----
 fluid/Fluid_Image.cxx                              |  3 +-
 fluid/code.cxx                                     |  5 ++-
 fluid/file.cxx                                     | 13 +++---
 fluid/fluid.cxx                                    |  3 +-
 fluid/print_panel.cxx                              |  3 +-
 fluid/print_panel.fl                               |  5 ++-
 fluid/template_panel.cxx                           |  3 +-
 fluid/template_panel.fl                            |  5 ++-
 src/CMakeLists.txt                                 |  1 +
 src/Fl_Check_Browser.cxx                           |  3 +-
 src/Fl_File_Browser.cxx                            |  3 +-
 src/Fl_File_Chooser2.cxx                           |  3 +-
 src/Fl_Help_View.cxx                               |  5 ++-
 src/Fl_Image_Reader.cxx                            |  5 ++-
 src/Fl_MacOS_Sys_Menu_Bar.mm                       |  3 +-
 src/Fl_Menu_add.cxx                                |  5 ++-
 src/Fl_Native_File_Chooser_GTK.cxx                 |  7 ++--
 src/Fl_Native_File_Chooser_MAC.mm                  |  7 ++--
 src/Fl_Preferences.cxx                             | 29 ++++++-------
 src/Fl_SVG_Image.cxx                               |  3 +-
 src/Fl_System_Driver.H                             |  3 ++
 src/Fl_Text_Buffer.cxx                             |  3 +-
 src/Fl_Text_Display.cxx                            |  7 ++--
 src/Fl_Tooltip.cxx                                 |  4 +-
 src/Fl_Tree.cxx                                    |  3 +-
 src/Fl_Tree_Item.cxx                               |  6 ++-
 src/Fl_Widget.cxx                                  |  3 +-
 src/Fl_Window.cxx                                  |  5 ++-
 src/Fl_cocoa.mm                                    |  5 ++-
 src/Fl_get_system_colors.cxx                       |  7 ++--
 src/Fl_win32.cxx                                   |  3 +-
 src/Makefile                                       |  3 +-
 src/drivers/Android/Fl_Android_Application.cxx     |  3 +-
 src/drivers/Android/Fl_Android_System_Driver.H     |  3 +-
 src/drivers/Android/Fl_Android_System_Driver.cxx   |  3 +-
 src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm       |  3 +-
 src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx    |  9 +++--
 src/drivers/Posix/Fl_Posix_System_Driver.H         |  2 +
 src/drivers/Posix/Fl_Posix_System_Driver.cxx       |  3 +-
 src/drivers/PostScript/Fl_PostScript.cxx           |  3 +-
 .../Quartz/Fl_Quartz_Graphics_Driver_font.cxx      |  5 ++-
 src/drivers/SVG/Fl_SVG_File_Surface.cxx            | 12 +++---
 src/drivers/WinAPI/Fl_WinAPI_System_Driver.H       |  3 ++
 src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx     |  3 +-
 src/drivers/X11/Fl_X11_System_Driver.cxx           |  3 +-
 .../Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx        |  5 ++-
 .../Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx      | 11 ++---
 src/filename_absolute.cxx                          |  3 +-
 src/fl_ask.cxx                                     |  3 +-
 src/fl_string.cxx                                  | 34 ++++++++++++++++
 src/flstring.h                                     |  4 --
 src/print_panel.cxx                                |  5 ++-
 src/xutf8/utf8Wrap.c                               |  3 +-
 test/menubar.cxx                                   |  3 +-
 test/unittests.cxx                                 |  3 +-
 test/utf8.cxx                                      |  5 ++-
 62 files changed, 260 insertions(+), 114 deletions(-)

diff --git FL/fl_string.h FL/fl_string.h
new file mode 100644
index 0000000..adcefa4
--- /dev/null
+++ FL/fl_string.h
@@ -0,0 +1,47 @@
+/*
+ * Platform agnostic string portability functions for the Fast Light Tool Kit (FLTK).
+ *
+ * Copyright 2020 by Bill Spitzak and others.
+ *
+ * This library is free software. Distribution and use rights are outlined in
+ * the file "COPYING" which should have been included with this file.  If this
+ * file is missing or damaged, see the license at:
+ *
+ *     https://www.fltk.org/COPYING.php
+ *
+ * Please see the following page on how to report bugs and issues:
+ *
+ *     https://www.fltk.org/bugs.php
+ */
+
+/**
+  \file fl_string.h
+  \brief Public header for FLTK's own platform agnostic string handling.
+*/
+
+#ifndef _FL_fl_string_h_
+#define _FL_fl_string_h_
+
+#include "Fl_Export.H"
+#include "fl_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \addtogroup fl_string
+    @{
+*/
+
+FL_EXPORT char* fl_strdup(const char *s);
+
+/** @} */
+
+/*****************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* _FL_fl_string_h_ */
diff --git examples/table-as-container.cxx examples/table-as-container.cxx
index 515ad88..838c555 100644
--- examples/table-as-container.cxx
+++ examples/table-as-container.cxx
@@ -31,6 +31,7 @@
 #include <FL/Fl_Input.H>
 #include <FL/fl_draw.H>
 #include <FL/Fl_Table.H>
+#include <FL/fl_string.h>	// fl_strdup()
 
 void button_cb(Fl_Widget *w, void*);
 
@@ -75,7 +76,7 @@ public:
           } else {
             // Create the light buttons
             sprintf(s, "%d/%d ", r, c);
-            Fl_Light_Button *butt = new Fl_Light_Button(X,Y,W,H,strdup(s));
+            Fl_Light_Button *butt = new Fl_Light_Button(X,Y,W,H,fl_strdup(s));
             butt->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
             butt->callback(button_cb, (void*)0);
             butt->value( ((r+c*2) & 4 ) ? 1 : 0);
diff --git examples/table-sort.cxx examples/table-sort.cxx
index d492bf5..a907af9 100644
--- examples/table-sort.cxx
+++ examples/table-sort.cxx
@@ -26,6 +26,7 @@
 #include <FL/Fl_Double_Window.H>
 #include <FL/fl_draw.H>
 #include <FL/Fl_Table_Row.H>
+#include <FL/fl_string.h>
 
 #include <stdio.h>
 #include <string.h>
@@ -225,7 +226,7 @@ void MyTable::load_command(const char *cmd) {
         char *ss;
         const char *delim = " \t\n";
         for(int t=0; (t==0)?(ss=strtok(s,delim)):(ss=strtok(NULL,delim)); t++) {
-            rc.push_back(strdup(ss));
+            rc.push_back(fl_strdup(ss));
         }
         // Keep track of max # columns
         if ( (int)rc.size() > cols() ) {
diff --git fluid/ExternalCodeEditor_UNIX.cxx fluid/ExternalCodeEditor_UNIX.cxx
index 189f297..c0f7535 100644
--- fluid/ExternalCodeEditor_UNIX.cxx
+++ fluid/ExternalCodeEditor_UNIX.cxx
@@ -16,6 +16,7 @@
 
 #include <FL/Fl.H>      /* Fl_Timeout_Handler.. */
 #include <FL/fl_ask.H>  /* fl_alert() */
+#include <FL/fl_string.h> /* fl_strdup() */
 
 #include "ExternalCodeEditor_UNIX.h"
 
@@ -61,7 +62,7 @@ ExternalCodeEditor::~ExternalCodeEditor() {
 //
 void ExternalCodeEditor::set_filename(const char *val) {
   if ( filename_ ) free((void*)filename_);
-  filename_ = val ? strdup(val) : 0;
+  filename_ = val ? fl_strdup(val) : 0;
 }
 
 // [Public] Is editor running?
diff --git fluid/ExternalCodeEditor_WIN32.cxx fluid/ExternalCodeEditor_WIN32.cxx
index 9be5a30..45ad612 100644
--- fluid/ExternalCodeEditor_WIN32.cxx
+++ fluid/ExternalCodeEditor_WIN32.cxx
@@ -8,6 +8,7 @@
 #include <FL/Fl.H>      // Fl_Timeout_Handler..
 #include <FL/fl_ask.H>  // fl_alert()
 #include <FL/fl_utf8.h> // fl_utf8fromwc()
+#include <FL/fl_string.h> // fl_strdup()
 
 #include "ExternalCodeEditor_WIN32.h"
 
@@ -83,7 +84,7 @@ ExternalCodeEditor::~ExternalCodeEditor() {
 //
 void ExternalCodeEditor::set_filename(const char *val) {
   if ( filename_ ) free((void*)filename_);
-  filename_ = val ? strdup(val) : 0;
+  filename_ = val ? fl_strdup(val) : 0;
 }
 
 // [Public] Is editor running?
diff --git fluid/Fl_Function_Type.cxx fluid/Fl_Function_Type.cxx
index f6e8f5b..54b4a73 100644
--- fluid/Fl_Function_Type.cxx
+++ fluid/Fl_Function_Type.cxx
@@ -17,6 +17,7 @@
 #include <FL/Fl_Window.H>
 #include <FL/Fl_Preferences.H>
 #include <FL/Fl_File_Chooser.H>
+#include <FL/fl_string.h>
 #include "Fl_Type.h"
 #include <FL/fl_show_input.H>
 #include <FL/Fl_File_Chooser.H>
@@ -843,7 +844,7 @@ void Fl_Data_Type::open() {
     }
     // store the variable name:
     const char*c = data_input->value();
-    char *s = strdup(c), *p = s, *q, *n;
+    char *s = fl_strdup(c), *p = s, *q, *n;
     for (;;++p) {
       if (!isspace((unsigned char)(*p))) break;
     }
@@ -890,7 +891,7 @@ void Fl_Data_Type::open() {
     else if (!filename_ && *c)
       set_modflag(1);
     if (filename_) { free((void*)filename_); filename_ = 0L; }
-    if (c && *c) filename_ = strdup(c);
+    if (c && *c) filename_ = fl_strdup(c);
     // store the comment
     c = data_comment_input->buffer()->text();
     if (c && *c) {
@@ -1016,7 +1017,7 @@ Fl_Type *Fl_DeclBlock_Type::make() {
   Fl_DeclBlock_Type *o = new Fl_DeclBlock_Type();
   o->name("#if 1");
   o->public_ = 0;
-  o->after = strdup("#endif");
+  o->after = fl_strdup("#endif");
   o->add(p);
   o->factory = this;
   return o;
@@ -1188,7 +1189,7 @@ void Fl_Comment_Type::open() {
                                        "Use forward slashes '/' to create submenus.",
                                        "My Comment");
           if (xname) {
-            char *name = strdup(xname);
+            char *name = fl_strdup(xname);
             for (char*s=name;*s;s++) if (*s==':') *s = ';';
             int n;
             Fl_Preferences db(Fl_Preferences::USER, "fltk.org", "fluid_comments");
@@ -1305,7 +1306,7 @@ void Fl_Comment_Type::write_code1() {
     return;
   }
   // copy the comment line by line, add the double slash if needed
-  char *txt = strdup(c);
+  char *txt = fl_strdup(c);
   char *b = txt, *e = txt;
   for (;;) {
     // find the end of the line and set it to NUL
@@ -1374,7 +1375,7 @@ int Fl_Class_Type::is_public() const {return public_;}
 
 void Fl_Class_Type::prefix(const char*p) {
   free((void*) class_prefix);
-  class_prefix=strdup(p ? p : "" );
+  class_prefix=fl_strdup(p ? p : "" );
 }
 
 Fl_Type *Fl_Class_Type::make() {
@@ -1440,7 +1441,7 @@ void Fl_Class_Type::open() {
       else if (!w) Fl::wait();
     }
     const char*c = c_name_input->value();
-    char *s = strdup(c);
+    char *s = fl_strdup(c);
     size_t len = strlen(s);
     if (!*s) goto OOPS;
     p = (char*) (s+len-1);
diff --git fluid/Fluid_Image.cxx fluid/Fluid_Image.cxx
index 19784e0..1f41a09 100644
--- fluid/Fluid_Image.cxx
+++ fluid/Fluid_Image.cxx
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 #include <stdarg.h>
 #include <FL/filename.H>
+#include <FL/fl_string.h>
 
 extern void goto_source_dir(); // in fluid.cxx
 extern void leave_source_dir(); // in fluid.cxx
@@ -204,7 +205,7 @@ Fluid_Image* Fluid_Image::find(const char *iname) {
 }
 
 Fluid_Image::Fluid_Image(const char *iname) {
-  name_ = strdup(iname);
+  name_ = fl_strdup(iname);
   written = 0;
   refcount = 0;
   img = Fl_Shared_Image::get(iname);
diff --git fluid/code.cxx fluid/code.cxx
index 7b156f5..4603e95 100644
--- fluid/code.cxx
+++ fluid/code.cxx
@@ -20,6 +20,7 @@
 #include <stdarg.h>
 
 #include <FL/Fl.H>
+#include <FL/fl_string.h>
 #include "Fl_Type.h"
 #include "alignment_panel.h"
 
@@ -46,7 +47,7 @@ struct id {
   char* text;
   void* object;
   id *left, *right;
-  id (const char* t, void* o) : text(strdup(t)), object(o) {left = right = 0;}
+  id (const char* t, void* o) : text(fl_strdup(t)), object(o) {left = right = 0;}
   ~id();
 };
 
@@ -109,7 +110,7 @@ struct included {
   char *text;
   included *left, *right;
   included(const char *t) {
-    text = strdup(t);
+    text = fl_strdup(t);
     left = right = 0;
   }
   ~included();
diff --git fluid/file.cxx fluid/file.cxx
index dd2ef34..30335a2 100644
--- fluid/file.cxx
+++ fluid/file.cxx
@@ -25,6 +25,7 @@
 #include <stdarg.h>
 #include "alignment_panel.h"
 #include <FL/Fl.H>
+#include <FL/fl_string.h>
 #include "Fl_Widget_Type.h"
 
 ////////////////////////////////////////////////////////////////
@@ -405,19 +406,19 @@ static void read_children(Fl_Type *p, int paste) {
       goto CONTINUE;
     }
     if (!strcmp(c,"i18n_function")) {
-      i18n_function = strdup(read_word());
+      i18n_function = fl_strdup(read_word());
       goto CONTINUE;
     }
     if (!strcmp(c,"i18n_file")) {
-      i18n_file = strdup(read_word());
+      i18n_file = fl_strdup(read_word());
       goto CONTINUE;
     }
     if (!strcmp(c,"i18n_set")) {
-      i18n_set = strdup(read_word());
+      i18n_set = fl_strdup(read_word());
       goto CONTINUE;
     }
     if (!strcmp(c,"i18n_include")) {
-      i18n_include = strdup(read_word());
+      i18n_include = fl_strdup(read_word());
       goto CONTINUE;
     }
     if (!strcmp(c,"i18n_type"))
@@ -431,13 +432,13 @@ static void read_children(Fl_Type *p, int paste) {
       goto CONTINUE;
     }
     if (!strcmp(c,"header_name")) {
-      if (!header_file_set) header_file_name = strdup(read_word());
+      if (!header_file_set) header_file_name = fl_strdup(read_word());
       else read_word();
       goto CONTINUE;
     }
 
     if (!strcmp(c,"code_name")) {
-      if (!code_file_set) code_file_name = strdup(read_word());
+      if (!code_file_set) code_file_name = fl_strdup(read_word());
       else read_word();
       goto CONTINUE;
     }
diff --git fluid/fluid.cxx fluid/fluid.cxx
index 0cd6788..e9025a4 100644
--- fluid/fluid.cxx
+++ fluid/fluid.cxx
@@ -36,6 +36,7 @@
 #include <FL/Fl_Native_File_Chooser.H>
 #include <FL/Fl_Printer.H>
 #include <FL/fl_utf8.h>
+#include <FL/fl_string.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
@@ -1544,7 +1545,7 @@ show_shell_window() {
 
 void set_filename(const char *c) {
   if (filename) free((void *)filename);
-  filename = c ? strdup(c) : NULL;
+  filename = c ? fl_strdup(c) : NULL;
 
   if (filename && !batch_mode)
     update_history(filename);
diff --git fluid/print_panel.cxx fluid/print_panel.cxx
index f41cae2..c5e520f 100644
--- fluid/print_panel.cxx
+++ fluid/print_panel.cxx
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include "../src/flstring.h"
 #include <FL/Fl_Preferences.H>
+#include <FL/fl_string.h>
 extern Fl_Preferences fluid_prefs;
 
 Fl_Double_Window *print_panel=(Fl_Double_Window *)0;
@@ -531,7 +532,7 @@ void print_load() {
         }
         *qptr = '\0';
 
-        print_choice->add(qname, 0, 0, (void *)strdup(name), 0);
+        print_choice->add(qname, 0, 0, (void *)fl_strdup(name), 0);
       } else if (!strncmp(line, "system default destination: ", 28)) {
         if (sscanf(line + 28, "%s", defname) != 1) defname[0] = '\0';
       }
diff --git fluid/print_panel.fl fluid/print_panel.fl
index 1dd0861..e2042f5 100644
--- fluid/print_panel.fl
+++ fluid/print_panel.fl
@@ -29,6 +29,9 @@ decl {\#include <stdlib.h>} {private local
 decl {\#include "../src/flstring.h"} {private local
 }
 
+decl {\#include <FL/fl_string.h>} {private local
+}
+
 decl {\#include <FL/Fl_Preferences.H>} {private local
 }
 
@@ -307,7 +310,7 @@ if ((lpstat = popen("LC_MESSAGES=C LANG=C lpstat -p -d", "r")) != NULL) {
       }
       *qptr = '\\0';
 
-      print_choice->add(qname, 0, 0, (void *)strdup(name), 0);
+      print_choice->add(qname, 0, 0, (void *)fl_strdup(name), 0);
     } else if (!strncmp(line, "system default destination: ", 28)) {
       if (sscanf(line + 28, "%s", defname) != 1) defname[0] = '\\0';
     }
diff --git fluid/template_panel.cxx fluid/template_panel.cxx
index f46b85d..fc04495 100644
--- fluid/template_panel.cxx
+++ fluid/template_panel.cxx
@@ -25,6 +25,7 @@
 #include <FL/fl_ask.H>
 #include <FL/Fl_Shared_Image.H>
 #include <FL/Fl_Preferences.H>
+#include <FL/fl_string.h>
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #include <io.h>
 #else
@@ -257,7 +258,7 @@ void template_load() {
 
       // Add the template to the browser...
       snprintf(filename, sizeof(filename), "%s/%s", path, files[i]->d_name);
-      template_browser->add(name, strdup(filename));
+      template_browser->add(name, fl_strdup(filename));
     }
 
     free(files[i]);
diff --git fluid/template_panel.fl fluid/template_panel.fl
index 5da8874..b0d5b9f 100644
--- fluid/template_panel.fl
+++ fluid/template_panel.fl
@@ -29,6 +29,9 @@ decl {\#include <stdlib.h>} {private local
 decl {\#include "../src/flstring.h"} {private local
 }
 
+decl {\#include <FL/fl_string.h>} {private local
+}
+
 decl {\#include <errno.h>} {private local
 }
 
@@ -253,7 +256,7 @@ for (i = 0; i < num_files; i ++) {
 
     // Add the template to the browser...
     snprintf(filename, sizeof(filename), "%s/%s", path, files[i]->d_name);
-    template_browser->add(name, strdup(filename));
+    template_browser->add(name, fl_strdup(filename));
   }
 
   free(files[i]);
diff --git src/CMakeLists.txt src/CMakeLists.txt
index d3ef394..d5eee5d 100644
--- src/CMakeLists.txt
+++ src/CMakeLists.txt
@@ -157,6 +157,7 @@ set (CPPFILES
   fl_vertex.cxx
   screen_xywh.cxx
   fl_utf8.cxx
+  fl_string.cxx
   fl_encoding_latin1.cxx
   fl_encoding_mac_roman.cxx
 )
diff --git src/Fl_Check_Browser.cxx src/Fl_Check_Browser.cxx
index 6d80268..6f286e4 100644
--- src/Fl_Check_Browser.cxx
+++ src/Fl_Check_Browser.cxx
@@ -18,6 +18,7 @@
 #include <stdlib.h>
 #include "flstring.h"
 #include <FL/fl_draw.H>
+#include <FL/fl_string.h> // fl_strdup()
 #include <FL/Fl_Check_Browser.H>
 
 /* This uses a cache for faster access when you're scanning the list
@@ -243,7 +244,7 @@ int Fl_Check_Browser::add(char *s, int b) {
         p->prev = 0;
         p->checked = b;
         p->selected = 0;
-    p->text = strdup(s?s:"");
+    p->text = fl_strdup(s?s:"");
 
         if (b) {
                 nchecked_++;
diff --git src/Fl_File_Browser.cxx src/Fl_File_Browser.cxx
index cb92428..da70c87 100644
--- src/Fl_File_Browser.cxx
+++ src/Fl_File_Browser.cxx
@@ -34,6 +34,7 @@
 #include "Fl_System_Driver.H"
 #include <FL/fl_draw.H>
 #include <FL/filename.H>
+#include <FL/fl_string.h>
 #include <FL/Fl_Image.H>        // icon
 #include <stdio.h>
 #include <stdlib.h>
@@ -387,7 +388,7 @@ Fl_File_Browser::~Fl_File_Browser() {
  */
 void Fl_File_Browser::errmsg(const char* emsg) {
   if ( errmsg_ ) { free((void*)errmsg_); errmsg_ = NULL; }
-  errmsg_ = emsg ? strdup(emsg) : NULL;
+  errmsg_ = emsg ? fl_strdup(emsg) : NULL;
 }
 
 
diff --git src/Fl_File_Chooser2.cxx src/Fl_File_Chooser2.cxx
index ec04bd7..ddbb3e5 100644
--- src/Fl_File_Chooser2.cxx
+++ src/Fl_File_Chooser2.cxx
@@ -325,6 +325,7 @@
 #include <FL/platform.H>
 #include <FL/Fl_Shared_Image.H>
 #include <FL/fl_draw.H>
+#include <FL/fl_string.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -945,7 +946,7 @@ Fl_File_Chooser::filter(const char *p)          // I - Pattern(s)
   if (!p || !*p) p = "*";
 
   // Copy the pattern string...
-  copyp = strdup(p);
+  copyp = fl_strdup(p);
 
   // Separate the pattern string as necessary...
   showChoice->clear();
diff --git src/Fl_Help_View.cxx src/Fl_Help_View.cxx
index f6c6407..e27f81e 100644
--- src/Fl_Help_View.cxx
+++ src/Fl_Help_View.cxx
@@ -56,6 +56,7 @@
 #include <stdlib.h>
 #include <FL/fl_utf8.h>
 #include <FL/filename.H>        // fl_open_uri()
+#include <FL/fl_string.h>       // fl_strdup()
 #include "flstring.h"
 #include <ctype.h>
 #include <errno.h>
@@ -3404,7 +3405,7 @@ int Fl_Help_View::load(const char *f)
              "<P>Unable to follow the link \"%s\" - "
              "%s.</P></BODY>",
              localname, strerror(errno));
-    value_ = strdup(error);
+    value_ = fl_strdup(error);
     ret = -1;
   }
 
@@ -3543,7 +3544,7 @@ Fl_Help_View::value(const char *val)    // I - Text to view
   if (!val)
     return;
 
-  value_ = strdup(val);
+  value_ = fl_strdup(val);
 
   initial_load = 1;
   format();
diff --git src/Fl_Image_Reader.cxx src/Fl_Image_Reader.cxx
index 1f19379..f9a886b 100644
--- src/Fl_Image_Reader.cxx
+++ src/Fl_Image_Reader.cxx
@@ -22,6 +22,7 @@
 #include "Fl_Image_Reader.h"
 
 #include <FL/fl_utf8.h>
+#include <FL/fl_string.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -40,7 +41,7 @@
 int Fl_Image_Reader::open(const char *filename) {
   if (!filename)
     return -1;
-  pName = strdup(filename);
+  pName = fl_strdup(filename);
   if ( (pFile = fl_fopen(filename, "rb")) == NULL ) {
     return -1;
   }
@@ -51,7 +52,7 @@ int Fl_Image_Reader::open(const char *filename) {
 // Initialize the reader for memory access, name is copied and stored
 int Fl_Image_Reader::open(const char *imagename, const unsigned char *data) {
   if (imagename)
-    pName = strdup(imagename);
+    pName = fl_strdup(imagename);
   if (data) {
     pStart = pData = data;
     pIsData = 1;
diff --git src/Fl_MacOS_Sys_Menu_Bar.mm src/Fl_MacOS_Sys_Menu_Bar.mm
index 7f7abba..c589f81 100644
--- src/Fl_MacOS_Sys_Menu_Bar.mm
+++ src/Fl_MacOS_Sys_Menu_Bar.mm
@@ -17,6 +17,7 @@
 #if defined(__APPLE__)
 
 #include <FL/platform.H>
+#include <FL/fl_string.h>
 #include "drivers/Cocoa/Fl_MacOS_Sys_Menu_Bar_Driver.H"
 #include "flstring.h"
 #include <stdio.h>
@@ -291,7 +292,7 @@ static void setMenuFlags( NSMenu* mh, int miCnt, const Fl_Menu_Item *m )
 
 static char *remove_ampersand(const char *s)
 {
-  char *ret = strdup(s);
+  char *ret = fl_strdup(s);
   const char *p = s;
   char *q = ret;
   while(*p != 0) {
diff --git src/Fl_Menu_add.cxx src/Fl_Menu_add.cxx
index b2282b6..d5fdae9 100644
--- src/Fl_Menu_add.cxx
+++ src/Fl_Menu_add.cxx
@@ -25,6 +25,7 @@
 // string with a % sign in it!
 
 #include <FL/Fl_Menu_.H>
+#include <FL/fl_string.h>
 #include "flstring.h"
 #include <stdio.h>
 #include <stdlib.h>
@@ -62,7 +63,7 @@ static Fl_Menu_Item* array_insert(
   memmove(array+n+1, array+n, sizeof(Fl_Menu_Item)*(size-n));
   // create the new item:
   Fl_Menu_Item* m = array+n;
-  m->text = text ? strdup(text) : 0;
+  m->text = text ? fl_strdup(text) : 0;
   m->shortcut_ = 0;
   m->callback_ = 0;
   m->user_data_ = 0;
@@ -455,7 +456,7 @@ void Fl_Menu_::replace(int i, const char *str) {
   if (!alloc) copy(menu_);
   if (alloc > 1) {
     free((void *)menu_[i].text);
-      str = strdup(str?str:"");
+      str = fl_strdup(str?str:"");
   }
   menu_[i].text = str;
 }
diff --git src/Fl_Native_File_Chooser_GTK.cxx src/Fl_Native_File_Chooser_GTK.cxx
index 4de7343..16ed1f4 100644
--- src/Fl_Native_File_Chooser_GTK.cxx
+++ src/Fl_Native_File_Chooser_GTK.cxx
@@ -25,6 +25,7 @@
 #include <FL/Fl_Shared_Image.H>
 #include <FL/Fl_Image_Surface.H>
 #include <FL/fl_draw.H>
+#include <FL/fl_string.h>
 #include <dlfcn.h>   // for dlopen et al
 #include "drivers/X11/Fl_X11_System_Driver.H"
 
@@ -110,7 +111,7 @@ private:
     const char *filter; // a filter string of the chooser
     pair(Fl_GTK_Native_File_Chooser_Driver* c, const char *f) {
       running = c;
-      filter = strdup(f);
+      filter = fl_strdup(f);
     };
     ~pair() {
       free((char*)filter);
@@ -490,7 +491,7 @@ static char *extract_dir_from_path(const char *path)
   }
   if (*path != '/') return NULL;
   if (dir) free(dir);
-  dir = strdup(path);
+  dir = fl_strdup(path);
   do {
     char *p = strrchr(dir, '/');
     if (p == dir) p++;
@@ -710,7 +711,7 @@ int Fl_GTK_Native_File_Chooser_Driver::fl_gtk_chooser_wrapper()
   GtkFileFilter **filter_tab = NULL;
   if (_parsedfilt) {
     filter_tab = new GtkFileFilter*[_nfilters];
-    char *filter = strdup(_parsedfilt);
+    char *filter = fl_strdup(_parsedfilt);
     p = strtok(filter, "\t");
     int count = 0;
     while (p) {
diff --git src/Fl_Native_File_Chooser_MAC.mm src/Fl_Native_File_Chooser_MAC.mm
index 0f6191d..6ae29be 100644
--- src/Fl_Native_File_Chooser_MAC.mm
+++ src/Fl_Native_File_Chooser_MAC.mm
@@ -27,6 +27,7 @@
 #include <FL/Fl_Native_File_Chooser.H>
 #include <FL/Fl_File_Chooser.H>
 #include <FL/filename.H>
+#include <FL/fl_string.h>
 #define MAXFILTERS      80
 #import <Cocoa/Cocoa.h>
 
@@ -402,7 +403,7 @@ int Fl_Quartz_Native_File_Chooser_Driver::filters() const {
 #define UNLIKELYPREFIX "___fl_very_unlikely_prefix_"
 
 int Fl_Quartz_Native_File_Chooser_Driver::get_saveas_basename(void) {
-  char *q = strdup( [[[_panel URL] path] UTF8String] );
+  char *q = fl_strdup( [[[_panel URL] path] UTF8String] );
   if ( !(_options & Fl_Native_File_Chooser::SAVEAS_CONFIRM) ) {
     const char *d = [[[[_panel URL] path] stringByDeletingLastPathComponent] UTF8String];
     int l = (int)strlen(d) + 1;
@@ -520,7 +521,7 @@ static char *prepareMacFilter(int count, const char *filter, char **patterns) {
 // correspondingly changes the extension of the output file name
 {
   if (fl_mac_os_version < 100600) return; // because of setNameFieldStringValue and nameFieldStringValue
-  char *s = strdup([[(NSPopUpButton*)sender titleOfSelectedItem] UTF8String]);
+  char *s = fl_strdup([[(NSPopUpButton*)sender titleOfSelectedItem] UTF8String]);
   if (!s) return;
   char *p = strchr(s, '(');
   if (!p) p = s;
@@ -724,7 +725,7 @@ int Fl_Quartz_Native_File_Chooser_Driver::post() {
           char *p = _filt_patt[_filt_value];
           char *q = strchr(p, '.'); if(!q) q = p-1;
           do q++; while (*q==' ' || *q=='{');
-          p = strdup(q);
+          p = fl_strdup(q);
           q = strchr(p, ','); if (q) *q = 0;
           [_panel setAllowedFileTypes:[NSArray arrayWithObject:[NSString stringWithUTF8String:p]]];
           free(p);
diff --git src/Fl_Preferences.cxx src/Fl_Preferences.cxx
index e732701..11851c0 100644
--- src/Fl_Preferences.cxx
+++ src/Fl_Preferences.cxx
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include <stdarg.h>
 #include <FL/fl_utf8.h>
+#include <FL/fl_string.h>
 #include "flstring.h"
 
 
@@ -636,7 +637,7 @@ char Fl_Preferences::get( const char *key, char *&text, const char *defaultValue
   }
   if ( !v ) v = defaultValue;
   if ( v )
-    text = strdup( v );
+    text = fl_strdup( v );
   else
     text = 0;
   return ( v != defaultValue );
@@ -911,9 +912,9 @@ Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs, Root root, const char
   root_(root)
 {
   char *filename = Fl::system_driver()->preference_rootnode(prefs, root, vendor, application);
-  filename_    = filename ? strdup(filename) : 0L;
-  vendor_      = strdup(vendor);
-  application_ = strdup(application);
+  filename_    = filename ? fl_strdup(filename) : 0L;
+  vendor_      = fl_strdup(vendor);
+  application_ = fl_strdup(application);
   read();
 }
 
@@ -931,14 +932,14 @@ Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs, const char *path, con
     vendor = "unknown";
   if (!application) {
     application = "unknown";
-    filename_ = strdup(path);
+    filename_ = fl_strdup(path);
   } else {
     char filename[ FL_PATH_MAX ]; filename[0] = 0;
     snprintf(filename, sizeof(filename), "%s/%s.prefs", path, application);
-    filename_  = strdup(filename);
+    filename_  = fl_strdup(filename);
   }
-  vendor_      = strdup(vendor);
-  application_ = strdup(application);
+  vendor_      = fl_strdup(vendor);
+  application_ = fl_strdup(application);
   read();
 }
 
@@ -1112,7 +1113,7 @@ char Fl_Preferences::RootNode::getPath( char *path, int pathlen ) {
 // create a node that represents a group
 // - path must be a single word, prferable alnum(), dot and underscore only. Space is ok.
 Fl_Preferences::Node::Node( const char *path ) {
-  if ( path ) path_ = strdup( path ); else path_ = 0;
+  if ( path ) path_ = fl_strdup( path ); else path_ = 0;
   child_ = 0; next_ = 0; parent_ = 0;
   entry_ = 0;
   nEntry_ = NEntry_ = 0;
@@ -1225,7 +1226,7 @@ void Fl_Preferences::Node::setParent( Node *pn ) {
   pn->child_ = this;
   sprintf( nameBuffer, "%s/%s", pn->path_, path_ );
   free( path_ );
-  path_ = strdup( nameBuffer );
+  path_ = fl_strdup( nameBuffer );
 }
 
 // find the corresponding root node
@@ -1242,7 +1243,7 @@ Fl_Preferences::RootNode *Fl_Preferences::Node::findRoot() {
 // add a child to this node and set its path (try to find it first...)
 Fl_Preferences::Node *Fl_Preferences::Node::addChild( const char *path ) {
   sprintf( nameBuffer, "%s/%s", path_, path );
-  char *name = strdup( nameBuffer );
+  char *name = fl_strdup( nameBuffer );
   Node *nd = find( name );
   free( name );
   updateIndex();
@@ -1258,7 +1259,7 @@ void Fl_Preferences::Node::set( const char *name, const char *value )
       if ( strcmp( value, entry_[i].value ) != 0 ) {
         if ( entry_[i].value )
           free( entry_[i].value );
-        entry_[i].value = strdup( value );
+        entry_[i].value = fl_strdup( value );
         dirty_ = 1;
       }
       lastEntrySet = i;
@@ -1269,8 +1270,8 @@ void Fl_Preferences::Node::set( const char *name, const char *value )
     NEntry_ = NEntry_ ? NEntry_*2 : 10;
     entry_ = (Entry*)realloc( entry_, NEntry_ * sizeof(Entry) );
   }
-  entry_[ nEntry_ ].name = strdup( name );
-  entry_[ nEntry_ ].value = value?strdup( value ):0;
+  entry_[ nEntry_ ].name = fl_strdup( name );
+  entry_[ nEntry_ ].value = value?fl_strdup(value):0;
   lastEntrySet = nEntry_;
   nEntry_++;
   dirty_ = 1;
diff --git src/Fl_SVG_Image.cxx src/Fl_SVG_Image.cxx
index ca9644f..93aaee2 100644
--- src/Fl_SVG_Image.cxx
+++ src/Fl_SVG_Image.cxx
@@ -21,6 +21,7 @@
 #include <FL/Fl_SVG_Image.H>
 #include <FL/fl_utf8.h>
 #include <FL/fl_draw.H>
+#include <FL/fl_string.h>
 #include "Fl_Screen_Driver.H"
 #include <stdio.h>
 #include <stdlib.h>
@@ -152,7 +153,7 @@ void Fl_SVG_Image::init_(const char *filename, const char *in_filedata, Fl_SVG_I
     if (!filedata) ld(ERR_FILE_ACCESS);
   } else {
     // XXX: Make internal copy -- nsvgParse() modifies filedata during parsing (!)
-    filedata = in_filedata ? strdup(in_filedata) : NULL;
+    filedata = in_filedata ? fl_strdup(in_filedata) : NULL;
   }
   if (filedata) {
     counted_svg_image_->svg_image = nsvgParse(filedata, "px", 96);
diff --git src/Fl_System_Driver.H src/Fl_System_Driver.H
index 77a5897..73f197f 100644
--- src/Fl_System_Driver.H
+++ src/Fl_System_Driver.H
@@ -98,6 +98,9 @@ public:
   virtual int putenv(const char *var) {return -1;}
   virtual int open(const char* f, int oflags, int pmode) {return -1;}
 
+  // implement these to support cross-platform string operations
+  virtual char *strdup(const char *s) {return NULL;}
+
   // Note: the default implementation ignores the 'binary' argument.
   // Some platforms (notably Windows) may use this argument.
   virtual int open_ext(const char* f, int binary, int oflags, int pmode) {
diff --git src/Fl_Text_Buffer.cxx src/Fl_Text_Buffer.cxx
index 9691d7a..476f1ec 100644
--- src/Fl_Text_Buffer.cxx
+++ src/Fl_Text_Buffer.cxx
@@ -17,6 +17,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <FL/fl_utf8.h>
+#include <FL/fl_string.h>
 #include "flstring.h"
 #include <ctype.h>
 #include <FL/Fl.H>
@@ -462,7 +463,7 @@ int Fl_Text_Buffer::undo(int *cursorPos)
   if (xlen && ilen) {
     undobuffersize(ilen + 1);
     undobuffer[ilen] = 0;
-    char *tmp = strdup(undobuffer);
+    char *tmp = fl_strdup(undobuffer);
     replace(b, undoat, tmp);
     if (cursorPos)
       *cursorPos = mCursorPosHint;
diff --git src/Fl_Text_Display.cxx src/Fl_Text_Display.cxx
index 8b4450c..34f6f38 100644
--- src/Fl_Text_Display.cxx
+++ src/Fl_Text_Display.cxx
@@ -20,10 +20,11 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <FL/fl_utf8.h>
+#include <FL/fl_string.h>     // fl_strdup()
 #include "flstring.h"
 #include <limits.h>
 #include <ctype.h>
-#include <string.h>     // strdup()
+#include <string.h>
 #include <FL/Fl.H>
 #include <FL/platform.H>
 #include <FL/Fl_Text_Buffer.H>
@@ -171,7 +172,7 @@ Fl_Text_Display::Fl_Text_Display(int X, int Y, int W, int H, const char* l)
   linenumber_fgcolor_ = FL_INACTIVE_COLOR;
   linenumber_bgcolor_ = 53;     // ~90% gray
   linenumber_align_   = FL_ALIGN_RIGHT;
-  linenumber_format_  = strdup("%d");
+  linenumber_format_  = fl_strdup("%d");
 
   // Method calls -- only AFTER all members initialized
   color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR);
@@ -326,7 +327,7 @@ Fl_Align Fl_Text_Display::linenumber_align() const {
 */
 void Fl_Text_Display::linenumber_format(const char* val) {
   if ( linenumber_format_ ) free((void*)linenumber_format_);
-  linenumber_format_ = val ? strdup(val) : 0;
+  linenumber_format_ = val ? fl_strdup(val) : 0;
 }
 
 /**
diff --git src/Fl_Tooltip.cxx src/Fl_Tooltip.cxx
index 53fcdb1..220e460 100644
--- src/Fl_Tooltip.cxx
+++ src/Fl_Tooltip.cxx
@@ -18,10 +18,10 @@
 #include <FL/fl_draw.H>
 #include <FL/Fl_Menu_Window.H>
 #include <FL/Fl.H>
+#include <FL/fl_string.h>
 #include "Fl_System_Driver.H"
 
 #include <stdio.h>
-#include <string.h>   // strdup()
 
 float     Fl_Tooltip::delay_ = 1.0f;
 float     Fl_Tooltip::hidedelay_ = 12.0f;
@@ -379,7 +379,7 @@ void Fl_Widget::copy_tooltip(const char *text) {
   if (flags() & COPIED_TOOLTIP) free((void *)(tooltip_));
   if (text) {
     set_flag(COPIED_TOOLTIP);
-    tooltip_ = strdup(text);
+    tooltip_ = fl_strdup(text);
   } else {
     clear_flag(COPIED_TOOLTIP);
     tooltip_ = (char *)0;
diff --git src/Fl_Tree.cxx src/Fl_Tree.cxx
index ec1d481..5dab99c 100644
--- src/Fl_Tree.cxx
+++ src/Fl_Tree.cxx
@@ -6,6 +6,7 @@
 
 #include <FL/Fl_Tree.H>
 #include <FL/Fl_Preferences.H>
+#include <FL/fl_string.h>
 
 //////////////////////
 // Fl_Tree.cxx
@@ -2643,7 +2644,7 @@ void Fl_Tree::load(Fl_Preferences &prefs) {
   n = prefs.entries();
   for (i=0; i<n; i++) {
     // We must remove all fwd slashes in the key and value strings. Replace with backslash.
-    char *key = strdup(prefs.entry(i));
+    char *key = fl_strdup(prefs.entry(i));
     int kn = (int) strlen(key);
     for (j=0; j<kn; j++) {
       if (key[j]=='/') key[j]='\\';
diff --git src/Fl_Tree_Item.cxx src/Fl_Tree_Item.cxx
index 3df432c..9861127 100644
--- src/Fl_Tree_Item.cxx
+++ src/Fl_Tree_Item.cxx
@@ -3,10 +3,12 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <FL/Fl.H>
 #include <FL/Fl_Widget.H>
 #include <FL/Fl_Tree_Item.H>
 #include <FL/Fl_Tree_Prefs.H>
 #include <FL/Fl_Tree.H>
+#include <FL/fl_string.h>
 
 //////////////////////
 // Fl_Tree_Item.cxx
@@ -103,7 +105,7 @@ Fl_Tree_Item::~Fl_Tree_Item() {
 /// Copy constructor.
 Fl_Tree_Item::Fl_Tree_Item(const Fl_Tree_Item *o) {
   _tree             = o->_tree;
-  _label        = o->label() ? strdup(o->label()) : 0;
+  _label        = o->label() ? fl_strdup(o->label()) : 0;
   _labelfont    = o->labelfont();
   _labelsize    = o->labelsize();
   _labelfgcolor = o->labelfgcolor();
@@ -154,7 +156,7 @@ void Fl_Tree_Item::show_self(const char *indent) const {
 ///
 void Fl_Tree_Item::label(const char *name) {
   if ( _label ) { free((void*)_label); _label = 0; }
-  _label = name ? strdup(name) : 0;
+  _label = name ? fl_strdup(name) : 0;
   recalc_tree();                // may change label geometry
 }
 
diff --git src/Fl_Widget.cxx src/Fl_Widget.cxx
index 25a4bb9..8b4de1a 100644
--- src/Fl_Widget.cxx
+++ src/Fl_Widget.cxx
@@ -19,6 +19,7 @@
 #include <FL/Fl_Group.H>
 #include <FL/Fl_Tooltip.H>
 #include <FL/fl_draw.H>
+#include <FL/fl_string.h>
 #include <stdlib.h>
 #include "flstring.h"
 
@@ -291,7 +292,7 @@ void Fl_Widget::copy_label(const char *a) {
   if ((flags() & COPIED_LABEL) && (label_.value == a))
     return;
   if (a) {
-    label(strdup(a));
+    label(fl_strdup(a));
     set_flag(COPIED_LABEL);
   } else {
     label(0);
diff --git src/Fl_Window.cxx src/Fl_Window.cxx
index dee4b32..a999511 100644
--- src/Fl_Window.cxx
+++ src/Fl_Window.cxx
@@ -28,6 +28,7 @@
 #include <FL/Fl_Window.H>
 #include <FL/Fl_Tooltip.H>
 #include <FL/fl_draw.H>
+#include <FL/fl_string.h>
 #include <stdlib.h>
 #include "flstring.h"
 
@@ -225,7 +226,7 @@ void Fl_Window::default_xclass(const char *xc)
     default_xclass_ = 0L;
   }
   if (xc) {
-    default_xclass_ = strdup(xc);
+    default_xclass_ = fl_strdup(xc);
   }
 }
 
@@ -260,7 +261,7 @@ void Fl_Window::xclass(const char *xc)
     xclass_ = 0L;
   }
   if (xc) {
-    xclass_ = strdup(xc);
+    xclass_ = fl_strdup(xc);
     if (!default_xclass_) {
       default_xclass(xc);
     }
diff --git src/Fl_cocoa.mm src/Fl_cocoa.mm
index 934dd2f..50c658e 100644
--- src/Fl_cocoa.mm
+++ src/Fl_cocoa.mm
@@ -30,6 +30,7 @@ extern "C" {
 #include <FL/Fl_Printer.H>
 #include <FL/fl_draw.H>
 #include <FL/Fl_Rect.H>
+#include <FL/fl_string.h>
 #include "drivers/Quartz/Fl_Quartz_Graphics_Driver.H"
 #include "drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.H"
 #include "drivers/Cocoa/Fl_Cocoa_Screen_Driver.H"
@@ -1587,7 +1588,7 @@ static void drain_dropped_files_list() {
     return;
   }
   NSString *s = (NSString*)[dropped_files_list objectAtIndex:0];
-  char *fname = strdup([s UTF8String]);
+  char *fname = fl_strdup([s UTF8String]);
   [dropped_files_list removeObjectAtIndex:0];
   if ([dropped_files_list count] == 0) {
     [dropped_files_list release];
@@ -3529,7 +3530,7 @@ static int get_plain_text_from_clipboard(int clipboard)
                                                         [data length],
                                                         [found isEqualToString:@"public.utf16-plain-text"] ? kCFStringEncodingUnicode : kCFStringEncodingMacRoman,
                                                         false);
-        aux_c = strdup([auxstring UTF8String]);
+        aux_c = fl_strdup([auxstring UTF8String]);
         [auxstring release];
         len = strlen(aux_c) + 1;
       }
diff --git src/Fl_get_system_colors.cxx src/Fl_get_system_colors.cxx
index e1b7fc2..73388c8 100644
--- src/Fl_get_system_colors.cxx
+++ src/Fl_get_system_colors.cxx
@@ -21,6 +21,7 @@
 #include <FL/platform.H>
 #include <FL/math.h>
 #include <FL/fl_utf8.h>
+#include <FL/fl_string.h>
 #include "flstring.h"
 #include <stdio.h>
 #include <stdlib.h>
@@ -163,9 +164,9 @@ int Fl::scheme(const char *s) {
 
   if (s) {
     if (!fl_ascii_strcasecmp(s, "none") || !fl_ascii_strcasecmp(s, "base") || !*s) s = 0;
-    else if (!fl_ascii_strcasecmp(s, "gtk+")) s = strdup("gtk+");
-    else if (!fl_ascii_strcasecmp(s, "plastic")) s = strdup("plastic");
-    else if (!fl_ascii_strcasecmp(s, "gleam")) s = strdup("gleam");
+    else if (!fl_ascii_strcasecmp(s, "gtk+")) s = fl_strdup("gtk+");
+    else if (!fl_ascii_strcasecmp(s, "plastic")) s = fl_strdup("plastic");
+    else if (!fl_ascii_strcasecmp(s, "gleam")) s = fl_strdup("gleam");
     else s = 0;
   }
   if (scheme_) free((void*)scheme_);
diff --git src/Fl_win32.cxx src/Fl_win32.cxx
index d234f7a..e0d5c9f 100644
--- src/Fl_win32.cxx
+++ src/Fl_win32.cxx
@@ -60,6 +60,7 @@ void fl_cleanup_dc_list(void);
 #include "drivers/WinAPI/Fl_WinAPI_Screen_Driver.H"
 #include "drivers/GDI/Fl_GDI_Graphics_Driver.H"
 #include <FL/fl_utf8.h>
+#include <FL/fl_string.h>
 #include <FL/Fl_Window.H>
 #include <FL/fl_draw.H>
 #include <FL/Enumerations.H>
@@ -1919,7 +1920,7 @@ public:
       NName += 5;
       name = (char **)realloc(name, NName * sizeof(char *));
     }
-    name[nName++] = strdup(n);
+    name[nName++] = fl_strdup(n);
   }
   char has_name(const char *n) {
     int i;
diff --git src/Makefile src/Makefile
index 123aef0..c1409a5 100644
--- src/Makefile
+++ src/Makefile
@@ -160,7 +160,8 @@ CPPFILES = \
 	fl_symbols.cxx \
 	fl_vertex.cxx \
 	screen_xywh.cxx \
-	fl_utf8.cxx
+	fl_utf8.cxx \
+	fl_string.cxx
 
 OBJCPPFILES = \
 	Fl_cocoa.mm \
diff --git src/drivers/Android/Fl_Android_Application.cxx src/drivers/Android/Fl_Android_Application.cxx
index 8705354..793ebb5 100644
--- src/drivers/Android/Fl_Android_Application.cxx
+++ src/drivers/Android/Fl_Android_Application.cxx
@@ -25,6 +25,7 @@
 
 #include <FL/platform.H>
 #include <FL/fl_draw.H>
+#include <FL/fl_string.h>
 
 #include <jni.h>
 
@@ -376,7 +377,7 @@ void *Fl_Android_Application::thread_entry(void* param)
   pthread_cond_broadcast(&pCond);
   pthread_mutex_unlock(&pMutex);
 
-  char *argv[] = { strdup(pActivity->obbPath), 0 };
+  char *argv[] = { fl_strdup(pActivity->obbPath), 0 };
   main(1, argv);
 
   destroy();
diff --git src/drivers/Android/Fl_Android_System_Driver.H src/drivers/Android/Fl_Android_System_Driver.H
index 198d7a2..84f8262 100644
--- src/drivers/Android/Fl_Android_System_Driver.H
+++ src/drivers/Android/Fl_Android_System_Driver.H
@@ -22,6 +22,7 @@
 #ifndef FL_ANDROID_SYSTEM_DRIVER_H
 #define FL_ANDROID_SYSTEM_DRIVER_H
 
+#include <FL/fl_string.h>
 #include "../../Fl_System_Driver.H"
 #include <stdarg.h>
 
@@ -46,7 +47,7 @@ public:
   virtual void fatal(const char *format, va_list args);
   virtual char *utf2mbcs(const char *s);
   virtual char *getenv(const char *var);
-  virtual int putenv(const char *var) { return ::putenv(strdup(var)); }
+  virtual int putenv(const char *var) { return ::putenv(fl_strdup(var)); }
   virtual int open(const char *fnam, int oflags, int pmode);
   virtual int open_ext(const char *fnam, int binary, int oflags, int pmode);
   virtual FILE *fopen(const char *fnam, const char *mode);
diff --git src/drivers/Android/Fl_Android_System_Driver.cxx src/drivers/Android/Fl_Android_System_Driver.cxx
index 0fa9671..d25e964 100644
--- src/drivers/Android/Fl_Android_System_Driver.cxx
+++ src/drivers/Android/Fl_Android_System_Driver.cxx
@@ -18,6 +18,7 @@
 #include "Fl_Android_System_Driver.H"
 #include <FL/Fl.H>
 #include <FL/fl_utf8.h>
+#include <FL/fl_string.h>
 #include <FL/filename.H>
 #include <FL/Fl_File_Browser.H>
 #include <FL/Fl_File_Icon.H>
@@ -545,7 +546,7 @@ Fl_WinAPI_System_Driver::filename_relative(char *to,    // O - Relative filename
   char          *newslash;              // Directory separator
   const char    *slash;                 // Directory separator
   char          *cwd = 0L, *cwd_buf = 0L;
-  if (base) cwd = cwd_buf = strdup(base);
+  if (base) cwd = cwd_buf = fl_strdup(base);
 
   // return if "from" is not an absolute path
   if (from[0] == '\0' ||
diff --git src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm
index ab3d90f..2a09556 100644
--- src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm
+++ src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm
@@ -26,6 +26,7 @@
 #include <FL/platform.H>
 #include <FL/fl_ask.H>
 #include <FL/fl_draw.H>
+#include <FL/fl_string.h>
 #import <Cocoa/Cocoa.h>
 
 typedef OSStatus (*PMSessionSetDocumentFormatGeneration_type)(
@@ -196,7 +197,7 @@ int Fl_Cocoa_Printer_Driver::begin_job (int pagecount, int *frompage, int *topag
     if (perr_message) {
       NSError *nserr = [NSError errorWithDomain:NSCocoaErrorDomain code:status userInfo:nil];
       NSString *s = [nserr localizedDescription];
-      if (s) *perr_message = strdup([s UTF8String]);
+      if (s) *perr_message = fl_strdup([s UTF8String]);
     }
     return 2;
   }
diff --git src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx
index 1e2b492..3371c4e 100644
--- src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx
+++ src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx
@@ -41,6 +41,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <FL/fl_string.h>
 
 // This function fills in the FLTK font table with all the fonts that
 // are found on the X server.  It tries to place the fonts into families
@@ -98,12 +99,12 @@ enumcbw(CONST LOGFONTW    *lpelf,
     if (!strcmp(Fl::get_font_name((Fl_Font)i),n)) {free(n);return 1;}
   char buffer[LF_FACESIZE + 1];
   strcpy(buffer+1, n);
-  buffer[0] = ' '; Fl::set_font((Fl_Font)(fl_free_font++), strdup(buffer));
+  buffer[0] = ' '; Fl::set_font((Fl_Font)(fl_free_font++), fl_strdup(buffer));
   if (lpelf->lfWeight <= 400)
-    buffer[0] = 'B', Fl::set_font((Fl_Font)(fl_free_font++), strdup(buffer));
-  buffer[0] = 'I'; Fl::set_font((Fl_Font)(fl_free_font++), strdup(buffer));
+    buffer[0] = 'B', Fl::set_font((Fl_Font)(fl_free_font++), fl_strdup(buffer));
+  buffer[0] = 'I'; Fl::set_font((Fl_Font)(fl_free_font++), fl_strdup(buffer));
   if (lpelf->lfWeight <= 400)
-    buffer[0] = 'P', Fl::set_font((Fl_Font)(fl_free_font++), strdup(buffer));
+    buffer[0] = 'P', Fl::set_font((Fl_Font)(fl_free_font++), fl_strdup(buffer));
   free(n);
   return 1;
 } /* enumcbw */
diff --git src/drivers/Posix/Fl_Posix_System_Driver.H src/drivers/Posix/Fl_Posix_System_Driver.H
index 55255b8..3f4cf72 100644
--- src/drivers/Posix/Fl_Posix_System_Driver.H
+++ src/drivers/Posix/Fl_Posix_System_Driver.H
@@ -38,6 +38,7 @@
  - directory and file access
  - system time and system timer
  - multithreading
+ - string management
  */
 
 class Fl_Posix_System_Driver : public Fl_System_Driver
@@ -74,6 +75,7 @@ public:
   virtual const char *home_directory_name() { return ::getenv("HOME"); }
   virtual int dot_file_hidden() {return 1;}
   virtual void gettime(time_t *sec, int *usec);
+  virtual char* strdup(const char *s) {return ::strdup(s);}
 };
 
 #endif // FL_POSIX_SYSTEM_DRIVER_H
diff --git src/drivers/Posix/Fl_Posix_System_Driver.cxx src/drivers/Posix/Fl_Posix_System_Driver.cxx
index d39ea6c..9f255f3 100644
--- src/drivers/Posix/Fl_Posix_System_Driver.cxx
+++ src/drivers/Posix/Fl_Posix_System_Driver.cxx
@@ -20,6 +20,7 @@
 #include <FL/Fl_File_Browser.H>
 #include <FL/Fl_File_Icon.H>
 #include <FL/filename.H>
+#include <FL/fl_string.h>
 #include <FL/Fl.H>
 #include <locale.h>
 #include <stdio.h>
@@ -65,7 +66,7 @@ void *Fl_Posix_System_Driver::dlopen(const char *filename)
   ptr = double_dlopen(filename);
 #  ifdef __APPLE_CC__ // allows testing on Darwin + XQuartz + fink
   if (!ptr) {
-    char *f_dylib = strdup(filename);
+    char *f_dylib = fl_strdup(filename);
     strcpy(strrchr(f_dylib, '.'), ".dylib");
     char path[FL_PATH_MAX];
     sprintf(path, "/sw/lib/%s", f_dylib);
diff --git src/drivers/PostScript/Fl_PostScript.cxx src/drivers/PostScript/Fl_PostScript.cxx
index b7b10da..5adf205 100644
--- src/drivers/PostScript/Fl_PostScript.cxx
+++ src/drivers/PostScript/Fl_PostScript.cxx
@@ -23,6 +23,7 @@
 #include <FL/Fl_PostScript.H>
 #include <FL/Fl_Native_File_Chooser.H>
 #include "../../Fl_System_Driver.H"
+#include <FL/fl_string.h>
 #include <stdarg.h>
 #include <time.h>
 
@@ -83,7 +84,7 @@ int Fl_PostScript_File_Device::begin_job (int pagecount, enum Fl_Paged_Device::P
   Fl_PostScript_Graphics_Driver *ps = driver();
   ps->output = fl_fopen(fnfc.filename(), "w");
   if(ps->output == NULL) return 2;
-  ps->ps_filename_ = strdup(fnfc.filename());
+  ps->ps_filename_ = fl_strdup(fnfc.filename());
   ps->start_postscript(pagecount, format, layout);
   this->set_current();
   return 0;
diff --git src/drivers/Quartz/Fl_Quartz_Graphics_Driver_font.cxx src/drivers/Quartz/Fl_Quartz_Graphics_Driver_font.cxx
index e6352af..fe43f0c 100644
--- src/drivers/Quartz/Fl_Quartz_Graphics_Driver_font.cxx
+++ src/drivers/Quartz/Fl_Quartz_Graphics_Driver_font.cxx
@@ -79,6 +79,7 @@
 #include <FL/Fl.H>
 #include <FL/platform.H>
 #include <FL/fl_utf8.h> // for fl_utf8toUtf16()
+#include <FL/fl_string.h> // fl_strdup()
 
 Fl_Fontdesc* fl_fonts = NULL;
 
@@ -682,7 +683,7 @@ Fl_Font Fl_Quartz_Graphics_Driver::ADD_SUFFIX(set_fonts, _CoreText)(const char*
     CFRelease(font);
     static char fname[200];
     CFStringGetCString(cfname, fname, sizeof(fname), kCFStringEncodingUTF8);
-    tabfontnames[i] = strdup(fname); // never free'ed
+    tabfontnames[i] = fl_strdup(fname); // never free'ed
     CFRelease(cfname);
   }
   CFRelease(arrayref);
@@ -869,7 +870,7 @@ Fl_Font Fl_Quartz_Graphics_Driver::ADD_SUFFIX(set_fonts, _ATSU)(const char* xsta
       oName[511] = 0;
     else
       oName[actualLength] = 0;
-    Fl::set_font((Fl_Font)(fl_free_font++), strdup(oName));
+    Fl::set_font((Fl_Font)(fl_free_font++), fl_strdup(oName));
     //  free(oName);
   }
   free(oFontIDs);
diff --git src/drivers/SVG/Fl_SVG_File_Surface.cxx src/drivers/SVG/Fl_SVG_File_Surface.cxx
index d0946da..5106c64 100644
--- src/drivers/SVG/Fl_SVG_File_Surface.cxx
+++ src/drivers/SVG/Fl_SVG_File_Surface.cxx
@@ -28,6 +28,8 @@
 #include <FL/Fl_RGB_Image.H>
 #include <FL/Fl_Pixmap.H>
 #include <FL/Fl_Bitmap.H>
+#include <FL/fl_string.h>
+
 extern "C" {
 #if defined(HAVE_LIBPNG)
 #  ifdef HAVE_PNG_H
@@ -137,7 +139,7 @@ Fl_SVG_Graphics_Driver::Fl_SVG_Graphics_Driver(FILE *f) {
   clip_count_ = 0;
   clip_ = NULL;
   user_dash_array_ = 0;
-  dasharray_ = strdup("none");
+  dasharray_ = fl_strdup("none");
   p_size = 0;
   p = NULL;
   last_rgb_name_ = NULL;
@@ -205,13 +207,13 @@ void Fl_SVG_Graphics_Driver::compute_dasharray(float s, char *dashes) {
       sprintf(dasharray_+strlen(dasharray_), "%.3f,", (*p)/s);
     }
     dasharray_[strlen(dasharray_) - 1] = 0;
-    if (user_dash_array_ != dashes) user_dash_array_ = strdup(dashes);
+    if (user_dash_array_ != dashes) user_dash_array_ = fl_strdup(dashes);
     return;
   }
   int dash_part = line_style_ & 0xFF;
   if (dash_part == FL_SOLID)  {
     if (dasharray_ && strcmp(dasharray_, "none")) free(dasharray_);
-    dasharray_ = strdup("none");
+    dasharray_ = fl_strdup("none");
   } else {
     int cap_part = (line_style_ & 0xF00);
     bool is_flat = (cap_part == FL_CAP_FLAT || cap_part == 0);
@@ -458,7 +460,7 @@ void Fl_SVG_Graphics_Driver::define_rgb_png(Fl_RGB_Image *rgb, const char *name,
   }
   if (name) {
     if (last_rgb_name_) free(last_rgb_name_);
-    last_rgb_name_ = strdup(name);
+    last_rgb_name_ = fl_strdup(name);
   }
   float f = rgb->data_w() > rgb->data_h() ? float(rgb->w()) / rgb->data_w(): float(rgb->h()) / rgb->data_h();
   if (name) fprintf(out_, "<defs><image id=\"%s\" ", name);
@@ -547,7 +549,7 @@ static void term_destination(jpeg_compress_struct *cinfo) {
 void Fl_SVG_Graphics_Driver::define_rgb_jpeg(Fl_RGB_Image *rgb, const char *name, int x, int y) {
   if (name) {
     if (last_rgb_name_) free(last_rgb_name_);
-    last_rgb_name_ = strdup(name);
+    last_rgb_name_ = fl_strdup(name);
   }
   float f = rgb->data_w() > rgb->data_h() ? float(rgb->w()) / rgb->data_w(): float(rgb->h()) / rgb->data_h();
   if (name) fprintf(out_, "<defs><image id=\"%s\" ", name);
diff --git src/drivers/WinAPI/Fl_WinAPI_System_Driver.H src/drivers/WinAPI/Fl_WinAPI_System_Driver.H
index 91b230d..049e6c1 100644
--- src/drivers/WinAPI/Fl_WinAPI_System_Driver.H
+++ src/drivers/WinAPI/Fl_WinAPI_System_Driver.H
@@ -24,6 +24,7 @@
 
 #include "../../Fl_System_Driver.H"
 #include <stdarg.h>
+#include <string.h>	// strdup
 
 /*
  Move everything here that manages the system interface.
@@ -34,6 +35,7 @@
  - directory and file access
  - system time and system timer
  - multithreading
+ - string management
  */
 
 class Fl_WinAPI_System_Driver : public Fl_System_Driver
@@ -116,6 +118,7 @@ public:
   virtual void remove_fd(int, int when);
   virtual void remove_fd(int);
   virtual void gettime(time_t *sec, int *usec);
+  virtual char* strdup(const char *s) { return ::_strdup(s); }
 };
 
 #endif // FL_WINAPI_SYSTEM_DRIVER_H
diff --git src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx
index 592e192..d37ec62 100644
--- src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx
+++ src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx
@@ -18,6 +18,7 @@
 #include "Fl_WinAPI_System_Driver.H"
 #include <FL/Fl.H>
 #include <FL/fl_utf8.h>
+#include <FL/fl_string.h>	// fl_strdup()
 #include <FL/filename.H>
 #include <FL/Fl_File_Browser.H>
 #include <FL/Fl_File_Icon.H>
@@ -548,7 +549,7 @@ Fl_WinAPI_System_Driver::filename_relative(char *to,    // O - Relative filename
   char          *newslash;              // Directory separator
   const char    *slash;                 // Directory separator
   char          *cwd = 0L, *cwd_buf = 0L;
-  if (base) cwd = cwd_buf = strdup(base);
+  if (base) cwd = cwd_buf = fl_strdup(base);
 
   // return if "from" is not an absolute path
   if (from[0] == '\0' ||
diff --git src/drivers/X11/Fl_X11_System_Driver.cxx src/drivers/X11/Fl_X11_System_Driver.cxx
index 28827bc..8a308bd 100644
--- src/drivers/X11/Fl_X11_System_Driver.cxx
+++ src/drivers/X11/Fl_X11_System_Driver.cxx
@@ -17,6 +17,7 @@
 
 #include "Fl_X11_System_Driver.H"
 #include <FL/Fl_File_Browser.H>
+#include <FL/fl_string.h>	// fl_strdup
 #include "../../flstring.h"
 
 #include <X11/Xlib.h>
@@ -592,7 +593,7 @@ bool Fl_X11_System_Driver::probe_for_GTK(int major, int minor, void **ptr_gtk) {
   char *before = NULL;
   // record in "before" the calling program's current locale
   char *p = setlocale(LC_ALL, NULL);
-  if (p) before = strdup(p);
+  if (p) before = fl_strdup(p);
   int ac = 0;
   init_f(&ac, NULL); // may change the locale
   if (before) {
diff --git src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx
index 8b37845..9251eaf 100644
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx
@@ -20,6 +20,7 @@
 #include <FL/Fl.H>
 #include <FL/fl_draw.H>
 #include <FL/platform.H>
+#include <FL/fl_string.h>
 #include "Fl_Font.H"
 
 #include <stdio.h>
@@ -305,7 +306,7 @@ Fl_Font Fl_Xlib_Graphics_Driver::set_fonts(const char* xstarname) {
         if (fl_fonts[j].name && !strcmp(fl_fonts[j].name, p)) break;
       } else */{
         j = fl_free_font++;
-        if (p == canon) p = strdup(p); else used_xlist = 1;
+        if (p == canon) p = fl_strdup(p); else used_xlist = 1;
         Fl::set_font((Fl_Font)j, p);
         break;
       }
@@ -521,7 +522,7 @@ static char *put_font_size(const char *n, int size)
         const char *f;
         char *name;
         int nbf = 1;
-        name = strdup(n);
+        name = fl_strdup(n);
         while (name[i]) {
                 if (name[i] == ',') {nbf++; name[i] = '\0';}
                 i++;
diff --git src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx
index 5a80904..6b42b88 100644
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx
@@ -20,6 +20,7 @@
 #include "Fl_Xlib_Graphics_Driver.H"
 #include <FL/Fl.H>
 #include <FL/fl_draw.H>
+#include <FL/fl_string.h>	// fl_strdup()
 #include <FL/platform.H>
 #include "Fl_Font.H"
 
@@ -423,7 +424,7 @@ Fl_Font Fl_Xlib_Graphics_Driver::set_fonts(const char* pattern_name)
       }
       else
       { // The listed name has been modified
-        full_list[j] = strdup(first);
+        full_list[j] = fl_strdup(first);
         // Free the font name storage
         free (font);
       }
@@ -451,7 +452,7 @@ Fl_Font Fl_Xlib_Graphics_Driver::set_fonts(const char* pattern_name)
         make_raw_name(xft_name, full_list[j]);
         // NOTE: This just adds on AFTER the default fonts - no attempt is made
         // to identify already loaded fonts. Is this bad?
-        stored_name = strdup(xft_name);
+        stored_name = fl_strdup(xft_name);
         Fl::set_font((Fl_Font)(j + FL_FREE_FONT), stored_name);
         fl_free_font ++;
 
@@ -552,7 +553,7 @@ static XftFont* fontopen(const char* name, /*Fl_Fontsize*/double size, bool core
     }
 
     if(comma_count) { // multiple comma-separated names were passed
-      char *local_name = strdup(name); // duplicate the full name so we can edit the copy
+      char *local_name = fl_strdup(name); // duplicate the full name so we can edit the copy
       char *curr = local_name; // points to first name in string
       char *nxt; // next name in string
       do {
@@ -681,7 +682,7 @@ static XftFont* fontopen(const char* name, /*Fl_Fontsize*/double size, bool core
      * XLFD's to construct a "super-pattern" that incorporates attributes from all
      * XLFD's and use that to perform a XftFontMatch(). Maybe...
      */
-    char *local_name = strdup(name);
+    char *local_name = fl_strdup(name);
     if(comma_count) { // This means we were passed multiple XLFD's
       char *pc = strchr(local_name, ',');
       *pc = 0; // terminate the XLFD at the first comma
@@ -1087,7 +1088,7 @@ static XFontStruct* load_xfont_for_xft2(Fl_Graphics_Driver *driver) {
   const char *weight = wt_med; // no specifc weight requested - accept any
   char slant = 'r';   // regular non-italic by default
   char xlfd[128];     // we will put our synthetic XLFD in here
-  char *pc = strdup(fl_fonts[fnum].name); // what font were we asked for?
+  char *pc = fl_strdup(fl_fonts[fnum].name); // what font were we asked for?
 #if USE_PANGO
   char *p = pc + 1;
   while (*p) { *p = tolower(*p); p++; }
diff --git src/filename_absolute.cxx src/filename_absolute.cxx
index 67beb50..e39da32 100644
--- src/filename_absolute.cxx
+++ src/filename_absolute.cxx
@@ -22,6 +22,7 @@
 
 #include <FL/filename.H>
 #include <FL/Fl.H>
+#include <FL/fl_string.h>
 #include "Fl_System_Driver.H"
 #include <stdlib.h>
 #include "flstring.h"
@@ -162,7 +163,7 @@ Fl_System_Driver::filename_relative(char *to,   // O - Relative filename
   char          *newslash;              // Directory separator
   const char    *slash;                 // Directory separator
   char          *cwd = 0L, *cwd_buf = 0L;
-  if (base) cwd = cwd_buf = strdup(base);
+  if (base) cwd = cwd_buf = fl_strdup(base);
 
   // return if "from" is not an absolute path
   if (from[0] == '\0' || !isdirsep(*from)) {
diff --git src/fl_ask.cxx src/fl_ask.cxx
index ecd853b..f711a9f 100644
--- src/fl_ask.cxx
+++ src/fl_ask.cxx
@@ -29,6 +29,7 @@
 #include "flstring.h"
 
 #include <FL/Fl.H>
+#include <FL/fl_string.h>
 
 #include <FL/fl_ask.H>
 
@@ -664,7 +665,7 @@ void fl_message_title_default(const char *title) {
     message_title_default = 0;
   }
   if (title)
-    message_title_default = strdup(title);
+    message_title_default = fl_strdup(title);
 }
 
 /** @} */
diff --git src/fl_string.cxx src/fl_string.cxx
new file mode 100644
index 0000000..cd0d084
--- /dev/null
+++ src/fl_string.cxx
@@ -0,0 +1,34 @@
+/*
+ * Platform agnostic string portability functions for the Fast Light Tool Kit (FLTK).
+ *
+ * Copyright 2020 by Bill Spitzak and others.
+ *
+ * This library is free software. Distribution and use rights are outlined in
+ * the file "COPYING" which should have been included with this file.  If this
+ * file is missing or damaged, see the license at:
+ *
+ *     https://www.fltk.org/COPYING.php
+ *
+ * Please see the following page on how to report bugs and issues:
+ *
+ *     https://www.fltk.org/bugs.php
+ */
+
+#include <FL/fl_string.h>
+#include <string.h>	// strdup/_strdup
+#include "Fl_System_Driver.H"
+
+/**
+  Cross platform interface to POSIX function strdup().
+
+  The fl_strdup() function returns a pointer to a new string which is
+  a duplicate of the string 's'. Memory for the new string is obtained
+  with malloc(3), and can be freed with free(3).
+
+  Implementation:
+    - POSIX: strdup()
+    - WinAPI: _strdup()
+ */
+char *fl_strdup(const char *s) {
+  return Fl::system_driver()->strdup(s);
+}
diff --git src/flstring.h src/flstring.h
index fa31112..d902c0a 100644
--- src/flstring.h
+++ src/flstring.h
@@ -52,10 +52,6 @@
  * Some of these functions are also defined in ISO C99...
  */
 
-#  if defined(_MSC_VER)
-#    define strdup _strdup
-#  endif /* _MSC_VER */
-
 #  if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
 #    define strcasecmp(s,t)     _stricmp((s), (t))
 #    define strncasecmp(s,t,n)  _strnicmp((s), (t), (n))
diff --git src/print_panel.cxx src/print_panel.cxx
index 617b993..7b29991 100644
--- src/print_panel.cxx
+++ src/print_panel.cxx
@@ -36,6 +36,7 @@
 #include "../src/flstring.h"
 #include <FL/Fl_Preferences.H>
 #include <FL/Fl_Int_Input.H>
+#include <FL/fl_string.h>
 
 static Fl_Double_Window *print_panel=(Fl_Double_Window *)0;
 static Fl_Group *print_panel_controls=(Fl_Group *)0;
@@ -541,7 +542,7 @@ printing_style print_load() { // return whether SystemV or BSD printing style is
         }
         *qptr = '\0';
 
-        print_choice->add(qname, 0, 0, (void *)strdup(name), 0);
+        print_choice->add(qname, 0, 0, (void *)fl_strdup(name), 0);
       } else if (!strncmp(line, "system default destination: ", 28)) {
         if (sscanf(line + 28, "%s", defname) != 1) defname[0] = '\0';
       }
@@ -553,7 +554,7 @@ printing_style print_load() { // return whether SystemV or BSD printing style is
     while (fgets(line, sizeof(line),lpstat)) { // get names of all known printers
       if (*line == '#' || (p = strchr(line, '|')) == NULL) continue;
       *p = 0;
-      print_choice->add(line, 0, 0, (void *)strdup(line), 0);
+      print_choice->add(line, 0, 0, (void *)fl_strdup(line), 0);
       style = BSD;
       *p = '|';
       while (1) {
diff --git src/xutf8/utf8Wrap.c src/xutf8/utf8Wrap.c
index e26aef1..a9f9bf9 100644
--- src/xutf8/utf8Wrap.c
+++ src/xutf8/utf8Wrap.c
@@ -21,6 +21,7 @@
 
 #include "../Xutf8.h"
 #include <X11/Xlib.h>
+#include <FL/fl_string.h>	// fl_strdup()
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
@@ -215,7 +216,7 @@ find_best_font(Display  *dpy,
   list = XListFonts(dpy, *name, 1, &cnt);
   if (cnt && list) {
     free(*name);
-    *name = strdup(list[0]);
+    *name = fl_strdup(list[0]);
     s = XLoadQueryFont(dpy, *name);
     XFreeFontNames(list);
     return s;
diff --git test/menubar.cxx test/menubar.cxx
index 856aa72..43e4961 100644
--- test/menubar.cxx
+++ test/menubar.cxx
@@ -30,6 +30,7 @@
 #include <FL/fl_draw.H>
 #include <FL/Fl_Simple_Terminal.H>
 #include <FL/fl_ask.H>
+#include <FL/fl_string.h>
 
 #define TERMINAL_HEIGHT 120
 
@@ -225,7 +226,7 @@ int main(int argc, char **argv) {
   for (int i=0; i<99; i++) {
     char buf[100];
     sprintf(buf,"item %d",i);
-    hugemenu[i].text = strdup(buf);
+    hugemenu[i].text = fl_strdup(buf);
   }
   Fl_Double_Window window(WIDTH,400+TERMINAL_HEIGHT);
   G_tty = new Fl_Simple_Terminal(0,400,WIDTH,TERMINAL_HEIGHT);
diff --git test/unittests.cxx test/unittests.cxx
index 12b65fe..ca04aac 100644
--- test/unittests.cxx
+++ test/unittests.cxx
@@ -28,6 +28,7 @@
 #include <FL/Fl_Group.H>
 #include <FL/Fl_Box.H>
 #include <FL/fl_draw.H>         // fl_text_extents()
+#include <FL/fl_string.h>       // fl_strdup()
 
 // WINDOW/WIDGET SIZES
 #define MAINWIN_W       700                             // main window w()
@@ -53,7 +54,7 @@ public:
   UnitTest(const char *label, Fl_Widget* (*create)()) :
     fWidget(0L)
   {
-    fLabel = strdup(label);
+    fLabel = fl_strdup(label);
     fCreate = create;
     add(this);
   }
diff --git test/utf8.cxx test/utf8.cxx
index ed1dd10..9151264 100644
--- test/utf8.cxx
+++ test/utf8.cxx
@@ -28,6 +28,7 @@
 #include <FL/Fl_Output.H>
 #include <FL/fl_draw.H>
 #include <FL/fl_utf8.h>
+#include <FL/fl_string.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -620,10 +621,10 @@ int main(int argc, char** argv)
     sprintf(bu, "0x%06lX", y * 16);
     Fl_Input *b = new Fl_Input(200,(y-off)*25,80,25);
     b->textfont(FL_COURIER);
-    b->value(strdup(bu));
+    b->value(fl_strdup(bu));
     b = new Fl_Input(280,(y-off)*25,380,25);
     b->textfont(extra_font);
-    b->value(strdup(buf));
+    b->value(fl_strdup(buf));
   }
   scroll.end();
   main_win->resizable(scroll);
Direct Link to Message ]
 
     
Previous Message ]Next Message ]
 
 

Comments are owned by the poster. All other content is copyright 1998-2024 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.