/**
	ToggleHeaderSource.bsh V1.4
	by Alan Ezust
	$Id: Toggle_Header_Source.bsh 16248 2009-09-29 20:43:41Z shlomy $

	A jedit beanshell macro that toggles your current buffer
	between the header file (.h) 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.

	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");

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

/** 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;
}

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))
        {
            String header = baseName + ".h";
            path = findBuffer(header);
            if (path == null) {
                if (activeProjectExists())
        	    path = findBufferInProject(header);
            }
            if (path == null) path = baseName + ".h";
        }
        else if (extension.equals("h")) {
            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();


