bool CDFFDUseStruct::check_data() { // Get values from the controls and validate them UpdateData(); // Make sure name is given unless the container is a FOR (whence sub-elements are accessed via array index) if (name_.IsEmpty() && parent_type_ != CHexEditDoc::DF_FORV && parent_type_ != CHexEditDoc::DF_FORF) { TaskMessageBox("No Name", "Please enter a name for this element"); ctl_name_.SetFocus(); return false; } if (!name_.IsEmpty() && !valid_id(name_)) { TaskMessageBox("Invalid STRUCT Name", "Please use alphanumeric characters (or " "underscores) and begin the name with an alphabetic character."); ctl_name_.SetFocus(); return false; } if (name_.CompareNoCase("true") == 0 || name_.CompareNoCase("false") == 0 || name_.CompareNoCase("end") == 0 || expr_eval::func_token(name_) != expr_eval::TOK_NONE) { TaskMessageBox("Reserved Name", name_ + " is reserved for internal use. Please choose another name."); ctl_name_.SetFocus(); return false; } if (struct_.IsEmpty()) { TaskMessageBox("No Defined Struct", "Please select a defined struct for this element"); ctl_struct_.SetFocus(); return false; } else if (!valid_id(struct_)) { TaskMessageBox("Invalid Defined Struct Name", "Please use alphanumeric characters " "(or underscore) and start with a alphabetic character."); ctl_name_.SetFocus(); return false; } // We can only have an empty name if parent is FOR in which case there are no siblings ASSERT(!name_.IsEmpty() || pelt_->GetParent().GetNumChildren() == 1); // Check that the name is not the same as any siblings CXmlTree::CElt ee; // First find the actual element whose siblings we want to check (an IF takes the name of its child) for (ee = *pelt_; ee.GetParent().GetName() == "if" || ee.GetParent().GetName() == "jump"; ee = ee.GetParent()) ; // empty loop body // Check that older siblings don't have the same name for (ee--; !ee.IsEmpty(); ee--) { CXmlTree::CElt ee2; for (ee2 = ee; !ee2.IsEmpty() && (ee2.GetName() == "if" || ee2.GetName() == "jump"); ee2 = ee2.GetFirstChild()) ; // nothing here if (!ee2.IsEmpty() && ee2.GetAttr("name") == name_) { TaskMessageBox("Name in use", name_ + " has a sibling with the same name.\n\n" "It is not be possible to differentiate between two elements " "with the same name at the same level (eg, in expressions)."); ctl_name_.SetFocus(); return false; } } for (ee = *pelt_; ee.GetParent().GetName() == "if" || ee.GetParent().GetName() == "jump"; ee = ee.GetParent()) ; // empty loop body // Check that younger siblings don't have the same name for (++ee; !ee.IsEmpty(); ++ee) { CXmlTree::CElt ee2; for (ee2 = ee; !ee2.IsEmpty() && (ee2.GetName() == "if" || ee2.GetName() == "jump"); ee2 = ee2.GetFirstChild()) ; // nothing here if (!ee2.IsEmpty() && ee2.GetAttr("name") == name_) { TaskMessageBox("Name in use", name_ + " has a sibling with the same name.\n\n" "It is not be possible to differentiate between two elements " "with the same name at the same level (eg, in expressions)."); ctl_name_.SetFocus(); return false; } } return true; }
// Make a whole menu system that shows all the variables that can be accessed // by an element in an expression. // Returns a pointer to a CMenu that must be destroyed and freed, unless NULL // is returned in which case no variables were found. CMenu *make_var_menu_tree(const CXmlTree::CElt ¤t_elt, bool this_too /*=false*/, bool file_too /*=false*/) { int item_no = 1; // Get sibling items CMenu *retval = make_menu(current_elt, item_no); // Add "this" if required if (this_too) { ASSERT(current_elt.GetName() != "if" && current_elt.GetName() != "switch"); ASSERT(current_elt.GetNumChildren() <= 1); ASSERT(prev_defined.size() == 0); // Make sure the list is cleared if (current_elt.GetNumChildren() > 0) add_menu_items(retval, item_no, current_elt.GetFirstChild(), _T("this")); else retval->AppendMenu(MF_ENABLED, item_no++, _T("this")); prev_defined.clear(); } // Added in 3.5 - ability to use file values (cursor, mark, eof) in expressions if (file_too) { CMenu * submenu = new CMenu; submenu->CreatePopupMenu(); submenu->AppendMenu(MF_ENABLED, item_no++, _T("cursor")); submenu->AppendMenu(MF_ENABLED, item_no++, _T("mark")); submenu->AppendMenu(MF_ENABLED, item_no++, _T("eof")); retval->AppendMenu(MF_POPUP, (UINT)submenu->m_hMenu, _T("From File")); } // Now check each ancestor in turn and add sub-menu (if not empty) CXmlTree::CElt ee; // Node of ancestor (starting with parent) int ii; // Keep track of which ancestor (1 = parent) for (ee = current_elt.GetParent(), ii = 1; ee.GetName() != "binary_file_format"; ee = ee.GetParent(), ++ii ) { CMenu *submenu = make_menu(ee, item_no); if (submenu->GetMenuItemCount() > 0) { // Add this menu as a submenu (popup) CString submenu_name; if (ii == 1) submenu_name = "Parent siblings"; else if (ii == 2) submenu_name = "Grandparent siblings"; else submenu_name.Format("Ancestor [%d] siblings", ii); retval->AppendMenu(MF_POPUP, (UINT)submenu->m_hMenu, submenu_name); } else submenu->DestroyMenu(); delete submenu; } // If we added nothing just put a dummy (disabled) menu item in there if (retval->GetMenuItemCount() == 0) retval->AppendMenu(MF_GRAYED, -1, _T("No values available")); return retval; }