/**
	ToggleHeaderSource.bsh V1.5
	by Alan Ezust
	$Id: Toggle_Header_Source.bsh 19693 2011-07-22 16:00:31Z ezust $

	A jedit beanshell macro that toggles your current buffer
	between the header file (.hh?) and the source file (.c(c|pp|xx)?).

	Enables you to switch the current text
	buffer between C/C++ header and sourcecode
	file. If the file does not already exist, it opens a new buffer
	of that name for you.

	New to 1.2: If another buffer is already open with the requested
	filename, it is selected, even if located in another directory.

	New to 1.3: If another EditPane is already open with the
	requested buffer, it is selected and focused.

	New to 1.4: Instead of throwing an exception, treats
	files with no extension as header files, and tries to
	open .cpp file with same basename. Searches in 
	current project for header/source files too.

	New to 1.5: Supports multiple, default header extensions. 
	
	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or any later version.

	This program 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 General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with the jEdit program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

 */

import projectviewer.*;
import projectviewer.vpt.*;
import java.util.*;

/* Set this property from the console beanshell to something else if cpp is not
   your favorite extension. e.g.:
   jEdit.setProperty("default.extension.c", "cc");
*/

String defaultSourceExtension = jEdit.getProperty("default.extension.c", "cpp");

/* jEdit.setProperty("default.extension.h", "hh"); */

String defaultHeaderExtension = jEdit.getProperty("default.extension.h", "h");

String[] sourceExtensions = new String[]{"cpp", "cxx", "cc", "c"};

String[] headerExtensions = new String[]{"h", "hh", "hpp", "hxx"};

/** Looks for an existing file in the current project, if ProjectViewer is
   installed and a 'current' project exists.
   @return the absolute path if found, NULL if not.
   */
String findBufferInProject(String fileName) {
    int sep1 = fileName.lastIndexOf('\\');
    int sep2 = fileName.lastIndexOf('/');
    if (sep1 > sep2)
        fileName = fileName.substring(sep1 + 1);
    else if (sep2 > sep1)
        fileName = fileName.substring(sep2 + 1);
    VPTProject project = ProjectViewer.getActiveProject(view);
    Collection nodes = project.getOpenableNodes();
    for (VPTNode node: nodes) {
        String path = node.getNodePath();
        if ((path.endsWith("\\" + fileName)) || (path.endsWith("/" + fileName)))
            return path;
    }
    return null;		
}

/** Looks for an existing file in the same directory, or
   an already open buffer with the given name in another directory.
   @return the absolute path if found, NULL if not.
   */
String findBuffer(String fileName) {
    File f = new File(fileName);
    if (f.canRead()) return f.getPath();
    String fn2 = f.getName();
    Buffer[] bufs = jEdit.getBuffers();
    bn = bufs.length;
    for (int i=0; i<bn; ++i) {
        Buffer b = bufs[i];
        if (b.getName().equals(fn2)) return b.getPath();
    }
    return null;
}

/** Returns true if PV is installed and a project is selected (current)
*/
boolean activeProjectExists()
{
    EditPlugin p = jEdit.getPlugin("projectviewer.ProjectPlugin",false);
    if(p == null)
        return false;
    VPTProject project = ProjectViewer.getActiveProject(view);
    return (project != null);
}

/** Given a header file, iterates through all sourcefile extensions checking if the sourcefile exists.
   @return the absolute path of the sourcefile for this header
*/

String getSourceFile(String baseName)
{
    int numExt = sourceExtensions.length;
    // First try open buffers
    for (int i=numExt-1; i>=0; --i)
    {
        String ext = sourceExtensions[i];
        String tryFile = baseName + "." + ext;
        String path = findBuffer(tryFile);
        if (path != null) return path;
    }
    // Then try current project
    if (activeProjectExists())
    {
        for (int i=numExt-1; i>=0; --i)
        {
            String ext = sourceExtensions[i];
            String tryFile = baseName + "." + ext;
            String path = findBufferInProject(tryFile);
            if (path != null) return path;
        }
    }
    return baseName + "." + defaultSourceExtension;
}

String getHeaderFile(String baseName) 
{
    int numExt = headerExtensions.length;
    for (int i=numExt-1; i>=0; --i)
    {
        String ext = headerExtensions[i];
        String tryFile = baseName + "." + ext;
        String path = findBuffer(tryFile);
        if (path != null) return path;
    }
    
    // Try no extension at all:
    String path = findBuffer(baseName);
    if (path != null) return path;
    
    // Then try current project
    if (activeProjectExists())
        for (int i=numExt-1; i>=0; --i)
        {
            String ext = headerExtensions[i];
            String tryFile = baseName + "." + ext;
            path = findBufferInProject(tryFile);
            if (path != null) return path;
        }
    // No extension at all in project:
    return findBufferInProject(baseName);
}

boolean isSourceFile(String extension)
{
    for (int i=0; i<sourceExtensions.length; ++i) {
        if (extension.equals(sourceExtensions[i])) return true;
    }
    return false;
}


void toggleHeaderSource()
{
    String currentFile = buffer.getPath();
    int pos = currentFile.lastIndexOf('.');
	String path = null;
    if (pos < 0) {
        path = getSourceFile(currentFile);
    }
    else {
        String baseName = currentFile.substring(0, pos);
        String extension = currentFile.substring(pos+1);
        if (isSourceFile(extension))
        {
            path = getHeaderFile(baseName);
            if (path == null) 
                path = baseName + "." + defaultHeaderExtension;
        }
        else 
        {
            path = getSourceFile(baseName);
        }
    }
	if (path == null) return;
	// see if it is already open in another editpane
	panes = view.getEditPanes();
	if (panes.length > 1)
		for (int i=panes.length - 1; i >= 0; --i) {
			buf = panes[i].getBuffer();
			if (buf.getName().equals(path)
			|| buf.getPath().equals(path)) {
				panes[i].focusOnTextArea();
				return;
			}
	}
	jEdit.openFile(view, path);
}

toggleHeaderSource();


