Serveur de données Presse-Papiers
Le module impliqué est c.clipboard
. Ce module se retrouve dans les quatre applications composantes de la suite. Au moment de l'initialisation, la fonction clipboard_init
est appelée; cette dernière:
- enregistrera des gestionnaires d'évènements;
- initialisera des varaibles globales comme les structures de messages pour l'envoi de messages Wimp ClaimEntity et DataSave.
Lorsque l'utilisateur clique sur l'un des items du menu, alors le code contenu dans la fonction msel_event
s'exécutera:
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;
}
Si une autre tâche déclare être le propriétaire du presse-papier, alors la seule action est de se souvenir de l'ID de tâche WIMP.
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;
}
La politique appliquée ici est que !AddressB ne prend en compte les messages DataRequest que si l'application est la propriétaire actuelle du presse-papier. Alors nous examinons en séquence tous les types de fichiers aue le client (source du message DataRequest) est capable de traiter.
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;
}
On force ensuite la variable state
à la valeur WAITFORDATASAVEACKORRF
qui signifie que le client peut répondre avec soit un message RamFetch (transsfer en mémoire) soit un message DataSaveAck (méthode de transfer à base de fichiers).
Si le client répond avec un message DataSaveAck, alors la fonction suvante est appelée:
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;
}