#pragma implementation #include #include "dialog.h" #include "modregister.h" #include "misc.h" #include #include #include /* #Specification: virtual registry / introduction The registry system provides a inexpensive mean for various modules to publish "variables". Those variables are readable and writable from other modules. The variables correspond to fields in various dialogs. Planned uses for this module: To be able to dump the entire system configuration to one file for reference purposes. To provide the functionality needed for an SQL interface to linuxconf. To allow upper-level variables to control the values of multiple lower-level variables across multiple modules. (Ie. select "dial-up-connection" and have sendmail, DNS, resolv.conf, etc, changed to behave properly for a non-direct connection. To allow command-line variable setting of all the values which could be set through dialogs. */ # PUBLIC MASTER_REGISTRY::MASTER_REGISTRY() { current_module = -1; session_id = -1; lastfunc = NULL; lastrecord = NULL; neverdelete(); } PUBLIC MASTER_REGISTRY::~MASTER_REGISTRY() { } PUBLIC int MASTER_REGISTRY::add(REGISTER_VARIABLES_OBJ *obj) { ARRAY::add(obj); return 1; } PUBLIC REGISTER_VARIABLES_OBJ *MASTER_REGISTRY::getitem (int no) const { return (REGISTER_VARIABLES_OBJ*)ARRAY::getitem(no); } /* Get the value of a variable. Return NULL if not found. This is the function used by clients. */ PUBLIC const char *MASTER_REGISTRY::get( const char* _module, const char* _key) // Single word, or word.record { const char *ret=NULL; for (int i =0; i < getnb(); i++){ REGISTER_VARIABLES_OBJ *obj = getitem(i); const char *tmp=obj->get_module_id(); if (tmp != NULL && strcmp(tmp, _module)==0){ // fprintf (stderr,"Module lookup %s found\n",_module); ret = obj->get(_key); break; } } return ret; } /* Get the value of a module.variable variable. This is probably the function used by most clients. */ PUBLIC const char *MASTER_REGISTRY::get (const char *_key) { // First, split the _key in a module id and variable name const char *ret = NULL; char tmodule[strlen(_key)+1]; strcpy (tmodule,_key); char *tkey=strchr(tmodule,'.'); if (tkey != NULL){ *tkey++ = '\0'; ret=get(tmodule, tkey); } return ret; } class REGISTRY_LIST: public ARRAY_OBJ{ public: const char *module; const char *variable; void (*exec_list)(SSTRINGS &tb); REGISTRY_LIST ( const char *_module, const char *_variable, void (*_exec_list)(SSTRINGS &tb)) { module = _module; variable = _variable; exec_list = _exec_list; } }; class REGISTRY_LISTS: public ARRAY{ public: REGISTRY_LIST *getitem(int no) const { return (REGISTRY_LIST *)ARRAY::getitem(no); } }; static REGISTRY_LISTS lists; /* Get the values of a list variable. This is a function used by clients. Return the number of item found, or -1 if the variable does not exist. */ PUBLIC int MASTER_REGISTRY::getlist( const char* _module, const char* _key, SSTRINGS &tb) { int ret = -1; int n = lists.getnb(); for (int i=0; imodule,_module)==0 && strcmp(l->variable,_key)==0){ l->exec_list (tb); ret = tb.getnb(); break; } } return ret; } /* Get the value of a module.variable list variable. This is probably the function used by most clients. Return the number of item found, or -1 if the variable does not exist. */ PUBLIC int MASTER_REGISTRY::getlist (const char *_key, SSTRINGS &tb) { // First, split the _key in a module id and variable name int ret = -1; char tmodule[strlen(_key)+1]; strcpy (tmodule,_key); char *tkey=strchr(tmodule,'.'); if (tkey != NULL){ *tkey++ = '\0'; ret=getlist(tmodule, tkey,tb); } return ret; } int MASTER_REGISTRY::lookup_index(const char* _module, const char* _key) { int ret = -1; for (int i =0; i < getnb(); i++){ REGISTER_VARIABLES_OBJ *obj = getitem(i); const char *tmp=obj->get_module_id(); if (tmp != NULL && strcmp(tmp, _module)==0){ ret = obj->lookup_var_index(_key); break; } } return ret; } int MASTER_REGISTRY::lookup_index(const char *_varname) { char tmodule[strlen(_varname)+1]; strcpy (tmodule,_varname); char *tkey=strchr(tmodule,'.'); if (tkey != NULL){ *tkey++ = '\0'; return lookup_index(tmodule, tkey); } return -1; } PRIVATE void MASTER_REGISTRY::flushrecord() { if (lastfunc != NULL){ // fprintf (stderr,"flushrecord :%s:\n",lastrecord); DIALOG_MODE curmode = dialog_setmode (DIALOG_SET); lastfunc (lastrecord,true); dialog_setmode(curmode); lastfunc = NULL; free (lastrecord); lastrecord = NULL; } } PRIVATE int MASTER_REGISTRY::parse ( const char *_key, SSTRING &module, SSTRING &var, SSTRING &subvar, REGISTER_VARIABLES_OBJ *&vars) { int ret = -1; vars = NULL; char tmodule[strlen(_key)+1]; strcpy (tmodule,_key); char *tkey=strchr(tmodule,'.'); if (tkey != NULL){ *tkey++ = '\0'; module.setfrom (tmodule); int i=lookup_module(tmodule); if (i >= 0){ vars = getitem(i); char *rkey = strchr(tkey,'.'); if (rkey != NULL){ *rkey++ = '\0'; } subvar.setfrom (rkey); var.setfrom (tkey); ret = 0; } } return ret; } /* Set the value of a registry variable. Return -1 if the variable does not exist. */ PUBLIC int MASTER_REGISTRY::set( const char *_key, // module.variable or module.variable.record const char *_value) { int ret = -1; SSTRING module,var,subvar; REGISTER_VARIABLES_OBJ *vars; if (parse (_key,module,var,subvar,vars) != -1){ if (subvar.is_filled()){ if (lastrecord != NULL && subvar.cmp(lastrecord)!=0){ // Ok, we are dealing with a new record // We flush the previous fields registered so far flushrecord(); } FUNC_RECORD func = vars->set (var.get(),subvar.get(),_value); if (func != NULL){ if (func != lastfunc){ flushrecord(); } lastfunc = func; if (lastrecord == NULL){ lastrecord = strdup (subvar.get()); } ret = 0; } }else{ flushrecord(); ret = vars->set(var.get(),_value); } } return ret; } PUBLIC int MASTER_REGISTRY::set( const char *_key, // module.variable or module.variable.record const SSTRING &_value) { return set (_key,_value.get()); } PUBLIC int MASTER_REGISTRY::set( const char *_key, // module.variable or module.variable.record int val) { char tmp[30]; sprintf (tmp,"%d",val); return set (_key,tmp); } int MASTER_REGISTRY::lookup_module_from_prompt(const char *_prompt) { // go through all the modules looking for prompts that match for (int i =0; i < nb; i++){ const char *tmp= getitem(i)->lookup_from_prompt(_prompt,NULL); if (tmp != NULL) return i; } return -1; } PUBLIC int MASTER_REGISTRY::lookup_module(const char *_id) { for (int i =0; i < nb; i++){ if (strcmp(getitem(i)->get_module_id(),_id)==0){ return i; } } return -1; } const char *MASTER_REGISTRY::lookup_from_prompt( const char *_prompt, const char *_dialog_id) { // go through all the modules looking for prompts that match for (int i =0; i < nb; i++){ const char *tmp= getitem(i)->lookup_from_prompt(_prompt,_dialog_id); if (tmp != NULL) return tmp; } return NULL; } PUBLIC int MASTER_REGISTRY::retrieve(FIELD *field, const char *dialog_id) { //Get the prompt const char *tregkey = field->return_prompt(); const char *tregval = lookup_from_prompt(tregkey,dialog_id); if (tregval == NULL){ tregval = lookup_from_prompt(field->get_registry_key(),dialog_id); } // fprintf (stderr,"retrieve :%s: :%s:\n",tregkey,tregval); if (tregval != NULL){ field->set_registry_value(tregval); return 1; } return 0; } const char *MASTER_REGISTRY::retrieve_next() { if (current_module >= nb) return NULL; if (current_module == -1){ return retrieve_first(); } const char *tmp = NULL; while (current_module < nb && ((tmp = getitem(current_module)->retrieve_next()) == NULL)) { current_module++; if (current_module < nb){ tmp = getitem(current_module)->retrieve_first(); if (tmp != NULL) return tmp; } } return tmp; } const char *MASTER_REGISTRY::retrieve_value() { if (current_module >= nb || current_module <0) return NULL; return getitem(current_module)->retrieve_value(); } const char *MASTER_REGISTRY::retrieve_first() { const char *ret = NULL; current_module = 0; while ((current_module < nb) && (ret = getitem(current_module)->retrieve_first()) == NULL){ current_module++; } return ret; } int MASTER_REGISTRY::reregister_field(FIELD *field) { static int last = -1; int flag = 0; if (last != -1 && last < getnb()){ // Try the last module we successfully registered a field in. // This optimizes the registration process when you register // more than one field at a time (which is what happens when // you create a dialog) flag = getitem(last)->reregister_field(field); if (flag) return flag; } for (int i=0; i < nb; i++){ if (i != last) flag = getitem(i)->reregister_field(field); if (flag){ //optimize for multiple insertions in one module last = i; return flag; } } return 0; } PUBLIC int MASTER_REGISTRY::register_field( FIELD *field, const char *dialog_id) { static int last = -1; int flag = 0; if (last != -1 && last < getnb()){ // Try the last module we successfully registered a field in. // This optimizes the registration process when you register // more than one field at a time (which is what happens when // you create a dialog) REGISTER_VARIABLES_OBJ* obj = getitem(last); flag = obj->register_field(field,dialog_id); if (flag) return flag; } for (int i=0; i < nb; i++){ REGISTER_VARIABLES_OBJ* obj = getitem(i); if (i != last) flag = obj->register_field(field,dialog_id); if (flag){ //optimize for multiple insertions in one module last = i; return flag; } } return 0; } PRIVATE void MASTER_REGISTRY::check_newmod() { static int nbmsgdone = 0; // Check if new modules were added lately for (; nbmsgdone < getnb(); nbmsgdone++){ getitem(nbmsgdone)->loadmsg(); } } PUBLIC int MASTER_REGISTRY::start_session() { check_newmod(); //There are two issues with the registeries that need //to be dealt with by the session management. // //First, whenever variables are re-read, the original //string is freed and reallocated. This means that any //dialogs with pointers to that string are suddenly //pointing to random locations in memory. // //Second, sessions can be started in dialogs which can //in turn reference other dialogs with sessions. We //have to keep a count of open sessions and only flush //or mark the buffers for re-read once all sessions //are closed. if (session_id == -1){ session_id=0; //Mark variables as "needing to be re-read" for (int i=0; i< nb; i++){ getitem(i)->start_session(); } } session_id++; return 1; } /* Return true if we have one session opened */ PUBLIC bool MASTER_REGISTRY::in_session() { return session_id != -1; } PUBLIC int MASTER_REGISTRY::end_session() { flushrecord(); session_id--; if (session_id == 0){ // Flush all the buffers writing all dirty-data for (int i=0; i< nb; i++){ getitem(i)->end_session(); } session_id = -1; }else if (session_id < -1){ // This means there is an error in programming // Someone has too many end_session() calls session_id=-1; // Right now, just ignore it } return 1; } /* Trigger the dialog (interactivly) associated to a variable. Return -1 if the dialog was not found. */ PUBLIC int MASTER_REGISTRY::rundialog (const char *_key) { check_newmod(); int ret = -1; SSTRING module,var,subvar; REGISTER_VARIABLES_OBJ *vars; if (parse (_key,module,var,subvar,vars) != -1){ ret = vars->rundialog(var.get(),subvar.get()); } return ret; } /* Notice which dialog is currently under edition and inform other modules about it. Return -1 if we can't find any dialog. */ PUBLIC int MASTER_REGISTRY::notice ( FIELD *field, const char *_dialog_id) { int ret = -1; check_newmod(); for (int i=0; i < nb; i++){ REGISTER_VARIABLES_OBJ* obj = getitem(i); if (obj->notice (field,_dialog_id) != -1){ ret = 0; break; } } return ret; } PUBLIC REGISTER_VARIABLES_OBJ::REGISTER_VARIABLES_OBJ ( const char *_module_id) { next = -1; module_id = NULL; if (_module_id != NULL) module_id = strdup(_module_id); } PUBLIC REGISTER_VARIABLES_OBJ::~REGISTER_VARIABLES_OBJ() { free (module_id); } PROTECTED VIRTUAL REGISTER_VARIABLE *REGISTER_VARIABLES_OBJ::create_registry( const char *_varname, const char *_dialog_id, const char *_prompt, void (*_exec_dialog)(), void (*_exec_dialog_record)(const char *record, bool setting)) { REGISTER_VARIABLE *a = new REGISTER_VARIABLE( _varname ,_dialog_id, _prompt , _exec_dialog, _exec_dialog_record); add(a); return a; } PUBLIC REGISTER_VARIABLE *REGISTER_VARIABLES_OBJ::getitem(int no) const { return (REGISTER_VARIABLE*)ARRAY::getitem(no); } PUBLIC const char *REGISTER_VARIABLES_OBJ::get_module_id() { return module_id; } PUBLIC VIRTUAL int REGISTER_VARIABLES_OBJ::lookup_index(const char *_prompt) { return -1; } PUBLIC VIRTUAL const char *REGISTER_VARIABLES_OBJ::get(const char *_key) { return NULL; } PUBLIC VIRTUAL int REGISTER_VARIABLES_OBJ::set( const char *_key, const char *_value) { return -1; } PUBLIC VIRTUAL int REGISTER_VARIABLES_OBJ::rundialog( const char *_key, const char *_record) { return -1; } PUBLIC VIRTUAL int REGISTER_VARIABLES_OBJ::notice( FIELD *, const char *) { return -1; } PUBLIC VIRTUAL FUNC_RECORD REGISTER_VARIABLES_OBJ::set( const char *_key, const char *_record, const char *_value) { return NULL; } PUBLIC VIRTUAL int REGISTER_VARIABLES_OBJ::lookup_var_index(const char *_key) { return -1; } PUBLIC VIRTUAL const char *REGISTER_VARIABLES_OBJ::lookup_from_prompt( const char *, // prompt const char *) // dialog_id { return NULL; } PUBLIC VIRTUAL int REGISTER_VARIABLES_OBJ::retrieve(FIELD *field) { return 0; } PUBLIC VIRTUAL const char *REGISTER_VARIABLES_OBJ::retrieve_next() { return NULL; } PUBLIC VIRTUAL const char *REGISTER_VARIABLES_OBJ::retrieve_value() { return NULL; } PUBLIC VIRTUAL const char *REGISTER_VARIABLES_OBJ::retrieve_first() { return NULL; } PUBLIC VIRTUAL int REGISTER_VARIABLES_OBJ::delete_varname(const char *varname) { return 0; } PUBLIC VIRTUAL int REGISTER_VARIABLES_OBJ::reregister_field( FIELD *) { return 0; } PUBLIC VIRTUAL int REGISTER_VARIABLES_OBJ::register_field( FIELD *, const char *) // dialog_id { return 0; } PUBLIC VIRTUAL int REGISTER_VARIABLES_OBJ::start_session() { return 0; } PUBLIC VIRTUAL int REGISTER_VARIABLES_OBJ::end_session() { return 0; } class REGISTER_VARIABLES_PRIVATE{ public: REGISTER_VARIABLE_LOOKUP_MSG *tb_notloaded; PUBLISH_VARIABLES_MSG *tbpub; PUBLISH_VARIABLES_STR *tbstr; const char *listname; const char *dialog_id; void (*exec_dialog)(); void (*exec_dialog_record)(const char *, bool); void (*exec_list)(SSTRINGS &); REGISTER_VARIABLES_PRIVATE(); REGISTRY_LIST *listvar; }; REGISTER_VARIABLES_PRIVATE::REGISTER_VARIABLES_PRIVATE() { tb_notloaded = NULL; tbpub = NULL; tbstr = NULL; listname = NULL; exec_dialog = NULL; exec_dialog_record = NULL; exec_list = NULL; dialog_id = NULL; } PUBLIC REGISTER_VARIABLES::REGISTER_VARIABLES ( const char *_module_id, REGISTER_VARIABLE_LOOKUP _tb[]) : REGISTER_VARIABLES_OBJ (_module_id) { priv = new REGISTER_VARIABLES_PRIVATE; REGISTER_VARIABLES_OBJ *vars = this; int lk = master_registry.lookup_module(get_module_id()); if (lk != -1) vars = master_registry.getitem(lk); for (int loop = 0; _tb[loop].varname != NULL; loop++){ REGISTER_VARIABLE *a = new REGISTER_VARIABLE( _tb[loop].varname, _tb[loop].dialog_id, _tb[loop].prompt, _tb[loop].exec_dialog, _tb[loop].exec_dialog_record); vars->add(a); } master_registry.add(this); } PUBLIC REGISTER_VARIABLES::REGISTER_VARIABLES ( const char *_module_id, REGISTER_VARIABLE_LOOKUP_MSG _tb[]) : REGISTER_VARIABLES_OBJ (_module_id) { priv = new REGISTER_VARIABLES_PRIVATE; priv->tb_notloaded = _tb; master_registry.add(this); } PUBLIC REGISTER_VARIABLES::REGISTER_VARIABLES ( const char *_module_id, PUBLISH_VARIABLES_MSG _tb[], const char *_dialog_id, void (*exec_dialog)()) : REGISTER_VARIABLES_OBJ (_module_id) { priv = new REGISTER_VARIABLES_PRIVATE; priv->tbpub = _tb; priv->dialog_id = _dialog_id; priv->exec_dialog = exec_dialog; master_registry.add(this); } PUBLIC REGISTER_VARIABLES::REGISTER_VARIABLES ( const char *_module_id, PUBLISH_VARIABLES_STR _tb[], const char *_dialog_id, void (*exec_dialog)()) : REGISTER_VARIABLES_OBJ (_module_id) { priv = new REGISTER_VARIABLES_PRIVATE; priv->tbstr = _tb; priv->dialog_id = _dialog_id; priv->exec_dialog = exec_dialog; master_registry.add(this); } PUBLIC REGISTER_VARIABLES::REGISTER_VARIABLES ( const char *_module_id, const char *_listname, PUBLISH_VARIABLES_MSG _tb[], const char *_dialog_id, void (*exec_dialog_record)(const char *, bool), void (*exec_list)(SSTRINGS &)) : REGISTER_VARIABLES_OBJ (_module_id) { priv = new REGISTER_VARIABLES_PRIVATE; priv->tbpub = _tb; priv->listname = _listname; priv->dialog_id = _dialog_id; priv->exec_dialog_record = exec_dialog_record; priv->exec_list = exec_list; priv->listvar = new REGISTRY_LIST(_module_id,_listname,exec_list); lists.add (priv->listvar); master_registry.add(this); } PUBLIC REGISTER_VARIABLES::REGISTER_VARIABLES ( const char *_module_id, const char *_listname, PUBLISH_VARIABLES_STR _tb[], const char *_dialog_id, void (*exec_dialog_record)(const char *, bool), void (*exec_list)(SSTRINGS &)) : REGISTER_VARIABLES_OBJ (_module_id) { priv = new REGISTER_VARIABLES_PRIVATE; priv->tbstr = _tb; priv->listname = _listname; priv->dialog_id = _dialog_id; priv->exec_dialog_record = exec_dialog_record; priv->exec_list = exec_list; priv->listvar = new REGISTRY_LIST(_module_id,_listname,exec_list); lists.add (priv->listvar); master_registry.add(this); } PRIVATE VIRTUAL void REGISTER_VARIABLES_OBJ::loadmsg() { } /* Map the P_MSG_U() macros to real message strings */ PRIVATE void REGISTER_VARIABLES::loadmsg() { REGISTER_VARIABLES_OBJ *vars = this; int lk = master_registry.lookup_module(get_module_id()); if (lk != -1) vars = master_registry.getitem(lk); if (priv->tb_notloaded != NULL){ REGISTER_VARIABLE_LOOKUP_MSG *tb_notloaded = priv->tb_notloaded; for (int loop = 0; tb_notloaded[loop].varname != NULL; loop++){ REGISTER_VARIABLE *a = new REGISTER_VARIABLE( tb_notloaded[loop].varname, tb_notloaded[loop].dialog_id, tb_notloaded[loop].notloaded->get(), tb_notloaded[loop].exec_dialog, tb_notloaded[loop].exec_dialog_record); vars->add(a); } }else if (priv->tbpub != NULL){ PUBLISH_VARIABLES_MSG *tb = priv->tbpub; for (int loop = 0; tb[loop].varname != NULL; loop++){ REGISTER_VARIABLE *a = new REGISTER_VARIABLE( tb[loop].varname, priv->dialog_id, tb[loop].notloaded->get(), priv->exec_dialog, priv->exec_dialog_record); a->listvar = priv->listvar; vars->add(a); } }else if (priv->tbstr != NULL){ PUBLISH_VARIABLES_STR *tb = priv->tbstr; for (int loop = 0; tb[loop].varname != NULL; loop++){ REGISTER_VARIABLE *a = new REGISTER_VARIABLE( tb[loop].varname, priv->dialog_id, tb[loop].prompt, priv->exec_dialog, priv->exec_dialog_record); a->listvar = priv->listvar; vars->add(a); } } } PUBLIC REGISTER_VARIABLE *REGISTER_VARIABLES::getitem (int no) const { return (REGISTER_VARIABLE*)ARRAY::getitem (no); } PUBLIC REGISTER_VARIABLES::~REGISTER_VARIABLES() { delete priv; } int REGISTER_VARIABLES::lookup_index(const char *_prompt) { for (int i=0; i < nb; i++){ REGISTER_VARIABLE *var = getitem(i); if (var->is_system()){ if (var->prompt == _prompt) return i; }else{ //In case variable is added later, prompt pointer invalid //depend on string comparison if (strcmp(var->prompt, _prompt)==0){ return i; } } } return -1; } int REGISTER_VARIABLES::lookup_var_index(const char *_varname) { for (int i=0; i < nb; i++){ if (!strcmp(getitem(i)->varname, _varname)){ return i; } } return -1; } const char *REGISTER_VARIABLES::get(const char *_varname) { for (int i=0; i < nb; i++){ REGISTER_VARIABLE *var = getitem(i); // fprintf (stderr,"Compare :%s: :%s:\n",var->varname,_varname); if (strcmp(var->varname, _varname)==0){ return var->get(); } } //If not found regularly, try to see if it is has a record { char tmp[strlen(_varname)+1]; strcpy (tmp,_varname); char *t2 = strchr(tmp, '.'); //does this have a "record" on it? if (t2 != NULL){ //this has a record. //break where the period is *t2 = '\0'; t2++; int x=lookup_var_index(tmp); // fprintf (stderr,"get record :%s: :%s: %d\n",tmp,t2,x); if (x == -1){ // could not find it return NULL; } return getitem(x)->get(t2); } } return NULL; } /* Retrieve the value associated (stored) in a variable from the DIALOG field prompt */ const char *REGISTER_VARIABLES::lookup_from_prompt( const char *_prompt, const char *_dialog_id) { const char *ret = NULL; for (int i=0; i < nb; i++){ REGISTER_VARIABLE *var = getitem(i); if (var->is_dirty()){ if (var->is_system()){ // fprintf (stderr,"lookup_from_prompt %p %p :%s:\n",var->prompt,_prompt,_prompt); if (var->prompt == _prompt && var->dialog_id == _dialog_id){ ret = var->getvalue(); var->mark_written(); break; } }else{ //In case variable is added later, prompt pointer invalid //depend on string comparison if (strcmp(var->prompt, _prompt)==0 && var->dialog_id == _dialog_id){ ret = var->getvalue(); var->mark_written(); break; } } } } return ret; } int REGISTER_VARIABLES::retrieve(FIELD *field) { // Change field value to new registry value // if the registry value does not exist, do not change field int pos = lookup_index(field->return_prompt()); //Do not use "get" here or we might end up in a loop. char *tregval = getitem(pos)->value; if (tregval != NULL){ field->set_registry_value(tregval); REGISTER_VARIABLE *var = getitem(pos); field->set_registry_key(var->varname); var->mark_written(); return 1; } return 0; } const char *REGISTER_VARIABLES::retrieve_next() { next++; if (next >= nb){ next = -1; return NULL; } return getitem(next)->varname; } const char *REGISTER_VARIABLES::retrieve_value() { if (next == -1 || next >= nb) return NULL; return getitem(next)->value; } const char *REGISTER_VARIABLES::retrieve_first() { next = -1; return retrieve_next(); } int REGISTER_VARIABLES::delete_varname(const char *varname) { for (int i = 0; i < nb; i++){ if (!strcmp(getitem(i)->varname, varname)){ return remove_del(i); } } return 0; } int REGISTER_VARIABLES::reregister_field(FIELD *field) { const char *tprompt = field->return_prompt(); for (int i=0; i < nb; i++){ REGISTER_VARIABLE *var = getitem(i); if (var->prompt == tprompt){ // This is the registry entry we want // Set the value, regardless if has alerady been set var->set(field->get_registry_value()); return 1; } } // If it gets here, the field was not in the REGISTER_VARIABLE_LOOKUP return 0; } int REGISTER_VARIABLES::register_field(FIELD *field, const char *dialog_id) { const char *tprompt = field->return_prompt(); const char *regkey = field->get_registry_key(); for (int i=0; i < nb; i++){ REGISTER_VARIABLE *var = getitem(i); // fprintf (stderr,"register_field :%s: %p %p\n",var->varname,var->dialog_id,dialog_id); if ((var->prompt==tprompt || var->prompt == regkey) && var->dialog_id == dialog_id){ // This is the registry entry we want // only set it if it has not already been set once if (! var->has_been_set()){ var->setvalue(field->get_registry_value()); } return 1; } } #if 0 // If it gets here, the field was not in the REGISTER_VARIABLE_LOOKUP if (regkey != NULL){ //if the registry_key is not null then someone went through //the trouble of doing a field->set_registry_key(); //We will register this for them then. REGISTER_VARIABLE *a; a=create_registry(regkey,dialog_id,field->return_prompt(), NULL, NULL); if (a != NULL) a->setvalue(field->get_registry_value()); } #endif return 0; } PUBLIC int REGISTER_VARIABLES::start_session() { // only mark as not set (so is re-read) when session_id =0 if (master_registry.session_id == 0){ for (int i=0; imark_unset(); } } return 1; } PUBLIC int REGISTER_VARIABLES::end_session() { if (master_registry.session_id == 0){ for (int i=0; iis_dirty()){ //Tell the dialog to write the variables var->flush(); } } } return 1; } int REGISTER_VARIABLES::set(const char *_key, const char *_value) { int ret = -1; for (int i=0; i < nb; i++){ REGISTER_VARIABLE *var = getitem(i); if (strcmp(var->varname, _key)==0){ ret = var->set (_value); break; } } return ret; #if 0 int x=-1; for (int i=0; i < nb; i++){ if (strcmp(getitem(i)->varname, _key)==0){ x=i; break; } } if (x == -1){ char tmp[strlen(_key)+1]; strcpy (tmp,_key); char *t2 = strchr(tmp, '.'); //does this have a "record" on it? if (t2 != NULL){ *t2 = '\0'; t2++; x=lookup_var_index(tmp); if (x == -1){ return -1; } return getitem(x)->set(t2,_value); } }else{ return getitem(x)->set(_value); } return -1; #endif } /* Set a value for one record */ FUNC_RECORD REGISTER_VARIABLES::set( const char *_key, const char *record, const char *_value) { FUNC_RECORD ret = NULL; for (int i=0; i < nb; i++){ REGISTER_VARIABLE *var = getitem(i); if (strcmp(var->varname, _key)==0){ ret = var->set (record,_value); break; } } return ret; } int REGISTER_VARIABLES::rundialog(const char *_key, const char *_record) { int ret = -1; for (int i=0; i < nb; i++){ REGISTER_VARIABLE *var = getitem(i); if (strcmp(var->varname, _key)==0){ ret = var->rundialog (_record); break; } } return ret; } PUBLIC VIRTUAL int REGISTER_VARIABLES::notice( FIELD *field, const char *_dialog_id) { int ret = -1; const char *tprompt = field->return_prompt(); const char *regkey = field->get_registry_key(); for (int i=0; i < nb; i++){ REGISTER_VARIABLE *var = getitem(i); if (var->dialog_id == _dialog_id){ if (var->prompt==tprompt || var->prompt == regkey){ SSTRING tmp; const char *tb[] = {tmp.get(),NULL}; tmp.setfromf ("%s.%s",module_id,var->varname); module_sendmessage ("editdialog",1,tb); ret = 0; break; } } } return ret; } int REGISTER_VARIABLE::rundialog(const char *_record) { int ret = -1; if (_record == NULL || _record[0] == '\0'){ if (exec_dialog != NULL){ exec_dialog (); ret = 0; } }else if (exec_dialog_record != NULL){ exec_dialog_record (_record,false); ret = 0; } return ret; } PUBLIC REGISTER_VARIABLE::REGISTER_VARIABLE ( const char *_varname, const char *_dialog_id, const char *_prompt, void (*_exec_dialog)(), void (*_exec_dialog_record)(const char *record, bool setting)) { varname = _varname; dialog_id = _dialog_id; prompt = _prompt; value = NULL; exec_dialog = _exec_dialog; exec_dialog_record = _exec_dialog_record; system_registry=true; value_has_been_set=false; dirty=false; listvar = NULL; } PUBLIC int REGISTER_VARIABLE::getlistvar (SSTRING &var) { int ret = -1; if (listvar != NULL){ ret = 0; var.setfromf ("%s.%s",listvar->module,listvar->variable); } return ret; } PUBLIC const char *REGISTER_VARIABLE::get_varname() const { return varname; } PUBLIC const char *REGISTER_VARIABLE::get_prompt() const { return prompt; } /* Retrieve the value of a variable. This trigger a dialog and the field value is grabbed. This function is used to access a dialog out of a record list. The record variable may represent anything known to the exec_dialog_record function. For example, it could be a user id. */ const char *REGISTER_VARIABLE::get(const char *record) { //Only return values if a session has started. if (master_registry.session_id >= 0 && exec_dialog_record != NULL){ // always call the function DIALOG_MODE curmode = dialog_setmode (DIALOG_GET); mark_unset(); exec_dialog_record(record,false); dialog_setmode(curmode); //We just read the value afresh. It has not changed. dirty=false; if (value_has_been_set) return value; } return NULL; } PUBLIC const char *REGISTER_VARIABLE::getvalue() { return value_has_been_set ? value : NULL; } /* Retrieve the value of a variable. This trigger a dialog and the field value is grabbed. */ const char *REGISTER_VARIABLE::get() { //Only return values if a session has started. if (master_registry.session_id >= 0 && exec_dialog != NULL){ if (value_has_been_set) return value; DIALOG_MODE curmode = dialog_setmode (DIALOG_GET); exec_dialog(); dialog_setmode(curmode); //We just read the value afresh. It has not changed. dirty=false; if (value_has_been_set) return value; } return NULL; } /* Move the data recorded with REGISTER_VARIABLE::set() to the corresponding dialogs. */ int REGISTER_VARIABLE::flush() { //Only flush if all sessions have stopped if (master_registry.session_id == 0){ if (exec_dialog == NULL){ fprintf (stderr,"No exec_dialog for virtual registry variable %s\n" ,varname); }else{ // Only write if we need to if (!dirty) return 1; DIALOG_MODE curmode = dialog_setmode (DIALOG_SET); exec_dialog(); dialog_setmode(curmode); dirty=false; return 1; } } return 0; } FUNC_RECORD REGISTER_VARIABLE::set(const char *record, const char *_value) { FUNC_RECORD ret = NULL; //Only set values if we are within a session if (master_registry.session_id > 0 && exec_dialog_record != NULL){ setvalue (_value); if (_value != NULL && value == NULL){ value_has_been_set = false; }else{ dirty = true; ret = exec_dialog_record; } } return ret; } /* Does this registry variable control operate on records */ PUBLIC bool REGISTER_VARIABLE::is_record() const { return exec_dialog_record != NULL; } PRIVATE void REGISTER_VARIABLE::setvalue(const char *_value) { free (value); value = NULL; if (_value != NULL) value = strdup(_value); value_has_been_set = true; } int REGISTER_VARIABLE::set(const char *_value) { //Only set values if we are within a session if (master_registry.session_id > 0){ setvalue (_value); dirty=true; //mark as dirty-data return 1; } return 0; } bool REGISTER_VARIABLE::has_been_set() { return value_has_been_set; } void REGISTER_VARIABLE::mark_unset() { value_has_been_set = false; } bool REGISTER_VARIABLE::is_dirty() { return dirty; } void REGISTER_VARIABLE::mark_written() { dirty=false; } bool REGISTER_VARIABLE::is_system() { return system_registry; } void REGISTER_VARIABLE::set_not_system() { system_registry=false; } PUBLIC REGISTER_VARIABLE::~REGISTER_VARIABLE() { free (value); } /*******************************************/ MASTER_REGISTRY master_registry; /* Return true if we are operating a dialog in registry mode */ EXPORT bool dialog_registrymode() { return dialog_mode == DIALOG_GET || dialog_mode == DIALOG_SET; }