44 bool is_prefined(
const string& cfgname) {
return cfgname[0] ==
'*'; }
54 : default_file(default_file_),
68 const char *
get_id()
const {
return id.c_str(); }
71 return string(
"tmp/general_configs/"+(temp ? 0 : 4))+
id+
'/'+subname;
88 StoreConfigCallback store;
89 RestoreConfigCallback load_or_reset;
102 load_or_reset(load_or_reset_),
105 field_selection(
NULp)
112 return predef ? predef->
config :
"";
123 error =
"cannot modify predefined config";
139 char *
Store()
const {
return store(); }
143 if (s.empty()) error =
"empty/nonexistant config";
144 else load_or_reset(s.c_str());
152 GB_ERROR Save(
const char* filename,
const string& cfg_name,
const string& comment);
153 GB_ERROR Load(
const char* filename,
const string& cfg_name,
string& found_comment);
158 string wanted = S+ lookFor +S;
160 return existing.find(wanted) != string::npos;
163 void erase_deleted_configs();
167 for (
int i = 0; predefined[i].
name; ++i) {
169 cfgs.
put(predefined[i].name);
175 for (
int i = 0; predefined[i].
name; ++i) {
176 if (cfgname == predefined[i].name) {
177 return &predefined[i];
183 void popup_edit_window(
AW_window *aw_config);
184 void update_field_selection_list();
185 void update_field_content();
186 void store_changed_field_content();
187 void delete_selected_field();
188 void keep_changed_fields();
191 #define HEADER "ARB_CONFIGURATION"
197 printf(
"Saving config to '%s'..\n", filename);
199 FILE *out = fopen(filename,
"wt");
205 if (comment.empty()) {
206 fprintf(out,
HEADER ":%s\n", get_id());
209 string encoded_comment(comment);
211 fprintf(out,
HEADER ":%s;%s\n", get_id(), encoded_comment.c_str());
214 string content = get_config(cfg_name);
215 fputs(content.c_str(), out);
225 printf(
"Loading config from '%s'..\n", filename);
233 error =
"Unexpected content (" HEADER " missing)";
237 char *
nl = strchr(id_pos,
'\n');
240 error =
"Unexpected content (no ID)";
245 char *comment = strchr(id_pos,
';');
246 if (comment) *comment++ = 0;
248 if (strcmp(id_pos, get_id()) != 0) {
249 error =
GBS_global_string(
"Wrong config type (expected=%s, found=%s)", get_id(), id_pos);
252 error = set_config(cfg_name, nl);
253 if (comment && !error) {
254 found_comment = comment;
282 const char *name = key+4;
283 if (!has_existing(name)) {
299 for (
int i = 0; cfgs[i]; ++i) {
300 if (strcmp(cfgs[i], config.c_str()) != 0) {
301 remaining.
put(cfgs[i]);
306 existing_configs = rest;
310 #define NO_CONFIG_SELECTED "<no config selected>"
320 if (entered_name[0]) {
323 name = isPredefined ?
string(1,
'*')+asKey : asKey;
340 if (comments.parseError()) {
341 display =
GBS_global_string(
"Error reading config comments:\n%s", comments.parseError());
344 const char *saved_comment = comments.get_entry(name.c_str());
345 display = null2empty(saved_comment);
372 free(comments_string);
377 if (!curr_cfg.empty()) {
381 if (found && changed_comment != found->
description) {
382 aw_message(
"The description of predefined configs is immutable");
388 if (comments.parseError()) {
392 if (changed_comment.empty()) {
393 comments.delete_entry(curr_cfg.c_str());
396 comments.set_entry(curr_cfg.c_str(), changed_comment.c_str());
410 if (cfgName.empty()) {
411 error =
"Please select config to restore";
420 if (cfgName.empty())
aw_message(
"Please select or enter name of config to store");
430 existing = existing.empty() ? cfgName : (
string(cfgName)+
';'+existing);
432 char *cfgStr = config->
Store();
446 aw_message(
"You may not delete predefined configs");
466 if (cfgName.empty()) error =
"Please enter or select target config";
467 else if (
is_prefined(cfgName)) error =
"You may not load over a predefined config";
474 error = config->
Load(filename, cfgName, comment);
491 if (cfgName.empty()) error =
"Please select config to save";
495 cfgName.c_str() + (cfgName[0] ==
'*'));
498 if (filename && filename[0]) {
501 error = config->
Save(filename, cfgName, comment);
511 static string esc(
const string&
str) {
514 char *escaped =
GBS_string_eval(str.c_str(),
"\\\\=\\\\\\\\:\"=\\\\\":\\n=\\\\n:\\t=\\\\t");
528 if (cfgName.empty()) error =
"Please select config to dump";
531 string confStr = esc(config->
get_config(cfgName));
533 cfgName = esc(cfgName);
534 const char *cfg = cfgName.c_str();
536 fprintf(stderr,
" { \"*%s\", \"%s\", \"%s\" },\n",
537 cfg[0] ==
'*' ? cfg+1 : cfg,
547 if (field_selection) {
550 bool seenSelected =
false;
552 field_selection->clear();
553 if (!cfgName.empty() && has_existing(cfgName)) {
554 string configString = get_config(cfgName);
557 stored.get_entries(entries);
559 StrArray entries_with_content;
561 for (
size_t e = 0; e<entries.size(); ++e) {
562 maxlen =
std::max(maxlen, strlen(entries[e]));
563 if (strcmp(selected, entries[e]) == 0) seenSelected =
true;
565 for (
size_t e = 0; e<entries.size(); ++e) {
567 int(maxlen), entries[e],
568 stored.get_entry(entries[e])),
572 field_selection->insert_default(
"",
"");
573 field_selection->update();
587 string content =
"<select a field below>";
588 if (!cfgName.empty() && has_existing(cfgName)) {
590 if (!selected.empty()) {
591 string configString = get_config(cfgName);
594 if (stored.has_entry(selected.c_str())) {
595 content = stored.
get_entry(selected.c_str());
598 content =
GBS_global_string(
"<field '%s' not stored in config>", selected.c_str());
605 GB_ERROR AWT_configuration::update_config(
const string& cfgname,
const AWT_config& config) {
607 GB_ERROR error = set_config(cfgname, changedConfigString);
608 free(changedConfigString);
614 if (!cfgName.empty() && has_existing(cfgName)) {
616 if (!selected.empty()) {
617 string configString = get_config(cfgName);
619 if (stored.has_entry(selected.c_str())) {
620 string stored_content = stored.
get_entry(selected.c_str());
623 if (stored_content != changed_content) {
624 stored.set_entry(selected.c_str(), changed_content.c_str());
634 if (!cfgName.empty() && has_existing(cfgName)) {
636 if (!selected.empty()) {
637 string configString = get_config(cfgName);
639 if (stored.has_entry(selected.c_str())) {
642 field_selection->move_selection(1);
643 update_field_selection_list();
651 if (!cfgName.empty() && has_existing(cfgName)) {
652 string configString = get_config(cfgName);
655 char *current_state = Store();
659 stored.get_entries(entries);
662 for (
size_t e = 0; e<entries.
size(); ++e) {
663 const char *entry = entries[e];
664 const char *stored_content = stored.get_entry(entry);
667 const char *current_content = current.
get_entry(entry);
668 if (strcmp(stored_content, current_content) == 0) {
669 stored.delete_entry(entry);
680 update_field_selection_list();
683 aw_message(
"All entries differ from current state");
698 AW_window_simple *aws =
new AW_window_simple;
701 aws->init(root, wid,
"Edit configuration entries");
704 aws->load_xfig(
"awt/edit_config.fig");
708 aws->create_button(
"CLOSE",
"CLOSE");
712 aws->create_button(
"HELP",
"HELP");
721 field_selection = aws->create_selection_list(get_awar(
SELECTED_FIELD)->awar_name);
723 aws->auto_space(0, 3);
724 aws->button_length(10);
727 int xpos = aws->get_at_xposition();
728 int ypos = aws->get_at_yposition();
731 aws->create_button(
"DELETE",
"Delete\nselected\nentry",
"D");
734 ypos = aws->get_at_yposition();
739 aws->create_button(
"KEEP_CHANGED",
"Keep only\nentries\ndiffering\nfrom\ncurrent\nstate",
"K");
748 update_field_selection_list();
771 AW_window_simple *aws =
new AW_window_simple;
777 aws->load_xfig(
"awt/manage_config.fig");
781 aws->create_button(
"CLOSE",
"CLOSE");
785 aws->create_button(
"HELP",
"HELP");
793 aws->create_text_field(awar_comment->
awar_name);
797 aws->create_autosize_button(
"erase",
"Erase",
"E");
805 awar_existing->
touch();
806 awar_current->
touch();
808 aws->auto_space(0, 3);
809 aws->button_length(10);
812 int xpos = aws->get_at_xposition();
813 int ypos = aws->get_at_yposition();
822 {
store_cb,
"STORE",
"Store",
"S" },
824 {
load_cb,
"LOAD",
"Load",
"L" },
825 {
save_cb,
"SAVE",
"Save",
"v" },
826 {
reset_cb,
"RESET",
"Factory\ndefaults",
"F" },
827 {
edit_cb,
"EDIT",
"Edit",
"E" },
829 { dump_cb,
"DUMP",
"dump\npredef",
"U" },
833 for (
int b = 0; b<buttons; ++b) {
834 const but& B = butDef[b];
841 aws->callback(makeWindowCallback(B.cb, config));
842 aws->create_button(B.id, B.label, B.mnemonic);
845 ypos = aws->get_at_yposition();
857 const RestoreConfigCallback& load_or_reset_cb,
const char *macro_id,
const AWT_predefined_config *predef)
873 aww->
create_button(macro_id ? macro_id :
"SAVELOAD_CONFIG",
"#conf_save.xpm");
888 if (stored_string) cdef.
write(stored_string);
900 ConfigSetupCallback *
const setup_cb_copy =
new ConfigSetupCallback(setup_cb);
929 parse_error = mapping->
parseFrom(cfgStr);
936 void AWT_config::init_from_awars(
const ConfigMapping& cfgname2awar) {
941 for (config_map::const_iterator c = cfgname2awar.begin(); c != cfgname2awar.end(); ++c) {
942 const string& key(c->first);
943 const string& awar_name(c->second);
948 valuemap[key] = awar_value;
958 awt_assert((valuemap.size()+skipped) == cfgname2awar.size());
966 init_from_awars(cfgname2awar);
986 for (config_map::const_iterator e = mapping->begin(); e != mapping->end(); ++e) {
987 const string& config_name(e->first);
988 const string& value(e->second);
990 config_map::const_iterator found = cfgname2awar.find(config_name);
991 if (found == cfgname2awar.end()) {
996 const string& awar_name(found->second);
1002 if (unmapped && warn) {
1003 int mapped = mapping->size()-unmapped;
1005 "(known/restored: %i, unknown/ignored: %i)\n"
1006 "Note: ok for configs shared between multiple windows",
1029 delete config_mapping;
1033 (*config_mapping)[config_name] = awar_name;
1060 char *old_state =
read();
1063 if (strcmp(old_state, cfgStr) != 0) {
1064 char *new_state =
read();
1065 if (strcmp(new_state, cfgStr) != 0) {
1067 int maxRetries = 10;
1068 while (retry && maxRetries--) {
1069 printf(
"Note: repeating config restore (did not set all awars correct)\n");
1071 char *new_state2 =
read();
1072 if (strcmp(new_state, new_state2) != 0) {
1073 reassign(new_state, new_state2);
1081 error =
"Unable to restore everything (might be caused by outdated, now invalid settings)";
1094 for (config_map::const_iterator e = config_mapping->begin(); e != config_mapping->end(); ++e) {
1095 const string& awar_name(e->second);
1121 for (
size_t c = 0; c<cfgs.
size(); ++c) {
1135 bool update =
false;
1136 for (
size_t e = 0; e<entries.
size(); ++e) {
1137 const char *old_content = cmap.
get_entry(entries[e]);
1138 char *new_content = mod_cb(entries[e], old_content, cl_user);
1144 else if (strcmp(old_content, new_content) != 0) {
1145 cmap.
set_entry(entries[e], new_content);
AW_awar * get_awar(const string &subname, bool temp=false) const
void set_awar_value(ConfigAwar a, const string &new_value) const
AWT_configuration(AW_default default_file_, const char *id_, const StoreConfigCallback &store_, const RestoreConfigCallback &load_or_reset_, const AWT_predefined_config *predef)
GB_ERROR Restore(const string &s) const
void put(const char *elem)
void delete_entry(const char *entry)
static void field_content_changed_cb(AW_root *, AWT_configuration *config)
void button_length(int length)
void add(const char *awar_name, const char *config_name)
bool has_entry(const char *entry) const
static void delete_cb(AW_window *, AWT_configuration *config)
GBDATA * GB_child(GBDATA *father)
return string(buffer, length)
static void erase_comment_cb(AW_window *, AW_awar *awar_comment)
GB_ERROR GB_write_string(GBDATA *gbd, const char *s)
const char * get_window_id() const
GB_ERROR Save(const char *filename, const string &cfg_name, const string &comment)
const char * get_id() const
void store_changed_field_content()
void write_to_awars(const ConfigMapping &cfgname2awar, bool warn) const
AW_default get_db() const
std::map< std::string, std::string > config_map
GB_ERROR GB_IO_error(const char *action, const char *filename)
void AWT_insert_config_manager(AW_window *aww, AW_default default_file_, const char *id, const StoreConfigCallback &store_cb, const RestoreConfigCallback &load_or_reset_cb, const char *macro_id, const AWT_predefined_config *predef)
static char * store_generated_config_cb(const ConfigSetupCallback *setup_cb)
const char * GBS_global_string(const char *templat,...)
char * GBS_string_eval(const char *insource, const char *icommand)
void AW_POPDOWN(AW_window *window)
char * GBS_string_2_key(const char *str)
static void comment_changed_cb(AW_root *, AWT_configuration *config)
char *(* ConfigModifyCallback)(const char *key, const char *value, AW_CL cl_user)
GB_ERROR set_config(const string &cfgname, const string &new_value)
const AWT_predefined_config * find_predefined(const string &cfgname)
string get_awar_name(const string &subname, bool temp=false) const
static void generate_config_from_mapping_cb(AWT_config_definition &cdef, const AWT_config_mapping_def *mapping)
#define ARRAY_ELEMS(array)
string get_config(const string &cfgname)
GB_ERROR parseError() const
static void load_or_reset_generated_config_cb(const char *stored_string, const ConfigSetupCallback *setup_cb)
void add_predefined_to(ConstStrArray &cfgs)
AW_awar * add_callback(const RootCallback &cb)
GB_ERROR GB_delete(GBDATA *&source)
static void selected_field_changed_cb(AW_root *, AWT_configuration *config)
static void refresh_config_sellist_cb(AW_root *, AWT_configuration *config, AW_selection_list *sel)
const char * read_char_pntr() const
void save_comments(const AWT_config &comments, AWT_configuration *config)
GB_ERROR GB_await_error()
static AW_root * SINGLETON
WindowCallback makeHelpCallback(const char *helpfile)
GB_CSTR GB_read_key_pntr(GBDATA *gbd)
void update_field_content()
void get_entries(class ConstStrArray &to_array)
void keep_changed_fields()
static void encode_escapes(std::string &s, const char *to_escape)
const char * get_window_title() const
void popup_edit_window(AW_window *aw_config)
static void error(const char *msg)
void update_field_selection_list()
#define NO_CONFIG_SELECTED
void remove_from_configs(const string &config, string &existing_configs)
static void save_cb(AW_window *, AWT_configuration *config)
static GB_ERROR decode_escapes(std::string &s)
char * read_as_string() const
static void get_existing_configs(ConfigDefinition &configDef, ConstStrArray &cfgs)
GB_ERROR reset_to_default()
void warn_unknown_awar(const string &awar_name)
AWT_config(const char *cfgStr)
static void edit_cb(AW_window *aww, AWT_configuration *config)
AW_awar * awar_no_error(const char *awar)
end timer stuff
AW_awar * awar(const char *awar)
int get_button_length() const
ConfigDefinition(AW_default default_file_, const char *id_)
static void destroy_AWT_configuration(AWT_configuration *c, AW_window *)
static void store_cb(AW_window *, AWT_configuration *config)
AW_selection_list * awt_create_selection_list_with_input_field(AW_window *aww, const char *awar_name, const char *at_box, const char *at_field)
bool is_prefined(const string &cfgname)
GB_ERROR write_as_string(const char *aw_string)
char * GBT_join_strings(const CharPtrArray &strings, char separator)
fputs(TRACE_PREFIX, stderr)
static void current_changed_cb(AW_root *, AWT_configuration *config)
GB_ERROR Load(const char *filename, const string &cfg_name, string &found_comment)
void get_entries(class ConstStrArray &to_array)
static AW_window * create_config_manager_window(AW_root *, AWT_configuration *config, AW_window *aww)
GB_ERROR parseFrom(const std::string &configString)
static void delete_field_cb(AW_window *, AWT_configuration *config)
void AWT_modify_managed_configs(AW_default default_file, const char *id, ConfigModifyCallback mod_cb, AW_CL cl_user)
string get_config_dbpath(const string &cfgname) const
bool operator<(const ConfigDefinition &other) const
void set_entry(const char *entry, const char *value)
void erase_deleted_configs()
string get_awar_value(ConfigAwar a) const
void aw_message(const char *msg)
const ConfigMapping & get_mapping() const
char * aw_modal_file_selection(const char *title, const char *dir, const char *def_name, const char *suffix)
static void reset_cb(AW_window *, AWT_configuration *config)
static void keep_changed_fields_cb(AW_window *, AWT_configuration *config)
GB_ERROR write_string(const char *aw_string)
void GBT_split_string(ConstStrArray &dest, const char *namelist, const char *separator, SplitMode mode)
const char * get_awar_name(const char *awar_base_name, const char *entry)
bool ARB_strBeginsWith(const char *str, const char *with)
bool has_existing(string lookFor)
GBDATA * GB_nextChild(GBDATA *child)
GB_transaction ta(gb_var)
void callback(const WindowCallback &cb)
const char * get_entry(const char *entry) const
GB_CSTR GB_read_char_pntr(GBDATA *gbd)
void init_from_array(const CharPtrArray &entries, const char *default_displayed, const char *default_value)
AW_awar * awar_string(const char *var_name, const char *default_value="", AW_default default_file=AW_ROOT_DEFAULT)
GBDATA * GB_search(GBDATA *gbd, const char *fieldpath, GB_TYPES create)
void delete_selected_field()
char * config_string() const
static void restore_cb(AW_window *, AWT_configuration *config)
AW_awar * get_awar(ConfigAwar a) const
void aw_message_if(GB_ERROR error)
char * GBS_global_string_copy(const char *templat,...)
void write(const char *cfgStr) const
void create_button(const char *macro_name, AW_label label, const char *mnemonic=NULp, const char *color=NULp)
GB_ERROR rewrite_string(const char *aw_string)
char * GB_read_file(const char *path)
static void load_cb(AW_window *, AWT_configuration *config)
GB_write_int const char s