[Contents] [Index] [Help] [Retrace] [Browse <] [Browse >]

/* Cbio.c
 *
 * Provide standard clipboard device interface routines
 *            such as Open, Close, Post, Read, Write, etc.
 *
 * Compile with SAS C 5.10: LC -b1 -cfistq -v -y
 *
 *  NOTE - These functions are useful for writing, and reading simple
 *         FTXT.  Writing, and reading complex FTXT, ILBM, etc.,
 *         requires more work - under 2.0 it is highly recommended that
 *         you use iffparse.library.
 */

#include <exec/types.h>
#include <exec/ports.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <devices/clipboard.h>

#define CBIO 1

#include "cb.h"

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

/****** cbio/CBOpen *************************************************
*
*   NAME
*       CBOpen() - Open the clipboard.device
*
*   SYNOPSIS
*       ior = CBOpen(unit)
*
*       struct IOClipReq *CBOpen( ULONG )
*
*   FUNCTION
*       Opens the clipboard.device.  A clipboard unit number
*       must be passed in as an argument.  By default, the unit
*       number should be 0 (currently valid unit numbers are
*       0-255).
*
*   RESULTS
*       A pointer to an initialized IOClipReq structure, or
*       a NULL pointer if the function fails.
*
*********************************************************************/

struct IOClipReq *CBOpen(unit)
ULONG unit;
{
struct MsgPort *mp;
struct IOStdReq *ior;

if (mp = CreatePort(0L,0L))
    {
    if (ior=CreateExtIO(mp,sizeof(struct IOClipReq)))
        {
        if (!(OpenDevice("clipboard.device",unit,ior,0L)))
            {
            return((struct IOClipReq *)ior);
            }
        DeleteExtIO(ior);
        }
    DeletePort(mp);
    }
return(NULL);

}

/****** cbio/CBClose ************************************************
*
*   NAME
*       CBClose() - Close the clipboard.device
*
*   SYNOPSIS
*       CBClose()
*
*       void CBClose()
*
*   FUNCTION
*       Close the clipboard.device unit which was opened via
*       CBOpen().
*
*********************************************************************/

void CBClose(ior)
struct IOClipReq *ior;
{
struct MsgPort *mp;

mp = ior->io_Message.mn_ReplyPort;

CloseDevice((struct IOStdReq *)ior);
DeleteExtIO((struct IOStdReq *)ior);
DeletePort(mp);

}

/****** cbio/CBWriteFTXT *********************************************
*
*   NAME
*       CBWriteFTXT() - Write a string of text to the clipboard.device
*
*   SYNOPSIS
*       success = CBWriteFTXT( ior, string)
*
*       int CBWriteFTXT(struct IOClipReq *, char *)
*
*   FUNCTION
*       Write a NULL terminated string of text to the clipboard.
*       The string will be written in simple FTXT format.
*
*       Note that this function pads odd length strings automatically
*       to conform to the IFF standard.
*
*   RESULTS
*       TRUE if the write succeeded, else FALSE.
*
*********************************************************************/

int CBWriteFTXT(ior,string)
struct IOClipReq *ior;
char *string;
{

ULONG length, slen;
BOOL odd;
int success;

slen = strlen(string);
odd = (slen & 1);               /* pad byte flag */

length = (odd) ? slen+1 : slen;

/* initial set-up for Offset, Error, and ClipID */

ior->io_Offset = 0;
ior->io_Error  = 0;
ior->io_ClipID = 0;


/* Create the IFF header information */

WriteLong(ior, (long *) "FORM");     /* "FORM"             */
length+=12L;                         /* + "[size]FTXTCHRS" */
WriteLong(ior, &length);             /* total length       */
WriteLong(ior, (long *) "FTXT");     /* "FTXT"             */
WriteLong(ior, (long *) "CHRS");     /* "CHRS"             */
WriteLong(ior, &slen);               /* string length      */

/* Write string */
ior->io_Data    = (STRPTR)string;
ior->io_Length  = slen;
ior->io_Command = CMD_WRITE;
DoIO( (struct IORequest *) ior);

/* Pad if needed */
if (odd)
    {
    ior->io_Data   = (STRPTR)"";
    ior->io_Length = 1L;
    DoIO( (struct IORequest *) ior);
    }

/* Tell the clipboard we are done writing */

ior->io_Command=CMD_UPDATE;
DoIO( (struct IORequest *) ior);

/* Check if io_Error was set by any of the preceding IO requests */
success = ior->io_Error ? FALSE : TRUE;

return(success);
}

WriteLong(ior, ldata)
struct IOClipReq *ior;
long *ldata;
{

ior->io_Data    = (STRPTR)ldata;
ior->io_Length  = 4L;
ior->io_Command = CMD_WRITE;
DoIO( (struct IORequest *) ior);

if (ior->io_Actual == 4)
    {
    return( ior->io_Error ? FALSE : TRUE);
    }

return(FALSE);

}


/****** cbio/CBQueryFTXT **********************************************
*
*   NAME
*       CBQueryFTXT() - Check to see if clipboard contains FTXT
*
*   SYNOPSIS
*       result = CBQueryFTXT( ior )
*
*       int CBQueryFTXT(struct IOClipReq *)
*
*   FUNCTION
*       Check to see if the clipboard contains FTXT.  If so,
*       call CBReadCHRS() one or more times until all CHRS
*       chunks have been read.
*
*   RESULTS
*       TRUE if the clipboard contains an FTXT chunk, else FALSE.
*
*   NOTES
*       If this function returns TRUE, you must either call
*       CBReadCHRS() until CBReadCHRS() returns FALSE, or
*       call CBReadDone() to tell the clipboard.device that
*       you are done reading.
*
*
*********************************************************************/

int CBQueryFTXT(ior)
struct IOClipReq *ior;
{
ULONG cbuff[4];


/* initial set-up for Offset, Error, and ClipID */

ior->io_Offset = 0;
ior->io_Error  = 0;
ior->io_ClipID = 0;

/* Look for "FORM[size]FTXT" */

ior->io_Command = CMD_READ;
ior->io_Data    = (STRPTR)cbuff;
ior->io_Length  = 12;

DoIO( (struct IORequest *) ior);


/* Check to see if we have at least 12 bytes */

if (ior->io_Actual == 12L)
    {
    /* Check to see if it starts with "FORM" */
    if (cbuff[0] == ID_FORM)
        {
        /* Check to see if its "FTXT" */
        if (cbuff[2] == ID_FTXT)
            return(TRUE);
        }

    /* It's not "FORM[size]FTXT", so tell clipboard we are done */
    }

CBReadDone(ior);

return(FALSE);
}


/****** cbio/CBReadCHRS **********************************************
*
*   NAME
*       CBReadCHRS() - Reads the next CHRS chunk from clipboard
*
*   SYNOPSIS
*       cbbuf = CBReadCHRS( ior )
*
*       struct cbbuf *CBReadCHRS(struct IOClipReq * )
*
*   FUNCTION
*       Reads and returns the text in the next CHRS chunk
*       (if any) from the clipboard.
*
*       Allocates memory to hold data in next CHRS chunk.
*
*   RESULTS
*       Pointer to a cbbuf struct (see cb.h), or a NULL indicating
*       a failure (e.g., not enough memory, or no more CHRS chunks).
*
*       ***Important***
*
*       The caller must free the returned buffer when done with the
*       data by calling CBFreeBuf().
*
*   NOTES
*       This function strips NULL bytes, however, a full reader may
*       wish to perform more complete checking to verify that the
*       text conforms to the IFF standard (stripping data as required).
*
*       Under 2.0, the AllocVec() function could be used instead of
*       AllocMem() in which case the cbbuf structure may not be
*       needed.
*
*********************************************************************/

struct cbbuf *CBReadCHRS(ior)
struct IOClipReq *ior;
{
ULONG chunk,size;
struct cbbuf *buf;
int looking;

/* Find next CHRS chunk */

looking = TRUE;
buf = NULL;

while (looking)
      {
      looking = FALSE;

      if (ReadLong(ior,&chunk))
          {
          /* Is CHRS chunk ? */
          if (chunk == ID_CHRS)
              {
              /* Get size of chunk, and copy data */
              if (ReadLong(ior,&size))
                  {
                  if (size)
                      buf=FillCBData(ior,size);
                  }
              }

            /* If not, skip to next chunk */
          else
              {
              if (ReadLong(ior,&size))
                  {
                   looking = TRUE;
                   if (size & 1)
                       size++;    /* if odd size, add pad byte */

                    ior->io_Offset += size;
                  }
              }
          }
      }

if (buf == NULL)
    CBReadDone(ior);        /* tell clipboard we are done */

return(buf);
}


ReadLong(ior, ldata)
struct IOClipReq *ior;
ULONG *ldata;
{
ior->io_Command = CMD_READ;
ior->io_Data    = (STRPTR)ldata;
ior->io_Length  = 4L;

DoIO( (struct IORequest *) ior);

if (ior->io_Actual == 4)
    {
    return( ior->io_Error ? FALSE : TRUE);
    }

return(FALSE);
}

struct cbbuf *FillCBData(ior,size)
struct IOClipReq *ior;
ULONG size;
{
register UBYTE *to,*from;
register ULONG x,count;

ULONG length;
struct cbbuf *buf,*success;

success = NULL;

if (buf = AllocMem(sizeof(struct cbbuf),MEMF_PUBLIC))
    {

    length = size;
    if (size & 1)
        length++;            /* if odd size, read 1 more */

    if (buf->mem = AllocMem(length+1L,MEMF_PUBLIC))
        {
        buf->size = length+1L;

        ior->io_Command = CMD_READ;
        ior->io_Data    = (STRPTR)buf->mem;
        ior->io_Length  = length;

        to = buf->mem;
        count = 0L;

        if (!(DoIO( (struct IOStdReq *) ior)))
            {
            if (ior->io_Actual == length)
                {
                success = buf;      /* everything succeeded */

                /* strip NULL bytes */
                for (x=0, from=buf->mem ;x<size;x++)
                     {
                     if (*from)
                         {
                         *to = *from;
                         to++;
                         count++;
                         }

                     from++;
                     }
                *to=0x0;            /* Null terminate buffer */
                buf->count = count; /* cache count of chars in buf */
                }
            }

        if (!(success))
            FreeMem(buf->mem,buf->size);
        }
    if (!(success))
        FreeMem(buf,sizeof(struct cbbuf));
    }

return(success);
}

/****** cbio/CBReadDone **********************************************
*
*   NAME
*       CBReadDone() - Tell clipboard we are done reading
*
*   SYNOPSIS
*       CBReadDone( ior )
*
*       void CBReadDone(struct IOClipReq * )
*
*   FUNCTION
*       Reads past end of clipboard file until io_Actual is equal to 0.
*       This is tells the clipboard that we are done reading.
*
*********************************************************************/

void CBReadDone(ior)
struct IOClipReq *ior;
{
char buffer[256];

ior->io_Command = CMD_READ;
ior->io_Data    = (STRPTR)buffer;
ior->io_Length  = 254;


/* falls through immediately if io_Actual == 0 */

while (ior->io_Actual)
      {
      if (DoIO( (struct IORequest *) ior))
          break;
      }
}

/****** cbio/CBFreeBuf **********************************************
*
*   NAME
*       CBFreeBuf() - Free buffer allocated by CBReadCHRS()
*
*   SYNOPSIS
*       CBFreeBuf( buf )
*
*       void CBFreeBuf( struct cbbuf * )
*
*   FUNCTION
*       Frees a buffer allocated by CBReadCHRS().
*
*********************************************************************/

void CBFreeBuf(buf)
struct cbbuf *buf;
{
FreeMem(buf->mem, buf->size);
FreeMem(buf, sizeof(struct cbbuf));
}


*************************************************************************
*        Hookface.asm
*        assembly routines for Chtest
*
*        Assemble with Adapt  hx68 hookface.a to hookface.o
*        Link with Changehook_Test.o as shown in Changehook_Test.c header
*
*************************************************************************
        INCDIR  'include:'
        INCLUDE 'exec/types.i'
        INCLUDE 'utility/hooks.i'
        xdef    _callHook
        xdef    _callHookPkt
        xdef    _hookEntry
        xdef    _stubReturn
*************************************************************************
* new hook standard
* use struct Hook (with minnode at the top)
*
* *** register calling convention: ***
*       A0 - pointer to hook itself
*       A1 - pointer to parameter packed ("message")
*       A2 - Hook specific address data ("object," e.g, gadget )
*
* ***  C conventions: ***
* Note that parameters are in unusual register order: a0, a2, a1.
* This is to provide a performance boost for assembly language
* programming (the object in a2 is most frequently untouched).
* It is also no problem in "register direct" C function parameters.
*
* calling through a hook
*       callHook( hook, object, msgid, p1, p2, ... );
*       callHookPkt( hook, object, msgpkt );
*
* using a C function:   CFunction( hook, object, message );
*       hook.h_Entry = hookEntry;
*       hook.h_SubEntry = CFunction;
*************************************************************************
* C calling hook interface for prepared message packet
_callHookPkt:
        movem.l a2/a6,-(sp)     ; protect
        move.l  12(sp),a0       ; hook
        move.l  16(sp),a2       ; object
        move.l  20(sp),a1       ; message
        ; ------ now have registers ready, invoke function
        pea.l   hreturn(pc)
        move.l  h_Entry(a0),-(sp)       ; old rts-jump trick
        rts
hreturn:
        movem.l (sp)+,a2/a6
        rts

* C calling hook interface for "varargs message packet"
_callHook:
        movem.l a2/a6,-(sp)     ; protect
        move.l  12(sp),a0       ; hook
        move.l  16(sp),a2       ; object
        lea.l   20(sp),a1       ; message
        ; ------ now have registers ready, invoke function
        pea.l   hpreturn(pc)
        move.l  h_Entry(a0),-(sp)       ; old rts-jump trick
        rts
hpreturn:
        movem.l (sp)+,a2/a6
        rts

* entry interface for C code (large-code, stack parameters)
_hookEntry:
        move.l  a1,-(sp)
        move.l  a2,-(sp)
        move.l  a0,-(sp)
        move.l  h_SubEntry(a0),a0       ; C entry point
        jsr     (a0)
        lea     12(sp),sp
_stubReturn:
        rts