netsurf/atari/dragdrop.c

516 lines
8.5 KiB
C
Raw Normal View History

/*
* Routine pour Drag and drop sous MultiTos
* source: D&D Atari, demo OEP (Alexander Lorenz)
*
* Struktur OEP (oep.apid): AES-ID der Applikation
*
* (Tab = 4)
*/
#ifdef __PUREC__
#include <tos.h>
#else
#include <osbind.h>
#include <mintbind.h>
#include <signal.h>
#endif
#include <string.h>
#include <stdio.h>
#include "windom.h"
#include "dragdrop.h"
#ifndef EACCDN
#define EACCDN (-36)
#endif
#ifndef FA_HIDDEN
#define FA_HIDDEN 0x02
#endif
static char pipename[] = "U:\\PIPE\\DRAGDROP.AA";
static long pipesig;
/*
* Routinen f<EFBFBD>r den Sender
*/
/*
* Erzeugt Pipe f<EFBFBD>r D&D
*
* Eingabeparameter:
* pipe - Pointer auf 2 Byte Buffer f<EFBFBD>r Pipeextension
*
* Ausgabeparameters:
* keine
*
* Returnwert:
* >0: Filehandle der Pipe
* -1: Fehler beim Erzeugen der Pipe
*/
short ddcreate(short *pipe)
{
long fd = -1;
pipename[17] = 'A';
pipename[18] = 'A' - 1;
do /* ouvre un pipe inoccup<75> */
{
pipename[18]++;
if (pipename[18] > 'Z')
{
pipename[17]++;
if (pipename[17] > 'Z')
break;
else
pipename[18] = 'A';
}
/* FA_HIDDEN f<>r Pipe notwendig! */
fd = Fcreate(pipename, FA_HIDDEN);
} while (fd == (long) EACCDN);
if (fd < 0L)
return(-1);
*pipe = (pipename[17] << 8) | pipename[18];
/* Signalhandler konfigurieren */
ddgetsig(&pipesig);
return((short) fd);
}
/*
* Sendet AP_DRAGDROP an Empf<EFBFBD>ngerapplikation
*
* Eingabeparameter:
* apid - AES-ID der Emf<EFBFBD>ngerapp.
* fd - Filehandle der D&D-Pipe
* winid - Handle des Zielfensters (0 f<EFBFBD>r Desktopfenster)
* mx/my - Maus X und Y Koord.
* (-1/-1 f<EFBFBD>r einen fake Drag&Drop)
* kstate - Sondertastenstatus
* pipename - Extension der D&D-Pipe
*
* Ausgabeparameter:
* keine
*
* Returnwert:
* >0: kein Fehler
* -1: Empf<EFBFBD>ngerapp. gibt DD_NAK zur<EFBFBD>ck
* -2: Empf<EFBFBD>ngerapp. antwortet nicht (Timeout)
* -3: Fehler bei appl_write()
*/
short ddmessage(short apid, short fd, short winid, short mx, short my, short kstate, short pipeid)
{
char c;
short i, msg[8];
long fd_mask;
/* AES-Message define and post */
msg[0] = AP_DRAGDROP;
msg[1] = _AESapid;
msg[2] = 0;
msg[3] = winid;
msg[4] = mx;
msg[5] = my;
msg[6] = kstate;
msg[7] = pipeid;
i = appl_write(apid, 16, msg);
if (i == 0)
{
ddclose(fd);
return(-3);
}
/* receiver reaction */
fd_mask = (1L << fd);
i = Fselect(DD_TIMEOUT, &fd_mask, 0L, 0L);
if (!i || !fd_mask)
{
/* Timeout eingetreten */
ddclose(fd);
return(-2);
}
/* le recepteur refuse (lecture du pipe) */
if (Fread(fd, 1L, &c) != 1L)
{
ddclose(fd);
return(-1);
}
if (c != DD_OK)
{
ddclose(fd);
return(-1);
}
return(1);
}
/*
* Liest die 8 "bevorzugten" Extensionen der Empf<EFBFBD>ngerapplikation
*
* Eingabeparameter:
* fd - Filehandle der D&D-Pipe
*
* Ausgabeparameters:
* exts - 32 Bytebuffer f<EFBFBD>r die 8 bevorzugten Extensionen
* der Zielapp.
*
* Returnwert:
* >0: kein Fehler
* -1: Fehler beim Lesen aus der Pipe
*/
short ddrexts(short fd, char *exts)
{
if (Fread(fd, DD_EXTSIZE, exts) != DD_EXTSIZE)
{
ddclose(fd);
return(-1);
}
return(1);
}
/*
* Testet, ob der Empf<EFBFBD>nger einen Datentyp akzeptiert
*
* Eingabeparameter:
* fd - Filehandle (von ddcreate())
* ext - Zeiger auf Datentyp (4 Bytes zB. "ARGS")
* text - Zeiger auf Datenbeschreibung (optional, zB. "DESKTOP args")
* name - Zeiger auf Datendateiname (optional, zB. "SAMPLE.TXT")
* size - Anzahl Bytes der zu sendenden Daten
*
* Ausgabeparameter:
* keine
*
* Returnwert:
* DD_OK - Empf<EFBFBD>nger akzeptiert Datentyp
* DD_NAK - Empf<EFBFBD>nger brach Drag&Drop ab
* DD_EXT - Empf<EFBFBD>nger lehnt Datentyp ab
* DD_LEN - Empf<EFBFBD>nger kann Datenmenge nicht verarbeiten
* DD_TRASH - Drop erfolgte auf M<EFBFBD>lleimer
* DD_PRINTER - Drop erfolgte auf Drucker
* DD_CLIPBOARD - Drop erfolgte auf Clipboard
*/
short ddstry(short fd, char *ext, char *text, char *name, long size)
{
char c;
short hdrlen, i;
/* 4 Bytes f<>r "ext", 4 Bytes f<>r "size",
2 Bytes f<EFBFBD>r Stringendnullen */
hdrlen = (short) (4 + 4 + strlen(text)+1 + strlen(name)+1);
/* Header senden */
if (Fwrite(fd, 2L, &hdrlen) != 2L)
return(DD_NAK);
i = (short) Fwrite(fd, 4L, ext);
i += (short) Fwrite(fd, 4L, &size);
i += (short) Fwrite(fd, strlen(text)+1, text);
i += (short) Fwrite(fd, strlen(name)+1, name);
if (i != hdrlen)
return(DD_NAK);
/* auf die Antwort warten */
if (Fread(fd, 1L, &c) != 1L)
return(DD_NAK);
return(c);
}
/* Routinen f<>r Sender und Empf<70>nger */
/*
* Pipe schlie<EFBFBD>en (Drag&Drop beenden/abbrechen)
*/
void ddclose(short fd)
{
/* Signalhandler restaurieren */
ddsetsig(pipesig);
Fclose(fd);
}
/*
* Signalhandler f<EFBFBD>r D&D konfigurieren
*
* Eingabeparameter:
* oldsig - Zeiger auf 4 Byte Puffer f<EFBFBD>r alten Handlerwert
*
* Ausgabeparameter:
* keine
*
* Returnwerte:
* keine
*/
void ddgetsig(long *oldsig)
{
*oldsig = (long) Psignal(SIGPIPE, (void *) SIG_IGN);
}
/*
* Signalhandler nach D&D restaurieren
*
* Eingabeparameter:
* oldsig - Alter Handlerwert (von ddgetsig)
*
* Ausgabeparameter:
* keine
*
* Returnwerte:
* keine
*/
void ddsetsig(long oldsig)
{
if (oldsig != -32L)
Psignal(SIGPIPE, (void *) oldsig);
}
/* Routinen f<>r Empf<70>nger */
/*
* Drag&Drop Pipe <EFBFBD>ffnen
*
* Eingabeparameter:
* ddnam - Extension der Pipe (letztes short von AP_DRAGDROP)
* ddmsg - DD_OK oder DD_NAK
*
* Ausgabeparameter:
* keine
*
* Returnwerte:
* >0 - Filehandle der Drag&Drop pipe
* -1 - Drag&Drop abgebrochen
*/
short ddopen(short ddnam, char ddmsg)
{
long fd;
pipename[17] = (ddnam & 0xff00) >> 8;
pipename[18] = ddnam & 0x00ff;
fd = Fopen(pipename, 2);
if (fd < 0L)
return(-1);
/* Signalhandler konfigurieren */
ddgetsig(&pipesig);
if (Fwrite((short) fd, 1L, &ddmsg) != 1L)
{
ddclose((short) fd);
return(-1);
}
return((short) fd);
}
/*
* Schreibt die 8 "bevorzugten" Extensionen der Applikation
*
* Eingabeparameter:
* fd - Filehandle der D&D-Pipe
* exts - Liste aus acht 4 Byte Extensionen die verstanden
* werden. Diese Liste sollte nach bevorzugten Datentypen
* sortiert sein. Sollten weniger als DD_NUMEXTS
* Extensionen unterst<EFBFBD>tzt werden, mu<EFBFBD> die Liste mit
* Nullen (0) aufgef<EFBFBD>llt werden!
*
* Ausgabeparameter:
* keine
*
* Returnwert:
* >0: kein Fehler
* -1: Fehler beim Schreiben in die Pipe
*/
short ddsexts(short fd, char *exts)
{
if (Fwrite(fd, DD_EXTSIZE, exts) != DD_EXTSIZE)
{
ddclose(fd);
return(-1);
}
return(1);
}
/*
* N<EFBFBD>chsten Header vom Sender holen
*
* Eingabeparameter:
* fd - Filehandle der Pipe (von ddopen())
*
* Ausgabeparameters:
* name - Zeiger auf Buffer f<EFBFBD>r Datenbeschreibung (min. DD_NAMEMAX!)
* file - Zeiger auf Buffer f<EFBFBD>r Datendateiname (min. DD_NAMEMAX!)
* whichext- Zeiger auf Buffer f<EFBFBD>r Extension (4 Bytes)
* size - Zeiger auf Buffer f<EFBFBD>r Datengr<EFBFBD><EFBFBD>e (4 Bytes)
*
* Returnwert:
* >0: kein Fehler
* -1: Sender brach Drag&Drop ab
*
* On lit dans le pipe qui normalement est constitu<EFBFBD> de:
* 1 short: taille du header
* 4 CHAR: type de donn<EFBFBD>e (extension)
* 1 long: taille des donn<EFBFBD>es
* STRING: description des donn<EFBFBD>es
* STRING: nom du fichiers
* soit au minimun 11 octets (cas ou les string sont r<EFBFBD>duites <EFBFBD> \0)
* les string sont limit<EFBFBD> a 128 octets
*/
short ddrtry(short fd, char *name, char *file, char *whichext, long *size)
{
char buf[DD_NAMEMAX * 2];
short hdrlen, i, len;
if (Fread(fd, 2L, &hdrlen) != 2L)
return(-1);
if (hdrlen < 9) /* il reste au minimum 11 - 2 = 9 octets a lire */
{
/* sollte eigentlich nie passieren */
return(-1); /* erreur taille incorrecte */
}
if (Fread(fd, 4L, whichext) != 4L) /* lecture de l'extension */
return(-1);
if (Fread(fd, 4L, size) != 4L) /* lecture de la longueurs des donn<6E>es */
return(-1);
hdrlen -= 8; /* on a lu 8 octets */
if (hdrlen > DD_NAMEMAX*2)
i = DD_NAMEMAX*2;
else
i = hdrlen;
len = i;
if (Fread(fd, (long) i, buf) != (long) i)
return(-1);
hdrlen -= i;
strncpy(name, buf, DD_NAMEMAX);
i = (short) strlen(name) + 1;
if (len - i > 0)
strncpy(file, buf + i, DD_NAMEMAX);
else
file[0] = '\0';
/* weitere Bytes im Header in den M<>ll */
while (hdrlen > DD_NAMEMAX*2)
{
if (Fread(fd, DD_NAMEMAX*2, buf) != DD_NAMEMAX*2)
return(-1);
hdrlen -= DD_NAMEMAX*2;
}
if (hdrlen > 0)
{
if (Fread(fd, (long) hdrlen, buf) != (long) hdrlen)
return(-1);
}
return(1);
}
/*
* Sendet der Senderapplikation eine 1 Byte Antwort
*
* Eingabeparameter:
* fd - Filehandle der Pipe (von ddopen())
* ack - Byte das gesendet werden soll (zB. DD_OK)
*
* Ausgabeparameter:
* keine
*
* Returnwert:
* >0: kein Fehler
* -1: Fehler (die Pipe wird automatisch geschlossen!)
*/
short ddreply(short fd, char ack)
{
if (Fwrite(fd, 1L, &ack) != 1L)
{
ddclose(fd);
return(-1);
}
return(1);
}