/* This file is part of the KDE libraries
Copyright ( C ) 2005 Christoph Cullmann < cullmann @ kde . org >
Copyright ( C ) 2005 Joseph Wenninger < jowenn @ kde . org >
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 <sys/types.h>
# include <sys/stat.h>
# include <unistd.h>
# include <kdebug.h>
# include <kstandarddirs.h>
# include <tdelocale.h>
# include <tdemessagebox.h>
# include <tdeconfig.h>
# include <kjs/function_object.h>
# include <kjs/interpreter.h>
# include <kjs/lookup.h>
# include <tqfile.h>
# include <tqfileinfo.h>
# include <tqpopupmenu.h>
# include <tqregexp.h>
# include <tqtextstream.h>
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 < KateJSDocument * > ( m_document - > imp ( ) ) - > doc = view - > doc ( ) ;
static_cast < KateJSView * > ( 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 < KateJSDocument * > ( 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 < KateJSDocument , KJS : : ObjectImp > ( 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 < KateJSDocument , KJS : : ObjectImp > ( 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 < KateJSView * > ( 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 < KateJSView , KJS : : ObjectImp > ( 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 < KateJSView , KJS : : ObjectImp > ( 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 < KateJScriptManager : : Script > 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 & copyright , 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 " < < endl ;
m_interpreter = new KJS : : Interpreter ( KJS : : Object ( new KateJSGlobal ( ) ) ) ;
m_docWrapper = new KateJSDocument ( m_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): " < < errorMsg < < endl ;
interpreter - > globalExec ( ) - > clearException ( ) ;
return false ;
}
// init doc & view with new pointers!
docWrapper - > doc = v - > doc ( ) ;
viewWrapper - > view = v ;
/*kdDebug(13050)<<"Call Object:"<<o.toString(interpreter->globalExec()).ascii()<<endl;*/
o . call ( interpreter - > globalExec ( ) , interpreter - > globalObject ( ) , params ) ;
if ( interpreter - > globalExec ( ) - > hadException ( ) )
{
errorMsg = interpreter - > globalExec ( ) - > exception ( ) . toString ( interpreter - > globalExec ( ) ) . ascii ( ) ;
kdDebug ( 13050 ) < < " Exception(2): " < < errorMsg < < endl ;
interpreter - > globalExec ( ) - > clearException ( ) ;
return false ;
}
return true ;
}
bool KateIndentJScriptImpl : : processChar ( Kate : : View * view , TQChar c , TQString & errorMsg )
{
kdDebug ( 13050 ) < < " KateIndentJScriptImpl::processChar " < < endl ;
if ( ! setupInterpreter ( errorMsg ) ) return false ;
KJS : : List params ;
params . append ( KJS : : String ( TQString ( c ) ) ) ;
return KateIndentJScriptCall ( view , errorMsg , m_docWrapper , m_viewWrapper , m_interpreter , * m_indenter , KJS : : Identifier ( " onchar " ) , params ) ;
}
bool KateIndentJScriptImpl : : processLine ( Kate : : View * view , const KateDocCursor & line , TQString & errorMsg )
{
kdDebug ( 13050 ) < < " KateIndentJScriptImpl::processLine " < < endl ;
if ( ! setupInterpreter ( errorMsg ) ) return false ;
return KateIndentJScriptCall ( view , errorMsg , m_docWrapper , m_viewWrapper , m_interpreter , * m_indenter , KJS : : Identifier ( " online " ) , KJS : : List ( ) ) ;
}
bool KateIndentJScriptImpl : : processNewline ( class Kate : : View * view , const KateDocCursor & begin , bool needcontinue , TQString & errorMsg )
{
kdDebug ( 13050 ) < < " KateIndentJScriptImpl::processNewline " < < endl ;
if ( ! setupInterpreter ( errorMsg ) ) return false ;
return KateIndentJScriptCall ( view , errorMsg , m_docWrapper , m_viewWrapper , m_interpreter , * m_indenter , KJS : : Identifier ( " onnewline " ) , KJS : : List ( ) ) ;
}
//END
//BEGIN KateIndentJScriptManager
KateIndentJScriptManager : : KateIndentJScriptManager ( ) : KateIndentScriptManagerAbstract ( )
{
m_scripts . setAutoDelete ( true ) ;
collectScripts ( ) ;
}
KateIndentJScriptManager : : ~ KateIndentJScriptManager ( )
{
}
void KateIndentJScriptManager : : 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 ( " katepartindentjscriptrc " , false , false ) ;
#if 0
// 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 ;
}
# 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 , & copyright , & 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 ) < < scriptname < < " == " < < s < < endl ;
return KateIndentScript ( s ) ;
}
void KateIndentJScriptManager : : parseScriptHeader ( const TQString & filePath ,
TQString * niceName , TQString * copyright , double * version )
{
TQFile f ( TQFile : : encodeName ( filePath ) ) ;
if ( ! f . open ( IO_ReadOnly ) ) {
kdDebug ( 13050 ) < < " Header could not be parsed, because file could not be opened " < < endl ;
return ;
}
TQTextStream st ( & f ) ;
st . setEncoding ( TQTextStream : : UnicodeUTF8 ) ;
if ( ! st . readLine ( ) . upper ( ) . startsWith ( " /**KATE " ) ) {
kdDebug ( 13050 ) < < " No header found " < < endl ;
f . close ( ) ;
return ;
}
// here the real parsing begins
kdDebug ( 13050 ) < < " Parsing indent script header " < < endl ;
enum { NOTHING = 0 , COPYRIGHT = 1 } currentState = NOTHING ;
TQString line ;
TQString tmpblockdata = " " ;
TQRegExp endExpr ( " [ \\ s \\ t]* \\ * \\ * \\ /[ \\ s \\ t]*$ " ) ;
TQRegExp keyValue ( " [ \\ s \\ t]* \\ * \\ s*(.+) : ( . * ) $ " ) ;
TQRegExp blockContent ( " [ \\ s \\ t]* \\ *(.*) $ " ) ;
while ( ( line = st . readLine ( ) ) ! = TQString : : null ) {
if ( endExpr . exactMatch ( line ) ) {
kdDebug ( 13050 ) < < " end of config block " < < endl ;
if ( currentState = = NOTHING ) break ;
if ( currentState = = COPYRIGHT ) {
* copyright = tmpblockdata ;
break ;
}
Q_ASSERT ( 0 ) ;
}
if ( currentState = = NOTHING )
{
if ( keyValue . exactMatch ( line ) ) {
TQStringList sl = keyValue . capturedTexts ( ) ;
kdDebug ( 13050 ) < < " key: " < < sl [ 1 ] < < endl < < " value: " < < sl [ 2 ] < < endl ;
kdDebug ( 13050 ) < < " key-length: " < < sl [ 1 ] . length ( ) < < endl < < " value-length: " < < sl [ 2 ] . length ( ) < < endl ;
TQString key = sl [ 1 ] ;
TQString value = sl [ 2 ] ;
if ( key = = " NAME " ) ( * niceName ) = value . stripWhiteSpace ( ) ;
else if ( key = = " VERSION " ) ( * version ) = value . stripWhiteSpace ( ) . toDouble ( 0 ) ;
else if ( key = = " COPYRIGHT " )
{
tmpblockdata = " " ;
if ( value . stripWhiteSpace ( ) . length ( ) > 0 ) tmpblockdata = value ;
currentState = COPYRIGHT ;
} else kdDebug ( 13050 ) < < " ignoring key " < < endl ;
}
} else {
if ( blockContent . exactMatch ( line ) )
{
TQString bl = blockContent . capturedTexts ( ) [ 1 ] ;
//kdDebug(13050)<<"block content line:"<<bl<<endl<<bl.length()<<" "<<bl.isEmpty()<<endl;
if ( bl . isEmpty ( ) )
{
( * copyright ) = tmpblockdata ;
kdDebug ( 13050 ) < < " Copyright block: " < < endl < < ( * copyright ) < < endl ;
currentState = NOTHING ;
} else tmpblockdata = tmpblockdata + " \n " + bl ;
}
}
}
f . close ( ) ;
}
//END
// kate: space-indent on; indent-width 2; replace-tabs on;