70
76
// ------------------------------------------
71
77
// Callbacks from database and awars
72
// ------------------------------------------
74
79
static bool in_item_changed_callback = false;
75
80
static bool in_field_changed_callback = false;
76
81
static bool in_awar_changed_callback = false;
78
static void item_changed_cb(GBDATA */*gb_item*/, int *cl_awt_linked_to_item, GB_CB_TYPE type) {
83
static void item_changed_cb(GBDATA*, awt_linked_to_item *item_link, GB_CB_TYPE type) {
79
84
if (!in_item_changed_callback) { // avoid deadlock
80
in_item_changed_callback = true;
81
awt_linked_to_item *item_link = (awt_linked_to_item*)cl_awt_linked_to_item;
85
LocallyModify<bool> flag(in_item_changed_callback, true);
83
86
if (type&GB_CB_DELETE) { // handled child was deleted
84
87
item_link->relink();
86
else if ((type&(GB_CB_CHANGED|GB_CB_SON_CREATED)) == (GB_CB_CHANGED|GB_CB_SON_CREATED)) {
89
else if ((type&GB_CB_CHANGED_OR_SON_CREATED) == GB_CB_CHANGED_OR_SON_CREATED) {
87
90
// child was created (not only changed)
88
91
item_link->relink();
90
93
else if (type&GB_CB_CHANGED) { // only changed
91
94
item_link->general_item_change();
94
in_item_changed_callback = false;
98
static void field_changed_cb(GBDATA */*gb_item*/, int *cl_awt_input_handler, GB_CB_TYPE type) {
99
static void field_changed_cb(GBDATA*, awt_input_handler *handler, GB_CB_TYPE type) {
99
100
if (!in_field_changed_callback) { // avoid deadlock
100
in_field_changed_callback = true;
101
awt_input_handler *handler = (awt_input_handler*)cl_awt_input_handler;
101
LocallyModify<bool> flag(in_field_changed_callback, true);
103
102
if (type&GB_CB_DELETE) { // field was deleted from db -> relink this item
104
103
handler->relink();
106
105
else if (type&GB_CB_CHANGED) {
107
106
handler->db_changed(); // database entry was changed
109
in_field_changed_callback = false;
113
static void awar_changed_cb(AW_root */*awr*/, AW_CL cl_awt_mask_awar_item) {
111
static void awar_changed_cb(AW_root*, awt_mask_awar_item *item) {
114
112
if (!in_awar_changed_callback) { // avoid deadlock
115
in_awar_changed_callback = true;
116
awt_mask_awar_item *item = (awt_mask_awar_item*)cl_awt_mask_awar_item;
113
LocallyModify<bool> flag(in_awar_changed_callback, true);
117
114
awt_assert(item);
118
115
if (item) item->awar_changed();
119
in_awar_changed_callback = false;
205
201
#if defined(DEBUG)
206
202
printf("awarName='%s'\n", awarName.c_str());
208
mask_global()->get_root()->awar_string(awarName.c_str(), default_value.c_str()); // create the awar
209
add_awar_callbacks();
212
void awt_mask_awar_item::add_awar_callbacks() {
213
AW_awar *var = awar();
215
if (var) var->add_callback(awar_changed_cb, AW_CL(this));
217
void awt_mask_awar_item::remove_awar_callbacks() {
218
AW_awar *var = awar();
220
if (var) var->remove_callback((AW_RCB)awar_changed_cb, AW_CL(this), AW_CL(0));
223
awt_variable::awt_variable(awt_input_mask_global *global_, const string& id, bool is_global_, const string& default_value, GB_ERROR& error)
204
mask_global().get_root()->awar_string(awarName.c_str(), default_value.c_str()); // create the awar
205
add_awarItem_callbacks();
208
void awt_mask_awar_item::add_awarItem_callbacks() {
209
AW_awar *var = awar();
211
if (var) var->add_callback(makeRootCallback(awar_changed_cb, this));
213
void awt_mask_awar_item::remove_awarItem_callbacks() {
214
AW_awar *var = awar();
216
if (var) var->remove_callback(makeRootCallback(awar_changed_cb, this));
219
awt_variable::awt_variable(awt_input_mask_global& global_, const string& id, bool is_global_, const string& default_value, GB_ERROR& error)
224
220
: awt_mask_awar_item(global_, generate_baseName(global_, id, is_global_), default_value, true)
225
221
, is_global(is_global_)
234
230
string awt_script::get_value() const
237
AW_root *root = mask_global()->get_root();
238
const awt_item_type_selector *selector = mask_global()->get_selector();
239
GBDATA *gbd = selector->current(root);
233
AW_root *root = mask_global().get_root();
234
const awt_item_type_selector *selector = mask_global().get_selector();
235
GBDATA *gb_main = mask_global().get_gb_main();
236
GBDATA *gbd = selector->current(root, gb_main);
242
239
char *species_name = root->awar(selector->get_self_awar())->read_string();
243
GBDATA *gb_main = mask_global()->get_gb_main();
244
240
GB_transaction tscope(gb_main);
246
242
char *val = GB_command_interpreter(gb_main, species_name, script.c_str(), gbd, 0);
270
266
GB_ERROR awt_linked_to_item::add_db_callbacks()
272
268
GB_ERROR error = 0;
273
if (gb_item) error = GB_add_callback(gb_item, (GB_CB_TYPE)(GB_CB_CHANGED|GB_CB_DELETE), item_changed_cb, (int*)this);
269
if (gb_item) error = GB_add_callback(gb_item, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(item_changed_cb, this));
277
273
void awt_linked_to_item::remove_db_callbacks() {
278
GB_remove_callback(gb_item, (GB_CB_TYPE)(GB_CB_CHANGED|GB_CB_DELETE), item_changed_cb, (int*)this);
274
if (!GB_inside_callback(gb_item, GB_CB_DELETE)) {
275
GB_remove_callback(gb_item, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(item_changed_cb, this));
281
awt_script_viewport::awt_script_viewport(awt_input_mask_global *global_, const awt_script *script_, const string& label_, long field_width_)
279
awt_script_viewport::awt_script_viewport(awt_input_mask_global& global_, const awt_script *script_, const string& label_, long field_width_)
282
280
: awt_viewport(global_, generate_baseName(global_), "", false, label_)
283
281
, script(script_)
284
282
, field_width(field_width_)
338
334
GB_ERROR awt_input_handler::add_db_callbacks() {
339
335
GB_ERROR error = awt_linked_to_item::add_db_callbacks();
340
if (item() && gbd) error = GB_add_callback(gbd, (GB_CB_TYPE)(GB_CB_CHANGED|GB_CB_DELETE), field_changed_cb, (int*)this);
336
if (item() && gbd) error = GB_add_callback(gbd, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(field_changed_cb, this));
343
339
void awt_input_handler::remove_db_callbacks() {
344
340
awt_linked_to_item::remove_db_callbacks();
345
if (item() && gbd) GB_remove_callback(gbd, (GB_CB_TYPE)(GB_CB_CHANGED|GB_CB_DELETE), field_changed_cb, (int*)this);
341
if (item() && gbd && !GB_inside_callback(gbd, GB_CB_DELETE)) {
342
GB_remove_callback(gbd, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(field_changed_cb, this));
348
awt_input_handler::awt_input_handler(awt_input_mask_global *global_, const string& child_path_, GB_TYPES type_, const string& label_)
346
awt_input_handler::awt_input_handler(awt_input_mask_global& global_, const string& child_path_, GB_TYPES type_, const string& label_)
349
347
: awt_viewport(global_, generate_baseName(global_, child_path_), "", false, label_)
351
349
, child_path(child_path_)
387
385
error = add_db_callbacks();
390
add_awar_callbacks(); // rebind awar callbacks
388
add_awarItem_callbacks(); // rebind awar callbacks
395
393
void awt_string_handler::awar_changed() {
396
394
GBDATA *gbdata = data();
397
GBDATA *gb_main = mask_global()->get_gb_main();
395
GBDATA *gb_main = mask_global().get_gb_main();
398
396
bool relink_me = false;
399
397
GB_ERROR error = 0;
401
399
GB_push_transaction(gb_main);
403
if (!mask_global()->edit_allowed()) error = "Editing is disabled. Check the 'Enable edit' switch!";
401
if (!mask_global().edit_allowed()) error = "Editing is disabled. Check the 'Enable edit' switch!";
405
403
if (!error && !gbdata) {
406
404
const char *child = get_child_path().c_str();
407
const char *keypath = mask_global()->get_selector()->getKeyPath();
405
const char *keypath = mask_global().get_selector()->getKeyPath();
410
408
gbdata = GB_search(item(), child, GB_FIND);
996
993
#if defined(DEBUG)
997
994
printf("Skipping '%s' (not a input mask)\n", filename.c_str());
1002
static void AWT_edit_input_mask(AW_window *, AW_CL cl_mask_name, AW_CL cl_local) {
1003
const string *mask_name = (const string *)cl_mask_name;
1004
string fullmask = inputMaskFullname(*mask_name, (bool)cl_local);
1006
AWT_edit(fullmask.c_str()); // @@@ add callback and automatically reload input mask
999
static void AWT_edit_input_mask(AW_window *, const string *mask_name, bool local) {
1000
string fullmask = inputMaskFullname(*mask_name, local);
1001
AW_edit(fullmask.c_str()); // @@@ add callback and automatically reload input mask
1009
1004
// ---------------------------------
1010
1005
// input mask container :
1011
// ---------------------------------
1012
1007
typedef SmartPtr<awt_input_mask> awt_input_mask_ptr;
1013
1008
typedef map<string, awt_input_mask_ptr> InputMaskList; // contains all active masks
1014
1009
static InputMaskList input_mask_list;
1016
static void awt_input_mask_awar_changed_cb(AW_root */*root*/, AW_CL cl_mask) {
1017
awt_input_mask *mask = (awt_input_mask*)(cl_mask);
1011
static void awt_input_mask_awar_changed_cb(AW_root*, awt_input_mask *mask) {
1018
1012
mask->relink();
1020
1014
static void link_mask_to_database(awt_input_mask_ptr mask) {
1021
awt_input_mask_global *global = mask->mask_global();
1022
const awt_item_type_selector *sel = global->get_selector();
1023
AW_root *root = global->get_root();
1015
awt_input_mask_global& global = mask->mask_global();
1016
const awt_item_type_selector *sel = global.get_selector();
1017
AW_root *root = global.get_root();
1025
sel->add_awar_callbacks(root, awt_input_mask_awar_changed_cb, (AW_CL)(&*mask));
1026
awt_input_mask_awar_changed_cb(root, (AW_CL)(&*mask));
1019
sel->add_awar_callbacks(root, makeRootCallback(awt_input_mask_awar_changed_cb, &*mask));
1020
awt_input_mask_awar_changed_cb(root, &*mask);
1028
1022
static void unlink_mask_from_database(awt_input_mask_ptr mask) {
1029
awt_input_mask_global *global = mask->mask_global();
1030
const awt_item_type_selector *sel = global->get_selector();
1031
AW_root *root = global->get_root();
1023
awt_input_mask_global& global = mask->mask_global();
1024
const awt_item_type_selector *sel = global.get_selector();
1025
AW_root *root = global.get_root();
1033
sel->remove_awar_callbacks(root, awt_input_mask_awar_changed_cb, (AW_CL)(&*mask));
1027
sel->remove_awar_callbacks(root, makeRootCallback(awt_input_mask_awar_changed_cb, &*mask));
1036
1030
inline bool isInternalMaskName(const string& s) {
1037
1031
return s[0] == '0' || s[0] == '1';
1040
static void awt_open_input_mask(AW_window *aww, AW_CL cl_internal_mask_name, AW_CL cl_mask_to_open, bool reload, bool hide_current) {
1041
const string *internal_mask_name = (const string *)cl_internal_mask_name;
1042
const string *mask_to_open = (const string *)cl_mask_to_open;
1043
InputMaskList::iterator mask_iter = input_mask_list.find(*internal_mask_name);
1034
static void awt_open_input_mask(AW_window *aww, const string *internal_mask_name, const string *mask_to_open, bool reload, bool hide_current) {
1035
InputMaskList::iterator mask_iter = input_mask_list.find(*internal_mask_name);
1045
1037
awt_assert(internal_mask_name && isInternalMaskName(*internal_mask_name));
1046
1038
awt_assert(mask_to_open && isInternalMaskName(*mask_to_open));
1048
1040
if (mask_iter != input_mask_list.end()) {
1049
1041
awt_input_mask_ptr mask = mask_iter->second;
1050
awt_input_mask_global *global = mask->mask_global();
1042
awt_input_mask_global& global = mask->mask_global();
1052
printf("aww=%p root=%p ; global=%p root=%p\n", aww, aww->get_root(), global, global->get_root());
1053
awt_assert(aww->get_root() == global->get_root());
1044
printf("aww=%p root=%p ; global=%p root=%p\n", aww, aww->get_root(), &global, global.get_root());
1045
awt_assert(aww->get_root() == global.get_root());
1055
1047
if (reload) mask->set_reload_on_reinit(true);
1056
1048
if (hide_current) mask->hide();
1057
1049
// @@@ hier sollte nicht der Selector der alten Maske verwendet werden, sondern anhand des Typs ein
1058
1050
// Selector ausgewaehlt werden. Dazu muessen jedoch alle Selectoren registriert werden.
1059
GB_ERROR error = AWT_initialize_input_mask(global->get_root(), global->get_gb_main(), global->get_selector(), mask_to_open->c_str(), global->is_local_mask());
1051
GB_ERROR error = AWT_initialize_input_mask(global.get_root(), global.get_gb_main(), global.get_selector(), mask_to_open->c_str(), global.is_local_mask());
1060
1052
// CAUTION: AWT_initialize_input_mask invalidates mask and mask_iter
1061
1053
if (error && hide_current) {
1062
1054
mask_iter = input_mask_list.find(*internal_mask_name);
1073
1065
#endif // DEBUG
1076
static void AWT_reload_input_mask(AW_window *aww, AW_CL cl_internal_mask_name) {
1077
awt_open_input_mask(aww, cl_internal_mask_name, cl_internal_mask_name, true, true);
1079
static void AWT_open_input_mask(AW_window *aww, AW_CL cl_internal_mask_name, AW_CL cl_mask_to_open) {
1080
awt_open_input_mask(aww, cl_internal_mask_name, cl_mask_to_open, false, false);
1082
static void AWT_change_input_mask(AW_window *aww, AW_CL cl_internal_mask_name, AW_CL cl_mask_to_open) {
1083
awt_open_input_mask(aww, cl_internal_mask_name, cl_mask_to_open, false, true);
1068
static void AWT_reload_input_mask(AW_window *aww, const string *internal_mask_name) {
1069
awt_open_input_mask(aww, internal_mask_name, internal_mask_name, true, true);
1071
static void AWT_open_input_mask(AW_window *aww, const string *internal_mask_name, const string *mask_to_open) {
1072
awt_open_input_mask(aww, internal_mask_name, mask_to_open, false, false);
1074
static void AWT_change_input_mask(AW_window *aww, const string *internal_mask_name, const string *mask_to_open) {
1075
awt_open_input_mask(aww, internal_mask_name, mask_to_open, false, true);
1088
1078
// ------------------------------
1089
1079
// class awt_mask_action
1090
// ------------------------------
1091
// something that is performed i.e. when user pressed a mask button
1092
// used as callback parameter
1093
1081
class awt_mask_action {
1082
// something that is performed i.e. when user pressed a mask button
1083
// used as callback parameter
1095
1085
virtual GB_ERROR action() = 0;
1129
1119
, id_dest(id_dest_)
1130
1120
, id_source(id_source_)
1132
virtual ~awt_assignment() {}
1122
virtual ~awt_assignment() OVERRIDE {}
1135
static void AWT_input_mask_perform_action(AW_window */*aww*/, AW_CL cl_awt_mask_action, AW_CL) {
1136
awt_mask_action *action = (awt_mask_action*)cl_awt_mask_action;
1125
static void AWT_input_mask_perform_action(AW_window*, awt_mask_action *action) {
1137
1126
action->perform_action();
1140
static void AWT_input_mask_browse_url(AW_window *aww, AW_CL cl_url_srt, AW_CL cl_mask_ptr) {
1141
AW_root *root = aww->get_root();
1142
const string *url_srt = (const string *)cl_url_srt;
1143
const awt_input_mask *mask = (const awt_input_mask *)cl_mask_ptr;
1144
const awt_input_mask_global *global = mask->mask_global();
1145
const awt_item_type_selector *selector = global->get_selector();
1146
GBDATA *gbd = selector->current(root);
1129
static void AWT_input_mask_browse_url(AW_window *aww, const string *url_srt, const awt_input_mask *mask) {
1130
const awt_input_mask_global& global = mask->mask_global();
1131
const awt_item_type_selector *selector = global.get_selector();
1133
AW_root *root = aww->get_root();
1134
GBDATA *gb_main = global.get_gb_main();
1135
GBDATA *gbd = selector->current(root, gb_main);
1149
1138
aw_message(GBS_global_string("You have to select a %s first", awt_itemtype_names[selector->get_item_type()]));
1152
1141
char *name = root->awar(selector->get_self_awar())->read_string();
1153
GB_ERROR error = awt_open_ACISRT_URL_by_gbd(root, global->get_gb_main(), gbd, name, url_srt->c_str());
1142
GB_ERROR error = awt_open_ACISRT_URL_by_gbd(root, gb_main, gbd, name, url_srt->c_str());
1154
1143
if (error) aw_message(error);
1321
1309
// ----------------------------------
1322
1310
// class awt_marked_checkbox
1323
// ----------------------------------
1325
1312
class awt_marked_checkbox : public awt_viewport, public awt_linked_to_item {
1328
string generate_baseName(awt_input_mask_global *global_) {
1329
return GBS_global_string("%s/marked", global_->get_maskid().c_str());
1315
string generate_baseName(awt_input_mask_global& global_) {
1316
return GBS_global_string("%s/marked", global_.get_maskid().c_str());
1333
awt_marked_checkbox(awt_input_mask_global *global_, const std::string& label_)
1320
awt_marked_checkbox(awt_input_mask_global& global_, const std::string& label_)
1334
1321
: awt_viewport(global_, generate_baseName(global_), "0", false, label_)
1335
1322
, awt_linked_to_item()
1337
virtual ~awt_marked_checkbox() {}
1324
virtual ~awt_marked_checkbox() OVERRIDE {}
1339
virtual GB_ERROR link_to(GBDATA *gb_new_item); // link to a new item
1340
virtual GB_ERROR relink() { return link_to(mask_global()->get_selector()->current(mask_global()->get_root())); }
1341
virtual void awar_changed();
1342
virtual void db_changed();
1343
virtual void general_item_change() { db_changed(); } // called if item was changed (somehow)
1344
virtual void build_widget(AW_window *aws); // builds the widget at the current position
1326
virtual GB_ERROR link_to(GBDATA *gb_new_item) OVERRIDE; // link to a new item
1327
virtual GB_ERROR relink() OVERRIDE { return link_to(mask_global().get_selected_item()); }
1328
virtual void awar_changed() OVERRIDE;
1329
virtual void db_changed() OVERRIDE;
1330
virtual void general_item_change() OVERRIDE { db_changed(); } // called if item was changed (somehow)
1331
virtual void build_widget(AW_window *aws) OVERRIDE; // builds the widget at the current position
1347
1334
GB_ERROR awt_marked_checkbox::link_to(GBDATA *gb_new_item) { // link to a new item
1348
1335
GB_ERROR error = 0;
1349
GB_transaction dummy(mask_global()->get_gb_main());
1336
GB_transaction ta(mask_global().get_gb_main());
1351
remove_awar_callbacks(); // unbind awar callbacks temporarily
1338
remove_awarItem_callbacks(); // unbind awar callbacks temporarily
1354
1341
remove_db_callbacks(); // ignore result (if handled db-entry was deleted, it returns an error)
1424
bool is_known(const string& id) { return seen.find(id) != seen.end(); }
1426
string makeUnique(string id) {
1429
for (int i = 0; ; ++i) {
1430
string undup = GBS_global_string("%s%i", id.c_str(), i);
1431
if (!is_known(undup)) {
1442
ID_checker(bool reloading_)
1443
: reloading(reloading_)
1446
const char *fromKey(const char *id) {
1447
curr_id = makeUnique(id);
1448
return reloading ? NULL : curr_id.c_str();
1450
const char *fromText(const string& anystr) {
1451
SmartCharPtr key = GBS_string_2_key(anystr.c_str());
1452
return fromKey(&*key);
1455
bool seenDups() const { return !dup.empty(); }
1456
const char *get_dup_error(const string& maskName) const {
1458
for (set<string>::iterator d = dup.begin(); d != dup.end(); ++d) {
1459
dupList = dupList+" '"+*d+"'";
1461
return GBS_global_string("Warning: duplicated IDs seen in '%s':\n"
1463
"(they need to be unique; change button texts etc. to change them)",
1464
maskName.c_str(), dupList.c_str());
1434
1468
static awt_input_mask_ptr awt_create_input_mask(AW_root *root, GBDATA *gb_main, const awt_item_type_selector *sel,
1435
1469
const string& mask_name, bool local, GB_ERROR& error, bool reloading) {
1437
1470
awt_input_mask_ptr mask;
1517
1552
// create window
1519
awt_assert(!mask.Null());
1554
awt_assert(!mask.isNull());
1520
1555
AW_window_simple*& aws = mask->get_window();
1521
1556
aws = new AW_window_simple;
1523
// do not use callback ids for reloaded masks
1524
#define ID(id) (reloading ? NULL : id)
1558
ID_checker ID(reloading);
1527
char *window_id = GBS_global_string_copy("INPUT_MASK_%s", mask->mask_global()->get_maskid().c_str()); // create a unique id for each mask
1561
char *window_id = GBS_global_string_copy("INPUT_MASK_%s", mask->mask_global().get_maskid().c_str()); // create a unique id for each mask
1528
1562
aws->init(root, window_id, title.c_str());
1529
1563
free(window_id);
1531
1566
aws->load_xfig(0, true);
1533
aws->recalc_size_at_show = 1; // ignore user size!
1567
aws->recalc_size_atShow(AW_RESIZE_DEFAULT); // ignore user size!
1535
1569
aws->auto_space(x_spacing, y_spacing);
1536
1570
aws->at_newline();
1538
aws->callback((AW_CB0)AW_POPDOWN); aws->create_button(ID("CLOSE"), "CLOSE", "C");
1539
aws->callback( AW_POPUP_HELP,(AW_CL)"input_mask.hlp"); aws->create_button(ID("HELP"),"HELP","H");
1572
aws->callback((AW_CB0)AW_POPDOWN); aws->create_button(ID.fromKey("CLOSE"), "CLOSE", "C");
1573
aws->callback(makeHelpCallback("input_mask.hlp")); aws->create_button(ID.fromKey("HELP"), "HELP", "H");
1541
1575
if (edit_reload) {
1542
aws->callback(AWT_edit_input_mask, (AW_CL)&mask->mask_global()->get_maskname(), (AW_CL)mask->mask_global()->is_local_mask()); aws->create_button(0, "EDIT","E");
1543
aws->callback(AWT_reload_input_mask, (AW_CL)&mask->mask_global()->get_internal_maskname()); aws->create_button(0, "RELOAD","R");
1576
aws->callback(makeWindowCallback(AWT_edit_input_mask, &mask->mask_global().get_maskname(), mask->mask_global().is_local_mask()));
1577
aws->create_button(0, "!EDIT", "E");
1579
aws->callback(makeWindowCallback(AWT_reload_input_mask, &mask->mask_global().get_internal_maskname()));
1580
aws->create_button(0, "RELOAD", "R");
1546
1583
if (edit_reload && edit_enable && show_marked) aws->at_newline();
1659
1695
string id, def_value;
1661
1697
id = scan_identifier(line, scan_pos, error);
1662
bool global_exists = mask->mask_global()->has_global_id(id);
1663
bool local_exists = mask->mask_global()->has_local_id(id);
1698
bool global_exists = mask->mask_global().has_global_id(id);
1699
bool local_exists = mask->mask_global().has_local_id(id);
1665
1701
if ((cmd == CMD_GLOBAL && local_exists) || (cmd == CMD_LOCAL && global_exists)) {
1666
error = GB_export_errorf("ID '%s' already declared as %s ID (rename your local id)",
1667
id.c_str(), cmd == CMD_LOCAL ? "global" : "local");
1702
error = GBS_global_string("ID '%s' already declared as %s ID (rename your local id)",
1703
id.c_str(), cmd == CMD_LOCAL ? "global" : "local");
1669
1705
else if (cmd == CMD_LOCAL && local_exists) {
1670
error = GB_export_errorf("ID '%s' declared twice", id.c_str());
1706
error = GBS_global_string("ID '%s' declared twice", id.c_str());
1673
1709
if (!error) def_value = scan_string_parameter(line, scan_pos, error);
1675
1711
if (cmd == CMD_GLOBAL) {
1676
if (!mask->mask_global()->has_global_id(id)) { // do not create globals more than once
1712
if (!mask->mask_global().has_global_id(id)) { // do not create globals more than once
1677
1713
// and never free them -> so we don't need pointer
1678
1714
new awt_variable(mask->mask_global(), id, true, def_value, error);
1680
awt_assert(handler.Null());
1716
awt_assert(handler.isNull());
1683
1719
handler = new awt_variable(mask->mask_global(), id, false, def_value, error);
1732
1768
check_last_parameter(error, command);
1735
char *key = ID(GBS_string_2_key(label.c_str()));
1736
AW_CB cb = cmd == CMD_OPENMASK ? AWT_open_input_mask : AWT_change_input_mask;
1737
string mask_to_start_internal = find_internal_name(mask_to_start, local);
1771
string mask_to_start_internal = find_internal_name(mask_to_start, local);
1739
1773
if (mask_to_start_internal.length() == 0) {
1740
1774
error = "Can't detect which mask to load";
1743
string *cl_arg1 = new string(mask->mask_global()->get_internal_maskname());
1744
string *cl_arg2 = new string(mask_to_start_internal);
1746
awt_assert(cl_arg1);
1747
awt_assert(cl_arg2);
1749
aws->callback( cb, (AW_CL)cl_arg1, (AW_CL)cl_arg2);
1777
const char *key = ID.fromText(label);
1779
string *const internal_mask_name = new string(mask->mask_global().get_internal_maskname());
1780
string *const mask_to_open = new string(mask_to_start_internal);
1782
awt_assert(internal_mask_name);
1783
awt_assert(mask_to_open);
1785
aws->callback(makeWindowCallback(cmd == CMD_OPENMASK ? AWT_open_input_mask : AWT_change_input_mask, internal_mask_name, mask_to_open));
1750
1787
aws->button_length(label.length()+2);
1751
1788
aws->create_button(key, label.c_str());
1757
1792
else if (cmd == CMD_WWW) {
1796
1825
check_last_parameter(error, command);
1799
char *key = ID(GBS_string_2_key(text.c_str()));
1800
1828
aws->button_length(text.length()+2);
1801
aws->create_button(key, text.c_str());
1829
aws->create_button(NULL, text.c_str());
1805
1832
else if (cmd == CMD_SELF) {
1806
1833
check_no_parameter(line, scan_pos, error, command);
1808
const awt_item_type_selector *selector = mask->mask_global()->get_selector();
1809
string button_awar_name = selector->get_self_awar();
1810
char *key = ID(GBS_string_2_key(button_awar_name.c_str()));
1835
const awt_item_type_selector *selector = mask->mask_global().get_selector();
1812
1836
aws->button_length(selector->get_self_awar_content_length());
1813
aws->create_button(key, button_awar_name.c_str());
1837
aws->create_button(NULL, selector->get_self_awar());
1817
1840
else if (cmd == CMD_NEW_LINE) {
2028
2043
// start of implementation of class awt_input_mask:
2030
2045
awt_input_mask::~awt_input_mask() {
2031
relink(true); // unlink from DB
2032
2047
for (awt_mask_item_list::iterator h = handlers.begin(); h != handlers.end(); ++h) {
2033
2048
(*h)->remove_name();
2037
void awt_input_mask::relink(bool unlink) {
2052
void awt_input_mask::link_to(GBDATA *gb_item) {
2038
2053
// this functions links/unlinks all registered item handlers to/from the database
2039
const awt_item_type_selector *sel = global.get_selector();
2040
GBDATA *gb_item = unlink ? 0 : sel->current(global.get_root());
2042
2054
for (awt_mask_item_list::iterator h = handlers.begin(); h != handlers.end(); ++h) {
2043
if ((*h)->is_linked_item()) (*h)->to_linked_item()->link_to(gb_item);
2044
// if ((*h)->is_input_handler()) (*h)->to_input_handler()->link_to(gb_item);
2045
// else if ((*h)->is_script_viewport()) (*h)->to_script_viewport()->link_to(gb_item);
2055
if ((*h)->is_linked_item()) (*h)->to_linked_item()->link_to(gb_item);
2166
2176
// -----------------------------
2167
2177
// Registered Itemtypes
2168
// -----------------------------
2170
typedef void (*AWT_OpenMaskWindowCallback)(AW_window* aww, AW_CL cl_id, AW_CL);
2172
// --------------------------------------
2173
// class AWT_registered_itemtype
2174
// --------------------------------------
2175
// stores information about so-far-used item types
2176
2179
class AWT_registered_itemtype {
2178
AW_window_menu_modes *awm; // the main window responsible for opening windows
2179
AWT_OpenMaskWindowCallback open_window_cb; // callback to open the window
2180
// stores information about so-far-used item types
2181
AW_window_menu_modes *awm; // the main window responsible for opening windows
2182
AWT_OpenMaskWindowCallback open_window_cb; // callback to open the window
2182
AWT_registered_itemtype() : awm(0), open_window_cb(0) {}
2183
AWT_registered_itemtype(AW_window_menu_modes *awm_, AWT_OpenMaskWindowCallback open_window_cb_)
2186
AWT_registered_itemtype() : awm(0), open_window_cb(0), gb_main(0) {}
2187
AWT_registered_itemtype(AW_window_menu_modes *awm_, AWT_OpenMaskWindowCallback open_window_cb_, GBDATA *gb_main_)
2185
2189
, open_window_cb(open_window_cb_)
2192
AWT_registered_itemtype(const AWT_registered_itemtype& other)
2194
open_window_cb(other.open_window_cb),
2195
gb_main(other.gb_main)
2197
DECLARE_ASSIGNMENT_OPERATOR(AWT_registered_itemtype);
2187
2198
virtual ~AWT_registered_itemtype() {}
2189
2200
AW_window_menu_modes *getWindow() const { return awm; }
2190
2201
AWT_OpenMaskWindowCallback getOpenCb() const { return open_window_cb; }
2193
static map<awt_item_type, AWT_registered_itemtype> registeredTypes;
2204
typedef map<awt_item_type, AWT_registered_itemtype> TypeRegistry;
2205
typedef TypeRegistry::const_iterator TypeRegistryIter;
2207
static TypeRegistry registeredTypes;
2195
2209
static GB_ERROR openMaskWindowByType(int mask_id, awt_item_type type) {
2196
map<awt_item_type, AWT_registered_itemtype>::const_iterator registered = registeredTypes.find(type);
2210
TypeRegistryIter registered = registeredTypes.find(type);
2199
2213
if (registered == registeredTypes.end()) error = GBS_global_string("Type '%s' not registered (yet)", awt_itemtype_names[type]);
2200
2214
else registered->second.getOpenCb()(registered->second.getWindow(), (AW_CL)mask_id, (AW_CL)0);
2236
string itemname = awr->awar(AWAR_INPUT_MASK_ITEM)->read_string();
2237
int scope = awr->awar(AWAR_INPUT_MASK_SCOPE)->read_int();
2238
int hidden = awr->awar(AWAR_INPUT_MASK_HIDDEN)->read_int();
2239
bool local = scope == AWT_SCOPE_LOCAL;
2240
string maskfullname = inputMaskFullname(maskname, local);
2241
bool openMask = false;
2242
bool closeWindow = false;
2243
const char *error = 0;
2248
string itemname = awr->awar(AWAR_INPUT_MASK_ITEM)->read_char_pntr();
2249
int scope = awr->awar(AWAR_INPUT_MASK_SCOPE)->read_int();
2250
int hidden = awr->awar(AWAR_INPUT_MASK_HIDDEN)->read_int();
2251
bool local = scope == AWT_SCOPE_LOCAL;
2252
string maskfullname = inputMaskFullname(maskname, local);
2253
bool openMask = false;
2255
const char *error = 0;
2244
2256
struct stat st;
2246
2258
if (stat(maskfullname.c_str(), &st) == 0) { // file exists
2247
int answer = aw_question("File does already exist", "Open mask,Cancel");
2259
int answer = aw_question("overwrite_mask", "File does already exist", "Overwrite mask,Cancel");
2248
2260
switch (answer) {
2250
2262
openMask = true;
2341
2352
aws->at_newline();
2343
2354
aws->callback(create_new_mask_cb);
2344
aws->create_button("CREATE", "CREATE","C");
2355
aws->create_button("CREATE", "CREATE", "C");
2346
2357
aws->window_fit();
2349
2360
aws->activate();
2350
aww->get_root()->awar(AWAR_INPUT_MASK_ITEM)->write_string(awt_itemtype_names[int(cl_item_type)]);
2361
aww->get_root()->awar(AWAR_INPUT_MASK_ITEM)->write_string(awt_itemtype_names[item_type]);
2353
2364
// -----------------------------------------------------
2354
2365
// Create User-Mask-Submenu for any application
2355
// -----------------------------------------------------
2357
void AWT_create_mask_submenu(AW_window_menu_modes *awm, awt_item_type wanted_item_type, void (*open_window_cb)(AW_window* aww, AW_CL cl_id, AW_CL)) {
2367
static bool hadMnemonic(char *availableMnemonics, char c) {
2368
// return true if 'c' occurs in 'availableMnemonics' (case ignored)
2369
// (in that case 'c' is removed from 'availableMnemonics').
2370
// returns false otherwise.
2371
char lc = tolower(c);
2372
char *cand = strchr(availableMnemonics, lc);
2374
char *last = strchr(cand+1, 0)-1;
2380
awt_assert(last == cand);
2388
static char *selectMnemonic(const char *orgTitle, char *availableMnemonics, char& mnemonic) {
2389
// select (and remove) one from 'availableMnemonics' occurring in orgTitle
2390
// return selected in 'mnemonic'
2391
// return orgTitle (eventually modified if no matching mnemonic available)
2393
bool prevWasChar = false;
2394
for (int startOfWord = 1; startOfWord>=0; --startOfWord) {
2395
for (int i = 0; orgTitle[i]; ++i) {
2396
char c = orgTitle[i];
2398
if (!prevWasChar || !startOfWord) {
2399
if (hadMnemonic(availableMnemonics, c)) {
2401
return strdup(orgTitle);
2406
else prevWasChar = false;
2410
for (int i = 0; i<2; ++i) {
2411
const char *takeAny = i ? availableMnemonics : "1234567890";
2412
for (int t = 0; takeAny[t]; ++t) {
2413
char c = takeAny[t];
2414
if (hadMnemonic(availableMnemonics, c)) {
2416
return GBS_global_string_copy("%s [%c]", orgTitle, c);
2421
mnemonic = 0; // failed
2422
return strdup(orgTitle);
2425
void AWT_create_mask_submenu(AW_window_menu_modes *awm, awt_item_type wanted_item_type, AWT_OpenMaskWindowCallback open_mask_window_cb, GBDATA *gb_main) {
2358
2426
// add a user mask submenu at current position
2359
2427
AW_root *awr = awm->get_root();
2376
2446
if (item_type == wanted_item_type) {
2377
2447
if (!descriptor->is_hidden()) { // do not show masks with hidden-flag
2378
entries_made = true;
2448
entries_made = true;
2379
2449
char *macroname2key = GBS_string_2_key(descriptor->get_internal_maskname());
2380
2450
#if defined(DEBUG) && 0
2381
2451
printf("added user-mask '%s' with id=%i\n", descriptor->get_maskname(), id);
2382
2452
#endif // DEBUG
2383
awm->insert_menu_topic(macroname2key, descriptor->get_title(), "", "input_mask.hlp", AWM_ALL, open_window_cb, (AW_CL)id, (AW_CL)0);
2453
char mnemonic[2] = "x";
2454
char *mod_title = selectMnemonic(descriptor->get_title(), availableMnemonics, mnemonic[0]);
2456
awm->insert_menu_topic(macroname2key, mod_title, mnemonic, "input_mask.hlp", AWM_ALL, makeWindowCallback(open_mask_window_cb, id, gb_main));
2384
2458
free(macroname2key);
2386
registerType(item_type, awm, open_window_cb);
2460
registerType(item_type, awm, open_mask_window_cb, gb_main);
2388
2462
else if (item_type == AWT_IT_UNKNOWN) {
2389
2463
aw_message(GBS_global_string("Unknown @ITEMTYPE '%s' in '%s'", descriptor->get_itemtypename(), descriptor->get_internal_maskname()));
2392
if (entries_made) awm->insert_separator();
2466
if (entries_made) awm->sep______________();
2397
2471
char *new_item_mask_id = GBS_global_string_copy("new_%s_mask", itemname);
2398
2472
char *new_item_mask_label = GBS_global_string_copy("New %s mask..", itemname);
2400
awm->insert_menu_topic(new_item_mask_id, new_item_mask_label, "N", "input_mask_new.hlp", AWM_ALL, create_new_input_mask, (AW_CL)wanted_item_type, (AW_CL)0);
2474
awm->insert_menu_topic(new_item_mask_id, new_item_mask_label, "N", "input_mask_new.hlp", AWM_ALL, makeWindowCallback(create_new_input_mask, wanted_item_type));
2402
2476
free(new_item_mask_label);
2403
2477
free(new_item_mask_id);
2479
free(availableMnemonics);
2405
2480
awm->close_sub_menu();
2408
2483
void AWT_destroy_input_masks() {
2484
// unlink from DB manually - there are too many smartptrs to
2485
// get rid of all of them before DB gets destroyed on exit
2486
for (InputMaskList::iterator i = input_mask_list.begin();
2487
i != input_mask_list.end();
2490
i->second->unlink();
2409
2492
input_mask_list.clear();
2496
void awt_item_type_selector::add_awar_callbacks(AW_root *root, const RootCallback& cb) const {
2497
root->awar(get_self_awar())->add_callback(cb);
2500
void awt_item_type_selector::remove_awar_callbacks(AW_root *root, const RootCallback& cb) const {
2501
root->awar(get_self_awar())->remove_callback(cb);