La version actuelle est la v0.4.2
Auteur: Benoît GILON
Logo de HTMLEdit v3
Retour à la page de description !AddressB

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: 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;
}