/* This file is part of the KDE libraries Copyright (C) 2005 Christoph Cullmann Copyright (C) 2005 Joseph Wenninger This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. 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; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "katejscript.h" #include "katedocument.h" #include "kateview.h" #include "katefactory.h" #include "kateconfig.h" #include "kateautoindent.h" #include "katehighlight.h" #include "katetextline.h" #include "kateindentscriptabstracts.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace KJS { // taken from tdehtml // therefor thx to: // Copyright (C) 1999-2003 Harri Porten (porten@kde.org) // Copyright (C) 2001-2003 David Faure (faure@kde.org) // Copyright (C) 2003 Apple Computer, Inc. UString::UString(const TQString &d) { unsigned int len = d.length(); UChar *dat = new UChar[len]; memcpy(dat, d.unicode(), len * sizeof(UChar)); rep = UString::Rep::create(dat, len); } TQString UString::qstring() const { return TQString((TQChar*) data(), size()); } TQConstString UString::qconststring() const { return TQConstString((TQChar*) data(), size()); } //BEGIN global methods class KateJSGlobalFunctions : public ObjectImp { public: KateJSGlobalFunctions(int i, int length); virtual bool implementsCall() const { return true; } virtual Value call(ExecState *exec, Object &thisObj, const List &args); enum { Debug }; private: int id; }; KateJSGlobalFunctions::KateJSGlobalFunctions(int i, int length) : ObjectImp(), id(i) { putDirect(lengthPropertyName,length,DontDelete|ReadOnly|DontEnum); } Value KateJSGlobalFunctions::call(ExecState *exec, Object &/*thisObj*/, const List &args) { switch (id) { case Debug: tqDebug("Kate (KJS Scripting): %s", args[0].toString(exec).ascii()); return Undefined(); default: break; } return Undefined(); } //END global methods } // namespace KJS //BEGIN JS API STUFF class KateJSGlobal : public KJS::ObjectImp { public: virtual KJS::UString className() const { return "global"; } }; class KateJSDocument : public KJS::ObjectImp { public: KateJSDocument (KJS::ExecState *exec, KateDocument *_doc); KJS::Value get( KJS::ExecState *exec, const KJS::Identifier &propertyName) const; KJS::Value getValueProperty(KJS::ExecState *exec, int token) const; void put(KJS::ExecState *exec, const KJS::Identifier &propertyName, const KJS::Value& value, int attr = KJS::None); void putValueProperty(KJS::ExecState *exec, int token, const KJS::Value& value, int attr); const KJS::ClassInfo* classInfo() const { return &info; } enum { FullText, Text, TextLine, Lines, Length, LineLength, SetText, Clear, InsertText, RemoveText, InsertLine, RemoveLine, EditBegin, EditEnd, IndentWidth, IndentMode, SpaceIndent, MixedIndent, HighlightMode, IsInWord, CanBreakAt, CanComment, CommentMarker, CommentStart, CommentEnd, Attribute }; public: KateDocument *doc; static const KJS::ClassInfo info; }; class KateJSView : public KJS::ObjectImp { public: KateJSView (KJS::ExecState *exec, KateView *_view); KJS::Value get( KJS::ExecState *exec, const KJS::Identifier &propertyName) const; KJS::Value getValueProperty(KJS::ExecState *exec, int token) const; void put(KJS::ExecState *exec, const KJS::Identifier &propertyName, const KJS::Value& value, int attr = KJS::None); void putValueProperty(KJS::ExecState *exec, int token, const KJS::Value& value, int attr); const KJS::ClassInfo* classInfo() const { return &info; } enum { CursorLine, CursorColumn, CursorColumnReal, SetCursorPosition, SetCursorPositionReal, Selection, HasSelection, SetSelection, RemoveSelectedText, SelectAll, ClearSelection, SelStartLine, SelStartCol, SelEndLine, SelEndCol }; public: KateView *view; static const KJS::ClassInfo info; }; class KateJSIndenter : public KJS::ObjectImp { public: KateJSIndenter (KJS::ExecState *exec); /* KJS::Value get( KJS::ExecState *exec, const KJS::Identifier &propertyName) const; KJS::Value getValueProperty(KJS::ExecState *exec, int token) const; void put(KJS::ExecState *exec, const KJS::Identifier &propertyName, const KJS::Value& value, int attr = KJS::None); void putValueProperty(KJS::ExecState *exec, int token, const KJS::Value& value, int attr); */ const KJS::ClassInfo* classInfo() const { return &info; } enum { OnChar, OnLine, OnNewline, Dummy }; public: static const KJS::ClassInfo info; }; #include "katejscript.lut.h" //END KateJScript::KateJScript () : m_global (new KJS::Object (new KateJSGlobal ())) , m_interpreter (new KJS::Interpreter (*m_global)) , m_document (new KJS::Object(wrapDocument(m_interpreter->globalExec(), 0))) , m_view (new KJS::Object (wrapView(m_interpreter->globalExec(), 0))) { // put some stuff into env., this should stay for all executions, as we keep external // references to the inserted KJS::Objects, this should avoid any garbage collection m_interpreter->globalObject().put(m_interpreter->globalExec(), "document", *m_document); m_interpreter->globalObject().put(m_interpreter->globalExec(), "view", *m_view); m_interpreter->globalObject().put(m_interpreter->globalExec(), "debug", KJS::Object(new KateJSGlobalFunctions(KateJSGlobalFunctions::Debug,1))); } KateJScript::~KateJScript () { delete m_view; delete m_document; delete m_interpreter; delete m_global; } KJS::ObjectImp *KateJScript::wrapDocument (KJS::ExecState *exec, KateDocument *doc) { return new KateJSDocument(exec, doc); } KJS::ObjectImp *KateJScript::wrapView (KJS::ExecState *exec, KateView *view) { return new KateJSView(exec, view); } bool KateJScript::execute (KateView *view, const TQString &script, TQString &errorMsg) { // no view, no fun if (!view) { errorMsg = i18n("Could not access view"); return false; } // init doc & view with new pointers! static_cast( m_document->imp() )->doc = view->doc(); static_cast( m_view->imp() )->view = view; // run the script for real KJS::Completion comp (m_interpreter->evaluate(script)); if (comp.complType() == KJS::Throw) { KJS::ExecState *exec = m_interpreter->globalExec(); KJS::Value exVal = comp.value(); char *msg = exVal.toString(exec).ascii(); int lineno = -1; if (exVal.type() == KJS::ObjectType) { KJS::Value lineVal = KJS::Object::dynamicCast(exVal).get(exec,"line"); if (lineVal.type() == KJS::NumberType) lineno = int(lineVal.toNumber(exec)); } errorMsg = i18n("Exception, line %1: %2").arg(lineno).arg(msg); return false; } return true; } //BEGIN KateJSDocument // ------------------------------------------------------------------------- /* Source for KateJSDocumentProtoTable. @begin KateJSDocumentProtoTable 21 # # edit interface stuff + editBegin/End, this is nice start # textFull KateJSDocument::FullText DontDelete|Function 0 textRange KateJSDocument::Text DontDelete|Function 4 textLine KateJSDocument::TextLine DontDelete|Function 1 lines KateJSDocument::Lines DontDelete|Function 0 length KateJSDocument::Length DontDelete|Function 0 lineLength KateJSDocument::LineLength DontDelete|Function 1 setText KateJSDocument::SetText DontDelete|Function 1 clear KateJSDocument::Clear DontDelete|Function 0 insertText KateJSDocument::InsertText DontDelete|Function 3 removeText KateJSDocument::RemoveText DontDelete|Function 4 insertLine KateJSDocument::InsertLine DontDelete|Function 2 removeLine KateJSDocument::RemoveLine DontDelete|Function 1 editBegin KateJSDocument::EditBegin DontDelete|Function 0 editEnd KateJSDocument::EditEnd DontDelete|Function 0 # # methods from highlight (and around) # isInWord KateJSDocument::IsInWord DontDelete|Function 2 canBreakAt KateJSDocument::CanBreakAt DontDelete|Function 2 canComment KateJSDocument::CanComment DontDelete|Function 2 commentMarker KateJSDocument::CommentMarker DontDelete|Function 1 commentStart KateJSDocument::CommentStart DontDelete|Function 1 commentEnd KateJSDocument::CommentEnd DontDelete|Function 1 attribute KateJSDocument::Attribute DontDelete|Function 2 @end @begin KateJSDocumentTable 6 # # Configuration properties # indentWidth KateJSDocument::IndentWidth DontDelete|ReadOnly indentMode KateJSDocument::IndentMode DontDelete|ReadOnly spaceIndent KateJSDocument::SpaceIndent DontDelete|ReadOnly mixedIndent KateJSDocument::MixedIndent DontDelete|ReadOnly highlightMode KateJSDocument::HighlightMode DontDelete|ReadOnly @end */ DEFINE_PROTOTYPE("KateJSDocument",KateJSDocumentProto) IMPLEMENT_PROTOFUNC(KateJSDocumentProtoFunc) IMPLEMENT_PROTOTYPE(KateJSDocumentProto,KateJSDocumentProtoFunc) const KJS::ClassInfo KateJSDocument::info = { "KateJSDocument", 0, 0, 0 }; KJS::Value KJS::KateJSDocumentProtoFunc::call(KJS::ExecState *exec, KJS::Object &thisObj, const KJS::List &args) { KJS_CHECK_THIS( KateJSDocument, thisObj ); KateDocument *doc = static_cast( thisObj.imp() )->doc; if (!doc) return KJS::Undefined(); switch (id) { case KateJSDocument::FullText: return KJS::String (doc->text()); case KateJSDocument::Text: return KJS::String (doc->text(args[0].toUInt32(exec), args[1].toUInt32(exec), args[2].toUInt32(exec), args[3].toUInt32(exec))); case KateJSDocument::TextLine: return KJS::String (doc->textLine (args[0].toUInt32(exec))); case KateJSDocument::Lines: return KJS::Number (doc->numLines()); case KateJSDocument::Length: return KJS::Number (doc->length()); case KateJSDocument::LineLength: return KJS::Number (doc->lineLength(args[0].toUInt32(exec))); case KateJSDocument::SetText: return KJS::Boolean (doc->setText(args[0].toString(exec).qstring())); case KateJSDocument::Clear: return KJS::Boolean (doc->clear()); case KateJSDocument::InsertText: return KJS::Boolean (doc->insertText (args[0].toUInt32(exec), args[1].toUInt32(exec), args[2].toString(exec).qstring())); case KateJSDocument::RemoveText: return KJS::Boolean (doc->removeText(args[0].toUInt32(exec), args[1].toUInt32(exec), args[2].toUInt32(exec), args[3].toUInt32(exec))); case KateJSDocument::InsertLine: return KJS::Boolean (doc->insertLine (args[0].toUInt32(exec), args[1].toString(exec).qstring())); case KateJSDocument::RemoveLine: return KJS::Boolean (doc->removeLine (args[0].toUInt32(exec))); case KateJSDocument::EditBegin: doc->editBegin(); return KJS::Null (); case KateJSDocument::EditEnd: doc->editEnd (); return KJS::Null (); case KateJSDocument::IsInWord: return KJS::Boolean( doc->highlight()->isInWord( args[0].toString(exec).qstring().at(0), args[1].toUInt32(exec) ) ); case KateJSDocument::CanBreakAt: return KJS::Boolean( doc->highlight()->canBreakAt( args[0].toString(exec).qstring().at(0), args[1].toUInt32(exec) ) ); case KateJSDocument::CanComment: return KJS::Boolean( doc->highlight()->canComment( args[0].toUInt32(exec), args[1].toUInt32(exec) ) ); case KateJSDocument::CommentMarker: return KJS::String( doc->highlight()->getCommentSingleLineStart( args[0].toUInt32(exec) ) ); case KateJSDocument::CommentStart: return KJS::String( doc->highlight()->getCommentStart( args[0].toUInt32(exec) ) ); case KateJSDocument::CommentEnd: return KJS::String( doc->highlight()->getCommentEnd( args[0].toUInt32(exec) ) ); case KateJSDocument::Attribute: return KJS::Number( doc->kateTextLine(args[0].toUInt32(exec))->attribute(args[1].toUInt32(exec)) ); } return KJS::Undefined(); } KJS::Value KateJSDocument::get( KJS::ExecState *exec, const KJS::Identifier &propertyName) const { return KJS::lookupGetValue(exec, propertyName, &KateJSDocumentTable, this ); } KJS::Value KateJSDocument::getValueProperty(KJS::ExecState *exec, int token) const { if (!doc) return KJS::Undefined (); switch (token) { case KateJSDocument::IndentWidth: return KJS::Number( doc->config()->indentationWidth() ); case KateJSDocument::IndentMode: return KJS::String( KateAutoIndent::modeName( doc->config()->indentationMode() ) ); case KateJSDocument::SpaceIndent: return KJS::Boolean( doc->config()->configFlags() & KateDocumentConfig::cfSpaceIndent ); case KateJSDocument::MixedIndent: return KJS::Boolean( doc->config()->configFlags() & KateDocumentConfig::cfMixedIndent ); case KateJSDocument::HighlightMode: return KJS::String( doc->hlModeName( doc->hlMode() ) ); } return KJS::Undefined (); } void KateJSDocument::put(KJS::ExecState *exec, const KJS::Identifier &propertyName, const KJS::Value& value, int attr) { KJS::lookupPut(exec, propertyName, value, attr, &KateJSDocumentTable, this ); } void KateJSDocument::putValueProperty(KJS::ExecState *exec, int token, const KJS::Value& value, int attr) { if (!doc) return; } KateJSDocument::KateJSDocument (KJS::ExecState *exec, KateDocument *_doc) : KJS::ObjectImp (KateJSDocumentProto::self(exec)) , doc (_doc) { } //END //BEGIN KateJSView // ------------------------------------------------------------------------- /* Source for KateJSViewProtoTable. @begin KateJSViewProtoTable 14 cursorLine KateJSView::CursorLine DontDelete|Function 0 cursorColumn KateJSView::CursorColumn DontDelete|Function 0 cursorColumnReal KateJSView::CursorColumnReal DontDelete|Function 0 setCursorPosition KateJSView::SetCursorPosition DontDelete|Function 2 setCursorPositionReal KateJSView::SetCursorPositionReal DontDelete|Function 2 selection KateJSView::Selection DontDelete|Function 0 hasSelection KateJSView::HasSelection DontDelete|Function 0 setSelection KateJSView::SetSelection DontDelete|Function 4 removeSelectedText KateJSView::RemoveSelectedText DontDelete|Function 0 selectAll KateJSView::SelectAll DontDelete|Function 0 clearSelection KateJSView::ClearSelection DontDelete|Function 0 @end */ /* Source for KateJSViewTable. @begin KateJSViewTable 5 selectionStartLine KateJSView::SelStartLine DontDelete|ReadOnly selectionStartColumn KateJSView::SelStartCol DontDelete|ReadOnly selectionEndLine KateJSView::SelEndLine DontDelete|ReadOnly selectionEndColumn KateJSView::SelEndCol DontDelete|ReadOnly @end */ DEFINE_PROTOTYPE("KateJSView",KateJSViewProto) IMPLEMENT_PROTOFUNC(KateJSViewProtoFunc) IMPLEMENT_PROTOTYPE(KateJSViewProto,KateJSViewProtoFunc) const KJS::ClassInfo KateJSView::info = { "KateJSView", 0, &KateJSViewTable, 0 }; KJS::Value KJS::KateJSViewProtoFunc::call(KJS::ExecState *exec, KJS::Object &thisObj, const KJS::List &args) { KJS_CHECK_THIS( KateJSView, thisObj ); KateView *view = static_cast( thisObj.imp() )->view; if (!view) return KJS::Undefined(); switch (id) { case KateJSView::CursorLine: return KJS::Number (view->cursorLine()); case KateJSView::CursorColumn: return KJS::Number (view->cursorColumn()); case KateJSView::CursorColumnReal: return KJS::Number (view->cursorColumnReal()); case KateJSView::SetCursorPosition: return KJS::Boolean( view->setCursorPosition( args[0].toUInt32(exec), args[1].toUInt32(exec) ) ); case KateJSView::SetCursorPositionReal: return KJS::Boolean( view->setCursorPositionReal( args[0].toUInt32(exec), args[1].toUInt32(exec) ) ); // SelectionInterface goes in the view, in anticipation of the future case KateJSView::Selection: return KJS::String( view->selection() ); case KateJSView::HasSelection: return KJS::Boolean( view->hasSelection() ); case KateJSView::SetSelection: return KJS::Boolean( view->setSelection(args[0].toUInt32(exec), args[1].toUInt32(exec), args[2].toUInt32(exec), args[3].toUInt32(exec)) ); case KateJSView::RemoveSelectedText: return KJS::Boolean( view->removeSelectedText() ); case KateJSView::SelectAll: return KJS::Boolean( view->selectAll() ); case KateJSView::ClearSelection: return KJS::Boolean( view->clearSelection() ); } return KJS::Undefined(); } KateJSView::KateJSView (KJS::ExecState *exec, KateView *_view) : KJS::ObjectImp (KateJSViewProto::self(exec)) , view (_view) { } KJS::Value KateJSView::get( KJS::ExecState *exec, const KJS::Identifier &propertyName) const { return KJS::lookupGetValue(exec, propertyName, &KateJSViewTable, this ); } KJS::Value KateJSView::getValueProperty(KJS::ExecState *exec, int token) const { if (!view) return KJS::Undefined (); switch (token) { case KateJSView::SelStartLine: return KJS::Number( view->selStartLine() ); case KateJSView::SelStartCol: return KJS::Number( view->selStartCol() ); case KateJSView::SelEndLine: return KJS::Number( view->selEndLine() ); case KateJSView::SelEndCol: return KJS::Number( view->selEndCol() ); } return KJS::Undefined (); } void KateJSView::put(KJS::ExecState *exec, const KJS::Identifier &propertyName, const KJS::Value& value, int attr) { KJS::lookupPut(exec, propertyName, value, attr, &KateJSViewTable, this ); } void KateJSView::putValueProperty(KJS::ExecState *exec, int token, const KJS::Value& value, int attr) { if (!view) return; } //END //BEGIN KateJScriptManager KateJScriptManager::KateJScriptManager () { m_scripts.setAutoDelete (true); collectScripts (); } KateJScriptManager::~KateJScriptManager () { } void KateJScriptManager::collectScripts (bool force) { // If there's something in myModeList the Mode List was already built so, don't do it again if (!m_scripts.isEmpty()) return; // We'll store the scripts list in this config TDEConfig config("katepartjscriptrc", false, false); // figure out if the kate install is too new config.setGroup ("General"); if (config.readNumEntry ("Version") > config.readNumEntry ("CachedVersion")) { config.writeEntry ("CachedVersion", config.readNumEntry ("Version")); force = true; } // Let's get a list of all the .js files TQStringList list = TDEGlobal::dirs()->findAllResources("data","katepart/scripts/*.js",false,true); // Let's iterate through the list and build the Mode List for ( TQStringList::Iterator it = list.begin(); it != list.end(); ++it ) { // Each file has a group called: TQString Group="Cache "+ *it; // Let's go to this group config.setGroup(Group); // stat the file struct stat sbuf; memset (&sbuf, 0, sizeof(sbuf)); stat(TQFile::encodeName(*it), &sbuf); // If the group exist and we're not forced to read the .js file, let's build myModeList for katepartjscriptrc if (!force && config.hasGroup(Group) && (sbuf.st_mtime == config.readNumEntry("lastModified"))) { } else { kdDebug (13050) << "add script: " << *it << endl; TQString desktopFile = (*it).left((*it).length()-2).append ("desktop"); kdDebug (13050) << "add script (desktop file): " << desktopFile << endl; TQFileInfo dfi (desktopFile); if (dfi.exists()) { TDEConfig df (desktopFile, true, false); df.setDesktopGroup (); // get cmdname, fallback to baseName, if it is empty, therefor not use the tdeconfig fallback TQString cmdname = df.readEntry ("X-Kate-Command"); if (cmdname.isEmpty()) { TQFileInfo fi (*it); cmdname = fi.baseName(); } if (m_scripts[cmdname]) continue; KateJScriptManager::Script *s = new KateJScriptManager::Script (); s->name = cmdname; s->filename = *it; s->desktopFileExists = true; m_scripts.insert (s->name, s); } else // no desktop file around, fall back to scriptfilename == commandname { kdDebug (13050) << "add script: fallback, no desktop file around!" << endl; TQFileInfo fi (*it); if (m_scripts[fi.baseName()]) continue; KateJScriptManager::Script *s = new KateJScriptManager::Script (); s->name = fi.baseName(); s->filename = *it; s->desktopFileExists = false; m_scripts.insert (s->name, s); } } } // Syncronize with the file katepartjscriptrc config.sync(); } bool KateJScriptManager::exec( Kate::View *view, const TQString &_cmd, TQString &errorMsg ) { // cast it hardcore, we know that it is really a kateview :) KateView *v = (KateView*) view; if ( !v ) { errorMsg = i18n("Could not access view"); return false; } //create a list of args TQStringList args( TQStringList::split( TQRegExp("\\s+"), _cmd ) ); TQString cmd ( args.first() ); args.remove( args.first() ); kdDebug(13050) << "try to exec: " << cmd << endl; if (!m_scripts[cmd]) { errorMsg = i18n("Command not found"); return false; } TQFile file (m_scripts[cmd]->filename); if ( !file.open( IO_ReadOnly ) ) { errorMsg = i18n("JavaScript file not found"); return false; } TQTextStream stream( &file ); stream.setEncoding (TQTextStream::UnicodeUTF8); TQString source = stream.read (); file.close(); return KateFactory::self()->jscript()->execute(v, source, errorMsg); } bool KateJScriptManager::help( Kate::View *, const TQString &cmd, TQString &msg ) { if (!m_scripts[cmd] || !m_scripts[cmd]->desktopFileExists) return false; TDEConfig df (m_scripts[cmd]->desktopFilename(), true, false); df.setDesktopGroup (); msg = df.readEntry ("X-Kate-Help"); if (msg.isEmpty()) return false; return true; } TQStringList KateJScriptManager::cmds() { TQStringList l; TQDictIterator it( m_scripts ); for( ; it.current(); ++it ) l << it.current()->name; return l; } //END //BEGIN KateJSIndenter // ------------------------------------------------------------------------- /* Source for KateJSIndenterProtoTable. @begin KateJSIndenterProtoTable 1 Dummy KateJSIndenter::Dummy DontDelete @end */ /* Source for KateJSIndenterTable. @begin KateJSIndenterTable 3 onchar KateJSIndenter::OnChar DontDelete onnewline KateJSIndenter::OnNewline DontDelete online KateJSIndenter::OnLine DontDelete @end */ KateJSIndenter::KateJSIndenter (KJS::ExecState *exec) : KJS::ObjectImp (KateJSViewProto::self(exec)) { } DEFINE_PROTOTYPE("KateJSIndenter",KateJSIndenterProto) IMPLEMENT_PROTOFUNC(KateJSIndenterProtoFunc) IMPLEMENT_PROTOTYPE(KateJSIndenterProto,KateJSIndenterProtoFunc) const KJS::ClassInfo KateJSIndenter::info = { "KateJSIndenter", 0, &KateJSIndenterTable, 0 }; KJS::Value KJS::KateJSIndenterProtoFunc::call(KJS::ExecState *exec, KJS::Object &thisObj, const KJS::List &args) { KJS_CHECK_THIS( KateJSIndenter, thisObj ); return KJS::Undefined(); } //END //BEGIN KateIndentJScriptImpl KateIndentJScriptImpl::KateIndentJScriptImpl(const TQString& internalName, const TQString &filePath, const TQString &niceName, const TQString ©right, double version): KateIndentScriptImplAbstract(internalName,filePath,niceName,copyright,version),m_interpreter(0),m_indenter(0) { } KateIndentJScriptImpl::~KateIndentJScriptImpl() { deleteInterpreter(); } void KateIndentJScriptImpl::decRef() { KateIndentScriptImplAbstract::decRef(); if (refCount()==0) { deleteInterpreter(); } } void KateIndentJScriptImpl::deleteInterpreter() { m_docWrapper=0; m_viewWrapper=0; delete m_indenter; m_indenter=0; delete m_interpreter; m_interpreter=0; } bool KateIndentJScriptImpl::setupInterpreter(TQString &errorMsg) { if (!m_interpreter) { kdDebug(13050)<<"Setting up interpreter"<globalExec(),0); m_viewWrapper=new KateJSView(m_interpreter->globalExec(),0); m_indenter=new KJS::Object(new KateJSIndenter(m_interpreter->globalExec())); m_interpreter->globalObject().put(m_interpreter->globalExec(),"document",KJS::Object(m_docWrapper),KJS::DontDelete | KJS::ReadOnly); m_interpreter->globalObject().put(m_interpreter->globalExec(),"view",KJS::Object(m_viewWrapper),KJS::DontDelete | KJS::ReadOnly); m_interpreter->globalObject().put(m_interpreter->globalExec(),"debug", KJS::Object(new KateJSGlobalFunctions(KateJSGlobalFunctions::Debug,1))); m_interpreter->globalObject().put(m_interpreter->globalExec(),"indenter",*m_indenter,KJS::DontDelete | KJS::ReadOnly); TQFile file (filePath()); if ( !file.open( IO_ReadOnly ) ) { errorMsg = i18n("JavaScript file not found"); deleteInterpreter(); return false; } TQTextStream stream( &file ); stream.setEncoding (TQTextStream::UnicodeUTF8); TQString source = stream.read (); file.close(); KJS::Completion comp (m_interpreter->evaluate(source)); if (comp.complType() == KJS::Throw) { KJS::ExecState *exec = m_interpreter->globalExec(); KJS::Value exVal = comp.value(); char *msg = exVal.toString(exec).ascii(); int lineno = -1; if (exVal.type() == KJS::ObjectType) { KJS::Value lineVal = KJS::Object::dynamicCast(exVal).get(exec,"line"); if (lineVal.type() == KJS::NumberType) lineno = int(lineVal.toNumber(exec)); } errorMsg = i18n("Exception, line %1: %2").arg(lineno).arg(msg); deleteInterpreter(); return false; } else { return true; } } else return true; } inline static bool KateIndentJScriptCall(Kate::View *view, TQString &errorMsg, KateJSDocument *docWrapper, KateJSView *viewWrapper, KJS::Interpreter *interpreter, KJS::Object lookupobj,const KJS::Identifier& func,KJS::List params) { // no view, no fun if (!view) { errorMsg = i18n("Could not access view"); return false; } KateView *v=(KateView*)view; KJS::Object o=lookupobj.get(interpreter->globalExec(),func).toObject(interpreter->globalExec()); if (interpreter->globalExec()->hadException()) { errorMsg=interpreter->globalExec()->exception().toString(interpreter->globalExec()).qstring(); kdDebug(13050)<<"Exception(1):"<globalExec()->clearException(); return false; } // init doc & view with new pointers! docWrapper->doc = v->doc(); viewWrapper->view = v; /*kdDebug(13050)<<"Call Object:"<globalExec()).ascii()<globalExec(),interpreter->globalObject(),params); if (interpreter->globalExec()->hadException()) { errorMsg=interpreter->globalExec()->exception().toString(interpreter->globalExec()).ascii(); kdDebug(13050)<<"Exception(2):"<globalExec()->clearException(); return false; } return true; } bool KateIndentJScriptImpl::processChar(Kate::View *view, TQChar c, TQString &errorMsg ) { kdDebug(13050)<<"KateIndentJScriptImpl::processChar"< config.readNumEntry ("CachedVersion")) { config.writeEntry ("CachedVersion", config.readNumEntry ("Version")); force = true; } #endif // Let's get a list of all the .js files TQStringList list = TDEGlobal::dirs()->findAllResources("data","katepart/scripts/indent/*.js",false,true); // Let's iterate through the list and build the Mode List for ( TQStringList::Iterator it = list.begin(); it != list.end(); ++it ) { // Each file has a group ed: TQString Group="Cache "+ *it; // Let's go to this group config.setGroup(Group); // stat the file struct stat sbuf; memset (&sbuf, 0, sizeof(sbuf)); stat(TQFile::encodeName(*it), &sbuf); // If the group exist and we're not forced to read the .js file, let's build myModeList for katepartjscriptrc bool readnew=false; if (!force && config.hasGroup(Group) && (sbuf.st_mtime == config.readNumEntry("lastModified"))) { config.setGroup(Group); TQString filePath=*it; TQString internalName=config.readEntry("internlName","KATE-ERROR"); if (internalName=="KATE-ERROR") readnew=true; else { TQString niceName=config.readEntry("niceName",internalName); TQString copyright=config.readEntry("copyright",i18n("(Unknown)")); double version=config.readDoubleNumEntry("version",0.0); KateIndentJScriptImpl *s=new KateIndentJScriptImpl( internalName,filePath,niceName,copyright,version); m_scripts.insert (internalName, s); } } else readnew=true; if (readnew) { TQFileInfo fi (*it); if (m_scripts[fi.baseName()]) continue; TQString internalName=fi.baseName(); TQString filePath=*it; TQString niceName=internalName; TQString copyright=i18n("(Unknown)"); double version=0.0; parseScriptHeader(filePath,&niceName,©right,&version); /*save the information for retrieval*/ config.setGroup(Group); config.writeEntry("lastModified",sbuf.st_mtime); config.writeEntry("internalName",internalName); config.writeEntry("niceName",niceName); config.writeEntry("copyright",copyright); config.writeEntry("version",version); KateIndentJScriptImpl *s=new KateIndentJScriptImpl( internalName,filePath,niceName,copyright,version); m_scripts.insert (internalName, s); } } // Syncronize with the file katepartjscriptrc config.sync(); } KateIndentScript KateIndentJScriptManager::script(const TQString &scriptname) { KateIndentJScriptImpl *s=m_scripts[scriptname]; kdDebug(13050)<0) tmpblockdata=value; currentState=COPYRIGHT; } else kdDebug(13050)<<"ignoring key"<