/**
* Utility methods for Emacs emulation macros.
*/

import org.gjt.sp.jedit.Registers;
import org.gjt.sp.gui.HistoryModel;

boolean repeatingSameMacro (String macroName)
{
    ih = textArea.getInputHandler();
    lastAction = ih.getLastAction();
    lastActionCount = ih.getLastActionCount();
    
    // When called from within a macro, the last action will be that macro.
    // But, if the last action count is greater than 1, then it's a repeat.

    boolean repeat = false;
    if ( (lastAction.getName().equals (macroName)) && (lastActionCount > 1) )
        repeat = true;
    
    return repeat;
}

String lineAt (int i)
{
    StringBuffer buf = new StringBuffer();
    
    while (! atEndOfBuffer (i))
    {
        char c = charAt (i);
        buf.append (c);
        if (c == '\n')
            break;
    }
    
    return buf.toString();
}

char charAt (int i)
{
    return buffer.getText (i, 1).charAt (0);
}

char charAtCaret()
{
    caret = textArea.getCaretPosition();
    return (atEndOfBuffer() ? '\0' : buffer.getText (caret, 1).charAt (0));
}

boolean atEndOfBuffer()
{
    return atEndOfBuffer (textArea.getCaretPosition());
}

boolean atEndOfBuffer (int caret)
{
    return (caret >= buffer.getLength());
}

int eatNonAlphanums()
{
    boolean eat = true;

    while (eat)
    {
        ch = charAtCaret();
        
        if (ch == '\n')
        {
            textArea.goToNextLine (false);
            textArea.goToStartOfLine (false);
        }
        
        else
        {
            if (Character.isLetterOrDigit (ch))
                eat = false;
            
            else
                textArea.goToNextCharacter (false);
        }
    }
    
    return textArea.getCaretPosition();
}
       
int eatWhitespace()
{
    boolean eat = true;
    
    while (eat)
    {
        ch = charAtCaret();
        
        if (ch == '\n')
        {
            textArea.goToNextLine (false);
            textArea.goToStartOfLine (false);
        }
        
        else if (Character.isWhitespace (ch))
        {
            textArea.goToNextCharacter (false);
        }

        else
        {
            eat = false;
        }
    }
    
    return textArea.getCaretPosition();
}

int getCardinalProperty (String name, int defaultValue)
{
    int result = jEdit.getIntegerProperty (name, defaultValue);

    if (result <= 0)
        result = defaultValue;
    
    return result;
}

String makeBufferPropertyName (String prefix)
{
    return makeBufferPropertyName (buffer, prefix);
}

String makeBufferPropertyName (Buffer theBuffer, String prefix)
{
    propName = new StringBuffer (prefix);

    // Convert any Windows-style file separators to Unix ones, since
    // backslashes are special characters in properties files.

    fileSep = System.getProperty ("file.separator");
    if (! fileSep.equals ("/"))
    {
        // Backslash is also special in regular expressions. Since, in theory,
        // the file separator could be *anything*, we check explicitly for
        // backslash here.

        if (fileSep.equals ("\\"))
            fileSep = fileSep + "\\";

        bufName = theBuffer.getPath().replaceAll (fileSep, "/");
    }
    
    else
    {
        bufName = theBuffer.getPath();
    }

    propName.append (bufName);
    return propName.toString();
}

int getDefaultWrap()
{
    return getCardinalProperty ("buffer.maxLineLen", 79);
}

int getMark (Buffer buffer)
{
    propName = makeBufferPropertyName ("emacs.mark");
    int mark = getCardinalProperty (propName, -1);
    if (mark != -1)
    {
        if (mark >= buffer.getLength())
            mark = buffer.getLength() - 1;
    }
    return mark;
}

void setMark (Buffer buffer, int pos)
{
    propName = makeBufferPropertyName (buffer, "emacs.mark");
    jEdit.setTemporaryProperty (propName, String.valueOf (pos));
}

void beep()
{
    view.getToolkit().beep();
}

Selection getKillRegion()
{
    // If there's a selection, use it instead.

    int caret = textArea.getCaretPosition();
    Selection selection = textArea.getSelectionAtOffset (caret);
    if (selection == null)
    {
        int mark = getMark (buffer);
        if (mark == -1)
        {
            beep();
            return null;
        }

        selection = new Selection.Range (Math.min (caret, mark),
                                         Math.max (caret, mark));
        textArea.setSelection (selection);
    }

    return selection;
}

Registers.Register getClipboard()
{
    return Registers.getRegister ('$');
}

void setClipboard (String string)
{
    Registers.setRegister ('$', string);
}

void setClipboard (Selection selection)
{
    setClipboard (textArea.getSelectedText (selection));
}

void addToClipboardAndHistory (String string)
{
    // The special register '$' is the clipboard.

    setClipboard (string);
    
    // Save the text in the history, too.
    
    HistoryModel.getModel ("clipboard").addItem (string);
}

void addToClipboardAndHistory (Selection selection)
{
    addToClipboardAndHistory (textArea.getSelectedText (selection));
}

int findEndOfSentence()
{
    caret = textArea.getCaretPosition();

    for (;;)
    {
        if (atEndOfBuffer (caret))
            break;

        ch = charAt (caret);
        if (ch == '.')
        {
            if (Character.isWhitespace (charAt (caret + 1)))
            {
                caret++;
                break;
            }
        }

        caret++;
    }
    
    return caret;
}

int findBeginningOfSentence()
{
    caret = textArea.getCaretPosition() - 1;
    if (charAt (caret) == '.')
        caret--;

    for (;;)
    {
        if (caret <= 0)
            break;

        ch = charAt (caret);
        if (ch == '.')
        {
            if (Character.isWhitespace (charAt (caret + 1)))
            {
                caret++;
                break;
            }
        }
        
        else if (Character.isUpperCase (ch))
        {
            caret--;
            if (caret <= 0)
                break;
            if (Character.isWhitespace (charAt (caret)))
                break;
        }

        caret--;
    }
    
    return caret;
}

