Index: /trunk/FACT++/src/InterpreterV8.cc
===================================================================
--- /trunk/FACT++/src/InterpreterV8.cc	(revision 14642)
+++ /trunk/FACT++/src/InterpreterV8.cc	(revision 14643)
@@ -21,4 +21,5 @@
 
 #include "tools.h"
+#include "externals/izstream.h"
 
 using namespace std;
@@ -27,5 +28,5 @@
 v8::Handle<v8::FunctionTemplate> InterpreterV8::fTemplateLocal;
 v8::Handle<v8::FunctionTemplate> InterpreterV8::fTemplateSky;
-//v8::Handle<v8::FunctionTemplate> InterpreterV8::fTemplateMoon;
+v8::Handle<v8::FunctionTemplate> InterpreterV8::fTemplateEvent;
 //v8::Handle<v8::FunctionTemplate> InterpreterV8::fTemplateDatabase;
 
@@ -73,5 +74,5 @@
 // until it goes out of scope. Handles which are not needed anymore are
 // then deleted. To return a handle from a HandleScope you need to use
-// Close(). E.g., String::Utf8Value does not create a new handle and
+// Close(). E.g., String::AsciiValue does not create a new handle and
 // hence does not need a HandleScope. Any ::New will need a handle scope.
 // Forgetting the HandleScope could in principle fill your memory,
@@ -212,5 +213,5 @@
         return ThrowException(String::New("Argument 1 must be a string."));
 
-    const String::Utf8Value str(args[0]);
+    const String::AsciiValue str(args[0]);
 
     string command = *str;
@@ -219,5 +220,5 @@
     for (int i=1; i<args.Length(); i++)
     {
-        const String::Utf8Value arg(args[i]);
+        const String::AsciiValue arg(args[i]);
         if (args[i]->IsString())
             command += " \""+string(*arg)+"\"";
@@ -252,6 +253,6 @@
     const string index   = args[1]->IsInt32() ? "s.index" : "s.name";
     const bool   timeout = args.Length()==3;
-    const string arg0    = *String::Utf8Value(args[0]);
-    const string state   = args[1]->IsString() ? *String::Utf8Value(args[1]) : "";
+    const string arg0    = *String::AsciiValue(args[0]);
+    const string state   = args[1]->IsString() ? *String::AsciiValue(args[1]) : "";
     const string arg1    = args[1]->IsString() ? ("\""+state+"\"") : to_string(args[1]->Int32Value());
 
@@ -295,16 +296,15 @@
     // Return state.name/state.index
 
-    const String::Utf8Value str(args[0]);
+    const String::AsciiValue str(args[0]);
 
     const State rc = JsState(*str);
-
-    //if (rc.first<=-256)
-    //    return Undefined();
+    if (rc.index<=-256)
+        return Object::New();
 
     HandleScope handle_scope;
 
     Handle<ObjectTemplate> obj = ObjectTemplate::New();
-    obj->Set(String::New("index"), rc.index<=-256?Undefined():Integer::New(rc.index),       ReadOnly);
-    obj->Set(String::New("name"),  rc.index<=-256?Undefined():String::New(rc.name.c_str()), ReadOnly);
+    obj->Set(String::New("index"), Integer::New(rc.index),       ReadOnly);
+    obj->Set(String::New("name"),  String::New(rc.name.c_str()), ReadOnly);
 
     const Local<Value> date = Date::New(rc.time.JavaDate());
@@ -328,6 +328,6 @@
 
     const uint32_t index   = args[0]->Int32Value();
-    const string   name    = *String::Utf8Value(args[1]);
-    const string   comment = *String::Utf8Value(args[2]);
+    const string   name    = *String::AsciiValue(args[1]);
+    const string   comment = *String::AsciiValue(args[2]);
 
     if (index<10 || index>255)
@@ -372,5 +372,5 @@
     else
     {
-        const string name = *String::Utf8Value(args[0]);
+        const string name = *String::AsciiValue(args[0]);
         index = JsGetState(name);
         if (index==-2)
@@ -416,5 +416,5 @@
     for (int i=0; i<args.Length(); i++)
     {
-        const String::Utf8Value str(args[i]);
+        const String::AsciiValue str(args[i]);
         if (*str)
             JsPrint(*str);
@@ -427,5 +427,5 @@
     for (int i=0; i<args.Length(); i++)
     {
-        const String::Utf8Value str(args[i]);
+        const String::AsciiValue str(args[i]);
         if (*str)
             JsAlarm(*str);
@@ -442,5 +442,5 @@
     for (int i=0; i<args.Length(); i++)
     {
-        const String::Utf8Value str(args[i]);
+        const String::AsciiValue str(args[i]);
         if (*str)
             JsOut(*str);
@@ -456,5 +456,5 @@
     for (int i=0; i<args.Length(); i++)
     {
-        const String::Utf8Value file(args[i]);
+        const String::AsciiValue file(args[i]);
         if (*file == NULL)
             return ThrowException(String::New("File name missing"));
@@ -468,25 +468,52 @@
 Handle<Value> InterpreterV8::FuncFile(const Arguments& args)
 {
-    for (int i=0; i<1; i++)
-    {
-        const String::Utf8Value file(args[i]);
-        if (*file == NULL)
-            return ThrowException(String::New("File name missing"));
-
-        ifstream fin(*file);
-        if (!fin)
-            return ThrowException(String::New(("Error - Could not open file '"+string(*file)+"'").c_str()));
-
+    if (args.Length()!=1 && args.Length()!=2)
+        return ThrowException(String::New("Number of arguments must be one or two."));
+
+    const String::AsciiValue file(args[0]);
+    if (*file == NULL)
+        return ThrowException(String::New("File name missing"));
+
+    if (args.Length()==2 && !args[1]->IsString())
+        return ThrowException(String::New("Second argument must be a string."));
+
+    const string delim = args.Length()==2 ? *String::AsciiValue(args[1]) : "";
+
+    if (args.Length()==2 && delim.size()!=1)
+        return ThrowException(String::New("Second argument must be a string of length 1."));
+
+    HandleScope handle_scope;
+
+    izstream fin(*file);
+    if (!fin)
+        return ThrowException(String::New(errno!=0?strerror(errno):"Insufficient memory for decompression"));
+
+    if (args.Length()==1)
+    {
         string buffer;
         if (!getline(fin, buffer, '\0'))
-            return ThrowException(String::New(("Error - Could read file '"+string(*file)+"'").c_str()));
-
-        if (fin.fail())
-            return ThrowException(String::New(("Error - Could read file '"+string(*file)+"'").c_str()));
-
-        return String::New(buffer.c_str());
-
-    }
-    return Boolean::New(true);
+            return ThrowException(String::New(strerror(errno)));
+
+        Handle<Value> str = StringObject::New(String::New(buffer.c_str()));
+        StringObject::Cast(*str)->Set(String::New("name"), String::New(*file));
+        return handle_scope.Close(str);
+    }
+
+    Handle<Array> arr = Array::New();
+    if (arr.IsEmpty())
+        return Undefined();
+
+    int i=0;
+    string buffer;
+    while (getline(fin, buffer, delim[0]))
+        arr->Set(i++, String::New(buffer.c_str()));
+
+    if ((fin.fail() && !fin.eof()) || fin.bad())
+        return ThrowException(String::New(strerror(errno)));
+
+    arr->Set(String::New("name"),  String::New(*file));
+    arr->Set(String::New("delim"), String::New(delim.c_str(), 1));
+
+    return handle_scope.Close(arr);
 }
 
@@ -531,5 +558,5 @@
     string query;
     for (int i=0; i<args.Length(); i++)
-        query += string(" ") + *String::Utf8Value(args[i]);
+        query += string(" ") + *String::AsciiValue(args[i]);
     query.erase(0, 1);
 
@@ -693,5 +720,5 @@
         //    return Constructor(fTemplateDatabase, args);
 
-        Database *db = new Database(*String::Utf8Value(args[0]));
+        Database *db = new Database(*String::AsciiValue(args[0]));
         fDatabases.push_back(db);
 
@@ -756,5 +783,5 @@
     //const void *ptr = Local<External>::Cast(args.Holder()->GetInternalField(0))->Value();
 
-    const String::Utf8Value str(args.Holder()->Get(String::New("name")));
+    const String::AsciiValue str(args.Holder()->Get(String::New("name")));
 
     const auto it = fReverseMap.find(*str);
@@ -774,5 +801,5 @@
     const vector<Description> vec = JsDescription(str);
 
-    Handle<Object> ret = Object::New();
+    Handle<Object> ret = fTemplateEvent->GetFunction()->NewInstance();//Object::New();
     if (ret.IsEmpty())
         return Undefined();
@@ -782,15 +809,11 @@
         return Undefined();
 
-    ret->Set(String::New("name"),    String::New(str),             ReadOnly);
+    ret->Set(String::New("name"),    String::New(str),              ReadOnly);
     ret->Set(String::New("format"),  String::New(evt->GetFormat().c_str()), ReadOnly);
     ret->Set(String::New("qos"),     Integer::New(evt->GetQoS()),   ReadOnly);
     ret->Set(String::New("size"),    Integer::New(evt->GetSize()),  ReadOnly);
     ret->Set(String::New("counter"), Integer::New(counter),         ReadOnly);
-    ret->Set(String::New("time"),    date,  ReadOnly);
-
-    // If no event was received (usually a disconnection event in
-    // the context of FACT++), no data is returned
-    if (evt->IsEmpty())
-        return ret;
+    if (evt->GetJavaDate()>0)
+        ret->Set(String::New("time"), date, ReadOnly);
 
     // If names are available data will also be provided as an
@@ -801,9 +824,11 @@
     // obj!==undefined, obj.length>0: names available, data received
     Handle<Object> named = Object::New();
-    if (named.IsEmpty())
-        return Undefined();
-
     if (vec.size()>0)
         ret->Set(String::New("obj"), named, ReadOnly);
+
+    // If no event was received (usually a disconnection event in
+    // the context of FACT++), no data is returned
+    if (evt->IsEmpty())
+        return ret;
 
     // If valid data was received, but the size was zero, then
@@ -895,5 +920,5 @@
     HandleScope handle_scope;
 
-    const String::Utf8Value str(args.Holder()->Get(String::New("name")));
+    const String::AsciiValue str(args.Holder()->Get(String::New("name")));
 
     const pair<uint64_t, EventImp *> p = JsGetEvent(*str);
@@ -936,5 +961,5 @@
     const Handle<String> object = String::New("obj");
 
-    const String::Utf8Value name(args.Holder()->Get(String::New("name")));
+    const String::AsciiValue name(args.Holder()->Get(String::New("name")));
 
     TryCatch exception;
@@ -1038,5 +1063,5 @@
     if (ret->IsNativeError())
     {
-        JsException(service+".onchange callback - "+*String::Utf8Value(ret));
+        JsException(service+".onchange callback - "+*String::AsciiValue(ret));
         V8::TerminateExecution(fThreadId);
     }
@@ -1046,5 +1071,5 @@
 {
     // Returns the value if the setter intercepts the request. Otherwise, returns an empty handle.
-    const string server = *String::Utf8Value(prop);
+    const string server = *String::AsciiValue(prop);
     auto it = fStateCallbacks.find(server);
 
@@ -1084,12 +1109,15 @@
 
     Handle<ObjectTemplate> obj = ObjectTemplate::New();
-    obj->Set(String::New("index"),   state.index<=-256?Undefined():Integer::New(state.index),          ReadOnly);
-    obj->Set(String::New("name"),    state.index<=-256?Undefined():String::New(state.name.c_str()),    ReadOnly);
-    obj->Set(String::New("comment"), state.index<=-256?Undefined():String::New(state.comment.c_str()), ReadOnly);
     obj->Set(String::New("server"),  String::New(server.c_str()), ReadOnly);
 
-    const Local<Value> date = Date::New(state.time.JavaDate());
-    if (state.index>-256 && !date.IsEmpty())
-        obj->Set(String::New("time"), date);
+    if (state.index>-256)
+    {
+        obj->Set(String::New("index"),   Integer::New(state.index),          ReadOnly);
+        obj->Set(String::New("name"),    String::New(state.name.c_str()),    ReadOnly);
+        obj->Set(String::New("comment"), String::New(state.comment.c_str()), ReadOnly);
+        const Local<Value> date = Date::New(state.time.JavaDate());
+        if (!date.IsEmpty())
+            obj->Set(String::New("time"), date);
+    }
 
     // -------------------------------------------------------------------
@@ -1124,5 +1152,5 @@
         return ThrowException(String::New("Argument 1 must be a string."));
 
-    const String::Utf8Value str(args[0]);
+    const String::AsciiValue str(args[0]);
 
     if (!args.IsConstructCall())
@@ -1452,5 +1480,5 @@
         return true;
 
-    const String::Utf8Value exception(except);
+    const String::AsciiValue exception(except);
 
     const Handle<Message> message = try_catch.Message();
@@ -1463,5 +1491,5 @@
     {
         // Print (filename):(line number): (message).
-        const String::Utf8Value filename(message->GetScriptResourceName());
+        const String::AsciiValue filename(message->GetScriptResourceName());
 
         out << *filename;
@@ -1480,5 +1508,5 @@
 
     // Print line of source code.
-    const String::Utf8Value sourceline(message->GetSourceLine());
+    const String::AsciiValue sourceline(message->GetSourceLine());
     if (*sourceline)
         JsException(*sourceline);
@@ -1495,5 +1523,5 @@
     JsException(out.str());
 
-    const String::Utf8Value stack_trace(try_catch.StackTrace());
+    const String::AsciiValue stack_trace(try_catch.StackTrace());
     if (stack_trace.length()<=0)
         return false;
@@ -1563,5 +1591,5 @@
     // the returned value.
     if (!result.IsEmpty() && result->IsUndefined())
-        JsResult(*String::Utf8Value(result));
+        JsResult(*String::AsciiValue(result));
 
     return handle_scope.Close(result);
@@ -1608,5 +1636,5 @@
 {
     const string code =
-        "dim.format = function(str, arr)"
+        "String.form = function(str, arr)"
         "{"
             "var i = -1;"
@@ -1652,5 +1680,5 @@
         "String.prototype.$ = function()"
         "{"
-            "return dim.format(this, Array.prototype.slice.call(arguments));"
+            "return String.form(this, Array.prototype.slice.call(arguments));"
         "}"/*
         "\n"
@@ -1689,15 +1717,12 @@
     dim->Set(String::New("send"),      FunctionTemplate::New(WrapSend),      ReadOnly);
     dim->Set(String::New("state"),     FunctionTemplate::New(WrapState),     ReadOnly);
-    dim->Set(String::New("newState"),  FunctionTemplate::New(WrapNewState),  ReadOnly);
-    dim->Set(String::New("setState"),  FunctionTemplate::New(WrapSetState),  ReadOnly);
-    dim->Set(String::New("getState"),  FunctionTemplate::New(WrapGetState),  ReadOnly);
     dim->Set(String::New("sleep"),     FunctionTemplate::New(WrapSleep),     ReadOnly);
-    dim->Set(String::New("file"),      FunctionTemplate::New(WrapFile),      ReadOnly);
-
-    // file      -> File    - class?
+
+    Handle<ObjectTemplate> dimctrl = ObjectTemplate::New();
+    dimctrl->Set(String::New("newState"),  FunctionTemplate::New(WrapNewState),  ReadOnly);
+    dimctrl->Set(String::New("setState"),  FunctionTemplate::New(WrapSetState),  ReadOnly);
+    dimctrl->Set(String::New("getState"),  FunctionTemplate::New(WrapGetState),  ReadOnly);
+
     // new class State ?
-    // newState -> return State?
-    // setState -> return State?
-    // getState -> return State?
 
     Handle<ObjectTemplate> onchange = ObjectTemplate::New();
@@ -1706,5 +1731,6 @@
 
     Handle<ObjectTemplate> global = ObjectTemplate::New();
-    global->Set(String::New("dim"), dim, ReadOnly);
+    global->Set(String::New("dim"),      dim,     ReadOnly);
+    global->Set(String::New("dimctrl"),  dimctrl, ReadOnly);
     global->Set(String::New("include"),  FunctionTemplate::New(WrapInclude),                ReadOnly);
     global->Set(String::New("exit"),     FunctionTemplate::New(WrapExit),                   ReadOnly);
@@ -1725,4 +1751,15 @@
     thread->InstanceTemplate()->SetInternalFieldCount(1);
     global->Set(String::New("Thread"), thread, ReadOnly);
+
+    Handle<FunctionTemplate> file = FunctionTemplate::New(WrapFile);
+    file->SetClassName(String::New("File"));
+    file->InstanceTemplate()->SetInternalFieldCount(1);
+    global->Set(String::New("File"), file, ReadOnly);
+
+    Handle<FunctionTemplate> evt = FunctionTemplate::New();
+    evt->SetClassName(String::New("Event"));
+    global->Set(String::New("Event"), evt, ReadOnly);
+
+    fTemplateEvent = evt;
 
 #ifdef HAVE_NOVA
