/**************************************************************************
*
*  @@@BUILDINFO@@@ 85findReplaceDialog-2.jsx 2.0.1.61  14-March-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.
**************************************************************************/

app.createFR = function( where )
{
	findReplaceObj = new DocFindReplace( where );
	findReplaceObj.initialShow = true;
    findReplaceObj.show();
	findReplaceObj.initialShow = false;
	globalBroadcaster.registerClient( findReplaceObj );	                                
}

///////////////////////////////////////////////////////////////////////////////
//
// F&R object
//
DocFindReplace.WHERE_CURRDOC    = 0;
DocFindReplace.WHERE_CURRSEL    = 1;
DocFindReplace.WHERE_ALLDOCS    = 2;	// multiple find
DocFindReplace.WHERE_FAVORITES  = 3;	// multiple find
DocFindReplace.WHERE_CURRENGINE = 4;	// multiple find

function DocFindReplace( where ) 
{ 
	this.strFind                = "$$$/ESToolkit/FindReplaceDlg/Find=&Find";
	this.strFindNext            = "$$$/ESToolkit/FindReplaceDlg/FindNext=&Find Next";
	this.strFindAll				= "$$$/ESToolkit/FindReplaceDlg/FindAll=&Find All";
	this.strSearchFailed        = "$$$/ESToolkit/FindReplaceDlg/Alerts/SearchFailed=No matches found";
	this.strSearchFailedRetry   = "$$$/ESToolkit/FindReplaceDlg/Alerts/SearchFailedRetry=The end of the document has been reached.^nContinue checking from the beginning?";
	this.strReplacementDone     = "$$$/ESToolkit/FindReplaceDlg/Alerts/ReplacementDone=Search complete. %1 changes were made.";
	this.strOneReplacementDone  = "$$$/ESToolkit/FindReplaceDlg/Alerts/OneReplacementDone=Search complete. One change was made.";

    //
	// The Find/Replace floating palette resource
	//
	var dlgResSpec = "dockpalette {							\
		properties  :										\
		{													\
    	    defaultVisibility : false,						\
		    closeOnKey  : 'Escape',							\
		    minimumSize : [335,160],						\
		    maximumSize : [5000,1000],						\
		    name        : 'findAndReplace',					\
			icon : '#PFindReplace_N',						\
			rollover : '#PFindReplace_R',"
			+ where + " 									\
        },													\
		text        : '$$$/ESToolkit/FindReplaceDlg/Title=Find and Replace', \
		alignment   : ['fill','top'],						\
		orientation : 'column',								\
		alignChildren: 'top',								\
		margins     : 5,									\
		spacing		: 5,									\
		topGroup : Group									\
		{													\
			alignment   : ['fill','top'],					\
			orientation : 'row',							\
			findGrp    :	Group							\
			{												\
				alignment       : ['fill','top'],			\
				orientation     : 'column',					\
				alignChildren   : 'left',					\
				margins			: 0,						\
				search          : Group						\
				{											\
					alignment       : ['fill','top'],		\
					orientation     : 'row',				\
					lbl             : StaticText			\
					{										\
						text            : '$$$/ESToolkit/FindReplaceDlg/FindLbl=Find:' \
					},										\
					string          :	EditText			\
					{										\
        				alignment       : ['fill','top'],	\
						helpTip         : '$$$/ESToolkit/FindReplaceDlg/htFind=A text string to search for', \
						properties      : { enterKeySignalsOnChange : false }   \
					}										\
				},											\
				replace: Group								\
				{											\
					alignment       : ['fill','top'],		\
					orientation     : 'row',				\
					lbl             : StaticText { text : '$$$/ESToolkit/FindReplaceDlg/ReplaceWith=Replace With:' },   \
					string          : EditText				\
					{										\
        				alignment       : ['fill','top'],	\
						helpTip         : '$$$/ESToolkit/FindReplaceDlg/htReplaceWith=A text string to replace the search text',\
						properties      : { enterKeySignalsOnChange : false }   \
					}										\
				},											\
				where:	Group								\
				{											\
					alignment		: ['fill','center'],	\
					orientation     : 'row',				\
					lbl             : StaticText			\
					{										\
        				alignment       : ['left','center'],\
						text            : '$$$/ESToolkit/FindReplaceDlg/Where=&Search Where:'	  \
					},										\
					list	       : DropDownList			\
					{										\
					    preferredSize   : [180,21],         \
        				alignment       : ['fill','center'],\
						helpTip         : '$$$/ESToolkit/FindReplaceDlg/htWhere=Choose where to search'	  \
					},										\
				}											\
			},												\
			btnsGrp:	Group								\
			{												\
				alignment       : ['right','fill'],			\
				orientation     : 'column',					\
				alignChildren   : 'fill',					\
				margins			: 0,						\
				spacing			: 5,						\
				find            : Button					\
				{											\
					enabled         : true,					\
					text            : '$$$/ESToolkit/FindReplaceDlg/Find=&Find',\
					helpTip         : '$$$/ESToolkit/FindReplaceDlg/Btn/htFind=Find the specified text string'  \
				},											\
				replace         : Button					\
				{											\
					enabled         : true,					\
					text            : '$$$/ESToolkit/FindReplaceDlg/Btn/Replace=&Replace',		  \
					helpTip         : '$$$/ESToolkit/FindReplaceDlg/Btn/htReplace=Replace the selected text with the specified text'	  \
				},											\
				replaceFind     : Button					\
				{											\
					enabled         : true,					\
					helpTip         : '$$$/ESToolkit/FindReplaceDlg/Btn/htReplaceFind=Replace the selected text with the specified text, and find the next occurence',  \
					text            : '$$$/ESToolkit/FindReplaceDlg/Btn/ReplaceFind=Replace && Fi&nd'	  \
				},											\
				replaceAll      : Button					\
				{											\
					enabled         : true,					\
					text    : '$$$/ESToolkit/FindReplaceDlg/Btn/ReplaceAll=Replace &All',  \
					helpTip : '$$$/ESToolkit/FindReplaceDlg/Btn/htReplaceAll=Replace all occurences of the selected text with the specified text'	  \
				}											\
			}												\
		},													\
		bottomGroup:	Group								\
		{													\
			orientation     : 'row',						\
			alignChildren   : ['left','top'],				\
			margins			: 0,							\
			left:	Group									\
			{												\
				orientation     : 'column',					\
				alignChildren   : ['left','top'],			\
				matchCase       : Checkbox					\
				{											\
					text            : '$$$/ESToolkit/FindReplaceDlg/MatchCase=Match &Case',	  	\
					helpTip         : '$$$/ESToolkit/FindReplaceDlg/htMatchCase=Only matches with the same capitalization will be found'	  	\
				},											\
				wholeWord       : Checkbox					\
				{											\
					text            : '$$$/ESToolkit/FindReplaceDlg/FindWholeWord=Match &Whole Word',	 	\
					helpTip         : '$$$/ESToolkit/FindReplaceDlg/htFindWholeWord=Only matches that are an entire word will be found'	  	\
				},											\
			},												\
			right: Group									\
			{												\
				orientation     : 'column',					\
				alignChildren   : ['left','top'],			\
				matchRegExp     : Checkbox					\
				{											\
					text            : '$$$/ESToolkit/FindReplaceDlg/MatchRegExp=Match Regular E&xpression',		\
					helpTip         : '$$$/ESToolkit/FindReplaceDlg/htMatchRegExp=Only strings which match the given regular expression will be found'		\
				},											\
				clearResults: Checkbox						\
				{											\
					text            : '$$$/ESToolkit/FindReplaceDlg/ClearResults=&Clear Old Results', 	 	\
					helpTip         : '$$$/ESToolkit/FindReplaceDlg/htClearResults=Clear old results.'	 	\
				}											\
			}												\
		}													\
	}";

	// Create the floating palette, link it to the FindReplace object
	this.palette = new Window (dlgResSpec);
	this.palette.findReplaceObj = this; 
	
	this.baseFolder		= "";	// the base folder for Favorites search
	this.where			= DocFindReplace.WHERE_CURRDOC;

	this.searchEdit		= this.palette.topGroup.findGrp.search.string;
	this.replaceEdit	= this.palette.topGroup.findGrp.replace.string;
	this.whereList		= this.palette.topGroup.findGrp.where.list;
	this.findBtn		= this.palette.topGroup.btnsGrp.find;
	this.replaceBtn		= this.palette.topGroup.btnsGrp.replace;
	this.replaceFindBtn	= this.palette.topGroup.btnsGrp.replaceFind;
	this.replaceAllBtn	= this.palette.topGroup.btnsGrp.replaceAll;
	this.matchCase		= this.palette.bottomGroup.left.matchCase;
	this.wholeWord		= this.palette.bottomGroup.left.wholeWord;
	this.matchRegExp	= this.palette.bottomGroup.right.matchRegExp;
	this.clearResults	= this.palette.bottomGroup.right.clearResults;

	// Set update event handlers for Find and Replace strings
	this.searchEdit.onChanging  = 
	this.searchEdit.onChange    =
	this.replaceEdit.onChanging = 
	this.replaceEdit.onChange   = function ()
	{
		this.window.findReplaceObj.resetFindReplace (true);
	}

    this.searchEdit.onEnterKey = function()
	{
	    this.window.findReplaceObj.findBtn.notify();
	}
		
    this.replaceEdit.onEnterKey = function ()
	{
	    this.window.findReplaceObj.replaceBtn.notify();
	}

	// Set update event handlers for 'match options' checkboxes
	this.matchCase.onClick =
	this.wholeWord.onClick =
	this.matchRegExp.onClick = function ()
	{
		//	A match option is changing: reset FindReplace controls state
		this.window.findReplaceObj.resetFindReplace (true);
	}

	// Set onClick event handlers for the buttons pane
	this.findBtn.onClick = function ()
	{
		var frObj = this.window.findReplaceObj;
		frObj.find (false);
		/*	We want the search string to retain the focus after a
			Find/Find Next, so it is easy to change the string.
			Because Find/Find Next is the default button, it will
			get Enter keystrokes even if the search string has the
			focus, unlike in the Replace and Replace & Find cases below. */
		if (frObj.where < DocFindReplace.WHERE_ALLDOCS)
			frObj.resetFocus (frObj.searchEdit);
	}

	this.replaceBtn.onClick = function ()
	{
		var frObj = this.window.findReplaceObj;
		var replaced = frObj.replace (false, false);
		/*	After a successful Replace, we want the focus to
			stay on the Replace button, so the user can easily do
			another Replace by typing Enter. If the Replace was
			unsuccessful, return the focus to the search string, so
			it can be easily changed. */
		if (replaced)
			frObj.resetFocus (frObj.replaceEdit);
		else
			frObj.resetFocus (frObj.searchEdit);
	}

	this.replaceFindBtn.onClick = function ()
	{
		var frObj = this.window.findReplaceObj;
		var replacedAndFound = false;
		if (frObj.replace (false, false))
			// Only do the 'follow on' find if the replace() matched
			replacedAndFound = frObj.find (false);
		/*	After a successful Replace & Find, we want the focus to
			stay on the 'Replace & Find' button, so the user can easily do
			another 'Replace & Find' by typing Enter. If the Replace was
			unsuccessful, return the focus to the search string, so
			it can be easily changed. */
		if (replacedAndFound)
			frObj.resetFocus (frObj.replaceFindBtn);
		else
			frObj.resetFocus (frObj.searchEdit);
	};
	this.replaceAllBtn.onClick = function ()
	{
		var frObj = this.window.findReplaceObj;
		frObj.replace (true, false);
		/*	After a 'Replace All', always return the focus to the
			search string, so it can be easily changed. */
		frObj.resetFocus (frObj.searchEdit);
	};
	
	// initialize "where" popup
	this.updateTargetList();

    this.clearResults.enabled = false;

    this.whereList.onChange = function()
    {
		var frObj = this.window.findReplaceObj;
        if( frObj )
        {
			if (this.selection)
			{
				frObj.where     = this.selection.where;
				frObj.wherePath = this.selection.path;
				frObj.filter	= this.selection.filter;
				frObj.recursive = this.selection.recursive;
			}
			else
			{
				frObj.where     = DocFindReplace.WHERE_CURRDOC;
				frObj.wherePath = '';
				frObj.filter	= "*.jsx";
				frObj.recursive = false;
			}
            frObj.resetFindReplace( true );
        }
    }
    
	// Define an onActivate event handler that will execute each time the dialog is activated
	this.palette.onShow = function ()
	{
		var frObj = this.findReplaceObj;
	    //	On each 'show', reset the find & replace strings and the states of the buttons
	    /* Replace current 'Find' string if a selection is active in current document.
	       For multi-line selections, use only the first line */
	    var selection = document ? document.textselection : '';
	    var nlIndex = selection.indexOf ('\n');
	    if (nlIndex >= 0)
		    selection = selection.substring (0, nlIndex);
	    if (selection.length == 0)
		    //	Use last known search string
		    frObj.searchEdit.text = frObj.searchEdit.activeSearchString;
	    else
		    //	Use the selection (up to first newline)
		    frObj.searchEdit.text = selection;
	    frObj.replaceEdit.text = frObj.replaceEdit.activeReplaceString;

		// Adjust widths of some text labels for alignment
		with (this.topGroup.findGrp)
		{
			var maxWidth = replace.lbl.size.width;
			var findWidth = search.lbl.size.width;
			if (findWidth > maxWidth)
				maxWidth = findWidth;
			var whereWidth = where.lbl.size.width;
			if (whereWidth > maxWidth)
				maxWidth = whereWidth;
			search.lbl.size.width = maxWidth;
			replace.lbl.size.width = maxWidth;
			where.lbl.size.width = maxWidth;
			this.layout.layout(true);
		}
	    frObj.resetFindReplace (true);

	    //	After the window is visible, give the 'search' edit field the focus
	    if( !frObj.initialShow )
	        addDelayedTask( frObj.resetFocus, frObj.searchEdit, frObj.palette );
	};

    this.palette.onResize = 
    this.palette.onResizing = function ()
    {
		this.layout.resize();
    }

	this.initFromPrefs();
}

DocFindReplace.prototype.updateTargetList = function()
{
    var sel = ( this.whereList.selection ? this.whereList.selection.text : '' );

    // force Current Doc if documents.length > 0 for the first time
	if (documents.length > 0 && this.whereList.items[0].where != DocFindReplace.WHERE_CURRDOC)
		sel = "";

    this.whereList.removeAll();
    
    var item = null;	
    
	var mustHaveDocs = (documents.length != 0);
	if ((this.docInfoInTargetList == undefined || mustHaveDocs != this.docInfoInTargetList) && mustHaveDocs)
	{
        item = this.whereList.add( 'item', localize( '$$$/ESToolkit/FindReplaceDlg/Where/CurrDoc=Current document' ) );
        item.where = DocFindReplace.WHERE_CURRDOC;
        item = this.whereList.add( 'item', localize( '$$$/ESToolkit/FindReplaceDlg/Where/CurrSel=Current selection' ) );
        item.where = DocFindReplace.WHERE_CURRSEL;
        item = this.whereList.add( 'item', localize( '$$$/ESToolkit/FindReplaceDlg/Where/AllDocs=All open documents' ) );
        item.where = DocFindReplace.WHERE_ALLDOCS;
        item = this.whereList.add( 'item', localize( '$$$/ESToolkit/FindReplaceDlg/Where/CurrEng=Current target/engine' ) );
        item.where = DocFindReplace.WHERE_CURRENGINE;
    }
    this.docInfoInTargetList = mustHaveDocs;

    if( favorites && favorites.length > 0 )
    {
		if (this.whereList.items.length == 0 && this.where != DocFindReplace.WHERE_FAVORITES)
			this.where = DocFindReplace.WHERE_FAVORITES;

		if (this.whereList.items.length)
			this.whereList.add ('separator', '');
			
        for( var i=0; i<favorites.length; i++ )
        {
            var item = this.whereList.add( 'item', favorites.items[i].name );
    	    item.where = DocFindReplace.WHERE_FAVORITES;
            item.path = favorites.items[i].path;
            item.filter = favorites.items[i].filter;
			item.recursive = favorites.items[i].recursive;
        }
    }

    this.whereList.selection = 0;

    if( sel.length > 0 )
    {
        for( var i=0; i<this.whereList.items.length; i++ )
        {
            if( this.whereList.items[i].text == sel )
            {
                this.whereList.selection = this.whereList.items[i];
				this.where = this.whereList.items[i].where;
                break;
            }
        }
    }
    
    this.resetFindReplace();
}

/////////////////////////////////////////////////////////////////////////
//	Define the DocFindReplace 'public method' functions

/*	find(searchWholeDoc)
	Search for the search text.
	* If 'searchWholeDoc' is true, search the entire document,
	  otherwise search from the insertion point to the end of the document.
	
	Returns true if the search was successful, false if not.
	
	Called from the Find button event handler, or
	from a keyboard shortcut handler.
*/
DocFindReplace.prototype.find = function(searchWholeDoc)
{
    if( this.where < DocFindReplace.WHERE_ALLDOCS )
        return this.findInDocument( document, searchWholeDoc )
	else
	    return this.findInFiles();
} // DFR_find

DocFindReplace.prototype.findInDocument = function( doc, searchWholeDoc )
{
    if (doc && doc.composing)
	    doc.endComposing();
	    
    var options = this.getMatchOptions (searchWholeDoc);
    
    var searchString = this.searchEdit.text;
    //	Remember that we searched for this text, for preferences
    this.searchEdit.activeSearchString = searchString;
    if (doc.find (searchString, options)) 
    {
	    //	Match found: reset search state
	    this.resetFindReplace (false);
	    return true;
    }
    else 
    {
	    /*	Match not found: if already in 'search the whole doc'
		    mode, note the search failure, else, ask if user
		    wants to search from the beginning */
	    if (searchWholeDoc) 
	    {
		    //	Already searched whole doc: we're done
		    app.beep();
		    messageBox (this.strSearchFailed);
		    this.resetFindReplace (true);
		    return false;
	    }
	    else if (queryBox (this.strSearchFailedRetry)) 
	    {
		    //	Search again, from the top, but don't allow a global search again
		    this.resetFindReplace (false);
		    return this.find (true);
	    }
	    else 
	    {
		    this.resetFindReplace (true);
		    return false;
	    }
    }
}

DocFindReplace.prototype.findInText = function( hiddenSearchDoc, text, title, scriptID, target, engine )
{
	var ok = true;

    var searchString    = this.searchEdit.text;
    var options         = this.getMatchOptions(false);
    var lastMatchedLine = -1;
    
    hiddenSearchDoc.text = text;

    while( ok && hiddenSearchDoc.find( searchString, options ) )
    {
        var pos = hiddenSearchDoc.getLogicalPos();
        
        if( pos[0] != lastMatchedLine )
        {
            lastMatchedLine = pos[0];  
            
            var foundLine = {   text        : hiddenSearchDoc.lines [pos[0]],
                                scriptID    : scriptID,
                                title       : title,
                                line        : pos[0],
                                pos         : pos[1],
                                searchStr   : searchString,
                                where       : this.where,
                                target      : target,
                                engine      : engine
                            };
                      
            ok = app.findResult.addResult( foundLine );
		}
    }
	return ok;
}

DocFindReplace.prototype.onNotify = function( reason, param01, param02, param03, param04 )
{
    switch( reason )
    {
		case 'shutdown':
		{
			if( this.hiddenSearchWin )
				this.hiddenSearchWin = null;
				
			globalBroadcaster.unregisterClient( this );
			
			if( !param01 )
				this.updatePrefs();
		}
		break; 
	
        case 'getScriptSourceFor':
        {
            if( this.awaitScriptSource )
            {
                this.awaitScriptSource		= false;
                this.awaitedScriptSource	= param01;
            }
        }
        break;
        
        case 'getScriptListFor':
        {
            if( this.awaitScriptList )
            {
                this.awaitScriptList    = false;
                this.awaitedScriptList  = param01;
            }
        }
        break;
        
        case 'numDocsChanged':
			var docsOpen = (documents.length != 0);
			if (this.docInfoInTargetList != docsOpen)
	            this.updateTargetList();
            break;

        case 'favoritesChanged':
			this.docInfoInTargetList = undefined;
			this.updateTargetList();
			break;
    }
}

DocFindReplace.checkScriptList = function()
{
    return ( findReplaceObj.awaitScriptList ? true : false );
}

DocFindReplace.checkScriptSource = function()
{
    return ( findReplaceObj.awaitScriptSource ? true : false );
}

// Helper: count the number of all files to search

DocFindReplace.prototype.countFiles = function (folder, filter, recursive)
{
    var files = folder.getFiles( filter );
	var count = files.length;
	if (recursive)
	{
		files = folder.getFiles ();
		for (var i = 0; i < files.length; i++)
		{
			folder = files [i];
			if (folder instanceof Folder)
				count += this.countFiles (folder, filter, recursive);
		}
	}
	return count;
}

// Helper: search all files in a folder

DocFindReplace.prototype.searchInFolder = function (hiddenSearchDoc, folder, filter, recursive)
{
    var files = folder.getFiles( filter );

    for( var i=0; i<files.length; i++ )
    {
		var f = files [i];
		if (f.alias)
			f = files [i] = f.resolve();
		if( f && !( f instanceof Folder ) )
		{
			app.findResult.incProgress();
			
			var text = Document.safeRead (f);
			if (null == text)
				break;
			
			if( text.length > 0 )
			{
				var title = decodeURIComponent (files[i].getRelativeURI (this.baseFolder));
				if (!this.findInText( hiddenSearchDoc, text, title, f.absoluteURI ))
					return false;
			}
		}
    }

	if (recursive)
	{
		files = folder.getFiles ();
		for (var i = 0; i < files.length; i++)
		{
			folder = files [i];
			var resolved = folder.resolve();
			if (resolved)
				folder = resolved;

			if (folder instanceof Folder)
			{
				if (!this.searchInFolder (hiddenSearchDoc, folder, filter, recursive))
					return false;
			}
		}
	}
	return true;
}

DocFindReplace.prototype.findInFiles = function()
{
    var searchString    = this.searchEdit.text;
    var options         = this.getMatchOptions(true);
	var found			= false;

	if( !this.hiddenSearchWin )
	{
		this.hiddenSearchWin = new Window( 'palette', 'hidden' );
		this.hiddenSearchWin.hiddenSearchDoc = this.hiddenSearchWin.add( 'document' );
		this.hiddenSearchWin.show();
		this.hiddenSearchWin.hide();
	}
	
    switch( this.where )
    {
        case DocFindReplace.WHERE_ALLDOCS:
        {
            app.findResult.startSearch( searchString, 
                                        documents.length, 
                                        this.clearResults.value,
										"" );
            
            for( var i=0; i<documents.length; i++ )
            {
                app.findResult.incProgress();
                if (!this.findInText( this.hiddenSearchWin.hiddenSearchDoc, documents[i].text, documents[i].paneTitle, documents[i].scriptID ))
					break;
            }

            found = app.findResult.endSearch();
        }
        break;
        
        case DocFindReplace.WHERE_FAVORITES:
        {
            var folder = new Folder( this.wherePath );
            
            if( folder.exists )
            {
				var resolved = folder.resolve();
				if (resolved)
					folder = resolved;

				this.baseFolder = folder.absoluteURI;
                var files = folder.getFiles( '*.jsx' );

                app.findResult.startSearch( searchString, 
                                            files.length, 
                                            this.clearResults.value );
                
				this.searchInFolder (this.hiddenSearchWin.hiddenSearchDoc, folder, this.filter, this.recursive)
                
                found = app.findResult.endSearch();
				this.baseFolder = "";
            }
        }
        break;
        
        case DocFindReplace.WHERE_CURRENGINE:
        {
            var target    = '';
            var engine    = '';
            var targetObj = targetMgr.getActiveTarget();
            
            if( targetObj )
            {
                target = targetObj.targetName;
                engine = targetObj.getActive();
            }
                
			this.awaitScriptList    = true;
			this.awaitedScriptList  = null;

            if( target.length > 0 && engine.length > 0 && scripts.getScriptListFor( target, engine, this ) )
            {
                if( wait( DocFindReplace.checkScriptList ) )
                {
                    var havescripts = this.awaitedScriptList;
                    
                    if( havescripts )
                    {
                        app.findResult.startSearch( searchStringt, 
                                                    havescripts.length, 
                                                    this.clearResults.value );
                        
                        for( var i=0; i<havescripts.length; i++ )
                        {
                            app.findResult.incProgress();
                            
                            var source = '';
                            
                            var doc = Document.find( havescripts[i].scriptID );
                            
                            if( doc )
                                source = doc.text;
                            else
                            {
								this.awaitScriptSource    = true;
								this.awaitedScriptSource  = null;
								
                                if( scripts.getScriptSourceFor( havescripts[i].scriptID, havescripts[i].displayName, target, engine, this ) )
                                {
                                    if( wait( DocFindReplace.checkScriptSource ) )
									{
                                        source = this.awaitedScriptSource;
									}
								}
							}
							
							if( source && source.length > 0 )
							{
								if (!this.findInText( this.hiddenSearchWin.hiddenSearchDoc, source, havescripts[i].displayName, havescripts[i].scriptID, target, engine ))
									break;
							}
                        }
                
                        found = app.findResult.endSearch();
                    }
                }
            }
        }
        break;
    }
	
	return found;
}

/*	replace(replaceAll, searchWholeDoc)
	Replace the currently selected text with the contents of
	findGrp.replaceEdit.text.
	* If 'replaceAll' is true, replace all instances of the selected
	  text in the document.
	* If 'searchWholeDoc' is true, search the entire document,
	  otherwise search from the insertion point to the end of the document.
	Return:
	* true if a match was found
	
	Called from the Replace, Replace & Find, and Replace All button
	event handlers, or from a keyboard shortcut handler.
*/
DocFindReplace.prototype.replace = function(replaceAll, searchWholeDoc)
{
	var options = this.getMatchOptions (searchWholeDoc);
	if (replaceAll)
		options += Document.FIND_REPLACEALL;

	var searchString = this.searchEdit.text;
	var replaceString = this.replaceEdit.text;
	//	Remember that we searched for this text, for preferences
	this.searchEdit.activeSearchString = searchString;
	//	Remember that we used this text for replacements, for preferences
	this.replaceEdit.activeReplaceString = replaceString;
	var replacements = document.replace (searchString, replaceString, options);
	if (replacements > 0) 
	{
		//	Match(es) found: reset search state
		this.resetFindReplace (false);
		if (replaceAll)
		{
			//	Tell user how many replacements were made
			if (replacements == 1)
				messageBox (this.strOneReplacementDone);
			else
				messageBox (this.strReplacementDone, replacements);
		}
		return true;
	}
	else 
	{
		/*	Match not found: if already in 'search the whole doc'
			mode, note the search failure, else, ask if user
			wants to search from the beginning */
		if (searchWholeDoc) {
			//	Already searched whole doc: we're done
			messageBox (this.strSearchFailed);
			this.resetFindReplace (true);
			return false;
		}
		else if (queryBox (this.strSearchFailedRetry)) {
			//	Search again, from the top, but don't allow a global search again
			this.resetFindReplace (false);
			return this.replace (replaceAll, true);
		}
		else {
			this.resetFindReplace (true);
			return false;
		}
	}
} // DFR_replace

/*	show()
	show the Find/Replace palette. If this is the first call to show()
	in this invocation of the IDE, load (or create) the find/replace preferences.
	Called from the Find/Replace menu item onSelect handler
*/
DocFindReplace.prototype.show = function()
{
    if( this.palette.visible )
		addDelayedTask( this.resetFocus, this.searchEdit, this.palette );
    else
	    this.palette.show();
} // DFR_show

///////////////////////////////////////////////////////////////////////////////
//
// 
//

/*	initFromPrefs()
	Initialize values of various controls from the saved 'preference' values.
	Called from first 'show' of the F/R palette.
*/

DocFindReplace.prototype.initFromPrefs = function()
{
	if (prefs.findReplacePrefs.paletteLocation != null)
		this.palette.frameLocation = prefs.findReplacePrefs.paletteLocation;
	else
		this.palette.center(window);

	this.searchEdit.activeSearchString   = PrefUtils.getValue( 'prefs.findReplacePrefs.searchString', 'String' );
	this.replaceEdit.activeReplaceString = PrefUtils.getValue( 'prefs.findReplacePrefs.replaceString', 'String' );
	this.matchCase.value			     = PrefUtils.getValue( 'prefs.findReplacePrefs.matchCase', 'Boolean' );
	this.wholeWord.value			     = PrefUtils.getValue( 'prefs.findReplacePrefs.wholeWord', 'Boolean' );
	this.matchRegExp.value				 = PrefUtils.getValue( 'prefs.findReplacePrefs.matchRegExp', 'Boolean' );
	this.clearResults.value				 = PrefUtils.getValue( 'prefs.findReplacePrefs.clearresults', 'Boolean' );
	
	if( this.searchEdit.activeSearchString.length > 0 )
		//	Initially, if there's a search string, make the
		//	Find button respond to Enter key
		this.palette.defaultElement = this.findBtn;

	this.resetFindReplace (true);

} // DFR_initFromPrefs


/*	updatePrefs()
	Update the find/replace 'preferences' object with current values from the controls.
*/

DocFindReplace.prototype.updatePrefs = function()
{
	prefs.findReplacePrefs.paletteLocation = this.palette.frameLocation;
	
	prefs.findReplacePrefs.searchString     = this.searchEdit.activeSearchString;
	prefs.findReplacePrefs.replaceString    = this.replaceEdit.activeReplaceString;
	prefs.findReplacePrefs.matchCase        = this.matchCase.value;
	prefs.findReplacePrefs.wholeWord        = this.wholeWord.value;
	prefs.findReplacePrefs.matchRegExp      = this.matchRegExp.value;
	prefs.findReplacePrefs.clearresults     = this.clearResults.value;
} // DFR_updatePrefs


/*	resetFindReplace()
	Reset states of the 'find' and 'replace' controls after a state change.
	'newSearch' indicates a new search string: false means searching again
	for same string.
*/
DocFindReplace.prototype.resetFindReplace = function(newSearch)
{
	var palette             = this.palette;
	var haveSearchString    = this.currentSearchString().length > 0;
	var docIsWriteable      = true; // replace with "! document.readOnly" if we need to disable F/R for RO docs
	var multiFind			= (this.where >= DocFindReplace.WHERE_ALLDOCS);

	var btnText;
	if (multiFind)
		btnText = this.strFindAll;
	else
		btnText = ( newSearch || documents.length == 0 ) ? this.strFind : this.strFindNext;

	this.findBtn.text           = localize ( btnText );
	this.findBtn.enabled        = haveSearchString;
	this.replaceBtn.enabled     =
	this.replaceFindBtn.enabled	=
	this.replaceAllBtn.enabled  = ( haveSearchString                             && 
	                                documents.length > 0                         &&
	                                docIsWriteable                               && 
	                                ( this.where == DocFindReplace.WHERE_CURRDOC || 
	                                  this.where == DocFindReplace.WHERE_CURRSEL ) );
	this.clearResults.enabled = multiFind;
} // DFR_resetFindReplace


/*	resetFocus(control)
	Set keyboard focus to the given 'control', or to the palette if control == null.
*/
DocFindReplace.prototype.resetFocus = function( control, palette )
{
	var palette = palette;
	
	if( !palette )
		palette = this.palette;
	
	if( palette && !palette.active )
		palette.active = true;

	if (control)
	{
		if( control.active )
			control.active = false;

		control.active = true;
	}
} // DFR_resetFocus


/*	getMatchOptions()
	Return the 'match options' flags to pass to Document.find() or
	Document.replace(), based on the current dialog match options
	checkboxes and the 'searchWholeDoc' parameter.
*/
DocFindReplace.prototype.getMatchOptions = function(searchWholeDoc)
{
	var options = 0;
	if (searchWholeDoc)
		options += Document.FIND_WRAPAROUND;
	if (this.matchCase.value == 0)
		options += Document.FIND_IGNORECASE;
	if (this.wholeWord.value != 0)
		options += Document.FIND_WORDS;
	if (this.matchRegExp.value != 0)
		options += Document.FIND_REGEXP;
	if( this.where == DocFindReplace.WHERE_CURRSEL )
	    options += Document.FIND_SELECTION;
	return options;
} // DFR_getMatchOptions

/*	currentSearchString()
	Return the current string to search for: may be empty.
*/
DocFindReplace.prototype.currentSearchString = function()
{
	return this.searchEdit.text;
} // currentSearchString
