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