Un tel lien relit aussi les tables d'identités (!AddressB) et de ressources URL (!AddressI).
Chacune de ces applications peuvent s'exécuter séparément ou en groupe. Le démarrage en groupe permet toutefois de bénéficier des échanges inter-applications prévus dans le design. Chaque application composante peut être considérée comme:
strncpy
par des appels à la fonction memcpy
puisque mon application stocke des données binaires et non uniquement des chaines de caractères terminées par des caractères nuls.GDBM
est utilisée au sein du code source pour différencier les deux options.typedef struct { int key; struct { char titre; char nom[32]; char prenom[32]; } data; } tmdonnees;
typedef struct { int key; struct { int numvoie; char typevoie; char country; char nom[32]; char zipcode[16]; char commune[32]; } data; } tmdonnees;
typedef struct { int key; struct { int ididentity, idaddress; int type; } data; } tmdonnees;
typedef struct { int key; struct { int ididentity; int type /* E-Mail, Web etc... */, kind /* Privée, professionnelle */; char url[64]; } data; } tmdonnees;
gdbmfront
du composant !AddressB (fonction bgig_init
) (les fonctions d'initialisation des autres composants sont semblables); lorsque cette fonction se termine, la variable gkey
est positionnée à la valeur maximale de toutes les clés d'enregistrement de la base de données et l'enregistrement courant est le premier enregistrement de la base (si cette dernire est non vide), sinon la valeur NEW
est forcée dans la variable state
et la fonction refresh
est appelèe pour mettre à jour l'apparence de la fenêtre. De même une chaine de structures en mémoire contient toutes les valeurs de clé de la base de données , c'est à travers le parcours de cette liste que l'utilisateur peut naviguer avec les touches Flèches gauche et droite.
static void mrefresh(void) { _kernel_oserror *p; char buffer[8]; p= stringset_set_selected(StringSet_IndexedSelection, woid, KSTRSETTITLE, (char *) (mesdonnees.data.titre - '0') /* pseltitre[mesdonnees.data.titre - '0'] */); if(!p) p= writablefield_set_value(0, woid, KWRTFLDNOM, mesdonnees.data.nom); if(!p) p= writablefield_set_value(0, woid, KWRTFLDPRE, mesdonnees.data.prenom); sprintf(buffer,state == OLD ? "%u" : "%u *", currkey); if(!p) p= window_set_title(0, woid, buffer); ERROR_CHECK(p) } ... void bgig_refresh(const ObjectId oid, const int key) { int res; mesdonnees.key= key; res= gdbm_fetch(mdbf, mkey, mval); if(res != -1) mrefresh(); } ... static _kernel_oserror *mgadgetsetf(const ComponentId cid, const int value) { return gadget_set_flags(0, toid, cid, value); } void refresh(void) { struct MinNode *pnode; _kernel_oserror *p; char buffer[8]; int bF= state == OLD ? 0 : Gadget_Faded; p= menu_set_fade(0, wmenuoid, KWMCOPYENT, bF); if(!p) p= gadget_set_flags(0, woid, KACTBUTOK, state == OLD ? Gadget_Faded : 0); if(!p) p= gadget_set_flags(0, woid, KACTBUTCANCEL, state == OLD ? Gadget_Faded : 0); if(!p) p= mgadgetsetf(KACTBUTNEW, bF); if(!p) p= mgadgetsetf(KACTBUTDEL, bF); if(!p) { if(state!= OLD) { p= mgadgetsetf(KADJPREV, Gadget_Faded); if(!p) p= mgadgetsetf(KADJNEXT, Gadget_Faded); } else { pnode= (struct MinNode *) ((char *) pcurkey + offsetof(tkey, mnode)); p= mgadgetsetf(KADJNEXT, pnode->mln_Succ->mln_Succ ? 0 : Gadget_Faded); if(!p) p= mgadgetsetf(KADJPREV, maliste.mlh_Head == pnode ? Gadget_Faded : 0); } } if(!p && (state == NEW)) { mesdonnees.data.titre= '0'; strcpy(mesdonnees.data.nom, "Gilon"); strcpy(mesdonnees.data.prenom, "Benoît"); mrefresh(); } sprintf(buffer,state == OLD ? "%u" : "%u *", currkey); if(!p) p= window_set_title(0, woid, buffer); ERROR_CHECK(p); } ... void bgig_init(void) { int res; mkey.dptr= (void *) &(mesdonnees.key); mkey.dsize= 4; mval.dptr= (void *) &(mesdonnees.data); mval.dsize= sizeof(mesdonnees.data); mdbf= gdbm_open("<AddressB$Dir>.Resources.Address"); if(mdbf == (gdbm_file_info *) -1) return; atexit(bgig_atex); NewList((struct List *) &maliste); event_register_toolbox_handler(toid, KACTBUTNEWEVENT, new_event, 0); event_register_toolbox_handler(toid, KACTBUTDELEVENT, del_event, 0); event_register_toolbox_handler(woid, KACTBUTOKEVENT, ok_event, 0); event_register_toolbox_handler(woid, KACTBUTCANEVENT, can_event, 0); event_register_toolbox_handler(toid, Adjuster_Clicked, prevnext_event, 0); event_register_toolbox_handler(woid, WritableField_ValueChanged, vchanged_event, 0); event_register_toolbox_handler(woid, StringSet_ValueChanged, vchanged_event, 0); pseltitre[0]= lookup_token("TITLE0:Mister"); pseltitre[1]= lookup_token("TITLE1:Missis"); pseltitre[2]= lookup_token("TITLE2:Miss"); pseltitre[3]= lookup_token("TITLE3:Doctor"); clipboard_init(); /* Find next key value */ #ifdef GDBM res= gdbm_firstkey(mdbf, mkey); #else res= gdbm_firstkey(mdbf, mkey, sizeof(mesdonnees.data)); #endif if(res != -1) { currkey= mesdonnees.key; do { if(!new_tkey(mesdonnees.key)) break; if(mesdonnees.key > gkey) gkey= mesdonnees.key; #ifdef GDBM } while(gdbm_nextkey(mdbf, mkey, mkey)!= -1); #else } while(gdbm_nextkey(mdbf, mkey, mkey, sizeof(mesdonnees.data))!= -1); #endif state= OLD; gkey++; pcurkey= find_tkey(currkey); bgig_refresh(woid, currkey); } else { currkey= gkey++; state= NEW; } refresh(); }Le code s'exécutant lorsque l'utilisateur clique sur l'une des f;èches de navigation et donné ci-dessous:
static int next_event(ToolboxEvent *event, void *handle) { struct MinNode *pnode= (struct MinNode *) ((char *) pcurkey + offsetof(tkey, mnode)); pnode= pnode->mln_Succ; pcurkey= (tkey *) ((char *) pnode - offsetof(tkey, mnode)); currkey= pcurkey->key; bgig_refresh(woid, currkey); (void) mgadgetsetf(KADJPREV, 0); if(!(pnode->mln_Succ->mln_Succ)) (void) mgadgetsetf(KADJNEXT, Gadget_Faded); return 0; } static int prev_event(ToolboxEvent *event, void *handle) { struct MinNode *pnode= (struct MinNode *) ((char *) pcurkey + offsetof(tkey, mnode)); pnode= pnode->mln_Pred; pcurkey= (tkey *) ((char *) pnode - offsetof(tkey, mnode)); currkey= pcurkey->key; bgig_refresh(woid, currkey); (void) mgadgetsetf(KADJNEXT, 0); if(maliste.mlh_Head == pnode) (void) mgadgetsetf(KADJPREV, Gadget_Faded); return 0; } static int prevnext_event(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle) { return (id_block->self_component == KADJNEXT) ? next_event(event, handle) : prev_event(event, handle); }
bgi_gstore
est utiliser pour appliquer dans la base de données les changement opérés dans la fenêtre de saisie, cela dès que l'utilisateur a cliqué sur le bouton OK.
void bgig_store(const ObjectId oid) { _kernel_oserror *p; int nbytes; int is; p= stringset_get_selected(StringSet_IndexedSelection, oid, KSTRSETTITLE, &is, sizeof(int), &nbytes); if(!p) { mesdonnees.data.titre= is + '0'; p= writablefield_get_value(0, oid, KWRTFLDNOM, mesdonnees.data.nom, sizeof(mesdonnees.data.nom), &nbytes); } if(!p) { mesdonnees.data.nom[nbytes]= '\0'; p= writablefield_get_value(0, oid, KWRTFLDPRE, mesdonnees.data.prenom, sizeof(mesdonnees.data.prenom), &nbytes); } if(!p) { mesdonnees.data.prenom[nbytes]= '\0'; mesdonnees.key= currkey; if(!p) gdbm_store(mdbf, mkey, mval); } ERROR_CHECK(p) } ... static int ok_event(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle) { bgig_store(woid); if(state == NEW) new_tkey(currkey); state= OLD; refresh(); return 1; }