Index: FL/fl_ask.H
===================================================================
--- FL/fl_ask.H	(revision 10831)
+++ FL/fl_ask.H	(working copy)
@@ -57,6 +57,10 @@
 FL_EXPORT const char *fl_input(const char *label, const char *deflt = 0, ...) __fl_attr((__format__ (__printf__, 1, 3)));
 FL_EXPORT const char *fl_password(const char *label, const char *deflt = 0, ...) __fl_attr((__format__ (__printf__, 1, 3)));
 
+// since FLTK 1.3.4: new versions with limited input size
+FL_EXPORT const char *fl_input_str(int maxchar, const char *label, const char *deflt = 0, ...) __fl_attr((__format__ (__printf__, 2, 4)));
+FL_EXPORT const char *fl_password_str(int maxchar, const char *label, const char *deflt = 0, ...) __fl_attr((__format__ (__printf__, 2, 4)));
+
 FL_EXPORT Fl_Widget *fl_message_icon();
 extern FL_EXPORT Fl_Font fl_message_font_;
 extern FL_EXPORT Fl_Fontsize fl_message_size_;
Index: src/Fl_Dialog_13x.H
===================================================================
--- src/Fl_Dialog_13x.H	(revision 0)
+++ src/Fl_Dialog_13x.H	(working copy)
@@ -0,0 +1,108 @@
+//
+// "$Id$"
+//
+// Common dialog header file for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2015 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:
+//
+//     http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems on the following page:
+//
+//     http://www.fltk.org/str.php
+//
+
+#ifndef Fl_Dialog_13x_H
+#define Fl_Dialog_13x_H
+
+#include <FL/Fl_Window.H>
+
+class Fl_Box;
+class Fl_Button;
+class Fl_Input;
+
+#ifndef FL_DOXYGEN	// exclude from Doxygen docs for now
+
+/**
+  \class Fl_Dialog_13x
+
+  This is the base class for common FLTK dialog windows used in
+  fl_message(), fl_ask(), fl_choice(), fl_input(), and fl_password().
+
+  \note The preliminary class Fl_Dialog_13x is only used internally in
+  FLTK 1.3.x (x \>= 4). This class \b will be deleted and replaced with
+  Fl_Dialog and maybe more classes in FLTK 1.4 and later.
+  <em> DO NOT USE THIS CLASS ! It is reserved for FLTK's \b internal
+  use in common dialogs in FLTK 1.3.x (x \>= 4).</em>
+*/
+
+class /* DON'T FL_EXPORT */ Fl_Dialog_13x : public Fl_Window {
+
+  // static variables and methods
+
+private:
+
+  static Fl_Box *message_icon_;	// returned by Fl_Dialog_13x::message_icon()
+
+  static const char *message_title_;
+  static const char *message_title_default_;
+
+  // Note: since Fl_Dialog_13x objects are destroyed before fl_input()
+  // and fl_password() return their input text, we *need* to store
+  // the text in an internal (static) buffer. :-(
+
+  // Newer versions of fl_input() and fl_password() return the input text
+  // in allocated storage and require the caller to free() the text.
+
+  // private !
+
+  static char *input_buffer_;	// points to the allocated text buffer
+  static int input_size_;	// size of allocated text buffer
+
+  // the button and window callback:
+  static void button_cb_(Fl_Widget *w, void *d);
+
+public:
+
+  static Fl_Box *message_icon();	// used by fl_message_icon()
+
+  static void message_title(const char *title);		// compat.
+  static void message_title_default(const char *title);	// compat.
+
+  // member variables and methods
+
+private:
+
+  Fl_Box *message;		///< message text
+  Fl_Box *icon;			///< contains the icon
+  Fl_Button *button[3];		///< buttons used internally
+  Fl_Input *input;		///< normal text or secret input
+
+  int ret_val;			///< internally used to store the return value
+
+  void resizeform();		///< resize to make text and buttons fit
+
+public:
+
+  // c'tor(s) and d'tor
+
+  Fl_Dialog_13x(const char *iconlabel /* = iconlabel_ */);
+  ~Fl_Dialog_13x() { /* delete message_form; */ }
+
+  int innards(const char* fmt, va_list ap, const char *b0, const char *b1, const char *b2);
+
+  const char* input_innards(const char* fmt, va_list ap, const char* defstr, uchar type, int maxchar = -1);
+
+};
+
+#endif	// FL_DOXYGEN	// exclude from Doxygen docs for now
+
+#endif // Fl_Dialog_13x_H
+
+//
+// End of "$Id$".
+//
Index: src/Fl_Dialog_13x.cxx
===================================================================
--- src/Fl_Dialog_13x.cxx	(revision 0)
+++ src/Fl_Dialog_13x.cxx	(working copy)
@@ -0,0 +1,440 @@
+//
+// "$Id$"
+//
+// Standard dialog implementation for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2015 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:
+//
+//     http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems on the following page:
+//
+//     http://www.fltk.org/str.php
+//
+
+/**
+  \file Fl_Dialog_13x.cxx - Base class for common dialogs.
+
+  This is the base class for common FLTK dialog windows like
+  fl_message, fl_ask, fl_choice, fl_input, and fl_password.
+
+  All common dialogs can be altered by changing static variables and
+  by changing their contents.
+
+  The Fl_Dialog_13x class is intended to be subclassed by users to create
+  their own dialog windows.
+*/
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "flstring.h"
+
+#include <FL/Fl.H>
+
+#include <FL/fl_ask.H>
+#include "Fl_Dialog_13x.H" // this is intentionally "hidden" in src/...
+
+#include <FL/Fl_Window.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Return_Button.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Secret_Input.H>
+#include <FL/fl_draw.H>
+
+#ifndef FL_DOXYGEN	// exclude from Doxygen docs for now
+
+// Fl_Dialog_13x static variables
+
+const char *Fl_Dialog_13x::message_title_default_;
+const char *Fl_Dialog_13x::message_title_;
+
+Fl_Box* Fl_Dialog_13x::message_icon_;
+
+char *Fl_Dialog_13x::input_buffer_;
+int Fl_Dialog_13x::input_size_;
+
+/**
+  Fl_Dialog_13x's internal button callback.
+
+  This callback function is used internally for Fl_Dialog_13x's buttons and
+  the dialog window itself.
+
+  If the user closes the dialog window, then the window callback is called.
+
+  If the user clicks on one of the buttons, then the button's callback
+  is used.
+
+  In both cases Fl_Dialog_13x's internal return value \p ret_val is set
+  accordingly, and the window is closed.
+
+*/
+
+void Fl_Dialog_13x::button_cb_(Fl_Widget *w, void *d) {
+
+  Fl_Dialog_13x *dialog = (Fl_Dialog_13x *)w;	// assume window callback
+  if (!w->as_window())			// button callback
+    dialog = (Fl_Dialog_13x *)w->window();
+  dialog->ret_val = (int)(fl_intptr_t)d;
+  dialog->hide();
+}
+
+Fl_Dialog_13x::Fl_Dialog_13x(const char *iconlabel) :
+  Fl_Window(0, 0, 410, 103, NULL),
+  ret_val(0)
+{
+  // Make sure that the dialog does not become the child of some current group.
+  // If there /was/ such a current group, then we need to remove the window
+  // from this group, which is now our parent().
+
+  Fl_Group *previous_group = parent(); // may be NULL
+  if (parent()) remove(parent());
+
+  // create widgets
+
+  message = new Fl_Box(60, 25, 340, 20);
+  message->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
+
+  input = new Fl_Input(60, 37, 340, 23);
+  input->hide();
+
+  Fl_Box *icon_template = message_icon(); // use template for icon box
+
+  icon = new Fl_Box(10, 10, 50, 50);
+  icon->box(icon_template->box());
+  icon->labelfont(icon_template->labelfont());
+  icon->labelsize(icon_template->labelsize());
+  icon->color(icon_template->color());
+  icon->labelcolor(icon_template->labelcolor());
+  icon->label(iconlabel);
+
+  end(); // don't add the buttons automatically
+
+  // create the buttons (right to left)
+
+  for (int b=0, x=310; b<3; b++, x -= 100) {
+    if (b==1)
+      button[b] = new Fl_Return_Button(x, 70, 90, 23);
+    else
+      button[b] = new Fl_Button(x, 70, 90, 23);
+    button[b]->align(FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
+    button[b]->callback(button_cb_, (void *)(fl_intptr_t)b);
+  }
+  button[0]->shortcut(FL_Escape);
+
+  // add the buttons (left to right)
+
+  for (int b=2; b>=0; b--)
+    add(button[b]);
+
+  begin();
+  resizable(new Fl_Box(60,10,110-60,27));
+  end();
+  callback(button_cb_,(void*)0);
+  set_modal();
+
+  // restore previous group
+  Fl_Group::current(previous_group);
+}
+
+/*
+ * 'resizeform()' - Resize the form and widgets so that they hold everything
+ *                  that is asked of them...
+ */
+
+void Fl_Dialog_13x::resizeform() {
+  int	i;
+  int	message_w, message_h;
+  int	text_height;
+  int	button_w[3], button_h[3];
+  int	x, w, h, max_w, max_h;
+  const int icon_size = 50;
+
+  fl_font(message->labelfont(), message->labelsize());
+  message_w = message_h = 0;
+  fl_measure(message->label(), message_w, message_h);
+
+  message_w += 10;
+  message_h += 10;
+  if (message_w < 340)
+    message_w = 340;
+  if (message_h < 30)
+    message_h = 30;
+
+  fl_font(button[0]->labelfont(), button[0]->labelsize());
+
+  memset(button_w, 0, sizeof(button_w));
+  memset(button_h, 0, sizeof(button_h));
+
+  for (max_h = 25, i = 0; i < 3; i ++)
+    if (button[i]->visible()) {
+      fl_measure(button[i]->label(), button_w[i], button_h[i]);
+
+      if (i == 1)
+        button_w[1] += 20; // account for return button arrow
+
+      button_w[i] += 30;
+      button_h[i] += 10;
+
+      if (button_h[i] > max_h)
+        max_h = button_h[i];
+    }
+
+  if (input->visible()) text_height = message_h + 25;
+  else text_height = message_h;
+
+  max_w = message_w + 10 + icon_size;
+  w     = button_w[0] + button_w[1] + button_w[2] - 10;
+
+  if (w > max_w)
+    max_w = w;
+
+  message_w = max_w - 10 - icon_size;
+
+  w = max_w + 20;
+  h = max_h + 30 + text_height;
+
+  size(w, h);
+  size_range(w, h, w, h);
+
+  message->resize(20 + icon_size, 10, message_w, message_h);
+  icon->resize(10, 10, icon_size, icon_size);
+  icon->labelsize(icon_size - 10);
+  input->resize(20 + icon_size, 10 + message_h, message_w, 25);
+
+  for (x = w, i = 0; i < 3; i ++) {
+    if (button_w[i]) {
+      x -= button_w[i];
+      button[i]->resize(x, h - 10 - max_h, button_w[i] - 10, max_h);
+    }
+  }
+}
+
+int Fl_Dialog_13x::innards(const char* fmt, va_list ap,
+  const char *b0,
+  const char *b1,
+  const char *b2)
+{
+  Fl::pushed(0); // stop dragging (STR #2159)
+
+  char buffer[1024];
+  if (!strcmp(fmt,"%s")) {
+    message->label(va_arg(ap, const char*));
+  } else {
+    ::vsnprintf(buffer, sizeof(buffer)-1, fmt, ap);
+    message->label(buffer);
+  }
+
+  message->labelfont(fl_message_font_);
+  if (fl_message_size_ == -1)
+    message->labelsize(FL_NORMAL_SIZE);
+  else
+    message->labelsize(fl_message_size_);
+
+  if (b0) {button[0]->show(); button[0]->label(b0); button[1]->position(210,70);}
+  else {button[0]->hide(); button[1]->position(310,70);}
+  if (b1) {button[1]->show(); button[1]->label(b1);}
+  else button[1]->hide();
+  if (b2) {button[2]->show(); button[2]->label(b2);}
+  else button[2]->hide();
+
+  resizeform();
+
+  if (button[1]->visible() && !input->visible())
+    button[1]->take_focus();
+  if (enableHotspot)
+    hotspot(button[0]);
+  if (b0 && Fl_Widget::label_shortcut(b0))
+    button[0]->shortcut(0);
+  else
+    button[0]->shortcut(FL_Escape);
+
+  // set the one-time window title, if defined and a specific title is not set
+  if (!label() && message_title_) {
+    copy_label(message_title_);
+    message_title(0);	// reset global message title (compat.)
+  }
+
+  // set default window title, if defined and a specific title is not set
+  if (!label() && message_title_default_)
+    copy_label(message_title_default_);
+
+  // deactivate Fl::grab(), because it is incompatible with modal windows
+  Fl_Window* g = Fl::grab();
+  if (g) Fl::grab(0);
+  Fl_Group *current_group = Fl_Group::current(); // make sure the dialog does not interfere with any active group
+  show();
+  Fl_Group::current(current_group);
+  while (shown()) Fl::wait();
+  if (g) // regrab the previous popup menu, if there was one
+    Fl::grab(g);
+
+  return ret_val;
+}
+
+
+/** Gets the default icon container (Fl_Box) used in common dialogs.
+
+    Many common dialogs like fl_message(), fl_alert(), fl_ask(),
+    fl_choice(), fl_input(), and fl_password() display an icon.
+
+    You can use this method to get the icon box (Fl_Box) and modify
+    the icon's box type, font, fontsize etc.
+
+    \since FLTK 1.4.0
+
+    \note This method replaces the deprecated method fl_message_icon().
+    Note that this new method correctly returns an Fl_Box * pointer,
+    whereas fl_message_icon() returns Fl_Widget *.
+
+    The current icon default values are:
+
+      - width and height: 50 (currently not changeable)
+      - box(FL_THIN_UP_BOX)
+      - labelfont(FL_TIMES_BOLD)
+      - labelsize(34)
+      - color(FL_WHITE)
+      - labelcolor(FL_BLUE)
+
+    Although it is not very likely these values may be changed in a
+    future FLTK version.
+
+    If you change this then the changed values are used for subsequently
+    started common dialogs. This is intended to change the icon layout
+    for your application at startup time. It is not recommended to change
+    the default values for each message.
+
+    \note \#include <FL/fl_ask.H>
+*/
+Fl_Box *Fl_Dialog_13x::message_icon() {
+
+  if (!Fl_Dialog_13x::message_icon_) { // not yet initialized
+
+    Fl_Group *current_group = Fl_Group::current();
+    Fl_Group::current(0);
+
+    Fl_Box* o = Fl_Dialog_13x::message_icon_ = new Fl_Box(10, 10, 50, 50);
+    o->box(FL_THIN_UP_BOX);
+    o->labelfont(FL_TIMES_BOLD);
+    o->labelsize(34);
+    o->color(FL_WHITE);
+    o->labelcolor(FL_BLUE);
+    Fl_Group::current(current_group);
+  }
+  return Fl_Dialog_13x::message_icon_;
+}
+
+
+/**
+  Does all Fl_Dialog_13x window internals for messages with a text input field.
+
+  \todo More documentation.
+*/
+const char* Fl_Dialog_13x::input_innards(const char* fmt, va_list ap,
+				 const char* defstr, uchar type,
+				 int maxchar) {
+  message->position(60,10);
+  input->type(type);
+  input->show();
+  input->value(defstr);
+  input->take_focus();
+  if (maxchar > 0)
+    input->maximum_size(maxchar);
+
+  int r = innards(fmt, ap, fl_cancel, fl_ok, 0);
+
+  if (!r) return 0;
+
+  if (input->value()) {
+
+    int size = input->size() + 1;
+
+    if (maxchar < 0) { // need to store the value in pre-allocated buffer
+
+      // The allocated input buffer starts with size 0 and is allocated
+      // in multiples of 128 bytes >= size. If both the size and the pointer
+      // are 0 (NULL) then realloc() allocates a /new/ buffer.
+
+      if (size > input_size_) {
+	size += 127; size &= ~127;
+	input_buffer_ = (char *)realloc(input_buffer_, size);
+	input_size_ = size;
+      }
+
+      // Store the input. Note that value() can contain null bytes,
+      // so we use memcpy and add a terminating null byte as well.
+
+      memcpy(input_buffer_, input->value(), input->size());
+      input_buffer_[input->size()] = '\0';
+      return (input_buffer_);
+    }
+    else { // new version: allocate string buffer
+
+      char *buf = (char *)malloc(size);
+      memcpy(buf, input->value(), input->size());
+      buf[input->size()] = '\0';
+      return (buf);
+    }
+
+  } else
+    return 0;
+}
+
+/** Sets the title of the dialog window used in many common dialogs.
+
+    This window \p title will be used in the next call of one of the
+    common dialogs like fl_message(), fl_alert(), fl_ask(), fl_choice(),
+    fl_input(), fl_password().
+
+    The \p title string is copied internally, so that you can use a
+    local variable or free the string immediately after this call. It
+    applies only to the \b next call of one of the common dialogs and
+    will be reset to an empty title (the default for all dialogs) after
+    that call.
+
+    \note \#include <FL/fl_ask.H>
+    \param[in] title	window label, string copied internally
+*/
+void Fl_Dialog_13x::message_title(const char *title) {
+  if (message_title_) {
+    free ((void *)message_title_);
+    message_title_ = 0;
+  }
+  if (title)
+    message_title_ = strdup(title);
+}
+
+/** Sets the default title of the dialog window used in many common dialogs.
+
+    This window \p title will be used in all subsequent calls of one of the
+    common dialogs like fl_message(), fl_alert(), fl_ask(), fl_choice(),
+    fl_input(), fl_password(), unless a specific title has been set
+    with fl_message_title(const char *title).
+
+    The default is no title. You can override the default title for a
+    single dialog with fl_message_title(const char *title).
+
+    The \p title string is copied internally, so that you can use a
+    local variable or free the string immediately after this call.
+
+    \note \#include <FL/fl_ask.H>
+    \param[in] title	default window label, string copied internally
+*/
+void Fl_Dialog_13x::message_title_default(const char *title) {
+  if (message_title_default_) {
+    free ((void *)message_title_default_);
+    message_title_default_ = 0;
+  }
+  if (title)
+    message_title_default_ = strdup(title);
+}
+
+#endif	// FL_DOXYGEN	// exclude from Doxygen docs for now
+
+//
+// End of "$Id$".
+//
Index: src/fl_ask.cxx
===================================================================
--- src/fl_ask.cxx	(revision 10831)
+++ src/fl_ask.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Standard dialog functions for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2011 by Bill Spitzak and others.
+// Copyright 1998-2015 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
@@ -32,241 +32,30 @@
 
 #include <FL/Fl.H>
 
+#ifdef __APPLE__
+extern "C" void NSBeep(void);
+#endif
+
 #include <FL/fl_ask.H>
+#include "Fl_Dialog_13x.H" // this is intentionally "hidden" in src/...
 
-#include <FL/Fl_Box.H>
-#include <FL/Fl_Button.H>
-#include <FL/Fl_Return_Button.H>
-#include <FL/Fl_Window.H>
-#include <FL/Fl_Input.H>
-#include <FL/Fl_Secret_Input.H>
-#include <FL/x.H>
-#include <FL/fl_draw.H>
+// static, configurable variables
 
-static Fl_Window *message_form;
-static Fl_Box *message;
-static Fl_Box *icon;
-static Fl_Button *button[3];
-static Fl_Input *input;
-static int ret_val;
-static const char *iconlabel = "?";
-static const char *message_title_default;
 Fl_Font fl_message_font_ = FL_HELVETICA;
 Fl_Fontsize fl_message_size_ = -1;
 static int enableHotspot = 1;
-#ifdef __APPLE__
-extern "C" void NSBeep(void);
-#endif
 
-static char avoidRecursion = 0;
-
-// Sets the global return value (ret_val) and closes the window.
-// Note: this is used for the button callbacks and the window
-// callback (closing the window with the close button or menu).
-// The first argument (Fl_Widget *) can either be an Fl_Button*
-// pointer to one of the buttons or an Fl_Window* pointer to the
-// message window (message_form).
-static void button_cb(Fl_Widget *, long val) {
-  ret_val = (int) val;
-  message_form->hide();
-}
-
-static Fl_Window *makeform() {
- if (message_form) {
-   return message_form;
- }
- // make sure that the dialog does not become the child of some
- // current group
- Fl_Group *previously_current_group = Fl_Group::current();
- Fl_Group::current(0);
- // create a new top level window
- Fl_Window *w = message_form = new Fl_Window(410,103);
-  message_form->callback(button_cb);
- // w->clear_border();
- // w->box(FL_UP_BOX);
- (message = new Fl_Box(60, 25, 340, 20))
-   ->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
- (input = new Fl_Input(60, 37, 340, 23))->hide();
- {Fl_Box* o = icon = new Fl_Box(10, 10, 50, 50);
-  o->box(FL_THIN_UP_BOX);
-  o->labelfont(FL_TIMES_BOLD);
-  o->labelsize(34);
-  o->color(FL_WHITE);
-  o->labelcolor(FL_BLUE);
- }
- w->end(); // don't add the buttons automatically
- // create the buttons (right to left)
- {
-   for (int b=0, x=310; b<3; b++, x -= 100) {
-     if (b==1)
-       button[b] = new Fl_Return_Button(x, 70, 90, 23);
-     else
-       button[b] = new Fl_Button(x, 70, 90, 23);
-     button[b]->align(FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
-     button[b]->callback(button_cb, b);
-   }
- }
- button[0]->shortcut(FL_Escape);
- // add the buttons (left to right)
- {
-   for (int b=2; b>=0; b--)
-     w->add(button[b]);
- }
- w->begin();
- w->resizable(new Fl_Box(60,10,110-60,27));
- w->end();
- w->set_modal();
- Fl_Group::current(previously_current_group);
- return w;
-}
-
 /*
- * 'resizeform()' - Resize the form and widgets so that they hold everything
- *                  that is asked of them...
- */
+  The following file is #include'd in FLTK 1.3.4 (1.3.x) to avoid
+  having to include it in IDE's, Makefiles, and CMake files.
+  This will be fixed in FLTK 1.4.0.
+*/
+#include "Fl_Dialog_13x.cxx"
 
-static void resizeform() {
-  int	i;
-  int	message_w, message_h;
-  int	text_height;
-  int	button_w[3], button_h[3];
-  int	x, w, h, max_w, max_h;
-	const int icon_size = 50;
+/** \addtogroup group_comdlg
+    @{
+*/
 
-  message_form->size(410,103);
-
-  fl_font(message->labelfont(), message->labelsize());
-  message_w = message_h = 0;
-  fl_measure(message->label(), message_w, message_h);
-
-  message_w += 10;
-  message_h += 10;
-  if (message_w < 340)
-    message_w = 340;
-  if (message_h < 30)
-    message_h = 30;
-
-  fl_font(button[0]->labelfont(), button[0]->labelsize());
-
-  memset(button_w, 0, sizeof(button_w));
-  memset(button_h, 0, sizeof(button_h));
-
-  for (max_h = 25, i = 0; i < 3; i ++)
-    if (button[i]->visible())
-    {
-      fl_measure(button[i]->label(), button_w[i], button_h[i]);
-
-      if (i == 1)
-        button_w[1] += 20;
-
-      button_w[i] += 30;
-      button_h[i] += 10;
-
-      if (button_h[i] > max_h)
-        max_h = button_h[i];
-    }
-
-  if (input->visible()) text_height = message_h + 25;
-  else text_height = message_h;
-
-  max_w = message_w + 10 + icon_size;
-  w     = button_w[0] + button_w[1] + button_w[2] - 10;
-
-  if (w > max_w)
-    max_w = w;
-
-  message_w = max_w - 10 - icon_size;
-
-  w = max_w + 20;
-  h = max_h + 30 + text_height;
-
-  message_form->size(w, h);
-  message_form->size_range(w, h, w, h);
-
-  message->resize(20 + icon_size, 10, message_w, message_h);
-  icon->resize(10, 10, icon_size, icon_size);
-  icon->labelsize(icon_size - 10);
-  input->resize(20 + icon_size, 10 + message_h, message_w, 25);
-
-  for (x = w, i = 0; i < 3; i ++)
-    if (button_w[i])
-    {
-      x -= button_w[i];
-      button[i]->resize(x, h - 10 - max_h, button_w[i] - 10, max_h);
-
-//      printf("button %d (%s) is %dx%d+%d,%d\n", i, button[i]->label(),
-//             button[i]->w(), button[i]->h(),
-//	     button[i]->x(), button[i]->y());
-    }
-}
-
-static int innards(const char* fmt, va_list ap,
-  const char *b0,
-  const char *b1,
-  const char *b2)
-{
-  Fl::pushed(0); // stop dragging (STR #2159)
-
-  avoidRecursion = 1;
-
-  makeform();
-  message_form->size(410,103);
-  char buffer[1024];
-  if (!strcmp(fmt,"%s")) {
-    message->label(va_arg(ap, const char*));
-  } else {
-    ::vsnprintf(buffer, 1024, fmt, ap);
-    message->label(buffer);
-  }
-
-  message->labelfont(fl_message_font_);
-  if (fl_message_size_ == -1)
-    message->labelsize(FL_NORMAL_SIZE);
-  else
-    message->labelsize(fl_message_size_);
-  if (b0) {button[0]->show(); button[0]->label(b0); button[1]->position(210,70);}
-  else {button[0]->hide(); button[1]->position(310,70);}
-  if (b1) {button[1]->show(); button[1]->label(b1);}
-  else button[1]->hide();
-  if (b2) {button[2]->show(); button[2]->label(b2);}
-  else button[2]->hide();
-  const char* prev_icon_label = icon->label();
-  if (!prev_icon_label) icon->label(iconlabel);
-
-  resizeform();
-
-  if (button[1]->visible() && !input->visible())
-    button[1]->take_focus();
-  if (enableHotspot)
-    message_form->hotspot(button[0]);
-  if (b0 && Fl_Widget::label_shortcut(b0))
-    button[0]->shortcut(0);
-  else
-    button[0]->shortcut(FL_Escape);
-
-  // set default window title, if defined and a specific title is not set
-  if (!message_form->label() && message_title_default)
-    message_form->label(message_title_default);
-
-  // deactivate Fl::grab(), because it is incompatible with modal windows
-  Fl_Window* g = Fl::grab();
-  if (g) Fl::grab(0);
-  Fl_Group *current_group = Fl_Group::current(); // make sure the dialog does not interfere with any active group
-  message_form->show();
-  Fl_Group::current(current_group);
-  while (message_form->shown()) Fl::wait();
-  if (g) // regrab the previous popup menu, if there was one
-    Fl::grab(g);
-  icon->label(prev_icon_label);
-  message_form->label(0); // reset window title
-
-  avoidRecursion = 0;
-  return ret_val;
-}
-
- /** \addtogroup group_comdlg
-    @{ */
-
 // pointers you can use to change FLTK to another language:
 const char* fl_no = "No";        ///< string pointer used in common dialogs, you can change it to another language
 const char* fl_yes= "Yes";       ///< string pointer used in common dialogs, you can change it to another language
@@ -326,34 +115,27 @@
 #endif // WIN32
 }
 
+
 /** Shows an information message dialog box.
 
-   \note Common dialog boxes are application modal. No more than one common dialog box
-   can be open at any time. Requests for additional dialog boxes are ignored.
    \note \#include <FL/fl_ask.H>
 
-
    \param[in] fmt can be used as an sprintf-like format and variables for the message text
  */
 void fl_message(const char *fmt, ...) {
 
-  if (avoidRecursion) return;
-
+  Fl_Dialog_13x msg("i");
   va_list ap;
 
   // fl_beep(FL_BEEP_MESSAGE);
 
   va_start(ap, fmt);
-  iconlabel = "i";
-  innards(fmt, ap, 0, fl_close, 0);
+  msg.innards(fmt, ap, 0, fl_close, 0);
   va_end(ap);
-  iconlabel = "?";
 }
 
-/** Shows an alert message dialog box
+/** Shows an alert message dialog box.
 
-   \note Common dialog boxes are application modal. No more than one common dialog box
-   can be open at any time. Requests for additional dialog boxes are ignored.
    \note \#include <FL/fl_ask.H>
 
    \param[in] fmt can be used as an sprintf-like format and variables for the message text
@@ -360,27 +142,23 @@
  */
 void fl_alert(const char *fmt, ...) {
 
-  if (avoidRecursion) return;
-
+  Fl_Dialog_13x msg("!");
   va_list ap;
 
   // fl_beep(FL_BEEP_ERROR);
 
   va_start(ap, fmt);
-  iconlabel = "!";
-  innards(fmt, ap, 0, fl_close, 0);
+  msg.innards(fmt, ap, 0, fl_close, 0);
   va_end(ap);
-  iconlabel = "?";
 }
+
 /** Shows a dialog displaying the \p fmt message,
-    this dialog features 2 yes/no buttons
+    this dialog features 2 yes/no buttons.
 
-   \note Common dialog boxes are application modal. No more than one common dialog box
-   can be open at any time. Requests for additional dialog boxes are ignored.
    \note \#include <FL/fl_ask.H>
 
    \param[in] fmt can be used as an sprintf-like format and variables for the message text
-   \retval 0 if the no button is selected or another dialog box is still open
+   \retval 0 if the no button is selected
    \retval 1 if yes is selected
 
    \deprecated fl_ask() is deprecated since it uses "Yes" and "No" for the buttons which
@@ -389,14 +167,13 @@
  */
 int fl_ask(const char *fmt, ...) {
 
-  if (avoidRecursion) return 0;
-
+  Fl_Dialog_13x msg("?");
   va_list ap;
 
   // fl_beep(FL_BEEP_QUESTION);
 
   va_start(ap, fmt);
-  int r = innards(fmt, ap, fl_no, fl_yes, 0);
+  int r = msg.innards(fmt, ap, fl_no, fl_yes, 0);
   va_end(ap);
 
   return r;
@@ -403,10 +180,8 @@
 }
 
 /** Shows a dialog displaying the \p fmt message,
-    this dialog features up to 3 customizable choice buttons
+    this dialog features up to 3 customizable choice buttons.
 
-   \note Common dialog boxes are application modal. No more than one common dialog box
-    can be open at any time. Requests for additional dialog boxes are ignored.
    \note \#include <FL/fl_ask.H>
 
    Three choice example:
@@ -446,103 +221,161 @@
    \param[in] b0 text label of button 0
    \param[in] b1 text label of button 1 (can be 0)
    \param[in] b2 text label of button 2 (can be 0)
-   \retval 0 if the first button with \p b0 text is selected or another dialog box is still open
+   \retval 0 if the first button with \p b0 text is selected
    \retval 1 if the second button with \p b1 text is selected
    \retval 2 if the third button with \p b2 text is selected
  */
 int fl_choice(const char*fmt,const char *b0,const char *b1,const char *b2,...){
 
-  if (avoidRecursion) return 0;
-
+  Fl_Dialog_13x msg("?");
   va_list ap;
 
   // fl_beep(FL_BEEP_QUESTION);
 
   va_start(ap, b2);
-  int r = innards(fmt, ap, b0, b1, b2);
+  int r = msg.innards(fmt, ap, b0, b1, b2);
   va_end(ap);
   return r;
 }
-/** Gets the Fl_Box icon container of the current default dialog used in
-    many common dialogs like fl_message(), fl_alert(),
-    fl_ask(), fl_choice(), fl_input(), fl_password()
-    \note \#include <FL/fl_ask.H>
+
+
+/**
+  Returns the default message icon (Fl_Widget *).
+
+  The return value cannot be Null. The object pointed to is an Fl_Box widget.
+  The returned pointer (Fl_Widget *) can be safely cast to an Fl_Box* pointer.
 */
-Fl_Widget *fl_message_icon() {makeform(); return icon;}
+// can not be inlined (otherwise it is undefined / not exported)
 
-static const char* input_innards(const char* fmt, va_list ap,
-				 const char* defstr, uchar type) {
-  makeform();
-  message_form->size(410,103);
-  message->position(60,10);
-  input->type(type);
-  input->show();
-  input->value(defstr);
-  input->take_focus();
+Fl_Widget *fl_message_icon() { return Fl_Dialog_13x::message_icon(); }
 
-  int r = innards(fmt, ap, fl_cancel, fl_ok, 0);
-  input->hide();
-  message->position(60,25);
-  return r ? input->value() : 0;
-}
 
-/** Shows an input dialog displaying the \p fmt message
+/** Shows an input dialog displaying the \p fmt message with variable arguments.
 
-   \note Common dialog boxes are application modal. No more than one common dialog box
-   can be open at any time. Requests for additional dialog boxes are ignored.
-   \note \#include <FL/fl_ask.H>
+  This version of fl_input() is deprecated. The return value points
+  to an internal allocated string that may be changed later. You must
+  copy the string immediately after return from this method - at least
+  before the next call of the event loop.
 
-   \param[in] fmt can be used as an sprintf-like format and variables for the message text
-   \param[in] defstr defines the default returned string if no text is entered
-   \return the user string input if OK was pushed, NULL if Cancel was pushed or another dialog box was still open
+  \deprecated Please use
+  fl_input_str(int maxchar, const char *fmt, const char *defstr, ...) instead.
+
+  \note \#include <FL/fl_ask.H>
+
+  \param[in] fmt can be used as an sprintf-like format and variables for the message text
+  \param[in] defstr defines the default returned string if no text is entered
+  \return the user string input if OK was pushed, NULL if Cancel was pushed
  */
 const char* fl_input(const char *fmt, const char *defstr, ...) {
 
-  if (avoidRecursion) return 0;
+  // fl_beep(FL_BEEP_QUESTION);
 
+  Fl_Dialog_13x msg("?");
+  va_list ap;
+  va_start(ap, defstr);
+  const char* r = msg.input_innards(fmt, ap, defstr, FL_NORMAL_INPUT, -1);
+  va_end(ap);
+  return r;
+}
+
+/** Shows an input dialog displaying the \p fmt message with variable arguments.
+
+  Like fl_input(), but this method has an additional (first) argument \p maxchar
+  that limits the number of \b characters that can be input. Since the
+  string is encoded in UTF-8 it is possible that the number of bytes
+  in the string is larger than \p maxchar.
+
+  Other than the deprecated fl_input() method w/o the \p maxchar argument,
+  this one returns the string in an allocated buffer that must be free'd
+  after use.
+
+  \note \#include <FL/fl_ask.H>
+
+  \param[in] maxchar	input size limit in characters (not bytes),
+			use 0 for no limit
+  \param[in] fmt can be used as an sprintf-like format and variables for the message text
+  \param[in] defstr defines the default returned string if no text is entered
+  \return the user string input if OK was pushed, NULL if Cancel was pushed
+ */
+const char* fl_input_str(int maxchar, const char *fmt, const char *defstr, ...) {
+
   // fl_beep(FL_BEEP_QUESTION);
 
+  Fl_Dialog_13x msg("?");
+  if (maxchar < 0) maxchar = 0;
   va_list ap;
   va_start(ap, defstr);
-  const char* r = input_innards(fmt, ap, defstr, FL_NORMAL_INPUT);
+  const char* r = msg.input_innards(fmt, ap, defstr, FL_NORMAL_INPUT, maxchar);
   va_end(ap);
   return r;
 }
 
-/** Shows an input dialog displaying the \p fmt message.
+/** Shows an input dialog displaying the \p fmt message with variable arguments.
 
-    Like fl_input() except the input text is not shown,
-    '*' characters are displayed instead.
+  Like fl_input() except the input text is not shown,
+  '*' or similar replacement characters are displayed instead.
 
-   \note Common dialog boxes are application modal. No more than one common dialog box
-   can be open at any time. Requests for additional dialog boxes are ignored.
-   \note \#include <FL/fl_ask.H>
+  \deprecated Please use
+  fl_password_str(int maxchar, const char *fmt, const char *defstr, ...) instead.
 
-   \param[in] fmt can be used as an sprintf-like format and variables for the message text
-   \param[in] defstr defines the default returned string if no text is entered
-   \return the user string input if OK was pushed, NULL if Cancel was pushed or aother dialog box was still open
+  \note \#include <FL/fl_ask.H>
+
+  \param[in] fmt can be used as an sprintf-like format and variables for the message text
+  \param[in] defstr defines the default returned string if no text is entered
+
+  \return the user string input if OK was pushed, NULL if Cancel was pushed
  */
 const char *fl_password(const char *fmt, const char *defstr, ...) {
 
-  if (avoidRecursion) return 0;
+  // fl_beep(FL_BEEP_PASSWORD);
 
+  Fl_Dialog_13x msg("?");
+  va_list ap;
+  va_start(ap, defstr);
+  const char* r = msg.input_innards(fmt, ap, defstr, FL_SECRET_INPUT);
+  va_end(ap);
+  return r;
+}
+
+/** Shows an input dialog displaying the \p fmt message with variable arguments.
+
+  Like fl_input_str() except the input text is not shown,
+  '*' or similar replacement characters are displayed instead.
+
+  Other than the deprecated fl_password() method w/o the \p maxchar argument,
+  this one returns the string in an allocated buffer that must be free'd
+  after use.
+
+  \note \#include <FL/fl_ask.H>
+
+  \param[in] maxchar	input size limit in characters (not bytes); use 0 for no limit
+  \param[in] fmt	can be used as an sprintf-like format and variables for the message text
+  \param[in] defstr	defines the default returned string if no text is entered
+
+  \return the user string input if OK was pushed, NULL if Cancel was pushed
+ */
+const char *fl_password_str(int maxchar, const char *fmt, const char *defstr, ...) {
+
   // fl_beep(FL_BEEP_PASSWORD);
 
+  Fl_Dialog_13x msg("?");
+  if (maxchar < 0) maxchar = 0;
   va_list ap;
   va_start(ap, defstr);
-  const char* r = input_innards(fmt, ap, defstr, FL_SECRET_INPUT);
+  const char* r = msg.input_innards(fmt, ap, defstr, FL_SECRET_INPUT, maxchar);
   va_end(ap);
   return r;
 }
 
-/** Sets whether or not to move the common message box used in
-    many common dialogs like fl_message(), fl_alert(),
-    fl_ask(), fl_choice(), fl_input(), fl_password() to follow
-    the mouse pointer.
+/** Sets whether or not to move the common message box used in many
+    common dialogs like fl_message(), fl_alert(), fl_ask(), fl_choice(),
+    fl_input(), fl_password() to follow the mouse pointer.
 
     The default is \e enabled, so that the default button is the
     hotspot and appears at the mouse position.
+
     \note \#include <FL/fl_ask.H>
+
     \param[in]	enable	non-zero enables hotspot behavior,
 			0 disables hotspot
  */
@@ -578,8 +411,7 @@
     \param[in] title	window label, string copied internally
 */
 void fl_message_title(const char *title) {
-  makeform();
-  message_form->copy_label(title);
+  Fl_Dialog_13x::message_title(title);
 }
 
 /** Sets the default title of the dialog window used in many common dialogs.
@@ -588,7 +420,7 @@
     common dialogs like fl_message(), fl_alert(), fl_ask(), fl_choice(),
     fl_input(), fl_password(), unless a specific title has been set
     with fl_message_title(const char *title).
-    
+
     The default is no title. You can override the default title for a
     single dialog with fl_message_title(const char *title).
 
@@ -599,12 +431,7 @@
     \param[in] title	default window label, string copied internally
 */
 void fl_message_title_default(const char *title) {
-  if (message_title_default) {
-    free ((void *)message_title_default);
-    message_title_default = 0;
-  }
-  if (title)
-    message_title_default = strdup(title);
+  Fl_Dialog_13x::message_title_default(title);
 }
 
 /** @} */
Index: test/ask.cxx
===================================================================
--- test/ask.cxx	(revision 10831)
+++ test/ask.cxx	(working copy)
@@ -39,13 +39,15 @@
 }
 
 void rename_me(Fl_Widget*o) {
-  const char *input = fl_input("Input:", o->label());
+  const char *input = fl_input_str(0,"Input (no size limit, use ctrl/j for newline):", o->label());
   update_input_text(o, input);
+  free((void *)input);
 }
 
 void rename_me_pwd(Fl_Widget*o) {
-  const char *input = fl_password("Input PWD:", o->label());
+  const char *input = fl_password_str(20,"Input PWD (max. 20 characters):", o->label());
   update_input_text(o, input);
+  free((void *)input);
 }
 
 void window_callback(Fl_Widget*, void*) {
@@ -81,8 +83,10 @@
 void timer_cb(void *) {
 
   static int stop = 0;
+  static int n = 0;
   double delta = 5.0;
 
+  n++;
   Fl_Box *message_icon = (Fl_Box *)fl_message_icon();
 
   Fl::repeat_timeout(delta, timer_cb);
@@ -98,12 +102,24 @@
   if (c == message_icon->labelcolor()) c++;
   message_icon->color((Fl_Color)c);
 
+  // test message title assignment with a local buffer
+  // also test that the message text is being reset
+  if (n&1) {				// test: every 2nd message
+    char buf[40];			// test: use local variable
+    sprintf(buf,"Message #%d",n);	// fill message title
+    fl_message_title(buf);		// set message title
+    strcpy(buf,"** void **");		// overwrite buffer to be sure
+  }					// buf goes out of scope here
+
   // pop up a message:
-  stop = fl_choice("Timeout. Click the 'Close' button.\n"
-	     "Note: this message is blocked in FLTK 1.3\n"
-	     "if another message window is open.\n"
-	     "This message should pop up every 5 seconds.",
-	     "Close","Stop these funny popups",NULL);
+  stop = fl_choice(
+	"Timeout. Click the 'Close' button or press Escape.\n"
+	"Note: this message was blocked in FLTK 1.3.3 and\n"
+	"earlier if another message window was open.\n"
+	"This message should pop up every 5 seconds in FLTK 1.3.4\n"
+	"and later until stopped by clicking the button below or\n"
+	"by pressing the Enter (Return) key.\n",
+	"Close","Stop these funny popups",NULL);
 }
 
 int main(int argc, char **argv) {
@@ -125,9 +141,9 @@
   window.callback(window_callback);
 
   // Test: set default message window title:
-  // fl_message_title_default("Default Window Title");
+  // fl_message_title_default("Default Message Title");
 
-  // Test: multiple (nested, aka "recursive") popups
+  // Test: multiple (nested, aka "recursive") popups (see timer_cb())
   Fl::add_timeout(5.0, timer_cb);
 
   return Fl::run();
