Le bénéfice doit être apporté aux applications tournant sous taskwindow comme à des programmes Wimp pour lesquels vous pouvez ne pas disposer du source et/ou d'un environnement de développement adéquat.
Une manière simple d'y arriver serait d'implémenter cette facilité dans une librairie telle que celle décrite sur une autre page; cependant, cela restreindrait par trop le champ d'application que je souhaite aussi vaste que possible (programmes écrits dans d'autres langages, programmes n'utilisant pas la librairie Uname etc..).
La solution proposée est basée sur l'utilisation d'un module CWDSupport, chargé d'installer entre autres, pour chaque tâche enregistrée auprès de lui, un filtre pré-polling comme un filtre post-polling.
OS_FSControlV
afin de détecter les changements dans la configuration des systèmes de fichiers "surveillés" tant que la tâche Wimp est active.
Wimp_Initialise
; Tapez juste CWDRegister au prompt CLI * d'une fenêtre taskwindow; A partir de ce moment, il est possible de déclarer certaines variables d'environnement comme privées pour cette tâche: c'est aussi simple que de soummettre la commande CWDRegVar (par ex. CWDRegVar File*Path Sys$RCLimit
).
CWDRegisterCatch
laquelle peut accepter une syntaxe équivalente à CWDRegVar
(production des mêmes effets). À partir de ce moment là, la prochaine tâche Wimp qui s'initialisera sera d'office enregistrée avec le module et les variables spécifiées déclarées dans son contexte privé.
CWDUnRegister
(avec la fonction system()
pour un programme C dont vous disposez des sources) lors de sa séquence de terminaison;
Service_WimpCloseDown
.
*CWDShow >struct 021ea954 id = 0 tskhdl = 7cc020f8 taskname TaskWindow mode solicited fsname ADFS fsnum 8 CSD pathwsf 022909ec <> resofpath 00000000 specialfield 00000000 PSD pathwsf 02290afc <> resofpath 00000000 specialfield 00000000 URD pathwsf 02290c0c <> resofpath 00000000 specialfield 00000000 Lib pathwsf 02290d1c <> resofpath 00000000 specialfield 00000000 registered vars none struct 021f1fe4 id = 1 tskhdl = 7d402100 taskname Alarm mode unsolicited fsname ADFS fsnum 8 CSD pathwsf 0228ec7c <> resofpath 00000000 specialfield 00000000 PSD pathwsf 0228ed8c <> resofpath 00000000 specialfield 00000000 URD pathwsf 0228ee9c <> resofpath 00000000 specialfield 00000000 Lib pathwsf 0228efac <> resofpath 00000000 specialfield 00000000 registered vars name <Alarm$Path> exists Y vartype <0> value <Choices:Alarm.,Resources:$.Apps.!Alarm.,Resources:$.Resources.Alarm.>
Ici deux tâches le sont, la tâche qui a émis la commande CWDShow
est marquée par un signe > en début de ligne; la tâche Alarm
a été enregistrée par l'artifice de la commande CWDRegisterCatch Alarm$Path
.
ttask
) contenant deux listes: une liste contenant les désignations des systèmes de fichiers connus de la tâche (à commencer par le système de fichier temporaire lorsque la tâche s'est lancé) et l'autre liste contenant les spécifications de variables privées (ces deux listes constituant l'essentiel du résultat de la commande CWDShow
).
Wimp_Poll
au sein de l'application.
/* This function is a copy routine relevant to FS setting contexts * as managed from inside the module */ static void ctx_cpy(tpathelm *pdest, const tpathelm *psrc) { const ptrdiff_t moff= (char *) pdest - (char *) psrc; strcpy(pdest->pathwithsf, psrc->pathwithsf); pdest->restofpath= psrc->restofpath ? (psrc->restofpath + moff) : NULL; pdest->specialfield= psrc->specialfield ? (psrc->specialfield + moff) : NULL; } static _kernel_oserror *mswp(tfspath *mpt, BOOL getonly, size_t ipath) { _kernel_oserror *p; _kernel_swi_regs r; tpathelm *mptelm= &(mpt->mpaths[ipath]), lelm; /* Read current setting into the lelm struct */ r.r[0]= 54; r.r[1]= (int) &(lelm.pathwithsf); r.r[2]= ipath; r.r[3]= (int) &(mpt->fsname); r.r[5]= sizeof(lelm.pathwithsf); p= osfscontrol(&r); if(p) return p; lelm.pathwithsf[sizeof(lelm.pathwithsf)-r.r[5]]= '\0'; lelm.restofpath= (char *) r.r[1]; lelm.specialfield= (char *) r.r[6]; if(!getonly) { /* Set the current setting from struct pointed by mptelm */ r.r[0]= 53; r.r[1]= (int) mptelm->restofpath; r.r[2]= ipath; r.r[3]= (int) &(mpt->fsname); r.r[6]= (int) mptelm->specialfield; p= osfscontrol(&r); } ctx_cpy(mptelm, &lelm); return p; } /* Swap the FS setting between the task context and the * global context */ _kernel_oserror *setting_switch(ttask *pt, BOOL getonly) { _kernel_oserror *p; _kernel_swi_regs r; struct MinNode *pw; tfspath *mpt; int ipath, curfsnumber= gettempfsnumber(&p); if(p) return p; if(curfsnumber!= pt->fsnumber) { if(!getonly) { r.r[0]= 14; /* Set the current file system */ r.r[1]= pt->fsnumber; p= osfscontrol(&r); } pt->fsnumber= curfsnumber; if(p) return p; } /* Browse through the list of FS known to the task */ for(pw= pt->malfs.mlh_Head; pw->mln_Succ; pw= pw->mln_Succ) { mpt= (tfspath *) ((char *) pw - offsetof(tfspath, mnode)); for(ipath= 0; ipath < NPATHS; ipath++) { p= mswp(mpt, getonly, ipath); if(p) return p; } } return p; } int post_filter_handler(_kernel_swi_regs *pr, void *pw) { ttask *lgpt; if(pr->r[0] == -1) return 1; lgpt= FindTask(pr->r[2], TRUE); if(lgpt == NULL) return 1; gpt= lgpt; post_filt_varjob(lgpt); /* process system variables */ (void) setting_switch(lgpt, FALSE); /* process FS settings */ bact= TRUE; return 1; } int pre_filter_handler(_kernel_swi_regs *pr, void *pw) { ttask *lgpt= FindTask(pr->r[2], TRUE); if(!lgpt) return 1; gpt= NULL; bact= FALSE; validate_and_unify(lgpt); /* manage new FS discoveries */ pre_filt_varjob(lgpt); /* process system variables */ (void) setting_switch(lgpt, FALSE); /* process FS settings */ return 1; }
pre_filt_varjob
et post_filt_varjob
se trouvent dans le module source vrutils.c
. Une différence à noter par rapport à la gestion des systèmes de fichiers est que la gestions des variables se base sur un système d'enregistrement(voir les commandes CWDRegVar
, CWDUnregVar
et CWDRegisterCatch
) et non sur un système de découvertes au fil de l'eau de nouveaux système de fichiers (à travers l'utilisation du vecteur OS_FSControlV
).
Une autre différence d'implémentation par rapport à la gestion des systèmes de fichiers est que l'allocation mémoire pour stocker les noms et valeurs de variables d'environnement est dynamique et peut donc supporter les variables de type code n'ayant pas de taille maximum.
Les commandes CWDRegVar
et CWDRegisterCatch
acceptent des caractères joker dans la spécification de leur paramètres et fonctionnent donc comme la commande RISC OS Show
.
Ce n'est pas le cas de la commande CWDUnregVar
qui n'accepte pas de caractères joker dans ses paramètres de noms de variables.
static BOOL bglob; static char lbuf[256]; static int largc; ... static _kernel_oserror *set_filter( BOOL mount, void *pw) { extern int post_generic( _kernel_swi_regs *, void *); static const int filter_mask = ~(Wimp_Poll_UserMessageMask | Wimp_Poll_UserMessageRecordedMask); static const char fname[]= "CWDcatch"; _kernel_swi_regs r; _kernel_oserror *p; r.r[0]= (int) fname; r.r[1]= (int) post_generic; r.r[2]= (int) pw; /* pw */ r.r[3]= 0; r.r[4]= filter_mask; p= _kernel_swi(mount ? Filter_RegisterPostFilter : Filter_DeRegisterPostFilter, &r, &r); if(!p) bglob= mount; return p; } ... int post_generic_handler( _kernel_swi_regs *pr, void *pw) { WimpUserMessageEvent *pum; ttask *pt; pum= (WimpUserMessageEvent *) pr->r[1]; if(pum->hdr.action_code == Wimp_MTaskInitialise) { pt= sNewtask(pum->hdr.sender, TRUE, pw, NULL); if(pt && largc > 0) traite_insert_strings(lbuf, pt, FALSE, largc); (void) set_filter(FALSE, pw); } return 1; } _kernel_oserror *regcatch_next( void *pw, const char *str, int argc) { _kernel_oserror *p; p= bglob ? NULL : set_filter(TRUE, pw); if(!p) { /* copy arg string to static buffer for future use */ largc= argc; strncpy(lbuf, str, sizeof(lbuf) -1); } return p; }La fonction
regcatch_next
est appelée pour traiter la commande CWDRegisterCatch
.
Les personnes intéressées pourront trouver utile le petit utilitaire compagnon SYSCSD qui permet que le prompt CLI d'une taskwindow affiche le CSD courant (juste en soumettant la commande *SetMacro CLI$Prompt <Sys$CSD> *
après le lancement de l'utilitaire SYSCSD03.
Le code source !AAsm est inclus dans l'archive afin que vous puissiez vérifier par vous même qu'il ne s'agit pas d'un virus.