42 bool is_prefined(
const string& cfgname) {
return cfgname[0] ==
'*'; }
52 : default_file(default_file_),
66 const char *
get_id()
const {
return id.c_str(); }
69 return string(
"tmp/general_configs/"+(temp ? 0 : 4))+
id+
'/'+subname;
86 StoreConfigCallback store;
87 RestoreConfigCallback load_or_reset;
100 load_or_reset(load_or_reset_),
103 field_selection(
NULp)
110 return predef ? predef->
config :
"";
121 error =
"cannot modify predefined config";
137 char *
Store()
const {
return store(); }
141 if (s.empty()) error =
"empty/nonexistant config";
142 else load_or_reset(s.c_str());
150 GB_ERROR Save(
const char* filename,
const string& cfg_name,
const string& comment);
151 GB_ERROR Load(
const char* filename,
const string& cfg_name,
string& found_comment);
156 string wanted = S+ lookFor +S;
158 return existing.find(wanted) != string::npos;
161 void erase_deleted_configs();
165 for (
int i = 0; predefined[i].
name; ++i) {
167 cfgs.
put(predefined[i].name);
173 for (
int i = 0; predefined[i].
name; ++i) {
174 if (cfgname == predefined[i].name) {
175 return &predefined[i];
181 void popup_edit_window(
AW_window *aw_config);
182 void update_field_selection_list();
183 void update_field_content();
184 void store_changed_field_content();
185 void delete_selected_field();
186 void keep_changed_fields();
189 #define HEADER "ARB_CONFIGURATION"
195 printf(
"Saving config to '%s'..\n", filename);
197 FILE *out = fopen(filename,
"wt");
203 if (comment.empty()) {
204 fprintf(out,
HEADER ":%s\n", get_id());
207 string encoded_comment(comment);
209 fprintf(out,
HEADER ":%s;%s\n", get_id(), encoded_comment.c_str());
212 string content = get_config(cfg_name);
213 fputs(content.c_str(), out);
223 printf(
"Loading config from '%s'..\n", filename);
231 error =
"Unexpected content (" HEADER " missing)";
235 char *
nl = strchr(id_pos,
'\n');
238 error =
"Unexpected content (no ID)";
243 char *comment = strchr(id_pos,
';');
244 if (comment) *comment++ = 0;
246 if (strcmp(id_pos, get_id()) != 0) {
247 error =
GBS_global_string(
"Wrong config type (expected=%s, found=%s)", get_id(), id_pos);
250 error = set_config(cfg_name, nl);
251 if (comment && !error) {
252 found_comment = comment;
280 const char *name = key+4;
281 if (!has_existing(name)) {
297 for (
int i = 0; cfgs[i]; ++i) {
298 if (strcmp(cfgs[i], config.c_str()) != 0) {
299 remaining.
put(cfgs[i]);
304 existing_configs = rest;
308 #define NO_CONFIG_SELECTED "<no config selected>"
318 if (entered_name[0]) {
321 name = isPredefined ?
string(1,
'*')+asKey : asKey;
338 if (comments.parseError()) {
339 display =
GBS_global_string(
"Error reading config comments:\n%s", comments.parseError());
342 const char *saved_comment = comments.get_entry(name.c_str());
343 display = null2empty(saved_comment);
370 free(comments_string);
375 if (!curr_cfg.empty()) {
379 if (found && changed_comment != found->
description) {
380 aw_message(
"The description of predefined configs is immutable");
386 if (comments.parseError()) {
390 if (changed_comment.empty()) {
391 comments.delete_entry(curr_cfg.c_str());
394 comments.set_entry(curr_cfg.c_str(), changed_comment.c_str());
408 if (cfgName.empty()) {
409 error =
"Please select config to restore";
418 if (cfgName.empty())
aw_message(
"Please select or enter name of config to store");
428 existing = existing.empty() ? cfgName : (
string(cfgName)+
';'+existing);
430 char *cfgStr = config->
Store();
444 aw_message(
"You may not delete predefined configs");
464 if (cfgName.empty()) error =
"Please enter or select target config";
465 else if (
is_prefined(cfgName)) error =
"You may not load over a predefined config";
472 error = config->
Load(filename, cfgName, comment);
489 if (cfgName.empty()) error =
"Please select config to save";
493 cfgName.c_str() + (cfgName[0] ==
'*'));
496 if (filename && filename[0]) {
499 error = config->
Save(filename, cfgName, comment);
509 static string esc(
const string&
str) {
512 char *escaped =
GBS_string_eval(str.c_str(),
"\\\\=\\\\\\\\:\"=\\\\\":\\n=\\\\n:\\t=\\\\t");
526 if (cfgName.empty()) error =
"Please select config to dump";
529 string confStr = esc(config->
get_config(cfgName));
531 cfgName = esc(cfgName);
532 const char *cfg = cfgName.c_str();
534 fprintf(stderr,
" { \"*%s\", \"%s\", \"%s\" },\n",
535 cfg[0] ==
'*' ? cfg+1 : cfg,
545 if (field_selection) {
548 bool seenSelected =
false;
550 field_selection->clear();
551 if (!cfgName.empty() && has_existing(cfgName)) {
552 string configString = get_config(cfgName);
555 stored.get_entries(entries);
557 StrArray entries_with_content;
559 for (
size_t e = 0; e<entries.size(); ++e) {
560 maxlen =
std::max(maxlen, strlen(entries[e]));
561 if (strcmp(selected, entries[e]) == 0) seenSelected =
true;
563 for (
size_t e = 0; e<entries.size(); ++e) {
565 int(maxlen), entries[e],
566 stored.get_entry(entries[e])),
570 field_selection->insert_default(
"",
"");
571 field_selection->update();
585 string content =
"<select a field below>";
586 if (!cfgName.empty() && has_existing(cfgName)) {
588 if (!selected.empty()) {
589 string configString = get_config(cfgName);
592 if (stored.has_entry(selected.c_str())) {
593 content = stored.
get_entry(selected.c_str());
596 content =
GBS_global_string(
"<field '%s' not stored in config>", selected.c_str());
603 GB_ERROR AWT_configuration::update_config(
const string& cfgname,
const AWT_config& config) {
605 GB_ERROR error = set_config(cfgname, changedConfigString);
606 free(changedConfigString);
612 if (!cfgName.empty() && has_existing(cfgName)) {
614 if (!selected.empty()) {
615 string configString = get_config(cfgName);
617 if (stored.has_entry(selected.c_str())) {
618 string stored_content = stored.
get_entry(selected.c_str());
621 if (stored_content != changed_content) {
622 stored.set_entry(selected.c_str(), changed_content.c_str());
632 if (!cfgName.empty() && has_existing(cfgName)) {
634 if (!selected.empty()) {
635 string configString = get_config(cfgName);
637 if (stored.has_entry(selected.c_str())) {
640 field_selection->move_selection(1);
641 update_field_selection_list();
649 if (!cfgName.empty() && has_existing(cfgName)) {
650 string configString = get_config(cfgName);
653 char *current_state = Store();
657 stored.get_entries(entries);
660 for (
size_t e = 0; e<entries.
size(); ++e) {
661 const char *entry = entries[e];
662 const char *stored_content = stored.get_entry(entry);
665 const char *current_content = current.
get_entry(entry);
666 if (strcmp(stored_content, current_content) == 0) {
667 stored.delete_entry(entry);
678 update_field_selection_list();
681 aw_message(
"All entries differ from current state");
696 AW_window_simple *aws =
new AW_window_simple;
699 aws->init(root, wid,
"Edit configuration entries");
702 aws->load_xfig(
"awt/edit_config.fig");
706 aws->create_button(
"CLOSE",
"CLOSE");
710 aws->create_button(
"HELP",
"HELP");
719 field_selection = aws->create_selection_list(get_awar(
SELECTED_FIELD)->awar_name);
721 aws->auto_space(0, 3);
722 aws->button_length(10);
725 int xpos = aws->get_at_xposition();
726 int ypos = aws->get_at_yposition();
729 aws->create_button(
"DELETE",
"Delete\nselected\nentry",
"D");
732 ypos = aws->get_at_yposition();
737 aws->create_button(
"KEEP_CHANGED",
"Keep only\nentries\ndiffering\nfrom\ncurrent\nstate",
"K");
746 update_field_selection_list();
769 AW_window_simple *aws =
new AW_window_simple;
775 aws->load_xfig(
"awt/manage_config.fig");
779 aws->create_button(
"CLOSE",
"CLOSE");
783 aws->create_button(
"HELP",
"HELP");
791 aws->create_text_field(awar_comment->
awar_name);
795 aws->create_autosize_button(
"erase",
"Erase",
"E");
803 awar_existing->
touch();
804 awar_current->
touch();
806 aws->auto_space(0, 3);
807 aws->button_length(10);
810 int xpos = aws->get_at_xposition();
811 int ypos = aws->get_at_yposition();
820 {
store_cb,
"STORE",
"Store",
"S" },
822 {
load_cb,
"LOAD",
"Load",
"L" },
823 {
save_cb,
"SAVE",
"Save",
"v" },
824 {
reset_cb,
"RESET",
"Factory\ndefaults",
"F" },
825 {
edit_cb,
"EDIT",
"Edit",
"E" },
827 { dump_cb,
"DUMP",
"dump\npredef",
"U" },
831 for (
int b = 0; b<buttons; ++b) {
832 const but& B = butDef[b];
839 aws->callback(makeWindowCallback(B.cb, config));
840 aws->create_button(B.id, B.label, B.mnemonic);
843 ypos = aws->get_at_yposition();
855 const RestoreConfigCallback& load_or_reset_cb,
const char *macro_id,
const AWT_predefined_config *predef)
871 aww->
create_button(macro_id ? macro_id :
"SAVELOAD_CONFIG",
"#conf_save.xpm");
886 if (stored_string) cdef.
write(stored_string);
898 ConfigSetupCallback *
const setup_cb_copy =
new ConfigSetupCallback(setup_cb);
927 parse_error = mapping->
parseFrom(cfgStr);
934 void AWT_config::init_from_awars(
const ConfigMapping& cfgname2awar) {
939 for (config_map::const_iterator c = cfgname2awar.begin(); c != cfgname2awar.end(); ++c) {
940 const string& key(c->first);
941 const string& awar_name(c->second);
946 valuemap[key] = awar_value;
956 awt_assert((valuemap.size()+skipped) == cfgname2awar.size());
964 init_from_awars(cfgname2awar);
984 for (config_map::const_iterator e = mapping->begin(); e != mapping->end(); ++e) {
985 const string& config_name(e->first);
986 const string& value(e->second);
988 config_map::const_iterator found = cfgname2awar.find(config_name);
989 if (found == cfgname2awar.end()) {
994 const string& awar_name(found->second);
1000 if (unmapped && warn) {
1001 int mapped = mapping->size()-unmapped;
1003 "(known/restored: %i, unknown/ignored: %i)\n"
1004 "Note: ok for configs shared between multiple windows",
1027 delete config_mapping;
1031 (*config_mapping)[config_name] = awar_name;
1058 char *old_state =
read();
1061 if (strcmp(old_state, cfgStr) != 0) {
1062 char *new_state =
read();
1063 if (strcmp(new_state, cfgStr) != 0) {
1065 int maxRetries = 10;
1066 while (retry && maxRetries--) {
1067 printf(
"Note: repeating config restore (did not set all awars correct)\n");
1069 char *new_state2 =
read();
1070 if (strcmp(new_state, new_state2) != 0) {
1071 reassign(new_state, new_state2);
1079 error =
"Unable to restore everything (might be caused by outdated, now invalid settings)";
1092 for (config_map::const_iterator e = config_mapping->begin(); e != config_mapping->end(); ++e) {
1093 const string& awar_name(e->second);
1119 for (
size_t c = 0; c<cfgs.
size(); ++c) {
1133 bool update =
false;
1134 for (
size_t e = 0; e<entries.
size(); ++e) {
1135 const char *old_content = cmap.
get_entry(entries[e]);
1136 char *new_content = mod_cb(entries[e], old_content, cl_user);
1142 else if (strcmp(old_content, new_content) != 0) {
1143 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)
void button_length(int length)
void add(const char *awar_name, const char *config_name)
bool has_entry(const char *entry) const
static void get_existing_configs(ConfigDefinition &configDef, ConstStrArray &cfgs)
GBDATA * GB_child(GBDATA *father)
static void destroy_AWT_configuration(AWT_configuration *c, AW_window *)
return string(buffer, length)
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)
GB_ERROR GB_write_string(GBDATA *gbd, const char *s)
const char * get_window_id() const
static void save_cb(AW_window *, AWT_configuration *config)
GB_ERROR Save(const char *filename, const string &cfg_name, const string &comment)
const char * get_id() const
void store_changed_field_content()
void warn_unknown_awar(const string &awar_name)
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)
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)
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
#define ARRAY_ELEMS(array)
string get_config(const string &cfgname)
GB_ERROR parseError() const
void add_predefined_to(ConstStrArray &cfgs)
AW_awar * add_callback(const RootCallback &cb)
GB_ERROR GB_delete(GBDATA *&source)
const char * read_char_pntr() const
GB_ERROR GB_await_error()
static AW_root * SINGLETON
WindowCallback makeHelpCallback(const char *helpfile)
void AWT_modify_managed_configs(AW_default default_file, const char *id, ConfigModifyCallback mod_cb, AW_CL cl_user)
GB_CSTR GB_read_key_pntr(GBDATA *gbd)
void update_field_content()
static void keep_changed_fields_cb(AW_window *, AWT_configuration *config)
void get_entries(class ConstStrArray &to_array)
static void delete_cb(AW_window *, AWT_configuration *config)
static void restore_cb(AW_window *, AWT_configuration *config)
char *(* ConfigModifyCallback)(const char *key, const char *value, AW_CL cl_user)
void keep_changed_fields()
static void encode_escapes(std::string &s, const char *to_escape)
static void refresh_config_sellist_cb(AW_root *, AWT_configuration *config, AW_selection_list *sel)
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()
static void reset_cb(AW_window *, AWT_configuration *config)
#define NO_CONFIG_SELECTED
static GB_ERROR decode_escapes(std::string &s)
static void generate_config_from_mapping_cb(AWT_config_definition &cdef, const AWT_config_mapping_def *mapping)
char * read_as_string() const
static void current_changed_cb(AW_root *, AWT_configuration *config)
GB_ERROR reset_to_default()
static void delete_field_cb(AW_window *, AWT_configuration *config)
AWT_config(const char *cfgStr)
static void comment_changed_cb(AW_root *, AWT_configuration *config)
static void selected_field_changed_cb(AW_root *, AWT_configuration *config)
AW_awar * awar_no_error(const char *awar)
end timer stuff
AW_awar * awar(const char *awar)
void save_comments(const AWT_config &comments, AWT_configuration *config)
int get_button_length() const
ConfigDefinition(AW_default default_file_, const char *id_)
static void load_cb(AW_window *, AWT_configuration *config)
void remove_from_configs(const string &config, string &existing_configs)
GB_ERROR write_as_string(const char *aw_string)
char * GBT_join_strings(const CharPtrArray &strings, char separator)
fputs(TRACE_PREFIX, stderr)
static AW_window * create_config_manager_window(AW_root *, AWT_configuration *config, AW_window *aww)
GB_ERROR Load(const char *filename, const string &cfg_name, string &found_comment)
bool is_prefined(const string &cfgname)
void get_entries(class ConstStrArray &to_array)
GB_ERROR parseFrom(const std::string &configString)
static void store_cb(AW_window *, AWT_configuration *config)
string get_config_dbpath(const string &cfgname) const
bool operator<(const ConfigDefinition &other) const
void set_entry(const char *entry, const char *value)
static void field_content_changed_cb(AW_root *, AWT_configuration *config)
void erase_deleted_configs()
string get_awar_value(ConfigAwar a) const
static void load_or_reset_generated_config_cb(const char *stored_string, const ConfigSetupCallback *setup_cb)
void aw_message(const char *msg)
const ConfigMapping & get_mapping() const
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)
char * aw_modal_file_selection(const char *title, const char *dir, const char *def_name, const char *suffix)
static void erase_comment_cb(AW_window *, AW_awar *awar_comment)
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)
static char * store_generated_config_cb(const ConfigSetupCallback *setup_cb)
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()
static void edit_cb(AW_window *aww, AWT_configuration *config)
char * config_string() const
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)
GB_write_int const char s