/* * Copyright (C) Volition, Inc. 1999. All rights reserved. * * All source code herein is the property of Volition, Inc. You may not sell * or otherwise commercially exploit the source or things you created based on the * source. * */ // ModifyVariableDlg.cpp : implementation file // #include "stdafx.h" #include "FRED.h" #include "ModifyVariableDlg.h" #include "parse/sexp.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define NO_RESET_FOCUS 0 #define RESET_FOCUS 1 ///////////////////////////////////////////////////////////////////////////// // CModifyVariableDlg dialog CModifyVariableDlg::CModifyVariableDlg(CWnd* pParent /*=NULL*/) : CDialog(CModifyVariableDlg::IDD, pParent) { //{{AFX_DATA_INIT(CModifyVariableDlg) m_default_value = _T(""); m_cur_variable_name = _T(""); //}}AFX_DATA_INIT } void CModifyVariableDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CModifyVariableDlg) DDX_Text(pDX, IDC_MODIFY_DEFAULT_VALUE, m_default_value); DDV_MaxChars(pDX, m_default_value, TOKEN_LENGTH - 1); DDX_CBString(pDX, IDC_MODIFY_VARIABLE_NAME, m_cur_variable_name); DDV_MaxChars(pDX, m_cur_variable_name, TOKEN_LENGTH - 1); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CModifyVariableDlg, CDialog) //{{AFX_MSG_MAP(CModifyVariableDlg) ON_BN_CLICKED(ID_DELETE_VARIABLE, OnDeleteVariable) ON_BN_CLICKED(IDC_TYPE_STRING, OnTypeString) ON_BN_CLICKED(IDC_TYPE_NUMBER, OnTypeNumber) ON_BN_CLICKED(IDC_TYPE_PLAYER_PERSISTENT, OnTypeMissionClose) ON_BN_CLICKED(IDC_TYPE_CAMPAIGN_PERSISTENT, OnTypeMissionProgress) ON_BN_CLICKED(IDC_TYPE_NETWORK_VARIABLE, OnTypeNetworkVariable) ON_BN_CLICKED(IDC_TYPE_ETERNAL, OnTypeEternal) ON_CBN_SELCHANGE(IDC_MODIFY_VARIABLE_NAME, OnSelchangeModifyVariableName) ON_CBN_EDITCHANGE(IDC_MODIFY_VARIABLE_NAME, OnEditchangeModifyVariableName) ON_EN_KILLFOCUS(IDC_MODIFY_DEFAULT_VALUE, OnKillfocusModifyDefaultValue) ON_CBN_DROPDOWN(IDC_MODIFY_VARIABLE_NAME, OnDropdownModifyVariableName) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CModifyVariableDlg message handlers // Maybe delete variable void CModifyVariableDlg::OnDeleteVariable() { CString temp_name; int rval; // Check for name change CComboBox *cbox = (CComboBox *) GetDlgItem(IDC_MODIFY_VARIABLE_NAME); cbox->GetWindowText(temp_name); // Can't delete. Name has been changed if ( stricmp(Sexp_variables[get_sexp_var_index()].variable_name, temp_name) ) { MessageBox("Can not delete variable. Name has been changed."); return; } char message[128] = "Can not delete variable."; if (!IsChangeSafe(message)) { return; } // maybe delete variable rval = MessageBox("This will permanantly delete the variable. Do you want to continue?", NULL, MB_OKCANCEL); if (rval == IDOK) { // delete variable and exit m_deleted = true; // next statement does UpdataData(TRUE); CDialog::OnOK(); } } // Karajorma - Checks whether it is safe to delete or modify this string bool CModifyVariableDlg::IsChangeSafe(char *message) { // Can't as there are SEXPs using it. int num_counts = m_p_sexp_tree->_model.get_variable_count(Sexp_variables[get_sexp_var_index()].variable_name); if (num_counts > 0) { char buffer[256]; sprintf(buffer, "%s Used in %d SEXP(s).", message, num_counts); MessageBox(buffer); return false; } // Can't as it is used in the team loadout num_counts = m_p_sexp_tree->_model.get_loadout_variable_count(get_sexp_var_index()); if (num_counts > 0) { char buffer[256]; sprintf(buffer, "%s Used in %d location(s) in loadout.", message, num_counts); MessageBox(buffer); return false; } return true; } // Set type to string void CModifyVariableDlg::OnTypeString() { // check if type actually modified if (m_type_number == true) { // Don't allow type change if in use. char message[128] = "Can not modify variable type."; if (!IsChangeSafe(message)) { m_type_number = true; m_modified_type = false; set_variable_type(); return; } // keep track if type is really changed if (m_modified_type == true) { m_modified_type = false; } else { m_modified_type = true; } } m_type_number = false; set_variable_type(); } // Set type to number void CModifyVariableDlg::OnTypeNumber() { // check if type actually modified if (m_type_number == false) { // Don't allow type change if in use. char message[128] = "Can not modify variable type."; if (!IsChangeSafe(message)) { m_type_number = false; m_modified_type = false; set_variable_type(); return; } // keep track if type is really changed if (m_modified_type == true) { m_modified_type = false; } else { m_modified_type = true; } } m_type_number = true; set_variable_type(); } // set player persistence void CModifyVariableDlg::OnTypeMissionClose() { m_type_on_mission_close = ((CButton *) GetDlgItem(IDC_TYPE_PLAYER_PERSISTENT))->GetCheck() ? true : false; // keep track if type is really changed (ugh - just force it to be always changed) m_modified_persistence = true; if (m_type_on_mission_close) m_type_on_mission_progress = false; // if the variable isn't persistent, it can't be eternal if (!m_type_on_mission_close && !m_type_on_mission_progress) { m_type_eternal = false; } set_variable_type(); } // set campaign persistence void CModifyVariableDlg::OnTypeMissionProgress() { m_type_on_mission_progress = ((CButton *) GetDlgItem(IDC_TYPE_CAMPAIGN_PERSISTENT))->GetCheck() ? true : false; // keep track if type is really changed (ugh - just force it to be always changed) m_modified_persistence = true; if (m_type_on_mission_progress) m_type_on_mission_close = false; // if the variable isn't persistent, it can't be eternal if (!m_type_on_mission_close && !m_type_on_mission_progress) { m_type_eternal = false; } set_variable_type(); } // set eternal persistence void CModifyVariableDlg::OnTypeEternal() { m_type_eternal = ((CButton *)GetDlgItem(IDC_TYPE_ETERNAL))->GetCheck() ? true : false; m_modified_persistence = true; // if the variable isn't persistent, it can't be eternal if (!m_type_on_mission_close && !m_type_on_mission_progress) { m_type_eternal = false; MessageBox("Eternal variables must have a different persistence type set first!"); } set_variable_type(); } void CModifyVariableDlg::OnTypeNetworkVariable() { m_type_network_variable = ((CButton *) GetDlgItem(IDC_TYPE_NETWORK_VARIABLE))->GetCheck() ? true : false; m_modified_type = true; set_variable_type(); } void CModifyVariableDlg::OnSelchangeModifyVariableName() { CComboBox *cbox = (CComboBox *) GetDlgItem(IDC_MODIFY_VARIABLE_NAME); // get index of current selection int index = cbox->GetCurSel(); // check an item was actually selected, and not outside the box if (index == CB_ERR) { return; } // check if another has been modified if (m_modified_type || m_modified_persistence || m_modified_name || m_modified_value) { // Don't send message if changing to self if (index != m_combo_last_modified_index) { MessageBox("Can only modify one variable."); } //reset focus to current cbox->SetCurSel(m_combo_last_modified_index); return; } m_combo_last_modified_index = index; // Get index into sexp_variables int sexp_variable_index = get_sexp_var_index(); // Set new type for selection m_type_number = ((Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_NUMBER) != 0) ? true : false; m_type_on_mission_progress = ((Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_SAVE_ON_MISSION_PROGRESS) != 0) ? true : false; m_type_on_mission_close = ((Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE) != 0) ? true : false; m_type_network_variable = ((Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_NETWORK) != 0) ? true : false; m_type_eternal = ((Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_SAVE_TO_PLAYER_FILE) != 0) ? true : false; set_variable_type(); // Set new default value for selection if (sexp_variable_index > -1) { CEdit *edit = (CEdit *) GetDlgItem(IDC_MODIFY_DEFAULT_VALUE); edit->SetWindowText(Sexp_variables[sexp_variable_index].text); } } // Check if variable name has changed from Sexp_variables[].varaible name void CModifyVariableDlg::OnEditchangeModifyVariableName() { // Do string compare to check for change CString temp_name; // Get current variable name CComboBox *cbox = (CComboBox *) GetDlgItem(IDC_MODIFY_VARIABLE_NAME); cbox->GetWindowText(temp_name); // Check if variable name is modified if ( strcmp(Sexp_variables[get_sexp_var_index()].variable_name, temp_name) ) { m_modified_name = true; } else { m_modified_name = false; } } BOOL CModifyVariableDlg::OnInitDialog() { CDialog::OnInitDialog(); int i, box_index; // Init combo box and translation table from combo box to sexp_varaibles CComboBox *cbox = (CComboBox *) GetDlgItem(IDC_MODIFY_VARIABLE_NAME); cbox->ResetContent(); for (i=0; iAddString(Sexp_variables[i].variable_name); // check no error if ( !((box_index == CB_ERR) || (box_index == CB_ERRSPACE)) ) { m_translate_combo_to_sexp[box_index] = i; } } } // Exit gracefully if nothing added to combo box if (cbox->GetCount() == 0) { Int3(); // this should not happen OnCancel(); } int last_modified = 0; // Set current variable if (m_start_index > -1) { for (i=0; iSetCurSel(last_modified); // Set the default value if (m_translate_combo_to_sexp[last_modified] > -1) { CEdit *edit = (CEdit *) GetDlgItem(IDC_MODIFY_DEFAULT_VALUE); edit->SetWindowText(Sexp_variables[m_translate_combo_to_sexp[last_modified]].text); } // Set old variable name m_old_var_name = Sexp_variables[m_translate_combo_to_sexp[last_modified]].variable_name; // Set type m_type_number = ((Sexp_variables[last_modified].type & SEXP_VARIABLE_NUMBER) != 0) ? true : false; m_type_on_mission_progress = ((Sexp_variables[last_modified].type & SEXP_VARIABLE_SAVE_ON_MISSION_PROGRESS) != 0) ? true : false; m_type_on_mission_close = ((Sexp_variables[last_modified].type & SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE) != 0) ? true : false; m_type_network_variable = ((Sexp_variables[last_modified].type & SEXP_VARIABLE_NETWORK) != 0) ? true : false; m_type_eternal = ((Sexp_variables[last_modified].type & SEXP_VARIABLE_SAVE_TO_PLAYER_FILE) != 0) ? true : false; set_variable_type(); // keep track of changes m_modified_name = false; m_modified_value = false; m_modified_type = false; m_modified_persistence = false; m_deleted = false; m_do_modify = false; m_data_validated = false; m_var_name_validated = false; //create tool tip controls m_ProgressToolTip.Create(this); m_CloseToolTip.Create(this); m_EternalToolTip.Create(this); CWnd* pWnd = GetDlgItem(IDC_TYPE_CAMPAIGN_PERSISTENT); m_ProgressToolTip.AddTool(pWnd, "This type of variable will save when the player clicks Accept to go to the next mission"); m_ProgressToolTip.Activate(TRUE); pWnd = GetDlgItem(IDC_TYPE_PLAYER_PERSISTENT); m_CloseToolTip.AddTool(pWnd, "This type of variable will save when the player leaves the mission"); m_CloseToolTip.Activate(TRUE); pWnd = GetDlgItem(IDC_TYPE_ETERNAL); m_EternalToolTip.AddTool(pWnd, "This type of variable is saved to the player file. So it can be referred to by other campaigns"); m_EternalToolTip.Activate(TRUE); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } BOOL CModifyVariableDlg::PreTranslateMessage(MSG* pMsg) { m_ProgressToolTip.RelayEvent(pMsg); m_CloseToolTip.RelayEvent(pMsg); m_EternalToolTip.RelayEvent(pMsg); return CDialog::PreTranslateMessage(pMsg); } void CModifyVariableDlg::set_variable_type() { // get buttons CButton *button_string = (CButton *) GetDlgItem(IDC_TYPE_STRING); CButton *button_number = (CButton *) GetDlgItem(IDC_TYPE_NUMBER); // assign state button_number->SetCheck( m_type_number); button_string->SetCheck(!m_type_number); ((CButton *) GetDlgItem(IDC_TYPE_CAMPAIGN_PERSISTENT))->SetCheck(m_type_on_mission_progress); ((CButton *) GetDlgItem(IDC_TYPE_PLAYER_PERSISTENT))->SetCheck(m_type_on_mission_close); ((CButton *) GetDlgItem(IDC_TYPE_NETWORK_VARIABLE))->SetCheck(m_type_network_variable); ((CButton *) GetDlgItem(IDC_TYPE_ETERNAL))->SetCheck(m_type_eternal); } void CModifyVariableDlg::OnOK() { CString temp_data; // Validate data CEdit *edit = (CEdit *) GetDlgItem(IDC_MODIFY_DEFAULT_VALUE); edit->GetWindowText(temp_data); // validate data validate_data(temp_data, RESET_FOCUS); if (m_data_validated) { // Don't get OnKillfocusModifyDefaultValue when ok if (!m_modified_value) { if ( strcmp(Sexp_variables[get_sexp_var_index()].text, temp_data) ) { m_modified_value = true; } } // validate variable name validate_var_name(RESET_FOCUS); if (m_var_name_validated) { // maybe set m_do_modify -- this is needed. compare with OnCancel() if (m_modified_name || m_modified_persistence || m_modified_value || m_modified_type) { m_do_modify = true; } CDialog::OnOK(); } } } void CModifyVariableDlg::OnKillfocusModifyDefaultValue() { // Do string compare to check for change CString temp_data; CEdit *edit = (CEdit *) GetDlgItem(IDC_MODIFY_DEFAULT_VALUE); edit->GetWindowText(temp_data); if ( strcmp(Sexp_variables[get_sexp_var_index()].text, temp_data) ) { m_modified_value = true; } else { m_modified_value = false; } } // validate data // check (1) zero length (2) invalid chars (3) value if numberf void CModifyVariableDlg::validate_data(CString &temp_data, int set_focus) { // display invalid data message bool message = false; char message_text[256]; // check length > 0 auto length = strlen(temp_data); if (length == 0) { strcpy_s(message_text, "Invalid Default Value"); message = true; } else if (m_type_number) { // check if string and str(atoi(stri)) are same int temp_num = atoi(temp_data); char buf[TOKEN_LENGTH]; sprintf(buf, "%d", temp_num); if ( stricmp(buf, temp_data) ) { message = true; strcpy_s(message_text, "Invalid Default Value"); } else { message = false; } } // check for invalid characters auto rval = strcspn(temp_data, "@()"); if (rval != length) { message = true; sprintf(message_text, "Invalid char '%c' in Default Value", temp_data[(int)rval]); } // display message if ( message ) { m_data_validated = false; MessageBox(message_text); // reset focus if (set_focus == RESET_FOCUS) { CEdit *edit = (CEdit *) GetDlgItem(IDC_MODIFY_DEFAULT_VALUE); edit->SetFocus(); edit->SetSel(0, -1); } } // string always ok, numbers if no message m_data_validated = !message; } // validate variable name // check (1) zero length (2) invalid chars (3) already in use void CModifyVariableDlg::validate_var_name(int set_focus) { CString temp_name; CComboBox *cbox = (CComboBox *) GetDlgItem(IDC_MODIFY_VARIABLE_NAME); cbox->GetWindowText(temp_name); int cur_sel = cbox->GetCurSel(); m_old_var_name = Sexp_variables[m_translate_combo_to_sexp[cur_sel]].variable_name; // display invalid data message bool message = false; char message_text[256]; // check length > 0 auto length = strlen(temp_name); if (length == 0) { strcpy_s(message_text, "Invalid Variable Name"); message = true; } else { // check for invalid characters auto rval = strcspn(temp_name, "@()"); if (rval != length) { message = true; sprintf(message_text, "Invalid char '%c' in Variable Name", temp_name[(int)rval]); } else { int index = get_index_sexp_variable_name(temp_name); // if not a new name and not start name if ( (index != -1) && (index != m_translate_combo_to_sexp[m_combo_last_modified_index]) ) { message = true; strcpy_s(message_text, "Variable Name already in use"); } } } // display message if ( message ) { MessageBox(message_text); // reset focus if (set_focus == RESET_FOCUS) { cbox->SetFocus(); } } // set var_name_validated m_var_name_validated = !message; } int CModifyVariableDlg::get_sexp_var_index() { int index = m_translate_combo_to_sexp[m_combo_last_modified_index]; Assert( (index >= 0) && (index < MAX_SEXP_VARIABLES) ); return index; } // Reset text in drop down list void CModifyVariableDlg::OnDropdownModifyVariableName() { CString temp_name; // Get current variable name CComboBox *cbox = (CComboBox *) GetDlgItem(IDC_MODIFY_VARIABLE_NAME); cbox->GetWindowText(temp_name); // Reset combo box text int rval; rval = cbox->InsertString(m_combo_last_modified_index, temp_name); if ( (rval == CB_ERR) || (rval == CB_ERRSPACE) ) { AfxMessageBox("An internal error has occured."); OnCancel(); } cbox->DeleteString(m_combo_last_modified_index+1); cbox->SetCurSel(m_combo_last_modified_index); }