/*
 * clipftxt.c © by Martin Steppler
 *
 * $Id: clipftxt.c 1.2 1994/04/16 15:58:23 steppler Exp $
 *
 * $Log: clipftxt.c $
 * Revision 1.2  1994/04/16  15:58:23  steppler
 * official release
 *
 * Revision 1.1.1.1  1994/04/10  16:38:08  steppler
 * LoadBuf(): rearranged passing of args to AddListEntry()
 * due to change of AddListEntry()
 *
 * Revision 1.1  1994/02/26  21:48:00  steppler
 * Initial revision
 *
 *
 */

#include "muiffr.h"
#include "muiffr_locale.h"

#define RBUFSZ BUF_SIZE

#define  ID_FTXT        MAKE_ID('F','T','X','T')
#define  ID_CHRS        MAKE_ID('C','H','R','S')

struct Library *IFFParseBase;

static int LoadBuf(UBYTE *buf, int rlen);

int CopyClip(void)
{
    int return_ok = FALSE;
    struct IFFHandle *iff = NULL;
    long error = 0, unitnumber = 0;
    int textlen;

    // empty request list
    if (!app->app_RequestList)
        goto abort;

    if (!(IFFParseBase = OpenLibrary("iffparse.library", 0L)))
    {
        DispError(MSG_ERROR_CANT_OPEN, "iffparse.library");
        goto abort;
    }

    /*
     * Allocate IFF_File structure.
     */
    if (!(iff = AllocIFF()))
        goto abort;

    /*
     * Set up IFF_File for Clipboard I/O.
     */
    if (!(iff->iff_Stream = (ULONG) OpenClipboard (unitnumber)))
    {
        DispError(MSG_ERROR_CANT_OPEN, "clipboard");
        goto abort;
    }

    InitIFFasClip (iff);

    /*
     * Start the IFF transaction.
     */
    if (error = OpenIFF(iff, IFFF_WRITE))
        goto abort;

    /*
     * Write our text to the clipboard as CHRS chunk in FORM FTXT
     *
     * First, write the FORM ID (FTXT)
     */
    if (!(error = PushChunk(iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN)))
    {
        UBYTE *buf, *linefeed = "\n";
        LONG pos = -1;

        /* Now the CHRS chunk ID followed by the chunk data
         */
        if (error = PushChunk(iff, 0, ID_CHRS, IFFSIZE_UNKNOWN))
            goto abort;

        do
        {
            DoMethod(app->app_lv_Main_RequestList, MUIM_List_NextSelected, &pos);

            if (pos >= 0)
            {
                DoMethod(app->app_lv_Main_RequestList, MUIM_List_GetEntry, pos, &buf);

                /* Now the actual data (the text) */
                textlen = strlen(buf);
                if (WriteChunkBytes(iff, buf, textlen) != textlen)
                    error = IFFERR_WRITE;
                if (!error)
                    // append linefeed
                    if (WriteChunkBytes(iff, linefeed, 1) != 1)
                        error = IFFERR_WRITE;
            }
        }
        while (!error && pos >= 0);

        if (!error)
            error = PopChunk(iff);
    }
    if(!error)
        error = PopChunk(iff);

    return_ok = TRUE;
abort:
    if (iff)
    {
        /*
         * Terminate the IFF transaction with the stream.  Free
         * all associated structures.
         */
        CloseIFF(iff);

        /*
         * Close the clipboard stream
         */
        if (iff->iff_Stream)
            CloseClipboard((struct ClipboardHandle *) iff->iff_Stream);

        /*
         * Free the IFF_File structure itself.
         */
        FreeIFF(iff);
    }
    if (IFFParseBase)
    {
        CloseLibrary (IFFParseBase);
        IFFParseBase = NULL;
    }
    return (return_ok);
}

int CutClip(void)
{
    int return_ok = FALSE;

    if (!CopyClip())
        goto abort;

    DeleteListEntry();

    return_ok = TRUE;
abort:
    return (return_ok);
}

int PasteClip(void)
{
    int return_ok = FALSE;
    struct IFFHandle *iff = NULL;
    long error = 0, unitnumber = 0;
    struct ContextNode  *cn;
    int rlen;
    UBYTE buf[RBUFSZ];


    if (!(IFFParseBase = OpenLibrary("iffparse.library", 0L)))
    {
        DispError(MSG_ERROR_CANT_OPEN, "iffparse.library");
        goto abort;
    }

    /*
     * Allocate IFF_File structure.
     */
    if (!(iff = AllocIFF ()))
        goto abort;

    /*
     * Set up IFF_File for Clipboard I/O.
     */
    if (!(iff->iff_Stream = (ULONG) OpenClipboard (unitnumber)))
    {
        DispError(MSG_ERROR_CANT_OPEN, "clipboard");
        goto abort;
    }

    InitIFFasClip (iff);

    /*
     * Start the IFF transaction.
     */
    if (error = OpenIFF(iff, IFFF_READ))
        goto abort;

    /* Tell iffparse we want to stop on FTXT CHRS chunks */
    if (error = StopChunk(iff, ID_FTXT, ID_CHRS))
        goto abort;

    /* Find all of the FTXT CHRS chunks */
    while (1)
    {
        error = ParseIFF(iff, IFFPARSE_SCAN);
        /* enter next context */
        if (error == IFFERR_EOC)
            continue;
        else if (error)
            break;

        /* We only asked to stop at FTXT CHRS chunks
         * If no error we've hit a stop chunk
         * Read the CHRS chunk data
         */
        cn = CurrentChunk(iff);

        if (cn && cn->cn_Type == ID_FTXT && cn->cn_ID == ID_CHRS)
        {
            while ((rlen = ReadChunkBytes(iff, buf, RBUFSZ)) > 0)
            {
                if (!LoadBuf(buf, rlen))
                    goto abort;
            }

            if (rlen < 0)
                error = rlen;
        }
    }
    return_ok = TRUE;
abort:
    if (iff)
    {
        /*
         * Terminate the IFF transaction with the stream.  Free
         * all associated structures.
         */
        CloseIFF(iff);

        /*
         * Close the clipboard stream
         */
        if (iff->iff_Stream)
            CloseClipboard((struct ClipboardHandle *) iff->iff_Stream);

        /*
         * Free the IFF_File structure itself.
         */
        FreeIFF(iff);
    }
    if (IFFParseBase)
    {
        CloseLibrary (IFFParseBase);
        IFFParseBase = NULL;
    }
    return (return_ok);
}

static int LoadBuf(UBYTE *buf, int rlen)
{
    int return_ok = FALSE;
    int pos, rpos;
    UBYTE rbuf[RBUFSZ + 1];

    pos = 0;

    while (pos < rlen)
    {
        *rbuf = EOS;
        rpos = 0;
        do
        {
            if ((buf[pos] >= 32 && buf[pos] <= 127) || buf[pos] >= 160)
                rbuf[rpos++] = buf[pos];
            // tab
            else if (buf[pos] == 9)
            {
                do
                {
                    rbuf[rpos++] = ' ';
                }
                while ((rpos & 7) && rpos < RBUFSZ);
            }
            // linefeed
            else if (buf[pos] == 10)
            {
                pos++;
                break;
            }
        } while (rpos < RBUFSZ && ++pos < rlen);

        if (rpos)
            rbuf[rpos--] = EOS;

        // remove spaces
        while (1)
        {
            if (rbuf[rpos] == ' ')
            {
                rbuf[rpos--] = EOS;
                if (rpos < 0)
                    rpos = 0;
            }
            else
                break;
        }

        if (*rbuf)
            rpos++;

        if (!AddListEntry(rbuf, NULL, FALSE))
            goto abort;
    }

    return_ok = TRUE;
abort:
    return (return_ok);
}
