Index: FL/Fl_Input_Choice.H
===================================================================
--- FL/Fl_Input_Choice.H	(revision 9157)
+++ FL/Fl_Input_Choice.H	(working copy)
@@ -24,6 +24,8 @@
 /* \file
    Fl_Input_Choice widget . */
 
+
+
 #ifndef Fl_Input_Choice_H
 #define Fl_Input_Choice_H
 
@@ -31,6 +33,9 @@
 #include <FL/Fl_Group.H>
 #include <FL/Fl_Input.H>
 #include <FL/Fl_Menu_Button.H>
+
+// leaving these so builds don't break if user includes this header
+// and uses items from fl_draw or string (but dosen't include in src)
 #include <FL/fl_draw.H>
 #include <string.h>
 
@@ -48,69 +53,28 @@
 class FL_EXPORT Fl_Input_Choice : public Fl_Group {
   // Private class to handle slightly 'special' behavior of menu button
   class InputMenuButton : public Fl_Menu_Button {
-    void draw() {
-      draw_box(FL_UP_BOX, color());
-      fl_color(active_r() ? labelcolor() : fl_inactive(labelcolor()));
-      int xc = x()+w()/2, yc=y()+h()/2;
-      fl_polygon(xc-5,yc-3,xc+5,yc-3,xc,yc+3);
-      if (Fl::focus() == this) draw_focus();
-    }
+    void draw();
+
+  protected:
+    static const int FLAG_EX_ARROW_SHORTCUT=1;  // allow arrow down to open menu
+    int flags_ex_;
+
   public:
-    InputMenuButton(int X,int Y,int W,int H,const char*L=0) : 
-	Fl_Menu_Button(X, Y, W, H, L) { box(FL_UP_BOX); }
+    InputMenuButton(int X,int Y,int W,int H,const char*L=0);
+    int handle(int event);
+
+    void enable_arrow_shortcut(void) { flags_ex_ |= FLAG_EX_ARROW_SHORTCUT; };
+    void disable_arrow_shortcut(void) { flags_ex_ &= ~FLAG_EX_ARROW_SHORTCUT; };
+    bool using_arrow_shortcut(void) { return (flags_ex_ & FLAG_EX_ARROW_SHORTCUT)!=0; };
   };
 
   Fl_Input *inp_;
   InputMenuButton *menu_;
 
-  static void menu_cb(Fl_Widget*, void *data) { 
-    Fl_Input_Choice *o=(Fl_Input_Choice *)data;
-    Fl_Widget_Tracker wp(o);
-    const Fl_Menu_Item *item = o->menubutton()->mvalue();
-    if (item && item->flags & (FL_SUBMENU|FL_SUBMENU_POINTER)) return;	// ignore submenus
-    if (!strcmp(o->inp_->value(), o->menu_->text()))
-    {
-      o->Fl_Widget::clear_changed();
-      if (o->when() & FL_WHEN_NOT_CHANGED)
-	o->do_callback();
-    }
-    else
-    {
-      o->inp_->value(o->menu_->text());
-      o->inp_->set_changed();
-      o->Fl_Widget::set_changed();
-      if (o->when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE))
-	o->do_callback();
-    }
-    
-    if (wp.deleted()) return;
+  static void menu_cb(Fl_Widget*, void *data);
 
-    if (o->callback() != default_callback)
-    {
-      o->Fl_Widget::clear_changed();
-      o->inp_->clear_changed();
-    }
-  }
+  static void inp_cb(Fl_Widget*, void *data);
 
-  static void inp_cb(Fl_Widget*, void *data) { 
-    Fl_Input_Choice *o=(Fl_Input_Choice *)data;
-    Fl_Widget_Tracker wp(o);
-    if (o->inp_->changed()) {
-      o->Fl_Widget::set_changed();
-      if (o->when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE))
-	o->do_callback();
-    } else {
-      o->Fl_Widget::clear_changed();
-      if (o->when() & FL_WHEN_NOT_CHANGED)
-	o->do_callback();
-    }
-    
-    if (wp.deleted()) return;
-
-    if (o->callback() != default_callback)
-      o->Fl_Widget::clear_changed();
-  }
-
   // Custom resize behavior -- input stretches, menu button doesn't
   inline int inp_x() { return(x() + Fl::box_dx(box())); }
   inline int inp_y() { return(y() + Fl::box_dy(box())); }
@@ -128,28 +92,14 @@
     and label string.
   <P> Inherited destructor Destroys the widget and any value associated with it.
   */
-  Fl_Input_Choice (int X,int Y,int W,int H,const char*L=0) : Fl_Group(X,Y,W,H,L) {
-    Fl_Group::box(FL_DOWN_BOX);
-    align(FL_ALIGN_LEFT);				// default like Fl_Input
-    inp_ = new Fl_Input(inp_x(), inp_y(),
-			inp_w(), inp_h());
-    inp_->callback(inp_cb, (void*)this);
-    inp_->box(FL_FLAT_BOX);		// cosmetic
-    inp_->when(FL_WHEN_CHANGED|FL_WHEN_NOT_CHANGED);
-    menu_ = new InputMenuButton(menu_x(), menu_y(),
-				menu_w(), menu_h());
-    menu_->callback(menu_cb, (void*)this);
-    menu_->box(FL_FLAT_BOX);				// cosmetic
-    end();
-  }
+  Fl_Input_Choice (int X,int Y,int W,int H,const char*L=0);
+
+  int handle(int event);
   
   /** Adds an item to the menu.*/
   void add(const char *s) { menu_->add(s);  }
   int changed() const { return inp_->changed() | Fl_Widget::changed();}
-  void clear_changed() { 
-    inp_->clear_changed();
-    Fl_Widget::clear_changed();
-  }
+  void clear_changed();
   void set_changed() { 
     inp_->set_changed();
     // no need to call Fl_Widget::set_changed()
@@ -164,11 +114,7 @@
   const Fl_Menu_Item *menu() { return (menu_->menu()); }
   /** Sets the Fl_Menu_Item array used for the menu. */
   void menu(const Fl_Menu_Item *m) { menu_->menu(m); }
-  void resize(int X, int Y, int W, int H) {
-    Fl_Group::resize(X,Y,W,H);
-    inp_->resize(inp_x(), inp_y(), inp_w(), inp_h());
-    menu_->resize(menu_x(), menu_y(), menu_w(), menu_h());
-  }
+  void resize(int X, int Y, int W, int H);
   /** Gets the encapsulated input text color attributes */
   Fl_Color textcolor() const { return (inp_->textcolor());}
   /** Sets the encapsulated input text color attributes */
@@ -192,16 +138,26 @@
   */
   void value(const char *val) { inp_->value(val); }
   /**    See void Fl_Input_Choice::value(const char *s)  */
-  void value(int val) {
-    menu_->value(val);
-    inp_->value(menu_->text(val));
-  }
+  void value(int val);
   /**    Returns a reference to the internal Fl_Menu_Button widget.  */
   Fl_Menu_Button *menubutton() { return menu_; }
   /**
     Returns a reference to the internal Fl_Input widget.</p>
   */
   Fl_Input *input() { return inp_; }
+  /**
+    sets the maximum input size
+  */
+  void maximum_size(int size)
+  {
+    if (inp_)
+      inp_->maximum_size(size);
+  };
+
+  void enable_arrow_shortcut(void) { menu_->enable_arrow_shortcut(); };
+  void disable_arrow_shortcut(void) { menu_->disable_arrow_shortcut(); };
+  bool using_arrow_shortcut(void) { return menu_->using_arrow_shortcut(); };
+
 };
 
 #endif // !Fl_Input_Choice_H
Index: src/Fl_Input_Choice.cxx
===================================================================
--- src/Fl_Input_Choice.cxx	(revision 0)
+++ src/Fl_Input_Choice.cxx	(working copy)
@@ -0,0 +1,184 @@
+//
+// "$Id: Fl_Input_Choice.cxx "
+//
+// An input/chooser widget.
+//            ______________  ____
+//           |              || __ |
+//           | input area   || \/ |
+//           |______________||____|
+//
+// Copyright 1998-2010 by Bill Spitzak and others.
+// Copyright 2004 by Greg Ercolano.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+// USA.
+//
+// Please report all bugs and problems on the following page:
+//
+//     http://www.fltk.org/str.php
+//
+
+/* \file
+   Fl_Input_Choice widget . */
+
+
+#include <FL/Fl_Input_Choice.H>
+
+/** Constructor for private button */
+
+Fl_Input_Choice::InputMenuButton::InputMenuButton(int X,int Y,int W,int H,const char*L)
+                                 :Fl_Menu_Button(X,Y,W,H,L)
+{
+  flags_ex_=0;
+  box(FL_UP_BOX);
+};
+
+/** Handle down arrow to open button */
+
+int Fl_Input_Choice::InputMenuButton::handle(int event)
+{
+  if (using_arrow_shortcut()) {
+    // captures all forms of down arrow to open menu.
+    if (event==FL_KEYBOARD && Fl::focus()==this && Fl::event_key()==FL_Down) {
+      popup();
+      return 1;
+    }
+  }
+
+  return Fl_Menu_Button::handle(event);
+}
+
+/** draw the button */
+
+void Fl_Input_Choice::InputMenuButton::draw() {
+  draw_box(FL_UP_BOX, color());
+  fl_color(active_r() ? labelcolor() : fl_inactive(labelcolor()));
+  int xc = x()+w()/2, yc=y()+h()/2;
+  fl_polygon(xc-5,yc-3,xc+5,yc-3,xc,yc+3);
+  if (Fl::focus() == this) draw_focus();
+}
+
+
+/** callback for menu */
+
+void Fl_Input_Choice::menu_cb(Fl_Widget*, void *data) {
+  Fl_Input_Choice *o=(Fl_Input_Choice *)data;
+  Fl_Widget_Tracker wp(o);
+  const Fl_Menu_Item *item = o->menubutton()->mvalue();
+  if (item && item->flags & (FL_SUBMENU|FL_SUBMENU_POINTER)) return;	// ignore submenus
+  if (!strcmp(o->inp_->value(), o->menu_->text()))
+  {
+    o->Fl_Widget::clear_changed();
+    if (o->when() & FL_WHEN_NOT_CHANGED)
+      o->do_callback();
+  }
+  else
+  {
+    o->inp_->value(o->menu_->text());
+    o->inp_->set_changed();
+    o->Fl_Widget::set_changed();
+    if (o->when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE))
+      o->do_callback();
+  }
+
+  if (wp.deleted()) return;
+
+  if (o->callback() != default_callback)
+  {
+    o->Fl_Widget::clear_changed();
+    o->inp_->clear_changed();
+  }
+}
+
+/** call back for input field */
+
+void Fl_Input_Choice::inp_cb(Fl_Widget*, void *data)
+{
+  Fl_Input_Choice *o=(Fl_Input_Choice *)data;
+  Fl_Widget_Tracker wp(o);
+  if (o->inp_->changed()) {
+    o->Fl_Widget::set_changed();
+    if (o->when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE))
+      o->do_callback();
+  } else {
+    o->Fl_Widget::clear_changed();
+    if (o->when() & FL_WHEN_NOT_CHANGED)
+      o->do_callback();
+  }
+
+  if (wp.deleted()) return;
+
+  if (o->callback() != default_callback)
+    o->Fl_Widget::clear_changed();
+}
+
+/** Constructor for Fl_Input_Choice widget using the given position, size,
+  and label string.
+  Inherited destructor Destroys the widget and any value associated with it.
+*/
+Fl_Input_Choice::Fl_Input_Choice (int X,int Y,int W,int H,const char*L)
+                : Fl_Group(X,Y,W,H,L) {
+  Fl_Group::box(FL_DOWN_BOX);
+  align(FL_ALIGN_LEFT);				// default like Fl_Input
+  inp_ = new Fl_Input(inp_x(), inp_y(),
+    inp_w(), inp_h());
+  inp_->callback(inp_cb, (void*)this);
+  inp_->box(FL_FLAT_BOX);		// cosmetic
+  inp_->when(FL_WHEN_CHANGED|FL_WHEN_NOT_CHANGED);
+  menu_ = new InputMenuButton(menu_x(), menu_y(),
+      menu_w(), menu_h());
+  menu_->callback(menu_cb, (void*)this);
+  menu_->box(FL_FLAT_BOX);				// cosmetic
+  end();
+}
+
+/** Adds an item to the menu.*/
+void Fl_Input_Choice::clear_changed() {
+  inp_->clear_changed();
+  Fl_Widget::clear_changed();
+}
+
+/** resize the widget */
+
+void Fl_Input_Choice::resize(int X, int Y, int W, int H) {
+  Fl_Group::resize(X,Y,W,H);
+  inp_->resize(inp_x(), inp_y(), inp_w(), inp_h());
+  menu_->resize(menu_x(), menu_y(), menu_w(), menu_h());
+}
+
+/** See void Fl_Input_Choice::value(const char *s)  */
+void Fl_Input_Choice::value(int val) {
+  menu_->value(val);
+  inp_->value(menu_->text(val));
+}
+
+/** Handle down arrow to open button */
+
+int Fl_Input_Choice::handle(int event)
+{
+  // this captures Alt-Down arrow when input field has kb focus
+  // because a normal down arrow is already eaten by the Fl_Input
+  // object (receives handle first when it has focus).  If you want
+  // the down arrow to work too, you'd need to subclass Fl_Input
+  // and override handle()
+  if (using_arrow_shortcut()) {
+    if (event==FL_KEYBOARD && Fl::focus()==inp_ && Fl::event_key()==FL_Down) {
+      menu_->popup();
+      return 1;
+    }
+  }
+  return Fl_Group::handle(event);
+}
+
Index: src/Makefile
===================================================================
--- src/Makefile	(revision 9157)
+++ src/Makefile	(working copy)
@@ -45,6 +45,7 @@
 	Fl_Image.cxx \
 	Fl_Input.cxx \
 	Fl_Input_.cxx \
+	Fl_Input_Choice.cxx \
 	Fl_Light_Button.cxx \
 	Fl_Menu.cxx \
 	Fl_Menu_.cxx \
