Clipboard Data Server part
The module involved is c.clipboard. This module is part of every application suite module. At initialisation time, the clipboard_init function is called; the latter will:
- register event handlers;
- initialise global variables like the message structures for sending ClaimEntity and DataSave WIMP messages.
When the user clicks on on one of the copy item in the menu, then the function msel_event is called:
void bgig_copy(ComponentId cid, char *const pcopy)
{
switch(cid)
{
case KMENTMENCOMP:
sprintf(pcopy,"%s %s %s",
pseltitre[mesdonnees.data.titre - '0'],
mesdonnees.data.prenom,
mesdonnees.data.nom);
break;
case KMENTSANSTITRE:
sprintf(pcopy, "%s %s",
mesdonnees.data.prenom,
mesdonnees.data.nom);
break;
}
}
...
static char pcopie[256];
...
static int msel_event(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
{
bgig_copy(id_block->self_component, pcopie);
msize= strlen(pcopie) + 1;
(void) wimp_send_message(Wimp_EUserMessage, &monmessce, 0, 0, NULL);
return 1;
}
If another task claims the clipboard then we just quote the task handle.
static int ce_message(WimpMessage *message, void *handle)
{
WimpClaimEntityMessage *pmes= &(((MWimpMessage *) message)->data.claim_entity);
if(pmes->flags & CLIPBOARD_CLAIMED) tskhdl= message->hdr.sender;
return 1;
}
The policy performed as !AddressB is handling a DataRequest message is to proceed only if the current clipboard owner is the !AddressB task. Then we scan all the filetypes that the data client (sender of the DataRequest message) is able to deal with.
static int dr_message(WimpMessage *message, void *handle)
{
WimpDataRequestMessage *pmes= (WimpDataRequestMessage *) &(message->data);
int *pi;
if(tskhdl == mytskhdl && state == IDLE && msize!= -1)
{
for(pi= pmes->filelist; *pi != -1; pi++)
if(*pi == 0xfff)
{
monmessds.hdr.your_ref= message->hdr.my_ref;
monmessds.data.data_save.estimated_size= msize;
monmessds.data.data_save.destination_window=
pmes->win_handle;
monmessds.data.data_save.destination_icon=
pmes->internal_handle;
monmessds.data.data_save.destination_x= pmes->x;
monmessds.data.data_save.destination_y= pmes->y;
wimp_send_message(Wimp_EUserMessageRecorded,
&monmessds, message->hdr.sender, 0, NULL);
refm= monmessds.hdr.my_ref;
state= WAITFORDATASAVEACKORRF;
return 1;
}
}
return 0;
}
We then set our state variable to WAITFORDATASAVEACKORRF which means that the client can answer with either a RamFetch (In memory transfer handled) or a DataSaveAck (file method handled) message.
In case the client answers with a DataSaveAck message, then the function below is called:
static int dsa_message(WimpMessage *message, void *handle)
{
FILE *mfile;
WimpDataSaveAckMessage *pmes= (WimpDataSaveAckMessage *) &(message->data);
if(state!= WAITFORDATASAVEACKORRF || refm != message->hdr.your_ref) return 0;
mfile= fopen(pmes->leaf_name, "w");
if(!mfile) {
state= IDLE;
return 1;
}
fputs(pcopie, mfile);
fclose(mfile);
message->hdr.action_code= Wimp_MDataLoad;
message->hdr.your_ref= message->hdr.my_ref;
(void) wimp_send_message(Wimp_EUserMessageRecorded,
message, message->hdr.sender, 0, NULL);
refm= message->hdr.my_ref;
state= WAITFORDATALOADACK;
return 0;
}
In the alternate case where the client can handle in memory transfers, then the application will receive a RamFetch message from it. At the exit of the function the state can be either WAITFORRAMFETCH (transfer still in progress) or IDLE (transfer completed).
static int rf_message(WimpMessage *message, void *handle)
{
WimpRAMFetchMessage *pmes;
_kernel_oserror *p;
size_t ylen;
BOOL moreafter;
if(message->hdr.your_ref!= refm) return 0;
if(mfile) fputs("RAMFetch message recu\n", mfile);
pmes= &(message->data.ram_fetch);
switch(state)
{
case WAITFORDATASAVEACKORRF:
moffset= 0;
case WAITFORRAMFETCH:
ylen= pmes->buffer_size < (msize - moffset) ?
pmes->buffer_size : (msize - moffset);
moreafter= (ylen == pmes->buffer_size);
p= wimp_transfer_block(mytskhdl, pcopie + moffset,
message->hdr.sender, pmes->buffer, ylen);
if(!p) {
message->hdr.your_ref= message->hdr.my_ref;
message->hdr.action_code= Wimp_MRAMTransmit;
pmes->buffer_size= ylen;
p= wimp_send_message(moreafter ?
Wimp_EUserMessageRecorded :
Wimp_EUserMessage,
message, 0, 0, NULL);
moffset+= ylen;
if(!p && moreafter) refm= message->hdr.my_ref;
}
ERROR_CHECK(p)
state= (!p && moreafter) ? WAITFORRAMFETCH : IDLE;
break;
default:
return 0;
}
return 1;
}