Index: /trunk/FACT++/src/InterpreterV8.cc
===================================================================
--- /trunk/FACT++/src/InterpreterV8.cc	(revision 16801)
+++ /trunk/FACT++/src/InterpreterV8.cc	(revision 16802)
@@ -715,32 +715,31 @@
 Handle<Value> InterpreterV8::FuncInclude(const Arguments& args)
 {
-    for (int i=0; i<args.Length(); i++)
-    {
-        const String::AsciiValue file(args[i]);
-        if (*file == NULL)
-            return ThrowException(String::New("File name missing."));
-
-        if (strlen(*file)==0)
-            return ThrowException(String::New("File name empty."));
-
-        izstream fin(*file);
-        if (!fin)
-            return ThrowException(String::New(errno!=0?strerror(errno):"Insufficient memory for decompression"));
-
-        string buffer;
-        getline(fin, buffer, '\0');
-
-        if ((fin.fail() && !fin.eof()) || fin.bad())
-            return ThrowException(String::New(strerror(errno)));
-
-        if (buffer.length()>1 && buffer[0]=='#' && buffer[1]=='!')
-            buffer.insert(0, "//");
-
-        const Handle<Value> rc = ExecuteCode(buffer, *file);
-        if (rc.IsEmpty())
-            return Undefined();
-    }
-
-    return Undefined();
+    if (args.Length()!=1)
+        return ThrowException(String::New("Number of arguments must be one."));
+
+    if (!args[0]->IsString())
+        return ThrowException(String::New("Argument must be a string."));
+
+    const String::AsciiValue file(args[0]);
+    if (*file == NULL)
+        return ThrowException(String::New("File name missing."));
+
+    if (strlen(*file)==0)
+        return ThrowException(String::New("File name empty."));
+
+    izstream fin(*file);
+    if (!fin)
+        return ThrowException(String::New(errno!=0?strerror(errno):"Insufficient memory for decompression"));
+
+    string buffer;
+    getline(fin, buffer, '\0');
+
+    if ((fin.fail() && !fin.eof()) || fin.bad())
+        return ThrowException(String::New(strerror(errno)));
+
+    if (buffer.length()>1 && buffer[0]=='#' && buffer[1]=='!')
+        buffer.insert(0, "//");
+
+    return ExecuteCode(buffer, *file);
 }
 
@@ -1556,4 +1555,8 @@
 }
 
+// ==========================================================================
+//                           Interrupt handling
+// ==========================================================================
+
 Handle<Value> InterpreterV8::FuncSetInterrupt(const Arguments &args)
 {
@@ -1575,4 +1578,36 @@
 }
 
+Handle<Value> InterpreterV8::HandleInterruptImp(string str, uint64_t time)
+{
+    if (fInterruptCallback.IsEmpty())
+        return Handle<Value>();
+
+    const size_t p = str.find_last_of('\n');
+
+    const string usr = p==string::npos?"":str.substr(p+1);
+
+    string irq = p==string::npos?str:str.substr(0, p);
+    const map<string,string> data = Tools::Split(irq, true);
+
+    Local<Value>  irq_str = String::New(irq.c_str());
+    Local<Value>  usr_str = String::New(usr.c_str());
+    Local<Value>  date    = Date::New(time);
+    Handle<Object> arr    = Array::New(data.size());
+
+    if (date.IsEmpty() || arr.IsEmpty())
+        return Handle<Value>();
+
+    for (auto it=data.begin(); it!=data.end(); it++)
+    {
+        cout << "|" << it->first << "=" << it->second << "|" << endl;
+        arr->Set(String::New(it->first.c_str()), String::New(it->second.c_str()));
+    }
+
+    Handle<Value> args[] = { irq_str, arr, date, usr_str };
+    Handle<Function> fun = Handle<Function>(Function::Cast(*fInterruptCallback));
+
+    return fun->Call(fun, 4, args);
+}
+
 int InterpreterV8::JsHandleInterrupt(const EventImp &evt)
 {
@@ -1582,7 +1617,4 @@
         return -42;
 
-    if (fInterruptCallback.IsEmpty())
-        return -42;
-
     const HandleScope handle_scope;
 
@@ -1593,30 +1625,12 @@
     TryCatch exception;
 
-    const string str = evt.GetString();
-
-    const size_t p = str.find_last_of('\n');
-
-    const string irq = p==string::npos?str:str.substr(0, p);
-    const string usr = p==string::npos?"nobody":str.substr(p+1);
-
-    Local<Value> irq_str = String::New(irq.c_str());
-    Local<Value> usr_str = String::New(usr.c_str());
-    Local<Value> date = Date::New(evt.GetJavaDate());
-
-    int32_t rc = -42;
-    if (!date.IsEmpty())
-    {
-        const int id = V8::GetCurrentThreadId();
-        fThreadIds.insert(id);
-
-        Handle<Value> args[] = { irq_str, date, usr_str };
-        Handle<Function> fun = Handle<Function>(Function::Cast(*fInterruptCallback));
-
-        const Handle<Value> val = fun->Call(fun, 3, args);
-
-        rc = !val.IsEmpty() && val->IsInt32() ? val->Int32Value() : 0;
-
-        fThreadIds.erase(id);
-    }
+    const int id = V8::GetCurrentThreadId();
+    fThreadIds.insert(id);
+
+    const Handle<Value> val = HandleInterruptImp(evt.GetString(), evt.GetJavaDate());
+
+    fThreadIds.erase(id);
+
+    const int rc = !val.IsEmpty() && val->IsInt32() ? val->Int32Value() : 0;
 
     if (!HandleException(exception, "interrupt"))
@@ -1626,9 +1640,30 @@
 }
 
-/*
-void Cleanup( Persistent<Value> object, void *parameter )
-{
-    cout << "======================> RemoveMyObj()" << endl;
-}*/
+Handle<Value> InterpreterV8::FuncTriggerInterrupt(const Arguments &args)
+{
+    string data;
+    for (int i=0; i<args.Length(); i++)
+    {
+        const String::AsciiValue str(args[i]);
+
+        if (string(*str).find_first_of('\n')!=string::npos)
+            return ThrowException(String::New("No argument must contain line breaks."));
+
+        if (!*str)
+            continue;
+
+        data += *str;
+        data += ' ';
+    }
+
+    HandleScope handle_scope;
+
+    const Handle<Value> rc = HandleInterruptImp(Tools::Trim(data), Time().JavaDate());
+    return handle_scope.Close(rc);
+}
+
+// ==========================================================================
+//                           Class 'Subscription'
+// ==========================================================================
 
 Handle<Value> InterpreterV8::FuncSubscription(const Arguments &args)
@@ -2215,9 +2250,4 @@
         return Undefined();
 
-    // If all went well and the result wasn't undefined then print
-    // the returned value.
-    if (!rc->IsUndefined() && file!="internal")
-        JsResult(*String::AsciiValue(rc));
-
     if (!global.IsEmpty() && !save_date.IsEmpty())
     {
@@ -2277,5 +2307,11 @@
 
         // Execute code which was entered
-        ExecuteCode(command, "console");
+        const Handle<Value> rc = ExecuteCode(command, "console");
+
+        // If all went well and the result wasn't undefined then print
+        // the returned value.
+        if (!rc->IsUndefined() && !rc->IsFunction())
+            JsResult(*String::AsciiValue(rc));
+
         if (!HandleException(exception, "console"))
             lout << endl;
@@ -2443,4 +2479,5 @@
     dimctrl->Set(String::New("getState"),    FunctionTemplate::New(WrapGetState),  ReadOnly);
     dimctrl->Set(String::New("setInterruptHandler"), FunctionTemplate::New(WrapSetInterrupt), ReadOnly);
+    dimctrl->Set(String::New("triggerInterrupt"), FunctionTemplate::New(WrapTriggerInterrupt), ReadOnly);
 
     Handle<ObjectTemplate> v8 = ObjectTemplate::New();
Index: /trunk/FACT++/src/InterpreterV8.h
===================================================================
--- /trunk/FACT++/src/InterpreterV8.h	(revision 16801)
+++ /trunk/FACT++/src/InterpreterV8.h	(revision 16802)
@@ -91,4 +91,5 @@
     v8::Handle<v8::Value> FuncNewState(const v8::Arguments& args);
     v8::Handle<v8::Value> FuncSetInterrupt(const v8::Arguments& args);
+    v8::Handle<v8::Value> FuncTriggerInterrupt(const v8::Arguments& args);
     //v8::Handle<v8::Value> FuncOpen(const v8::Arguments& args);
     v8::Handle<v8::Value> FuncSubscription(const v8::Arguments& args);
@@ -149,4 +150,5 @@
     static v8::Handle<v8::Value> WrapGetServices(const v8::Arguments &args){ if (This) return This->FuncGetServices(args);else return v8::Undefined(); }
     static v8::Handle<v8::Value> WrapSetInterrupt(const v8::Arguments &args){ if (This) return This->FuncSetInterrupt(args);else return v8::Undefined(); }
+    static v8::Handle<v8::Value> WrapTriggerInterrupt(const v8::Arguments &args){ if (This) return This->FuncTriggerInterrupt(args);else return v8::Undefined(); }
     //static v8::Handle<v8::Value> WrapOpen(const v8::Arguments &args)     { if (This) return This->FuncOpen(args);     else return v8::Undefined(); }
     static v8::Handle<v8::Value> WrapSubscription(const v8::Arguments &args){ if (This) return This->FuncSubscription(args);else return v8::Undefined(); }
@@ -170,4 +172,6 @@
     v8::Handle<v8::Value> ConvertEvent(const EventImp *evt, uint64_t, const char *str);
 #endif
+
+    v8::Handle<v8::Value> HandleInterruptImp(std::string, uint64_t);
 
 public:
