home *** CD-ROM | disk | FTP | other *** search
- /*
- * clipboard.c
- * by Robert R. Burns
- *
- * Copyright (c) 1988 Commodore-Amiga, Inc.
- *
- * Executables based on this information may be used in software
- * for Commodore Amiga computers. All other rights reserved.
- *
- * This information is provided "as is"; no warranties are made.
- * All use is at your own risk, and no liability or responsibility is assumed.
- *
- * The devs:mountlist needed:
- *
- *--------------------------------------------------------------------
- * CLIP: Handler = l:clipboard-handler
- * Stacksize = 5000
- * Priority = 5
- * GlobVec = 1
- * #
- *--------------------------------------------------------------------
- *
- * I have done this under MANX, but I don't see too much trouble getting
- * it to work with Lattice...just don't use any startup code and
- * disable the stack checking on LC2 with '-v'.
- */
-
- #include "exec/types.h"
- #include "exec/nodes.h"
- #include "exec/lists.h"
- #include "exec/ports.h"
- #include "exec/libraries.h"
- #include "exec/devices.h"
- #include "exec/io.h"
- #include "exec/memory.h"
- #include "intuition/intuition.h"
- #include "libraries/dos.h"
- #include "libraries/dosextens.h"
- #include "libraries/filehandler.h"
- #include "devices/clipboard.h"
-
- #ifdef MANX
- #include "functions.h"
-
- ULONG SysBase, /* these are here to make the startup code happy */
- _savsp; /* (this is unique to Manx Aztec C startup) */
- #endif
-
- struct Process *FindTask();
- struct Message *GetMsg();
- struct ClipArg *AllocMem();
-
- /* A version of BADDR() has no problems with casting */
- #undef BADDR
- #define BADDR(x) ((APTR)((long)x << 2))
-
- #ifndef ACTION_FIND_INPUT
- #define ACTION_FIND_INPUT 1005L /* please refer to DOS Tech. Ref. */
- #endif
- #ifndef ACTION_FIND_OUTPUT
- #define ACTION_FIND_OUTPUT 1006L
- #endif
- #ifndef ACTION_END
- #define ACTION_END 1007L
- #endif
- #ifndef ACTION_SEEK
- #define ACTION_SEEK 1008L
- #endif
-
- struct ClipArg {
- struct IOClipReq ca_IOR;
- struct DosPacket *ca_Packet; /* active dos packet */
- void (*ca_ReplyPacket)(); /* (*ca_ReplyPacket)(process, ca, ) */
- ULONG ca_Data; /* (used to hold seek arguments) */
- ULONG ca_Argument; /* " */
- ULONG ca_Offset; /* " */
- UWORD ca_Direction; /* read or write */
- };
-
- void
- returnPacket(process, packet, res1)
- struct Process *process;
- struct DosPacket *packet;
- ULONG res1;
- {
- struct Message *message;
- struct MsgPort *replyport;
-
- packet->dp_Res1 = res1;
- replyport = packet->dp_Port;
- packet->dp_Port = &process->pr_MsgPort;
- message = packet->dp_Link;
- message->mn_Node.ln_Name = (char *) packet;
-
- #ifdef DEBUG
- kprintf("returnPacket: %ld %ld\t", packet->dp_Res1, packet->dp_Res2);
- #endif
-
- PutMsg(replyport, message);
- }
-
-
- void
- replyClip(process, ca, openCnt)
- struct Process *process;
- struct ClipArg *ca;
- int *openCnt;
- {
- #ifdef DEBUG
- kprintf("replyClip... ");
- #endif
- if (ca->ca_IOR.io_Error) {
- /* Return an indecipherable error */
- ca->ca_Packet->dp_Res2 = 1000+ca->ca_IOR.io_Error;
- returnPacket(process, ca->ca_Packet, -1);
- }
- else {
- returnPacket(process, ca->ca_Packet, ca->ca_IOR.io_Actual);
- }
- }
-
- void
- seekClip(process, ca, openCnt)
- struct Process *process;
- struct ClipArg *ca;
- int *openCnt;
- {
- #ifdef DEBUG
- kprintf("seekClip... ");
- #endif
- if ((ca->ca_IOR.io_Error) || (ca->ca_IOR.io_Actual != 4L)) {
- /* cannot seek from end of file */
- ca->ca_Packet->dp_Res2 = ERROR_SEEK_ERROR;
- returnPacket(process, ca->ca_Packet, -1);
- }
- else {
- ca->ca_IOR.io_Offset = ca->ca_Data + ca->ca_Argument + 8;
- returnPacket(process, ca->ca_Packet, ca->ca_Offset);
- }
- }
-
-
- void
- closeClip(process, ca, openCnt)
- struct Process *process;
- struct ClipArg *ca;
- int *openCnt;
- {
- struct DosPacket *packet;
- #ifdef DEBUG
- kprintf("closeClip %ld... ", ca->ca_IOR.io_Error);
- #endif
-
- /* cache the packet */
- packet = ca->ca_Packet;
- /* close the clipboard device */
- CloseDevice(&ca->ca_IOR);
- /* free the clipboard IO request */
- FreeMem(ca, sizeof(struct ClipArg));
- (*openCnt)--;
- returnPacket(process, packet, DOSTRUE);
- }
-
-
- _main()
- {
- /* handler related data structures */
- struct Process *myProcess; /* my process */
- struct DeviceNode *myDevNode; /* our device node passed in Arg3 */
- struct DosPacket *packet; /* a pointer to a dos packet sent */
- struct MsgPort clipReplyPort; /* the reply port for clipboard IO */
- struct IOClipReq openIOR; /* clipboard request to keep dev open */
- struct ClipArg *ca; /* clipboard.device IO request, etc. */
- struct FileHandle *fh; /* a pointer to a file handle */
- ULONG sigPacket, sigClipReply; /* individual signal masks */
- ULONG sigWait; /* combined signal mask */
- ULONG signal; /* current signal mask */
- UWORD unit; /* clipboard unit number */
- int openCnt; /* access counter to this handler */
- char alive; /* absence of ACTION_DIE */
- struct Message *message; /* a message temporary */
- char *name; /* filename temporary */
- int result, i; /* some temporarys */
-
- #ifdef DEBUG
- kprintf("\n********************\nStart CLIP:\n");
- #endif
-
- /*
- * Initialization: initialize some things while the parameter packet
- * gets here
- */
- myProcess = (struct Process *) FindTask(0L); /* find myself */
-
- /* set up the message port for clipboard I/O requests */
- clipReplyPort.mp_Node.ln_Type = NT_MSGPORT;
- clipReplyPort.mp_Flags = 0;
- clipReplyPort.mp_SigBit = AllocSignal(-1);
- clipReplyPort.mp_SigTask = (struct Task *) myProcess;
- NewList(&clipReplyPort.mp_MsgList);
-
- /* set the signal masks */
- sigPacket = 1 << myProcess->pr_MsgPort.mp_SigBit;
- sigClipReply = 1 << clipReplyPort.mp_SigBit;
- sigWait = sigPacket | sigClipReply;
-
- alive = TRUE; /* handler loop flag */
- openCnt = 0; /* handler open count */
- /*
- * Get Parameters: since this is a non-BCPL module it gets sent the
- * parameter pkt. (BCPL modules get it in D1)
- */
-
- while ((message = GetMsg(&myProcess->pr_MsgPort)) == NULL)
- /* wait for parameter packet */
- Wait(sigPacket);
-
- #ifdef DEBUG
- kprintf("Got Parmeter Packet\n");
- #endif
-
- /*
- * open the clipboard.device so it will stay open throughout the duration
- * of the life of the CLIP: handler. Otherwise, the clip goes to disk
- * a lot.
- */
- openIOR.io_Message.mn_ReplyPort = &clipReplyPort;
- openIOR.io_Device = 0;
- OpenDevice("clipboard.device", 0, &openIOR, 0);
-
- /* get the pointer to the device node */
- packet = (struct DosPacket *) (message->mn_Node.ln_Name);
- myDevNode = (struct DeviceNode *) BADDR(packet->dp_Arg3);
-
- /*
- * install our taskid ... if we don't...for every reference
- * to our handler a NEW process will be created. This is
- * fine for things like CON: (console handler) but if you
- * plan to be the only dude on block ( like the file-system
- * handler or SER: ) you should fill the task field with
- * your taskid (ie. &(pr_MsgPort) ) Note:
- * remember that shared code has to be reentrant. (like
- * CON: handler) ( keep your variables on the stack
- * [autos], and allocate memory for larger data structures
- * and "FLAG" global data structures that need only be
- * intialized once )
- */
- myDevNode->dn_Task = &myProcess->pr_MsgPort;
-
- #ifdef DEBUG
- kprintf("Returning parmeter packet\n");
- #endif
-
- /* indicate initialization was successful */
- returnPacket(myProcess, packet, DOSTRUE);
-
- /*
- * Main Loop: look for things to do that are either
- * 1. New packets to this handler
- * 2. Completions of clipboard.device IO and thus of an associated packet
- */
- while (alive) { /* start of the real work */
- #ifdef DEBUG
- kprintf("Waiting... ");
- #endif
- signal = Wait(sigWait);
-
- /*
- * Packet handler: handle the packet
- */
- if (signal & sigPacket) {
- while (message = GetMsg(&myProcess->pr_MsgPort)) {
- packet = (struct DosPacket *) (message->mn_Node.ln_Name);
- switch (packet->dp_Type) {
- case ACTION_FIND_INPUT:
- case ACTION_FIND_OUTPUT:
- /*
- * Open: be flexible about opening for read or write here
- */
- #ifdef DEBUG
- kprintf("Open: \"");
- for (i = 1; i <= *(char *) BADDR(packet->dp_Arg3); i++)
- kprintf("%lc", ((char *) BADDR(packet->dp_Arg3))[i]);
- kprintf("\"\t");
- #endif
- fh = (struct FileHandle *) BADDR(packet->dp_Arg1);
- /* allocate the clipboard IO request */
- ca = (struct ClipArg *)
- AllocMem(sizeof(struct ClipArg), MEMF_CLEAR);
- fh->fh_Port = DOSFALSE; /* not interactive */
- if (fh->fh_Arg1 = (LONG) ca) {
- ca->ca_IOR.io_Message.mn_ReplyPort = &clipReplyPort;
- /* get the clip unit from the name, if it exists */
- unit = 0;
- name = (char *) BADDR(packet->dp_Arg3);
- /* find colon of clip device name */
- for (i = 1; (i <= *name) && (name[i] != ':'); i++);
- #ifdef DEBUG
- kprintf("u i %ld '%lc'\t", i, name[i]);
- #endif
- for (i++; i <= *name; i++) {
- if ((name[i] >= '0') && (name[i] <= '9')) {
- unit *= 10;
- unit += name[i] - '0';
- }
- else {
- #ifdef DEBUG
- kprintf("\\ i %ld '%lc'\t", i, name[i]);
- #endif
- unit = -1;
- break;
- }
- }
- #ifdef DEBUG
- kprintf("unit %ld\n", unit);
- #endif
- if (unit >= 0) {
- /* open the clipboard device */
- result = OpenDevice("clipboard.device", unit,
- &ca->ca_IOR, 0);
- if (result != 0) {
- FreeMem(ca, sizeof(struct ClipArg));
- fh->fh_Arg1 = NULL;
- packet->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
- }
- }
- else {
- FreeMem(ca, sizeof(struct ClipArg));
- fh->fh_Arg1 = NULL;
- packet->dp_Res2 = ERROR_BAD_STREAM_NAME;
- }
- }
- else {
- packet->dp_Res2 = ERROR_NO_FREE_STORE;
- }
- ca->ca_Direction = 0L; /* neither read nor write */
- if (fh->fh_Arg1 == NULL) {
- returnPacket(myProcess, packet, DOSFALSE);
- }
- else {
- returnPacket(myProcess, packet, DOSTRUE);
- openCnt++;
- }
- break;
-
- case ACTION_END:
- /*
- * Close
- */
- #ifdef DEBUG
- kprintf("Close\t");
- #endif
- ca = (struct ClipArg *) packet->dp_Arg1;
- if (ca) {
- /* terminate the reading or writing */
- if (ca->ca_Direction != 0) {
- ca->ca_Packet = packet;
- ca->ca_ReplyPacket = closeClip;
- if (ca->ca_Direction == ACTION_READ) {
- /* read past EOF to signal reading is done */
- ca->ca_IOR.io_Command = CMD_READ;
- ca->ca_IOR.io_Length = 1;
- ca->ca_IOR.io_Data = NULL;
- ca->ca_IOR.io_Offset = 0xfffffffe;
- }
- else {
- /* update to signal writing is done */
- ca->ca_IOR.io_Command = CMD_UPDATE;
- }
- SendIO(&ca->ca_IOR);
- break;
- }
- else {
- /* close the clipboard device */
- CloseDevice(&ca->ca_IOR);
- /* free the clipboard IO request */
- FreeMem(ca, sizeof(struct ClipArg));
- openCnt--;
- }
- }
- returnPacket(myProcess, packet, DOSTRUE);
- break;
-
- case ACTION_READ:
- /*
- * Read
- */
- #ifdef DEBUG
- kprintf("Read: %ld\t", packet->dp_Arg3);
- #endif
- ca = (struct ClipArg *) packet->dp_Arg1;
- if (ca->ca_Direction != ACTION_WRITE) {
- ca->ca_Direction = ACTION_READ;
- ca->ca_Packet = packet;
- ca->ca_ReplyPacket = replyClip;
- /* issue clip read */
- ca->ca_IOR.io_Command = CMD_READ;
- ca->ca_IOR.io_Length = packet->dp_Arg3;
- ca->ca_IOR.io_Data = (STRPTR) packet->dp_Arg2;
- SendIO(&ca->ca_IOR);
- }
- else {
- /* cannot read in the middle of a clip write */
- packet->dp_Res2 = ERROR_READ_PROTECTED;
- returnPacket(myProcess, packet, -1);
- }
- break;
-
- case ACTION_WRITE:
- #ifdef DEBUG
- kprintf("Write: %ld\t", packet->dp_Arg3);
- #endif
- ca = (struct ClipArg *) packet->dp_Arg1;
- if (ca->ca_Direction != ACTION_READ) {
- ca->ca_Direction = ACTION_WRITE;
- ca->ca_Packet = packet;
- ca->ca_ReplyPacket = replyClip;
- /* issue clip write */
- ca->ca_IOR.io_Command = CMD_WRITE;
- ca->ca_IOR.io_Length = packet->dp_Arg3;
- ca->ca_IOR.io_Data = (STRPTR) packet->dp_Arg2;
- SendIO(&ca->ca_IOR);
- }
- else {
- /* cannot write in the middle of a clip read */
- packet->dp_Res2 = ERROR_WRITE_PROTECTED;
- returnPacket(myProcess, packet, -1);
- }
- break;
-
- case ACTION_SEEK:
- /*
- * Seek
- */
- #ifdef DEBUG
- kprintf("Seek: %ld %ld\t", packet->dp_Arg2, packet->dp_Arg3);
- #endif
- ca = (struct ClipArg *) packet->dp_Arg1;
- result = ca->ca_IOR.io_Offset; /* cache old position */
- if (packet->dp_Arg3 == OFFSET_BEGINNING) {
- ca->ca_IOR.io_Offset = packet->dp_Arg2;
- returnPacket(myProcess, packet, result);
- }
- else if (packet->dp_Arg3 == OFFSET_CURRENT) {
- ca->ca_IOR.io_Length += packet->dp_Arg2;
- returnPacket(myProcess, packet, result);
- }
- else {
- /* can only determine end by reading IFF length */
- if (ca->ca_Direction != ACTION_WRITE) {
- ca->ca_Argument = packet->dp_Arg2;
- ca->ca_Offset = result;
- ca->ca_Direction = ACTION_READ;
- ca->ca_Packet = packet;
- ca->ca_ReplyPacket = seekClip;
- /* issue clip read */
- ca->ca_IOR.io_Command = CMD_READ;
- ca->ca_IOR.io_Length = 4;
- ca->ca_IOR.io_Data = (STRPTR) &ca->ca_Data;
- ca->ca_IOR.io_Offset = 4;
- SendIO(&ca->ca_IOR);
- }
- else {
- /* cannot seek from end of file */
- packet->dp_Res2 = ERROR_SEEK_ERROR;
- returnPacket(myProcess, packet, -1);
- }
- }
- break;
-
- default:
- /*
- * Unsupported packet type
- */
- #ifdef DEBUG
- kprintf("Unknown packet type %ld\t", packet->dp_Type);
- #endif
- packet->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
- returnPacket(myProcess, packet, DOSFALSE);
- } /* switch(packet->dp_Type) */
- }
- }
- /*
- * Clipboard IO Reply: reply the packet
- */
- if (signal & sigClipReply) {
- while (ca = (struct ClipArg *) GetMsg(&clipReplyPort)) {
- /*
- * ReplyPacket: process this ClipArg by calling its
- * reply routine
- */
- (*ca->ca_ReplyPacket)(myProcess, ca, &openCnt);
- }
- }
- } /* while() */
-
- #ifdef DEBUG
- kprintf("Kill CLIP:\n");
- #endif
-
- if (openIOR.io_Device != 0) CloseDevice(&openIOR);
-
- myDevNode->dn_Task = NULL; /* zero the taskid field of device node */
-
- /*
- * Return: let whoever it was that spawned us provide the cleanup code
- */
- } /* _main() */
-