diff --git a/pub/src/axis.h b/pub/src/axis.h
index 70f07bcc97adda2953734e25807e2f37b0729209..b3b608ace0bb353109980f2cb6d29cec39bb4a94 100644
--- a/pub/src/axis.h
+++ b/pub/src/axis.h
@@ -7,7 +7,6 @@ class CAxis {
     CAxis( bool _log ) :
         logflag(_log), force(false) { setAuto(); };
 
-    void Ask( string quest );
     void setLog( bool _log );
 
     void setAuto();
diff --git a/pub/src/coord.cpp b/pub/src/coord.cpp
index 6d8df4a56cf6704838cf3d1d9d9f8e8da72d9bf7..4696b205e2025e268bc14e201b9a8dffa3e4154d 100644
--- a/pub/src/coord.cpp
+++ b/pub/src/coord.cpp
@@ -8,8 +8,10 @@
 #include <math.h>
 #include <stdlib.h>
 #include <string.h>
+#include <iostream>
 
-#include <ask_and_callback.h>
+#include <ask_simple_value.h> // for ASK flags
+#include <readln.h>
 
 using namespace std;
 
@@ -20,52 +22,69 @@ using namespace std;
 //  class CCoord                                                            //
 //**************************************************************************//
 
-char CoordDecode( const string& resp, CCoord *rval )
+CCoord CCoord::Ask( const string& quest, const int flags, const CCoord& defval )
 {
-    if (resp[0]=='\0') {
-        return 'd';
-    } else if ( resp=="?" ) {
-        return 'h';
-    } else if ( resp=="\\EOL" ) {
-        *rval = CCoord();
-        return 'v';
-    }
-
-    uint i, j, np, n;
-    n = resp.size();
-    if (resp[n-1]!=')') {
-        return 'h';
-    }
-    for(j=n-2, np=1; j!=(uint)-1; j--) {
-        if (resp[j]==')') 
-            np++;
-        else if (resp[j]=='(') {
-            np--;
-            if (np==0) break;
+    string defstr("");
+    if( flags & ASK_DEF_GIVEN )
+        defstr = defval.str();
+
+    string prompt = quest;
+    if ( defstr!="" && !(flags & ASK_DEF_NOT_SHOW) )
+        prompt += " [" + defstr + "] ?";
+    prompt += " ";
+
+    for( ;; ) {
+        string resp = NRead::readln(prompt);
+        if        ( resp == "\\q" ) {
+            throw "user escape to main menu";
+        } else if ( resp == "" ) {
+            if ( defstr!="" )
+                return defval;
+            cout << "no default available\n";
+        } else if ( resp == "?" ) {
+            cout << "required input type: coordinate name and unit\n";
+            cout << "input must be in the form: name (unit)\n";
+            if( defstr!="" )
+                cout << "just press ENTER to accept default [" <<
+                    defstr << "]\n";
+        } else {
+            uint i, j, np, n;
+            n = resp.size();
+            if (resp[n-1]!=')') {
+                cout << "input must terminate with ')'\n";
+                continue;
+            }
+            for(j=n-2, np=1; j!=(uint)-1; j--) {
+                if (resp[j]==')') 
+                    np++;
+                else if (resp[j]=='(') {
+                    np--;
+                    if (np==0) break;
+                }
+            }
+            if (np!=0){
+                cout << "input must contain balanced parentheses\n";
+                continue;
+            }
+            for (i=j; i>0 && strchr(" \t",resp[i-1]); i--) ;
+            if (i==0){
+                cout << "input must contain a non-empty coordinate name\n";
+                continue;
+            }
+            return CCoord( resp.substr(0,i), resp.substr(j+1, n-j-2) );
         }
     }
-    if (np!=0) return 'h';
-
-    for (i=j; i>0 && strchr(" \t",resp[i-1]); i--) ;
-    if (i==0) return 'h';
-	
-    *rval = CCoord( resp.substr(0,i), resp.substr(j+1, n-j-2) );
-    return 'v';
+    
 }
 
-const char* CCoord::helptext = 
-"a coordinate: <name> (<unit>)";
-
 CCoord CCoord::Ask( const string& quest, const CCoord& defval )
 {
-    *this =  myask( quest, 1, defval, defval.str(), helptext, CoordDecode );
-    return *this;
+    return Ask( quest, 1, defval );
 }
 
 CCoord CCoord::Ask( const string& quest )
 {
-    *this =  myask( quest, 0, CCoord(), "", helptext, CoordDecode );
-    return *this;
+    return Ask( quest, 0, CCoord() );
 }
 
 string CCoord::str( int maxlen ) const
diff --git a/pub/src/coord.h b/pub/src/coord.h
index 942bab78c3f279cdf74fd7a3b2894cfdda91f5f2..24cfdb2eb4be3dcc414968dbaaf2f5020aa40e23 100644
--- a/pub/src/coord.h
+++ b/pub/src/coord.h
@@ -6,6 +6,7 @@ class CCoord {
     CCoord( const string _name, const string _unit) :
         name(_name), unit(_unit) {};
 
+    CCoord Ask( const string& quest, const int flags, const CCoord& defval );
     CCoord Ask( const string& quest, const CCoord& defval );
     CCoord Ask( const string& quest );
 
diff --git a/pub/src/index.cpp b/pub/src/index.cpp
index 23e3ebd032c975ef91238437527c75357d4a638f..3d3f274a280356e3ec6619c7cdc6b5d8ab262589 100644
--- a/pub/src/index.cpp
+++ b/pub/src/index.cpp
@@ -10,7 +10,8 @@
 #include <iostream>
 #include <algorithm>
 
-#include <ask_and_callback.h>
+#include <ask_simple_value.h> // for ASK flags
+#include <readln.h>
 
 using namespace std;
 
@@ -86,11 +87,11 @@ void IndexSet::parse(const string s, const uint v0, const uint vn)
     IndexParse::ParseSet(&T, s, v0, vn);
 }
 
-void IndexSet::ask(const string quest, const string def, 
-                   const uint v0, const uint vn)
+void IndexSet::ask( const string& quest, const string& def, 
+                    const uint v0, const uint vn )
 {
-    string ans = index_ask(quest, def, v0, vn);
-    parse(ans, v0, vn);
+    string resp = index_ask(quest, def, v0, vn);
+    parse( resp, v0, vn );
 }
 
 // *** info ***
@@ -237,37 +238,40 @@ void IndexParse::ParseValue(string inp, int which, uint *val)
             strg(p0) + ".." + strg(pn);
 }
 
-// *** user interaction ***
 
-const char * IndexDialog::helptext = 
-                                                     "a list (a set of indices):\n"
-                                                     "    list:            <empty_list> | <finite_list> | <infinite_list>\n"
-                                                     "    empty_list:      -\n"
-                                                     "    finite_list:     <range_with_skip> { , <range_with_skip> }\n"
-                                                     "    infinite_list:   *\n"  
-                                                     "    range_with_skip: <range> [ . <skip> ]\n"
-                                                     "    range:           <bound> [ - <bound>]\n"
-                                                     "    skip:            (integer >= 1)\n"
-                                                     "    bound:           * | (integer >= 0)\n";
+// just get a string; do not parse nor check for validity.
 
-char IndexDialog::decode(const string& resp, string *rval )
+string index_ask( const string& quest, const string& defstr, uint p0, uint pn )
 {
-    if ( resp=="" ) {
-        return 'd';
-    } else if ( resp=="?" ) {
-        return 'h';
+    string prompt = quest;
+    if ( defstr!="" )
+        prompt += " [" + defstr + "] ?";
+    prompt += " ";
+
+    for( ;; ) {
+        string resp = NRead::readwd(prompt);
+        if        ( resp == "\\q" ) {
+            throw "user escape to main menu";
+        } else if ( resp == "" ) {
+            if ( defstr!="" )
+                return defstr;
+            else
+                cout << "empty input not allowed; " <<
+                    "use '-' for empty list, '?' for help\n";
+        } else if ( resp == "?" ) {
+            cout << "required input type: index list (without blanks)\n"
+                "examples:\n"
+                "    0,2,7         comma-separated list of values\n"
+                "    0-7           range\n"
+                "    0-7.2         each 2nd: 0,2,4,6\n"
+                "    -             empty list\n"
+                "    *             full range, according to context\n"
+                "    8-*           from 8 to end of range\n";
+            if( defstr!="" )
+                cout << "just press ENTER to accept default [" <<
+                    defstr << "]\n";
+        } else {
+            return resp;
+        }
     }
-    *rval = resp;
-    // IndexParse::ParseTest( *rval, 0, 0 );
-    return 'v';
-}
-
-string index_ask( const string& quest, string def, uint p0, uint pn )
-{
-    uint lims[2];
-    lims[0] = p0;
-    lims[1] = pn;
-    int defflag = ASK_DEF_GIVEN*(def!="") | ASK_WORD;
-    return  myask( quest, defflag, def, def,
-                   IndexDialog::helptext, IndexDialog::decode ); 
 }
diff --git a/pub/src/index.h b/pub/src/index.h
index 133c6aeb1803b007bf95337215dd774439006c9f..dd43e8ba0500b93139ff3665eecc641281433bfc 100644
--- a/pub/src/index.h
+++ b/pub/src/index.h
@@ -25,11 +25,11 @@ public:
     // from text (returns 0 if string is valid):
     void parse( const string s, const uint v0=0, const uint vn=0 );
 
-    void ask( const string quest, const string def, 
+    void ask( const string& quest, const string& defstr, 
               const uint v0=0, const uint vn=0 );
-    void ask( const string quest, const IndexSet set,
+    void ask( const string& quest, const IndexSet set,
               const uint v0=0, const uint vn=0 ) {
-        ask(quest, set.str(), v0, vn); };
+        ask( quest, set.str(), v0, vn ); };
 
     // Info:
     uint size() const { return T.size(); };
@@ -39,6 +39,7 @@ public:
     const char* c_str() const { return str().c_str(); } ;
 };
 
+
 class IndexSetIterator : private IndexSet { 
 private:
     set<uint>::iterator pos;
@@ -77,4 +78,5 @@ public:
 	
 };
 
-string index_ask(const string& quest, string def="", uint p0=0, uint pn=0);
+string index_ask( const string& quest, const string& def="",
+                  uint p0=0, uint pn=0);
diff --git a/pub/src/manip.cpp b/pub/src/manip.cpp
index f76f796d0444ed0e6dac1bd5db0c13001b8a9413..8afd9c5dc3f611fac2c71015826cf15980af9a2b 100644
--- a/pub/src/manip.cpp
+++ b/pub/src/manip.cpp
@@ -111,7 +111,7 @@ void NManip::PtsAvge()
     NOlm::SelAssert();
 
     static string groups;
-    groups = index_ask("Start bins at points", groups);
+    groups = index_ask( "Start bins at points", groups );
     if (groups=="") return;
     
     NOlm::IterateD fiter;