/************************************************************************** * * @@@BUILDINFO@@@ 80document-2.jsx 2.0.1.70 05-June-2007 * Copyright 2006-2007 Adobe Systems Incorporated * All Rights Reserved. * * NOTICE: All information contained herein is, and remains the property of * Adobe Systems Incorporated and its suppliers, if any. The intellectual * and technical concepts contained herein are proprietary to Adobe Systems * Incorporated and its suppliers and may be covered by U.S. and Foreign * Patents,patents in process,and are protected by trade secret or copyright * law. Dissemination of this information or reproduction of this material * is strictly forbidden unless prior written permission is obtained from * Adobe Systems Incorporated. **************************************************************************/ Document.__sourceID__ = 0; // next source ID appended to title Document.__scriptID__ = 0; // next script ID attached to name Document.__windowID__ = 0; // next document ID for the window Document.autoCompletion = null; // holds autocompletion data if there is a timer pending document = null; documents = []; Document.FIND_WRAPAROUND = 1; Document.FIND_IGNORECASE = 4; Document.FIND_WORDS = 8; Document.FIND_REGEXP = 16; Document.FIND_REPLACEALL = 32; Document.FIND_SELECTION = 64; // Each Document instance has the following extra properties. // These properties are not present for instances that are not documents. // paneTitle - the original title to display // fileName - the file name part of the title // roState - true if the document is logically read only (it can be modified, though) // scriptID - the script ID; either a full pathname, (ScriptN) for new scripts, or a target ID // langID - the lexer language (default: js) // lf - the line endings for Save // encoding - the file encoding for Save // badLine - temporary: If a syntax error was detected, this is the line (need to remove color on edits) // lastAutoComplete - holds the last autocomplete string to inhibit double calls // Create a new document, but do not show the window yet. Return the window. // Supply an optional title and an optional language and script ID. Document.newDoc = function( title, langID, scriptID ) { // reset remote flag remoteLaunched = false; // // set default language // if( !langID || langID.toString().length <= 0 ) langID = "js"; // // set default title // if( !title ) title = localize( "$$$/ESToolkit/DefaultSourceName=Source%1", ++this.__sourceID__ ); // // set default script ID // if( !scriptID ) scriptID = "(Script" + ++this.__scriptID__ + ")"; var windowID = "doc" + ++this.__windowID__; var properties = "name: '" + windowID + "'"; var maximize = ( document ? document.window.maximized : false ); // // create window // var w = new Window ( "documentwindow { \ orientation : 'column', \ margins : 2, \ spacing : 2, \ properties : \ { \ minimumSize : [370, 180], \ }, \ toolbarGroup : Group \ { \ alignment : ['fill', 'top' ], \ orientation : 'row', \ margins : 0, \ spacing : 0, \ targetGroup : Group \ { \ alignment : ['fill','fill'], \ alignChildren : ['fill','fill'], \ orientation : 'row', \ margins : 0, \ spacing : 2, \ btnCon : IconButton \ { \ preferredSize : [24, 24], \ properties : { style : 'toolbutton' }, \ alignment : [ 'left', 'top' ], \ helpTip : '$$$/ESToolkit/Document/htCon=Click to connect to target application.' \ }, \ targetDDL : DropDownList \ { \ helpTip : '$$$/ESToolkit/Document/htTargets=Select the target application.' \ }, \ imgstate : Image \ { \ preferredSize : [18, 18], \ maximumSize : [18, 18], \ minimumSize : [18, 18], \ helpTip : '$$$/ESToolkit/Document/htState=Current state of selected engine.' \ }, \ engineDDL : DropDownList \ { \ helpTip : '$$$/ESToolkit/Document/htEngine=Select the engine of the target application.' \ } \ }, \ dummy01 : Group \ { \ preferredSize : [15,22], \ alignment : ['right','fill'] \ }, \ debugGroup : Group \ { \ alignment : ['right','fill'], \ orientation : 'row', \ margins : 0, \ spacing : 2, \ btnRun : IconButton \ { \ preferredSize : [24, 24], \ properties : { style : 'toolbutton' }, \ helpTip : '$$$/ESToolkit/Document/htRun=Start running script.' \ }, \ btnPause : IconButton \ { \ preferredSize : [24, 24], \ properties : { style : 'toolbutton' }, \ helpTip : '$$$/ESToolkit/Document/htHalt=Halt execution of the script.' \ }, \ btnStop : IconButton \ { \ preferredSize : [24, 24], \ properties : { style : 'toolbutton' }, \ helpTip : '$$$/ESToolkit/Document/htStop=Stop execution of the script.' \ }, \ btnStepover : IconButton \ { \ preferredSize : [24, 24], \ properties : { style : 'toolbutton' }, \ helpTip : '$$$/ESToolkit/Document/htStepover=Step over current script line.' \ }, \ btnStepinto : IconButton \ { \ preferredSize : [24, 24], \ properties : { style : 'toolbutton' }, \ helpTip : '$$$/ESToolkit/Document/htStepinto=Step into function call in the current line.' \ }, \ btnStepout : IconButton \ { \ preferredSize : [24, 24], \ properties : { style : 'toolbutton' }, \ helpTip : '$$$/ESToolkit/Document/htStepout=Step out of current executed function.' \ } \ } \ }, \ document : Document \ { \ maximumSize : [10000,10000], \ preferredSize : [390, 460], \ alignment : ['fill', 'fill' ], \ }, \ statusGroup : Group \ { \ alignment : ['fill', 'bottom' ], \ orientation : 'row', \ margins : 0, \ spacing : 0, \ maximumSize : [1000,22], \ infoStatus : Panel \ { \ alignment : ['fill','center'], \ margins : 0, \ spacing : 0, \ properties : { borderStyle : 'sunken' }, \ statustext : StaticText \ { \ properties : { truncate : 'middle' }, \ alignment : ['fill','center'], \ characters : 40 \ } \ }, \ posStatus : Panel \ { \ alignment : ['right','center'], \ margins : 0, \ spacing : 0, \ properties : { borderStyle : 'sunken' }, \ statustext : StaticText \ { \ properties : { truncate : 'middle' }, \ alignment : ['center','center'], \ characters : 20 \ } \ }, \ busyStatus : Group \ { \ alignment : ['right','center'], \ orientation : 'row', \ margins : [7,0,0,0], \ spacing : 0, \ imgbusy : Image \ { \ alignment : ['left', 'center'], \ preferredSize : [18, 18] \ }, \ sizeBoxSpacer : Group { \ size : [20,1] \ } \ } \ } \ }"); w.maximized = maximize; /////////////////////////////////////////////////////////////////////////////// // // create shortcuts // w.targetDDL = w.toolbarGroup.targetGroup.targetDDL; w.engineDDL = w.toolbarGroup.targetGroup.engineDDL; w.btnCon = w.toolbarGroup.targetGroup.btnCon; w.btnRun = w.toolbarGroup.debugGroup.btnRun; w.btnStepover = w.toolbarGroup.debugGroup.btnStepover; w.btnStepinto = w.toolbarGroup.debugGroup.btnStepinto; w.btnStepout = w.toolbarGroup.debugGroup.btnStepout; w.btnStop = w.toolbarGroup.debugGroup.btnStop; w.btnPause = w.toolbarGroup.debugGroup.btnPause; w.imgstate = w.toolbarGroup.targetGroup.imgstate; /////////////////////////////////////////////////////////////////////////////// // // set widths // w.targetDDL.preferredSize.width = 150; w.engineDDL.preferredSize.width = 100; /////////////////////////////////////////////////////////////////////////////// // // debugging buttons // w.btnRun.icon = ScriptUI.newImage( '#Run_R', '#Run_N' ); w.btnPause.icon = ScriptUI.newImage( '#Pause_R', '#Pause_N' ); w.btnStop.icon = ScriptUI.newImage( '#Stop_R', '#Stop_N' ); w.btnStepover.icon = ScriptUI.newImage( '#StepOver_R', '#StepOver_N' ); w.btnStepinto.icon = ScriptUI.newImage( '#StepInto_R', '#StepInto_N' ); w.btnStepout.icon = ScriptUI.newImage( '#StepOut_R', '#StepOut_N' ); w.btnRun.onClick = menus.debug.run.onSelect; w.btnPause.onClick = menus.debug.pause.onSelect; w.btnStop.onClick = menus.debug.stop.onSelect; w.btnStepover.onClick = menus.debug.over.onSelect; w.btnStepinto.onClick = menus.debug.into.onSelect; w.btnStepout.onClick = menus.debug.out.onSelect; /////////////////////////////////////////////////////////////////////////////// // // connect button // w.btnCon.iconConnected = ScriptUI.newImage( '#Connected_R', '#Connected_N' ); w.btnCon.iconDisconnected = ScriptUI.newImage( '#Disconnected_R', '#Disconnected_N' ); w.btnCon.iconConnecting = ScriptUI.newImage( '#Connecting_R', '#Connecting_N' ); w.btnCon.icon = w.btnCon.iconConnected; w.btnCon.onClick = function() { var targetName = this.window.document.getCurrentTargetName(); if( targetMgr.getConnected( targetName ) ) Debugger.disconnect( targetName, true ); else targetMgr.select( targetName, '', this.window.document ); } /////////////////////////////////////////////////////////////////////////////// // // engine state icon // w.imgstate.iconInactive = ScriptUI.newImage( '#InactiveEngine', '#InactiveEngine' ); w.imgstate.iconWait = ScriptUI.newImage( '#WaitingEngine', '#InactiveEngine' ); w.imgstate.iconRun = ScriptUI.newImage( '#RunningEngine', '#InactiveEngine' ); w.imgstate.iconStop = ScriptUI.newImage( '#StoppedEngine', '#InactiveEngine' ); w.imgstate.icon = w.imgstate.iconInactive; /////////////////////////////////////////////////////////////////////////////// // // targets & engines dropdown lists // //----------------------------------------------------------------------------- // // w.getChangingTargetEngine(...) // // Purpose:get/set change status of targets & engines - DropDownLists // //----------------------------------------------------------------------------- w.getChangingTargetEngine = function() { return ( targetMgr.isChanging() || this.userChangeTargetEngine ); } w.setChangingTargetEngine = function( change ) { this.userChangeTargetEngine = change; targetMgr.setIsChanging( change ); } //----------------------------------------------------------------------------- // // w.targetDDL.onChange(...) // // Purpose:selection of targets list changed // //----------------------------------------------------------------------------- w.targetDDL.onChange = function() { if( !appInShutDown ) { // // we process only change events if the user selects a new target // if( !this.window.getChangingTargetEngine() ) { var targetItem = this.selection; if( targetItem ) { this.window.setChangingTargetEngine( true ); // // set active target at target manager // (cause notify 'changeActiveEngine') // targetMgr.setActive( targetItem.target, null, this.document ); this.window.setChangingTargetEngine( false ); } if( targetItem && !targetMgr.getConnected( targetItem.target ) ) { if( PrefUtils.getValue( 'prefs.autolaunch', 'Boolean' ) || ( targetItem && BridgeTalk.isRunning( targetItem.target ) ) ) this.window.btnCon.notify(); } } } } //----------------------------------------------------------------------------- // // w.engineDDL.onChange(...) // // Purpose: selection of engines list changed // //----------------------------------------------------------------------------- w.engineDDL.onChange = function() { if( !appInShutDown ) { // // we process only change events if the user selects a new target // if( !this.window.getChangingTargetEngine() ) { var activeTarget = targetMgr.getActiveTarget(); var engineItem = this.selection; if( activeTarget && engineItem ) { this.window.setChangingTargetEngine( true ); // // set active engine at current active target // (cause notify 'changeActiveEngine') // activeTarget.setActive( engineItem.engine ); this.window.setChangingTargetEngine( false ); } } } } /////////////////////////////////////////////////////////////////////////////// // // document // //----------------------------------------------------------------------------- // // w.document.addTarget(...) // // Purpose: add new target to list // //----------------------------------------------------------------------------- w.document.addTarget = function( target ) { var oldSelection = 0; if( this.window.targetDDL.selection ) oldSelection = this.window.targetDDL.selection; this.window.setChangingTargetEngine( true ); var item = this.window.targetDDL.add( 'item', target.title ); item.target = target.targetName; this.window.targetDDL.selection = oldSelection; this.window.setChangingTargetEngine( false ); } //----------------------------------------------------------------------------- // // w.document.setupTargets(...) // // Purpose: setup targets list // //----------------------------------------------------------------------------- w.document.setupTargets = function() { this.window.setChangingTargetEngine( true ); this.window.targetDDL.removeAll(); this.window.engineDDL.removeAll(); var alltargets = targetMgr.getTargets(); if( alltargets ) { for( var i=0; i 0 ) { for( var i=0; i 0 && display > 0 ) { var level = PrefUtils.getValue( 'prefs.profiling.profileLevel', 'Number' ); this.profiling = display == 1 ? level-1 : level; } } //----------------------------------------------------------------------------- // // w.document.onNotify(...) // // Purpose: notify handler // //----------------------------------------------------------------------------- w.document.onNotify = function( reason ) { this.window.updateToolbarState(); var targetName = this.getCurrentTargetName(); var engineName = this.getCurrentEngineName(); switch( reason ) { case 'filechanged' : { var newFile = arguments[1]; if( newFile.absoluteURI == File( this.scriptID ).absoluteURI ) { var reload = true; if (this.isModified()) // Always ask if the file has been modified reload = true; /* // tpr queryBox ("$$$/ESToolkit/Alerts/AutoreloadChanged=File %1^nhas been changed.^nDo you want to reload it and lose your changes?", decodeURIComponent( newFile.fsName ) ); */ else if (!PrefUtils.getValue( 'prefs.document.autoReload', 'Boolean' )) // Autoreload off: ask if not modified reload = true; /* // tpr queryBox ("$$$/ESToolkit/Alerts/AutoreloadUnchanged=File %1^nhas been changed.^nDo you want to reload it?", decodeURIComponent( newFile.fsName ) ); */ if (reload) { newFile.encoding = this.encoding; var text = Document.safeRead (newFile); if (null != text) { this.encoding = newFile.encoding; this.setText( text, false ); this.setSavePoint(); this.setTitle(); } } } } break; case 'startConnect': { if( targetName == arguments[1] ) { this.window.connecting = true; this.window.updateToolbarState(); } } break; case 'endConnect': { if( targetName == arguments[1] ) { this.window.connecting = false; this.window.updateToolbarState(); } } break; case 'state': { if( targetName == arguments[1].target ) this.setEngineState( arguments[1].target, arguments[1].engine ); } break; case 'changeActiveTarget': case 'changeActiveEngine': { // // active engine (and probably the target) changed at target manager // this.selectActiveTarget( arguments[1] ) this.window.updateToolbarState(); } break; case 'targetDied': // nothing to do break; case 'addTarget': // new target added this.addTarget( arguments[1] ); this.window.updateToolbarState(); break; case 'changeTargets': // new targets list this.setupTargets(); break; case 'removeEngines': case 'changeEngines': // new engines list { if( targetName == arguments[1].targetName ) this.setupEngines( arguments[1] ); } break; case 'autoCompletionPrefsChanged': if (Document.autoCompletion) { // cancel any pending timer app.cancelTask (Document.autoCompletion.autoID); Document.autoCompletion = null; } break; case 'shutdown': globalBroadcaster.unregisterClient( this ); this.window.setChangingTargetEngine( true ); this.window.targetDDL.removeAll(); this.window.engineDDL.removeAll(); break; } } w.document.canAutoComplete = function( style ) { // // TODO: this information should come from syntaxdefs.xml // var ret = true; switch( style ) { case 1: case 2: case 3: case 6: case 7: case 12: case 13: case 15: ret = false; } return ret; } w.document.startAutoCompletion = function() { if( this.textselection.length == 0 && this.wordRight.length == 0 ) { var pos = this.getLogicalPos(); var line = this.lines[pos[0]]; var searchStr = this.wordLeft; // // include classname // if( line.charAt( line.length - searchStr.length - 1 ) == '.' ) { var prevWord = this.getWordAt( pos[2] - searchStr.length - 1 ); if( prevWord.length > 0 && prevWord.charCodeAt(0) > 64 && prevWord.charCodeAt(0) < 91 ) searchStr = prevWord + '.' + searchStr; } if( searchStr.length > 0 && searchStr != this.lastAutoComplete ) { // // since this document is actually active // the current debugger has the same target // as this document // if( currentDebugger ) { // // ask for code hints (an array is returned) // every line has the format [Classname.]Elementname[ - helptext] // var strs = currentDebugger.getCodeHints( searchStr ); // // show auto completion listbox // if( strs && strs.length > 0 ) this.showAutoCompletion( strs ); } } } } /////////////////////////////////////////////////////////////////////////////// // // Document UI handler // w.document.onLineClick = function (line) { this.toggleBreakpoint (line); } w.document.onUpdateUI = function() { var pos = this.getLogicalPos(); this.setCursorPos( pos[0], pos[1] ); if( PrefUtils.getValue( 'prefs.autocompletion', 'Boolean' ) && pos[1] == this.currentPos[1]+1 && pos[0] == this.currentPos[0] ) { if( Document.autoCompletion ) app.cancelTask( Document.autoCompletion.autoID ); if( this.canAutoComplete( this.currentStyle ) ) { var time = PrefUtils.getValue( 'prefs.autotime', 'Number' ); var id = app.scheduleTask( "Document.startAutoCompletion();", time * 1000, false ); Document.autoCompletion = { autoDoc : this , autoID : id }; } } this.currentPos = pos; } w.document.onAutocomplete = function( text ) { if( this.textselection.length == 0 && this.wordRight.length == 0 ) { // // The text format is [Classname.]Elementname[: help text] // var fullText = text.split(": ")[0]; var classText = fullText.split('.'); var elementText = classText.length > 0 ? classText[classText.length-1] : ''; var searchText = this.wordLeft; if( elementText.length > 0 && elementText.indexOf( searchText ) == 0 ) { this.lastAutoComplete = elementText; // // Update the OMV UI // currentDebugger.displaySelectedCodeHint (text); // // insert the completion // elementText = elementText.substr( searchText.length ); this.insert( elementText, this.getLogicalPos()[2] ); var curSel = this.getSelection(); this.setSelection( curSel[0], curSel[1]+elementText.length, curSel[0], curSel[1]+elementText.length ); } } } w.document.onMouseOver = function( line, text ) { if( currentDebugger && prefs.dynamicHelp.valueOf() ) currentDebugger.getHelpTip( this, line, text ); else this.helpTip = ''; } /////////////////////////////////////////////////////////////////////////////// // // Window // //----------------------------------------------------------------------------- // // w.updateToolbarState(...) // // Purpose: Update UI states of toolbar area // //----------------------------------------------------------------------------- w.updateToolbarState = function() { var targetName = ''; var engineName = ''; if( this.targetDDL.selection ) targetName = this.targetDDL.selection.target; if( this.engineDDL.selection ) engineName = this.engineDDL.selection.engine; // // disable engine DDL if target isn't connected // if( targetMgr.getConnected( targetName ) || targetMgr.defaultTarget.targetName == targetName ) { this.engineDDL.enabled = true; this.btnCon.icon = this.btnCon.iconConnected; } else { this.engineDDL.enabled = false; this.btnCon.icon = this.btnCon.iconDisconnected; } // // set connect button icon if we just about to connect // if( this.connecting ) this.btnCon.icon = this.btnCon.iconConnecting; // // debugging state // // // Is there a debugger for the current target & engine ? // If there is one and if it's running then don't let // the user change target or engine! // if( this.document.isDebugging() ) { // // debugger of document is actually running, so disable target&engine DropDownList // this.targetDDL.enabled = false; this.engineDDL.enabled = false; } else { this.targetDDL.enabled = true; if( this.engineDDL.enabled ) // don't enable if it was disabled before this.engineDDL.enabled = true; } // // Is there any other debugger for the current target? // If there is one (but not using the current engine) and // it's running then don't let the user start another // session at the same target but different engine! // var canDebug = this.document.canDebug(); if( this.document == document ) { // update menu items, too menus.debug.reflectState(); } else this.updateDebugButtonStates( !canDebug && targetMgr.getConnected( targetName ) ); // update current engine state icon this.document.setEngineState( targetName, engineName ); } //----------------------------------------------------------------------------- // // w.updateDebugButtonStates(...) // // Purpose: Update UI states of debugging buttons // //----------------------------------------------------------------------------- w.updateDebugButtonStates = function( disable ) { var forceDisable = false; if( disable ) forceDisable = true; var targetName = ''; var engineName = ''; if( this.targetDDL.selection ) targetName = this.targetDDL.selection.target; if( this.engineDDL.selection ) engineName = this.engineDDL.selection.engine; var running = false; var stopped = false; var dbg = Debugger.find( targetName, engineName ); if( dbg ) { running = ( dbg.state == Debugger.RUNNING ); stopped = ( dbg.state == Debugger.STOPPED ); } switch( this.document.status ) { case "noexec": // not executable this.btnRun.setEnabled( false ); this.btnStepover.setEnabled( false ); this.btnStepinto.setEnabled( false ); this.btnStepout.setEnabled( false ); this.btnStop.setEnabled( false ); this.btnPause.setEnabled( false ); break; case "exec": // standard executable this.btnRun.setEnabled( !forceDisable && ( !running || stopped ) ); this.btnStepover.setEnabled( !forceDisable && ( !running || stopped ) ); this.btnStepinto.setEnabled( !forceDisable && ( !running || stopped ) ); this.btnStepout.setEnabled( !forceDisable && stopped ); this.btnStop.setEnabled( !forceDisable && ( running || stopped ) ); this.btnPause.setEnabled( !forceDisable && running ); break; case "dynamic": // dynamic script, not saveable this.btnRun.setEnabled( !forceDisable && stopped ); this.btnStepover.setEnabled( !forceDisable && stopped ); this.btnStepinto.setEnabled( !forceDisable && stopped ); this.btnStepout.setEnabled( !forceDisable && stopped ); this.btnStop.setEnabled( !forceDisable && stopped ); this.btnPause.setEnabled( false ); break; } } /////////////////////////////////////////////////////////////////////////////// // // busy animation // w.document.busyID = app.initBusyPlaceholderImage( w.statusGroup.busyStatus.imgbusy ); w.id = windowID; /////////////////////////////////////////////////////////////////////////////// // // Window UI handler // w.onResize = function() { this.layout.resize(); }; w.onActivate = function() { if( !this.userChangeTargetEngine ) { this.document.activate(); if( this.targetDDL.selection && this.engineDDL.selection ) { var target = this.targetDDL.selection.target; var engine = this.engineDDL.selection.engine; if( target.length && engine.length ) { // // if target&engine is not active at the moment // set them active // var activeTarget = targetMgr.getActiveTarget(); var activeEngine = ''; if( activeTarget ) { activeEngine = activeTarget.getActive(); activeTarget = activeTarget.targetName; } if( activeTarget != target || activeEngine != engine ) { targetMgr.setActive( target, engine, this.document ); } } } else { this.document.selectActiveTarget( targetMgr.getActiveTarget() ) this.updateToolbarState(); } menus.debug.reflectState(); var pos = this.document.getLogicalPos(); this.document.setCursorPos( pos[0], pos[1] ); } this.document.activeStyle = true; if( this.minimized ) this.minimized = false; } w.onDeactivate = function() { this.document.clearCursorPos(); this.document.activeStyle = false; if( document == this.document ) { document = null; if( !appInShutDown ) globalBroadcaster.notifyClients( 'activeDocChanged' ); } } w.onShow = function() { this.document.readPrefs(); } w.onClose = function() { if( this.document.isDebugging() ) { this.document.setStatusLine( '$$$/ESToolkit/Status/StopDebugForClose=Stop debugging before closing document' ); return false; } if( this.document.isModified() && !this.document.save( false, app.enableStandardUI ) ) return false; this.document.writePrefs(); targetMgr.unregisterClient( this.document ); Debugger.unregisterClient( this.document ); // // remove from documents list // for (var i = 0; i < documents.length; i++) { if( documents[i] == this.document ) { documents.splice (i, 1); break; } } // // switch to last opened document // if( !appInShutDown ) { globalBroadcaster.notifyClients( 'activeDocChanged' ); globalBroadcaster.notifyClients( 'numDocsChanged' ); } if (document == this.document) { document = null; if (documents.length) documents [documents.length-1].active = true; } addDelayedTask (menus.updateWindowMenu); this.document.setScriptID(); } w.document.currentPos = [0,0]; w.document.lastAutoComplete = ""; w.document.roState = false; w.document.lf = PrefUtils.getValue( 'prefs.document.lineend', 'String' ).toLowerCase(); w.document.encoding = "UTF-8"; w.document.profileData = []; w.document.includePath = ''; w.document.autoIndent = PrefUtils.getValue( 'prefs.document.autoIndent', 'Number' ); w.document.setScriptID( scriptID ); if (w.document.isFile()) { var f = File (w.document.scriptID); w.document.paneTitle = f.fsName; w.document.fileName = f.name; w.document.roState = f.readonly; } else { w.document.paneTitle = w.document.fileName = decodeURIComponent (title); } if( langID == 'js' ) w.document.status = 'exec'; else w.document.status = 'noexec'; w.document.clearUndo(); w.origTitle = w.paneTitle; w.document.setTitle(); // update the global document variables document = w.document; documents.push (w.document); w.document.setLanguage (langID); if( w.document.status == 'noexec' ) w.toolbarGroup.enabled = false; globalBroadcaster.registerClient( w.document ); targetMgr.registerClient( w.document ); Debugger.registerClient( w.document ); targetMgr.setIsChanging( true ); w.document.setupTargets(); w.document.setupEngines(); targetMgr.setIsChanging( false ); if( !appInShutDown ) { globalBroadcaster.notifyClients( 'activeDocChanged' ); globalBroadcaster.notifyClients( 'numDocsChanged' ); } addDelayedTask (menus.updateWindowMenu); return w; } /////////////////////////////////////////////////////////////////////////////// // // Document UI handler // Document.prototype.onCreate = function() {} Document.prototype.onLoad = function() {} Document.prototype.onKey = function (key) { // print (key); } Document.prototype.onActivate = function() { if( this.paneTitle ) { if (this != document) { document = this; if( !appInShutDown ) globalBroadcaster.notifyClients( 'activeDocChanged' ); } this.window.updateToolbarState(); } } Document.prototype.onDeactivate = function() { if( this.window.updateToolbarState ) this.window.updateToolbarState(); } Document.prototype.onChange = function() { if( !this.ignoreChange ) { // If we are debugging, we need to stop if( currentDebugger && currentDebugger.isActive() && this.isDebugging() ) { if( queryBox( "$$$/ESToolkit/Alerts/DebuggingUnchanged=The script of the document %1 is in debug mode.^nDo you want to stop debugging to enter your changes?", decodeURIComponent(this.fileName) ) ) { currentDebugger.stop(); } else { var oldindent = this.autoIndent; this.autoIndent = 0; var src = "var oldind="+oldindent+"; \ var __doc__=Document.find('" + this.scriptID + "'); \ if(__doc__){ \ var old=__doc__.ignoreChange; \ __doc__.ignoreChange=true; \ __doc__.undo(); \ __doc__.autoIndent=oldind; \ __doc__.ignoreChange=old; \ __doc__.setTitle();}"; app.scheduleTask( src, 10 ); } } if( this.badLine ) { this.setCurrentLine( this.badLine, colors.White ); delete this.badLine; } if( this.paneTitle ) this.setTitle(); } } Document.prototype.onLineNumbersChanged = function() { breakpoints.updateFromDoc (this); } //----------------------------------------------------------------------------- // // Document.prototype.isFile(...) // // Purpose: Is this document a disk file? // //----------------------------------------------------------------------------- Document.prototype.isFile = function() { // true if the scriptID contains an absolute URI. // Do not use File.exists - it may be slow on networked files return( this.scriptID && ( this.scriptID[0] == '/' || this.scriptID[0] == '~' ) ); } //----------------------------------------------------------------------------- // // Document.prototype.activate(...) // // Purpose: De/activate the document. // //----------------------------------------------------------------------------- Document.prototype.activate = function() { this.parent.active = true; this.active = true; // TODO: do we need this? if (this.paneTitle && (this != document)) { document = this; if( !appInShutDown ) globalBroadcaster.notifyClients( 'activeDocChanged' ); } } Document.prototype.deactivate = function() { this.active = false; } //----------------------------------------------------------------------------- // // Document.prototype.setText(...) // // Purpose: set documents content // //----------------------------------------------------------------------------- Document.prototype.setText = function( text, silent ) { if( typeof silent == 'undefined' ) silent = true; var oldState = this.ignoreChange; this.ignoreChange = silent; this.text = text; if( silent ) this.setSavePoint(); this.ignoreChange = oldState; } //----------------------------------------------------------------------------- // // Document.prototype.setTitle(...) // // Purpose: Set the title with readonly and modified indicators // //----------------------------------------------------------------------------- Document.prototype.setTitle = function() { var title = this.paneTitle; if (title.length) { if (this.roState) title = localize ("$$$/ESToolkit/Status/ReadOnlyIndicator=[R/O]") + " " + title; if (this.isModified()) title = "* " + title; if (this.parent.text != title) this.parent.text = title; } } //----------------------------------------------------------------------------- // // Document.prototype.insertVersionTag(...) // // Purpose: Insert a Version tag // //----------------------------------------------------------------------------- Document.prototype.insertVersionTag = function() { if (this.isFile()) { var name = decodeURIComponent( File (this.scriptID).name ); var text = "@@@" + "BUILDINFO" + "@@@ " + name + " !Version! " + new Date().toString(); if (this.find ("@@@" + "BUILDINFO" + "@@@", 2)) { // replace current string var sel = this.getSelection(); this.setSelection (sel[0], sel [1], sel[0]+1, 0); this.textselection = text + "\n"; } else { var sel = this.getSelection(); this.setSelection (sel[0], 0); this.textselection = "/**\n* " + text + "\n*/\n"; } } } //----------------------------------------------------------------------------- // // Document.prototype.reload(...) // // Purpose: Reload document contents (if not modified) // //----------------------------------------------------------------------------- Document.prototype.reload = function() { if( this.isFile() && !this.isModified() ) { var myFile = new File( this.scriptID ); myFile.encoding = this.encoding; var text = Document.safeRead (myFile); if (null != text) { this.encoding = myFile.encoding; this.setText( text, false ); this.setSavePoint(); this.setTitle(); } } } //----------------------------------------------------------------------------- // // Document.prototype.setSaved(...) // // Purpose: Set the saved state // //----------------------------------------------------------------------------- Document.prototype.setSaved = function( uri ) { if( uri ) this.setScriptID( uri ); if (this.isFile()) { var f = File (this.scriptID); this.paneTitle = f.fsName; this.fileName = f.name; this.roState = f.readonly; var langID = this.langID; if( !langID || ( langID && langID == '' ) ) langID = lang.getLanguageForFile (File (this.scriptID)); if (langID) this.setLanguage (langID); if( menus.file.recent ) menus.file.recent.add (this.scriptID, this.langID); } this.setSavePoint(); this.setTitle(); } //----------------------------------------------------------------------------- // // Document.prototype.save(...) // // Purpose: Save the document: // saveAs - invoke Save As // ask - ask before saving // retuns true if saved, false on errors or if the result of asking // was Cancel // //----------------------------------------------------------------------------- Document.prototype.save = function (saveAs, ask) { // do not save non-documents if (!this.paneTitle) return true; // TODO: save to target if (ask) { switch (app.saveAlert ( decodeURIComponent(this.fileName))) { case -1: return false; case 0: return true; } } var f = null; if (saveAs) { if( !this.currentFolder ) this.currentFolder = app.currentFolder; var obj = lang.getLexerAndStyles (this.langID); var proposedName = this.fileName; var fileExt = '.' + obj.defFileExt; if( proposedName.indexOf( fileExt ) < 0 ) proposedName += fileExt; var f = File( this.currentFolder + '/' + proposedName ); f = f.saveDlg( localize( "$$$/ESToolkit/FileDlg/SaveAs=Save As" ), lang.buildFileTypes (this.langID) ); if(f) // remember the folder this.currentFolder = app.currentFolder = f.parent ? f.parent.absoluteURI : "/"; } else { // normal save // do nothing if doc is not modified if (!this.isModified()) return true; if (this.scriptID[0] == '(') // no file name yet return this.save (true); // TODO: save to target f = new File (this.scriptID); } if (f) { // if the selected file already is open, do not save var doc = Document.find (f.absoluteURI); if (doc && doc != this) { errorBox ("$$$/ESToolkit/FileDlg/InUse=File %1 is currently opened and cannot be overwritten.", decodeURIComponent(f.name) ); return false; } // If the file is read-only, abort if (f.readonly) { var msg = _win ? "$$$/ESToolkit/FileDlg/ProtectedWin=Could not save as %1 because the file is locked.^nUse the 'Properties' command in the Windows Explorer to unlock the file." : "$$$/ESToolkit/FileDlg/ProtectedMac=Could not save as %1 because the file is locked.^nUse the 'Get Info' command in the Finder to unlock the file."; errorBox( msg, decodeURIComponent(f.name) ); return false; } var error = ""; if( f.open("w") ) { // Remove from Folder Watch to inhibit own notification app.removeFileWatch( this, f ); f.encoding = this.encoding; f.lineFeed = this.lf; f.write (this.text); error = f.error; f.close(); if (error == "") error = f.error; // we are good citizen app.notifyFileChanged (f); // and re-enable file watch app.addFileWatch( this, f ); } else error = f.error; if (error != "") errorBox ("$$$/ESToolkit/FileDlg/CannotWrite=Cannot write to file %1!\n" + error, decodeURIComponent( f.name ) ); else { this.setSaved (f.absoluteURI); if( saveAs ) { scripts.fillScripts(); menus.updateWindowMenu(); } return true; } } return false; } //----------------------------------------------------------------------------- // // Document.prototype.exportAsBinary(...) // // Purpose: Export script as jsxbin // //----------------------------------------------------------------------------- Document.prototype.exportAsBinary = function() { var s; // do not save non-documents or docs that are not JS if (!this.paneTitle || (this.langID != "js")) return true; if( !this.checkSyntax( this.includePath ) ) return false; try { s = app.compile (this.text); } catch (e) { return false; } if( !this.currentFolder ) this.currentFolder = app.currentFolder; var pos = this.fileName.lastIndexOf ('.'); if( pos < 0 ) pos = this.fileName.length; var proposedName = this.fileName.substr( 0, pos ) + ".jsxbin"; var f = File( this.currentFolder ); f.changePath( proposedName ); f = f.saveDlg( localize( "$$$/ESToolkit/FileDlg/ExportAsBinary=Export To Binary JavaScript" ), localize( "$$$/ESToolkit/FileDlg/JSXBIN=Binary JavaScript files:*.jsxbin" )); if(f) { // remember the folder this.currentFolder = app.currentFolder = f.parent ? f.parent.absoluteURI : "/"; // If the file is read-only, abort if (f.readonly) { var msg = _win ? "$$$/ESToolkit/FileDlg/ProtectedWin=Could not save as %1 because the file is locked.^nUse the 'Properties' command in the Windows explorer to unlock the file." : "$$$/ESToolkit/FileDlg/ProtectedMac=Could not save as %1 because the file is locked.^nUse the 'Get Info' command in the Finder to unlock the file."; errorBox (msg, decodeURIComponent( f.name ) ); return false; } if (f.open ("w")) { f.lineFeed = this.lf; f.encoding = this.encoding; f.write (s); f.close(); // we are good citizen app.notifyFileChanged (f); } if (f.error != "") errorBox ("$$$/ESToolkit/FileDlg/CannotWrite=Cannot write to file %1!", decodeURIComponent( f.name ) ); else return true; } return false; } //----------------------------------------------------------------------------- // // Document.prototype.close(...) // // Purpose: Close the document (return false on error or abort) // //----------------------------------------------------------------------------- Document.prototype.close = function() { // do not close non-documents if (this.paneTitle) return this.parent.close(); return true; } //----------------------------------------------------------------------------- // // Document.prototype.setStyles(...) // // Purpose: Set an XML list of styles // //----------------------------------------------------------------------------- Document.prototype.setStyles = function (styles) { if (styles) { for (var i = 0; i < styles.length(); i++) { var style = styles [i]; // Never set the default style if (style.@index == 32) continue; //